feat: modèles SQLAlchemy pour todos, shopping et notes

This commit is contained in:
2026-05-24 04:51:21 +02:00
parent ee00848fdc
commit be5c34e4f7
3 changed files with 147 additions and 0 deletions
+40
View File
@@ -0,0 +1,40 @@
import uuid
from datetime import datetime
from decimal import Decimal
from sqlalchemy import String, Text, TIMESTAMP, Numeric, ForeignKey, text
from sqlalchemy.dialects.postgresql import UUID, ARRAY, JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.core.database import Base
class NoteItem(Base):
__tablename__ = "items"
__table_args__ = {"schema": "notes"}
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
title: Mapped[str | None] = mapped_column(String(255))
content: Mapped[str] = mapped_column(Text, nullable=False)
category: Mapped[str | None] = mapped_column(String(50))
tags: Mapped[list[str]] = mapped_column(ARRAY(String(50)), server_default=text("'{}'::varchar[]"))
gps_lat: Mapped[Decimal | None] = mapped_column(Numeric(10, 7))
gps_lon: Mapped[Decimal | None] = mapped_column(Numeric(10, 7))
metadata_: Mapped[dict | None] = mapped_column("metadata", JSONB)
created_at: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), server_default=text("now()"))
owner_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
attachments: Mapped[list["NoteAttachment"]] = relationship("NoteAttachment", back_populates="note", cascade="all, delete-orphan")
class NoteAttachment(Base):
__tablename__ = "attachments"
__table_args__ = {"schema": "notes"}
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
note_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("notes.items.id", ondelete="CASCADE"), nullable=False)
file_path: Mapped[str | None] = mapped_column(String(255))
thumbnail_path: Mapped[str | None] = mapped_column(String(255))
file_type: Mapped[str | None] = mapped_column(String(20))
original_name: Mapped[str | None] = mapped_column(String(255))
created_at: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), server_default=text("now()"))
note: Mapped["NoteItem"] = relationship("NoteItem", back_populates="attachments")
+81
View File
@@ -0,0 +1,81 @@
import uuid
from datetime import datetime, date
from decimal import Decimal
from sqlalchemy import String, Text, Integer, TIMESTAMP, Date, Numeric, Boolean, ForeignKey, text
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.core.database import Base
class Product(Base):
__tablename__ = "products"
__table_args__ = {"schema": "shopping"}
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
name: Mapped[str] = mapped_column(String(150), nullable=False)
brand: Mapped[str | None] = mapped_column(String(100))
category: Mapped[str | None] = mapped_column(String(50))
image_path: Mapped[str | None] = mapped_column(String(255))
thumbnail_path: Mapped[str | None] = mapped_column(String(255))
default_unit: Mapped[str | None] = mapped_column(String(20))
barcode: Mapped[str | None] = mapped_column(String(50))
frequency_score: Mapped[int] = mapped_column(Integer, server_default=text("0"))
owner_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
created_at: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), server_default=text("now()"))
class Store(Base):
__tablename__ = "stores"
__table_args__ = {"schema": "shopping"}
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
name: Mapped[str] = mapped_column(String(100), nullable=False)
location: Mapped[str | None] = mapped_column(Text)
owner_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
class PriceHistory(Base):
__tablename__ = "price_history"
__table_args__ = {"schema": "shopping"}
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
product_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("shopping.products.id", ondelete="CASCADE"), nullable=False)
store_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("shopping.stores.id", ondelete="SET NULL"))
price: Mapped[Decimal] = mapped_column(Numeric(8, 2), nullable=False)
unit: Mapped[str | None] = mapped_column(String(20))
quantity: Mapped[Decimal | None] = mapped_column(Numeric(8, 3))
source: Mapped[str] = mapped_column(String(20), server_default="manual")
recorded_at: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), server_default=text("now()"))
class ShoppingList(Base):
__tablename__ = "lists"
__table_args__ = {"schema": "shopping"}
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
name: Mapped[str | None] = mapped_column(String(100))
store_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("shopping.stores.id", ondelete="SET NULL"))
week_date: Mapped[date | None] = mapped_column(Date)
status: Mapped[str] = mapped_column(String(20), server_default="draft")
owner_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))
created_at: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), server_default=text("now()"))
items: Mapped[list["ListItem"]] = relationship("ListItem", back_populates="shopping_list", cascade="all, delete-orphan")
class ListItem(Base):
__tablename__ = "list_items"
__table_args__ = {"schema": "shopping"}
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
list_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("shopping.lists.id", ondelete="CASCADE"), nullable=False)
product_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True), ForeignKey("shopping.products.id", ondelete="SET NULL"))
custom_name: Mapped[str | None] = mapped_column(String(150))
quantity: Mapped[Decimal | None] = mapped_column(Numeric(8, 3))
unit: Mapped[str | None] = mapped_column(String(20))
is_checked: Mapped[bool] = mapped_column(Boolean, server_default=text("false"))
price_recorded: Mapped[Decimal | None] = mapped_column(Numeric(8, 2))
carried_over: Mapped[bool] = mapped_column(Boolean, server_default=text("false"))
sort_order: Mapped[int | None] = mapped_column(Integer)
shopping_list: Mapped["ShoppingList"] = relationship("ShoppingList", back_populates="items")
+26
View File
@@ -0,0 +1,26 @@
import uuid
from datetime import datetime
from sqlalchemy import String, Text, Integer, TIMESTAMP, text
from sqlalchemy.dialects.postgresql import UUID, ARRAY
from sqlalchemy.orm import Mapped, mapped_column
from app.core.database import Base
class TodoItem(Base):
__tablename__ = "items"
__table_args__ = {"schema": "todos"}
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
title: Mapped[str] = mapped_column(String(255), nullable=False)
body: Mapped[str | None] = mapped_column(Text)
url: Mapped[str | None] = mapped_column(Text)
domain: Mapped[str | None] = mapped_column(String(50))
category: Mapped[str | None] = mapped_column(String(50))
tags: Mapped[list[str]] = mapped_column(ARRAY(String(50)), server_default=text("'{}'::varchar[]"))
status: Mapped[str] = mapped_column(String(20), server_default="pending")
priority: Mapped[str] = mapped_column(String(10), server_default="medium")
due_date: Mapped[datetime | None] = mapped_column(TIMESTAMP(timezone=True))
postponed_count: Mapped[int] = mapped_column(Integer, server_default=text("0"))
created_at: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True), server_default=text("now()"))
updated_at: Mapped[datetime | None] = mapped_column(TIMESTAMP(timezone=True))
owner_id: Mapped[uuid.UUID | None] = mapped_column(UUID(as_uuid=True))