from __future__ import annotations import uuid from datetime import datetime from sqlalchemy import Boolean, DateTime, Integer, String, Text, UniqueConstraint, func from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.types import JSON from app.core.database import Base from app.models.base import UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin, ActorAuditMixin from app.models.types import GUID class Standard(Base, UUIDPrimaryKeyMixin, TenantMixin, TimestampMixin, ActorAuditMixin): __abstract__ = True code: Mapped[str | None] = mapped_column(String(120)) name: Mapped[str | None] = mapped_column(String(255)) status: Mapped[str] = mapped_column(String(40), default="active", nullable=False) data: Mapped[dict] = mapped_column(JSON, default=dict, nullable=False) class PaymentWorkspace(Standard): __tablename__="payment_workspaces" status: Mapped[str] = mapped_column(String(40), default="enabled", nullable=False) default_payment_mode: Mapped[str] = mapped_column(String(40), default="byo_psp", nullable=False) class PaymentBundleDefinition(Standard): __tablename__="payment_bundle_definitions" class TenantPaymentBundle(Standard): __tablename__="tenant_payment_bundles" bundle_code: Mapped[str] = mapped_column(String(120), nullable=False) is_active: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) __table_args__=(UniqueConstraint("tenant_id","bundle_code",name="uq_tenant_bundle"),) class PaymentFeatureToggle(Standard): __tablename__="payment_feature_toggles" key: Mapped[str] = mapped_column(String(150), nullable=False) enabled: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False) class PaymentProviderAssignment(Standard): __tablename__="payment_provider_assignments" class PspProviderRegistration(Standard): __tablename__="psp_provider_registrations" provider_code: Mapped[str] = mapped_column(String(80), nullable=False) class CreditProviderRegistration(Standard): __tablename__="credit_provider_registrations" provider_code: Mapped[str] = mapped_column(String(80), nullable=False) class PaymentConfiguration(Standard): __tablename__="payment_configurations" class PaymentSetting(Standard): __tablename__="payment_settings" key: Mapped[str] = mapped_column(String(150), nullable=False) value: Mapped[dict] = mapped_column(JSON, default=dict, nullable=False) class PaymentRole(Standard): __tablename__="payment_roles" class PaymentPermission(Standard): __tablename__="payment_permissions" class PaymentAuditLog(Base, UUIDPrimaryKeyMixin, TenantMixin): __tablename__="payment_audit_logs" entity_type: Mapped[str] = mapped_column(String(100), nullable=False) entity_id: Mapped[uuid.UUID | None] = mapped_column(GUID()) action: Mapped[str] = mapped_column(String(50), nullable=False) actor_user_id: Mapped[str | None] = mapped_column(String(100)) changes: Mapped[dict] = mapped_column(JSON, default=dict, nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False) class OutboxEvent(Base, UUIDPrimaryKeyMixin, TenantMixin): __tablename__="outbox_events" event_type: Mapped[str] = mapped_column(String(150), nullable=False) aggregate_type: Mapped[str] = mapped_column(String(100), nullable=False) aggregate_id: Mapped[str] = mapped_column(String(100), nullable=False) payload: Mapped[dict] = mapped_column(JSON, default=dict, nullable=False) status: Mapped[str] = mapped_column(String(30), default="pending", nullable=False) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False) class PspConnection(Standard): __tablename__="psp_connections" provider_code: Mapped[str] = mapped_column(String(80), nullable=False) credential_vault_ref: Mapped[str | None] = mapped_column(String(255)) secret_config: Mapped[dict] = mapped_column(JSON, default=dict, nullable=False) class PspCredentialVaultRef(Standard): __tablename__="psp_credential_vault_refs" class PspConnectionHealthCheck(Standard): __tablename__="psp_connection_health_checks" class PspRoutingPolicy(Standard): __tablename__="psp_routing_policies" class MerchantAccount(Standard): __tablename__="merchant_accounts" class MerchantAccountProfile(Standard): __tablename__="merchant_account_profiles" class MerchantSettlementProfile(Standard): __tablename__="merchant_settlement_profiles" class MerchantComplianceRef(Standard): __tablename__="merchant_compliance_refs" class MerchantAccountStatusHistory(Standard): __tablename__="merchant_account_status_history" class PaymentRequest(Standard): __tablename__="payment_requests" status: Mapped[str] = mapped_column(String(40), default="draft", nullable=False) idempotency_key: Mapped[str] = mapped_column(String(200), nullable=False) amount_minor: Mapped[int] = mapped_column(Integer, nullable=False) currency: Mapped[str] = mapped_column(String(3), default="IRR", nullable=False) payment_source: Mapped[str] = mapped_column(String(40), default="PSP", nullable=False) provider_code: Mapped[str] = mapped_column(String(80), default="mock", nullable=False) provider_transaction_id: Mapped[str | None] = mapped_column(String(200)) redirect_url: Mapped[str | None] = mapped_column(Text) source_service: Mapped[str | None] = mapped_column(String(80)) source_ref_type: Mapped[str | None] = mapped_column(String(80)) source_ref_id: Mapped[str | None] = mapped_column(String(100)) credit_provider_id: Mapped[uuid.UUID | None] = mapped_column(GUID()) financing_reference: Mapped[str | None] = mapped_column(String(200)) credit_authorization_reference: Mapped[str | None] = mapped_column(String(200)) installment_contract_reference: Mapped[str | None] = mapped_column(String(200)) __table_args__=(UniqueConstraint("tenant_id","idempotency_key",name="uq_payment_request_idem"),) class PaymentRequestStatusHistory(Standard): __tablename__="payment_request_status_history" class PaymentRequestLine(Standard): __tablename__="payment_request_lines" class PaymentCallbackLog(Standard): __tablename__="payment_callback_logs" connection_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False) provider_code: Mapped[str] = mapped_column(String(80), nullable=False) replay_key: Mapped[str] = mapped_column(String(250), nullable=False) __table_args__=(UniqueConstraint("tenant_id","replay_key",name="uq_callback_replay"),) class PaymentVerificationAttempt(Standard): __tablename__="payment_verification_attempts" class PaymentTransaction(Standard): __tablename__="payment_transactions" payment_request_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False) amount_minor: Mapped[int] = mapped_column(Integer, nullable=False) currency: Mapped[str] = mapped_column(String(3), nullable=False) provider_transaction_id: Mapped[str | None] = mapped_column(String(200)) __table_args__=(UniqueConstraint("tenant_id","payment_request_id",name="uq_transaction_request"),) class PaymentTransactionFeeLine(Standard): __tablename__="payment_transaction_fee_lines" class PaymentLedgerEntry(Standard): __tablename__="payment_ledger_entries" payment_transaction_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False) amount_minor: Mapped[int] = mapped_column(Integer, nullable=False) direction: Mapped[str] = mapped_column(String(10), nullable=False)