This repository has been archived on 2026-02-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
cart/models/order.py
giles d407957928
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 41s
Phase 5: Replace cross-domain writes with glue services, emit events
- checkout.py: use claim_entries_for_order(), emit order.created
- check_sumup_status.py: use confirm_entries_for_order(), emit order.paid
- global_routes.py: use get_entries_for_order() instead of relationship
- order.py: remove calendar_entries relationship
- api.py: remove /adopt endpoint (replaced by event-driven adoption)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 17:35:43 +00:00

115 lines
3.5 KiB
Python

from __future__ import annotations
from datetime import datetime
from typing import Optional, List
from sqlalchemy import Integer, String, DateTime, ForeignKey, Numeric, func, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship
from shared.db.base import Base
class Order(Base):
__tablename__ = "orders"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
user_id: Mapped[Optional[int]] = mapped_column(ForeignKey("users.id"), nullable=True)
session_id: Mapped[Optional[str]] = mapped_column(String(64), index=True, nullable=True)
page_config_id: Mapped[Optional[int]] = mapped_column(
ForeignKey("page_configs.id", ondelete="SET NULL"),
nullable=True,
index=True,
)
status: Mapped[str] = mapped_column(
String(32),
nullable=False,
default="pending",
server_default="pending",
)
currency: Mapped[str] = mapped_column(String(16), nullable=False, default="GBP")
total_amount: Mapped[float] = mapped_column(Numeric(12, 2), nullable=False)
# free-form description for the order
description: Mapped[Optional[str]] = mapped_column(Text, nullable=True, index=True)
# SumUp reference string (what we send as checkout_reference)
sumup_reference: Mapped[Optional[str]] = mapped_column(
String(255),
nullable=True,
index=True,
)
# SumUp integration fields
sumup_checkout_id: Mapped[Optional[str]] = mapped_column(
String(128),
nullable=True,
index=True,
)
sumup_status: Mapped[Optional[str]] = mapped_column(String(32), nullable=True)
sumup_hosted_url: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
server_default=func.now(),
)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
server_default=func.now(),
onupdate=func.now(),
)
items: Mapped[List["OrderItem"]] = relationship(
"OrderItem",
back_populates="order",
cascade="all, delete-orphan",
lazy="selectin",
)
page_config: Mapped[Optional["PageConfig"]] = relationship(
"PageConfig",
foreign_keys=[page_config_id],
lazy="selectin",
)
class OrderItem(Base):
__tablename__ = "order_items"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
order_id: Mapped[int] = mapped_column(
ForeignKey("orders.id", ondelete="CASCADE"),
nullable=False,
)
product_id: Mapped[int] = mapped_column(
ForeignKey("products.id"),
nullable=False,
)
product_title: Mapped[Optional[str]] = mapped_column(String(512), nullable=True)
quantity: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
unit_price: Mapped[float] = mapped_column(Numeric(12, 2), nullable=False)
currency: Mapped[str] = mapped_column(String(16), nullable=False, default="GBP")
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
nullable=False,
server_default=func.now(),
)
order: Mapped["Order"] = relationship(
"Order",
back_populates="items",
)
# NEW: link each order item to its product
product: Mapped["Product"] = relationship(
"Product",
back_populates="order_items",
lazy="selectin",
)