feat: merge cartsnitch/api into api/ subdirectory
Consolidate API gateway service into monorepo. Squashed from https://github.com/cartsnitch/api main (89bacb1). Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
"""Purchase and PurchaseItem models."""
|
||||
|
||||
import uuid
|
||||
from datetime import date, datetime
|
||||
from decimal import Decimal
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import (
|
||||
JSON,
|
||||
Date,
|
||||
DateTime,
|
||||
ForeignKey,
|
||||
Index,
|
||||
Numeric,
|
||||
String,
|
||||
UniqueConstraint,
|
||||
func,
|
||||
)
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from cartsnitch_api.models.base import Base, TimestampMixin, UUIDPrimaryKeyMixin
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from cartsnitch_api.models.price import PriceHistory
|
||||
from cartsnitch_api.models.product import NormalizedProduct
|
||||
from cartsnitch_api.models.store import Store, StoreLocation
|
||||
from cartsnitch_api.models.user import User
|
||||
|
||||
|
||||
class Purchase(UUIDPrimaryKeyMixin, TimestampMixin, Base):
|
||||
"""A single shopping trip / receipt."""
|
||||
|
||||
__tablename__ = "purchases"
|
||||
|
||||
user_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("users.id"), nullable=False)
|
||||
store_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("stores.id"), nullable=False)
|
||||
store_location_id: Mapped[uuid.UUID | None] = mapped_column(ForeignKey("store_locations.id"))
|
||||
receipt_id: Mapped[str] = mapped_column(String(200), nullable=False)
|
||||
purchase_date: Mapped[date] = mapped_column(Date, nullable=False)
|
||||
total: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False)
|
||||
subtotal: Mapped[Decimal | None] = mapped_column(Numeric(10, 2))
|
||||
tax: Mapped[Decimal | None] = mapped_column(Numeric(10, 2))
|
||||
savings_total: Mapped[Decimal | None] = mapped_column(Numeric(10, 2))
|
||||
source_url: Mapped[str | None] = mapped_column(String(500))
|
||||
raw_data: Mapped[dict | None] = mapped_column(JSON)
|
||||
ingested_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
server_default=func.now(),
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
# Relationships
|
||||
user: Mapped["User"] = relationship(back_populates="purchases")
|
||||
store: Mapped["Store"] = relationship(back_populates="purchases")
|
||||
store_location: Mapped["StoreLocation | None"] = relationship(back_populates="purchases")
|
||||
items: Mapped[list["PurchaseItem"]] = relationship(back_populates="purchase")
|
||||
|
||||
__table_args__ = (
|
||||
Index("ix_purchases_user_store", "user_id", "store_id"),
|
||||
UniqueConstraint("user_id", "store_id", "receipt_id", name="uq_purchase_receipt"),
|
||||
)
|
||||
|
||||
|
||||
class PurchaseItem(UUIDPrimaryKeyMixin, TimestampMixin, Base):
|
||||
"""Individual line item on a receipt."""
|
||||
|
||||
__tablename__ = "purchase_items"
|
||||
|
||||
purchase_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("purchases.id"), nullable=False)
|
||||
product_name_raw: Mapped[str] = mapped_column(String(300), nullable=False)
|
||||
upc: Mapped[str | None] = mapped_column(String(20))
|
||||
quantity: Mapped[Decimal] = mapped_column(Numeric(10, 3), nullable=False, default=1)
|
||||
unit_price: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False)
|
||||
extended_price: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False)
|
||||
regular_price: Mapped[Decimal | None] = mapped_column(Numeric(10, 2))
|
||||
sale_price: Mapped[Decimal | None] = mapped_column(Numeric(10, 2))
|
||||
coupon_discount: Mapped[Decimal | None] = mapped_column(Numeric(10, 2))
|
||||
loyalty_discount: Mapped[Decimal | None] = mapped_column(Numeric(10, 2))
|
||||
category_raw: Mapped[str | None] = mapped_column(String(100))
|
||||
normalized_product_id: Mapped[uuid.UUID | None] = mapped_column(
|
||||
ForeignKey("normalized_products.id")
|
||||
)
|
||||
|
||||
# Relationships
|
||||
purchase: Mapped["Purchase"] = relationship(back_populates="items")
|
||||
normalized_product: Mapped["NormalizedProduct | None"] = relationship(
|
||||
back_populates="purchase_items"
|
||||
)
|
||||
price_history_entries: Mapped[list["PriceHistory"]] = relationship(
|
||||
back_populates="purchase_item"
|
||||
)
|
||||
Reference in New Issue
Block a user