Skip to content

Commit b83993f

Browse files
committed
Use CSV-backed schema and DB helper
Replace direct psycopg2/dotenv usage with the shared get_db_connection helper; product listing now SELECTs * and builds dicts from cursor.description to return the full CSV-derived schema. The reset endpoint now recreates a product table matching the CSV columns and seeds rows from tests/csv/small.csv using csv.DictReader with parameterized INSERTs. Updated docstrings and response messages accordingly and removed the previous hardcoded sample seed data.
1 parent 85569ff commit b83993f

2 files changed

Lines changed: 59 additions & 67 deletions

File tree

app/api/products/products.py

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,27 @@
1+
12
from app import __version__
23
from fastapi import APIRouter
3-
from fastapi import status
44
import os, time
5-
import psycopg2
6-
from dotenv import load_dotenv
7-
from app import __version__
5+
from app.api.db import get_db_connection
86

97
router = APIRouter()
108

119
@router.get("/products")
1210
def root() -> dict:
13-
"""Return a structured welcome message for the API root, including product data."""
14-
load_dotenv()
15-
conn = psycopg2.connect(
16-
host=os.getenv('DB_HOST'),
17-
port=os.getenv('DB_PORT', '5432'),
18-
dbname=os.getenv('DB_NAME'),
19-
user=os.getenv('DB_USER'),
20-
password=os.getenv('DB_PASSWORD')
21-
)
11+
"""Return all products with full CSV-based schema."""
12+
conn_gen = get_db_connection()
13+
conn = next(conn_gen)
2214
cur = conn.cursor()
23-
cur.execute('SELECT id, name, description, price, in_stock, created_at FROM product;')
24-
products = [
25-
{
26-
"id": row[0],
27-
"name": row[1],
28-
"description": row[2],
29-
"price": float(row[3]),
30-
"in_stock": row[4],
31-
"created_at": row[5].isoformat() if row[5] else None
32-
}
33-
for row in cur.fetchall()
34-
]
15+
cur.execute('SELECT * FROM product;')
16+
if cur.description is None:
17+
products = []
18+
else:
19+
columns = [desc[0] for desc in cur.description]
20+
products = [dict(zip(columns, row)) for row in cur.fetchall()]
3521
cur.close()
3622
conn.close()
3723

38-
load_dotenv()
3924
base_url = os.getenv("BASE_URL", "http://localhost:8000")
40-
4125
epoch = int(time.time() * 1000)
4226
meta = {
4327
"severity": "success",

app/api/products/reset.py

Lines changed: 48 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,68 @@
11
import os
2-
import psycopg2
3-
from dotenv import load_dotenv
2+
import csv
43
from fastapi import APIRouter, status
4+
from app.api.db import get_db_connection
55

66
router = APIRouter()
77

8+
CSV_PATH = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'tests', 'csv', 'small.csv')
9+
810
@router.post("/products/reset", status_code=status.HTTP_200_OK)
911
def reset_products() -> dict:
10-
"""Delete and recreate the product table, then seed with initial data."""
11-
load_dotenv()
12-
conn = psycopg2.connect(
13-
host=os.getenv('DB_HOST'),
14-
port=os.getenv('DB_PORT', '5432'),
15-
dbname=os.getenv('DB_NAME'),
16-
user=os.getenv('DB_USER'),
17-
password=os.getenv('DB_PASSWORD')
18-
)
12+
"""Delete and recreate the product table, then seed with CSV data."""
13+
conn_gen = get_db_connection()
14+
conn = next(conn_gen)
1915
cur = conn.cursor()
20-
# Drop and recreate table
16+
# Drop and recreate table with all CSV columns
2117
cur.execute('''
2218
DROP TABLE IF EXISTS product;
2319
CREATE TABLE product (
2420
id SERIAL PRIMARY KEY,
25-
name VARCHAR(255) NOT NULL,
26-
description TEXT,
27-
price NUMERIC(10,2) NOT NULL,
28-
in_stock BOOLEAN DEFAULT TRUE,
29-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
21+
Params TEXT,
22+
item INTEGER,
23+
desc TEXT,
24+
UOS TEXT,
25+
Pack_Description TEXT,
26+
Hierarchy1 TEXT,
27+
Hierarchy2 TEXT,
28+
Hierarchy3 TEXT,
29+
UOP TEXT,
30+
sSell1 NUMERIC(10,2),
31+
sSell2 NUMERIC(10,2),
32+
sSell3 NUMERIC(10,2),
33+
sSell4 NUMERIC(10,2),
34+
sSell5 NUMERIC(10,2),
35+
pack1 INTEGER,
36+
pack2 INTEGER,
37+
pack3 INTEGER,
38+
pack4 INTEGER,
39+
pack5 INTEGER,
40+
EAN TEXT
3041
);
3142
''')
32-
# Seed data
33-
seed_products = [
34-
("Apple", "Fresh red apple", 0.99, True),
35-
("Banana", "Organic banana", 0.59, True),
36-
("Orange", "Juicy orange", 1.29, True),
37-
]
38-
cur.executemany(
39-
"INSERT INTO product (name, description, price, in_stock) VALUES (%s, %s, %s, %s);",
40-
seed_products
41-
)
43+
# Read and insert CSV data
44+
with open(CSV_PATH, newline='') as csvfile:
45+
reader = csv.DictReader(csvfile)
46+
rows = [row for row in reader]
47+
for row in rows:
48+
cur.execute(
49+
"""
50+
INSERT INTO product (
51+
Params, item, desc, UOS, Pack_Description, Hierarchy1, Hierarchy2, Hierarchy3, UOP,
52+
sSell1, sSell2, sSell3, sSell4, sSell5, pack1, pack2, pack3, pack4, pack5, EAN
53+
) VALUES (
54+
%(Params)s, %(item)s, %(desc)s, %(UOS)s, %(Pack_Description)s, %(Hierarchy1)s, %(Hierarchy2)s, %(Hierarchy3)s, %(UOP)s,
55+
%(sSell1)s, %(sSell2)s, %(sSell3)s, %(sSell4)s, %(sSell5)s, %(pack1)s, %(pack2)s, %(pack3)s, %(pack4)s, %(pack5)s, %(EAN)s
56+
)
57+
""",
58+
row
59+
)
4260
conn.commit()
43-
cur.execute('SELECT id, name, description, price, in_stock, created_at FROM product;')
44-
products = [
45-
{
46-
"id": row[0],
47-
"name": row[1],
48-
"description": row[2],
49-
"price": float(row[3]),
50-
"in_stock": row[4],
51-
"created_at": row[5].isoformat() if row[5] else None
52-
}
53-
for row in cur.fetchall()
54-
]
61+
cur.execute('SELECT * FROM product;')
62+
products = [dict(zip([desc[0] for desc in cur.description], row)) for row in cur.fetchall()]
5563
cur.close()
5664
conn.close()
57-
return {"message": "Product table reset and seeded.", "data": products}
65+
return {"message": "Product table reset and seeded from CSV.", "data": products}
5866
import os, time
5967
import psycopg2
6068
from dotenv import load_dotenv

0 commit comments

Comments
 (0)