feat(shopping): schémas Pydantic listes et articles + volume dev backend
This commit is contained in:
@@ -0,0 +1,91 @@
|
|||||||
|
import uuid
|
||||||
|
from datetime import datetime, date
|
||||||
|
from decimal import Decimal
|
||||||
|
from typing import Literal
|
||||||
|
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
||||||
|
|
||||||
|
|
||||||
|
class StoreResponse(BaseModel):
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
id: uuid.UUID
|
||||||
|
name: str
|
||||||
|
location: str | None
|
||||||
|
|
||||||
|
|
||||||
|
class ProductResponse(BaseModel):
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
id: uuid.UUID
|
||||||
|
name: str
|
||||||
|
brand: str | None
|
||||||
|
category: str | None
|
||||||
|
default_unit: str | None
|
||||||
|
frequency_score: int
|
||||||
|
|
||||||
|
|
||||||
|
class ListItemCreate(BaseModel):
|
||||||
|
product_id: uuid.UUID | None = None
|
||||||
|
custom_name: str | None = None
|
||||||
|
quantity: Decimal | None = None
|
||||||
|
unit: str | None = None
|
||||||
|
|
||||||
|
@model_validator(mode='after')
|
||||||
|
def must_have_name(self) -> 'ListItemCreate':
|
||||||
|
if not self.product_id and not self.custom_name:
|
||||||
|
raise ValueError('product_id ou custom_name requis')
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
class ListItemUpdate(BaseModel):
|
||||||
|
is_checked: bool | None = None
|
||||||
|
quantity: Decimal | None = None
|
||||||
|
unit: str | None = None
|
||||||
|
price_recorded: Decimal | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class ListItemResponse(BaseModel):
|
||||||
|
id: uuid.UUID
|
||||||
|
product_id: uuid.UUID | None
|
||||||
|
custom_name: str | None
|
||||||
|
display_name: str
|
||||||
|
quantity: Decimal | None
|
||||||
|
unit: str | None
|
||||||
|
is_checked: bool
|
||||||
|
price_recorded: Decimal | None
|
||||||
|
carried_over: bool
|
||||||
|
sort_order: int | None
|
||||||
|
|
||||||
|
|
||||||
|
class ShoppingListCreate(BaseModel):
|
||||||
|
name: str | None = None
|
||||||
|
store_id: uuid.UUID | None = None
|
||||||
|
week_date: date | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class ShoppingListUpdate(BaseModel):
|
||||||
|
name: str | None = None
|
||||||
|
store_id: uuid.UUID | None = None
|
||||||
|
status: Literal['draft', 'active', 'done'] | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class ShoppingListResponse(BaseModel):
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
id: uuid.UUID
|
||||||
|
name: str | None
|
||||||
|
store_id: uuid.UUID | None
|
||||||
|
week_date: date | None
|
||||||
|
status: str
|
||||||
|
created_at: datetime
|
||||||
|
item_count: int
|
||||||
|
checked_count: int
|
||||||
|
|
||||||
|
|
||||||
|
class ShoppingListDetailResponse(BaseModel):
|
||||||
|
id: uuid.UUID
|
||||||
|
name: str | None
|
||||||
|
store_id: uuid.UUID | None
|
||||||
|
week_date: date | None
|
||||||
|
status: str
|
||||||
|
created_at: datetime
|
||||||
|
item_count: int
|
||||||
|
checked_count: int
|
||||||
|
items: list[ListItemResponse]
|
||||||
@@ -20,6 +20,7 @@ services:
|
|||||||
UPLOAD_DIR: /uploads
|
UPLOAD_DIR: /uploads
|
||||||
CORS_ORIGINS: http://localhost:3001,http://localhost:3000
|
CORS_ORIGINS: http://localhost:3001,http://localhost:3000
|
||||||
volumes:
|
volumes:
|
||||||
|
- ./backend/app:/app/app
|
||||||
- uploads:/uploads
|
- uploads:/uploads
|
||||||
ports:
|
ports:
|
||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
|
|||||||
Reference in New Issue
Block a user