70 lines
2.5 KiB
Python
70 lines
2.5 KiB
Python
import uuid
|
|
from datetime import datetime
|
|
from decimal import Decimal
|
|
from enum import StrEnum
|
|
from typing import Any
|
|
|
|
from sqlalchemy import DateTime, Enum, Integer, Numeric, String, Text, func
|
|
from sqlalchemy.dialects.postgresql import JSONB, UUID
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.db import Base
|
|
|
|
|
|
class Currency(StrEnum):
|
|
RUB = "RUB"
|
|
USD = "USD"
|
|
EUR = "EUR"
|
|
|
|
|
|
class PaymentStatus(StrEnum):
|
|
PENDING = "pending"
|
|
SUCCEEDED = "succeeded"
|
|
FAILED = "failed"
|
|
|
|
|
|
class Payment(Base):
|
|
__tablename__ = "payments"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
amount: Mapped[Decimal] = mapped_column(Numeric(18, 2), nullable=False)
|
|
currency: Mapped[Currency] = mapped_column(
|
|
Enum(Currency, name="currency", values_callable=lambda values: [v.value for v in values]),
|
|
nullable=False,
|
|
)
|
|
description: Mapped[str] = mapped_column(String(500), nullable=False)
|
|
metadata_: Mapped[dict[str, Any]] = mapped_column(
|
|
"metadata", JSONB, default=dict, nullable=False
|
|
)
|
|
status: Mapped[PaymentStatus] = mapped_column(
|
|
Enum(
|
|
PaymentStatus,
|
|
name="payment_status",
|
|
values_callable=lambda values: [v.value for v in values],
|
|
),
|
|
default=PaymentStatus.PENDING,
|
|
nullable=False,
|
|
)
|
|
idempotency_key: Mapped[str] = mapped_column(String(255), unique=True, nullable=False)
|
|
webhook_url: Mapped[str] = mapped_column(Text, nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), nullable=False
|
|
)
|
|
processed_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
|
webhook_delivered_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
|
|
|
|
|
|
class OutboxEvent(Base):
|
|
__tablename__ = "outbox"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
|
aggregate_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), nullable=False, index=True)
|
|
event_type: Mapped[str] = mapped_column(String(100), nullable=False)
|
|
payload: Mapped[dict[str, Any]] = mapped_column(JSONB, nullable=False)
|
|
attempts: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
|
|
last_error: Mapped[str | None] = mapped_column(Text)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), nullable=False
|
|
)
|
|
published_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), index=True)
|