hesabixArc/hesabixAPI/adapters/db/models/wallet.py
2025-11-09 05:16:37 +00:00

110 lines
5.4 KiB
Python

from __future__ import annotations
from datetime import datetime
from typing import Optional
from sqlalchemy import String, Integer, DateTime, ForeignKey, UniqueConstraint, Numeric, Boolean, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship
from adapters.db.session import Base
class WalletAccount(Base):
__tablename__ = "wallet_accounts"
__table_args__ = (
UniqueConstraint('business_id', name='uq_wallet_accounts_business'),
)
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
business_id: Mapped[int] = mapped_column(Integer, ForeignKey("businesses.id", ondelete="CASCADE"), nullable=False, index=True)
# مانده‌ها به ارز پایه سیستم
available_balance: Mapped[float] = mapped_column(Numeric(18, 2), nullable=False, default=0)
pending_balance: Mapped[float] = mapped_column(Numeric(18, 2), nullable=False, default=0)
status: Mapped[str] = mapped_column(String(20), nullable=False, default="active") # active | suspended
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
# روابط
business = relationship("Business", backref="wallet_account", uselist=False)
class WalletTransaction(Base):
__tablename__ = "wallet_transactions"
__table_args__ = (
# ایندکس‌ها از طریق migration اضافه می‌شود
)
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
business_id: Mapped[int] = mapped_column(Integer, ForeignKey("businesses.id", ondelete="CASCADE"), nullable=False, index=True)
# انواع: customer_payment, top_up, internal_invoice_payment, payout_request, payout_settlement, refund, fee, chargeback, reversal
type: Mapped[str] = mapped_column(String(50), nullable=False)
status: Mapped[str] = mapped_column(String(20), nullable=False, default="pending") # pending, succeeded, failed, reversed
amount: Mapped[float] = mapped_column(Numeric(18, 2), nullable=False, default=0) # ارز پایه
fee_amount: Mapped[float | None] = mapped_column(Numeric(18, 2), nullable=True)
description: Mapped[str | None] = mapped_column(String(500), nullable=True)
external_ref: Mapped[str | None] = mapped_column(String(100), nullable=True) # شناسه درگاه/مرجع خارجی
# پیوند به سند حسابداری
document_id: Mapped[int | None] = mapped_column(Integer, ForeignKey("documents.id", ondelete="SET NULL"), nullable=True, index=True)
# متادیتا
extra_info: Mapped[str | None] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
business = relationship("Business", backref="wallet_transactions")
document = relationship("Document", backref="wallet_transactions")
class WalletPayout(Base):
__tablename__ = "wallet_payouts"
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
business_id: Mapped[int] = mapped_column(Integer, ForeignKey("businesses.id", ondelete="CASCADE"), nullable=False, index=True)
bank_account_id: Mapped[int] = mapped_column(Integer, ForeignKey("bank_accounts.id", ondelete="RESTRICT"), nullable=False, index=True)
gross_amount: Mapped[float] = mapped_column(Numeric(18, 2), nullable=False, default=0)
fees: Mapped[float] = mapped_column(Numeric(18, 2), nullable=False, default=0)
net_amount: Mapped[float] = mapped_column(Numeric(18, 2), nullable=False, default=0)
status: Mapped[str] = mapped_column(String(20), nullable=False, default="requested") # requested, approved, processing, settled, failed, canceled
schedule_type: Mapped[str] = mapped_column(String(20), nullable=False, default="manual") # manual, daily, weekly, threshold
external_ref: Mapped[str | None] = mapped_column(String(100), nullable=True)
extra_info: Mapped[str | None] = mapped_column(Text, nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
business = relationship("Business", backref="wallet_payouts")
class WalletSetting(Base):
__tablename__ = "wallet_settings"
__table_args__ = (
UniqueConstraint('business_id', name='uq_wallet_settings_business'),
)
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
business_id: Mapped[int] = mapped_column(Integer, ForeignKey("businesses.id", ondelete="CASCADE"), nullable=False, index=True)
mode: Mapped[str] = mapped_column(String(20), nullable=False, default="manual") # manual | auto
frequency: Mapped[str | None] = mapped_column(String(20), nullable=True) # daily | weekly
threshold_amount: Mapped[float | None] = mapped_column(Numeric(18, 2), nullable=True)
min_reserve: Mapped[float | None] = mapped_column(Numeric(18, 2), nullable=True)
default_bank_account_id: Mapped[int | None] = mapped_column(Integer, ForeignKey("bank_accounts.id", ondelete="SET NULL"), nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, nullable=False)
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
business = relationship("Business", backref="wallet_settings", uselist=False)