models

package
v3.3.2 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2023 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")

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) (err error)

BeforeSave sets OnBudget to false when External is true.

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:"-"`
	Links    struct {
		Self string `json:"self" example:"https://example.com/api/v1/allocations/902cd93c-3724-4e46-8540-d014131282fc"` // The allocation itself
	} `json:"links" gorm:"-"`
}

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

func (*Allocation) AfterFind

func (a *Allocation) AfterFind(tx *gorm.DB) (err error)

func (*Allocation) AfterSave

func (a *Allocation) AfterSave(tx *gorm.DB) (err error)

AfterSave also sets the links so that we do not need to query the resource directly after creating or updating it.

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
	Balance decimal.Decimal `json:"balance" gorm:"-" example:"3423.42"` // DEPRECATED. Will be removed in API v2, see https://github.com/envelope-zero/backend/issues/526.
	Links   struct {
		Self             string `json:"self" example:"https://example.com/api/v1/budgets/550dc009-cea6-4c12-b2a5-03446eb7b7cf"`                                 // The budget itself
		Accounts         string `json:"accounts" example:"https://example.com/api/v1/accounts?budget=550dc009-cea6-4c12-b2a5-03446eb7b7cf"`                     // Accounts for this budget
		Categories       string `json:"categories" example:"https://example.com/api/v1/categories?budget=550dc009-cea6-4c12-b2a5-03446eb7b7cf"`                 // Categories for this budget
		Envelopes        string `json:"envelopes" example:"https://example.com/api/v1/envelopes?budget=550dc009-cea6-4c12-b2a5-03446eb7b7cf"`                   // Envelopes for this budget
		Transactions     string `json:"transactions" example:"https://example.com/api/v1/transactions?budget=550dc009-cea6-4c12-b2a5-03446eb7b7cf"`             // Transactions for this budget
		Month            string `json:"month" example:"https://example.com/api/v1/budgets/550dc009-cea6-4c12-b2a5-03446eb7b7cf/YYYY-MM"`                        // This uses 'YYYY-MM' for clients to replace with the actual year and month.
		GroupedMonth     string `json:"groupedMonth" example:"https://example.com/api/v1/months?budget=550dc009-cea6-4c12-b2a5-03446eb7b7cf&month=YYYY-MM"`     // This uses 'YYYY-MM' for clients to replace with the actual year and month.
		MonthAllocations string `json:"monthAllocations" example:"https://example.com/api/v1/months?budget=550dc009-cea6-4c12-b2a5-03446eb7b7cf&month=YYYY-MM"` // This uses 'YYYY-MM' for clients to replace with the actual year and month.
	} `json:"links" gorm:"-"`
}

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

func (b *Budget) AfterFind(tx *gorm.DB) (err error)

func (*Budget) AfterSave

func (b *Budget) AfterSave(tx *gorm.DB) (err error)

AfterSave does the same as AfterFind, so we just call it.

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) 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:"-"`                  // The budget the category belongs to
	Envelopes []Envelope `json:"envelopes" gorm:"-"` // Envelopes for the category
	Links     struct {
		Self      string `json:"self" example:"https://example.com/api/v1/categories/3b1ea324-d438-4419-882a-2fc91d71772f"`              // The category itself
		Envelopes string `json:"envelopes" example:"https://example.com/api/v1/envelopes?category=3b1ea324-d438-4419-882a-2fc91d71772f"` // Envelopes for this category
	} `json:"links" gorm:"-"`
}

Category represents a category of envelopes.

func (*Category) AfterFind

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

func (*Category) AfterSave

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

AfterSave also sets the links so that we do not need to query the resource directly after creating or updating it.

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

func (c Category) Self() string

func (*Category) SetEnvelopes added in v3.1.1

func (c *Category) SetEnvelopes(tx *gorm.DB) error

SetEnvelopes sets the Envelope field to the envelopes of the category.

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:"-"`
	Links    struct {
		Self         string `json:"self" example:"https://example.com/api/v1/envelopes/45b6b5b9-f746-4ae9-b77b-7688b91f8166"`                     // The envelope itself
		Allocations  string `json:"allocations" example:"https://example.com/api/v1/allocations?envelope=45b6b5b9-f746-4ae9-b77b-7688b91f8166"`   // the envelope's allocations
		Month        string `json:"month" example:"https://example.com/api/v1/envelopes/45b6b5b9-f746-4ae9-b77b-7688b91f8166/YYYY-MM"`            // Month information endpoint. This will always end in 'YYYY-MM' for clients to use replace with actual numbers.
		Transactions string `json:"transactions" example:"https://example.com/api/v1/transactions?envelope=45b6b5b9-f746-4ae9-b77b-7688b91f8166"` // The envelope's transactions
	} `json:"links" gorm:"-"` // Links to related resources
}

Envelope represents an envelope in your budget.

func (*Envelope) AfterFind

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

func (*Envelope) AfterSave

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

AfterSave also sets the links so that we do not need to query the resource directly after creating or updating it.

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) 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 MatchRule added in v3.1.2

type MatchRule struct {
	DefaultModel
	MatchRuleCreate
	Links struct {
		Self string `json:"self" example:"https://example.com/api/v2/match-rules/95685c82-53c6-455d-b235-f49960b73b21"` // The match rule itself
	} `json:"links" gorm:"-"`
}

func (*MatchRule) AfterFind added in v3.1.2

func (r *MatchRule) AfterFind(tx *gorm.DB) (err error)

func (*MatchRule) AfterSave added in v3.1.2

func (r *MatchRule) AfterSave(tx *gorm.DB) (err error)

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.
	Links      struct {
		Self     string `json:"self" example:"https://example.com/api/v1/month-configs/61027ebb-ab75-4a49-9e23-a104ddd9ba6b/2017-10"` // The month config itself
		Envelope string `json:"envelope" example:"https://example.com/api/v1/envelopes/61027ebb-ab75-4a49-9e23-a104ddd9ba6b"`         // The envelope this config belongs to
	} `json:"links" gorm:"-"`
}

func (*MonthConfig) AfterFind

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

func (*MonthConfig) AfterSave

func (m *MonthConfig) AfterSave(tx *gorm.DB) (err error)

AfterSave also sets the links so that we do not need to query the resource directly after creating or updating it.

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

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.
	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