Files
pulse-api/internal/model/finance.go
Cosmo 23939ccc92
All checks were successful
CI / ci (push) Successful in 12s
feat: add finance module (categories, transactions, summary, analytics)
- model/finance.go: FinanceCategory, FinanceTransaction, Summary, Analytics
- repository/finance.go: CRUD + summary/analytics queries
- service/finance.go: business logic with auto-seed default categories
- handler/finance.go: REST endpoints with owner-only check (user_id=1)
- db.go: finance_categories + finance_transactions migrations
- main.go: register /finance/* routes

Endpoints: GET/POST/PUT/DELETE /finance/categories, /finance/transactions
GET /finance/summary, /finance/analytics
2026-03-01 04:22:10 +00:00

115 lines
3.8 KiB
Go

package model
import (
"database/sql"
"time"
)
type FinanceCategory struct {
ID int64 `db:"id" json:"id"`
UserID int64 `db:"user_id" json:"user_id"`
Name string `db:"name" json:"name"`
Emoji string `db:"emoji" json:"emoji"`
Type string `db:"type" json:"type"`
Budget sql.NullFloat64 `db:"budget" json:"-"`
BudgetVal *float64 `db:"-" json:"budget"`
Color string `db:"color" json:"color"`
SortOrder int `db:"sort_order" json:"sort_order"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
}
func (c *FinanceCategory) ProcessForJSON() {
if c.Budget.Valid {
c.BudgetVal = &c.Budget.Float64
}
}
type FinanceTransaction struct {
ID int64 `db:"id" json:"id"`
UserID int64 `db:"user_id" json:"user_id"`
CategoryID int64 `db:"category_id" json:"category_id"`
Type string `db:"type" json:"type"`
Amount float64 `db:"amount" json:"amount"`
Description string `db:"description" json:"description"`
Date time.Time `db:"date" json:"date"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
// Joined fields
CategoryName string `db:"category_name" json:"category_name,omitempty"`
CategoryEmoji string `db:"category_emoji" json:"category_emoji,omitempty"`
}
type CreateFinanceCategoryRequest struct {
Name string `json:"name"`
Emoji string `json:"emoji,omitempty"`
Type string `json:"type"`
Budget *float64 `json:"budget,omitempty"`
Color string `json:"color,omitempty"`
SortOrder int `json:"sort_order,omitempty"`
}
type UpdateFinanceCategoryRequest struct {
Name *string `json:"name,omitempty"`
Emoji *string `json:"emoji,omitempty"`
Type *string `json:"type,omitempty"`
Budget *float64 `json:"budget,omitempty"`
Color *string `json:"color,omitempty"`
SortOrder *int `json:"sort_order,omitempty"`
}
type CreateFinanceTransactionRequest struct {
CategoryID int64 `json:"category_id"`
Type string `json:"type"`
Amount float64 `json:"amount"`
Description string `json:"description,omitempty"`
Date string `json:"date"`
}
type UpdateFinanceTransactionRequest struct {
CategoryID *int64 `json:"category_id,omitempty"`
Type *string `json:"type,omitempty"`
Amount *float64 `json:"amount,omitempty"`
Description *string `json:"description,omitempty"`
Date *string `json:"date,omitempty"`
}
type FinanceSummary struct {
Balance float64 `json:"balance"`
TotalIncome float64 `json:"total_income"`
TotalExpense float64 `json:"total_expense"`
ByCategory []CategorySummary `json:"by_category"`
Daily []DailySummary `json:"daily"`
}
type CategorySummary struct {
CategoryID int64 `json:"category_id" db:"category_id"`
CategoryName string `json:"category_name" db:"category_name"`
CategoryEmoji string `json:"category_emoji" db:"category_emoji"`
Type string `json:"type" db:"type"`
Amount float64 `json:"amount" db:"amount"`
Percentage float64 `json:"percentage"`
Budget *float64 `json:"budget,omitempty"`
}
type DailySummary struct {
Date string `json:"date" db:"date"`
Amount float64 `json:"amount" db:"amount"`
}
type FinanceAnalytics struct {
MonthlyTrend []MonthlyTrend `json:"monthly_trend"`
AvgDailyExpense float64 `json:"avg_daily_expense"`
ComparisonPrevMonth Comparison `json:"comparison_prev_month"`
}
type MonthlyTrend struct {
Month string `json:"month" db:"month"`
Income float64 `json:"income" db:"income"`
Expense float64 `json:"expense" db:"expense"`
}
type Comparison struct {
Current float64 `json:"current"`
Previous float64 `json:"previous"`
DiffPercent float64 `json:"diff_percent"`
}