models

package
v4.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 1, 2024 License: AGPL-3.0 Imports: 9 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrAllocationZero        = errors.New("allocation amounts must be non-zero. Instead of setting to zero, delete the Allocation")
	ErrGoalAmountNotPositive = errors.New("goal amounts must be larger than zero")
)

Functions

func Migrate

func Migrate(db *gorm.DB) (err error)

Migrate migrates all models to the schema defined in the code.

Types

type Account

type Account struct {
	DefaultModel
	AccountCreate
	Budget Budget `json:"-"`
}

Account represents an asset account, e.g. a bank account.

func (*Account) BeforeSave

func (a *Account) BeforeSave(_ *gorm.DB) error

BeforeSave ensures consistency for the account

It enforces OnBudget to be false when the account is external.

It trims whitespace from all strings

func (Account) BeforeUpdate

func (a Account) BeforeUpdate(tx *gorm.DB) (err error)

BeforeUpdate verifies the state of the account before committing an update to the database.

func (Account) GetBalanceMonth

func (a Account) GetBalanceMonth(db *gorm.DB, month types.Month) (balance, available decimal.Decimal, err error)

GetBalanceMonth calculates the balance and available sums for a specific month.

The balance Decimal is the actual account balance, factoring in all transactions before the end of the month. The available Decimal is the sum that is available for budgeting at the end of the specified month.

func (Account) RecentEnvelopes

func (a Account) RecentEnvelopes(db *gorm.DB) ([]*uuid.UUID, error)

SetRecentEnvelopes returns the most common envelopes used in the last 50 transactions where the account is the destination account.

The list is sorted by decending frequency of the envelope being used. If two envelopes appear with the same frequency, the order is undefined since sqlite does not have ordering by datetime with more than second precision.

If creation times are more than a second apart, ordering is well defined.

func (Account) Self

func (Account) Self() string

func (Account) SumReconciled

func (a Account) SumReconciled(db *gorm.DB) (balance decimal.Decimal, err error)

Transactions returns all transactions for this account.

func (Account) Transactions

func (a Account) Transactions(db *gorm.DB) []Transaction

Transactions returns all transactions for this account.

type AccountCreate

type AccountCreate struct {
	Name               string          `json:"name" example:"Cash" default:"" gorm:"uniqueIndex:account_name_budget_id"`                          // Name of the account
	Note               string          `json:"note" example:"Money in my wallet" default:""`                                                      // A longer description for the account
	BudgetID           uuid.UUID       `json:"budgetId" example:"550dc009-cea6-4c12-b2a5-03446eb7b7cf" gorm:"uniqueIndex:account_name_budget_id"` // ID of the budget this account belongs to
	OnBudget           bool            `json:"onBudget" example:"true" default:"false"`                                                           // Does the account factor into the available budget? Always false when external: true
	External           bool            `json:"external" example:"false" default:"false"`                                                          // Does the account belong to the budget owner or not?
	InitialBalance     decimal.Decimal `json:"initialBalance" example:"173.12" default:"0"`                                                       // Balance of the account before any transactions were recorded
	InitialBalanceDate *time.Time      `json:"initialBalanceDate" example:"2017-05-12T00:00:00Z"`                                                 // Date of the initial balance
	Archived           bool            `json:"archived" example:"true" default:"false"`                                                           // Is the account archived?
	ImportHash         string          `json:"importHash" example:"867e3a26dc0baf73f4bff506f31a97f6c32088917e9e5cf1a5ed6f3f84a6fa70" default:""`  // The SHA256 hash of a unique combination of values to use in duplicate detection
}

AccountCreate represents all parameters of an Account that are configurable by the user.

type AggregatedTransaction

type AggregatedTransaction struct {
	Amount                     decimal.Decimal
	Date                       time.Time
	SourceAccountOnBudget      bool
	DestinationAccountOnBudget bool
}

type Budget

type Budget struct {
	DefaultModel
	BudgetCreate
}

Budget represents a budget

A budget is the highest level of organization in Envelope Zero, all other resources reference it directly or transitively.

func (Budget) Allocated

func (b Budget) Allocated(db *gorm.DB, month types.Month) (allocated decimal.Decimal, err error)

Allocated calculates the sum that has been budgeted for a specific month.

func (Budget) Balance

func (b Budget) Balance(tx *gorm.DB) (balance decimal.Decimal, err error)

Balance calculates the balance for a budget.

func (*Budget) BeforeSave

func (b *Budget) BeforeSave(_ *gorm.DB) error

func (Budget) Income

func (b Budget) Income(db *gorm.DB, month types.Month) (income decimal.Decimal, err error)

Income returns the income for a budget in a given month.

func (Budget) Self

func (b Budget) Self() string

type BudgetCreate

type BudgetCreate struct {
	Name     string `json:"name" example:"Morre's Budget" default:""`       // Name of the budget
	Note     string `json:"note" example:"My personal expenses" default:""` // A longer description of the budget
	Currency string `json:"currency" example:"€" default:""`                // The currency for the budget
}

type BudgetMonth

type BudgetMonth struct {
	ID        uuid.UUID       `json:"id" example:"1e777d24-3f5b-4c43-8000-04f65f895578"` // The ID of the Budget
	Name      string          `json:"name" example:"Groceries"`                          // The name of the Budget
	Month     types.Month     `json:"month" example:"2006-05-01T00:00:00.000000Z"`       // Month these calculations are made for
	Budgeted  decimal.Decimal `json:"budgeted" example:"2100"`                           // Amount of money that has been allocated to envelopes
	Income    decimal.Decimal `json:"income" example:"2317.34"`                          // Income. This is all money that is sent from off-budget to on-budget accounts without an envelope set.
	Available decimal.Decimal `json:"available" example:"217.34"`                        // The amount of money still available to budget.
	Envelopes []EnvelopeMonth `json:"envelopes"`                                         // The envelopes this budget has, with detailed calculations
}

func (BudgetMonth) Self

func (b BudgetMonth) Self() string

type Category

type Category struct {
	DefaultModel
	CategoryCreate
	Budget Budget `json:"-"`
}

Category represents a category of envelopes.

func (*Category) BeforeSave

func (c *Category) BeforeSave(_ *gorm.DB) error

func (*Category) BeforeUpdate

func (c *Category) BeforeUpdate(tx *gorm.DB) (err error)

BeforeUpdate archives all envelopes when the category is archived.

func (*Category) Envelopes

func (c *Category) Envelopes(tx *gorm.DB) ([]Envelope, error)

func (Category) Self

func (c Category) Self() string

type CategoryCreate

type CategoryCreate struct {
	Name     string    `json:"name" gorm:"uniqueIndex:category_budget_name" example:"Saving" default:""`                        // Name of the category
	BudgetID uuid.UUID `json:"budgetId" gorm:"uniqueIndex:category_budget_name" example:"52d967d3-33f4-4b04-9ba7-772e5ab9d0ce"` // ID of the budget the category belongs to
	Note     string    `json:"note" example:"All envelopes for long-term saving" default:""`                                    // Notes about the category
	Archived bool      `json:"archived" example:"true" default:"false"`                                                         // Is the category archived?
}

type CategoryEnvelopes

type CategoryEnvelopes struct {
	Category
	Envelopes  []EnvelopeMonth `json:"envelopes"`                // Slice of all envelopes
	Balance    decimal.Decimal `json:"balance" example:"-10.13"` // Sum of the balances of the envelopes
	Allocation decimal.Decimal `json:"allocation" example:"90"`  // Sum of allocations for the envelopes
	Spent      decimal.Decimal `json:"spent" example:"100.13"`   // Sum spent for all envelopes
}

type DefaultModel

type DefaultModel struct {
	ID uuid.UUID `json:"id" example:"65392deb-5e92-4268-b114-297faad6cdce"` // UUID for the resource
	Timestamps
}

DefaultModel is the base model for most models in Envelope Zero. As EnvelopeMonth uses the Envelope ID and the Month as primary key, the timestamps are managed in the Timestamps struct.

func (*DefaultModel) AfterFind

func (m *DefaultModel) AfterFind(_ *gorm.DB) (err error)

AfterFind updates the timestamps to use UTC as timezone, not +0000. Yes, this is different.

We already store them in UTC, but somehow reading them from the database returns them as +0000.

func (*DefaultModel) BeforeCreate

func (m *DefaultModel) BeforeCreate(_ *gorm.DB) (err error)

BeforeCreate is set to generate a UUID for the resource.

type Envelope

type Envelope struct {
	DefaultModel
	EnvelopeCreate
	Category Category `json:"-"`
}

Envelope represents an envelope in your budget.

func (Envelope) Balance

func (e Envelope) Balance(db *gorm.DB, month types.Month) (decimal.Decimal, error)

Balance calculates the balance of an Envelope in a specific month.

func (*Envelope) BeforeSave

func (e *Envelope) BeforeSave(_ *gorm.DB) error

func (*Envelope) BeforeUpdate

func (e *Envelope) BeforeUpdate(tx *gorm.DB) (err error)

BeforeUpdate verifies the state of the envelope before committing an update to the database.

func (Envelope) Month

func (e Envelope) Month(db *gorm.DB, month types.Month) (EnvelopeMonth, error)

Month calculates the month specific values for an envelope and returns an EnvelopeMonth and allocation ID for them.

func (Envelope) Self

func (e Envelope) Self() string

func (Envelope) Spent

func (e Envelope) Spent(db *gorm.DB, month types.Month) decimal.Decimal

Spent returns the amount spent for the month the time.Time instance is in.

type EnvelopeCreate

type EnvelopeCreate struct {
	Name       string    `json:"name" gorm:"uniqueIndex:envelope_category_name" example:"Groceries" default:""`                       // Name of the envelope
	CategoryID uuid.UUID `json:"categoryId" gorm:"uniqueIndex:envelope_category_name" example:"878c831f-af99-4a71-b3ca-80deb7d793c1"` // ID of the category the envelope belongs to
	Note       string    `json:"note" example:"For stuff bought at supermarkets and drugstores" default:""`                           // Notes about the envelope
	Archived   bool      `json:"archived" example:"true" default:"false"`                                                             // Is the envelope archived?
}

type EnvelopeMonth

type EnvelopeMonth struct {
	Envelope
	Spent      decimal.Decimal    `json:"spent" example:"73.12"`      // The amount spent over the whole month
	Balance    decimal.Decimal    `json:"balance" example:"12.32"`    // The balance at the end of the monht
	Allocation decimal.Decimal    `json:"allocation" example:"85.44"` // The amount of money allocated
	Links      EnvelopeMonthLinks `json:"links"`                      // Linked resources
}

EnvelopeMonth contains data about an Envelope for a specific month.

type EnvelopeMonthLinks struct {
	Allocation string `json:"allocation" example:"https://example.com/api/v3/allocations/772d6956-ecba-485b-8a27-46a506c5a2a3"` // The allocations for this envelope for this month
}

type Goal

type Goal struct {
	DefaultModel
	Name       string `gorm:"uniqueIndex:goal_name_envelope"`
	Note       string
	Envelope   Envelope
	EnvelopeID uuid.UUID       `gorm:"uniqueIndex:goal_name_envelope"`
	Amount     decimal.Decimal `` // The target for the goal
	/* 130-byte string literal not displayed */
	Month    types.Month
	Archived bool
}

func (*Goal) AfterSave

func (g *Goal) AfterSave(_ *gorm.DB) error

func (*Goal) BeforeSave

func (g *Goal) BeforeSave(_ *gorm.DB) error

func (Goal) Self

func (g Goal) Self() string

type MatchRule

type MatchRule struct {
	DefaultModel
	MatchRuleCreate
}

func (MatchRule) Self

func (r MatchRule) Self() string

type MatchRuleCreate

type MatchRuleCreate struct {
	Priority  uint      `json:"priority" example:"3"`                                     // The priority of the match rule
	Match     string    `json:"match" example:"Bank*"`                                    // The matching applied to the opposite account. This is a glob pattern. Multiple globs are allowed. Globbing is case sensitive.
	AccountID uuid.UUID `json:"accountId" example:"f9e873c2-fb96-4367-bfb6-7ecd9bf4a6b5"` // The account to map matching transactions to
}

type Model

type Model interface {
	Self() string
}

type Month

type Month struct {
	ID         uuid.UUID           `json:"id" example:"1e777d24-3f5b-4c43-8000-04f65f895578"` // The ID of the Budget
	Name       string              `json:"name" example:"Zero budget"`                        // The name of the Budget
	Month      types.Month         `json:"month" example:"2006-05-01T00:00:00.000000Z"`       // The month
	Budgeted   decimal.Decimal     `json:"budgeted" example:"2100"`                           // The sum of all allocations for the month. **Deprecated, please use the `allocation` field**
	Income     decimal.Decimal     `json:"income" example:"2317.34"`                          // The total income for the month (sum of all incoming transactions without an Envelope)
	Available  decimal.Decimal     `json:"available" example:"217.34"`                        // The amount available to budget
	Balance    decimal.Decimal     `json:"balance" example:"5231.37"`                         // The sum of all envelope balances
	Spent      decimal.Decimal     `json:"spent" example:"133.70"`                            // The amount of money spent in this month
	Allocation decimal.Decimal     `json:"allocation" example:"1200.50"`                      // The sum of all allocations for this month
	Categories []CategoryEnvelopes `json:"categories"`                                        // A list of envelope month calculations grouped by category
}

type MonthConfig

type MonthConfig struct {
	Timestamps
	MonthConfigCreate
	EnvelopeID uuid.UUID   `json:"envelopeId" gorm:"primaryKey" example:"10b9705d-3356-459e-9d5a-28d42a6c4547"` // ID of the envelope
	Month      types.Month `json:"month" gorm:"primaryKey" example:"1969-06-01T00:00:00.000000Z"`               // The month. This is always set to 00:00 UTC on the first of the month.
}

func (*MonthConfig) BeforeSave

func (m *MonthConfig) BeforeSave(_ *gorm.DB) error

func (MonthConfig) Self

func (m MonthConfig) Self() string

type MonthConfigCreate

type MonthConfigCreate struct {
	Allocation decimal.Decimal `` // The maximum value is "999999999999.99999999", swagger unfortunately rounds this.
	/* 136-byte string literal not displayed */
	Note string `json:"note" example:"Added 200€ here because we replaced Tim's expensive vase" default:""` // A note for the month config
}

type Timestamps

type Timestamps struct {
	CreatedAt time.Time       `json:"createdAt" example:"2022-04-02T19:28:44.491514Z"`                                             // Time the resource was created
	UpdatedAt time.Time       `json:"updatedAt" example:"2022-04-17T20:14:01.048145Z"`                                             // Last time the resource was updated
	DeletedAt *gorm.DeletedAt `json:"deletedAt" gorm:"index" example:"2022-04-22T21:01:05.058161Z" swaggertype:"primitive,string"` // Time the resource was marked as deleted
}

Timestamps only contains the timestamps that gorm sets automatically to enable other primary keys than ID.

type Transaction

type Transaction struct {
	DefaultModel
	TransactionCreate
	Budget             Budget   `json:"-"`
	SourceAccount      Account  `json:"-"`
	DestinationAccount Account  `json:"-"`
	Envelope           Envelope `json:"-"`
}

Transaction represents a transaction between two accounts.

func (*Transaction) AfterFind

func (t *Transaction) AfterFind(tx *gorm.DB) (err error)

AfterFind updates the timestamps to use UTC as timezone, not +0000. Yes, this is different.

We already store them in UTC, but somehow reading them from the database returns them as +0000.

func (*Transaction) BeforeSave

func (t *Transaction) BeforeSave(tx *gorm.DB) (err error)

BeforeSave

  • sets the timezone for the Date for UTC
  • ensures that ReconciledSource and ReconciledDestination are set to valid values
  • trims whitespace from string fields

func (Transaction) Self

func (t Transaction) Self() string

type TransactionCreate

type TransactionCreate struct {
	Date time.Time `json:"date" example:"1815-12-10T18:43:00.271152Z"` // Date of the transaction. Time is currently only used for sorting
	// The maximum value is "999999999999.99999999", swagger unfortunately rounds this.
	Amount decimal.Decimal `` // The amount for the transaction
	/* 132-byte string literal not displayed */
	Note            string    `json:"note" example:"Lunch" default:""`                         // A note
	BudgetID        uuid.UUID `json:"budgetId" example:"55eecbd8-7c46-4b06-ada9-f287802fb05e"` // ID of the budget
	SourceAccountID uuid.UUID ``                                                               // ID of the source account
	/* 155-byte string literal not displayed */
	DestinationAccountID  uuid.UUID  `json:"destinationAccountId" example:"8e16b456-a719-48ce-9fec-e115cfa7cbcc"` // ID of the destination account
	EnvelopeID            *uuid.UUID `json:"envelopeId" example:"2649c965-7999-4873-ae16-89d5d5fa972e"`           // ID of the envelope
	ReconciledSource      bool       `json:"reconciledSource" example:"true" default:"false"`                     // Is the transaction reconciled in the source account?
	ReconciledDestination bool       `json:"reconciledDestination" example:"true" default:"false"`                // Is the transaction reconciled in the destination account?

	AvailableFrom types.Month `json:"availableFrom" example:"2021-11-17T00:00:00Z"` // The date from which on the transaction amount is available for budgeting. Only used for income transactions. Defaults to the transaction date.

	ImportHash string `json:"importHash" example:"867e3a26dc0baf73f4bff506f31a97f6c32088917e9e5cf1a5ed6f3f84a6fa70" default:""` // The SHA256 hash of a unique combination of values to use in duplicate detection
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL