desktop/backend/types/account.go
package types
import (
"context"
"database/sql"
"math/big"
"pennyapp/backend/internal/dberror"
"pennyapp/backend/model"
"strings"
"github.com/shopspring/decimal"
"github.com/volatiletech/sqlboiler/v4/queries/qm"
)
type AccountResponse struct {
Success bool `json:"success"`
Msg string `json:"msg"`
Data Account `json:"data"`
}
type Account struct {
ID int64 `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
AccountType AccountType `json:"account_type"`
Amount string `json:"amount"`
Deleted bool `json:"deleted"`
}
type AccountType struct {
ID int64 `json:"id"`
Name string `json:"name"`
*ParentAccountType `json:"parent_account_type"`
}
type ParentAccountType struct {
ID int64 `json:"id"`
Name string `json:"name"`
}
func NewAccountResponse() AccountResponse {
a := AccountResponse{
Success: false,
Msg: "default",
Data: Account{},
}
return a
}
func NewAccount(ctx context.Context, db *sql.DB, a *model.Account) (Account, error) {
var err error
account := Account{
ID: a.ID,
Name: a.Name,
}
if a.R != nil && a.R.AccountType != nil {
account.AccountType = AccountType{
ID: a.R.AccountType.ID,
Name: a.R.AccountType.Name,
}
}
if err = account.setAmount(ctx, db, a); err != nil {
return account, err
}
if err = account.setDeleted(ctx, db, a); err != nil {
return account, err
}
if err = account.setDescription(ctx, db, a); err != nil {
return account, err
}
return account, err
}
func (a *Account) setAmount(ctx context.Context, db *sql.DB, account *model.Account) error {
splits, err := model.Splits(qm.Where("account_id=?", account.ID)).All(ctx, db)
if err != nil {
return err
}
accountType, err := model.AccountTypes(qm.Where("id=?", account.AccountTypeID)).One(ctx, db)
if err != nil {
return err
}
amount := float64(0)
for _, split := range splits {
transactionDeleted, err := isTransactionDeleted(ctx, db, split.TransactionsID)
if err != nil {
return err
}
if transactionDeleted {
continue
}
r := big.NewRat(split.ValueNum, split.ValueDenom)
f, _ := r.Float64()
switch strings.ToLower(accountType.Name) {
case "liability", "income":
f = -f
}
amount = amount + f
}
a.Amount = decimal.NewFromFloat(amount).StringFixed(2)
return nil
}
func (a *Account) setDeleted(ctx context.Context, db *sql.DB, account *model.Account) error {
accountAttribute, err := model.AccountAttributes(qm.Where("account_id=? AND name=?", account.ID, "deleted")).One(ctx, db)
switch {
case dberror.IsNoRowsFound(err):
case err != nil:
return err
default:
if accountAttribute.Value == "true" {
a.Deleted = true
}
}
return nil
}
func (a *Account) setDescription(ctx context.Context, db *sql.DB, account *model.Account) error {
accountAttribute, err := model.AccountAttributes(qm.Where("account_id=? AND name=?", account.ID, "description")).One(ctx, db)
switch {
case dberror.IsNoRowsFound(err):
case err != nil:
return err
default:
a.Description = accountAttribute.Value
}
return nil
}