feat(savings): Add savings module with categories, transactions, recurring plans

- Categories: regular, deposits, credits, recurring, multi-user, accounts
- Transactions: deposits and withdrawals with user tracking
- Recurring plans: monthly payment obligations per user
- Stats: overdues calculation with allocation algorithm
- Excludes is_account categories from total sums
- Documentation: docs/SAVINGS.md
This commit is contained in:
Cosmo
2026-02-16 06:48:09 +00:00
parent 9e90aa6d95
commit 2a50e50771
18 changed files with 2910 additions and 162 deletions

View File

@@ -18,6 +18,8 @@ type Habit struct {
TargetCount int `db:"target_count" json:"target_count"`
ReminderTime sql.NullString `db:"reminder_time" json:"-"`
ReminderTimeStr *string `db:"-" json:"reminder_time"`
StartDate sql.NullTime `db:"start_date" json:"-"`
StartDateStr *string `db:"-" json:"start_date"`
IsArchived bool `db:"is_archived" json:"is_archived"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
@@ -42,6 +44,12 @@ func (h *Habit) ProcessForJSON() {
h.ReminderTimeStr = &formatted
}
}
// Process start_date
if h.StartDate.Valid {
formatted := h.StartDate.Time.Format("2006-01-02")
h.StartDateStr = &formatted
}
}
type HabitLog struct {
@@ -63,6 +71,7 @@ type CreateHabitRequest struct {
TargetDays []int `json:"target_days,omitempty"`
TargetCount int `json:"target_count,omitempty"`
ReminderTime *string `json:"reminder_time,omitempty"`
StartDate *string `json:"start_date,omitempty"`
}
type UpdateHabitRequest struct {
@@ -74,6 +83,7 @@ type UpdateHabitRequest struct {
TargetDays []int `json:"target_days,omitempty"`
TargetCount *int `json:"target_count,omitempty"`
ReminderTime *string `json:"reminder_time,omitempty"`
StartDate *string `json:"start_date,omitempty"`
IsArchived *bool `json:"is_archived,omitempty"`
}