diff --git a/pkg/api/routes.go b/pkg/api/routes.go index fa44f9e..8307cd2 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -1,9 +1,8 @@ package api import ( - "wallet-api/pkg/controllers" + "wallet-api/pkg/controller" "wallet-api/pkg/middleware" - "wallet-api/pkg/services" "wallet-api/pkg/utl/common" "wallet-api/pkg/utl/configs" @@ -47,22 +46,5 @@ func Routes(s *gin.Engine, db *pg.DB) { c.Provide(func() *pg.DB { return db }) - c.Provide(services.NewApiService) - c.Provide(services.NewSubscriptionService) - c.Provide(services.NewSubscriptionTypeService) - c.Provide(services.NewTransactionService) - c.Provide(services.NewTransactionStatusService) - c.Provide(services.NewTransactionTypeService) - c.Provide(services.NewUsersService) - c.Provide(services.NewWalletService) - - c.Invoke(controllers.NewApiController) - c.Invoke(controllers.NewAuthController) - c.Invoke(controllers.NewWalletsController) - c.Invoke(controllers.NewWalletsHeaderController) - c.Invoke(controllers.NewTransactionController) - c.Invoke(controllers.NewTransactionStatusController) - c.Invoke(controllers.NewTransactionTypeController) - c.Invoke(controllers.NewSubscriptionController) - c.Invoke(controllers.NewSubscriptionTypeController) + controller.InitializeControllers(c) } diff --git a/pkg/controllers/api.go b/pkg/controller/api.go similarity index 86% rename from pkg/controllers/api.go rename to pkg/controller/api.go index a376867..ff1e972 100644 --- a/pkg/controllers/api.go +++ b/pkg/controller/api.go @@ -1,15 +1,15 @@ -package controllers +package controller import ( "wallet-api/pkg/middleware" - "wallet-api/pkg/services" + "wallet-api/pkg/service" "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type ApiController struct { - service *services.ApiService + service *service.ApiService } /* @@ -23,7 +23,7 @@ Initializes ApiController. Returns: *ApiController: Controller for "api" interactions */ -func NewApiController(as *services.ApiService, routeGroups *common.RouteGroups) *ApiController { +func NewApiController(as *service.ApiService, routeGroups *common.RouteGroups) *ApiController { ac := &ApiController{ service: as, } diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go new file mode 100644 index 0000000..25fbb9e --- /dev/null +++ b/pkg/controller/controller.go @@ -0,0 +1,70 @@ +package controller + +import ( + "fmt" + "go.uber.org/dig" + "strconv" + "strings" + "wallet-api/pkg/model" + "wallet-api/pkg/service" + "wallet-api/pkg/utl/common" + + "github.com/gin-gonic/gin" +) + +/* +InitializeControllers + +Initializes Dependency Injection modules and registers controllers + + Args: + *dig.Container: Dig Container +*/ +func InitializeControllers(c *dig.Container) { + service.InitializeServices(c) + + c.Invoke(NewApiController) + c.Invoke(NewUserController) + c.Invoke(NewWalletController) + c.Invoke(NewWalletHeaderController) + c.Invoke(NewTransactionController) + c.Invoke(NewTransactionStatusController) + c.Invoke(NewTransactionTypeController) + c.Invoke(NewSubscriptionController) + c.Invoke(NewSubscriptionTypeController) + +} + +/* +FilteredResponse + +Gets query parameters and populates FilteredResponse model. + + Args: + *gin.Context: Gin Application Context + Returns: + *model.FilteredResponse: Filtered response +*/ +func FilteredResponse(c *gin.Context) *model.FilteredResponse { + filtered := new(model.FilteredResponse) + page, _ := c.GetQuery("page") + rpp, _ := c.GetQuery("rpp") + sortBy, _ := c.GetQuery("sortBy") + + dividers := [5]string{"|", " ", ".", "/", ","} + + for _, div := range dividers { + sortArr := strings.Split(sortBy, div) + + if len(sortArr) >= 2 { + sortBy = fmt.Sprintf("%s %s", common.ToSnakeCase(sortArr[0]), strings.ToUpper(sortArr[1])) + } + } + + filtered.Embed, _ = c.GetQuery("embed") + filtered.Page, _ = strconv.Atoi(page) + filtered.Rpp, _ = strconv.Atoi(rpp) + filtered.SortBy = sortBy + + return filtered +} diff --git a/pkg/controllers/subscriptions.go b/pkg/controller/subscription.go similarity index 77% rename from pkg/controllers/subscriptions.go rename to pkg/controller/subscription.go index 4997d1c..ddd3150 100644 --- a/pkg/controllers/subscriptions.go +++ b/pkg/controller/subscription.go @@ -1,16 +1,17 @@ -package controllers +package controller import ( "net/http" - "wallet-api/pkg/models" - "wallet-api/pkg/services" + "wallet-api/pkg/filter" + "wallet-api/pkg/model" + "wallet-api/pkg/service" "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type SubscriptionController struct { - service *services.SubscriptionService + service *service.SubscriptionService } /* @@ -24,7 +25,7 @@ Initializes SubscriptionController. Returns: *SubscriptionController: Controller for "subscription" route interactions */ -func NewSubscriptionController(as *services.SubscriptionService, routeGroups *common.RouteGroups) *SubscriptionController { +func NewSubscriptionController(as *service.SubscriptionService, routeGroups *common.RouteGroups) *SubscriptionController { wc := &SubscriptionController{ service: as, } @@ -49,7 +50,7 @@ New */ // ROUTE (POST /subscription) func (wc *SubscriptionController) New(c *gin.Context) { - body := new(models.NewSubscriptionBody) + body := new(model.NewSubscriptionBody) if err := c.ShouldBind(body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return @@ -72,7 +73,7 @@ Edit */ // ROUTE (PUT /subscription/:id) func (wc *SubscriptionController) Edit(c *gin.Context) { - body := new(models.SubscriptionEdit) + body := new(model.SubscriptionEdit) if err := c.ShouldBind(body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return @@ -95,18 +96,21 @@ Get */ // ROUTE (GET /subscription/:id) func (wc *SubscriptionController) Get(c *gin.Context) { - body := new(models.Auth) - params := new(models.Params) + body := new(model.Auth) + params := new(model.Params) auth := c.MustGet("auth") - body.Id = auth.(*models.Auth).Id + body.Id = auth.(*model.Auth).Id id := c.Param("id") embed, _ := c.GetQuery("embed") params.Embed = embed - fr, exception := wc.service.Get(c, body, id, params) + flt := filter.NewSubscriptionFilter(*params) + flt.Id = id + + fr, exception := wc.service.Get(c, body, *flt) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -117,12 +121,12 @@ func (wc *SubscriptionController) Get(c *gin.Context) { // ROUTE (PUT /subscription/end/:id) func (wc *SubscriptionController) End(c *gin.Context) { - body := new(models.Auth) + body := new(model.Auth) auth := c.MustGet("auth") - body.Id = auth.(*models.Auth).Id + body.Id = auth.(*model.Auth).Id - end := new(models.SubscriptionEnd) + end := new(model.SubscriptionEnd) if err := c.ShouldBind(end); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return @@ -146,14 +150,16 @@ GetAll */ // ROUTE (GET /subscription) func (wc *SubscriptionController) GetAll(c *gin.Context) { - body := new(models.Auth) auth := c.MustGet("auth") - body.Id = auth.(*models.Auth).Id fr := FilteredResponse(c) wallet, _ := c.GetQuery("walletId") - exception := wc.service.GetAll(c, body, wallet, fr) + flt := filter.NewSubscriptionFilter(model.Params{}) + flt.WalletId = wallet + flt.Id = auth.(*model.Auth).Id + + exception := wc.service.GetAll(c, flt, fr) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controllers/subscriptionTypes.go b/pkg/controller/subscriptionType.go similarity index 81% rename from pkg/controllers/subscriptionTypes.go rename to pkg/controller/subscriptionType.go index 847b10d..f55aba5 100644 --- a/pkg/controllers/subscriptionTypes.go +++ b/pkg/controller/subscriptionType.go @@ -1,16 +1,16 @@ -package controllers +package controller import ( "net/http" - "wallet-api/pkg/models" - "wallet-api/pkg/services" + "wallet-api/pkg/model" + "wallet-api/pkg/service" "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type SubscriptionTypeController struct { - service *services.SubscriptionTypeService + service *service.SubscriptionTypeService } /* @@ -24,7 +24,7 @@ Initializes SubscriptionTypeController. Returns: *SubscriptionTypeController: Controller for "subscription-types" route interactions */ -func NewSubscriptionTypeController(as *services.SubscriptionTypeService, routeGroups *common.RouteGroups) *SubscriptionTypeController { +func NewSubscriptionTypeController(as *service.SubscriptionTypeService, routeGroups *common.RouteGroups) *SubscriptionTypeController { wc := &SubscriptionTypeController{ service: as, } @@ -42,7 +42,7 @@ New */ // ROUTE (POST /subscription-types) func (wc *SubscriptionTypeController) New(c *gin.Context) { - body := new(models.NewSubscriptionTypeBody) + body := new(model.NewSubscriptionTypeBody) if err := c.ShouldBind(body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return diff --git a/pkg/controllers/transactions.go b/pkg/controller/transaction.go similarity index 85% rename from pkg/controllers/transactions.go rename to pkg/controller/transaction.go index 75d54c4..2b8a6c7 100644 --- a/pkg/controllers/transactions.go +++ b/pkg/controller/transaction.go @@ -1,16 +1,16 @@ -package controllers +package controller import ( "net/http" - "wallet-api/pkg/models" - "wallet-api/pkg/services" + "wallet-api/pkg/model" + "wallet-api/pkg/service" "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type TransactionController struct { - service *services.TransactionService + service *service.TransactionService } /* @@ -24,7 +24,7 @@ Initializes TransactionController. Returns: *TransactionController: Controller for "transaction" route interactions */ -func NewTransactionController(as *services.TransactionService, routeGroups *common.RouteGroups) *TransactionController { +func NewTransactionController(as *service.TransactionService, routeGroups *common.RouteGroups) *TransactionController { wc := &TransactionController{ service: as, } @@ -54,7 +54,7 @@ New */ // ROUTE (POST /transactions) func (wc *TransactionController) New(c *gin.Context) { - body := new(models.NewTransactionBody) + body := new(model.NewTransactionBody) if err := c.ShouldBind(body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return @@ -75,9 +75,9 @@ GetAll */ // ROUTE (GET /transactions) func (wc *TransactionController) GetAll(c *gin.Context) { - body := new(models.Auth) + body := new(model.Auth) auth := c.MustGet("auth") - body.Id = auth.(*models.Auth).Id + body.Id = auth.(*model.Auth).Id fr := FilteredResponse(c) wallet, _ := c.GetQuery("walletId") @@ -101,9 +101,9 @@ Check */ // ROUTE (GET /transactions) func (wc *TransactionController) Check(c *gin.Context) { - body := new(models.Auth) + body := new(model.Auth) auth := c.MustGet("auth") - body.Id = auth.(*models.Auth).Id + body.Id = auth.(*model.Auth).Id fr := FilteredResponse(c) wallet, _ := c.GetQuery("walletId") @@ -124,7 +124,7 @@ Edit */ // ROUTE (PUT /transactions/:id) func (wc *TransactionController) Edit(c *gin.Context) { - body := new(models.TransactionEdit) + body := new(model.TransactionEdit) if err := c.ShouldBind(body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return @@ -147,7 +147,7 @@ BulkEdit */ // ROUTE (PUT /transactions/:id) func (wc *TransactionController) BulkEdit(c *gin.Context) { - body := new([]models.TransactionEdit) + body := new([]model.TransactionEdit) if err := c.ShouldBind(body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return @@ -168,11 +168,11 @@ Get */ // ROUTE (GET /transactions/:id) func (wc *TransactionController) Get(c *gin.Context) { - body := new(models.Auth) - params := new(models.Params) + body := new(model.Auth) + params := new(model.Params) auth := c.MustGet("auth") - body.Id = auth.(*models.Auth).Id + body.Id = auth.(*model.Auth).Id id := c.Param("id") diff --git a/pkg/controllers/transactionStatus.go b/pkg/controller/transactionStatus.go similarity index 81% rename from pkg/controllers/transactionStatus.go rename to pkg/controller/transactionStatus.go index bf7e6e3..3f99aa9 100644 --- a/pkg/controllers/transactionStatus.go +++ b/pkg/controller/transactionStatus.go @@ -1,16 +1,16 @@ -package controllers +package controller import ( "net/http" - "wallet-api/pkg/models" - "wallet-api/pkg/services" + "wallet-api/pkg/model" + "wallet-api/pkg/service" "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type TransactionStatusController struct { - service *services.TransactionStatusService + service *service.TransactionStatusService } /* @@ -24,7 +24,7 @@ Initializes TransactionStatusController. Returns: *TransactionStatusController: Controller for "transaction-status" route interactions */ -func NewTransactionStatusController(as *services.TransactionStatusService, routeGroups *common.RouteGroups) *TransactionStatusController { +func NewTransactionStatusController(as *service.TransactionStatusService, routeGroups *common.RouteGroups) *TransactionStatusController { wc := &TransactionStatusController{ service: as, } @@ -42,7 +42,7 @@ New */ // ROUTE (POST /transaction-status) func (wc *TransactionStatusController) New(c *gin.Context) { - body := new(models.NewTransactionStatusBody) + body := new(model.NewTransactionStatusBody) if err := c.ShouldBind(body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return diff --git a/pkg/controllers/transactionTypes.go b/pkg/controller/transactionType.go similarity index 81% rename from pkg/controllers/transactionTypes.go rename to pkg/controller/transactionType.go index 9a6c561..c04d412 100644 --- a/pkg/controllers/transactionTypes.go +++ b/pkg/controller/transactionType.go @@ -1,16 +1,16 @@ -package controllers +package controller import ( "net/http" - "wallet-api/pkg/models" - "wallet-api/pkg/services" + "wallet-api/pkg/model" + "wallet-api/pkg/service" "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type TransactionTypeController struct { - service *services.TransactionTypeService + service *service.TransactionTypeService } /* @@ -24,7 +24,7 @@ Initializes TransactionTypeController. Returns: *TransactionTypeController: Controller for "transaction-types" route interactions */ -func NewTransactionTypeController(as *services.TransactionTypeService, routeGroups *common.RouteGroups) *TransactionTypeController { +func NewTransactionTypeController(as *service.TransactionTypeService, routeGroups *common.RouteGroups) *TransactionTypeController { wc := &TransactionTypeController{ service: as, } @@ -42,7 +42,7 @@ New */ // ROUTE (POST /transaction-types) func (wc *TransactionTypeController) New(c *gin.Context) { - body := new(models.NewTransactionTypeBody) + body := new(model.NewTransactionTypeBody) if err := c.ShouldBind(body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return diff --git a/pkg/controllers/auth.go b/pkg/controller/user.go similarity index 70% rename from pkg/controllers/auth.go rename to pkg/controller/user.go index 0110dd7..cd12358 100644 --- a/pkg/controllers/auth.go +++ b/pkg/controller/user.go @@ -1,32 +1,32 @@ -package controllers +package controller import ( "net/http" "wallet-api/pkg/middleware" - "wallet-api/pkg/models" - "wallet-api/pkg/services" + "wallet-api/pkg/model" + "wallet-api/pkg/service" "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) -type AuthController struct { - service *services.UsersService +type UserController struct { + service *service.UserService } /* -NewAuthController +NewUserController -Initializes AuthController. +Initializes UserController. Args: - *services.UsersService: Users service + *services.UserService: User service *gin.RouterGroup: Gin Router Group Returns: - *AuthController: Controller for "auth" interactions + *UserController: Controller for "auth" interactions */ -func NewAuthController(rs *services.UsersService, routeGroups *common.RouteGroups) *AuthController { - rc := &AuthController{ +func NewUserController(rs *service.UserService, routeGroups *common.RouteGroups) *UserController { + rc := &UserController{ service: rs, } @@ -44,8 +44,8 @@ PostLogin *gin.Context: Gin Application Context */ // ROUTE (POST /auth/login). -func (rc *AuthController) PostLogin(c *gin.Context) { - body := new(models.Login) +func (rc *UserController) PostLogin(c *gin.Context) { + body := new(model.Login) if err := c.ShouldBind(&body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return @@ -66,8 +66,8 @@ PostRegister *gin.Context: Gin Application Context */ // ROUTE (POST /auth/register). -func (rc *AuthController) PostRegister(c *gin.Context) { - body := new(models.User) +func (rc *UserController) PostRegister(c *gin.Context) { + body := new(model.User) body.Init() body.IsActive = true if err := c.ShouldBind(body); err != nil { @@ -90,10 +90,10 @@ Delete *gin.Context: Gin Application Context */ // ROUTE (DELETE /auth/deactivate). -func (rc *AuthController) Delete(c *gin.Context) { - auth := new(models.Auth) +func (rc *UserController) Delete(c *gin.Context) { + auth := new(model.Auth) authGet := c.MustGet("auth") - auth.Id = authGet.(*models.Auth).Id + auth.Id = authGet.(*model.Auth).Id mr, er := rc.service.Deactivate(c, auth) @@ -111,9 +111,9 @@ CheckToken *gin.Context: Gin Application Context */ // ROUTE (GET /auth/check-token). -func (rc *AuthController) CheckToken(c *gin.Context) { +func (rc *UserController) CheckToken(c *gin.Context) { token, _ := c.GetQuery("token") - re := new(models.CheckToken) + re := new(model.CheckToken) _, err := middleware.CheckToken(token) diff --git a/pkg/controllers/wallets-header.go b/pkg/controller/wallet-header.go similarity index 50% rename from pkg/controllers/wallets-header.go rename to pkg/controller/wallet-header.go index 528b741..7b5b1ac 100644 --- a/pkg/controllers/wallets-header.go +++ b/pkg/controller/wallet-header.go @@ -1,30 +1,30 @@ -package controllers +package controller import ( - "wallet-api/pkg/models" - "wallet-api/pkg/services" + "wallet-api/pkg/model" + "wallet-api/pkg/service" "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) -type WalletsHeaderController struct { - service *services.WalletService +type WalletHeaderController struct { + service *service.WalletService } /* -NewWalletsHeaderController +NewWalletHeaderController -Initializes WalletsHeaderController. +Initializes WalletHeaderController. Args: *services.WalletService: Wallet service *gin.RouterGroup: Gin Router Group Returns: - *WalletsHeaderController: Controller for "wallet/wallet-header" route interactions + *WalletHeaderController: Controller for "wallet/wallet-header" route interactions */ -func NewWalletsHeaderController(as *services.WalletService, routeGroups *common.RouteGroups) *WalletsHeaderController { - wc := &WalletsHeaderController{ +func NewWalletHeaderController(as *service.WalletService, routeGroups *common.RouteGroups) *WalletHeaderController { + wc := &WalletHeaderController{ service: as, } @@ -39,13 +39,13 @@ Get *gin.Context: Gin Application Context */ // ROUTE (GET /wallet/wallet-header) -func (wc *WalletsHeaderController) Get(c *gin.Context) { - body := new(models.Auth) +func (wc *WalletHeaderController) Get(c *gin.Context) { + body := new(model.Auth) walletId, _ := c.GetQuery("walletId") auth := c.MustGet("auth") - body.Id = auth.(*models.Auth).Id + body.Id = auth.(*model.Auth).Id wm, exception := wc.service.GetHeader(c, body, walletId) if exception != nil { diff --git a/pkg/controllers/wallets.go b/pkg/controller/wallet.go similarity index 68% rename from pkg/controllers/wallets.go rename to pkg/controller/wallet.go index 495ee81..dbdfc62 100644 --- a/pkg/controllers/wallets.go +++ b/pkg/controller/wallet.go @@ -1,31 +1,31 @@ -package controllers +package controller import ( "net/http" - "wallet-api/pkg/models" - "wallet-api/pkg/services" + "wallet-api/pkg/model" + "wallet-api/pkg/service" "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) -type WalletsController struct { - service *services.WalletService +type WalletController struct { + service *service.WalletService } /* -NewWalletsController +NewWalletController -Initializes WalletsController. +Initializes WalletController. Args: *services.WalletService: Wallet service *gin.RouterGroup: Gin Router Group Returns: - *WalletsController: Controller for "wallet" route interactions + *WalletController: Controller for "wallet" route interactions */ -func NewWalletsController(as *services.WalletService, routeGroups *common.RouteGroups) *WalletsController { - wc := &WalletsController{ +func NewWalletController(as *service.WalletService, routeGroups *common.RouteGroups) *WalletController { + wc := &WalletController{ service: as, } @@ -43,8 +43,8 @@ New *gin.Context: Gin Application Context */ // ROUTE (POST /wallet) -func (wc *WalletsController) New(c *gin.Context) { - body := new(models.NewWalletBody) +func (wc *WalletController) New(c *gin.Context) { + body := new(model.NewWalletBody) if err := c.ShouldBind(body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) @@ -52,7 +52,7 @@ func (wc *WalletsController) New(c *gin.Context) { } get := c.MustGet("auth") - body.UserID = get.(*models.Auth).Id + body.UserID = get.(*model.Auth).Id wm, exception := wc.service.New(c, body) if exception != nil { @@ -68,10 +68,10 @@ GetAll *gin.Context: Gin Application Context */ // ROUTE (GET /wallet) -func (wc *WalletsController) GetAll(c *gin.Context) { - body := new(models.Auth) +func (wc *WalletController) GetAll(c *gin.Context) { + body := new(model.Auth) auth := c.MustGet("auth") - body.Id = auth.(*models.Auth).Id + body.Id = auth.(*model.Auth).Id fr := FilteredResponse(c) @@ -90,8 +90,8 @@ Edit *gin.Context: Gin Application Context */ // ROUTE (PUT /wallet/:id) -func (wc *WalletsController) Edit(c *gin.Context) { - body := new(models.WalletEdit) +func (wc *WalletController) Edit(c *gin.Context) { + body := new(model.WalletEdit) if err := c.ShouldBind(body); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return @@ -113,8 +113,8 @@ Get *gin.Context: Gin Application Context */ // ROUTE (GET /wallet/:id) -func (wc *WalletsController) Get(c *gin.Context) { - params := new(models.Params) +func (wc *WalletController) Get(c *gin.Context) { + params := new(model.Params) id := c.Param("id") diff --git a/pkg/controllers/controllers.go b/pkg/controllers/controllers.go deleted file mode 100644 index 083754b..0000000 --- a/pkg/controllers/controllers.go +++ /dev/null @@ -1,44 +0,0 @@ -package controllers - -import ( - "fmt" - "strconv" - "strings" - "wallet-api/pkg/models" - "wallet-api/pkg/utl/common" - - "github.com/gin-gonic/gin" -) - -/* -FilteredResponse - -Gets query parameters and populates FilteredResponse model. - Args: - *gin.Context: Gin Application Context - Returns: - *models.FilteredResponse: Filtered response -*/ -func FilteredResponse(c *gin.Context) *models.FilteredResponse { - filtered := new(models.FilteredResponse) - page, _ := c.GetQuery("page") - rpp, _ := c.GetQuery("rpp") - sortBy, _ := c.GetQuery("sortBy") - - dividers := [5]string{"|", " ", ".", "/", ","} - - for _, div := range dividers { - sortArr := strings.Split(sortBy, div) - - if len(sortArr) >= 2 { - sortBy = fmt.Sprintf("%s %s", common.ToSnakeCase(sortArr[0]), strings.ToUpper(sortArr[1])) - } - } - - filtered.Embed, _ = c.GetQuery("embed") - filtered.Page, _ = strconv.Atoi(page) - filtered.Rpp, _ = strconv.Atoi(rpp) - filtered.SortBy = sortBy - - return filtered -} diff --git a/pkg/filter/api.go b/pkg/filter/api.go new file mode 100644 index 0000000..167e427 --- /dev/null +++ b/pkg/filter/api.go @@ -0,0 +1,13 @@ +package filter + +import "wallet-api/pkg/model" + +type ApiFilter struct { + model.Params +} + +func NewApiFilter(params model.Params) *ApiFilter { + return &ApiFilter{ + Params: params, + } +} diff --git a/pkg/filter/filter.go b/pkg/filter/filter.go new file mode 100644 index 0000000..10aa5c1 --- /dev/null +++ b/pkg/filter/filter.go @@ -0,0 +1,27 @@ +package filter + +import "go.uber.org/dig" + +/* +InitializeFilters + +Initializes Dependency Injection modules for filters + + Args: + *dig.Container: Dig Container +*/ +func InitializeFilters(c *dig.Container) { + c.Provide(NewApiFilter) + c.Provide(NewSubscriptionFilter) + c.Provide(NewSubscriptionTypeFilter) + c.Provide(NewTransactionFilter) + c.Provide(NewTransactionStatusFilter) + c.Provide(NewTransactionTypeFilter) + c.Provide(NewUserFilter) + c.Provide(NewWalletFilter) +} + +type BaseFilter struct { + Id string + WalletId string +} diff --git a/pkg/filter/subscription.go b/pkg/filter/subscription.go new file mode 100644 index 0000000..d023cb8 --- /dev/null +++ b/pkg/filter/subscription.go @@ -0,0 +1,14 @@ +package filter + +import "wallet-api/pkg/model" + +type SubscriptionFilter struct { + model.Params + BaseFilter +} + +func NewSubscriptionFilter(params model.Params) *SubscriptionFilter { + return &SubscriptionFilter{ + Params: params, + } +} diff --git a/pkg/filter/subscriptionType.go b/pkg/filter/subscriptionType.go new file mode 100644 index 0000000..39eccac --- /dev/null +++ b/pkg/filter/subscriptionType.go @@ -0,0 +1,14 @@ +package filter + +import "wallet-api/pkg/model" + +type SubscriptionTypeFilter struct { + model.Params + BaseFilter +} + +func NewSubscriptionTypeFilter(params model.Params) *SubscriptionTypeFilter { + return &SubscriptionTypeFilter{ + Params: params, + } +} diff --git a/pkg/filter/transaction.go b/pkg/filter/transaction.go new file mode 100644 index 0000000..fb608ff --- /dev/null +++ b/pkg/filter/transaction.go @@ -0,0 +1,16 @@ +package filter + +import "wallet-api/pkg/model" + +type TransactionFilter struct { + model.Params + BaseFilter + NoPending bool + TransactionStatusId string +} + +func NewTransactionFilter(params model.Params) *TransactionFilter { + return &TransactionFilter{ + Params: params, + } +} diff --git a/pkg/filter/transactionStatus.go b/pkg/filter/transactionStatus.go new file mode 100644 index 0000000..6f11a92 --- /dev/null +++ b/pkg/filter/transactionStatus.go @@ -0,0 +1,15 @@ +package filter + +import "wallet-api/pkg/model" + +type TransactionStatusFilter struct { + model.Params + BaseFilter + Status string +} + +func NewTransactionStatusFilter(params model.Params) *TransactionStatusFilter { + return &TransactionStatusFilter{ + Params: params, + } +} diff --git a/pkg/filter/transactionType.go b/pkg/filter/transactionType.go new file mode 100644 index 0000000..b6c7375 --- /dev/null +++ b/pkg/filter/transactionType.go @@ -0,0 +1,14 @@ +package filter + +import "wallet-api/pkg/model" + +type TransactionTypeFilter struct { + model.Params + BaseFilter +} + +func NewTransactionTypeFilter(params model.Params) *TransactionTypeFilter { + return &TransactionTypeFilter{ + Params: params, + } +} diff --git a/pkg/filter/user.go b/pkg/filter/user.go new file mode 100644 index 0000000..3075707 --- /dev/null +++ b/pkg/filter/user.go @@ -0,0 +1,14 @@ +package filter + +import "wallet-api/pkg/model" + +type UserFilter struct { + model.Params + BaseFilter +} + +func NewUserFilter(params model.Params) *UserFilter { + return &UserFilter{ + Params: params, + } +} diff --git a/pkg/filter/wallet-header.go b/pkg/filter/wallet-header.go new file mode 100644 index 0000000..2de1ced --- /dev/null +++ b/pkg/filter/wallet-header.go @@ -0,0 +1,14 @@ +package filter + +import "wallet-api/pkg/model" + +type WalletHeaderFilter struct { + model.Params + BaseFilter +} + +func NewWalletHeaderFilter(params model.Params) *WalletHeaderFilter { + return &WalletHeaderFilter{ + Params: params, + } +} diff --git a/pkg/filter/wallet.go b/pkg/filter/wallet.go new file mode 100644 index 0000000..4c56bfd --- /dev/null +++ b/pkg/filter/wallet.go @@ -0,0 +1,14 @@ +package filter + +import "wallet-api/pkg/model" + +type WalletFilter struct { + model.Params + BaseFilter +} + +func NewWalletFilter(params model.Params) *WalletFilter { + return &WalletFilter{ + Params: params, + } +} diff --git a/pkg/middleware/auth.go b/pkg/middleware/auth.go index afa7616..a6d6644 100644 --- a/pkg/middleware/auth.go +++ b/pkg/middleware/auth.go @@ -4,7 +4,7 @@ import ( "errors" "os" "strings" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "wallet-api/pkg/utl/configs" "github.com/dgrijalva/jwt-go" @@ -16,11 +16,12 @@ import ( Auth Checks if token from header is valid and extracts the id. + Args: *gin.Context: Gin Application Context. */ func Auth(c *gin.Context) { - exceptionReturn := new(models.Exception) + exceptionReturn := new(model.Exception) tokenString := ExtractToken(c) token, err := CheckToken(tokenString) if err != nil { @@ -33,7 +34,7 @@ func Auth(c *gin.Context) { if ok && token.Valid { userId, _ := claims["id"].(string) - authModel := new(models.Auth) + authModel := new(model.Auth) authModel.Id = userId c.Set("auth", authModel) @@ -45,6 +46,7 @@ func Auth(c *gin.Context) { ExtractToken Extracts token from header + Args: *gin.Context: Gin Application Context. Returns: @@ -66,6 +68,7 @@ func ExtractToken(c *gin.Context) string { CheckToken Checks if token is valid + Args: string: Token to check Returns: diff --git a/pkg/middleware/secretCode.go b/pkg/middleware/secretCode.go index 519996f..e357b16 100644 --- a/pkg/middleware/secretCode.go +++ b/pkg/middleware/secretCode.go @@ -3,7 +3,7 @@ package middleware import ( "net/http" "os" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "wallet-api/pkg/utl/configs" "github.com/gin-gonic/gin" @@ -13,11 +13,12 @@ import ( SecretCode Checks if secret code from body is valid. - Args: - *gin.Context: Gin Application Context. + + Args: + *gin.Context: Gin Application Context. */ func SecretCode(c *gin.Context) { - exceptionReturn := new(models.Exception) + exceptionReturn := new(model.Exception) secretCode := ExtractCode(c) secret := os.Getenv("SECRET_CODE") if secret == "" { @@ -37,8 +38,9 @@ func SecretCode(c *gin.Context) { ExtractCode Extracts the secret code from body. - Args: - *gin.Context: Gin Application Context. + + Args: + *gin.Context: Gin Application Context. */ func ExtractCode(c *gin.Context) SecretCodeModel { secret := new(SecretCodeModel) diff --git a/pkg/migrate/10_create_table_transaction_status.go b/pkg/migrate/10_create_table_transaction_status.go index 0b9ff6a..05b9d52 100644 --- a/pkg/migrate/10_create_table_transaction_status.go +++ b/pkg/migrate/10_create_table_transaction_status.go @@ -3,7 +3,7 @@ package migrate import ( "fmt" "log" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "github.com/go-pg/pg/v10" @@ -14,14 +14,15 @@ import ( CreateTableTransactionStatus Creates transaction_status table if it does not exist. - Args: - *pg.DB: Postgres database client - Returns: - error: Returns if there is an error with table creation + + Args: + *pg.DB: Postgres database client + Returns: + error: Returns if there is an error with table creation */ func CreateTableTransactionStatus(db pg.DB) error { models := []interface{}{ - (*models.TransactionStatus)(nil), + (*model.TransactionStatus)(nil), } for _, model := range models { diff --git a/pkg/migrate/11_populate_transaction_status.go b/pkg/migrate/11_populate_transaction_status.go index 6ca1009..85523ae 100644 --- a/pkg/migrate/11_populate_transaction_status.go +++ b/pkg/migrate/11_populate_transaction_status.go @@ -3,7 +3,7 @@ package migrate import ( "fmt" "log" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "github.com/go-pg/pg/v10" ) @@ -12,15 +12,16 @@ import ( PopulateTransactionStatus Populates transaction_status table if it exists. - Args: - *pg.DB: Postgres database client - Returns: - error: Returns if there is an error with populating table + + Args: + *pg.DB: Postgres database client + Returns: + error: Returns if there is an error with populating table */ func PopulateTransactionStatus(db pg.DB) error { - completed := new(models.TransactionStatus) - pending := new(models.TransactionStatus) - deleted := new(models.TransactionStatus) + completed := new(model.TransactionStatus) + pending := new(model.TransactionStatus) + deleted := new(model.TransactionStatus) completed.Init() completed.Name = "Completed" diff --git a/pkg/migrate/1_create_table_api.go b/pkg/migrate/1_create_table_api.go index 0d07370..2f6d20b 100644 --- a/pkg/migrate/1_create_table_api.go +++ b/pkg/migrate/1_create_table_api.go @@ -3,7 +3,7 @@ package migrate import ( "fmt" "log" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "github.com/go-pg/pg/v10" @@ -14,15 +14,16 @@ import ( CreateTableApi Creates api table if it does not exist. - Args: - *pg.DB: Postgres database client - Returns: - error: Returns if there is an error with table creation + + Args: + *pg.DB: Postgres database client + Returns: + error: Returns if there is an error with table creation */ func CreateTableApi(db pg.DB) error { models := []interface{}{ - (*models.ApiModel)(nil), + (*model.ApiModel)(nil), } for _, model := range models { diff --git a/pkg/migrate/2_create_table_users.go b/pkg/migrate/2_create_table_users.go index 164bb61..c3a9f23 100644 --- a/pkg/migrate/2_create_table_users.go +++ b/pkg/migrate/2_create_table_users.go @@ -3,7 +3,7 @@ package migrate import ( "fmt" "log" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "github.com/go-pg/pg/v10" @@ -14,14 +14,15 @@ import ( CreateTableUsers Creates users table if it does not exist. - Args: - *pg.DB: Postgres database client - Returns: - error: Returns if there is an error with table creation + + Args: + *pg.DB: Postgres database client + Returns: + error: Returns if there is an error with table creation */ func CreateTableUsers(db pg.DB) error { models := []interface{}{ - (*models.User)(nil), + (*model.User)(nil), } for _, model := range models { diff --git a/pkg/migrate/3_create_table_wallets.go b/pkg/migrate/3_create_table_wallets.go index 51f4ebb..7269224 100644 --- a/pkg/migrate/3_create_table_wallets.go +++ b/pkg/migrate/3_create_table_wallets.go @@ -3,7 +3,7 @@ package migrate import ( "fmt" "log" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "github.com/go-pg/pg/v10" @@ -14,14 +14,15 @@ import ( CreateTableWallets Creates wallets table if it does not exist. - Args: - *pg.DB: Postgres database client - Returns: - error: Returns if there is an error with table creation + + Args: + *pg.DB: Postgres database client + Returns: + error: Returns if there is an error with table creation */ func CreateTableWallets(db pg.DB) error { models := []interface{}{ - (*models.Wallet)(nil), + (*model.Wallet)(nil), } for _, model := range models { diff --git a/pkg/migrate/4_create_table_transaction_types.go b/pkg/migrate/4_create_table_transaction_types.go index 6fd742e..691d7b8 100644 --- a/pkg/migrate/4_create_table_transaction_types.go +++ b/pkg/migrate/4_create_table_transaction_types.go @@ -3,7 +3,7 @@ package migrate import ( "fmt" "log" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "github.com/go-pg/pg/v10" @@ -14,14 +14,15 @@ import ( CreateTableTransactionTypes Creates transaction_types table if it does not exist. - Args: - *pg.DB: Postgres database client - Returns: - error: Returns if there is an error with table creation + + Args: + *pg.DB: Postgres database client + Returns: + error: Returns if there is an error with table creation */ func CreateTableTransactionTypes(db pg.DB) error { models := []interface{}{ - (*models.TransactionType)(nil), + (*model.TransactionType)(nil), } for _, model := range models { diff --git a/pkg/migrate/5_create_table_transactions.go b/pkg/migrate/5_create_table_transactions.go index d777869..3801db0 100644 --- a/pkg/migrate/5_create_table_transactions.go +++ b/pkg/migrate/5_create_table_transactions.go @@ -3,7 +3,7 @@ package migrate import ( "fmt" "log" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "github.com/go-pg/pg/v10" @@ -14,14 +14,15 @@ import ( CreateTableTransactions Creates transactions table if it does not exist. - Args: - *pg.DB: Postgres database client - Returns: - error: Returns if there is an error with table creation + + Args: + *pg.DB: Postgres database client + Returns: + error: Returns if there is an error with table creation */ func CreateTableTransactions(db pg.DB) error { models := []interface{}{ - (*models.Transaction)(nil), + (*model.Transaction)(nil), } for _, model := range models { diff --git a/pkg/migrate/6_create_table_subscription_types.go b/pkg/migrate/6_create_table_subscription_types.go index 716ac63..890b887 100644 --- a/pkg/migrate/6_create_table_subscription_types.go +++ b/pkg/migrate/6_create_table_subscription_types.go @@ -3,7 +3,7 @@ package migrate import ( "fmt" "log" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "github.com/go-pg/pg/v10" @@ -14,14 +14,15 @@ import ( CreateTableSubscriptionTypes Creates subscription_types table if it does not exist. - Args: - *pg.DB: Postgres database client - Returns: - error: Returns if there is an error with table creation + + Args: + *pg.DB: Postgres database client + Returns: + error: Returns if there is an error with table creation */ func CreateTableSubscriptionTypes(db pg.DB) error { models := []interface{}{ - (*models.SubscriptionType)(nil), + (*model.SubscriptionType)(nil), } for _, model := range models { diff --git a/pkg/migrate/7_create_table_subscriptions.go b/pkg/migrate/7_create_table_subscriptions.go index a7e5977..b6efb90 100644 --- a/pkg/migrate/7_create_table_subscriptions.go +++ b/pkg/migrate/7_create_table_subscriptions.go @@ -3,7 +3,7 @@ package migrate import ( "fmt" "log" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10/orm" @@ -13,14 +13,15 @@ import ( CreateTableSubscriptions Creates subscriptions table if it does not exist. - Args: - *pg.DB: Postgres database client - Returns: - error: Returns if there is an error with table creation + + Args: + *pg.DB: Postgres database client + Returns: + error: Returns if there is an error with table creation */ func CreateTableSubscriptions(db pg.DB) error { models := []interface{}{ - (*models.Subscription)(nil), + (*model.Subscription)(nil), } for _, model := range models { diff --git a/pkg/migrate/8_populate_subscription_types.go b/pkg/migrate/8_populate_subscription_types.go index c2703d4..74801ab 100644 --- a/pkg/migrate/8_populate_subscription_types.go +++ b/pkg/migrate/8_populate_subscription_types.go @@ -3,7 +3,7 @@ package migrate import ( "fmt" "log" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "github.com/go-pg/pg/v10" ) @@ -12,16 +12,17 @@ import ( PopulateSubscriptionTypes Populates subscription_types table if it exists. - Args: - *pg.DB: Postgres database client - Returns: - error: Returns if there is an error with populating table + + Args: + *pg.DB: Postgres database client + Returns: + error: Returns if there is an error with populating table */ func PopulateSubscriptionTypes(db pg.DB) error { - daily := new(models.SubscriptionType) - weekly := new(models.SubscriptionType) - monthly := new(models.SubscriptionType) - yearly := new(models.SubscriptionType) + daily := new(model.SubscriptionType) + weekly := new(model.SubscriptionType) + monthly := new(model.SubscriptionType) + yearly := new(model.SubscriptionType) daily.Init() daily.Name = "Daily" diff --git a/pkg/migrate/9_populate_transaction_types.go b/pkg/migrate/9_populate_transaction_types.go index 7b3a27f..52dbeb9 100644 --- a/pkg/migrate/9_populate_transaction_types.go +++ b/pkg/migrate/9_populate_transaction_types.go @@ -3,7 +3,7 @@ package migrate import ( "fmt" "log" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "github.com/go-pg/pg/v10" ) @@ -12,14 +12,15 @@ import ( PopulateTransactionTypes Populates transaction_types table if it exists. - Args: - *pg.DB: Postgres database client - Returns: - error: Returns if there is an error with populating table + + Args: + *pg.DB: Postgres database client + Returns: + error: Returns if there is an error with populating table */ func PopulateTransactionTypes(db pg.DB) error { - gain := new(models.TransactionType) - expense := new(models.TransactionType) + gain := new(model.TransactionType) + expense := new(model.TransactionType) gain.Init() gain.Name = "Gain" diff --git a/pkg/migrate/migrate.go b/pkg/migrate/migrate.go index 341b841..e23444e 100644 --- a/pkg/migrate/migrate.go +++ b/pkg/migrate/migrate.go @@ -13,7 +13,7 @@ Starts database migration. Returns: error: Returns if there is an error with populating table */ -func Start(conn *pg.DB, version string) { +func Start(conn *pg.DB, version string) []error { migration001 := Migration{ Version: "001", Migrations: []interface{}{ @@ -53,16 +53,23 @@ func Start(conn *pg.DB, version string) { migration004, } + var errors []error + for _, migrationCol := range migrationsMap { if version != "" && version == migrationCol.Version || version == "" { for _, migration := range migrationCol.Migrations { mgFunc, isFunc := migration.(func(pg.DB) error) if isFunc { - mgFunc(*conn) + err := mgFunc(*conn) + if err != nil { + errors = append(errors, err) + } } } } } + + return errors } type Migration struct { diff --git a/pkg/models/api.go b/pkg/model/api.go similarity index 86% rename from pkg/models/api.go rename to pkg/model/api.go index e670a4d..787c9cc 100644 --- a/pkg/models/api.go +++ b/pkg/model/api.go @@ -1,4 +1,4 @@ -package models +package model type ApiModel struct { tableName struct{} `pg:"api,alias:api"` diff --git a/pkg/model/auth.go b/pkg/model/auth.go new file mode 100644 index 0000000..062d521 --- /dev/null +++ b/pkg/model/auth.go @@ -0,0 +1,19 @@ +package model + +type Token struct { + Token string `json:"token"` +} + +type Login struct { + Email string `json:"email" form:"email"` + Password string `json:"password" form:"password"` + RememberMe bool `json:"rememberMe" form:"rememberMe"` +} + +type Auth struct { + Id string +} + +type CheckToken struct { + Valid bool `json:"valid"` +} diff --git a/pkg/models/db.go b/pkg/model/db.go similarity index 96% rename from pkg/models/db.go rename to pkg/model/db.go index f80637a..01ad271 100644 --- a/pkg/models/db.go +++ b/pkg/model/db.go @@ -1,4 +1,4 @@ -package models +package model import ( "time" diff --git a/pkg/models/exception.go b/pkg/model/exception.go similarity index 90% rename from pkg/models/exception.go rename to pkg/model/exception.go index b5213a9..d784655 100644 --- a/pkg/models/exception.go +++ b/pkg/model/exception.go @@ -1,4 +1,4 @@ -package models +package model type Exception struct { ErrorCode string `json:"errorCode"` diff --git a/pkg/model/model.go b/pkg/model/model.go new file mode 100644 index 0000000..3faa4f0 --- /dev/null +++ b/pkg/model/model.go @@ -0,0 +1,22 @@ +package model + +import "github.com/gin-gonic/gin" + +type FilteredResponse struct { + Items interface{} `json:"items"` + Params +} + +type ResponseFunc func(*gin.Context) *[]interface{} + +type MessageResponse struct { + Message string `json:"message"` +} + +type Params struct { + SortBy string `json:"sortBy"` + Embed string `json:"embed"` + Page int `json:"page"` + Rpp int `json:"rpp"` + TotalRecords int `json:"totalRecords"` +} diff --git a/pkg/models/register.go b/pkg/model/register.go similarity index 98% rename from pkg/models/register.go rename to pkg/model/register.go index 0a90960..ff7b5f2 100644 --- a/pkg/models/register.go +++ b/pkg/model/register.go @@ -1,4 +1,4 @@ -package models +package model type User struct { tableName struct{} `pg:"users,alias:users"` @@ -20,6 +20,7 @@ type UserReturnInfo struct { Payload Maps User object to UserReturnInfo object. + Returns: *UserReturnInfo: mapped UserReturnInfo object */ diff --git a/pkg/models/subscriptions.go b/pkg/model/subscription.go similarity index 99% rename from pkg/models/subscriptions.go rename to pkg/model/subscription.go index e605a12..6229f93 100644 --- a/pkg/models/subscriptions.go +++ b/pkg/model/subscription.go @@ -1,4 +1,4 @@ -package models +package model import ( "encoding/json" @@ -53,6 +53,7 @@ type SubscriptionEnd struct { ToTrans Maps Subscription object to Transaction object. + Returns: *Transaction: mapped Transaction object */ @@ -74,6 +75,7 @@ func (cm *Subscription) ToTrans() *Transaction { HasNew Checks if Subscription reached new transaction interval. + Returns: bool: Is new transaction interval reached */ diff --git a/pkg/models/subscriptionTypes.go b/pkg/model/subscriptionType.go similarity index 95% rename from pkg/models/subscriptionTypes.go rename to pkg/model/subscriptionType.go index 84ce657..12a7cb8 100644 --- a/pkg/models/subscriptionTypes.go +++ b/pkg/model/subscriptionType.go @@ -1,4 +1,4 @@ -package models +package model type SubscriptionType struct { tableName struct{} `pg:"subscriptionTypes,alias:subscriptionTypes"` diff --git a/pkg/models/transactions.go b/pkg/model/transaction.go similarity index 99% rename from pkg/models/transactions.go rename to pkg/model/transaction.go index f177a68..9eb8ac5 100644 --- a/pkg/models/transactions.go +++ b/pkg/model/transaction.go @@ -1,4 +1,4 @@ -package models +package model import ( "encoding/json" diff --git a/pkg/models/transactionStatus.go b/pkg/model/transactionStatus.go similarity index 72% rename from pkg/models/transactionStatus.go rename to pkg/model/transactionStatus.go index 3843a42..39e50d2 100644 --- a/pkg/models/transactionStatus.go +++ b/pkg/model/transactionStatus.go @@ -1,13 +1,13 @@ -package models +package model type TransactionStatus struct { tableName struct{} `pg:"transactionStatus,alias:transactionStatus"` BaseModel - Name string `json:"name" pg:"name"` + Name string `json:"name" pg:"name"` Status string `json:"status" pg:"status,notnull"` } type NewTransactionStatusBody struct { - Name string `json:"name" form:"name"` + Name string `json:"name" form:"name"` Status string `json:"status" form:"status"` } diff --git a/pkg/models/transactionTypes.go b/pkg/model/transactionType.go similarity index 95% rename from pkg/models/transactionTypes.go rename to pkg/model/transactionType.go index 32f8958..e40ddea 100644 --- a/pkg/models/transactionTypes.go +++ b/pkg/model/transactionType.go @@ -1,4 +1,4 @@ -package models +package model type TransactionType struct { tableName struct{} `pg:"transactionTypes,alias:transactionTypes"` diff --git a/pkg/models/wallets.go b/pkg/model/wallet.go similarity index 98% rename from pkg/models/wallets.go rename to pkg/model/wallet.go index c45ed24..b0e72c6 100644 --- a/pkg/models/wallets.go +++ b/pkg/model/wallet.go @@ -1,4 +1,4 @@ -package models +package model type Wallet struct { tableName struct{} `pg:"wallets,alias:wallets"` diff --git a/pkg/models/auth.go b/pkg/models/auth.go deleted file mode 100644 index 2e04efc..0000000 --- a/pkg/models/auth.go +++ /dev/null @@ -1,19 +0,0 @@ -package models - -type Token struct { - Token string `json:"token"` -} - -type Login struct { - Email string `json:"email" form:"email"` - Password string `json:"password" form:"password"` - RememberMe bool `json:"rememberMe" form:"rememberMe"` -} - -type Auth struct { - Id string -} - -type CheckToken struct { - Valid bool `json:"valid"` -} diff --git a/pkg/models/models.go b/pkg/models/models.go deleted file mode 100644 index 6b79356..0000000 --- a/pkg/models/models.go +++ /dev/null @@ -1,22 +0,0 @@ -package models - -import "github.com/gin-gonic/gin" - -type FilteredResponse struct { - Items interface{} `json:"items"` - Params -} - -type ResponseFunc func(*gin.Context) *[]interface{} - -type MessageResponse struct { - Message string `json:"message"` -} - -type Params struct { - SortBy string `json:"sortBy"` - Embed string `json:"embed"` - Page int `json:"page"` - Rpp int `json:"rpp"` - TotalRecords int `json:"totalRecords"` -} \ No newline at end of file diff --git a/pkg/repository/api.go b/pkg/repository/api.go new file mode 100644 index 0000000..79820cb --- /dev/null +++ b/pkg/repository/api.go @@ -0,0 +1,53 @@ +package repository + +import ( + "context" + "wallet-api/pkg/migrate" + "wallet-api/pkg/model" + + "github.com/go-pg/pg/v10" +) + +type ApiRepository struct { + db *pg.DB +} + +func NewApiRepository(db *pg.DB) *ApiRepository { + return &ApiRepository{ + db: db, + } +} + +/* +GetFirst + +Gets first row from API table. + + Args: + context.Context: Application context + Returns: + model.ApiModel: Api object from database. +*/ +func (as ApiRepository) GetFirst(ctx context.Context) model.ApiModel { + db := as.db.WithContext(ctx) + apiModel := model.ApiModel{Api: "Works"} + db.Model(&apiModel).First() + return apiModel +} + +/* +PostMigrate + +Starts database migration. + + Args: + context.Context: Application context + string: Migration version + Returns: + *model.MessageResponse: Message response object. + *model.Exception: Exception response object. +*/ +func (as ApiRepository) PostMigrate(ctx context.Context, version string) []error { + db := as.db.WithContext(ctx) + return migrate.Start(db, version) +} diff --git a/pkg/repository/repository.go b/pkg/repository/repository.go new file mode 100644 index 0000000..f9e9a58 --- /dev/null +++ b/pkg/repository/repository.go @@ -0,0 +1,59 @@ +package repository + +import ( + "go.uber.org/dig" + "wallet-api/pkg/model" + "wallet-api/pkg/utl/common" + + "github.com/go-pg/pg/v10" +) + +/* +InitializeRepositories + +Initializes Dependency Injection modules for repositories + + Args: + *dig.Container: Dig Container +*/ +func InitializeRepositories(c *dig.Container) { + c.Provide(NewApiRepository) + c.Provide(NewSubscriptionRepository) + c.Provide(NewSubscriptionTypeRepository) + c.Provide(NewTransactionRepository) + c.Provide(NewTransactionStatusRepository) + c.Provide(NewTransactionTypeRepository) + c.Provide(NewUserRepository) + c.Provide(NewWalletRepository) +} + +/* +FilteredResponse + +Adds filters to query and executes it. + + Args: + *pg.Query: postgres query + interface{}: model to be mapped from query execution. + *model.FilteredResponse: filter options. +*/ +func FilteredResponse(qry *pg.Query, mdl interface{}, filtered *model.FilteredResponse) error { + if filtered.Page == 0 { + filtered.Page = 1 + } + if filtered.Rpp == 0 { + filtered.Rpp = 20 + } + if filtered.SortBy == "" { + filtered.SortBy = "date_created DESC" + } + qry = qry.Limit(filtered.Rpp).Offset((filtered.Page - 1) * filtered.Rpp).Order(filtered.SortBy) + common.GenerateEmbed(qry, filtered.Embed) + count, err := qry.SelectAndCount() + common.CheckError(err) + + filtered.TotalRecords = count + filtered.Items = mdl + + return err +} diff --git a/pkg/repository/subscription.go b/pkg/repository/subscription.go new file mode 100644 index 0000000..ae0dfb8 --- /dev/null +++ b/pkg/repository/subscription.go @@ -0,0 +1,280 @@ +package repository + +import ( + "context" + "fmt" + "github.com/go-pg/pg/v10/orm" + "time" + "wallet-api/pkg/filter" + "wallet-api/pkg/model" + "wallet-api/pkg/utl/common" + + "github.com/go-pg/pg/v10" +) + +type SubscriptionRepository struct { + db *pg.DB +} + +func NewSubscriptionRepository(db *pg.DB) *SubscriptionRepository { + return &SubscriptionRepository{ + db: db, + } +} + +/* +New + +Inserts new row to subscription table. + + Args: + context.Context: Application context + *model.NewSubscriptionBody: Request body + Returns: + *model.Subscription: Created Subscription row object from database. + *model.Exception: Exception payload. +*/ +func (as *SubscriptionRepository) New(ctx context.Context, tm *model.Subscription) (*model.Subscription, error) { + db := as.db.WithContext(ctx) + + tx, _ := db.Begin() + defer tx.Rollback() + + _, err := tx.Model(tm).Insert() + if err != nil { + return nil, err + } + tx.Commit() + + return tm, nil +} + +/* +Get + +Gets row from subscription table by id. + + Args: + context.Context: Application context + *model.Auth: Authentication model + string: subscription id to search + params: *model.Params + Returns: + *model.Subscription: Subscription row object from database. + *model.Exception: Exception payload. +*/ +func (as *SubscriptionRepository) Get(ctx context.Context, am *model.Subscription, flt filter.SubscriptionFilter) (*model.Subscription, error) { + db := as.db.WithContext(ctx) + tx, _ := db.Begin() + defer tx.Rollback() + + qry := tx.Model(am) + as.OnBeforeGetSubscriptionFilter(qry, &flt) + err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select() + if err != nil { + return nil, err + } + + tx.Commit() + + return am, nil +} + +/* +GetAll + +Gets filtered rows from subscription table. + + Args: + context.Context: Application context + *model.Auth: Authentication object + string: Wallet id to search + *model.FilteredResponse: filter options + Returns: + *model.Exception: Exception payload. +*/ +func (as *SubscriptionRepository) GetAll(ctx context.Context, am *[]model.Subscription, filtered *model.FilteredResponse, flt *filter.SubscriptionFilter) error { + db := as.db.WithContext(ctx) + + tx, _ := db.Begin() + defer tx.Rollback() + + query := tx.Model(am) + as.OnBeforeGetSubscriptionFilter(query, flt) + + err := FilteredResponse(query, am, filtered) + if err != nil { + return err + } + tx.Commit() + + return nil +} + +/* +GetAllTx + +Gets filtered rows from subscription table. + + Args: + context.Context: Application context + *model.Auth: Authentication object + string: Wallet id to search + *model.FilteredResponse: filter options + Returns: + *model.Exception: Exception payload. +*/ +func (as *SubscriptionRepository) GetAllTx(tx *pg.Tx, am *[]model.Subscription, flt *filter.SubscriptionFilter) error { + query := tx.Model(am) + as.OnBeforeGetSubscriptionFilter(query, flt) + + err := query.Select() + if err != nil { + return err + } + tx.Commit() + + return nil +} + +/* +Edit + +Updates row from subscription table by id. + + Args: + context.Context: Application context + *model.SubscriptionEdit: Values to edit + string: id to search + Returns: + *model.Subscription: Edited Subscription row object from database. + *model.Exception: Exception payload. +*/ +func (as *SubscriptionRepository) Edit(ctx context.Context, tm *model.Subscription) (*model.Subscription, error) { + db := as.db.WithContext(ctx) + + tx, _ := db.Begin() + defer tx.Rollback() + + _, err := tx.Model(tm).WherePK().UpdateNotZero() + if err != nil { + return nil, err + } + + tx.Commit() + + return tm, nil +} + +/* +End + +Updates row in subscription table by id. + +Ends subscription with current date. + + Args: + context.Context: Application context + string: id to search + Returns: + *model.Subscription: Created Subscription row object from database. + *model.Exception: Exception payload. +*/ +func (as *SubscriptionRepository) End(ctx context.Context, tm *model.Subscription) (*model.Subscription, error) { + db := as.db.WithContext(ctx) + + tx, _ := db.Begin() + defer tx.Rollback() + + _, err := tx.Model(tm).WherePK().UpdateNotZero() + if err != nil { + return nil, err + } + + tx.Commit() + + return tm, nil +} + +/* +SubToTrans + +Generates and Inserts new Transaction rows from the subscription model. + + Args: + *model.Subscription: Subscription model to generate new transactions from + *pg.Tx: Postgres query context + Returns: + *model.Exception: Exception payload. +*/ +func (as *SubscriptionRepository) SubToTrans(subModel *model.Subscription, tx *pg.Tx) *model.Exception { + exceptionReturn := new(model.Exception) + + now := time.Now() + + currentYear, currentMonth, _ := now.Date() + currentLocation := now.Location() + + transactionStatus := new(model.TransactionStatus) + firstOfNextMonth := time.Date(currentYear, currentMonth+1, 1, 0, 0, 0, 0, currentLocation) + tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "pending").Select() + //tzFirstOfNextMonth := firstOfNextMonth.In(subModel.StartDate.Location()) + + startDate := subModel.StartDate + stopDate := firstOfNextMonth + if subModel.HasEnd && subModel.EndDate.Before(firstOfNextMonth) { + stopDate = subModel.EndDate + } + + transactions := new([]model.Transaction) + + if subModel.SubscriptionType == nil { + st := new(model.SubscriptionType) + tx.Model(st).Where("? = ?", pg.Ident("id"), subModel.SubscriptionTypeID).Select() + subModel.SubscriptionType = st + } + + for startDate.Before(stopDate) { + trans := subModel.ToTrans() + trans.TransactionDate = startDate + trans.TransactionStatusID = transactionStatus.Id + if startDate.After(subModel.LastTransactionDate) && (startDate.Before(now) || startDate.Equal(now)) { + *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) + } + } + + var err error + if len(*transactions) > 0 { + for _, trans := range *transactions { + _, err = tx.Model(&trans).Where("? = ?", pg.Ident("transaction_date"), trans.TransactionDate).Where("? = ?", pg.Ident("subscription_id"), trans.SubscriptionID).OnConflict("DO NOTHING").SelectOrInsert() + if err != nil { + _, err = tx.Model(subModel).Set("? = ?", pg.Ident("last_transaction_date"), trans.TransactionDate).WherePK().Update() + } + } + } + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400113" + exceptionReturn.Message = fmt.Sprintf("Error updating row in \"subscription\" table: %s", err) + return exceptionReturn + } + return nil +} + +func (as *SubscriptionRepository) OnBeforeGetSubscriptionFilter(qry *orm.Query, flt *filter.SubscriptionFilter) { + if flt.Id != "" { + qry.Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), flt.Id) + } + if flt.WalletId != "" { + qry.Where("? = ?", pg.Ident("wallet_id"), flt.WalletId) + } +} diff --git a/pkg/repository/subscriptionType.go b/pkg/repository/subscriptionType.go new file mode 100644 index 0000000..3c37301 --- /dev/null +++ b/pkg/repository/subscriptionType.go @@ -0,0 +1,67 @@ +package repository + +import ( + "context" + "wallet-api/pkg/filter" + "wallet-api/pkg/model" + "wallet-api/pkg/utl/common" + + "github.com/go-pg/pg/v10" +) + +type SubscriptionTypeRepository struct { + db *pg.DB +} + +func NewSubscriptionTypeRepository(db *pg.DB) *SubscriptionTypeRepository { + return &SubscriptionTypeRepository{ + db: db, + } +} + +/* +New + +Inserts new row to subscription type table. + + Args: + context.Context: Application context + *model.NewSubscriptionTypeBody: Values to create new row + Returns: + *model.SubscriptionType: Created row from database. + *model.Exception: Exception payload. +*/ +func (as *SubscriptionTypeRepository) New(ctx context.Context, tm *model.SubscriptionType) (*model.SubscriptionType, error) { + db := as.db.WithContext(ctx) + + _, err := db.Model(tm).Insert() + if err != nil { + return nil, err + } + + return tm, nil +} + +/* +GetAll + +Gets all rows from subscription type table. + + Args: + context.Context: Application context + string: Relations to embed + Returns: + *[]model.SubscriptionType: List of subscription type objects. + *model.Exception: Exception payload. +*/ +func (as *SubscriptionTypeRepository) GetAll(ctx context.Context, flt *filter.SubscriptionTypeFilter, wm *[]model.SubscriptionType) (*[]model.SubscriptionType, error) { + db := as.db.WithContext(ctx) + + query := db.Model(wm) + err := common.GenerateEmbed(query, flt.Embed).Select() + if err != nil { + return nil, err + } + + return wm, nil +} diff --git a/pkg/repository/transaction.go b/pkg/repository/transaction.go new file mode 100644 index 0000000..740c37e --- /dev/null +++ b/pkg/repository/transaction.go @@ -0,0 +1,268 @@ +package repository + +import ( + "context" + "fmt" + "github.com/go-pg/pg/v10/orm" + "wallet-api/pkg/filter" + "wallet-api/pkg/model" + "wallet-api/pkg/utl/common" + + "github.com/go-pg/pg/v10" +) + +type TransactionRepository struct { + db *pg.DB + subscriptionRepository *SubscriptionRepository + transactionStatusRepository *TransactionStatusRepository +} + +func NewTransactionRepository(db *pg.DB, ss *SubscriptionRepository, tsr *TransactionStatusRepository) *TransactionRepository { + return &TransactionRepository{ + db: db, + subscriptionRepository: ss, + transactionStatusRepository: tsr, + } +} + +/* +New row into transaction table + +Inserts + + Args: + context.Context: Application context + *model.NewTransactionBody: Transaction body object + Returns: + *model.Transaction: Transaction object + *model.Exception: Exception payload. +*/ +func (as *TransactionRepository) New(ctx context.Context, tm *model.Transaction) (*model.Transaction, error) { + db := as.db.WithContext(ctx) + + tx, _ := db.Begin() + defer tx.Rollback() + + _, err := tx.Model(tm).Insert() + if err != nil { + return nil, err + } + tx.Commit() + + return tm, nil +} + +/* +GetAll + +Gets all rows from subscription type table. + Args: + context.Context: Application context + string: Relations to embed + Returns: + *model.Exception: Exception payload. +*/ +// Gets filtered rows from transaction table. +func (as *TransactionRepository) GetAll(ctx context.Context, filtered *model.FilteredResponse, flt *filter.TransactionFilter) *model.Exception { + db := as.db.WithContext(ctx) + + exceptionReturn := new(model.Exception) + wm := new([]model.Transaction) + transactionStatus := new(model.TransactionStatus) + + tx, _ := db.Begin() + defer tx.Rollback() + + tsFlt := filter.NewTransactionStatusFilter(model.Params{}) + tsFlt.Status = "completed" + _, err := as.transactionStatusRepository.GetTx(tx, transactionStatus, tsFlt) + + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400117" + exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatus\" table: %s", err) + return exceptionReturn + } + + flt.TransactionStatusId = transactionStatus.Id + + query := tx.Model(wm) + + as.OnBeforeGetTransactionFilter(query, flt) + err = FilteredResponse(query, wm, filtered) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400118" + exceptionReturn.Message = fmt.Sprintf("Error selecting row(s) in \"transaction\" table: %s", err) + return exceptionReturn + } + + tx.Commit() + return nil +} + +/* +Check + +Checks subscriptions and create transacitons. + Args: + context.Context: Application context + string: Relations to embed + Returns: + *model.Exception: Exception payload. +*/ +// Gets filtered rows from transaction table. +func (as *TransactionRepository) Check(ctx context.Context, filtered *model.FilteredResponse, flt *filter.TransactionFilter) *model.Exception { + db := as.db.WithContext(ctx) + + wm := new([]model.Transaction) + sm := new([]model.Subscription) + transactionStatus := new(model.TransactionStatus) + exceptionReturn := new(model.Exception) + + tx, _ := db.Begin() + defer tx.Rollback() + + tsFlt := filter.NewTransactionStatusFilter(model.Params{}) + tsFlt.Status = "pending" + _, err := as.transactionStatusRepository.GetTx(tx, transactionStatus, tsFlt) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400119" + exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatus\" table: %s", err) + return exceptionReturn + } + flt.TransactionStatusId = transactionStatus.Id + + smFlt := filter.NewSubscriptionFilter(model.Params{}) + smFlt.Id = flt.Id + smFlt.WalletId = flt.WalletId + as.subscriptionRepository.GetAllTx(tx, sm, smFlt) + + for _, sub := range *sm { + if sub.HasNew() { + as.subscriptionRepository.SubToTrans(&sub, tx) + } + } + + qry := tx.Model(wm) + as.OnBeforeGetTransactionFilter(qry, flt) + err = FilteredResponse(qry, wm, filtered) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400120" + exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transaction\" table: %s", err) + return exceptionReturn + } + + tx.Commit() + return nil +} + +/* +Edit + +Updates row in transaction table by id. + + Args: + context.Context: Application context + *model.TransactionEdit: Object to edit + string: id to search + Returns: + *model.Transaction: Transaction object from database. + *model.Exception: Exception payload. +*/ +func (as *TransactionRepository) Edit(ctx context.Context, tm *model.Transaction) (*model.Transaction, error) { + db := as.db.WithContext(ctx) + + tx, _ := db.Begin() + defer tx.Rollback() + + _, err := tx.Model(tm).WherePK().UpdateNotZero() + + if err != nil { + return nil, err + } + + err = tx.Model(tm).WherePK().Select() + if err != nil { + return nil, err + } + + tx.Commit() + + return tm, nil +} + +/* +Bulk Edit + +Updates row in transaction table by id. + + Args: + context.Context: Application context + ?[]model.Transaction Bulk Edit: Object to edit + string: id to search + Returns: + *model.Transaction: Transaction object from database. + *model.Exception: Exception payload. +*/ +func (as *TransactionRepository) BulkEdit(ctx context.Context, transactions *[]model.Transaction) (*[]model.Transaction, error) { + db := as.db.WithContext(ctx) + tx, _ := db.Begin() + defer tx.Rollback() + + _, err := tx.Model(transactions).WherePK().UpdateNotZero() + if err != nil { + return nil, err + } + + tx.Commit() + + return transactions, nil +} + +/* +Get + +Gets row from transaction table by id. + + Args: + context.Context: Application context + *model.Auth: Authentication object + string: id to search + *model.Params: url query parameters + Returns: + *model.Transaction: Transaction object from database. + *model.Exception: Exception payload. +*/ +func (as *TransactionRepository) Get(ctx context.Context, flt *filter.TransactionFilter) (*model.Transaction, error) { + db := as.db.WithContext(ctx) + wm := new(model.Transaction) + + tx, _ := db.Begin() + defer tx.Rollback() + + qry := tx.Model(wm) + as.OnBeforeGetTransactionFilter(qry, flt) + err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select() + if err != nil { + return nil, err + } + + tx.Commit() + + return wm, nil +} + +func (as *TransactionRepository) OnBeforeGetTransactionFilter(qry *orm.Query, flt *filter.TransactionFilter) { + if flt.WalletId != "" { + qry.Where("? = ?", pg.Ident("wallet_id"), flt.WalletId) + } + if flt.Id != "" { + qry.Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), flt.Id) + } + if flt.NoPending && flt.TransactionStatusId != "" { + qry.Where("? = ?", pg.Ident("transaction_status_id"), flt.TransactionStatusId) + } +} diff --git a/pkg/repository/transactionStatus.go b/pkg/repository/transactionStatus.go new file mode 100644 index 0000000..1fdf042 --- /dev/null +++ b/pkg/repository/transactionStatus.go @@ -0,0 +1,146 @@ +package repository + +import ( + "context" + "fmt" + "github.com/go-pg/pg/v10/orm" + "wallet-api/pkg/filter" + "wallet-api/pkg/model" + "wallet-api/pkg/utl/common" + + "github.com/go-pg/pg/v10" +) + +type TransactionStatusRepository struct { + db *pg.DB +} + +func NewTransactionStatusRepository(db *pg.DB) *TransactionStatusRepository { + return &TransactionStatusRepository{ + db: db, + } +} + +/* +New + +Inserts new row to transaction status table. + + Args: + context.Context: Application context + *model.NewTransactionStatusBody: object to create + Returns: + *model.TransactionType: Transaction Type object from database. + *model.Exception: Exception payload. +*/ +func (as *TransactionStatusRepository) New(ctx context.Context, body *model.NewTransactionStatusBody) (*model.TransactionStatus, *model.Exception) { + db := as.db.WithContext(ctx) + + tm := new(model.TransactionStatus) + exceptionReturn := new(model.Exception) + + tm.Init() + tm.Name = body.Name + tm.Status = body.Status + + _, err := db.Model(tm).Insert() + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400123" + exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"transactionStatus\" table: %s", err) + return nil, exceptionReturn + } + + return tm, nil +} + +/* +GetAll + +Gets all rows from transaction status table. + + Args: + context.Context: Application context + string: Relations to embed + Returns: + *[]model.TransactionStatus: List of Transaction status objects from database. + *model.Exception: Exception payload. +*/ +func (as *TransactionStatusRepository) GetAll(ctx context.Context, embed string) (*[]model.TransactionStatus, *model.Exception) { + db := as.db.WithContext(ctx) + + wm := new([]model.TransactionStatus) + exceptionReturn := new(model.Exception) + + query := db.Model(wm) + err := common.GenerateEmbed(query, embed).Select() + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400124" + exceptionReturn.Message = fmt.Sprintf("Error selecting rows in \"transactionStatus\" table: %s", err) + return nil, exceptionReturn + } + + return wm, nil +} + +/* +Get + +Gets row from transactionStatus table by id. + + Args: + context.Context: Application context + *model.Auth: Authentication model + string: transactionStatus id to search + params: *model.Params + Returns: + *model.Subscription: Subscription row object from database. + *model.Exception: Exception payload. +*/ +func (as *TransactionStatusRepository) Get(ctx context.Context, am *model.TransactionStatus, flt filter.TransactionStatusFilter) (*model.TransactionStatus, error) { + db := as.db.WithContext(ctx) + tx, _ := db.Begin() + defer tx.Rollback() + + qry := tx.Model(am) + err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select() + if err != nil { + return nil, err + } + + tx.Commit() + + return am, nil +} + +/* +GetTx + +Gets row from transactionStatus table by id. + + Args: + context.Context: Application context + *model.Auth: Authentication model + string: transactionStatus id to search + params: *model.Params + Returns: + *model.Subscription: Subscription row object from database. + *model.Exception: Exception payload. +*/ +func (as *TransactionStatusRepository) GetTx(tx *pg.Tx, am *model.TransactionStatus, flt *filter.TransactionStatusFilter) (*model.TransactionStatus, error) { + qry := tx.Model(am) + as.OnBeforeGetTransactionStatusFilter(qry, flt) + err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select() + if err != nil { + return nil, err + } + + return am, nil +} + +func (as *TransactionStatusRepository) OnBeforeGetTransactionStatusFilter(qry *orm.Query, flt *filter.TransactionStatusFilter) { + if flt.Status != "" { + qry.Where("? = ?", pg.Ident("status"), flt.Status) + } +} diff --git a/pkg/repository/transactionType.go b/pkg/repository/transactionType.go new file mode 100644 index 0000000..6ed029f --- /dev/null +++ b/pkg/repository/transactionType.go @@ -0,0 +1,83 @@ +package repository + +import ( + "context" + "fmt" + "wallet-api/pkg/model" + "wallet-api/pkg/utl/common" + + "github.com/go-pg/pg/v10" +) + +type TransactionTypeRepository struct { + db *pg.DB +} + +func NewTransactionTypeRepository(db *pg.DB) *TransactionTypeRepository { + return &TransactionTypeRepository{ + db: db, + } +} + +/* +New + +Inserts new row to transaction type table. + + Args: + context.Context: Application context + *model.NewTransactionTypeBody: object to create + Returns: + *model.TransactionType: Transaction Type object from database. + *model.Exception: Exception payload. +*/ +func (as *TransactionTypeRepository) New(ctx context.Context, body *model.NewTransactionTypeBody) (*model.TransactionType, *model.Exception) { + db := as.db.WithContext(ctx) + + tm := new(model.TransactionType) + exceptionReturn := new(model.Exception) + + tm.Init() + tm.Name = body.Name + tm.Type = body.Type + + _, err := db.Model(tm).Insert() + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400125" + exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"transactionTypes\" table: %s", err) + return nil, exceptionReturn + } + + return tm, nil +} + +/* +GetAll + +Gets all rows from transaction type table. + + Args: + context.Context: Application context + string: Relations to embed + Returns: + *[]model.TransactionType: List of Transaction type objects from database. + *model.Exception: Exception payload. +*/ +func (as *TransactionTypeRepository) GetAll(ctx context.Context, embed string) (*[]model.TransactionType, *model.Exception) { + db := as.db.WithContext(ctx) + + wm := new([]model.TransactionType) + exceptionReturn := new(model.Exception) + + query := db.Model(wm) + err := common.GenerateEmbed(query, embed).Select() + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400133" + exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionTypes\" table: %s", err) + return nil, exceptionReturn + } + + return wm, nil +} diff --git a/pkg/services/users.go b/pkg/repository/user.go similarity index 76% rename from pkg/services/users.go rename to pkg/repository/user.go index 577b1d3..b27eb51 100644 --- a/pkg/services/users.go +++ b/pkg/repository/user.go @@ -1,10 +1,10 @@ -package services +package repository import ( "context" "os" "time" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "wallet-api/pkg/utl/common" "wallet-api/pkg/utl/configs" @@ -14,12 +14,12 @@ import ( "github.com/go-pg/pg/v10" ) -type UsersService struct { +type UserRepository struct { db *pg.DB } -func NewUsersService(db *pg.DB) *UsersService { - return &UsersService{ +func NewUserRepository(db *pg.DB) *UserRepository { + return &UserRepository{ db: db, } } @@ -31,16 +31,16 @@ Inserts new row to users table. Args: context.Context: Application context - *models.User: User object to create + *model.User: User object to create Returns: - *models.User: User object from database - *models.Exception + *model.User: User object from database + *model.Exception */ -func (us *UsersService) Create(ctx context.Context, registerBody *models.User) (*models.User, *models.Exception) { +func (us *UserRepository) Create(ctx context.Context, registerBody *model.User) (*model.User, *model.Exception) { db := us.db.WithContext(ctx) - check := new(models.User) - exceptionReturn := new(models.Exception) + check := new(model.User) + exceptionReturn := new(model.Exception) tx, _ := db.Begin() defer tx.Rollback() @@ -77,17 +77,17 @@ Gets row from users table by email and valid password. Args: context.Context: Application context - *models.Login: object to search + *model.Login: object to search Returns: - *models.Token: new session token - *models.Exception + *model.Token: new session token + *model.Exception */ -func (us *UsersService) Login(ctx context.Context, loginBody *models.Login) (*models.Token, *models.Exception) { +func (us *UserRepository) Login(ctx context.Context, loginBody *model.Login) (*model.Token, *model.Exception) { db := us.db.WithContext(ctx) - check := new(models.User) - exceptionReturn := new(models.Exception) - tokenPayload := new(models.Token) + check := new(model.User) + exceptionReturn := new(model.Exception) + tokenPayload := new(model.Token) tx, _ := db.Begin() defer tx.Rollback() @@ -134,17 +134,17 @@ IsActive column is set to false Args: context.Context: Application context - *models.Auth: Authentication object + *model.Auth: Authentication object Returns: - *models.MessageResponse - *models.Exception + *model.MessageResponse + *model.Exception */ -func (us *UsersService) Deactivate(ctx context.Context, auth *models.Auth) (*models.MessageResponse, *models.Exception) { +func (us *UserRepository) Deactivate(ctx context.Context, auth *model.Auth) (*model.MessageResponse, *model.Exception) { db := us.db.WithContext(ctx) - mm := new(models.MessageResponse) - me := new(models.Exception) - um := new(models.User) + mm := new(model.MessageResponse) + me := new(model.Exception) + um := new(model.User) tx, _ := db.Begin() defer tx.Rollback() @@ -182,13 +182,13 @@ Generates new jwt token. It encodes the user id. Based on rememberMe it is valid through 48hours or 2hours. Args: - *models.User: User object to encode + *model.User: User object to encode bool: Should function generate longer lasting token (48hrs) Returns: string: Generated token error: Error that occured in the process */ -func CreateToken(user *models.User, rememberMe bool) (string, error) { +func CreateToken(user *model.User, rememberMe bool) (string, error) { atClaims := jwt.MapClaims{} atClaims["authorized"] = true atClaims["id"] = user.Id diff --git a/pkg/repository/wallet.go b/pkg/repository/wallet.go new file mode 100644 index 0000000..ea983ee --- /dev/null +++ b/pkg/repository/wallet.go @@ -0,0 +1,323 @@ +package repository + +import ( + "context" + "fmt" + "time" + "wallet-api/pkg/model" + "wallet-api/pkg/utl/common" + + "github.com/go-pg/pg/v10" +) + +type WalletRepository struct { + db *pg.DB + subscriptionRepository *SubscriptionRepository +} + +func NewWalletRepository(db *pg.DB, ss *SubscriptionRepository) *WalletRepository { + return &WalletRepository{ + db: db, + subscriptionRepository: ss, + } +} + +/* +New + +Inserts row to wallets table. + + Args: + context.Context: Application context + *model.NewWalletBody: Object to be inserted + Returns: + *model.Wallet: Wallet object from database. + *model.Exception: Exception payload. +*/ +func (as *WalletRepository) New(ctx context.Context, am *model.NewWalletBody) (*model.Wallet, *model.Exception) { + db := as.db.WithContext(ctx) + + exceptionReturn := new(model.Exception) + walletModel := new(model.Wallet) + walletModel.Init() + walletModel.UserID = am.UserID + walletModel.Name = am.Name + _, err := db.Model(walletModel).Insert() + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400126" + exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"wallets\" table: %s", err) + return nil, exceptionReturn + } + return walletModel, nil +} + +/* +Edit + +Updates row in wallets table by id. + + Args: + context.Context: Application context + *model.WalletEdit: Object to be edited + string: id to search + Returns: + *model.Wallet: Wallet object from database. + *model.Exception: Exception payload. +*/ +func (as *WalletRepository) Edit(ctx context.Context, body *model.WalletEdit, id string) (*model.Wallet, *model.Exception) { + db := as.db.WithContext(ctx) + + exceptionReturn := new(model.Exception) + tm := new(model.Wallet) + tm.Id = id + tm.Name = body.Name + + tx, _ := db.Begin() + defer tx.Rollback() + + _, err := tx.Model(tm).WherePK().UpdateNotZero() + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400127" + exceptionReturn.Message = fmt.Sprintf("Error updating row in \"wallets\" table: %s", err) + return nil, exceptionReturn + } + + tx.Commit() + + return tm, nil +} + +/* +Get + +Gets row in wallets table by id. + + Args: + context.Context: Application context + string: id to search + *model.Params: url query parameters + Returns: + *model.Wallet: Wallet object from database + *model.Exception: Exception payload. +*/ +func (as *WalletRepository) Get(ctx context.Context, id string, params *model.Params) (*model.Wallet, *model.Exception) { + db := as.db.WithContext(ctx) + exceptionReturn := new(model.Exception) + + wm := new(model.Wallet) + wm.Id = id + + tx, _ := db.Begin() + defer tx.Rollback() + + qry := tx.Model(wm) + err := common.GenerateEmbed(qry, params.Embed).WherePK().Select() + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400128" + exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"wallets\" table: %s", err) + return nil, exceptionReturn + } + + tx.Commit() + + return wm, nil +} + +/* +GetAll + +Gets filtered rows from wallets table. + + Args: + context.Context: Application context + *model.Auth: Authentication object + *model.FilteredResponse: filter options + Returns: + *model.Exception: Exception payload. +*/ +func (as *WalletRepository) GetAll(ctx context.Context, am *model.Auth, filtered *model.FilteredResponse) *model.Exception { + exceptionReturn := new(model.Exception) + db := as.db.WithContext(ctx) + wm := new([]model.Wallet) + + query := db.Model(wm).Where("? = ?", pg.Ident("user_id"), am.Id) + err := FilteredResponse(query, wm, filtered) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400134" + exceptionReturn.Message = fmt.Sprintf("Error selecting rows in \"wallets\" table: %s", err) + return exceptionReturn + } + return nil +} + +/* +GetHeader + +Gets row from wallets table. + +Calculates previous month, current and next month totals. + + Args: + context.Context: Application context + *model.Auth: Authentication object + string: wallet id to search + Returns: + *model.WalletHeader: generated wallet header object + *model.Exception: Exception payload. +*/ +func (as *WalletRepository) GetHeader(ctx context.Context, am *model.Auth, walletId string) (*model.WalletHeader, *model.Exception) { + db := as.db.WithContext(ctx) + + wm := new(model.WalletHeader) + wallets := new([]model.WalletTransactions) + transactions := new([]model.Transaction) + subscriptions := new([]model.Subscription) + transactionStatus := new(model.TransactionStatus) + exceptionReturn := new(model.Exception) + + tx, _ := db.Begin() + defer tx.Rollback() + + err := tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "completed").Select() + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400130" + exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatuses\" table: %s", err) + return nil, exceptionReturn + } + query2 := tx.Model(subscriptions).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id).Relation("TransactionType").Relation("SubscriptionType") + if walletId != "" { + query2.Where("? = ?", pg.Ident("wallet_id"), walletId) + } + query2.Select() + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400131" + exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"subscriptions\" table: %s", err) + return nil, exceptionReturn + } + + now := time.Now() + + currentYear, currentMonth, _ := now.Date() + currentLocation := now.Location() + + firstOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, currentLocation) + firstOfNextMonth := time.Date(currentYear, currentMonth+1, 1, 0, 0, 0, 0, currentLocation) + firstOfMonthAfterNext := time.Date(currentYear, currentMonth+2, 1, 0, 0, 0, 0, currentLocation) + + query := tx.Model(transactions).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id).Relation("TransactionType") + if walletId != "" { + query.Where("? = ?", pg.Ident("wallet_id"), walletId) + } + query = query.Where("? = ?", pg.Ident("transaction_status_id"), transactionStatus.Id) + query.Select() + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400132" + exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactions\" table: %s", err) + return nil, exceptionReturn + } + tx.Commit() + + for _, sub := range *subscriptions { + stopDate := firstOfMonthAfterNext + if sub.HasEnd && sub.EndDate.Before(firstOfMonthAfterNext) { + stopDate = sub.EndDate + } + startDate := sub.StartDate + for startDate.Before(stopDate) { + trans := sub.ToTrans() + trans.TransactionDate = startDate + if startDate.After(firstOfNextMonth) || startDate.Equal(firstOfNextMonth) { + *transactions = append(*transactions, *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 _, trans := range *transactions { + addWhere(wallets, trans.WalletID, trans) + } + + for i, wallet := range *wallets { + for _, trans := range wallet.Transactions { + // tzFirstOfMonthAfterNext := firstOfMonthAfterNext.In(trans.TransactionDate.Location()) + // tzFirstOfNextMonth := firstOfNextMonth.In(trans.TransactionDate.Location()) + // tzFirstOfMonth := firstOfMonth.In(trans.TransactionDate.Location()) + if trans.TransactionDate.Before(firstOfNextMonth) && trans.TransactionDate.After(firstOfMonth) || trans.TransactionDate.Equal(firstOfMonth) { + if trans.TransactionType.Type == "expense" { + (*wallets)[i].CurrentBalance -= trans.Amount + } else { + (*wallets)[i].CurrentBalance += trans.Amount + } + } else if trans.TransactionDate.Before(firstOfMonthAfterNext) && trans.TransactionDate.After(firstOfNextMonth) { + if trans.TransactionType.Type == "expense" { + (*wallets)[i].NextMonth -= trans.Amount + } else { + (*wallets)[i].NextMonth += trans.Amount + } + } else if trans.TransactionDate.Before(firstOfMonth) { + if trans.TransactionType.Type == "expense" { + (*wallets)[i].LastMonth -= trans.Amount + } else { + (*wallets)[i].LastMonth += trans.Amount + } + } + + } + } + + for _, wallet := range *wallets { + wm.LastMonth += wallet.LastMonth + wm.CurrentBalance += wallet.CurrentBalance + wallet.LastMonth + wm.NextMonth += wallet.NextMonth + wallet.CurrentBalance + wallet.LastMonth + } + + wm.Currency = "USD" + wm.WalletId = walletId + + return wm, nil +} + +/* +addWhere + +Appends Transaction to the belonging walletId. + +If missing, it creates the item list. + + Args: + *[]model.WalletTransactions: list to append to + string: wallet id to check + model.Transaction: Transaction to append + Returns: + *model.Exception: Exception payload. +*/ +func addWhere(s *[]model.WalletTransactions, walletId string, e model.Transaction) { + var exists bool + for a := range *s { + if (*s)[a].WalletId == walletId { + (*s)[a].Transactions = append((*s)[a].Transactions, e) + exists = true + } + } + if !exists { + var walletTransaction model.WalletTransactions + walletTransaction.WalletId = walletId + walletTransaction.Transactions = append(walletTransaction.Transactions, e) + *s = append(*s, walletTransaction) + } +} diff --git a/pkg/service/api.go b/pkg/service/api.go new file mode 100644 index 0000000..4aa8d96 --- /dev/null +++ b/pkg/service/api.go @@ -0,0 +1,47 @@ +package service + +import ( + "context" + "wallet-api/pkg/model" + "wallet-api/pkg/repository" +) + +type ApiService struct { + repository *repository.ApiRepository +} + +func NewApiService(repository *repository.ApiRepository) *ApiService { + return &ApiService{ + repository, + } +} + +/* +GetFirst + +Gets first row from API table. + + Args: + context.Context: Application context + Returns: + model.ApiModel: Api object from database. +*/ +func (as ApiService) GetFirst(ctx context.Context) model.ApiModel { + return as.repository.GetFirst(ctx) +} + +/* +PostMigrate + +Starts database migration. + + Args: + context.Context: Application context + string: Migration version + Returns: + *model.MessageResponse: Message response object. + *model.Exception: Exception response object. +*/ +func (as ApiService) PostMigrate(ctx context.Context, version string) (*model.MessageResponse, *model.Exception) { + return as.repository.PostMigrate(ctx, version) +} diff --git a/pkg/service/service.go b/pkg/service/service.go new file mode 100644 index 0000000..5639788 --- /dev/null +++ b/pkg/service/service.go @@ -0,0 +1,27 @@ +package service + +import ( + "go.uber.org/dig" + "wallet-api/pkg/repository" +) + +/* +InitializeServices + +Initializes Dependency Injection modules for services + + Args: + *dig.Container: Dig Container +*/ +func InitializeServices(c *dig.Container) { + repository.InitializeRepositories(c) + + c.Provide(NewApiService) + c.Provide(NewSubscriptionService) + c.Provide(NewSubscriptionTypeService) + c.Provide(NewTransactionService) + c.Provide(NewTransactionStatusService) + c.Provide(NewTransactionTypeService) + c.Provide(NewUserService) + c.Provide(NewWalletService) +} diff --git a/pkg/service/subscription.go b/pkg/service/subscription.go new file mode 100644 index 0000000..adf42e3 --- /dev/null +++ b/pkg/service/subscription.go @@ -0,0 +1,192 @@ +package service + +import ( + "context" + "fmt" + "math" + "time" + "wallet-api/pkg/filter" + "wallet-api/pkg/model" + "wallet-api/pkg/repository" +) + +type SubscriptionService struct { + repository *repository.SubscriptionRepository +} + +func NewSubscriptionService(repository *repository.SubscriptionRepository) *SubscriptionService { + return &SubscriptionService{ + repository, + } +} + +/* +New + +Inserts new row to subscription table. + + Args: + context.Context: Application context + *model.NewSubscriptionBody: Request body + Returns: + *model.Subscription: Created Subscription row object from database. + *model.Exception: Exception payload. +*/ +func (as *SubscriptionService) New(ctx context.Context, body *model.NewSubscriptionBody) (*model.Subscription, *model.Exception) { + tm := new(model.Subscription) + exceptionReturn := new(model.Exception) + + amount, _ := body.Amount.Float64() + customRange, _ := body.CustomRange.Int64() + + tm.Init() + tm.WalletID = body.WalletID + tm.TransactionTypeID = body.TransactionTypeID + tm.SubscriptionTypeID = body.SubscriptionTypeID + tm.CustomRange = int(customRange) + tm.Description = body.Description + tm.StartDate = body.StartDate + tm.HasEnd = body.HasEnd + tm.EndDate = body.EndDate + tm.Amount = float32(math.Round(amount*100) / 100) + + if body.StartDate.IsZero() { + tm.StartDate = time.Now() + } + + response, err := as.repository.New(ctx, tm) + + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400109" + exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscription\" table: %s", err) + return nil, exceptionReturn + } + return response, nil +} + +/* +Get + +Gets row from subscription table by id. + + Args: + context.Context: Application context + *model.Auth: Authentication model + string: subscription id to search + params: *model.Params + Returns: + *model.Subscription: Subscription row object from database. + *model.Exception: Exception payload. +*/ +func (as *SubscriptionService) Get(ctx context.Context, am *model.Auth, flt filter.SubscriptionFilter) (*model.Subscription, *model.Exception) { + exceptionReturn := new(model.Exception) + wm := new(model.Subscription) + wm.Id = flt.Id + response, err := as.repository.Get(ctx, wm, flt) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400129" + exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscription\" table: %s", err) + return nil, exceptionReturn + } + + return response, nil +} + +/* +GetAll + +Gets filtered rows from subscription table. + + Args: + context.Context: Application context + *model.Auth: Authentication object + string: Wallet id to search + *model.FilteredResponse: filter options + Returns: + *model.Exception: Exception payload. +*/ +func (as *SubscriptionService) GetAll(ctx context.Context, flt *filter.SubscriptionFilter, filtered *model.FilteredResponse) *model.Exception { + wm := new([]model.Subscription) + exceptionReturn := new(model.Exception) + + err := as.repository.GetAll(ctx, wm, filtered, flt) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400110" + exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"subscription\" table: %s", err) + return exceptionReturn + } + + return nil +} + +/* +Edit + +Updates row from subscription table by id. + + Args: + context.Context: Application context + *model.SubscriptionEdit: Values to edit + string: id to search + Returns: + *model.Subscription: Edited Subscription row object from database. + *model.Exception: Exception payload. +*/ +func (as *SubscriptionService) Edit(ctx context.Context, body *model.SubscriptionEdit, id string) (*model.Subscription, *model.Exception) { + amount, _ := body.Amount.Float64() + exceptionReturn := new(model.Exception) + + tm := new(model.Subscription) + tm.Id = id + tm.EndDate = body.EndDate + tm.HasEnd = body.HasEnd + tm.Description = body.Description + tm.WalletID = body.WalletID + tm.Amount = float32(math.Round(amount*100) / 100) + + response, err := as.repository.Edit(ctx, tm) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400111" + exceptionReturn.Message = fmt.Sprintf("Error updating row in \"subscription\" table: %s", err) + return nil, exceptionReturn + } + + return response, nil +} + +/* +End + +Updates row in subscription table by id. + +Ends subscription with current date. + + Args: + context.Context: Application context + string: id to search + Returns: + *model.Subscription: Created Subscription row object from database. + *model.Exception: Exception payload. +*/ +func (as *SubscriptionService) End(ctx context.Context, id string) (*model.Subscription, *model.Exception) { + exceptionReturn := new(model.Exception) + + tm := new(model.Subscription) + tm.Id = id + tm.EndDate = time.Now() + tm.HasEnd = true + + response, err := as.repository.End(ctx, tm) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400112" + exceptionReturn.Message = fmt.Sprintf("Error updating row in \"subscription\" table: %s", err) + return nil, exceptionReturn + } + + return response, nil +} diff --git a/pkg/service/subscriptionType.go b/pkg/service/subscriptionType.go new file mode 100644 index 0000000..87c8696 --- /dev/null +++ b/pkg/service/subscriptionType.go @@ -0,0 +1,80 @@ +package service + +import ( + "context" + "fmt" + "wallet-api/pkg/filter" + "wallet-api/pkg/model" + "wallet-api/pkg/repository" +) + +type SubscriptionTypeService struct { + repository *repository.SubscriptionTypeRepository +} + +func NewSubscriptionTypeService(repository *repository.SubscriptionTypeRepository) *SubscriptionTypeService { + return &SubscriptionTypeService{ + repository, + } +} + +/* +New + +Inserts new row to subscription type table. + + Args: + context.Context: Application context + *model.NewSubscriptionTypeBody: Values to create new row + Returns: + *model.SubscriptionType: Created row from database. + *model.Exception: Exception payload. +*/ +func (as *SubscriptionTypeService) New(ctx context.Context, body *model.NewSubscriptionTypeBody) (*model.SubscriptionType, *model.Exception) { + tm := new(model.SubscriptionType) + exceptionReturn := new(model.Exception) + + tm.Init() + tm.Name = body.Name + tm.Type = body.Type + + response, err := as.repository.New(ctx, tm) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400114" + exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscriptionTypes\" table: %s", err) + return nil, exceptionReturn + } + + return response, nil +} + +/* +GetAll + +Gets all rows from subscription type table. + + Args: + context.Context: Application context + string: Relations to embed + Returns: + *[]model.SubscriptionType: List of subscription type objects. + *model.Exception: Exception payload. +*/ +func (as *SubscriptionTypeService) GetAll(ctx context.Context, embed string) (*[]model.SubscriptionType, *model.Exception) { + wm := new([]model.SubscriptionType) + exceptionReturn := new(model.Exception) + + flt := filter.NewSubscriptionTypeFilter(model.Params{ + Embed: embed, + }) + response, err := as.repository.GetAll(ctx, flt, wm) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400135" + exceptionReturn.Message = fmt.Sprintf("Error selecting rows in \"subscriptionTypes\" table: %s", err) + return nil, exceptionReturn + } + + return response, nil +} diff --git a/pkg/service/transaction.go b/pkg/service/transaction.go new file mode 100644 index 0000000..b4f02ac --- /dev/null +++ b/pkg/service/transaction.go @@ -0,0 +1,234 @@ +package service + +import ( + "context" + "fmt" + "math" + "time" + "wallet-api/pkg/filter" + "wallet-api/pkg/model" + "wallet-api/pkg/repository" +) + +type TransactionService struct { + repository *repository.TransactionRepository + subscriptionRepository *repository.SubscriptionRepository + transactionStatusService *TransactionStatusService +} + +func NewTransactionService(repository *repository.TransactionRepository, sr *repository.SubscriptionRepository, tss *TransactionStatusService) *TransactionService { + return &TransactionService{ + repository: repository, + subscriptionRepository: sr, + transactionStatusService: tss, + } +} + +/* +New row into transaction table + +Inserts + + Args: + context.Context: Application context + *model.NewTransactionBody: Transaction body object + Returns: + *model.Transaction: Transaction object + *model.Exception: Exception payload. +*/ +func (as *TransactionService) New(ctx context.Context, body *model.NewTransactionBody) (*model.Transaction, *model.Exception) { + exceptionReturn := new(model.Exception) + tm := new(model.Transaction) + + tsFlt := filter.NewTransactionStatusFilter(model.Params{}) + tsFlt.Status = "completed" + transactionStatus, exceptionReturn := as.transactionStatusService.Get(ctx, tsFlt) + + if exceptionReturn != nil { + return nil, exceptionReturn + } + + amount, _ := body.Amount.Float64() + + tm.Init() + tm.WalletID = body.WalletID + tm.TransactionTypeID = body.TransactionTypeID + tm.Description = body.Description + tm.TransactionDate = body.TransactionDate + tm.Amount = float32(math.Round(amount*100) / 100) + tm.TransactionStatusID = transactionStatus.Id + + if body.TransactionDate.IsZero() { + tm.TransactionDate = time.Now() + } + + response, err := as.repository.New(ctx, tm) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400116" + exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"transaction\" table: %s", err) + return nil, exceptionReturn + } + + return response, nil +} + +/* +GetAll + +Gets all rows from subscription type table. + Args: + context.Context: Application context + string: Relations to embed + Returns: + *model.Exception: Exception payload. +*/ +// Gets filtered rows from transaction table. +func (as *TransactionService) GetAll(ctx context.Context, filtered *model.FilteredResponse, flt *filter.TransactionFilter) *model.Exception { + exceptionReturn := new(model.Exception) + + err := as.repository.GetAll(ctx, filtered, flt) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400118" + exceptionReturn.Message = fmt.Sprintf("Error selecting row(s) in \"transaction\" table: %s", err) + return exceptionReturn + } + return nil +} + +/* +Check + +Checks subscriptions and create transacitons. + Args: + context.Context: Application context + string: Relations to embed + Returns: + *model.Exception: Exception payload. +*/ +// Gets filtered rows from transaction table. +func (as *TransactionService) Check(ctx context.Context, flt *filter.TransactionFilter) *model.Exception { + exceptionReturn := new(model.Exception) + filtered := new(model.FilteredResponse) + + err := as.repository.Check(ctx, filtered, flt) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400120" + exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transaction\" table: %s", err) + return exceptionReturn + } + return nil +} + +/* +Edit + +Updates row in transaction table by id. + + Args: + context.Context: Application context + *model.TransactionEdit: Object to edit + string: id to search + Returns: + *model.Transaction: Transaction object from database. + *model.Exception: Exception payload. +*/ +func (as *TransactionService) Edit(ctx context.Context, body *model.TransactionEdit, id string) (*model.Transaction, *model.Exception) { + amount, _ := body.Amount.Float64() + + exceptionReturn := new(model.Exception) + + tm := new(model.Transaction) + tm.Id = id + tm.Description = body.Description + tm.WalletID = body.WalletID + tm.TransactionTypeID = body.TransactionTypeID + tm.TransactionDate = body.TransactionDate + tm.TransactionStatusID = body.TransactionStatusID + tm.Amount = float32(math.Round(amount*100) / 100) + + response, err := as.repository.Edit(ctx, tm) + + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400107" + exceptionReturn.Message = fmt.Sprintf("Error updating row in \"transaction\" table: %s", err) + return nil, exceptionReturn + } + + return response, nil +} + +/* +Bulk Edit + +Updates row in transaction table by id. + + Args: + context.Context: Application context + ?[]model.Transaction Bulk Edit: Object to edit + string: id to search + Returns: + *model.Transaction: Transaction object from database. + *model.Exception: Exception payload. +*/ +func (as *TransactionService) BulkEdit(ctx context.Context, body *[]model.TransactionEdit) (*[]model.Transaction, *model.Exception) { + transactions := new([]model.Transaction) + exceptionReturn := new(model.Exception) + + for _, transaction := range *body { + + amount, _ := transaction.Amount.Float64() + + tm := new(model.Transaction) + tm.Id = transaction.Id + tm.Description = transaction.Description + tm.WalletID = transaction.WalletID + tm.TransactionTypeID = transaction.TransactionTypeID + tm.TransactionDate = transaction.TransactionDate + tm.Amount = float32(math.Round(amount*100) / 100) + + *transactions = append(*transactions, *tm) + } + + response, err := as.repository.BulkEdit(ctx, transactions) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400121" + exceptionReturn.Message = fmt.Sprintf("Error updating rows in \"transactions\" table: %s", err) + return nil, exceptionReturn + } + + return response, nil +} + +/* +Get + +Gets row from transaction table by id. + + Args: + context.Context: Application context + *model.Auth: Authentication object + string: id to search + *model.Params: url query parameters + Returns: + *model.Transaction: Transaction object from database. + *model.Exception: Exception payload. +*/ +func (as *TransactionService) Get(ctx context.Context, flt *filter.TransactionFilter) (*model.Transaction, *model.Exception) { + + exceptionReturn := new(model.Exception) + + response, err := as.repository.Get(ctx, flt) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400122" + exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactions\" table: %s", err) + return nil, exceptionReturn + } + + return response, nil +} diff --git a/pkg/services/transactionStatus.go b/pkg/service/transactionStatus.go similarity index 51% rename from pkg/services/transactionStatus.go rename to pkg/service/transactionStatus.go index a005396..f6fe470 100644 --- a/pkg/services/transactionStatus.go +++ b/pkg/service/transactionStatus.go @@ -1,9 +1,10 @@ -package services +package service import ( "context" "fmt" - "wallet-api/pkg/models" + "wallet-api/pkg/filter" + "wallet-api/pkg/model" "wallet-api/pkg/utl/common" "github.com/go-pg/pg/v10" @@ -26,16 +27,16 @@ Inserts new row to transaction status table. Args: context.Context: Application context - *models.NewTransactionStatusBody: object to create + *model.NewTransactionStatusBody: object to create Returns: - *models.TransactionType: Transaction Type object from database. - *models.Exception: Exception payload. + *model.TransactionType: Transaction Type object from database. + *model.Exception: Exception payload. */ -func (as *TransactionStatusService) New(ctx context.Context, body *models.NewTransactionStatusBody) (*models.TransactionStatus, *models.Exception) { +func (as *TransactionStatusService) New(ctx context.Context, body *model.NewTransactionStatusBody) (*model.TransactionStatus, *model.Exception) { db := as.db.WithContext(ctx) - tm := new(models.TransactionStatus) - exceptionReturn := new(models.Exception) + tm := new(model.TransactionStatus) + exceptionReturn := new(model.Exception) tm.Init() tm.Name = body.Name @@ -61,14 +62,14 @@ Gets all rows from transaction status table. context.Context: Application context string: Relations to embed Returns: - *[]models.TransactionStatus: List of Transaction status objects from database. - *models.Exception: Exception payload. + *[]model.TransactionStatus: List of Transaction status objects from database. + *model.Exception: Exception payload. */ -func (as *TransactionStatusService) GetAll(ctx context.Context, embed string) (*[]models.TransactionStatus, *models.Exception) { +func (as *TransactionStatusService) GetAll(ctx context.Context, embed string) (*[]model.TransactionStatus, *model.Exception) { db := as.db.WithContext(ctx) - wm := new([]models.TransactionStatus) - exceptionReturn := new(models.Exception) + wm := new([]model.TransactionStatus) + exceptionReturn := new(model.Exception) query := db.Model(wm) err := common.GenerateEmbed(query, embed).Select() @@ -81,3 +82,23 @@ func (as *TransactionStatusService) GetAll(ctx context.Context, embed string) (* return wm, nil } + +func (as *TransactionStatusService) Get(ctx context.Context, flt *filter.TransactionStatusFilter) (*model.TransactionStatus, *model.Exception) { + transactionStatus := new(model.TransactionStatus) + exceptionReturn := new(model.Exception) + if flt.Id != "" { + transactionStatus.Id = flt.Id + } + if flt.Status != "" { + transactionStatus.Status = flt.Status + } + response, err := as.repository.Get(ctx, wm, flt) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400129" + exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscription\" table: %s", err) + return nil, exceptionReturn + } + + return response, nil +} diff --git a/pkg/services/transactionTypes.go b/pkg/service/transactionType.go similarity index 68% rename from pkg/services/transactionTypes.go rename to pkg/service/transactionType.go index 6d6d703..3b6007b 100644 --- a/pkg/services/transactionTypes.go +++ b/pkg/service/transactionType.go @@ -1,9 +1,9 @@ -package services +package service import ( "context" "fmt" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "wallet-api/pkg/utl/common" "github.com/go-pg/pg/v10" @@ -26,16 +26,16 @@ Inserts new row to transaction type table. Args: context.Context: Application context - *models.NewTransactionTypeBody: object to create + *model.NewTransactionTypeBody: object to create Returns: - *models.TransactionType: Transaction Type object from database. - *models.Exception: Exception payload. + *model.TransactionType: Transaction Type object from database. + *model.Exception: Exception payload. */ -func (as *TransactionTypeService) New(ctx context.Context, body *models.NewTransactionTypeBody) (*models.TransactionType, *models.Exception) { +func (as *TransactionTypeService) New(ctx context.Context, body *model.NewTransactionTypeBody) (*model.TransactionType, *model.Exception) { db := as.db.WithContext(ctx) - tm := new(models.TransactionType) - exceptionReturn := new(models.Exception) + tm := new(model.TransactionType) + exceptionReturn := new(model.Exception) tm.Init() tm.Name = body.Name @@ -61,14 +61,14 @@ Gets all rows from transaction type table. context.Context: Application context string: Relations to embed Returns: - *[]models.TransactionType: List of Transaction type objects from database. - *models.Exception: Exception payload. + *[]model.TransactionType: List of Transaction type objects from database. + *model.Exception: Exception payload. */ -func (as *TransactionTypeService) GetAll(ctx context.Context, embed string) (*[]models.TransactionType, *models.Exception) { +func (as *TransactionTypeService) GetAll(ctx context.Context, embed string) (*[]model.TransactionType, *model.Exception) { db := as.db.WithContext(ctx) - wm := new([]models.TransactionType) - exceptionReturn := new(models.Exception) + wm := new([]model.TransactionType) + exceptionReturn := new(model.Exception) query := db.Model(wm) err := common.GenerateEmbed(query, embed).Select() diff --git a/pkg/service/user.go b/pkg/service/user.go new file mode 100644 index 0000000..73a1283 --- /dev/null +++ b/pkg/service/user.go @@ -0,0 +1,210 @@ +package service + +import ( + "context" + "os" + "time" + "wallet-api/pkg/model" + "wallet-api/pkg/utl/common" + "wallet-api/pkg/utl/configs" + + jwt "github.com/dgrijalva/jwt-go" + "golang.org/x/crypto/bcrypt" + + "github.com/go-pg/pg/v10" +) + +type UserService struct { + db *pg.DB +} + +func NewUserService(db *pg.DB) *UserService { + return &UserService{ + db: db, + } +} + +/* +Create + +Inserts new row to users table. + + Args: + context.Context: Application context + *model.User: User object to create + Returns: + *model.User: User object from database + *model.Exception +*/ +func (us *UserService) Create(ctx context.Context, registerBody *model.User) (*model.User, *model.Exception) { + db := us.db.WithContext(ctx) + + check := new(model.User) + exceptionReturn := new(model.Exception) + + tx, _ := db.Begin() + defer tx.Rollback() + + tx.Model(check).Where("? = ?", pg.Ident("username"), registerBody.Username).WhereOr("? = ?", pg.Ident("email"), registerBody.Email).Select() + if check.Username != "" || check.Email != "" { + exceptionReturn.Message = "User already exists" + exceptionReturn.ErrorCode = "400101" + exceptionReturn.StatusCode = 400 + return check, exceptionReturn + } + + hashedPassword, err := bcrypt.GenerateFromPassword([]byte(registerBody.Password), bcrypt.DefaultCost) + common.CheckError(err) + + registerBody.Password = string(hashedPassword) + _, err = tx.Model(registerBody).Insert() + + if err != nil { + exceptionReturn.Message = "Error creating user" + exceptionReturn.ErrorCode = "400102" + exceptionReturn.StatusCode = 400 + } + + tx.Commit() + + return registerBody, exceptionReturn +} + +/* +Login + +Gets row from users table by email and valid password. + + Args: + context.Context: Application context + *model.Login: object to search + Returns: + *model.Token: new session token + *model.Exception +*/ +func (us *UserService) Login(ctx context.Context, loginBody *model.Login) (*model.Token, *model.Exception) { + db := us.db.WithContext(ctx) + + check := new(model.User) + exceptionReturn := new(model.Exception) + tokenPayload := new(model.Token) + + tx, _ := db.Begin() + defer tx.Rollback() + + tx.Model(check).Where("? = ?", pg.Ident("email"), loginBody.Email).Select() + + if check.Email == "" { + exceptionReturn.Message = "Email not found" + exceptionReturn.ErrorCode = "400103" + exceptionReturn.StatusCode = 400 + return tokenPayload, exceptionReturn + } + + if !check.IsActive { + exceptionReturn.Message = "Can't log in. User is deactivated." + exceptionReturn.ErrorCode = "400106" + exceptionReturn.StatusCode = 400 + return tokenPayload, exceptionReturn + } + + if bcrypt.CompareHashAndPassword([]byte(check.Password), []byte(loginBody.Password)) != nil { + exceptionReturn.Message = "Incorrect password" + exceptionReturn.ErrorCode = "400104" + exceptionReturn.StatusCode = 400 + return tokenPayload, exceptionReturn + } + + token, err := CreateToken(check, loginBody.RememberMe) + common.CheckError(err) + + tokenPayload.Token = token + + tx.Commit() + + return tokenPayload, exceptionReturn +} + +/* +Deactivate + +Updates row in users table. + +IsActive column is set to false + + Args: + context.Context: Application context + *model.Auth: Authentication object + Returns: + *model.MessageResponse + *model.Exception +*/ +func (us *UserService) Deactivate(ctx context.Context, auth *model.Auth) (*model.MessageResponse, *model.Exception) { + db := us.db.WithContext(ctx) + + mm := new(model.MessageResponse) + me := new(model.Exception) + um := new(model.User) + + tx, _ := db.Begin() + defer tx.Rollback() + + err := tx.Model(um).Where("? = ?", pg.Ident("id"), auth.Id).Select() + + if err != nil { + me.ErrorCode = "404101" + me.Message = "User not found" + me.StatusCode = 404 + return mm, me + } + um.IsActive = false + _, err = tx.Model(um).Where("? = ?", pg.Ident("id"), auth.Id).Update() + + if err != nil { + me.ErrorCode = "400105" + me.Message = "Could not deactivate user" + me.StatusCode = 400 + return mm, me + } + + mm.Message = "User successfully deactivated." + + tx.Commit() + + return mm, me +} + +/* +CreateToken + +Generates new jwt token. + +It encodes the user id. Based on rememberMe it is valid through 48hours or 2hours. + + Args: + *model.User: User object to encode + bool: Should function generate longer lasting token (48hrs) + Returns: + string: Generated token + error: Error that occured in the process +*/ +func CreateToken(user *model.User, rememberMe bool) (string, error) { + atClaims := jwt.MapClaims{} + atClaims["authorized"] = true + atClaims["id"] = user.Id + if rememberMe { + atClaims["exp"] = time.Now().Add(time.Hour * 48).Unix() + } else { + atClaims["exp"] = time.Now().Add(time.Hour * 2).Unix() + } + + secret := os.Getenv("ACCESS_SECRET") + if secret == "" { + secret = configs.Secret + } + + at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims) + token, err := at.SignedString([]byte(secret)) + + return token, err +} diff --git a/pkg/services/wallets.go b/pkg/service/wallet.go similarity index 78% rename from pkg/services/wallets.go rename to pkg/service/wallet.go index b1980b0..a87bb51 100644 --- a/pkg/services/wallets.go +++ b/pkg/service/wallet.go @@ -1,10 +1,10 @@ -package services +package service import ( "context" "fmt" "time" - "wallet-api/pkg/models" + "wallet-api/pkg/model" "wallet-api/pkg/utl/common" "github.com/go-pg/pg/v10" @@ -29,16 +29,16 @@ Inserts row to wallets table. Args: context.Context: Application context - *models.NewWalletBody: Object to be inserted + *model.NewWalletBody: Object to be inserted Returns: - *models.Wallet: Wallet object from database. - *models.Exception: Exception payload. + *model.Wallet: Wallet object from database. + *model.Exception: Exception payload. */ -func (as *WalletService) New(ctx context.Context, am *models.NewWalletBody) (*models.Wallet, *models.Exception) { +func (as *WalletService) New(ctx context.Context, am *model.NewWalletBody) (*model.Wallet, *model.Exception) { db := as.db.WithContext(ctx) - exceptionReturn := new(models.Exception) - walletModel := new(models.Wallet) + exceptionReturn := new(model.Exception) + walletModel := new(model.Wallet) walletModel.Init() walletModel.UserID = am.UserID walletModel.Name = am.Name @@ -59,17 +59,17 @@ Updates row in wallets table by id. Args: context.Context: Application context - *models.WalletEdit: Object to be edited + *model.WalletEdit: Object to be edited string: id to search Returns: - *models.Wallet: Wallet object from database. - *models.Exception: Exception payload. + *model.Wallet: Wallet object from database. + *model.Exception: Exception payload. */ -func (as *WalletService) Edit(ctx context.Context, body *models.WalletEdit, id string) (*models.Wallet, *models.Exception) { +func (as *WalletService) Edit(ctx context.Context, body *model.WalletEdit, id string) (*model.Wallet, *model.Exception) { db := as.db.WithContext(ctx) - exceptionReturn := new(models.Exception) - tm := new(models.Wallet) + exceptionReturn := new(model.Exception) + tm := new(model.Wallet) tm.Id = id tm.Name = body.Name @@ -97,16 +97,16 @@ Gets row in wallets table by id. Args: context.Context: Application context string: id to search - *models.Params: url query parameters + *model.Params: url query parameters Returns: - *models.Wallet: Wallet object from database - *models.Exception: Exception payload. + *model.Wallet: Wallet object from database + *model.Exception: Exception payload. */ -func (as *WalletService) Get(ctx context.Context, id string, params *models.Params) (*models.Wallet, *models.Exception) { +func (as *WalletService) Get(ctx context.Context, id string, params *model.Params) (*model.Wallet, *model.Exception) { db := as.db.WithContext(ctx) - exceptionReturn := new(models.Exception) + exceptionReturn := new(model.Exception) - wm := new(models.Wallet) + wm := new(model.Wallet) wm.Id = id tx, _ := db.Begin() @@ -133,15 +133,15 @@ Gets filtered rows from wallets table. Args: context.Context: Application context - *models.Auth: Authentication object - *models.FilteredResponse: filter options + *model.Auth: Authentication object + *model.FilteredResponse: filter options Returns: - *models.Exception: Exception payload. + *model.Exception: Exception payload. */ -func (as *WalletService) GetAll(ctx context.Context, am *models.Auth, filtered *models.FilteredResponse) *models.Exception { - exceptionReturn := new(models.Exception) +func (as *WalletService) GetAll(ctx context.Context, am *model.Auth, filtered *model.FilteredResponse) *model.Exception { + exceptionReturn := new(model.Exception) db := as.db.WithContext(ctx) - wm := new([]models.Wallet) + wm := new([]model.Wallet) query := db.Model(wm).Where("? = ?", pg.Ident("user_id"), am.Id) err := FilteredResponse(query, wm, filtered) @@ -163,21 +163,21 @@ Calculates previous month, current and next month totals. Args: context.Context: Application context - *models.Auth: Authentication object + *model.Auth: Authentication object string: wallet id to search Returns: - *models.WalletHeader: generated wallet header object - *models.Exception: Exception payload. + *model.WalletHeader: generated wallet header object + *model.Exception: Exception payload. */ -func (as *WalletService) GetHeader(ctx context.Context, am *models.Auth, walletId string) (*models.WalletHeader, *models.Exception) { +func (as *WalletService) GetHeader(ctx context.Context, am *model.Auth, walletId string) (*model.WalletHeader, *model.Exception) { db := as.db.WithContext(ctx) - wm := new(models.WalletHeader) - wallets := new([]models.WalletTransactions) - transactions := new([]models.Transaction) - subscriptions := new([]models.Subscription) - transactionStatus := new(models.TransactionStatus) - exceptionReturn := new(models.Exception) + wm := new(model.WalletHeader) + wallets := new([]model.WalletTransactions) + transactions := new([]model.Transaction) + subscriptions := new([]model.Subscription) + transactionStatus := new(model.TransactionStatus) + exceptionReturn := new(model.Exception) tx, _ := db.Begin() defer tx.Rollback() @@ -300,13 +300,13 @@ Appends Transaction to the belonging walletId. If missing, it creates the item list. Args: - *[]models.WalletTransactions: list to append to + *[]model.WalletTransactions: list to append to string: wallet id to check - models.Transaction: Transaction to append + model.Transaction: Transaction to append Returns: - *models.Exception: Exception payload. + *model.Exception: Exception payload. */ -func addWhere(s *[]models.WalletTransactions, walletId string, e models.Transaction) { +func addWhere(s *[]model.WalletTransactions, walletId string, e model.Transaction) { var exists bool for a := range *s { if (*s)[a].WalletId == walletId { @@ -315,7 +315,7 @@ func addWhere(s *[]models.WalletTransactions, walletId string, e models.Transact } } if !exists { - var walletTransaction models.WalletTransactions + var walletTransaction model.WalletTransactions walletTransaction.WalletId = walletId walletTransaction.Transactions = append(walletTransaction.Transactions, e) *s = append(*s, walletTransaction) diff --git a/pkg/services/api.go b/pkg/services/api.go deleted file mode 100644 index 32f41e3..0000000 --- a/pkg/services/api.go +++ /dev/null @@ -1,59 +0,0 @@ -package services - -import ( - "context" - "wallet-api/pkg/migrate" - "wallet-api/pkg/models" - - "github.com/go-pg/pg/v10" -) - -type ApiService struct { - db *pg.DB -} - -func NewApiService(db *pg.DB) *ApiService { - return &ApiService{ - db: db, - } -} - -/* -GetFirst - -Gets first row from API table. - - Args: - context.Context: Application context - Returns: - models.ApiModel: Api object from database. -*/ -func (as ApiService) GetFirst(ctx context.Context) models.ApiModel { - db := as.db.WithContext(ctx) - apiModel := models.ApiModel{Api: "Works"} - db.Model(&apiModel).First() - return apiModel -} - -/* -PostMigrate - -Starts database migration. - - Args: - context.Context: Application context - string: Migration version - Returns: - *models.MessageResponse: Message response object. - *models.Exception: Exception response object. -*/ -func (as ApiService) PostMigrate(ctx context.Context, version string) (*models.MessageResponse, *models.Exception) { - db := as.db.WithContext(ctx) - - mr := new(models.MessageResponse) - er := new(models.Exception) - - migrate.Start(db, version) - - return mr, er -} diff --git a/pkg/services/services.go b/pkg/services/services.go deleted file mode 100644 index c87a50f..0000000 --- a/pkg/services/services.go +++ /dev/null @@ -1,38 +0,0 @@ -package services - -import ( - "wallet-api/pkg/models" - "wallet-api/pkg/utl/common" - - "github.com/go-pg/pg/v10" -) - -/* -FilteredResponse - -Adds filters to query and executes it. - Args: - *pg.Query: postgres query - interface{}: model to be mapped from query execution. - *models.FilteredResponse: filter options. -*/ -func FilteredResponse(qry *pg.Query, mdl interface{}, filtered *models.FilteredResponse) error { - if filtered.Page == 0 { - filtered.Page = 1 - } - if filtered.Rpp == 0 { - filtered.Rpp = 20 - } - if filtered.SortBy == "" { - filtered.SortBy = "date_created DESC" - } - qry = qry.Limit(filtered.Rpp).Offset((filtered.Page - 1) * filtered.Rpp).Order(filtered.SortBy) - common.GenerateEmbed(qry, filtered.Embed) - count, err := qry.SelectAndCount() - common.CheckError(err) - - filtered.TotalRecords = count - filtered.Items = mdl - - return err -} diff --git a/pkg/services/subscriptionTypes.go b/pkg/services/subscriptionTypes.go deleted file mode 100644 index 00ce747..0000000 --- a/pkg/services/subscriptionTypes.go +++ /dev/null @@ -1,83 +0,0 @@ -package services - -import ( - "context" - "fmt" - "wallet-api/pkg/models" - "wallet-api/pkg/utl/common" - - "github.com/go-pg/pg/v10" -) - -type SubscriptionTypeService struct { - db *pg.DB -} - -func NewSubscriptionTypeService(db *pg.DB) *SubscriptionTypeService { - return &SubscriptionTypeService{ - db: db, - } -} - -/* -New - -Inserts new row to subscription type table. - - Args: - context.Context: Application context - *models.NewSubscriptionTypeBody: Values to create new row - Returns: - *models.SubscriptionType: Created row from database. - *models.Exception: Exception payload. -*/ -func (as *SubscriptionTypeService) New(ctx context.Context, body *models.NewSubscriptionTypeBody) (*models.SubscriptionType, *models.Exception) { - db := as.db.WithContext(ctx) - - tm := new(models.SubscriptionType) - exceptionReturn := new(models.Exception) - - tm.Init() - tm.Name = body.Name - tm.Type = body.Type - - _, err := db.Model(tm).Insert() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400114" - exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscriptionTypes\" table: %s", err) - return nil, exceptionReturn - } - - return tm, nil -} - -/* -GetAll - -Gets all rows from subscription type table. - - Args: - context.Context: Application context - string: Relations to embed - Returns: - *[]models.SubscriptionType: List of subscription type objects. - *models.Exception: Exception payload. -*/ -func (as *SubscriptionTypeService) GetAll(ctx context.Context, embed string) (*[]models.SubscriptionType, *models.Exception) { - db := as.db.WithContext(ctx) - - wm := new([]models.SubscriptionType) - exceptionReturn := new(models.Exception) - - query := db.Model(wm) - err := common.GenerateEmbed(query, embed).Select() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400135" - exceptionReturn.Message = fmt.Sprintf("Error selecting rows in \"subscriptionTypes\" table: %s", err) - return nil, exceptionReturn - } - - return wm, nil -} diff --git a/pkg/services/subscriptions.go b/pkg/services/subscriptions.go deleted file mode 100644 index 86abcf2..0000000 --- a/pkg/services/subscriptions.go +++ /dev/null @@ -1,306 +0,0 @@ -package services - -import ( - "context" - "fmt" - "math" - "time" - "wallet-api/pkg/models" - "wallet-api/pkg/utl/common" - - "github.com/go-pg/pg/v10" -) - -type SubscriptionService struct { - db *pg.DB -} - -func NewSubscriptionService(db *pg.DB) *SubscriptionService { - return &SubscriptionService{ - db: db, - } -} - -/* -New - -Inserts new row to subscription table. - - Args: - context.Context: Application context - *models.NewSubscriptionBody: Request body - Returns: - *models.Subscription: Created Subscription row object from database. - *models.Exception: Exception payload. -*/ -func (as *SubscriptionService) New(ctx context.Context, body *models.NewSubscriptionBody) (*models.Subscription, *models.Exception) { - db := as.db.WithContext(ctx) - - tm := new(models.Subscription) - exceptionReturn := new(models.Exception) - - amount, _ := body.Amount.Float64() - customRange, _ := body.CustomRange.Int64() - - tm.Init() - tm.WalletID = body.WalletID - tm.TransactionTypeID = body.TransactionTypeID - tm.SubscriptionTypeID = body.SubscriptionTypeID - tm.CustomRange = int(customRange) - tm.Description = body.Description - tm.StartDate = body.StartDate - tm.HasEnd = body.HasEnd - tm.EndDate = body.EndDate - tm.Amount = float32(math.Round(amount*100) / 100) - - if body.StartDate.IsZero() { - tm.StartDate = time.Now() - } - - tx, _ := db.Begin() - defer tx.Rollback() - - _, err := tx.Model(tm).Insert() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400109" - exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscription\" table: %s", err) - return nil, exceptionReturn - } - tx.Commit() - - return tm, nil -} - -/* -Get - -Gets row from subscription table by id. - - Args: - context.Context: Application context - *models.Auth: Authentication model - string: subscription id to search - params: *models.Params - Returns: - *models.Subscription: Subscription row object from database. - *models.Exception: Exception payload. -*/ -func (as *SubscriptionService) Get(ctx context.Context, am *models.Auth, id string, params *models.Params) (*models.Subscription, *models.Exception) { - db := as.db.WithContext(ctx) - - exceptionReturn := new(models.Exception) - wm := new(models.Subscription) - wm.Id = id - - tx, _ := db.Begin() - defer tx.Rollback() - - qry := tx.Model(wm) - err := common.GenerateEmbed(qry, params.Embed).WherePK().Select() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400129" - exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscription\" table: %s", err) - return nil, exceptionReturn - } - - tx.Commit() - - return wm, nil -} - -/* -GetAll - -Gets filtered rows from subscription table. - - Args: - context.Context: Application context - *models.Auth: Authentication object - string: Wallet id to search - *models.FilteredResponse: filter options - Returns: - *models.Exception: Exception payload. -*/ -func (as *SubscriptionService) GetAll(ctx context.Context, am *models.Auth, walletId string, filtered *models.FilteredResponse) *models.Exception { - db := as.db.WithContext(ctx) - - wm := new([]models.Subscription) - exceptionReturn := new(models.Exception) - - tx, _ := db.Begin() - defer tx.Rollback() - - query := tx.Model(wm).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id) - if walletId != "" { - query = query.Where("? = ?", pg.Ident("wallet_id"), walletId) - } - - err := FilteredResponse(query, wm, filtered) - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400110" - exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"subscription\" table: %s", err) - return exceptionReturn - } - tx.Commit() - - return nil -} - -/* -Edit - -Updates row from subscription table by id. - - Args: - context.Context: Application context - *models.SubscriptionEdit: Values to edit - string: id to search - Returns: - *models.Subscription: Edited Subscription row object from database. - *models.Exception: Exception payload. -*/ -func (as *SubscriptionService) Edit(ctx context.Context, body *models.SubscriptionEdit, id string) (*models.Subscription, *models.Exception) { - db := as.db.WithContext(ctx) - - amount, _ := body.Amount.Float64() - exceptionReturn := new(models.Exception) - - tm := new(models.Subscription) - tm.Id = id - tm.EndDate = body.EndDate - tm.HasEnd = body.HasEnd - tm.Description = body.Description - tm.WalletID = body.WalletID - tm.Amount = float32(math.Round(amount*100) / 100) - - tx, _ := db.Begin() - defer tx.Rollback() - - _, err := tx.Model(tm).WherePK().UpdateNotZero() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400111" - exceptionReturn.Message = fmt.Sprintf("Error updating row in \"subscription\" table: %s", err) - return nil, exceptionReturn - } - - tx.Commit() - - return tm, nil -} - -/* -End - -Updates row in subscription table by id. - -Ends subscription with current date. - - Args: - context.Context: Application context - string: id to search - Returns: - *models.Subscription: Created Subscription row object from database. - *models.Exception: Exception payload. -*/ -func (as *SubscriptionService) End(ctx context.Context, id string) (*models.Subscription, *models.Exception) { - db := as.db.WithContext(ctx) - exceptionReturn := new(models.Exception) - - tm := new(models.Subscription) - tm.Id = id - tm.EndDate = time.Now() - tm.HasEnd = true - - tx, _ := db.Begin() - defer tx.Rollback() - - _, err := tx.Model(tm).WherePK().UpdateNotZero() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400112" - exceptionReturn.Message = fmt.Sprintf("Error updating row in \"subscription\" table: %s", err) - return nil, exceptionReturn - } - - tx.Commit() - - return tm, nil -} - -/* -SubToTrans - -Generates and Inserts new Transaction rows from the subscription model. - - Args: - *models.Subscription: Subscription model to generate new transactions from - *pg.Tx: Postgres query context - Returns: - *models.Exception: Exception payload. -*/ -func (as *SubscriptionService) SubToTrans(subModel *models.Subscription, tx *pg.Tx) *models.Exception { - exceptionReturn := new(models.Exception) - - now := time.Now() - - currentYear, currentMonth, _ := now.Date() - currentLocation := now.Location() - - transactionStatus := new(models.TransactionStatus) - firstOfNextMonth := time.Date(currentYear, currentMonth+1, 1, 0, 0, 0, 0, currentLocation) - tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "pending").Select() - //tzFirstOfNextMonth := firstOfNextMonth.In(subModel.StartDate.Location()) - - startDate := subModel.StartDate - stopDate := firstOfNextMonth - if subModel.HasEnd && subModel.EndDate.Before(firstOfNextMonth) { - stopDate = subModel.EndDate - } - - transactions := new([]models.Transaction) - - if subModel.SubscriptionType == nil { - st := new(models.SubscriptionType) - tx.Model(st).Where("? = ?", pg.Ident("id"), subModel.SubscriptionTypeID).Select() - subModel.SubscriptionType = st - } - - for startDate.Before(stopDate) { - trans := subModel.ToTrans() - trans.TransactionDate = startDate - trans.TransactionStatusID = transactionStatus.Id - if startDate.After(subModel.LastTransactionDate) && (startDate.Before(now) || startDate.Equal(now)) { - *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) - } - } - - var err error - if len(*transactions) > 0 { - for _, trans := range *transactions { - _, err = tx.Model(&trans).Where("? = ?", pg.Ident("transaction_date"), trans.TransactionDate).Where("? = ?", pg.Ident("subscription_id"), trans.SubscriptionID).OnConflict("DO NOTHING").SelectOrInsert() - if err != nil { - _, err = tx.Model(subModel).Set("? = ?", pg.Ident("last_transaction_date"), trans.TransactionDate).WherePK().Update() - } - } - } - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400113" - exceptionReturn.Message = fmt.Sprintf("Error updating row in \"subscription\" table: %s", err) - return exceptionReturn - } - return nil -} diff --git a/pkg/services/transactions.go b/pkg/services/transactions.go deleted file mode 100644 index a835cdf..0000000 --- a/pkg/services/transactions.go +++ /dev/null @@ -1,329 +0,0 @@ -package services - -import ( - "context" - "fmt" - "math" - "time" - "wallet-api/pkg/models" - "wallet-api/pkg/utl/common" - - "github.com/go-pg/pg/v10" -) - -type TransactionService struct { - db *pg.DB - subscriptionService *SubscriptionService -} - -func NewTransactionService(db *pg.DB, ss *SubscriptionService) *TransactionService { - return &TransactionService{ - db: db, - subscriptionService: ss, - } -} - -/* -New row into transaction table - -Inserts - - Args: - context.Context: Application context - *models.NewTransactionBody: Transaction body object - Returns: - *models.Transaction: Transaction object - *models.Exception: Exception payload. -*/ -func (as *TransactionService) New(ctx context.Context, body *models.NewTransactionBody) (*models.Transaction, *models.Exception) { - db := as.db.WithContext(ctx) - exceptionReturn := new(models.Exception) - - tm := new(models.Transaction) - transactionStatus := new(models.TransactionStatus) - - tx, _ := db.Begin() - defer tx.Rollback() - - err := tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "completed").Select() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400115" - exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionsStatus\" table: %s", err) - return nil, exceptionReturn - } - - amount, _ := body.Amount.Float64() - - tm.Init() - tm.WalletID = body.WalletID - tm.TransactionTypeID = body.TransactionTypeID - tm.Description = body.Description - tm.TransactionDate = body.TransactionDate - tm.Amount = float32(math.Round(amount*100) / 100) - tm.TransactionStatusID = transactionStatus.Id - - if body.TransactionDate.IsZero() { - tm.TransactionDate = time.Now() - } - - _, err = tx.Model(tm).Insert() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400116" - exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"transaction\" table: %s", err) - return nil, exceptionReturn - } - tx.Commit() - - return tm, nil -} - -/* -GetAll - -Gets all rows from subscription type table. - Args: - context.Context: Application context - string: Relations to embed - Returns: - *models.Exception: Exception payload. -*/ -// Gets filtered rows from transaction table. -func (as *TransactionService) GetAll(ctx context.Context, am *models.Auth, walletId string, filtered *models.FilteredResponse, noPending bool) *models.Exception { - db := as.db.WithContext(ctx) - - exceptionReturn := new(models.Exception) - wm := new([]models.Transaction) - transactionStatus := new(models.TransactionStatus) - - tx, _ := db.Begin() - defer tx.Rollback() - - err := tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "completed").Select() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400117" - exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatus\" table: %s", err) - return exceptionReturn - } - - query := tx.Model(wm).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id) - if walletId != "" { - query = query.Where("? = ?", pg.Ident("wallet_id"), walletId) - } - if noPending { - query = query.Where("? = ?", pg.Ident("transaction_status_id"), transactionStatus.Id) - } - - err = FilteredResponse(query, wm, filtered) - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400118" - exceptionReturn.Message = fmt.Sprintf("Error selecting row(s) in \"transaction\" table: %s", err) - return exceptionReturn - } - - tx.Commit() - return nil -} - -/* -Check - -Checks subscriptions and create transacitons. - Args: - context.Context: Application context - string: Relations to embed - Returns: - *models.Exception: Exception payload. -*/ -// Gets filtered rows from transaction table. -func (as *TransactionService) Check(ctx context.Context, am *models.Auth, walletId string, filtered *models.FilteredResponse) *models.Exception { - db := as.db.WithContext(ctx) - - wm := new([]models.Transaction) - sm := new([]models.Subscription) - transactionStatus := new(models.TransactionStatus) - exceptionReturn := new(models.Exception) - - tx, _ := db.Begin() - defer tx.Rollback() - - err := tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "pending").Select() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400119" - exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatus\" table: %s", err) - return exceptionReturn - } - query2 := tx.Model(sm).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id) - if walletId != "" { - query2 = query2.Where("? = ?", pg.Ident("wallet_id"), walletId) - } - query2.Select() - - for _, sub := range *sm { - if sub.HasNew() { - as.subscriptionService.SubToTrans(&sub, tx) - } - } - - query := tx.Model(wm).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id) - if walletId != "" { - query = query.Where("? = ?", pg.Ident("wallet_id"), walletId) - } - query = query.Where("? = ?", pg.Ident("transaction_status_id"), transactionStatus.Id) - - err = FilteredResponse(query, wm, filtered) - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400120" - exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transaction\" table: %s", err) - return exceptionReturn - } - - tx.Commit() - return nil -} - -/* -Edit - -Updates row in transaction table by id. - - Args: - context.Context: Application context - *models.TransactionEdit: Object to edit - string: id to search - Returns: - *models.Transaction: Transaction object from database. - *models.Exception: Exception payload. -*/ -func (as *TransactionService) Edit(ctx context.Context, body *models.TransactionEdit, id string) (*models.Transaction, *models.Exception) { - db := as.db.WithContext(ctx) - - amount, _ := body.Amount.Float64() - - exceptionReturn := new(models.Exception) - - tm := new(models.Transaction) - tm.Id = id - tm.Description = body.Description - tm.WalletID = body.WalletID - tm.TransactionTypeID = body.TransactionTypeID - tm.TransactionDate = body.TransactionDate - tm.TransactionStatusID = body.TransactionStatusID - tm.Amount = float32(math.Round(amount*100) / 100) - - tx, _ := db.Begin() - defer tx.Rollback() - - _, err := tx.Model(tm).WherePK().UpdateNotZero() - - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400107" - exceptionReturn.Message = fmt.Sprintf("Error updating row in \"transaction\" table: %s", err) - return nil, exceptionReturn - } - - err = tx.Model(tm).WherePK().Select() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400108" - exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transaction\" table: %s", err) - return nil, exceptionReturn - } - - tx.Commit() - - return tm, nil -} - -/* -Bulk Edit - -Updates row in transaction table by id. - - Args: - context.Context: Application context - ?[]models.Transaction Bulk Edit: Object to edit - string: id to search - Returns: - *models.Transaction: Transaction object from database. - *models.Exception: Exception payload. -*/ -func (as *TransactionService) BulkEdit(ctx context.Context, body *[]models.TransactionEdit) (*[]models.Transaction, *models.Exception) { - db := as.db.WithContext(ctx) - tx, _ := db.Begin() - defer tx.Rollback() - - transactions := new([]models.Transaction) - exceptionReturn := new(models.Exception) - - for _, transaction := range *body { - - amount, _ := transaction.Amount.Float64() - - tm := new(models.Transaction) - tm.Id = transaction.Id - tm.Description = transaction.Description - tm.WalletID = transaction.WalletID - tm.TransactionTypeID = transaction.TransactionTypeID - tm.TransactionDate = transaction.TransactionDate - tm.Amount = float32(math.Round(amount*100) / 100) - - *transactions = append(*transactions, *tm) - } - - _, err := tx.Model(transactions).WherePK().UpdateNotZero() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400121" - exceptionReturn.Message = fmt.Sprintf("Error updating rows in \"transactions\" table: %s", err) - return nil, exceptionReturn - } - - tx.Commit() - - return transactions, nil -} - -/* -Get - -Gets row from transaction table by id. - - Args: - context.Context: Application context - *models.Auth: Authentication object - string: id to search - *model.Params: url query parameters - Returns: - *models.Transaction: Transaction object from database. - *models.Exception: Exception payload. -*/ -func (as *TransactionService) Get(ctx context.Context, am *models.Auth, id string, params *models.Params) (*models.Transaction, *models.Exception) { - db := as.db.WithContext(ctx) - - exceptionReturn := new(models.Exception) - wm := new(models.Transaction) - wm.Id = id - - tx, _ := db.Begin() - defer tx.Rollback() - - qry := tx.Model(wm) - err := common.GenerateEmbed(qry, params.Embed).WherePK().Select() - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400122" - exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactions\" table: %s", err) - return nil, exceptionReturn - } - - tx.Commit() - - return wm, nil -}