Phase 1.2: Create Exchange model
Add Exchange model with: - user_id / user relationship - slot_start / slot_end (datetime) - direction (TradeDirection enum: buy/sell) - eur_amount (int, cents), sats_amount (int) - market_price_eur, agreed_price_eur (float) - premium_percentage (int, snapshot) - status (ExchangeStatus enum) - created_at, cancelled_at, completed_at timestamps - unique constraint on slot_start
This commit is contained in:
parent
30e5d0828e
commit
61e95e56d5
1 changed files with 53 additions and 0 deletions
|
|
@ -348,3 +348,56 @@ class PriceHistory(Base):
|
|||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=lambda: datetime.now(UTC)
|
||||
)
|
||||
|
||||
|
||||
class Exchange(Base):
|
||||
"""Bitcoin exchange trades booked by users."""
|
||||
|
||||
__tablename__ = "exchanges"
|
||||
__table_args__ = (UniqueConstraint("slot_start", name="uq_exchange_slot_start"),)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
user_id: Mapped[int] = mapped_column(
|
||||
Integer, ForeignKey("users.id"), nullable=False, index=True
|
||||
)
|
||||
user: Mapped[User] = relationship("User", foreign_keys=[user_id], lazy="joined")
|
||||
|
||||
# Slot timing
|
||||
slot_start: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), nullable=False, index=True
|
||||
)
|
||||
slot_end: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
|
||||
|
||||
# Trade details
|
||||
direction: Mapped[TradeDirection] = mapped_column(
|
||||
Enum(TradeDirection), nullable=False
|
||||
)
|
||||
eur_amount: Mapped[int] = mapped_column(Integer, nullable=False) # EUR cents
|
||||
sats_amount: Mapped[int] = mapped_column(Integer, nullable=False) # Satoshis
|
||||
|
||||
# Price information (snapshot at booking time)
|
||||
market_price_eur: Mapped[float] = mapped_column(
|
||||
Float, nullable=False
|
||||
) # EUR per BTC
|
||||
agreed_price_eur: Mapped[float] = mapped_column(
|
||||
Float, nullable=False
|
||||
) # EUR per BTC with premium
|
||||
premium_percentage: Mapped[int] = mapped_column(
|
||||
Integer, nullable=False
|
||||
) # e.g. 5 for 5%
|
||||
|
||||
# Status
|
||||
status: Mapped[ExchangeStatus] = mapped_column(
|
||||
Enum(ExchangeStatus), nullable=False, default=ExchangeStatus.BOOKED
|
||||
)
|
||||
|
||||
# Timestamps
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=lambda: datetime.now(UTC)
|
||||
)
|
||||
cancelled_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True
|
||||
)
|
||||
completed_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue