50 lines
2.4 KiB
Markdown
50 lines
2.4 KiB
Markdown
# CRM Step 01 — Backend: Module Scaffold + Products CRUD
|
|
|
|
## Context
|
|
Read `.claude/crm-build-plan.md` first for full data models, conventions, and IMPORTANT NOTES.
|
|
|
|
## Task
|
|
Create the `backend/crm/` module with Products CRUD. This is the first CRM backend step.
|
|
|
|
## What to build
|
|
|
|
### 1. `backend/crm/__init__.py` — empty
|
|
|
|
### 2. `backend/crm/models.py`
|
|
Pydantic models for Products:
|
|
- `ProductCosts` — pcb, components, enclosure, labor_hours, labor_rate, shipping_in, total (all float/int, all optional)
|
|
- `ProductStock` — on_hand, reserved, available (int, defaults 0)
|
|
- `ProductCategory` enum — controller, striker, clock, part, repair_service
|
|
- `ProductCreate` — name, sku (optional), category, description (optional), price (float), currency (default "EUR"), costs (ProductCosts optional), stock (ProductStock optional), nextcloud_folder (optional), linked_device_type (optional), active (bool default True)
|
|
- `ProductUpdate` — all fields Optional
|
|
- `ProductInDB` — extends ProductCreate + id (str), created_at (str), updated_at (str)
|
|
- `ProductListResponse` — products: List[ProductInDB], total: int
|
|
|
|
### 3. `backend/crm/service.py`
|
|
Firestore collection: `crm_products`
|
|
Functions:
|
|
- `list_products(search=None, category=None, active_only=False) -> List[ProductInDB]`
|
|
- `get_product(product_id) -> ProductInDB` — raises HTTPException 404 if not found
|
|
- `create_product(data: ProductCreate) -> ProductInDB` — generates UUID id, sets created_at/updated_at to ISO now
|
|
- `update_product(product_id, data: ProductUpdate) -> ProductInDB` — partial update (only set fields), updates updated_at
|
|
- `delete_product(product_id) -> None` — raises 404 if not found
|
|
|
|
### 4. `backend/crm/router.py`
|
|
Prefix: `/api/crm/products`, tag: `crm-products`
|
|
All routes require `require_permission("crm", "view")` for GET, `require_permission("crm", "edit")` for POST/PUT/DELETE.
|
|
- `GET /` → list_products (query params: search, category, active_only)
|
|
- `GET /{product_id}` → get_product
|
|
- `POST /` → create_product
|
|
- `PUT /{product_id}` → update_product
|
|
- `DELETE /{product_id}` → delete_product
|
|
|
|
### 5. Register in `backend/main.py`
|
|
Add: `from crm.router import router as crm_products_router`
|
|
Add: `app.include_router(crm_products_router)` (after existing routers)
|
|
|
|
## Notes
|
|
- Use `uuid.uuid4()` for IDs
|
|
- Use `datetime.utcnow().isoformat()` for timestamps
|
|
- Follow exact Firestore pattern from `backend/devices/service.py`
|
|
- No new pip dependencies needed
|