refactors
This commit is contained in:
parent
4e1a339432
commit
82c4d0168e
28 changed files with 1042 additions and 782 deletions
83
backend/models/exchange.py
Normal file
83
backend/models/exchange.py
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import uuid
|
||||
from datetime import UTC, datetime
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import DateTime, Enum, Float, ForeignKey, Integer
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from database import Base
|
||||
|
||||
from .enums import BitcoinTransferMethod, ExchangeStatus, TradeDirection
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .user import User
|
||||
|
||||
|
||||
class Exchange(Base):
|
||||
"""Bitcoin exchange trades booked by users."""
|
||||
|
||||
__tablename__ = "exchanges"
|
||||
# Note: No unique constraint on slot_start to allow cancelled bookings
|
||||
# to be replaced. Application-level check in create_exchange ensures only
|
||||
# one BOOKED trade per slot. For existing databases, manually drop the
|
||||
# constraint: ALTER TABLE exchanges DROP CONSTRAINT IF EXISTS
|
||||
# uq_exchange_slot_start;
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
public_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
unique=True,
|
||||
index=True,
|
||||
default=uuid.uuid4,
|
||||
)
|
||||
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
|
||||
)
|
||||
bitcoin_transfer_method: Mapped[BitcoinTransferMethod] = mapped_column(
|
||||
Enum(BitcoinTransferMethod),
|
||||
nullable=False,
|
||||
default=BitcoinTransferMethod.ONCHAIN,
|
||||
)
|
||||
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