package model import ( "database/sql" "time" ) type SavingsCategory struct { ID int64 `db:"id" json:"id"` UserID int64 `db:"user_id" json:"user_id"` Name string `db:"name" json:"name"` Description string `db:"description" json:"description"` // Type flags IsDeposit bool `db:"is_deposit" json:"is_deposit"` IsCredit bool `db:"is_credit" json:"is_credit"` IsAccount bool `db:"is_account" json:"is_account"` IsRecurring bool `db:"is_recurring" json:"is_recurring"` IsMulti bool `db:"is_multi" json:"is_multi"` IsClosed bool `db:"is_closed" json:"is_closed"` // Initial capital InitialCapital float64 `db:"initial_capital" json:"initial_capital"` // Deposit fields DepositAmount float64 `db:"deposit_amount" json:"deposit_amount"` InterestRate float64 `db:"interest_rate" json:"interest_rate"` DepositStartDate sql.NullTime `db:"deposit_start_date" json:"-"` DepositStartStr *string `db:"-" json:"deposit_start_date"` DepositTerm int `db:"deposit_term" json:"deposit_term"` DepositEndDate sql.NullTime `db:"deposit_end_date" json:"-"` DepositEndStr *string `db:"-" json:"deposit_end_date"` LastInterestCalc sql.NullTime `db:"last_interest_calc" json:"-"` FinalAmount float64 `db:"final_amount" json:"final_amount"` // Credit fields CreditAmount float64 `db:"credit_amount" json:"credit_amount"` CreditTerm int `db:"credit_term" json:"credit_term"` CreditRate float64 `db:"credit_rate" json:"credit_rate"` CreditStartDate sql.NullTime `db:"credit_start_date" json:"-"` CreditStartStr *string `db:"-" json:"credit_start_date"` // Recurring fields RecurringAmount float64 `db:"recurring_amount" json:"recurring_amount"` RecurringDay int `db:"recurring_day" json:"recurring_day"` RecurringStartDate sql.NullTime `db:"recurring_start_date" json:"-"` LastRecurringRun sql.NullTime `db:"last_recurring_run" json:"-"` // Computed (populated in service) CurrentAmount float64 `db:"-" json:"current_amount"` RecurringTotalAmount float64 `db:"-" json:"recurring_total_amount"` CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` // Relations Members []SavingsCategoryMember `db:"-" json:"members,omitempty"` } func (c *SavingsCategory) ProcessForJSON() { if c.DepositStartDate.Valid { formatted := c.DepositStartDate.Time.Format("2006-01-02") c.DepositStartStr = &formatted } if c.DepositEndDate.Valid { formatted := c.DepositEndDate.Time.Format("2006-01-02") c.DepositEndStr = &formatted } if c.CreditStartDate.Valid { formatted := c.CreditStartDate.Time.Format("2006-01-02") c.CreditStartStr = &formatted } } type SavingsTransaction struct { ID int64 `db:"id" json:"id"` CategoryID int64 `db:"category_id" json:"category_id"` UserID int64 `db:"user_id" json:"user_id"` Amount float64 `db:"amount" json:"amount"` Type string `db:"type" json:"type"` // deposit, withdrawal Description string `db:"description" json:"description"` Date time.Time `db:"date" json:"date"` CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` CategoryName string `db:"category_name" json:"category_name,omitempty"` UserName string `db:"user_name" json:"user_name,omitempty"` } type SavingsRecurringPlan struct { ID int64 `db:"id" json:"id"` CategoryID int64 `db:"category_id" json:"category_id"` UserID sql.NullInt64 `db:"user_id" json:"-"` UserIDPtr *int64 `db:"-" json:"user_id"` Effective time.Time `db:"effective" json:"effective"` Amount float64 `db:"amount" json:"amount"` Day int `db:"day" json:"day"` CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } func (p *SavingsRecurringPlan) ProcessForJSON() { if p.UserID.Valid { p.UserIDPtr = &p.UserID.Int64 } } type SavingsCategoryMember struct { ID int64 `db:"id" json:"id"` CategoryID int64 `db:"category_id" json:"category_id"` UserID int64 `db:"user_id" json:"user_id"` UserName string `db:"user_name" json:"user_name,omitempty"` CreatedAt time.Time `db:"created_at" json:"created_at"` } // Request DTOs type CreateSavingsCategoryRequest struct { Name string `json:"name"` Description string `json:"description,omitempty"` IsDeposit bool `json:"is_deposit,omitempty"` IsCredit bool `json:"is_credit,omitempty"` IsAccount bool `json:"is_account,omitempty"` IsRecurring bool `json:"is_recurring,omitempty"` IsMulti bool `json:"is_multi,omitempty"` InitialCapital float64 `json:"initial_capital,omitempty"` DepositAmount float64 `json:"deposit_amount,omitempty"` InterestRate float64 `json:"interest_rate,omitempty"` DepositStartDate *string `json:"deposit_start_date,omitempty"` DepositTerm int `json:"deposit_term,omitempty"` CreditAmount float64 `json:"credit_amount,omitempty"` CreditTerm int `json:"credit_term,omitempty"` CreditRate float64 `json:"credit_rate,omitempty"` CreditStartDate *string `json:"credit_start_date,omitempty"` RecurringAmount float64 `json:"recurring_amount,omitempty"` RecurringDay int `json:"recurring_day,omitempty"` RecurringStartDate *string `json:"recurring_start_date,omitempty"` MemberIDs []int64 `json:"member_ids,omitempty"` } type UpdateSavingsCategoryRequest struct { Name *string `json:"name,omitempty"` Description *string `json:"description,omitempty"` IsDeposit *bool `json:"is_deposit,omitempty"` IsCredit *bool `json:"is_credit,omitempty"` IsAccount *bool `json:"is_account,omitempty"` IsRecurring *bool `json:"is_recurring,omitempty"` IsMulti *bool `json:"is_multi,omitempty"` IsClosed *bool `json:"is_closed,omitempty"` InitialCapital *float64 `json:"initial_capital,omitempty"` DepositAmount *float64 `json:"deposit_amount,omitempty"` InterestRate *float64 `json:"interest_rate,omitempty"` DepositStartDate *string `json:"deposit_start_date,omitempty"` DepositTerm *int `json:"deposit_term,omitempty"` FinalAmount *float64 `json:"final_amount,omitempty"` CreditAmount *float64 `json:"credit_amount,omitempty"` CreditTerm *int `json:"credit_term,omitempty"` CreditRate *float64 `json:"credit_rate,omitempty"` CreditStartDate *string `json:"credit_start_date,omitempty"` RecurringAmount *float64 `json:"recurring_amount,omitempty"` RecurringDay *int `json:"recurring_day,omitempty"` RecurringStartDate *string `json:"recurring_start_date,omitempty"` } type CreateSavingsTransactionRequest struct { CategoryID int64 `json:"category_id"` Amount float64 `json:"amount"` Type string `json:"type"` // deposit, withdrawal Description string `json:"description,omitempty"` Date string `json:"date"` } type UpdateSavingsTransactionRequest struct { Amount *float64 `json:"amount,omitempty"` Type *string `json:"type,omitempty"` Description *string `json:"description,omitempty"` Date *string `json:"date,omitempty"` } type CreateRecurringPlanRequest struct { Effective string `json:"effective"` Amount float64 `json:"amount"` Day int `json:"day,omitempty"` UserID *int64 `json:"user_id,omitempty"` } type UpdateRecurringPlanRequest struct { Effective *string `json:"effective,omitempty"` Amount *float64 `json:"amount,omitempty"` Day *int `json:"day,omitempty"` } type SavingsStats struct { MonthlyPayments float64 `json:"monthly_payments"` MonthlyPaymentDetails []MonthlyPaymentDetail `json:"monthly_payment_details"` Overdues []OverduePayment `json:"overdues"` TotalBalance float64 `json:"total_balance"` TotalDeposits float64 `json:"total_deposits"` TotalWithdrawals float64 `json:"total_withdrawals"` CategoriesCount int `json:"categories_count"` ByCategory []CategoryStats `json:"by_category"` } type CategoryStats struct { CategoryID int64 `json:"category_id"` CategoryName string `json:"category_name"` Balance float64 `json:"balance"` IsDeposit bool `json:"is_deposit"` IsRecurring bool `json:"is_recurring"` } // MonthlyPaymentDetail represents a recurring payment detail type MonthlyPaymentDetail struct { CategoryID int64 `json:"category_id"` CategoryName string `json:"category_name"` Amount float64 `json:"amount"` Day int `json:"day"` } // OverduePayment represents an overdue recurring payment type OverduePayment struct { CategoryID int64 `json:"category_id"` CategoryName string `json:"category_name"` UserID int64 `json:"user_id"` UserName string `json:"user_name"` Amount float64 `json:"amount"` DueDay int `json:"due_day"` DaysOverdue int `json:"days_overdue"` Month string `json:"month"` }