diff --git a/migrations.py b/migrations.py index fd08f99..fbc7975 100644 --- a/migrations.py +++ b/migrations.py @@ -1,113 +1,2 @@ -# DCA Client Extension Database Migrations -# Creates all necessary tables for Dollar Cost Averaging administration -# with Lamassu ATM integration - - -async def m001_initial_dca_schema(db): - """ - Create complete DCA admin schema from scratch. - """ - # DCA Clients table - await db.execute( - f""" - CREATE TABLE satmachineclient.dca_clients ( - id TEXT PRIMARY KEY NOT NULL, - user_id TEXT NOT NULL, - wallet_id TEXT NOT NULL, - username TEXT, - dca_mode TEXT NOT NULL DEFAULT 'flow', - fixed_mode_daily_limit INTEGER, - status TEXT NOT NULL DEFAULT 'active', - created_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}, - updated_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now} - ); - """ - ) - - # DCA Deposits table - await db.execute( - f""" - CREATE TABLE satmachineclient.dca_deposits ( - id TEXT PRIMARY KEY NOT NULL, - client_id TEXT NOT NULL, - amount INTEGER NOT NULL, - currency TEXT NOT NULL DEFAULT 'GTQ', - status TEXT NOT NULL DEFAULT 'pending', - notes TEXT, - created_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}, - confirmed_at TIMESTAMP - ); - """ - ) - - # DCA Payments table - await db.execute( - f""" - CREATE TABLE satmachineclient.dca_payments ( - id TEXT PRIMARY KEY NOT NULL, - client_id TEXT NOT NULL, - amount_sats INTEGER NOT NULL, - amount_fiat INTEGER NOT NULL, - exchange_rate REAL NOT NULL, - transaction_type TEXT NOT NULL, - lamassu_transaction_id TEXT, - payment_hash TEXT, - status TEXT NOT NULL DEFAULT 'pending', - created_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now} - ); - """ - ) - - # Lamassu Configuration table - await db.execute( - f""" - CREATE TABLE satmachineclient.lamassu_config ( - id TEXT PRIMARY KEY NOT NULL, - host TEXT NOT NULL, - port INTEGER NOT NULL DEFAULT 5432, - database_name TEXT NOT NULL, - username TEXT NOT NULL, - password TEXT NOT NULL, - source_wallet_id TEXT, - commission_wallet_id TEXT, - is_active BOOLEAN NOT NULL DEFAULT true, - test_connection_last TIMESTAMP, - test_connection_success BOOLEAN, - last_poll_time TIMESTAMP, - last_successful_poll TIMESTAMP, - use_ssh_tunnel BOOLEAN NOT NULL DEFAULT false, - ssh_host TEXT, - ssh_port INTEGER NOT NULL DEFAULT 22, - ssh_username TEXT, - ssh_password TEXT, - ssh_private_key TEXT, - created_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}, - updated_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now} - ); - """ - ) - - # Lamassu Transactions table (for audit trail) - await db.execute( - f""" - CREATE TABLE satmachineclient.lamassu_transactions ( - id TEXT PRIMARY KEY NOT NULL, - lamassu_transaction_id TEXT NOT NULL UNIQUE, - fiat_amount INTEGER NOT NULL, - crypto_amount INTEGER NOT NULL, - commission_percentage REAL NOT NULL, - discount REAL NOT NULL DEFAULT 0.0, - effective_commission REAL NOT NULL, - commission_amount_sats INTEGER NOT NULL, - base_amount_sats INTEGER NOT NULL, - exchange_rate REAL NOT NULL, - crypto_code TEXT NOT NULL DEFAULT 'BTC', - fiat_code TEXT NOT NULL DEFAULT 'GTQ', - device_id TEXT, - transaction_time TIMESTAMP NOT NULL, - processed_at TIMESTAMP NOT NULL DEFAULT {db.timestamp_now}, - clients_count INTEGER NOT NULL DEFAULT 0, - distributions_total_sats INTEGER NOT NULL DEFAULT 0 - ); - """ - ) \ No newline at end of file +# No database migrations needed for client extension +# Client extension reads from admin extension's database (ext_satmachineadmin schema) \ No newline at end of file diff --git a/models.py b/models.py index 964d67c..59b683f 100644 --- a/models.py +++ b/models.py @@ -1,209 +1,60 @@ -# Description: Pydantic data models dictate what is passed between frontend and backend. +# Description: Pydantic data models for client extension API responses from datetime import datetime -from typing import Optional +from typing import List, Optional from pydantic import BaseModel -# DCA Client Models -class CreateDcaClientData(BaseModel): +# Client Dashboard Data Models +class ClientDashboardSummary(BaseModel): + """Summary metrics for client dashboard overview""" user_id: str - wallet_id: str - username: str - dca_mode: str = "flow" # 'flow' or 'fixed' - fixed_mode_daily_limit: Optional[int] = None - - -class DcaClient(BaseModel): - id: str - user_id: str - wallet_id: str - username: Optional[str] - dca_mode: str - fixed_mode_daily_limit: Optional[int] - status: str - created_at: datetime - updated_at: datetime - - -class UpdateDcaClientData(BaseModel): - username: Optional[str] = None - dca_mode: Optional[str] = None - fixed_mode_daily_limit: Optional[int] = None - status: Optional[str] = None - - -# Deposit Models -class CreateDepositData(BaseModel): - client_id: str - amount: int # Amount in smallest currency unit (centavos for GTQ) + total_sats_accumulated: int + total_fiat_invested: int # In centavos + average_cost_basis: float # Average sats per fiat unit + current_fiat_balance: int # Available balance for DCA + total_transactions: int + dca_mode: str # 'flow' or 'fixed' + dca_status: str # 'active' or 'inactive' + last_transaction_date: Optional[datetime] currency: str = "GTQ" - notes: Optional[str] = None -class DcaDeposit(BaseModel): +class ClientTransaction(BaseModel): + """Read-only view of client's DCA transactions""" id: str - client_id: str - amount: int - currency: str - status: str # 'pending' or 'confirmed' - notes: Optional[str] - created_at: datetime - confirmed_at: Optional[datetime] - - -class UpdateDepositStatusData(BaseModel): - status: str - notes: Optional[str] = None - - -# Payment Models -class CreateDcaPaymentData(BaseModel): - client_id: str amount_sats: int amount_fiat: int exchange_rate: float - transaction_type: str # 'flow', 'fixed', 'manual', 'commission' + transaction_type: str # 'flow', 'fixed', 'manual' + status: str + created_at: datetime lamassu_transaction_id: Optional[str] = None - payment_hash: Optional[str] = None -class DcaPayment(BaseModel): - id: str - client_id: str - amount_sats: int - amount_fiat: int - exchange_rate: float - transaction_type: str - lamassu_transaction_id: Optional[str] - payment_hash: Optional[str] - status: str # 'pending', 'confirmed', 'failed' - created_at: datetime +class ClientAnalytics(BaseModel): + """Performance analytics for client dashboard""" + user_id: str + cost_basis_history: List[dict] # Historical cost basis data points + accumulation_timeline: List[dict] # Sats accumulated over time + transaction_frequency: dict # Transaction frequency metrics + performance_vs_market: Optional[dict] = None # Market comparison data -# Client Balance Summary -class ClientBalanceSummary(BaseModel): - client_id: str - total_deposits: int # Total confirmed deposits - total_payments: int # Total payments made - remaining_balance: int # Available balance for DCA - currency: str +class ClientPreferences(BaseModel): + """Client dashboard preferences and settings""" + user_id: str + preferred_currency: str = "GTQ" + dashboard_theme: str = "light" + chart_time_range: str = "30d" # Default chart time range + notification_preferences: dict = {} -# Transaction Processing Models -class LamassuTransaction(BaseModel): - transaction_id: str - amount_fiat: int - amount_crypto: int - exchange_rate: float - transaction_type: str # 'cash_in' or 'cash_out' - status: str - timestamp: datetime - - -# Lamassu Transaction Storage Models -class CreateLamassuTransactionData(BaseModel): - lamassu_transaction_id: str - fiat_amount: int - crypto_amount: int - commission_percentage: float - discount: float = 0.0 - effective_commission: float - commission_amount_sats: int - base_amount_sats: int - exchange_rate: float - crypto_code: str = "BTC" - fiat_code: str = "GTQ" - device_id: Optional[str] = None - transaction_time: datetime - - -class StoredLamassuTransaction(BaseModel): - id: str - lamassu_transaction_id: str - fiat_amount: int - crypto_amount: int - commission_percentage: float - discount: float - effective_commission: float - commission_amount_sats: int - base_amount_sats: int - exchange_rate: float - crypto_code: str - fiat_code: str - device_id: Optional[str] - transaction_time: datetime - processed_at: datetime - clients_count: int # Number of clients who received distributions - distributions_total_sats: int # Total sats distributed to clients - - -# Lamassu Configuration Models -class CreateLamassuConfigData(BaseModel): - host: str - port: int = 5432 - database_name: str - username: str - password: str - # Source wallet for DCA distributions - source_wallet_id: Optional[str] = None - # Commission wallet for storing commission earnings - commission_wallet_id: Optional[str] = None - # SSH Tunnel settings - use_ssh_tunnel: bool = False - ssh_host: Optional[str] = None - ssh_port: int = 22 - ssh_username: Optional[str] = None - ssh_password: Optional[str] = None - ssh_private_key: Optional[str] = None # Path to private key file or key content - - -class LamassuConfig(BaseModel): - id: str - host: str - port: int - database_name: str - username: str - password: str - is_active: bool - test_connection_last: Optional[datetime] - test_connection_success: Optional[bool] - created_at: datetime - updated_at: datetime - # Source wallet for DCA distributions - source_wallet_id: Optional[str] = None - # Commission wallet for storing commission earnings - commission_wallet_id: Optional[str] = None - # SSH Tunnel settings - use_ssh_tunnel: bool = False - ssh_host: Optional[str] = None - ssh_port: int = 22 - ssh_username: Optional[str] = None - ssh_password: Optional[str] = None - ssh_private_key: Optional[str] = None - # Poll tracking - last_poll_time: Optional[datetime] = None - last_successful_poll: Optional[datetime] = None - - -class UpdateLamassuConfigData(BaseModel): - host: Optional[str] = None - port: Optional[int] = None - database_name: Optional[str] = None - username: Optional[str] = None - password: Optional[str] = None - is_active: Optional[bool] = None - # Source wallet for DCA distributions - source_wallet_id: Optional[str] = None - # Commission wallet for storing commission earnings - commission_wallet_id: Optional[str] = None - # SSH Tunnel settings - use_ssh_tunnel: Optional[bool] = None - ssh_host: Optional[str] = None - ssh_port: Optional[int] = None - ssh_username: Optional[str] = None - ssh_password: Optional[str] = None - ssh_private_key: Optional[str] = None +class UpdateClientSettings(BaseModel): + """Settings that client can modify""" + dca_mode: Optional[str] = None # 'flow' or 'fixed' + fixed_mode_daily_limit: Optional[int] = None + status: Optional[str] = None # 'active' or 'inactive'