Skip to content

Commit c02ff51

Browse files
committed
Rename reset to seed and seed products from CSV
Rename products/reset.py to products/seed.py and update API to seed the product table from an in-package CSV. Change endpoint from POST /products/reset to GET /products/seed, move CSV to app/api/products/start_data.csv and resolve its absolute path. Map CSV 'desc' field to DB 'title' on insert, update SQL to use title, and guard against empty query results (handle cur.description None). Update imports and router includes to use products_router/seed_router names. Remove legacy product-list root logic and clean up tests by deleting obsolete echo tests.
1 parent 0948dab commit c02ff51

5 files changed

Lines changed: 21 additions & 68 deletions

File tree

app/api/products/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
from .products import router
2-
from .reset import router as reset_router
1+
from .products import router as products_router
2+
from .seed import router as seed_router
Lines changed: 17 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
import os
1+
from app import __version__
2+
import os, time
23
import csv
34
from fastapi import APIRouter, status
45
from app.api.db import get_db_connection
56

67
router = APIRouter()
78

8-
CSV_PATH = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'tests', 'csv', 'small.csv')
9+
CSV_PATH = os.path.join(os.path.dirname(__file__), 'start_data.csv')
10+
CSV_PATH = os.path.abspath(CSV_PATH)
911

10-
@router.post("/products/reset", status_code=status.HTTP_200_OK)
11-
def reset_products() -> dict:
12+
@router.get("/products/seed", status_code=status.HTTP_200_OK)
13+
def seed_products() -> dict:
1214
"""Delete and recreate the product table, then seed with CSV data."""
1315
conn_gen = get_db_connection()
1416
conn = next(conn_gen)
@@ -20,7 +22,7 @@ def reset_products() -> dict:
2022
id SERIAL PRIMARY KEY,
2123
Params TEXT,
2224
item INTEGER,
23-
desc TEXT,
25+
title TEXT,
2426
UOS TEXT,
2527
Pack_Description TEXT,
2628
Hierarchy1 TEXT,
@@ -45,65 +47,35 @@ def reset_products() -> dict:
4547
reader = csv.DictReader(csvfile)
4648
rows = [row for row in reader]
4749
for row in rows:
50+
# Map 'desc' from CSV to 'title' for DB
51+
row['title'] = row.pop('desc')
4852
cur.execute(
4953
"""
5054
INSERT INTO product (
51-
Params, item, desc, UOS, Pack_Description, Hierarchy1, Hierarchy2, Hierarchy3, UOP,
55+
Params, item, title, UOS, Pack_Description, Hierarchy1, Hierarchy2, Hierarchy3, UOP,
5256
sSell1, sSell2, sSell3, sSell4, sSell5, pack1, pack2, pack3, pack4, pack5, EAN
5357
) VALUES (
54-
%(Params)s, %(item)s, %(desc)s, %(UOS)s, %(Pack_Description)s, %(Hierarchy1)s, %(Hierarchy2)s, %(Hierarchy3)s, %(UOP)s,
58+
%(Params)s, %(item)s, %(title)s, %(UOS)s, %(Pack_Description)s, %(Hierarchy1)s, %(Hierarchy2)s, %(Hierarchy3)s, %(UOP)s,
5559
%(sSell1)s, %(sSell2)s, %(sSell3)s, %(sSell4)s, %(sSell5)s, %(pack1)s, %(pack2)s, %(pack3)s, %(pack4)s, %(pack5)s, %(EAN)s
5660
)
5761
""",
5862
row
5963
)
6064
conn.commit()
6165
cur.execute('SELECT * FROM product;')
62-
products = [dict(zip([desc[0] for desc in cur.description], row)) for row in cur.fetchall()]
66+
if cur.description is None:
67+
products = []
68+
else:
69+
columns = [desc[0] for desc in cur.description]
70+
products = [dict(zip(columns, row)) for row in cur.fetchall()]
6371
cur.close()
6472
conn.close()
65-
return {"message": "Product table reset and seeded from CSV.", "data": products}
66-
import os, time
67-
import psycopg2
68-
from dotenv import load_dotenv
69-
from app import __version__
70-
71-
router = APIRouter()
7273

73-
@router.get("/products")
74-
def root() -> dict:
75-
"""Return a structured welcome message for the API root, including product data."""
76-
load_dotenv()
77-
conn = psycopg2.connect(
78-
host=os.getenv('DB_HOST'),
79-
port=os.getenv('DB_PORT', '5432'),
80-
dbname=os.getenv('DB_NAME'),
81-
user=os.getenv('DB_USER'),
82-
password=os.getenv('DB_PASSWORD')
83-
)
84-
cur = conn.cursor()
85-
cur.execute('SELECT id, name, description, price, in_stock, created_at FROM product;')
86-
products = [
87-
{
88-
"id": row[0],
89-
"name": row[1],
90-
"description": row[2],
91-
"price": float(row[3]),
92-
"in_stock": row[4],
93-
"created_at": row[5].isoformat() if row[5] else None
94-
}
95-
for row in cur.fetchall()
96-
]
97-
cur.close()
98-
conn.close()
99-
100-
load_dotenv()
10174
base_url = os.getenv("BASE_URL", "http://localhost:8000")
102-
10375
epoch = int(time.time() * 1000)
10476
meta = {
10577
"severity": "success",
106-
"title": "Product List",
78+
"title": "Product table seeded",
10779
"version": __version__,
10880
"base_url": base_url,
10981
"time": epoch,

app/api/routes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
from app.api.root import router as root_router
1414
from app.api.health import router as health_router
1515
from app.api.products.products import router as products_router
16-
from app.api.products.reset import router as reset_router
16+
from app.api.products.seed import router as seed_router
1717

1818
router.include_router(root_router)
1919
router.include_router(health_router)
2020
router.include_router(products_router)
21-
router.include_router(reset_router)
21+
router.include_router(seed_router)

tests/test_routes.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,3 @@ def test_health_returns_ok() -> None:
2525
assert response.status_code == 200
2626
assert response.json() == {"status": "ok"}
2727

28-
29-
def test_echo_returns_message() -> None:
30-
"""POST /echo should return the provided message."""
31-
response = client.post("/echo", json={"message": "hello"})
32-
assert response.status_code == 200
33-
assert response.json() == {"echo": "hello"}
34-
35-
36-
def test_echo_empty_string() -> None:
37-
"""POST /echo with an empty string should echo back an empty string."""
38-
response = client.post("/echo", json={"message": ""})
39-
assert response.status_code == 200
40-
assert response.json() == {"echo": ""}
41-
42-
43-
def test_echo_missing_body_returns_422() -> None:
44-
"""POST /echo without a body should return 422 Unprocessable Entity."""
45-
response = client.post("/echo", json={})
46-
assert response.status_code == 422

0 commit comments

Comments
 (0)