Phases 6-7
This commit is contained in:
parent
76a516a417
commit
029940b079
111 changed files with 17247 additions and 447 deletions
|
|
@ -181,6 +181,8 @@ interface PaginatedResponse<T> {
|
|||
- `ImportProductsSchema` — array of `CreateProductSchema` (for JSON import)
|
||||
- All schemas imported from `'zod/v4'`; enums use `z.enum(Object.values(...))`.
|
||||
|
||||
**Status**: DONE (types, enums, validation schemas all exist with tests)
|
||||
|
||||
### 5.2 — Mongoose Schema & Repository
|
||||
|
||||
- `packages/api/src/modules/products/schemas/product.schema.ts` — Mongoose schema with `timestamps: true`, `deletedAt` index, partial unique index on `(householdId, barcode)`.
|
||||
|
|
@ -195,7 +197,35 @@ interface PaginatedResponse<T> {
|
|||
- `bulkCreate(householdId, items[])` — uses `insertMany` with `ordered: false`
|
||||
- All read queries use `.lean().exec()`.
|
||||
|
||||
### 5.3 — Barcode Lookup Service
|
||||
**Status**: DONE (repository exists with tests)
|
||||
|
||||
### 5.3 — Products Service
|
||||
|
||||
- `ProductsService` with business logic:
|
||||
- Dedup check on create (same name + brand within household)
|
||||
- Barcode collision check (409 ConflictError)
|
||||
- Soft-delete with `deletedAt` timestamp
|
||||
- Coordinate barcode lookup (call BarcodeService)
|
||||
- Coordinate import (validate + bulkCreate)
|
||||
- Smart-add (call LLM provider)
|
||||
|
||||
**Status**: NOT STARTED
|
||||
|
||||
### 5.4 — Products Routes
|
||||
|
||||
- Route plugin registered via `fp()`:
|
||||
- `GET /products` — list/search (paginated)
|
||||
- `GET /products/:id` — get single
|
||||
- `POST /products` — create
|
||||
- `PATCH /products/:id` — update
|
||||
- `DELETE /products/:id` — soft-delete (admin)
|
||||
- `GET /products/barcode/:code` — barcode lookup
|
||||
- `POST /products/import` — bulk import
|
||||
- `POST /products/smart-add` — LLM placeholder
|
||||
|
||||
**Status**: NOT STARTED
|
||||
|
||||
### 5.5 — Barcode Lookup Service
|
||||
|
||||
- `BarcodeService`:
|
||||
- First check local DB for matching barcode (per household)
|
||||
|
|
@ -208,7 +238,9 @@ interface PaginatedResponse<T> {
|
|||
- Failures (network, 404, malformed): return `{ found: false }`; do not throw
|
||||
- Outbound HTTP via `undici` with a 5s timeout and a configurable User-Agent (`MeshiTrack/<version> (+self-hosted)`)
|
||||
|
||||
### 5.4 — LLM Provider Interface
|
||||
**Status**: NOT STARTED
|
||||
|
||||
### 5.6 — LLM Provider Interface
|
||||
|
||||
- `packages/api/src/modules/llm/interfaces/llm-provider.interface.ts`:
|
||||
|
||||
|
|
@ -231,14 +263,18 @@ export const LLM_PROVIDER = Symbol('LLM_PROVIDER');
|
|||
- `NoOpLlmProvider`: implements interface, returns `null` for all methods, logs a warning
|
||||
- `LlmModule`: provides `LLM_PROVIDER` via factory, selectable by env var `LLM_PROVIDER_TYPE`
|
||||
|
||||
### 5.5 — Smart Add Endpoint
|
||||
**Status**: DONE (interface + NoOp provider exist with tests)
|
||||
|
||||
### 5.7 — Smart Add Endpoint
|
||||
|
||||
- `POST /products/smart-add` accepts `{ text?: string, image?: file }`
|
||||
- Calls `ILlmProvider.extractNutrition()`
|
||||
- If LLM returns data, pre-fill a product and return to client for review (not auto-saved)
|
||||
- If LLM unavailable (`NoOpLlmProvider`), return `{ available: false, message: 'LLM not configured' }`
|
||||
|
||||
### 5.6 — Import Endpoint
|
||||
**Status**: NOT STARTED (blocked on 5.3/5.4)
|
||||
|
||||
### 5.8 — Import Endpoint
|
||||
|
||||
- `POST /products/import` accepts multipart CSV or JSON file (max 5 MB, 5000 rows)
|
||||
- Validate each row against `CreateProductSchema`; reject rows with imperial `servingUnit` values with a clear error message
|
||||
|
|
@ -248,7 +284,16 @@ export const LLM_PROVIDER = Symbol('LLM_PROVIDER');
|
|||
- `tags` is a `;`-separated list
|
||||
- `servingUnit` ∈ `{g, ml, piece, slice}`
|
||||
|
||||
### 5.7 — Web UI: Product Library
|
||||
**Status**: NOT STARTED (blocked on 5.3/5.4)
|
||||
|
||||
### 5.9 — Web: API Client Service
|
||||
|
||||
- `packages/web/src/services/products.ts` — fetch functions for all product endpoints
|
||||
- Unit tests in `packages/web/src/services/__tests__/products.test.ts`
|
||||
|
||||
**Status**: NOT STARTED
|
||||
|
||||
### 5.10 — Web UI: Product Library
|
||||
|
||||
- `/products` page (Server Component for initial fetch; client island for filters):
|
||||
- Search bar with debounced full-text search (300ms)
|
||||
|
|
@ -263,6 +308,15 @@ export const LLM_PROVIDER = Symbol('LLM_PROVIDER');
|
|||
- Barcode field with "Lookup" button (calls `/products/barcode/:code`)
|
||||
- "Smart Add" tab (text input or image upload)
|
||||
- Import dialog: file upload with preview, row count, and error display
|
||||
- Component tests for page and interactive components
|
||||
|
||||
**Status**: NOT STARTED
|
||||
|
||||
### 5.11 — CI Verification
|
||||
|
||||
- `npm run build` passes
|
||||
- `npm run test:cov` passes (100% lines/functions/statements, 90% branches)
|
||||
- `npm run lint` passes
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -276,10 +330,12 @@ export const LLM_PROVIDER = Symbol('LLM_PROVIDER');
|
|||
- [ ] Barcode collisions within a household return 409
|
||||
- [ ] Bulk import processes a CSV with 100+ products and reports per-row errors
|
||||
- [ ] Web UI allows searching, filtering, adding, and editing products
|
||||
- [ ] Web UI has component tests for all pages and interactive components
|
||||
- [ ] `ILlmProvider` interface is defined and injectable
|
||||
- [ ] Smart Add endpoint returns graceful `{ available: false }` with the NoOp provider
|
||||
- [ ] All product queries are scoped to `householdId`
|
||||
- [ ] Unit + integration tests meet coverage targets (100% lines/functions/statements, 90% branches)
|
||||
- [ ] `npm run build`, `npm run test:cov`, and `npm run lint` all pass
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue