diff --git a/pkg/api/routes.go b/pkg/api/routes.go index c27c3ed..5d7eec7 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -30,6 +30,9 @@ func Routes(s *gin.Engine, db *pg.DB) { subscriptionService := services.SubscriptionService{Db: db} subscriptionTypeService := services.SubscriptionTypeService{Db: db} + walletService.Ss = &subscriptionService + transactionService.Ss = &subscriptionService + controllers.NewApiController(&apiService, api) controllers.NewAuthController(&usersService, auth) controllers.NewWalletsController(&walletService, wallet) diff --git a/pkg/models/subscriptions.go b/pkg/models/subscriptions.go index 016afde..00f3a70 100644 --- a/pkg/models/subscriptions.go +++ b/pkg/models/subscriptions.go @@ -20,7 +20,7 @@ type Subscription struct { TransactionTypeID string `json:"transactionTypeId", pg:"transaction_type_id"` TransactionType *TransactionType `json:"transactionType", pg:"rel:has-one, fk:transaction_type_id"` LastTransactionDate time.Time `json:"lastTransactionDate", pg:"last_transaction_date"` - Amount int `json:"amount", pg:"amount"` + Amount float32 `json:"amount", pg:"amount"` } type NewSubscriptionBody struct { @@ -45,5 +45,6 @@ func (cm *Subscription) ToTrans() *Transaction { trans.TransactionTypeID = cm.TransactionTypeID trans.TransactionType = cm.TransactionType trans.DateCreated = cm.DateCreated + trans.SubscriptionID = cm.Id return trans } diff --git a/pkg/models/transactions.go b/pkg/models/transactions.go index 3854d46..c30c266 100644 --- a/pkg/models/transactions.go +++ b/pkg/models/transactions.go @@ -12,7 +12,7 @@ type Transaction struct { TransactionTypeID string `json:"transactionTypeId", pg:"transaction_type_id"` TransactionType *TransactionType `json:"transactionType", pg:"rel:has-one, fk:transaction_type_id"` WalletID string `json:"walletId", pg:"wallet_id"` - Amount int `json:"amount", pg:"amount"` + Amount float32 `json:"amount", pg:"amount"` Wallet *Wallet `json:"wallet" pg:"rel:has-one, fk:wallet_id"` TransactionDate time.Time `json:"transactionDate" pg:"transaction_date"` SubscriptionID string `json:"subscriptionId", pg:"subscription_id"` diff --git a/pkg/models/wallets.go b/pkg/models/wallets.go index 4c79665..b421d4f 100644 --- a/pkg/models/wallets.go +++ b/pkg/models/wallets.go @@ -14,14 +14,17 @@ type NewWalletBody struct { } type WalletHeader struct { - WalletId string `json:"walletId"` - CurrentBalance int `json:"currentBalance"` - LastMonth int `json:"lastMonth"` - NextMonth int `json:"nextMonth"` - Currency string `json:"currency"` + WalletId string `json:"walletId"` + CurrentBalance float32 `json:"currentBalance"` + LastMonth float32 `json:"lastMonth"` + NextMonth float32 `json:"nextMonth"` + Currency string `json:"currency"` } type WalletTransactions struct { - WalletId string - Transactions []Transaction + WalletId string + Transactions []Transaction + CurrentBalance float32 + LastMonth float32 + NextMonth float32 } diff --git a/pkg/services/subscriptions.go b/pkg/services/subscriptions.go index 9a638f6..3f6e6ea 100644 --- a/pkg/services/subscriptions.go +++ b/pkg/services/subscriptions.go @@ -1,6 +1,7 @@ package services import ( + "math" "time" "wallet-api/pkg/models" @@ -14,7 +15,7 @@ type SubscriptionService struct { func (as *SubscriptionService) New(body *models.NewSubscriptionBody) *models.Subscription { tm := new(models.Subscription) - amount, _ := body.Amount.Int64() + amount, _ := body.Amount.Float64() customRange, _ := body.CustomRange.Int64() tm.Init() @@ -26,7 +27,7 @@ func (as *SubscriptionService) New(body *models.NewSubscriptionBody) *models.Sub tm.StartDate = body.StartDate tm.HasEnd = body.HasEnd tm.EndDate = body.EndDate - tm.Amount = int(amount) + tm.Amount = float32(math.Round(amount*100) / 100) if body.StartDate.IsZero() { tm.StartDate = time.Now() @@ -34,6 +35,8 @@ func (as *SubscriptionService) New(body *models.NewSubscriptionBody) *models.Sub as.Db.Model(tm).Insert() + as.SubToTrans(tm) + return tm } @@ -46,3 +49,50 @@ func (as *SubscriptionService) GetAll(am *models.Auth, walletId string, filtered } FilteredResponse(query, wm, filtered) } + +func (as *SubscriptionService) SubToTrans(subModel *models.Subscription) { + now := time.Now() + + currentYear, currentMonth, _ := now.Date() + currentLocation := now.Location() + + firstOfNextMonth := time.Date(currentYear, currentMonth+1, 1, 0, 0, 0, 0, currentLocation) + + startDate := subModel.StartDate.Local() + stopDate := firstOfNextMonth + if subModel.HasEnd && subModel.EndDate.Local().Before(firstOfNextMonth) { + stopDate = subModel.EndDate.Local() + } + + transactions := new([]models.Transaction) + + if subModel.SubscriptionType == nil { + st := new(models.SubscriptionType) + as.Db.Model(st).Where("? = ?", pg.Ident("id"), subModel.SubscriptionTypeID).Select() + subModel.SubscriptionType = st + } + + for startDate.Before(stopDate) { + trans := subModel.ToTrans() + trans.TransactionDate = startDate + if startDate.After(subModel.LastTransactionDate) { + *transactions = append(*transactions, *trans) + } + if subModel.SubscriptionType.Type == "monthly" { + startDate = startDate.AddDate(0, subModel.CustomRange, 0) + } else if subModel.SubscriptionType.Type == "weekly" { + startDate = startDate.AddDate(0, 0, 7*subModel.CustomRange) + } else if subModel.SubscriptionType.Type == "daily" { + startDate = startDate.AddDate(0, 0, subModel.CustomRange) + } else { + startDate = startDate.AddDate(subModel.CustomRange, 0, 0) + } + } + + if len(*transactions) > 0 { + as.Db.Model(transactions).Insert() + subModel.LastTransactionDate = (*transactions)[len(*transactions)-1].TransactionDate + as.Db.Model(subModel).WherePK().Update() + + } +} diff --git a/pkg/services/transactions.go b/pkg/services/transactions.go index 09708bd..5eb38a7 100644 --- a/pkg/services/transactions.go +++ b/pkg/services/transactions.go @@ -1,6 +1,7 @@ package services import ( + "math" "time" "wallet-api/pkg/models" @@ -9,19 +10,20 @@ import ( type TransactionService struct { Db *pg.DB + Ss *SubscriptionService } func (as *TransactionService) New(body *models.NewTransactionBody) *models.Transaction { tm := new(models.Transaction) - amount, _ := body.Amount.Int64() + amount, _ := body.Amount.Float64() tm.Init() tm.WalletID = body.WalletID tm.TransactionTypeID = body.TransactionTypeID tm.Description = body.Description tm.TransactionDate = body.TransactionDate - tm.Amount = int(amount) + tm.Amount = float32(math.Round(amount*100) / 100) if body.TransactionDate.IsZero() { tm.TransactionDate = time.Now() @@ -34,8 +36,18 @@ func (as *TransactionService) New(body *models.NewTransactionBody) *models.Trans func (as *TransactionService) GetAll(am *models.Auth, walletId string, filtered *models.FilteredResponse) { wm := new([]models.Transaction) + sm := new([]models.Subscription) - query := as.Db.Model((wm)).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id) + query2 := as.Db.Model(sm).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id) + if walletId != "" { + query2 = query2.Where("? = ?", pg.Ident("wallet_id"), walletId) + } + + for _, sub := range *sm { + as.Ss.SubToTrans(&sub) + } + + query := as.Db.Model(wm).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id) if walletId != "" { query = query.Where("? = ?", pg.Ident("wallet_id"), walletId) } diff --git a/pkg/services/wallets.go b/pkg/services/wallets.go index ae68c12..805db98 100644 --- a/pkg/services/wallets.go +++ b/pkg/services/wallets.go @@ -11,6 +11,7 @@ import ( type WalletService struct { Db *pg.DB + Ss *SubscriptionService } func (as *WalletService) New(am *models.NewWalletBody) *models.Wallet { @@ -41,7 +42,7 @@ func (as *WalletService) GetAll(am *models.Auth, filtered *models.FilteredRespon func (as *WalletService) GetHeader(am *models.Auth, embed string, walletId string) *models.WalletHeader { wm := new(models.WalletHeader) - var wallets []models.WalletTransactions + wallets := new([]models.WalletTransactions) var wg sync.WaitGroup transactions := new([]models.Transaction) subscriptions := new([]models.Subscription) @@ -67,14 +68,6 @@ func (as *WalletService) GetHeader(am *models.Auth, embed string, walletId strin wg.Wait() - currentBalance := 0 - lastMonthBalance := 0 - nextMonth := 0 - - subCurrentBalance := 0 - subLastMonthBalance := 0 - subNextMonth := 0 - now := time.Now() currentYear, currentMonth, _ := now.Date() @@ -85,57 +78,59 @@ func (as *WalletService) GetHeader(am *models.Auth, embed string, walletId strin firstOfMonthAfterNext := time.Date(currentYear, currentMonth+2, 1, 0, 0, 0, 0, currentLocation) for _, trans := range *transactions { - addWhere(&wallets, trans.WalletID, trans) + addWhere(wallets, trans.WalletID, trans) } for _, sub := range *subscriptions { - startDate := sub.StartDate.Local() - stopDate := firstOfMonthAfterNext - if sub.HasEnd { - stopDate = sub.EndDate.Local() - } - for startDate.Before(stopDate) { - trans := sub.ToTrans() - trans.TransactionDate = startDate - addWhere(&wallets, sub.WalletID, *trans) - if sub.SubscriptionType.Type == "monthly" { - startDate = startDate.AddDate(0, sub.CustomRange, 0) - } else if sub.SubscriptionType.Type == "weekly" { - startDate = startDate.AddDate(0, 0, 7*sub.CustomRange) - } else if sub.SubscriptionType.Type == "daily" { - startDate = startDate.AddDate(0, 0, sub.CustomRange) - } else { - startDate = startDate.AddDate(sub.CustomRange, 0, 0) - } - } + as.Ss.SubToTrans(&sub) + // startDate := sub.StartDate.Local() + // stopDate := firstOfMonthAfterNext + // if sub.HasEnd { + // stopDate = sub.EndDate.Local() + // } + // for startDate.Before(stopDate) { + // trans := sub.ToTrans() + // trans.TransactionDate = startDate + // addWhere(&wallets, sub.WalletID, *trans) + // if sub.SubscriptionType.Type == "monthly" { + // startDate = startDate.AddDate(0, sub.CustomRange, 0) + // } else if sub.SubscriptionType.Type == "weekly" { + // startDate = startDate.AddDate(0, 0, 7*sub.CustomRange) + // } else if sub.SubscriptionType.Type == "daily" { + // startDate = startDate.AddDate(0, 0, sub.CustomRange) + // } else { + // startDate = startDate.AddDate(sub.CustomRange, 0, 0) + // } + // } } - for _, wallet := range wallets { - wg.Add(1) - go func() { - defer wg.Done() - for _, trans := range wallet.Transactions { - if trans.TransactionDate.Local().Before(firstOfNextMonth) && trans.TransactionDate.Local().After(firstOfMonth) { - if trans.TransactionType.Type == "expense" { - currentBalance -= trans.Amount - } else { - currentBalance += trans.Amount - } - } else if trans.TransactionDate.Local().Before(firstOfMonthAfterNext) && trans.TransactionDate.Local().After(firstOfNextMonth) { - if trans.TransactionType.Type == "expense" { - nextMonth -= trans.Amount - } else { - nextMonth += trans.Amount - } - } else if trans.TransactionDate.Local().Before(firstOfMonth) { - if trans.TransactionType.Type == "expense" { - lastMonthBalance -= trans.Amount - } else { - lastMonthBalance += trans.Amount - } + for i, wallet := range *wallets { + // wg.Add(1) + // go func() { + // defer wg.Done() + for _, trans := range wallet.Transactions { + if trans.TransactionDate.Local().Before(firstOfNextMonth) && trans.TransactionDate.Local().After(firstOfMonth) { + if trans.TransactionType.Type == "expense" { + (*wallets)[i].CurrentBalance -= trans.Amount + } else { + (*wallets)[i].CurrentBalance += trans.Amount + } + } else if trans.TransactionDate.Local().Before(firstOfMonthAfterNext) && trans.TransactionDate.Local().After(firstOfNextMonth) { + if trans.TransactionType.Type == "expense" { + (*wallets)[i].NextMonth -= trans.Amount + } else { + (*wallets)[i].NextMonth += trans.Amount + } + } else if trans.TransactionDate.Local().Before(firstOfMonth) { + if trans.TransactionType.Type == "expense" { + (*wallets)[i].LastMonth -= trans.Amount + } else { + (*wallets)[i].LastMonth += trans.Amount } } - }() + + } + // }() } // for _, sub := range *subscriptions { @@ -171,13 +166,12 @@ func (as *WalletService) GetHeader(am *models.Auth, embed string, walletId strin wg.Wait() - combinedCurrent := currentBalance + subCurrentBalance - combinedLast := lastMonthBalance + subLastMonthBalance - combinedNext := nextMonth + subNextMonth + for _, wallet := range *wallets { + wm.LastMonth += wallet.LastMonth + wm.CurrentBalance += wallet.CurrentBalance + wallet.LastMonth + wm.NextMonth += wallet.NextMonth + wallet.CurrentBalance + wallet.LastMonth + } - wm.LastMonth = combinedLast - wm.CurrentBalance = combinedCurrent + combinedLast - wm.NextMonth = combinedLast + combinedCurrent + combinedNext wm.Currency = "USD" wm.WalletId = walletId @@ -191,8 +185,8 @@ func addWhere(s *[]models.WalletTransactions, walletId string, e models.Transact for a, _ := range *s { if (*s)[a].WalletId == walletId { (*s)[a].Transactions = append((*s)[a].Transactions, e) + exists = true } - exists = true } if !exists { var walletTransaction models.WalletTransactions