Files
payment-processing-test/app/models.py
T

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)