Fix multiple linter errors
This commit is contained in:
parent
e08a21b750
commit
3cb39d978a
@ -45,7 +45,7 @@ func (n Numeric) IsZero() bool {
|
|||||||
|
|
||||||
func (n Numeric) MatchExp(exp int32) Numeric {
|
func (n Numeric) MatchExp(exp int32) Numeric {
|
||||||
diffExp := n.Exp - exp
|
diffExp := n.Exp - exp
|
||||||
factor := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(int64(diffExp)), nil)
|
factor := big.NewInt(0).Exp(big.NewInt(10), big.NewInt(int64(diffExp)), nil) //nolint:gomnd
|
||||||
return Numeric{pgtype.Numeric{
|
return Numeric{pgtype.Numeric{
|
||||||
Exp: exp,
|
Exp: exp,
|
||||||
Int: big.NewInt(0).Mul(n.Int, factor),
|
Int: big.NewInt(0).Mul(n.Int, factor),
|
||||||
|
@ -116,8 +116,7 @@ type Transfer struct {
|
|||||||
ToAccount string
|
ToAccount string
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportTransactions expects a TSV-file as exported by YNAB in the following format:
|
// ImportTransactions expects a TSV-file as exported by YNAB.
|
||||||
|
|
||||||
func (ynab *YNABImport) ImportTransactions(context context.Context, r io.Reader) error {
|
func (ynab *YNABImport) ImportTransactions(context context.Context, r io.Reader) error {
|
||||||
csv := csv.NewReader(r)
|
csv := csv.NewReader(r)
|
||||||
csv.Comma = '\t'
|
csv.Comma = '\t'
|
||||||
@ -132,60 +131,18 @@ func (ynab *YNABImport) ImportTransactions(context context.Context, r io.Reader)
|
|||||||
|
|
||||||
count := 0
|
count := 0
|
||||||
for _, record := range csvData[1:] {
|
for _, record := range csvData[1:] {
|
||||||
accountName := record[0]
|
transaction, err := ynab.GetTransaction(context, record)
|
||||||
account, err := ynab.GetAccount(context, accountName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get account %s: %w", accountName, err)
|
return err
|
||||||
}
|
|
||||||
|
|
||||||
// flag := record[1]
|
|
||||||
|
|
||||||
dateString := record[2]
|
|
||||||
date, err := time.Parse("02.01.2006", dateString)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("parse date %s: %w", dateString, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
categoryGroup, categoryName := record[5], record[6] // also in 4 joined by :
|
|
||||||
category, err := ynab.GetCategory(context, categoryGroup, categoryName)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("get category %s/%s: %w", categoryGroup, categoryName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
memo := record[7]
|
|
||||||
|
|
||||||
outflow := record[8]
|
|
||||||
inflow := record[9]
|
|
||||||
amount, err := GetAmount(inflow, outflow)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("parse amount from (%s/%s): %w", inflow, outflow, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
statusEnum := TransactionStatusUncleared
|
|
||||||
status := record[10]
|
|
||||||
switch status {
|
|
||||||
case "Cleared":
|
|
||||||
statusEnum = TransactionStatusCleared
|
|
||||||
case "Reconciled":
|
|
||||||
statusEnum = TransactionStatusReconciled
|
|
||||||
case "Uncleared":
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction := CreateTransactionParams{
|
|
||||||
Date: date,
|
|
||||||
Memo: memo,
|
|
||||||
AccountID: account.ID,
|
|
||||||
CategoryID: category,
|
|
||||||
Amount: amount,
|
|
||||||
Status: statusEnum,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
payeeName := record[3]
|
payeeName := record[3]
|
||||||
// Transaction is a transfer
|
// Transaction is a transfer
|
||||||
if strings.HasPrefix(payeeName, "Transfer : ") {
|
if strings.HasPrefix(payeeName, "Transfer : ") {
|
||||||
err = ynab.ImportTransferTransaction(payeeName, context, transaction, accountName, &openTransfers, account, amount)
|
err = ynab.ImportTransferTransaction(context, payeeName, transaction.CreateTransactionParams,
|
||||||
|
&openTransfers, transaction.Account, transaction.Amount)
|
||||||
} else {
|
} else {
|
||||||
err = ynab.ImportRegularTransaction(context, payeeName, transaction)
|
err = ynab.ImportRegularTransaction(context, payeeName, transaction.CreateTransactionParams)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -208,7 +165,66 @@ func (ynab *YNABImport) ImportTransactions(context context.Context, r io.Reader)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ynab *YNABImport) ImportRegularTransaction(context context.Context, payeeName string, transaction CreateTransactionParams) error {
|
type NewTransaction struct {
|
||||||
|
CreateTransactionParams
|
||||||
|
Account *Account
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ynab *YNABImport) GetTransaction(context context.Context, record []string) (NewTransaction, error) {
|
||||||
|
accountName := record[0]
|
||||||
|
account, err := ynab.GetAccount(context, accountName)
|
||||||
|
if err != nil {
|
||||||
|
return NewTransaction{}, fmt.Errorf("get account %s: %w", accountName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// flag := record[1]
|
||||||
|
|
||||||
|
dateString := record[2]
|
||||||
|
date, err := time.Parse("02.01.2006", dateString)
|
||||||
|
if err != nil {
|
||||||
|
return NewTransaction{}, fmt.Errorf("parse date %s: %w", dateString, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
categoryGroup, categoryName := record[5], record[6] // also in 4 joined by :
|
||||||
|
category, err := ynab.GetCategory(context, categoryGroup, categoryName)
|
||||||
|
if err != nil {
|
||||||
|
return NewTransaction{}, fmt.Errorf("get category %s/%s: %w", categoryGroup, categoryName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
memo := record[7]
|
||||||
|
|
||||||
|
outflow := record[8]
|
||||||
|
inflow := record[9]
|
||||||
|
amount, err := GetAmount(inflow, outflow)
|
||||||
|
if err != nil {
|
||||||
|
return NewTransaction{}, fmt.Errorf("parse amount from (%s/%s): %w", inflow, outflow, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
statusEnum := TransactionStatusUncleared
|
||||||
|
status := record[10]
|
||||||
|
switch status {
|
||||||
|
case "Cleared":
|
||||||
|
statusEnum = TransactionStatusCleared
|
||||||
|
case "Reconciled":
|
||||||
|
statusEnum = TransactionStatusReconciled
|
||||||
|
case "Uncleared":
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewTransaction{
|
||||||
|
CreateTransactionParams: CreateTransactionParams{
|
||||||
|
Date: date,
|
||||||
|
Memo: memo,
|
||||||
|
AccountID: account.ID,
|
||||||
|
CategoryID: category,
|
||||||
|
Amount: amount,
|
||||||
|
Status: statusEnum,
|
||||||
|
},
|
||||||
|
Account: account,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ynab *YNABImport) ImportRegularTransaction(context context.Context, payeeName string,
|
||||||
|
transaction CreateTransactionParams) error {
|
||||||
payeeID, err := ynab.GetPayee(context, payeeName)
|
payeeID, err := ynab.GetPayee(context, payeeName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get payee %s: %w", payeeName, err)
|
return fmt.Errorf("get payee %s: %w", payeeName, err)
|
||||||
@ -222,7 +238,9 @@ func (ynab *YNABImport) ImportRegularTransaction(context context.Context, payeeN
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ynab *YNABImport) ImportTransferTransaction(payeeName string, context context.Context, transaction CreateTransactionParams, accountName string, openTransfers *[]Transfer, account *Account, amount Numeric) error {
|
func (ynab *YNABImport) ImportTransferTransaction(context context.Context, payeeName string,
|
||||||
|
transaction CreateTransactionParams, openTransfers *[]Transfer,
|
||||||
|
account *Account, amount Numeric) error {
|
||||||
transferToAccountName := payeeName[11:]
|
transferToAccountName := payeeName[11:]
|
||||||
transferToAccount, err := ynab.GetAccount(context, transferToAccountName)
|
transferToAccount, err := ynab.GetAccount(context, transferToAccountName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -232,7 +250,7 @@ func (ynab *YNABImport) ImportTransferTransaction(payeeName string, context cont
|
|||||||
transfer := Transfer{
|
transfer := Transfer{
|
||||||
transaction,
|
transaction,
|
||||||
transferToAccount,
|
transferToAccount,
|
||||||
accountName,
|
account.Name,
|
||||||
transferToAccountName,
|
transferToAccountName,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +360,7 @@ func (ynab *YNABImport) GetPayee(context context.Context, name string) (uuid.Nul
|
|||||||
return uuid.NullUUID{UUID: payee.ID, Valid: true}, nil
|
return uuid.NullUUID{UUID: payee.ID, Valid: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ynab *YNABImport) GetCategory(context context.Context, group string, name string) (uuid.NullUUID, error) {
|
func (ynab *YNABImport) GetCategory(context context.Context, group string, name string) (uuid.NullUUID, error) { //nolint
|
||||||
if group == "" || name == "" {
|
if group == "" || name == "" {
|
||||||
return uuid.NullUUID{}, nil
|
return uuid.NullUUID{}, nil
|
||||||
}
|
}
|
||||||
@ -353,21 +371,21 @@ func (ynab *YNABImport) GetCategory(context context.Context, group string, name
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var categoryGroup *CategoryGroup
|
var categoryGroup CategoryGroup
|
||||||
for _, existingGroup := range ynab.categoryGroups {
|
for _, existingGroup := range ynab.categoryGroups {
|
||||||
if existingGroup.Name == group {
|
if existingGroup.Name == group {
|
||||||
categoryGroup = &existingGroup
|
categoryGroup = existingGroup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if categoryGroup == nil {
|
if categoryGroup.Name == "" {
|
||||||
newGroup := CreateCategoryGroupParams{Name: group, BudgetID: ynab.budgetID}
|
newGroup := CreateCategoryGroupParams{Name: group, BudgetID: ynab.budgetID}
|
||||||
newCategoryGroup, err := ynab.queries.CreateCategoryGroup(context, newGroup)
|
var err error
|
||||||
|
categoryGroup, err = ynab.queries.CreateCategoryGroup(context, newGroup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return uuid.NullUUID{}, err
|
return uuid.NullUUID{}, err
|
||||||
}
|
}
|
||||||
ynab.categoryGroups = append(ynab.categoryGroups, newCategoryGroup)
|
ynab.categoryGroups = append(ynab.categoryGroups, categoryGroup)
|
||||||
categoryGroup = &newCategoryGroup
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newCategory := CreateCategoryParams{Name: name, CategoryGroupID: categoryGroup.ID}
|
newCategory := CreateCategoryParams{Name: name, CategoryGroupID: categoryGroup.ID}
|
||||||
|
@ -91,6 +91,18 @@ func (h *Handler) budgetingForMonth(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
availableBalance := h.getAvailableBalance(categories, budget, moneyUsed, cumultativeBalances, firstOfNextMonth)
|
||||||
|
|
||||||
|
data := struct {
|
||||||
|
Categories []CategoryWithBalance
|
||||||
|
AvailableBalance postgres.Numeric
|
||||||
|
}{categoriesWithBalance, availableBalance}
|
||||||
|
c.JSON(http.StatusOK, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Handler) getAvailableBalance(categories []postgres.GetCategoriesRow, budget postgres.Budget,
|
||||||
|
moneyUsed postgres.Numeric, cumultativeBalances []postgres.GetCumultativeBalancesRow,
|
||||||
|
firstOfNextMonth time.Time) postgres.Numeric {
|
||||||
availableBalance := postgres.NewZeroNumeric()
|
availableBalance := postgres.NewZeroNumeric()
|
||||||
for _, cat := range categories {
|
for _, cat := range categories {
|
||||||
if cat.ID != budget.IncomeCategoryID {
|
if cat.ID != budget.IncomeCategoryID {
|
||||||
@ -110,12 +122,7 @@ func (h *Handler) budgetingForMonth(c *gin.Context) {
|
|||||||
availableBalance = availableBalance.Add(bal.Transactions)
|
availableBalance = availableBalance.Add(bal.Transactions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return availableBalance
|
||||||
data := struct {
|
|
||||||
Categories []CategoryWithBalance
|
|
||||||
AvailableBalance postgres.Numeric
|
|
||||||
}{categoriesWithBalance, availableBalance}
|
|
||||||
c.JSON(http.StatusOK, data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) budgeting(c *gin.Context) {
|
func (h *Handler) budgeting(c *gin.Context) {
|
||||||
@ -146,7 +153,9 @@ func (h *Handler) budgeting(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, data)
|
c.JSON(http.StatusOK, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) calculateBalances(c *gin.Context, budget postgres.Budget, firstOfNextMonth time.Time, firstOfMonth time.Time, categories []postgres.GetCategoriesRow, cumultativeBalances []postgres.GetCumultativeBalancesRow) ([]CategoryWithBalance, postgres.Numeric, error) {
|
func (h *Handler) calculateBalances(c *gin.Context, budget postgres.Budget,
|
||||||
|
firstOfNextMonth time.Time, firstOfMonth time.Time, categories []postgres.GetCategoriesRow,
|
||||||
|
cumultativeBalances []postgres.GetCumultativeBalancesRow) ([]CategoryWithBalance, postgres.Numeric, error) {
|
||||||
categoriesWithBalance := []CategoryWithBalance{}
|
categoriesWithBalance := []CategoryWithBalance{}
|
||||||
hiddenCategory := CategoryWithBalance{
|
hiddenCategory := CategoryWithBalance{
|
||||||
GetCategoriesRow: &postgres.GetCategoriesRow{
|
GetCategoriesRow: &postgres.GetCategoriesRow{
|
||||||
@ -162,39 +171,9 @@ func (h *Handler) calculateBalances(c *gin.Context, budget postgres.Budget, firs
|
|||||||
moneyUsed := postgres.NewZeroNumeric()
|
moneyUsed := postgres.NewZeroNumeric()
|
||||||
for i := range categories {
|
for i := range categories {
|
||||||
cat := &categories[i]
|
cat := &categories[i]
|
||||||
categoryWithBalance := CategoryWithBalance{
|
|
||||||
GetCategoriesRow: cat,
|
|
||||||
Available: postgres.NewZeroNumeric(),
|
|
||||||
AvailableLastMonth: postgres.NewZeroNumeric(),
|
|
||||||
Activity: postgres.NewZeroNumeric(),
|
|
||||||
Assigned: postgres.NewZeroNumeric(),
|
|
||||||
}
|
|
||||||
for _, bal := range cumultativeBalances {
|
|
||||||
if bal.CategoryID != cat.ID {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bal.Date.Before(firstOfNextMonth) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
moneyUsed = moneyUsed.Sub(bal.Assignments)
|
|
||||||
categoryWithBalance.Available = categoryWithBalance.Available.Add(bal.Assignments)
|
|
||||||
categoryWithBalance.Available = categoryWithBalance.Available.Add(bal.Transactions)
|
|
||||||
if !categoryWithBalance.Available.IsPositive() && bal.Date.Before(firstOfMonth) {
|
|
||||||
moneyUsed = moneyUsed.Add(categoryWithBalance.Available)
|
|
||||||
categoryWithBalance.Available = postgres.NewZeroNumeric()
|
|
||||||
}
|
|
||||||
|
|
||||||
if bal.Date.Before(firstOfMonth) {
|
|
||||||
categoryWithBalance.AvailableLastMonth = categoryWithBalance.Available
|
|
||||||
} else if bal.Date.Before(firstOfNextMonth) {
|
|
||||||
categoryWithBalance.Activity = bal.Transactions
|
|
||||||
categoryWithBalance.Assigned = bal.Assignments
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// do not show hidden categories
|
// do not show hidden categories
|
||||||
|
categoryWithBalance := h.CalculateCategoryBalances(cat, cumultativeBalances,
|
||||||
|
firstOfNextMonth, &moneyUsed, firstOfMonth, hiddenCategory, budget)
|
||||||
if cat.Group == "Hidden Categories" {
|
if cat.Group == "Hidden Categories" {
|
||||||
hiddenCategory.Available = hiddenCategory.Available.Add(categoryWithBalance.Available)
|
hiddenCategory.Available = hiddenCategory.Available.Add(categoryWithBalance.Available)
|
||||||
hiddenCategory.AvailableLastMonth = hiddenCategory.AvailableLastMonth.Add(categoryWithBalance.AvailableLastMonth)
|
hiddenCategory.AvailableLastMonth = hiddenCategory.AvailableLastMonth.Add(categoryWithBalance.AvailableLastMonth)
|
||||||
@ -214,3 +193,39 @@ func (h *Handler) calculateBalances(c *gin.Context, budget postgres.Budget, firs
|
|||||||
|
|
||||||
return categoriesWithBalance, moneyUsed, nil
|
return categoriesWithBalance, moneyUsed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (*Handler) CalculateCategoryBalances(cat *postgres.GetCategoriesRow, cumultativeBalances []postgres.GetCumultativeBalancesRow, firstOfNextMonth time.Time, moneyUsed *postgres.Numeric, firstOfMonth time.Time, hiddenCategory CategoryWithBalance, budget postgres.Budget) CategoryWithBalance {
|
||||||
|
categoryWithBalance := CategoryWithBalance{
|
||||||
|
GetCategoriesRow: cat,
|
||||||
|
Available: postgres.NewZeroNumeric(),
|
||||||
|
AvailableLastMonth: postgres.NewZeroNumeric(),
|
||||||
|
Activity: postgres.NewZeroNumeric(),
|
||||||
|
Assigned: postgres.NewZeroNumeric(),
|
||||||
|
}
|
||||||
|
for _, bal := range cumultativeBalances {
|
||||||
|
if bal.CategoryID != cat.ID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bal.Date.Before(firstOfNextMonth) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
*moneyUsed = moneyUsed.Sub(bal.Assignments)
|
||||||
|
categoryWithBalance.Available = categoryWithBalance.Available.Add(bal.Assignments)
|
||||||
|
categoryWithBalance.Available = categoryWithBalance.Available.Add(bal.Transactions)
|
||||||
|
if !categoryWithBalance.Available.IsPositive() && bal.Date.Before(firstOfMonth) {
|
||||||
|
*moneyUsed = moneyUsed.Add(categoryWithBalance.Available)
|
||||||
|
categoryWithBalance.Available = postgres.NewZeroNumeric()
|
||||||
|
}
|
||||||
|
|
||||||
|
if bal.Date.Before(firstOfMonth) {
|
||||||
|
categoryWithBalance.AvailableLastMonth = categoryWithBalance.Available
|
||||||
|
} else if bal.Date.Before(firstOfNextMonth) {
|
||||||
|
categoryWithBalance.Activity = bal.Transactions
|
||||||
|
categoryWithBalance.Assigned = bal.Assignments
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return categoryWithBalance
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user