models

package
v3.22.2 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: 10 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:"-"`
	Archived bool   `json:"archived" example:"true" default:"false" gorm:"-"` // Is the account archived?
}

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

func (*Account) AfterFind

func (a *Account) AfterFind(_ *gorm.DB) (err error)

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 added in v3.0.1

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
	Hidden             bool            `json:"hidden" 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 Allocation

type Allocation struct {
	DefaultModel
	AllocationCreate
	Envelope Envelope `json:"-"`
}

Allocation represents the allocation of money to an Envelope for a specific month.

func (*Allocation) BeforeSave

func (a *Allocation) BeforeSave(_ *gorm.DB) (err error)

BeforeSave verifies that the amount is non-zero. To remove an allocation, it has to be deleted instead of set to 0.

func (Allocation) Self

func (a Allocation) Self() string

type AllocationCreate

type AllocationCreate struct {
	Month  types.Month     `json:"month" gorm:"uniqueIndex:allocation_month_envelope" example:"2021-12-01T00:00:00.000000Z"` // Only year and month of this timestamp are used, everything else is ignored. This will always be set to 00:00 UTC on the first of the specified month
	Amount decimal.Decimal ``                                                                                                // The maximum value is "999999999999.99999999", swagger unfortunately rounds this.
	/* 132-byte string literal not displayed */
	EnvelopeID uuid.UUID `json:"envelopeId" gorm:"uniqueIndex:allocation_month_envelope" example:"a0909e84-e8f9-4cb6-82a5-025dff105ff2"` // ID of the envelope
}

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 added in v3.20.0

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) Month

func (b Budget) Month(db *gorm.DB, month types.Month) (Month, error)

Month calculates the month overview for this 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:"-"`
	Archived bool   `json:"archived" example:"true" default:"false" gorm:"-"` // Is the Category archived?
}

Category represents a category of envelopes.

func (*Category) AfterFind

func (c *Category) AfterFind(_ *gorm.DB) (err error)

func (*Category) BeforeSave added in v3.20.0

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

func (*Category) BeforeUpdate added in v3.1.0

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

BeforeUpdate archives all envelopes when the category is archived.

func (*Category) Envelopes added in v3.1.1

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
	Hidden   bool      `json:"hidden" example:"true" default:"false"`                                                           // Is the category hidden?
}

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:"-"`
	Archived bool     `json:"archived" example:"true" default:"false" gorm:"-"` // Is the Envelope archived?
}

Envelope represents an envelope in your budget.

func (*Envelope) AfterFind

func (e *Envelope) AfterFind(_ *gorm.DB) (err error)

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 added in v3.20.0

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, uuid.UUID, 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
	Hidden     bool      `json:"hidden" example:"true" default:"false"`                                                               // Is the envelope hidden?
}

type EnvelopeMonth

type EnvelopeMonth struct {
	Envelope
	Month      types.Month        `json:"month" example:"1969-06-01T00:00:00.000000Z" hidden:"deprecated"` // This is always set to 00:00 UTC on the first of the month. **This field is deprecated and will be removed in v2**
	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/v1/allocations/772d6956-ecba-485b-8a27-46a506c5a2a3"` // The allocations for this envelope for this month
}

type Goal added in v3.21.0

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 added in v3.21.0

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

func (*Goal) BeforeSave added in v3.21.0

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

func (Goal) Self added in v3.21.0

func (g Goal) Self() string

type MatchRule added in v3.1.2

type MatchRule struct {
	DefaultModel
	MatchRuleCreate
}

func (MatchRule) Self added in v3.1.2

func (r MatchRule) Self() string

type MatchRuleCreate added in v3.1.2

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.
	Allocation decimal.Decimal `json:"allocation" gorm:"-" example:"22.01" minimum:"0.00000001" maximum:"999999999999.99999999" multipleOf:"0.00000001"` // The maximum value is "999999999999.99999999", swagger unfortunately rounds this.
}

func (*MonthConfig) AfterFind

func (m *MonthConfig) AfterFind(tx *gorm.DB) error

func (*MonthConfig) BeforeSave added in v3.20.0

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

func (MonthConfig) Self added in v3.1.1

func (m MonthConfig) Self() string

type MonthConfigCreate

type MonthConfigCreate struct {
	OverspendMode OverspendMode `json:"overspendMode" example:"AFFECT_ENVELOPE" default:"AFFECT_AVAILABLE"`                 // The overspend handling mode to use. Deprecated, will be removed with 4.0.0 release and is not used in API v3 anymore
	Note          string        `json:"note" example:"Added 200€ here because we replaced Tim's expensive vase" default:""` // A note for the month config
}

type OverspendMode

type OverspendMode string

swagger:enum OverspendMode

const (
	AffectAvailable OverspendMode = "AFFECT_AVAILABLE"
	AffectEnvelope  OverspendMode = "AFFECT_ENVELOPE"
)

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
	Reconciled            bool       `json:"reconciled" example:"true" default:"false"`                           // DEPRECATED. Do not use, this field does not work as intended. See https://github.com/envelope-zero/backend/issues/528. Use reconciledSource and reconciledDestination instead. This field will be removed in 4.0.0
	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