From 73a41f2b54251ccec4e5eecdcb4d3a448929084b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Jurmanovi=C4=87?= Date: Mon, 26 Sep 2022 21:17:10 +0200 Subject: [PATCH 1/4] upgrade go to 1.19 --- .gitignore | 3 +++ go.mod | 33 ++++++++++++++++++++++++++------- go.sum | 9 ++++----- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 33ab022..f7ddef1 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ _testmain.go *.prof .Dockerfile + +logs.txt +querys.txt \ No newline at end of file diff --git a/go.mod b/go.mod index c8e6d8f..ce5a720 100644 --- a/go.mod +++ b/go.mod @@ -1,21 +1,40 @@ module wallet-api -// +heroku goVersion go1.15 -go 1.15 +// +heroku goVersion go1.19 +go 1.19 require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/gin-gonic/gin v1.7.7 github.com/go-pg/pg/v10 v10.10.6 - github.com/go-playground/validator/v10 v10.10.0 // indirect - github.com/golang/protobuf v1.5.2 // indirect github.com/google/uuid v1.3.0 github.com/joho/godotenv v1.4.0 - github.com/json-iterator/go v1.1.12 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/ugorji/go v1.2.6 // indirect + go.uber.org/dig v1.15.0 golang.org/x/crypto v0.0.0-20220214200702-86341886e292 +) + +require ( + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-pg/zerochecker v0.2.0 // indirect + github.com/go-playground/locales v0.14.0 // indirect + github.com/go-playground/universal-translator v0.18.0 // indirect + github.com/go-playground/validator/v10 v10.10.0 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/leodido/go-urn v1.2.1 // indirect + github.com/mattn/go-isatty v0.0.12 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect + github.com/ugorji/go/codec v1.2.6 // indirect + github.com/vmihailenco/bufpool v0.1.11 // indirect + github.com/vmihailenco/msgpack/v5 v5.3.4 // indirect + github.com/vmihailenco/tagparser v0.1.2 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect golang.org/x/text v0.3.7 // indirect + google.golang.org/protobuf v1.26.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + mellium.im/sasl v0.2.1 // indirect ) diff --git a/go.sum b/go.sum index 6831591..d59347c 100644 --- a/go.sum +++ b/go.sum @@ -108,12 +108,11 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo= github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E= github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= @@ -126,6 +125,8 @@ github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vb github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +go.uber.org/dig v1.15.0 h1:vq3YWr8zRj1eFGC7Gvf907hE0eRjPTZ1d3xHadD6liE= +go.uber.org/dig v1.15.0/go.mod h1:pKHs0wMynzL6brANhB2hLMro+zalv1osARTviTcqHLM= golang.org/x/crypto v0.0.0-20180910181607-0e37d006457b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -147,7 +148,6 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -164,7 +164,6 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210923061019-b8560ed6a9b7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -220,8 +219,8 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w= From 13ce0735d01fcdeaabe0a3378ab9079e414a9011 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Jurmanovi=C4=87?= Date: Mon, 26 Sep 2022 21:17:30 +0200 Subject: [PATCH 2/4] add DI --- pkg/api/routes.go | 70 ++++++++++-------- pkg/controllers/api.go | 19 +++-- pkg/controllers/auth.go | 25 ++++--- pkg/controllers/subscriptionTypes.go | 19 +++-- pkg/controllers/subscriptions.go | 31 ++++---- pkg/controllers/transactionStatus.go | 19 +++-- pkg/controllers/transactionTypes.go | 19 +++-- pkg/controllers/transactions.go | 35 +++++---- pkg/controllers/wallets-header.go | 15 ++-- pkg/controllers/wallets.go | 27 ++++--- pkg/services/api.go | 39 ++++++---- pkg/services/subscriptionTypes.go | 38 ++++++---- pkg/services/subscriptions.go | 102 ++++++++++++++------------ pkg/services/transactionStatus.go | 38 ++++++---- pkg/services/transactionTypes.go | 38 ++++++---- pkg/services/transactions.go | 87 ++++++++++++---------- pkg/services/users.go | 66 ++++++++++------- pkg/services/wallets.go | 105 +++++++++++++++------------ pkg/utl/common/common.go | 15 +++- 19 files changed, 466 insertions(+), 341 deletions(-) diff --git a/pkg/api/routes.go b/pkg/api/routes.go index 91b3452..fa44f9e 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -4,57 +4,65 @@ import ( "wallet-api/pkg/controllers" "wallet-api/pkg/middleware" "wallet-api/pkg/services" + "wallet-api/pkg/utl/common" "wallet-api/pkg/utl/configs" "github.com/gin-gonic/gin" "github.com/go-pg/pg/v10" + "go.uber.org/dig" ) /* Routes Initializes web api controllers and its corresponding routes. + Args: *gin.Engine: Gin Engine *pg.DB: Postgres database client */ func Routes(s *gin.Engine, db *pg.DB) { + c := dig.New() ver := s.Group(configs.Prefix) - api := ver.Group("api") - auth := ver.Group("auth") - wallet := ver.Group("wallet", middleware.Auth) - walletHeader := ver.Group("wallet/wallet-header", middleware.Auth) - transaction := ver.Group("transaction", middleware.Auth) - transactionType := ver.Group("transaction-type", middleware.Auth) - subscription := ver.Group("subscription", middleware.Auth) - subscriptionType := ver.Group("subscription-type", middleware.Auth) - transactionStatus := ver.Group("transaction-status", middleware.Auth) - + routeGroups := &common.RouteGroups{ + Api: ver.Group("api"), + Auth: ver.Group("auth"), + Wallet: ver.Group("wallet", middleware.Auth), + WalletHeader: ver.Group("wallet/wallet-header", middleware.Auth), + Transaction: ver.Group("transaction", middleware.Auth), + TransactionType: ver.Group("transaction-type", middleware.Auth), + Subscription: ver.Group("subscription", middleware.Auth), + SubscriptionType: ver.Group("subscription-type", middleware.Auth), + TransactionStatus: ver.Group("transaction-status", middleware.Auth), + } + s.NoRoute(func(c *gin.Context) { c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Page not found"}) }) - - apiService := services.ApiService{Db: db} - usersService := services.UsersService{Db: db} - walletService := services.WalletService{Db: db} - transactionService := services.TransactionService{Db: db} - transactionTypeService := services.TransactionTypeService{Db: db} - subscriptionService := services.SubscriptionService{Db: db} - subscriptionTypeService := services.SubscriptionTypeService{Db: db} - transactionStatusService := services.TransactionStatusService{Db: db} + c.Provide(func() *common.RouteGroups { + return routeGroups + }) + 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) - walletService.Ss = &subscriptionService - transactionService.Ss = &subscriptionService - - controllers.NewApiController(&apiService, api) - controllers.NewAuthController(&usersService, auth) - controllers.NewWalletsController(&walletService, wallet) - controllers.NewWalletsHeaderController(&walletService, walletHeader) - controllers.NewTransactionController(&transactionService, transaction) - controllers.NewTransactionTypeController(&transactionTypeService, transactionType) - controllers.NewSubscriptionController(&subscriptionService, subscription) - controllers.NewSubscriptionTypeController(&subscriptionTypeService, subscriptionType) - controllers.NewTransactionStatusController(&transactionStatusService, transactionStatus) + 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) } diff --git a/pkg/controllers/api.go b/pkg/controllers/api.go index d0bf007..a376867 100644 --- a/pkg/controllers/api.go +++ b/pkg/controllers/api.go @@ -3,30 +3,33 @@ package controllers import ( "wallet-api/pkg/middleware" "wallet-api/pkg/services" + "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type ApiController struct { - ApiService *services.ApiService + service *services.ApiService } /* NewApiController Initializes ApiController. + Args: *services.ApiService: API service *gin.RouterGroup: Gin Router Group Returns: *ApiController: Controller for "api" interactions */ -func NewApiController(as *services.ApiService, s *gin.RouterGroup) *ApiController { - ac := new(ApiController) - ac.ApiService = as +func NewApiController(as *services.ApiService, routeGroups *common.RouteGroups) *ApiController { + ac := &ApiController{ + service: as, + } - s.GET("", ac.getFirst) - s.POST("migrate", middleware.SecretCode, ac.postMigrate) + routeGroups.Api.GET("", ac.getFirst) + routeGroups.Api.POST("migrate", middleware.SecretCode, ac.postMigrate) return ac } @@ -38,7 +41,7 @@ getFirst */ // ROUTE (GET /api). func (ac *ApiController) getFirst(c *gin.Context) { - apiModel := ac.ApiService.GetFirst(c) + apiModel := ac.service.GetFirst(c) c.JSON(200, apiModel) } @@ -53,7 +56,7 @@ Requires "SECRET_CODE", "VERSION" (optional) from body. func (ac *ApiController) postMigrate(c *gin.Context) { migrateModel := c.MustGet("migrate") version := migrateModel.(middleware.SecretCodeModel).Version - mr, er := ac.ApiService.PostMigrate(c, version) + mr, er := ac.service.PostMigrate(c, version) if er.Message != "" { c.JSON(er.StatusCode, er) diff --git a/pkg/controllers/auth.go b/pkg/controllers/auth.go index a2f5661..0110dd7 100644 --- a/pkg/controllers/auth.go +++ b/pkg/controllers/auth.go @@ -5,32 +5,35 @@ import ( "wallet-api/pkg/middleware" "wallet-api/pkg/models" "wallet-api/pkg/services" + "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type AuthController struct { - UsersService *services.UsersService + service *services.UsersService } /* NewAuthController Initializes AuthController. + Args: *services.UsersService: Users service *gin.RouterGroup: Gin Router Group Returns: *AuthController: Controller for "auth" interactions */ -func NewAuthController(rs *services.UsersService, s *gin.RouterGroup) *AuthController { - rc := new(AuthController) - rc.UsersService = rs +func NewAuthController(rs *services.UsersService, routeGroups *common.RouteGroups) *AuthController { + rc := &AuthController{ + service: rs, + } - s.POST("login", rc.PostLogin) - s.POST("register", rc.PostRegister) - s.DELETE("deactivate", middleware.Auth, rc.Delete) - s.GET("check-token", rc.CheckToken) + routeGroups.Auth.POST("login", rc.PostLogin) + routeGroups.Auth.POST("register", rc.PostRegister) + routeGroups.Auth.DELETE("deactivate", middleware.Auth, rc.Delete) + routeGroups.Auth.GET("check-token", rc.CheckToken) return rc } @@ -47,7 +50,7 @@ func (rc *AuthController) PostLogin(c *gin.Context) { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } - returnedUser, exceptionReturn := rc.UsersService.Login(c, body) + returnedUser, exceptionReturn := rc.service.Login(c, body) if exceptionReturn.Message != "" { c.JSON(exceptionReturn.StatusCode, exceptionReturn) @@ -71,7 +74,7 @@ func (rc *AuthController) PostRegister(c *gin.Context) { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } - returnedUser, exceptionReturn := rc.UsersService.Create(c, body) + returnedUser, exceptionReturn := rc.service.Create(c, body) if exceptionReturn.Message != "" { c.JSON(exceptionReturn.StatusCode, exceptionReturn) @@ -92,7 +95,7 @@ func (rc *AuthController) Delete(c *gin.Context) { authGet := c.MustGet("auth") auth.Id = authGet.(*models.Auth).Id - mr, er := rc.UsersService.Deactivate(c, auth) + mr, er := rc.service.Deactivate(c, auth) if er.Message != "" { c.JSON(er.StatusCode, er) diff --git a/pkg/controllers/subscriptionTypes.go b/pkg/controllers/subscriptionTypes.go index 7e8b7d4..847b10d 100644 --- a/pkg/controllers/subscriptionTypes.go +++ b/pkg/controllers/subscriptionTypes.go @@ -4,30 +4,33 @@ import ( "net/http" "wallet-api/pkg/models" "wallet-api/pkg/services" + "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type SubscriptionTypeController struct { - SubscriptionTypeService *services.SubscriptionTypeService + service *services.SubscriptionTypeService } /* NewSubscriptionTypeController Initializes SubscriptionTypeController. + Args: *services.SubscriptionTypeService: Subscription type service *gin.RouterGroup: Gin Router Group Returns: *SubscriptionTypeController: Controller for "subscription-types" route interactions */ -func NewSubscriptionTypeController(as *services.SubscriptionTypeService, s *gin.RouterGroup) *SubscriptionTypeController { - wc := new(SubscriptionTypeController) - wc.SubscriptionTypeService = as +func NewSubscriptionTypeController(as *services.SubscriptionTypeService, routeGroups *common.RouteGroups) *SubscriptionTypeController { + wc := &SubscriptionTypeController{ + service: as, + } - s.POST("", wc.New) - s.GET("", wc.GetAll) + routeGroups.SubscriptionType.POST("", wc.New) + routeGroups.SubscriptionType.GET("", wc.GetAll) return wc } @@ -45,7 +48,7 @@ func (wc *SubscriptionTypeController) New(c *gin.Context) { return } - wm, exception := wc.SubscriptionTypeService.New(c, body) + wm, exception := wc.service.New(c, body) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -62,7 +65,7 @@ GetAll func (wc *SubscriptionTypeController) GetAll(c *gin.Context) { embed, _ := c.GetQuery("embed") - wm, exception := wc.SubscriptionTypeService.GetAll(c, embed) + wm, exception := wc.service.GetAll(c, embed) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controllers/subscriptions.go b/pkg/controllers/subscriptions.go index 0ddaaba..4997d1c 100644 --- a/pkg/controllers/subscriptions.go +++ b/pkg/controllers/subscriptions.go @@ -4,34 +4,37 @@ import ( "net/http" "wallet-api/pkg/models" "wallet-api/pkg/services" + "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type SubscriptionController struct { - SubscriptionService *services.SubscriptionService + service *services.SubscriptionService } /* NewSubscriptionController Initializes SubscriptionController. + Args: *services.SubscriptionService: Subscription service *gin.RouterGroup: Gin Router Group Returns: *SubscriptionController: Controller for "subscription" route interactions */ -func NewSubscriptionController(as *services.SubscriptionService, s *gin.RouterGroup) *SubscriptionController { - wc := new(SubscriptionController) - wc.SubscriptionService = as +func NewSubscriptionController(as *services.SubscriptionService, routeGroups *common.RouteGroups) *SubscriptionController { + wc := &SubscriptionController{ + service: as, + } - s.POST("", wc.New) - s.PUT("/:id", wc.Edit) - s.GET("/:id", wc.Get) - s.GET("", wc.GetAll) + routeGroups.Subscription.POST("", wc.New) + routeGroups.Subscription.PUT("/:id", wc.Edit) + routeGroups.Subscription.GET("/:id", wc.Get) + routeGroups.Subscription.GET("", wc.GetAll) - se := s.Group("/end") + se := routeGroups.Subscription.Group("/end") { se.PUT("/:id", wc.End) } @@ -52,7 +55,7 @@ func (wc *SubscriptionController) New(c *gin.Context) { return } - wm, exception := wc.SubscriptionService.New(c, body) + wm, exception := wc.service.New(c, body) if exception != nil { c.JSON(exception.StatusCode, exception) @@ -77,7 +80,7 @@ func (wc *SubscriptionController) Edit(c *gin.Context) { id := c.Param("id") - wm, exception := wc.SubscriptionService.Edit(c, body, id) + wm, exception := wc.service.Edit(c, body, id) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -103,7 +106,7 @@ func (wc *SubscriptionController) Get(c *gin.Context) { embed, _ := c.GetQuery("embed") params.Embed = embed - fr, exception := wc.SubscriptionService.Get(c, body, id, params) + fr, exception := wc.service.Get(c, body, id, params) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -127,7 +130,7 @@ func (wc *SubscriptionController) End(c *gin.Context) { id := c.Param("id") - fr, exception := wc.SubscriptionService.End(c, id) + fr, exception := wc.service.End(c, id) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -150,7 +153,7 @@ func (wc *SubscriptionController) GetAll(c *gin.Context) { fr := FilteredResponse(c) wallet, _ := c.GetQuery("walletId") - exception := wc.SubscriptionService.GetAll(c, body, wallet, fr) + exception := wc.service.GetAll(c, body, wallet, fr) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controllers/transactionStatus.go b/pkg/controllers/transactionStatus.go index cadb96e..bf7e6e3 100644 --- a/pkg/controllers/transactionStatus.go +++ b/pkg/controllers/transactionStatus.go @@ -4,30 +4,33 @@ import ( "net/http" "wallet-api/pkg/models" "wallet-api/pkg/services" + "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type TransactionStatusController struct { - TransactionStatusService *services.TransactionStatusService + service *services.TransactionStatusService } /* NewTransactionStatusController Initializes TransactionStatusController. + Args: *services.TransactionStatusService: Transaction Staus service *gin.RouterGroup: Gin Router Group Returns: *TransactionStatusController: Controller for "transaction-status" route interactions */ -func NewTransactionStatusController(as *services.TransactionStatusService, s *gin.RouterGroup) *TransactionStatusController { - wc := new(TransactionStatusController) - wc.TransactionStatusService = as +func NewTransactionStatusController(as *services.TransactionStatusService, routeGroups *common.RouteGroups) *TransactionStatusController { + wc := &TransactionStatusController{ + service: as, + } - s.POST("", wc.New) - s.GET("", wc.GetAll) + routeGroups.TransactionStatus.POST("", wc.New) + routeGroups.TransactionStatus.GET("", wc.GetAll) return wc } @@ -45,7 +48,7 @@ func (wc *TransactionStatusController) New(c *gin.Context) { return } - wm, exception := wc.TransactionStatusService.New(c, body) + wm, exception := wc.service.New(c, body) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -62,7 +65,7 @@ GetAll func (wc *TransactionStatusController) GetAll(c *gin.Context) { embed, _ := c.GetQuery("embed") - wm, exception := wc.TransactionStatusService.GetAll(c, embed) + wm, exception := wc.service.GetAll(c, embed) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controllers/transactionTypes.go b/pkg/controllers/transactionTypes.go index 1874bb6..9a6c561 100644 --- a/pkg/controllers/transactionTypes.go +++ b/pkg/controllers/transactionTypes.go @@ -4,30 +4,33 @@ import ( "net/http" "wallet-api/pkg/models" "wallet-api/pkg/services" + "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type TransactionTypeController struct { - TransactionTypeService *services.TransactionTypeService + service *services.TransactionTypeService } /* NewTransactionTypeController Initializes TransactionTypeController. + Args: *services.TransactionTypeService: Transaction Type service *gin.RouterGroup: Gin Router Group Returns: *TransactionTypeController: Controller for "transaction-types" route interactions */ -func NewTransactionTypeController(as *services.TransactionTypeService, s *gin.RouterGroup) *TransactionTypeController { - wc := new(TransactionTypeController) - wc.TransactionTypeService = as +func NewTransactionTypeController(as *services.TransactionTypeService, routeGroups *common.RouteGroups) *TransactionTypeController { + wc := &TransactionTypeController{ + service: as, + } - s.POST("", wc.New) - s.GET("", wc.GetAll) + routeGroups.TransactionType.POST("", wc.New) + routeGroups.TransactionType.GET("", wc.GetAll) return wc } @@ -45,7 +48,7 @@ func (wc *TransactionTypeController) New(c *gin.Context) { return } - wm, exception := wc.TransactionTypeService.New(c, body) + wm, exception := wc.service.New(c, body) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -62,7 +65,7 @@ GetAll func (wc *TransactionTypeController) GetAll(c *gin.Context) { embed, _ := c.GetQuery("embed") - wm, exception := wc.TransactionTypeService.GetAll(c, embed) + wm, exception := wc.service.GetAll(c, embed) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controllers/transactions.go b/pkg/controllers/transactions.go index 77e285a..75d54c4 100644 --- a/pkg/controllers/transactions.go +++ b/pkg/controllers/transactions.go @@ -4,39 +4,42 @@ import ( "net/http" "wallet-api/pkg/models" "wallet-api/pkg/services" + "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type TransactionController struct { - TransactionService *services.TransactionService + service *services.TransactionService } /* NewTransactionController Initializes TransactionController. + Args: *services.TransactionService: Transaction service *gin.RouterGroup: Gin Router Group Returns: *TransactionController: Controller for "transaction" route interactions */ -func NewTransactionController(as *services.TransactionService, s *gin.RouterGroup) *TransactionController { - wc := new(TransactionController) - wc.TransactionService = as +func NewTransactionController(as *services.TransactionService, routeGroups *common.RouteGroups) *TransactionController { + wc := &TransactionController{ + service: as, + } - s.POST("", wc.New) - s.GET("", wc.GetAll) - s.PUT("/:id", wc.Edit) - s.GET("/:id", wc.Get) + routeGroups.Transaction.POST("", wc.New) + routeGroups.Transaction.GET("", wc.GetAll) + routeGroups.Transaction.PUT("/:id", wc.Edit) + routeGroups.Transaction.GET("/:id", wc.Get) - bulkGroup := s.Group("bulk") + bulkGroup := routeGroups.Transaction.Group("bulk") { bulkGroup.PUT("", wc.BulkEdit) } - checkGroup := s.Group("check") + checkGroup := routeGroups.Transaction.Group("check") { checkGroup.GET("", wc.Check) } @@ -57,7 +60,7 @@ func (wc *TransactionController) New(c *gin.Context) { return } - wm, exception := wc.TransactionService.New(c, body) + wm, exception := wc.service.New(c, body) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -82,7 +85,7 @@ func (wc *TransactionController) GetAll(c *gin.Context) { noPendingQry, _ := c.GetQuery("noPending") noPending := noPendingQry != "" - exception := wc.TransactionService.GetAll(c, body, wallet, fr, noPending) + exception := wc.service.GetAll(c, body, wallet, fr, noPending) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -105,7 +108,7 @@ func (wc *TransactionController) Check(c *gin.Context) { fr := FilteredResponse(c) wallet, _ := c.GetQuery("walletId") - exception := wc.TransactionService.Check(c, body, wallet, fr) + exception := wc.service.Check(c, body, wallet, fr) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -129,7 +132,7 @@ func (wc *TransactionController) Edit(c *gin.Context) { id := c.Param("id") - wm, exception := wc.TransactionService.Edit(c, body, id) + wm, exception := wc.service.Edit(c, body, id) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -150,7 +153,7 @@ func (wc *TransactionController) BulkEdit(c *gin.Context) { return } - wm, exception := wc.TransactionService.BulkEdit(c, body) + wm, exception := wc.service.BulkEdit(c, body) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -176,7 +179,7 @@ func (wc *TransactionController) Get(c *gin.Context) { embed, _ := c.GetQuery("embed") params.Embed = embed - fr, exception := wc.TransactionService.Get(c, body, id, params) + fr, exception := wc.service.Get(c, body, id, params) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controllers/wallets-header.go b/pkg/controllers/wallets-header.go index da4be0d..528b741 100644 --- a/pkg/controllers/wallets-header.go +++ b/pkg/controllers/wallets-header.go @@ -3,29 +3,32 @@ package controllers import ( "wallet-api/pkg/models" "wallet-api/pkg/services" + "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type WalletsHeaderController struct { - WalletService *services.WalletService + service *services.WalletService } /* NewWalletsHeaderController Initializes WalletsHeaderController. + Args: *services.WalletService: Wallet service *gin.RouterGroup: Gin Router Group Returns: *WalletsHeaderController: Controller for "wallet/wallet-header" route interactions */ -func NewWalletsHeaderController(as *services.WalletService, s *gin.RouterGroup) *WalletsHeaderController { - wc := new(WalletsHeaderController) - wc.WalletService = as +func NewWalletsHeaderController(as *services.WalletService, routeGroups *common.RouteGroups) *WalletsHeaderController { + wc := &WalletsHeaderController{ + service: as, + } - s.GET("", wc.Get) + routeGroups.WalletHeader.GET("", wc.Get) return wc } @@ -44,7 +47,7 @@ func (wc *WalletsHeaderController) Get(c *gin.Context) { auth := c.MustGet("auth") body.Id = auth.(*models.Auth).Id - wm, exception := wc.WalletService.GetHeader(c, body, walletId) + wm, exception := wc.service.GetHeader(c, body, walletId) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controllers/wallets.go b/pkg/controllers/wallets.go index ba00ed0..495ee81 100644 --- a/pkg/controllers/wallets.go +++ b/pkg/controllers/wallets.go @@ -4,32 +4,35 @@ import ( "net/http" "wallet-api/pkg/models" "wallet-api/pkg/services" + "wallet-api/pkg/utl/common" "github.com/gin-gonic/gin" ) type WalletsController struct { - WalletService *services.WalletService + service *services.WalletService } /* NewWalletsController Initializes WalletsController. + Args: *services.WalletService: Wallet service *gin.RouterGroup: Gin Router Group Returns: *WalletsController: Controller for "wallet" route interactions */ -func NewWalletsController(as *services.WalletService, s *gin.RouterGroup) *WalletsController { - wc := new(WalletsController) - wc.WalletService = as +func NewWalletsController(as *services.WalletService, routeGroups *common.RouteGroups) *WalletsController { + wc := &WalletsController{ + service: as, + } - s.POST("", wc.New) - s.GET("", wc.GetAll) - s.PUT("/:id", wc.Edit) - s.GET("/:id", wc.Get) + routeGroups.Wallet.POST("", wc.New) + routeGroups.Wallet.GET("", wc.GetAll) + routeGroups.Wallet.PUT("/:id", wc.Edit) + routeGroups.Wallet.GET("/:id", wc.Get) return wc } @@ -51,7 +54,7 @@ func (wc *WalletsController) New(c *gin.Context) { get := c.MustGet("auth") body.UserID = get.(*models.Auth).Id - wm, exception := wc.WalletService.New(c, body) + wm, exception := wc.service.New(c, body) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -72,7 +75,7 @@ func (wc *WalletsController) GetAll(c *gin.Context) { fr := FilteredResponse(c) - exception := wc.WalletService.GetAll(c, body, fr) + exception := wc.service.GetAll(c, body, fr) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -96,7 +99,7 @@ func (wc *WalletsController) Edit(c *gin.Context) { id := c.Param("id") - wm, exception := wc.WalletService.Edit(c, body, id) + wm, exception := wc.service.Edit(c, body, id) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -118,7 +121,7 @@ func (wc *WalletsController) Get(c *gin.Context) { embed, _ := c.GetQuery("embed") params.Embed = embed - fr, exception := wc.WalletService.Get(c, id, params) + fr, exception := wc.service.Get(c, id, params) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/services/api.go b/pkg/services/api.go index 16f42b7..32f41e3 100644 --- a/pkg/services/api.go +++ b/pkg/services/api.go @@ -9,21 +9,27 @@ import ( ) type ApiService struct { - Db *pg.DB + 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) + 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 @@ -33,15 +39,16 @@ func (as *ApiService) GetFirst(ctx context.Context) models.ApiModel { PostMigrate Starts database migration. - Args: - context.Context: Application context - string: Migration version - Returns: - *models.MessageResponse: Message response object. - *models.Exception: Exception response object. + + 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) +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) diff --git a/pkg/services/subscriptionTypes.go b/pkg/services/subscriptionTypes.go index eb637d7..00ce747 100644 --- a/pkg/services/subscriptionTypes.go +++ b/pkg/services/subscriptionTypes.go @@ -10,22 +10,29 @@ import ( ) type SubscriptionTypeService struct { - Db *pg.DB + 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. + + 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) + db := as.db.WithContext(ctx) tm := new(models.SubscriptionType) exceptionReturn := new(models.Exception) @@ -49,15 +56,16 @@ func (as *SubscriptionTypeService) New(ctx context.Context, body *models.NewSubs 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. + + 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) + db := as.db.WithContext(ctx) wm := new([]models.SubscriptionType) exceptionReturn := new(models.Exception) diff --git a/pkg/services/subscriptions.go b/pkg/services/subscriptions.go index a1ce86f..86abcf2 100644 --- a/pkg/services/subscriptions.go +++ b/pkg/services/subscriptions.go @@ -12,22 +12,29 @@ import ( ) type SubscriptionService struct { - Db *pg.DB + 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. + + 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) + db := as.db.WithContext(ctx) tm := new(models.Subscription) exceptionReturn := new(models.Exception) @@ -69,17 +76,18 @@ func (as *SubscriptionService) New(ctx context.Context, body *models.NewSubscrip 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. + + 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) + db := as.db.WithContext(ctx) exceptionReturn := new(models.Exception) wm := new(models.Subscription) @@ -106,16 +114,17 @@ func (as *SubscriptionService) Get(ctx context.Context, am *models.Auth, id stri 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. + + 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) + db := as.db.WithContext(ctx) wm := new([]models.Subscription) exceptionReturn := new(models.Exception) @@ -144,16 +153,17 @@ func (as *SubscriptionService) GetAll(ctx context.Context, am *models.Auth, wall 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. + + 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) + db := as.db.WithContext(ctx) amount, _ := body.Amount.Float64() exceptionReturn := new(models.Exception) @@ -188,15 +198,16 @@ 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. + + 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) + db := as.db.WithContext(ctx) exceptionReturn := new(models.Exception) tm := new(models.Subscription) @@ -224,11 +235,12 @@ func (as *SubscriptionService) End(ctx context.Context, id string) (*models.Subs 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. + + 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) diff --git a/pkg/services/transactionStatus.go b/pkg/services/transactionStatus.go index 08ea176..a005396 100644 --- a/pkg/services/transactionStatus.go +++ b/pkg/services/transactionStatus.go @@ -10,22 +10,29 @@ import ( ) type TransactionStatusService struct { - Db *pg.DB + db *pg.DB +} + +func NewTransactionStatusService(db *pg.DB) *TransactionStatusService { + return &TransactionStatusService{ + db: db, + } } /* New Inserts new row to transaction status table. - Args: - context.Context: Application context - *models.NewTransactionStatusBody: object to create - Returns: - *models.TransactionType: Transaction Type object from database. - *models.Exception: Exception payload. + + Args: + context.Context: Application context + *models.NewTransactionStatusBody: object to create + Returns: + *models.TransactionType: Transaction Type object from database. + *models.Exception: Exception payload. */ func (as *TransactionStatusService) New(ctx context.Context, body *models.NewTransactionStatusBody) (*models.TransactionStatus, *models.Exception) { - db := as.Db.WithContext(ctx) + db := as.db.WithContext(ctx) tm := new(models.TransactionStatus) exceptionReturn := new(models.Exception) @@ -49,15 +56,16 @@ func (as *TransactionStatusService) New(ctx context.Context, body *models.NewTra GetAll Gets all rows from transaction status table. - Args: - context.Context: Application context - string: Relations to embed - Returns: - *[]models.TransactionStatus: List of Transaction status objects from database. - *models.Exception: Exception payload. + + Args: + context.Context: Application context + string: Relations to embed + Returns: + *[]models.TransactionStatus: List of Transaction status objects from database. + *models.Exception: Exception payload. */ func (as *TransactionStatusService) GetAll(ctx context.Context, embed string) (*[]models.TransactionStatus, *models.Exception) { - db := as.Db.WithContext(ctx) + db := as.db.WithContext(ctx) wm := new([]models.TransactionStatus) exceptionReturn := new(models.Exception) diff --git a/pkg/services/transactionTypes.go b/pkg/services/transactionTypes.go index aa67324..6d6d703 100644 --- a/pkg/services/transactionTypes.go +++ b/pkg/services/transactionTypes.go @@ -10,22 +10,29 @@ import ( ) type TransactionTypeService struct { - Db *pg.DB + db *pg.DB +} + +func NewTransactionTypeService(db *pg.DB) *TransactionTypeService { + return &TransactionTypeService{ + db: db, + } } /* New Inserts new row to transaction type table. - Args: - context.Context: Application context - *models.NewTransactionTypeBody: object to create - Returns: - *models.TransactionType: Transaction Type object from database. - *models.Exception: Exception payload. + + Args: + context.Context: Application context + *models.NewTransactionTypeBody: object to create + Returns: + *models.TransactionType: Transaction Type object from database. + *models.Exception: Exception payload. */ func (as *TransactionTypeService) New(ctx context.Context, body *models.NewTransactionTypeBody) (*models.TransactionType, *models.Exception) { - db := as.Db.WithContext(ctx) + db := as.db.WithContext(ctx) tm := new(models.TransactionType) exceptionReturn := new(models.Exception) @@ -49,15 +56,16 @@ func (as *TransactionTypeService) New(ctx context.Context, body *models.NewTrans GetAll Gets all rows from transaction type table. - Args: - context.Context: Application context - string: Relations to embed - Returns: - *[]models.TransactionType: List of Transaction type objects from database. - *models.Exception: Exception payload. + + Args: + context.Context: Application context + string: Relations to embed + Returns: + *[]models.TransactionType: List of Transaction type objects from database. + *models.Exception: Exception payload. */ func (as *TransactionTypeService) GetAll(ctx context.Context, embed string) (*[]models.TransactionType, *models.Exception) { - db := as.Db.WithContext(ctx) + db := as.db.WithContext(ctx) wm := new([]models.TransactionType) exceptionReturn := new(models.Exception) diff --git a/pkg/services/transactions.go b/pkg/services/transactions.go index 4185a32..a835cdf 100644 --- a/pkg/services/transactions.go +++ b/pkg/services/transactions.go @@ -12,23 +12,31 @@ import ( ) type TransactionService struct { - Db *pg.DB - Ss *SubscriptionService + db *pg.DB + subscriptionService *SubscriptionService +} + +func NewTransactionService(db *pg.DB, ss *SubscriptionService) *TransactionService { + return &TransactionService{ + db: db, + subscriptionService: ss, + } } /* -New new row into transaction table +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. + + 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) + db := as.db.WithContext(ctx) exceptionReturn := new(models.Exception) tm := new(models.Transaction) @@ -83,7 +91,7 @@ Gets all rows from subscription type table. */ // 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) + db := as.db.WithContext(ctx) exceptionReturn := new(models.Exception) wm := new([]models.Transaction) @@ -132,7 +140,7 @@ Checks subscriptions and create transacitons. */ // 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) + db := as.db.WithContext(ctx) wm := new([]models.Transaction) sm := new([]models.Subscription) @@ -157,7 +165,7 @@ func (as *TransactionService) Check(ctx context.Context, am *models.Auth, wallet for _, sub := range *sm { if sub.HasNew() { - as.Ss.SubToTrans(&sub, tx) + as.subscriptionService.SubToTrans(&sub, tx) } } @@ -183,16 +191,17 @@ func (as *TransactionService) Check(ctx context.Context, am *models.Auth, wallet 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. + + 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) + db := as.db.WithContext(ctx) amount, _ := body.Amount.Float64() @@ -236,16 +245,17 @@ func (as *TransactionService) Edit(ctx context.Context, body *models.Transaction 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. + + 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) + db := as.db.WithContext(ctx) tx, _ := db.Begin() defer tx.Rollback() @@ -284,17 +294,18 @@ func (as *TransactionService) BulkEdit(ctx context.Context, body *[]models.Trans 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. + + 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) + db := as.db.WithContext(ctx) exceptionReturn := new(models.Exception) wm := new(models.Transaction) diff --git a/pkg/services/users.go b/pkg/services/users.go index 27590ec..577b1d3 100644 --- a/pkg/services/users.go +++ b/pkg/services/users.go @@ -15,22 +15,29 @@ import ( ) type UsersService struct { - Db *pg.DB + db *pg.DB +} + +func NewUsersService(db *pg.DB) *UsersService { + return &UsersService{ + db: db, + } } /* Create Inserts new row to users table. - Args: - context.Context: Application context - *models.User: User object to create - Returns: - *models.User: User object from database - *models.Exception + + Args: + context.Context: Application context + *models.User: User object to create + Returns: + *models.User: User object from database + *models.Exception */ func (us *UsersService) Create(ctx context.Context, registerBody *models.User) (*models.User, *models.Exception) { - db := us.Db.WithContext(ctx) + db := us.db.WithContext(ctx) check := new(models.User) exceptionReturn := new(models.Exception) @@ -67,15 +74,16 @@ func (us *UsersService) Create(ctx context.Context, registerBody *models.User) ( Login Gets row from users table by email and valid password. - Args: - context.Context: Application context - *models.Login: object to search - Returns: - *models.Token: new session token - *models.Exception + + Args: + context.Context: Application context + *models.Login: object to search + Returns: + *models.Token: new session token + *models.Exception */ func (us *UsersService) Login(ctx context.Context, loginBody *models.Login) (*models.Token, *models.Exception) { - db := us.Db.WithContext(ctx) + db := us.db.WithContext(ctx) check := new(models.User) exceptionReturn := new(models.Exception) @@ -123,15 +131,16 @@ Deactivate Updates row in users table. IsActive column is set to false - Args: - context.Context: Application context - *models.Auth: Authentication object - Returns: - *models.MessageResponse - *models.Exception + + Args: + context.Context: Application context + *models.Auth: Authentication object + Returns: + *models.MessageResponse + *models.Exception */ func (us *UsersService) Deactivate(ctx context.Context, auth *models.Auth) (*models.MessageResponse, *models.Exception) { - db := us.Db.WithContext(ctx) + db := us.db.WithContext(ctx) mm := new(models.MessageResponse) me := new(models.Exception) @@ -171,12 +180,13 @@ CreateToken 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 - bool: Should function generate longer lasting token (48hrs) - Returns: - string: Generated token - error: Error that occured in the process + + Args: + *models.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) { atClaims := jwt.MapClaims{} diff --git a/pkg/services/wallets.go b/pkg/services/wallets.go index fb99554..b1980b0 100644 --- a/pkg/services/wallets.go +++ b/pkg/services/wallets.go @@ -11,23 +11,31 @@ import ( ) type WalletService struct { - Db *pg.DB - Ss *SubscriptionService + db *pg.DB + subscriptionService *SubscriptionService +} + +func NewWalletService(db *pg.DB, ss *SubscriptionService) *WalletService { + return &WalletService{ + db: db, + subscriptionService: ss, + } } /* New Inserts row to wallets table. - Args: - context.Context: Application context - *models.NewWalletBody: Object to be inserted - Returns: - *models.Wallet: Wallet object from database. - *models.Exception: Exception payload. + + Args: + context.Context: Application context + *models.NewWalletBody: Object to be inserted + Returns: + *models.Wallet: Wallet object from database. + *models.Exception: Exception payload. */ func (as *WalletService) New(ctx context.Context, am *models.NewWalletBody) (*models.Wallet, *models.Exception) { - db := as.Db.WithContext(ctx) + db := as.db.WithContext(ctx) exceptionReturn := new(models.Exception) walletModel := new(models.Wallet) @@ -48,16 +56,17 @@ func (as *WalletService) New(ctx context.Context, am *models.NewWalletBody) (*mo Edit Updates row in wallets table by id. - Args: - context.Context: Application context - *models.WalletEdit: Object to be edited - string: id to search - Returns: - *models.Wallet: Wallet object from database. - *models.Exception: Exception payload. + + Args: + context.Context: Application context + *models.WalletEdit: Object to be edited + string: id to search + Returns: + *models.Wallet: Wallet object from database. + *models.Exception: Exception payload. */ func (as *WalletService) Edit(ctx context.Context, body *models.WalletEdit, id string) (*models.Wallet, *models.Exception) { - db := as.Db.WithContext(ctx) + db := as.db.WithContext(ctx) exceptionReturn := new(models.Exception) tm := new(models.Wallet) @@ -84,16 +93,17 @@ func (as *WalletService) Edit(ctx context.Context, body *models.WalletEdit, id s Get Gets row in wallets table by id. - Args: - context.Context: Application context - string: id to search - *models.Params: url query parameters - Returns: - *models.Wallet: Wallet object from database - *models.Exception: Exception payload. + + Args: + context.Context: Application context + string: id to search + *models.Params: url query parameters + Returns: + *models.Wallet: Wallet object from database + *models.Exception: Exception payload. */ func (as *WalletService) Get(ctx context.Context, id string, params *models.Params) (*models.Wallet, *models.Exception) { - db := as.Db.WithContext(ctx) + db := as.db.WithContext(ctx) exceptionReturn := new(models.Exception) wm := new(models.Wallet) @@ -120,16 +130,17 @@ func (as *WalletService) Get(ctx context.Context, id string, params *models.Para GetAll Gets filtered rows from wallets table. - Args: - context.Context: Application context - *models.Auth: Authentication object - *models.FilteredResponse: filter options - Returns: - *models.Exception: Exception payload. + + Args: + context.Context: Application context + *models.Auth: Authentication object + *models.FilteredResponse: filter options + Returns: + *models.Exception: Exception payload. */ func (as *WalletService) GetAll(ctx context.Context, am *models.Auth, filtered *models.FilteredResponse) *models.Exception { exceptionReturn := new(models.Exception) - db := as.Db.WithContext(ctx) + db := as.db.WithContext(ctx) wm := new([]models.Wallet) query := db.Model(wm).Where("? = ?", pg.Ident("user_id"), am.Id) @@ -149,16 +160,17 @@ GetHeader Gets row from wallets table. Calculates previous month, current and next month totals. - Args: - context.Context: Application context - *models.Auth: Authentication object - string: wallet id to search - Returns: - *models.WalletHeader: generated wallet header object - *models.Exception: Exception payload. + + Args: + context.Context: Application context + *models.Auth: Authentication object + string: wallet id to search + Returns: + *models.WalletHeader: generated wallet header object + *models.Exception: Exception payload. */ func (as *WalletService) GetHeader(ctx context.Context, am *models.Auth, walletId string) (*models.WalletHeader, *models.Exception) { - db := as.Db.WithContext(ctx) + db := as.db.WithContext(ctx) wm := new(models.WalletHeader) wallets := new([]models.WalletTransactions) @@ -286,12 +298,13 @@ addWhere Appends Transaction to the belonging walletId. If missing, it creates the item list. - Args: - *[]models.WalletTransactions: list to append to - string: wallet id to check - models.Transaction: Transaction to append - Returns: - *models.Exception: Exception payload. + + Args: + *[]models.WalletTransactions: list to append to + string: wallet id to check + models.Transaction: Transaction to append + Returns: + *models.Exception: Exception payload. */ func addWhere(s *[]models.WalletTransactions, walletId string, e models.Transaction) { var exists bool diff --git a/pkg/utl/common/common.go b/pkg/utl/common/common.go index 4c2ee83..eee7cad 100644 --- a/pkg/utl/common/common.go +++ b/pkg/utl/common/common.go @@ -1,6 +1,7 @@ package common import ( + "github.com/gin-gonic/gin" "log" "net" "os" @@ -8,6 +9,18 @@ import ( "strings" ) +type RouteGroups struct { + Api *gin.RouterGroup + Auth *gin.RouterGroup + Wallet *gin.RouterGroup + WalletHeader *gin.RouterGroup + Transaction *gin.RouterGroup + TransactionType *gin.RouterGroup + Subscription *gin.RouterGroup + SubscriptionType *gin.RouterGroup + TransactionStatus *gin.RouterGroup +} + func CheckError(err error) { if err != nil { log.Printf("Error occured. %v", err) @@ -38,4 +51,4 @@ func GetIP() string { } } return "" -} \ No newline at end of file +} From 82e97fc97f60e68d04b330d52ae13f2511e9650b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Jurmanovi=C4=87?= Date: Tue, 27 Sep 2022 00:33:44 +0200 Subject: [PATCH 3/4] partial repository layer added --- pkg/api/routes.go | 22 +- pkg/{controllers => controller}/api.go | 8 +- pkg/controller/controller.go | 70 ++++ .../subscription.go} | 40 ++- .../subscriptionType.go} | 12 +- .../transaction.go} | 30 +- .../transactionStatus.go | 12 +- .../transactionType.go} | 12 +- .../auth.go => controller/user.go} | 40 +-- .../wallet-header.go} | 26 +- .../wallets.go => controller/wallet.go} | 40 +-- pkg/controllers/controllers.go | 44 --- pkg/filter/api.go | 13 + pkg/filter/filter.go | 27 ++ pkg/filter/subscription.go | 14 + pkg/filter/subscriptionType.go | 14 + pkg/filter/transaction.go | 16 + pkg/filter/transactionStatus.go | 15 + pkg/filter/transactionType.go | 14 + pkg/filter/user.go | 14 + pkg/filter/wallet-header.go | 14 + pkg/filter/wallet.go | 14 + pkg/middleware/auth.go | 9 +- pkg/middleware/secretCode.go | 14 +- .../10_create_table_transaction_status.go | 13 +- pkg/migrate/11_populate_transaction_status.go | 17 +- pkg/migrate/1_create_table_api.go | 13 +- pkg/migrate/2_create_table_users.go | 13 +- pkg/migrate/3_create_table_wallets.go | 13 +- .../4_create_table_transaction_types.go | 13 +- pkg/migrate/5_create_table_transactions.go | 13 +- .../6_create_table_subscription_types.go | 13 +- pkg/migrate/7_create_table_subscriptions.go | 13 +- pkg/migrate/8_populate_subscription_types.go | 19 +- pkg/migrate/9_populate_transaction_types.go | 15 +- pkg/migrate/migrate.go | 11 +- pkg/{models => model}/api.go | 2 +- pkg/model/auth.go | 19 + pkg/{models => model}/db.go | 2 +- pkg/{models => model}/exception.go | 2 +- pkg/model/model.go | 22 ++ pkg/{models => model}/register.go | 3 +- .../subscription.go} | 4 +- .../subscriptionType.go} | 2 +- .../transactions.go => model/transaction.go} | 2 +- pkg/{models => model}/transactionStatus.go | 6 +- .../transactionType.go} | 2 +- pkg/{models/wallets.go => model/wallet.go} | 2 +- pkg/models/auth.go | 19 - pkg/models/models.go | 22 -- pkg/repository/api.go | 53 +++ pkg/repository/repository.go | 59 ++++ pkg/repository/subscription.go | 280 +++++++++++++++ pkg/repository/subscriptionType.go | 67 ++++ pkg/repository/transaction.go | 268 ++++++++++++++ pkg/repository/transactionStatus.go | 146 ++++++++ pkg/repository/transactionType.go | 83 +++++ pkg/{services/users.go => repository/user.go} | 54 +-- pkg/repository/wallet.go | 323 +++++++++++++++++ pkg/service/api.go | 47 +++ pkg/service/service.go | 27 ++ pkg/service/subscription.go | 192 ++++++++++ pkg/service/subscriptionType.go | 80 +++++ pkg/service/transaction.go | 234 +++++++++++++ .../transactionStatus.go | 47 ++- .../transactionType.go} | 26 +- pkg/service/user.go | 210 +++++++++++ .../wallets.go => service/wallet.go} | 82 ++--- pkg/services/api.go | 59 ---- pkg/services/services.go | 38 -- pkg/services/subscriptionTypes.go | 83 ----- pkg/services/subscriptions.go | 306 ---------------- pkg/services/transactions.go | 329 ------------------ 73 files changed, 2686 insertions(+), 1216 deletions(-) rename pkg/{controllers => controller}/api.go (86%) create mode 100644 pkg/controller/controller.go rename pkg/{controllers/subscriptions.go => controller/subscription.go} (77%) rename pkg/{controllers/subscriptionTypes.go => controller/subscriptionType.go} (81%) rename pkg/{controllers/transactions.go => controller/transaction.go} (85%) rename pkg/{controllers => controller}/transactionStatus.go (81%) rename pkg/{controllers/transactionTypes.go => controller/transactionType.go} (81%) rename pkg/{controllers/auth.go => controller/user.go} (70%) rename pkg/{controllers/wallets-header.go => controller/wallet-header.go} (50%) rename pkg/{controllers/wallets.go => controller/wallet.go} (68%) delete mode 100644 pkg/controllers/controllers.go create mode 100644 pkg/filter/api.go create mode 100644 pkg/filter/filter.go create mode 100644 pkg/filter/subscription.go create mode 100644 pkg/filter/subscriptionType.go create mode 100644 pkg/filter/transaction.go create mode 100644 pkg/filter/transactionStatus.go create mode 100644 pkg/filter/transactionType.go create mode 100644 pkg/filter/user.go create mode 100644 pkg/filter/wallet-header.go create mode 100644 pkg/filter/wallet.go rename pkg/{models => model}/api.go (86%) create mode 100644 pkg/model/auth.go rename pkg/{models => model}/db.go (96%) rename pkg/{models => model}/exception.go (90%) create mode 100644 pkg/model/model.go rename pkg/{models => model}/register.go (98%) rename pkg/{models/subscriptions.go => model/subscription.go} (99%) rename pkg/{models/subscriptionTypes.go => model/subscriptionType.go} (95%) rename pkg/{models/transactions.go => model/transaction.go} (99%) rename pkg/{models => model}/transactionStatus.go (72%) rename pkg/{models/transactionTypes.go => model/transactionType.go} (95%) rename pkg/{models/wallets.go => model/wallet.go} (98%) delete mode 100644 pkg/models/auth.go delete mode 100644 pkg/models/models.go create mode 100644 pkg/repository/api.go create mode 100644 pkg/repository/repository.go create mode 100644 pkg/repository/subscription.go create mode 100644 pkg/repository/subscriptionType.go create mode 100644 pkg/repository/transaction.go create mode 100644 pkg/repository/transactionStatus.go create mode 100644 pkg/repository/transactionType.go rename pkg/{services/users.go => repository/user.go} (76%) create mode 100644 pkg/repository/wallet.go create mode 100644 pkg/service/api.go create mode 100644 pkg/service/service.go create mode 100644 pkg/service/subscription.go create mode 100644 pkg/service/subscriptionType.go create mode 100644 pkg/service/transaction.go rename pkg/{services => service}/transactionStatus.go (51%) rename pkg/{services/transactionTypes.go => service/transactionType.go} (68%) create mode 100644 pkg/service/user.go rename pkg/{services/wallets.go => service/wallet.go} (78%) delete mode 100644 pkg/services/api.go delete mode 100644 pkg/services/services.go delete mode 100644 pkg/services/subscriptionTypes.go delete mode 100644 pkg/services/subscriptions.go delete mode 100644 pkg/services/transactions.go 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 -} From ec863d55b35d8a41f5fd719c9eb1007ee0b80154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=20Jurmanovi=C4=87?= Date: Fri, 7 Oct 2022 23:48:35 +0200 Subject: [PATCH 4/4] add repositories and fixed services --- pkg/controller/api.go | 8 +- pkg/controller/subscription.go | 34 +++--- pkg/controller/subscriptionType.go | 9 +- pkg/controller/transaction.go | 46 +++++--- pkg/controller/transactionStatus.go | 8 +- pkg/controller/transactionType.go | 8 +- pkg/controller/user.go | 9 +- pkg/controller/wallet-header.go | 12 ++- pkg/controller/wallet.go | 20 ++-- pkg/filter/filter.go | 12 ++- pkg/model/api.go | 1 + pkg/model/model.go | 4 +- pkg/model/subscription.go | 36 +++++++ pkg/model/subscriptionType.go | 10 ++ pkg/model/transaction.go | 33 ++++++ pkg/model/transactionStatus.go | 8 ++ pkg/model/transactionType.go | 8 ++ pkg/model/wallet.go | 15 +++ pkg/repository/repository.go | 8 +- pkg/repository/subscription.go | 28 ++--- pkg/repository/subscriptionType.go | 3 +- pkg/repository/transaction.go | 116 +++++++++++++++------ pkg/repository/transactionStatus.go | 70 +++++++------ pkg/repository/transactionType.go | 26 ++--- pkg/repository/user.go | 156 +++++++++++++++++++++++----- pkg/repository/wallet.go | 69 +++++------- pkg/service/api.go | 4 +- pkg/service/service.go | 3 +- pkg/service/subscription.go | 51 ++------- pkg/service/subscriptionType.go | 17 +-- pkg/service/transaction.go | 111 ++++++++------------ pkg/service/transactionStatus.go | 35 ++----- pkg/service/transactionType.go | 34 ++---- pkg/service/user.go | 77 +++++++------- pkg/service/wallet.go | 102 +++++++----------- pkg/utl/common/common.go | 9 ++ 36 files changed, 703 insertions(+), 497 deletions(-) diff --git a/pkg/controller/api.go b/pkg/controller/api.go index ff1e972..e8c7a4e 100644 --- a/pkg/controller/api.go +++ b/pkg/controller/api.go @@ -56,11 +56,11 @@ Requires "SECRET_CODE", "VERSION" (optional) from body. func (ac *ApiController) postMigrate(c *gin.Context) { migrateModel := c.MustGet("migrate") version := migrateModel.(middleware.SecretCodeModel).Version - mr, er := ac.service.PostMigrate(c, version) + er := ac.service.PostMigrate(c, version) - if er.Message != "" { - c.JSON(er.StatusCode, er) + if len(er) > 0 { + c.JSON(500, er) } else { - c.JSON(200, mr) + c.JSON(200, nil) } } diff --git a/pkg/controller/subscription.go b/pkg/controller/subscription.go index ddd3150..f413c3a 100644 --- a/pkg/controller/subscription.go +++ b/pkg/controller/subscription.go @@ -56,7 +56,9 @@ func (wc *SubscriptionController) New(c *gin.Context) { return } - wm, exception := wc.service.New(c, body) + mdl := body.ToSubscription() + + wm, exception := wc.service.New(c, mdl) if exception != nil { c.JSON(exception.StatusCode, exception) @@ -81,7 +83,10 @@ func (wc *SubscriptionController) Edit(c *gin.Context) { id := c.Param("id") - wm, exception := wc.service.Edit(c, body, id) + mdl := body.ToSubscription() + mdl.Id = id + + wm, exception := wc.service.Edit(c, mdl) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -96,11 +101,10 @@ Get */ // ROUTE (GET /subscription/:id) func (wc *SubscriptionController) Get(c *gin.Context) { - body := new(model.Auth) params := new(model.Params) auth := c.MustGet("auth") - body.Id = auth.(*model.Auth).Id + userId := auth.(*model.Auth).Id id := c.Param("id") @@ -109,8 +113,9 @@ func (wc *SubscriptionController) Get(c *gin.Context) { flt := filter.NewSubscriptionFilter(*params) flt.Id = id + flt.UserId = userId - fr, exception := wc.service.Get(c, body, *flt) + fr, exception := wc.service.Get(c, *flt) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -121,17 +126,6 @@ func (wc *SubscriptionController) Get(c *gin.Context) { // ROUTE (PUT /subscription/end/:id) func (wc *SubscriptionController) End(c *gin.Context) { - body := new(model.Auth) - - auth := c.MustGet("auth") - body.Id = auth.(*model.Auth).Id - - end := new(model.SubscriptionEnd) - if err := c.ShouldBind(end); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - return - } - id := c.Param("id") fr, exception := wc.service.End(c, id) @@ -152,14 +146,14 @@ GetAll func (wc *SubscriptionController) GetAll(c *gin.Context) { auth := c.MustGet("auth") - fr := FilteredResponse(c) wallet, _ := c.GetQuery("walletId") + embed, _ := c.GetQuery("embed") - flt := filter.NewSubscriptionFilter(model.Params{}) + flt := filter.NewSubscriptionFilter(model.Params{Embed: embed}) flt.WalletId = wallet - flt.Id = auth.(*model.Auth).Id + flt.UserId = auth.(*model.Auth).Id - exception := wc.service.GetAll(c, flt, fr) + fr, exception := wc.service.GetAll(c, flt) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controller/subscriptionType.go b/pkg/controller/subscriptionType.go index f55aba5..f0d5169 100644 --- a/pkg/controller/subscriptionType.go +++ b/pkg/controller/subscriptionType.go @@ -2,6 +2,7 @@ package controller import ( "net/http" + "wallet-api/pkg/filter" "wallet-api/pkg/model" "wallet-api/pkg/service" "wallet-api/pkg/utl/common" @@ -48,7 +49,9 @@ func (wc *SubscriptionTypeController) New(c *gin.Context) { return } - wm, exception := wc.service.New(c, body) + mdl := body.ToSubscriptionType() + + wm, exception := wc.service.New(c, mdl) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -65,7 +68,9 @@ GetAll func (wc *SubscriptionTypeController) GetAll(c *gin.Context) { embed, _ := c.GetQuery("embed") - wm, exception := wc.service.GetAll(c, embed) + flt := filter.NewSubscriptionTypeFilter(model.Params{Embed: embed}) + + wm, exception := wc.service.GetAll(c, flt) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controller/transaction.go b/pkg/controller/transaction.go index 2b8a6c7..760ab3f 100644 --- a/pkg/controller/transaction.go +++ b/pkg/controller/transaction.go @@ -2,6 +2,7 @@ package controller import ( "net/http" + "wallet-api/pkg/filter" "wallet-api/pkg/model" "wallet-api/pkg/service" "wallet-api/pkg/utl/common" @@ -60,7 +61,9 @@ func (wc *TransactionController) New(c *gin.Context) { return } - wm, exception := wc.service.New(c, body) + mdl := body.ToTransaction() + + wm, exception := wc.service.New(c, mdl) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -75,17 +78,22 @@ GetAll */ // ROUTE (GET /transactions) func (wc *TransactionController) GetAll(c *gin.Context) { - body := new(model.Auth) auth := c.MustGet("auth") - body.Id = auth.(*model.Auth).Id + userId := auth.(*model.Auth).Id fr := FilteredResponse(c) wallet, _ := c.GetQuery("walletId") + embed, _ := c.GetQuery("embed") noPendingQry, _ := c.GetQuery("noPending") noPending := noPendingQry != "" - exception := wc.service.GetAll(c, body, wallet, fr, noPending) + flt := filter.NewTransactionFilter(model.Params{Embed: embed}) + flt.WalletId = wallet + flt.NoPending = noPending + flt.UserId = userId + + fr, exception := wc.service.GetAll(c, flt) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -101,14 +109,17 @@ Check */ // ROUTE (GET /transactions) func (wc *TransactionController) Check(c *gin.Context) { - body := new(model.Auth) auth := c.MustGet("auth") - body.Id = auth.(*model.Auth).Id + userId := auth.(*model.Auth).Id fr := FilteredResponse(c) wallet, _ := c.GetQuery("walletId") - exception := wc.service.Check(c, body, wallet, fr) + flt := filter.NewTransactionFilter(model.Params{}) + flt.WalletId = wallet + flt.UserId = userId + + fr, exception := wc.service.Check(c, flt) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -131,8 +142,10 @@ func (wc *TransactionController) Edit(c *gin.Context) { } id := c.Param("id") + mdl := body.ToTransaction() + mdl.Id = id - wm, exception := wc.service.Edit(c, body, id) + wm, exception := wc.service.Edit(c, mdl) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -153,7 +166,13 @@ func (wc *TransactionController) BulkEdit(c *gin.Context) { return } - wm, exception := wc.service.BulkEdit(c, body) + mdl := new([]model.Transaction) + for _, transaction := range *body { + tm := transaction.ToTransaction() + *mdl = append(*mdl, *tm) + } + + wm, exception := wc.service.BulkEdit(c, mdl) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -168,18 +187,21 @@ Get */ // ROUTE (GET /transactions/:id) func (wc *TransactionController) Get(c *gin.Context) { - body := new(model.Auth) params := new(model.Params) auth := c.MustGet("auth") - body.Id = auth.(*model.Auth).Id + userId := 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.NewTransactionFilter(*params) + flt.Id = id + flt.UserId = userId + + fr, exception := wc.service.Get(c, flt) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controller/transactionStatus.go b/pkg/controller/transactionStatus.go index 3f99aa9..e3fbd6a 100644 --- a/pkg/controller/transactionStatus.go +++ b/pkg/controller/transactionStatus.go @@ -2,6 +2,7 @@ package controller import ( "net/http" + "wallet-api/pkg/filter" "wallet-api/pkg/model" "wallet-api/pkg/service" "wallet-api/pkg/utl/common" @@ -48,7 +49,9 @@ func (wc *TransactionStatusController) New(c *gin.Context) { return } - wm, exception := wc.service.New(c, body) + mdl := body.ToTransactionStatus() + + wm, exception := wc.service.New(c, mdl) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -64,8 +67,9 @@ GetAll // ROUTE (GET /transaction-status) func (wc *TransactionStatusController) GetAll(c *gin.Context) { embed, _ := c.GetQuery("embed") + flt := filter.NewTransactionStatusFilter(model.Params{Embed: embed}) - wm, exception := wc.service.GetAll(c, embed) + wm, exception := wc.service.GetAll(c, flt) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controller/transactionType.go b/pkg/controller/transactionType.go index c04d412..9b5e734 100644 --- a/pkg/controller/transactionType.go +++ b/pkg/controller/transactionType.go @@ -2,6 +2,7 @@ package controller import ( "net/http" + "wallet-api/pkg/filter" "wallet-api/pkg/model" "wallet-api/pkg/service" "wallet-api/pkg/utl/common" @@ -47,8 +48,9 @@ func (wc *TransactionTypeController) New(c *gin.Context) { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } + mdl := body.ToTransactionType() - wm, exception := wc.service.New(c, body) + wm, exception := wc.service.New(c, mdl) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -65,7 +67,9 @@ GetAll func (wc *TransactionTypeController) GetAll(c *gin.Context) { embed, _ := c.GetQuery("embed") - wm, exception := wc.service.GetAll(c, embed) + flt := filter.NewTransactionTypeFilter(model.Params{Embed: embed}) + + wm, exception := wc.service.GetAll(c, flt) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controller/user.go b/pkg/controller/user.go index cd12358..a33ecc6 100644 --- a/pkg/controller/user.go +++ b/pkg/controller/user.go @@ -2,6 +2,7 @@ package controller import ( "net/http" + "wallet-api/pkg/filter" "wallet-api/pkg/middleware" "wallet-api/pkg/model" "wallet-api/pkg/service" @@ -91,11 +92,13 @@ Delete */ // ROUTE (DELETE /auth/deactivate). func (rc *UserController) Delete(c *gin.Context) { - auth := new(model.Auth) authGet := c.MustGet("auth") - auth.Id = authGet.(*model.Auth).Id + userId := authGet.(*model.Auth).Id - mr, er := rc.service.Deactivate(c, auth) + flt := filter.NewUserFilter(model.Params{}) + flt.UserId = userId + + mr, er := rc.service.Deactivate(c, flt) if er.Message != "" { c.JSON(er.StatusCode, er) diff --git a/pkg/controller/wallet-header.go b/pkg/controller/wallet-header.go index 7b5b1ac..708b3b2 100644 --- a/pkg/controller/wallet-header.go +++ b/pkg/controller/wallet-header.go @@ -1,6 +1,7 @@ package controller import ( + "wallet-api/pkg/filter" "wallet-api/pkg/model" "wallet-api/pkg/service" "wallet-api/pkg/utl/common" @@ -40,14 +41,17 @@ Get */ // ROUTE (GET /wallet/wallet-header) func (wc *WalletHeaderController) Get(c *gin.Context) { - body := new(model.Auth) - walletId, _ := c.GetQuery("walletId") auth := c.MustGet("auth") - body.Id = auth.(*model.Auth).Id + userId := auth.(*model.Auth).Id + embed, _ := c.GetQuery("embed") - wm, exception := wc.service.GetHeader(c, body, walletId) + flt := filter.NewWalletHeaderFilter(model.Params{Embed: embed}) + flt.UserId = userId + flt.WalletId = walletId + + wm, exception := wc.service.GetHeader(c, flt) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/controller/wallet.go b/pkg/controller/wallet.go index dbdfc62..dac08a0 100644 --- a/pkg/controller/wallet.go +++ b/pkg/controller/wallet.go @@ -2,6 +2,7 @@ package controller import ( "net/http" + "wallet-api/pkg/filter" "wallet-api/pkg/model" "wallet-api/pkg/service" "wallet-api/pkg/utl/common" @@ -69,13 +70,14 @@ GetAll */ // ROUTE (GET /wallet) func (wc *WalletController) GetAll(c *gin.Context) { - body := new(model.Auth) auth := c.MustGet("auth") - body.Id = auth.(*model.Auth).Id + userId := auth.(*model.Auth).Id - fr := FilteredResponse(c) + embed, _ := c.GetQuery("embed") + flt := filter.NewWalletFilter(model.Params{Embed: embed}) + flt.UserId = userId - exception := wc.service.GetAll(c, body, fr) + fr, exception := wc.service.GetAll(c, flt) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -99,7 +101,10 @@ func (wc *WalletController) Edit(c *gin.Context) { id := c.Param("id") - wm, exception := wc.service.Edit(c, body, id) + mdl := body.ToWallet() + mdl.Id = id + + wm, exception := wc.service.Edit(c, mdl) if exception != nil { c.JSON(exception.StatusCode, exception) return @@ -121,7 +126,10 @@ func (wc *WalletController) Get(c *gin.Context) { embed, _ := c.GetQuery("embed") params.Embed = embed - fr, exception := wc.service.Get(c, id, params) + flt := filter.NewWalletFilter(*params) + flt.Id = id + + fr, exception := wc.service.Get(c, flt) if exception != nil { c.JSON(exception.StatusCode, exception) return diff --git a/pkg/filter/filter.go b/pkg/filter/filter.go index 10aa5c1..07924d9 100644 --- a/pkg/filter/filter.go +++ b/pkg/filter/filter.go @@ -1,6 +1,9 @@ package filter -import "go.uber.org/dig" +import ( + "go.uber.org/dig" + "wallet-api/pkg/model" +) /* InitializeFilters @@ -22,6 +25,13 @@ func InitializeFilters(c *dig.Container) { } type BaseFilter struct { + model.Params Id string WalletId string + UserId string +} + +type BBa interface { + BaseFilter + some() bool } diff --git a/pkg/model/api.go b/pkg/model/api.go index 787c9cc..a280ab7 100644 --- a/pkg/model/api.go +++ b/pkg/model/api.go @@ -1,6 +1,7 @@ package model type ApiModel struct { + BaseModel tableName struct{} `pg:"api,alias:api"` Api string `json:"api"` } diff --git a/pkg/model/model.go b/pkg/model/model.go index 3faa4f0..b8c6efe 100644 --- a/pkg/model/model.go +++ b/pkg/model/model.go @@ -1,6 +1,8 @@ package model -import "github.com/gin-gonic/gin" +import ( + "github.com/gin-gonic/gin" +) type FilteredResponse struct { Items interface{} `json:"items"` diff --git a/pkg/model/subscription.go b/pkg/model/subscription.go index 6229f93..a8e2e27 100644 --- a/pkg/model/subscription.go +++ b/pkg/model/subscription.go @@ -2,6 +2,7 @@ package model import ( "encoding/json" + "math" "time" ) @@ -45,6 +46,41 @@ type NewSubscriptionBody struct { Amount json.Number `json:"amount" form:"amount"` } +func (body *SubscriptionEdit) ToSubscription() *Subscription { + amount, _ := body.Amount.Float64() + tm := new(Subscription) + tm.Id = body.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) + + return tm +} + +func (body *NewSubscriptionBody) ToSubscription() *Subscription { + tm := new(Subscription) + 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() + } + return tm +} + type SubscriptionEnd struct { Id string `json:"id" form:"id"` } diff --git a/pkg/model/subscriptionType.go b/pkg/model/subscriptionType.go index 12a7cb8..1bdd153 100644 --- a/pkg/model/subscriptionType.go +++ b/pkg/model/subscriptionType.go @@ -11,3 +11,13 @@ type NewSubscriptionTypeBody struct { Name string `json:"name" form:"name"` Type string `json:"type" form:"type"` } + +func (body *NewSubscriptionTypeBody) ToSubscriptionType() *SubscriptionType { + tm := new(SubscriptionType) + + tm.Init() + tm.Name = body.Name + tm.Type = body.Type + + return tm +} \ No newline at end of file diff --git a/pkg/model/transaction.go b/pkg/model/transaction.go index 9eb8ac5..38b3b82 100644 --- a/pkg/model/transaction.go +++ b/pkg/model/transaction.go @@ -2,6 +2,7 @@ package model import ( "encoding/json" + "math" "time" ) @@ -29,6 +30,23 @@ type NewTransactionBody struct { Amount json.Number `json:"amount" form:"amount"` } +func (body *NewTransactionBody) ToTransaction() *Transaction { + tm := new(Transaction) + 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) + + if body.TransactionDate.IsZero() { + tm.TransactionDate = time.Now() + } + return tm +} + type TransactionEdit struct { Id string `json:"id" form:"id"` WalletID string `json:"walletId" form:"walletId"` @@ -38,3 +56,18 @@ type TransactionEdit struct { Description string `json:"description" form:"description"` Amount json.Number `json:"amount" form:"amount"` } + +func (body *TransactionEdit) ToTransaction() *Transaction { + tm := new(Transaction) + amount, _ := body.Amount.Float64() + + tm.Id = body.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) + + return tm +} diff --git a/pkg/model/transactionStatus.go b/pkg/model/transactionStatus.go index 39e50d2..8e17dbc 100644 --- a/pkg/model/transactionStatus.go +++ b/pkg/model/transactionStatus.go @@ -11,3 +11,11 @@ type NewTransactionStatusBody struct { Name string `json:"name" form:"name"` Status string `json:"status" form:"status"` } + +func (body *NewTransactionStatusBody) ToTransactionStatus() *TransactionStatus { + tm := new(TransactionStatus) + tm.Init() + tm.Name = body.Name + tm.Status = body.Status + return tm +} diff --git a/pkg/model/transactionType.go b/pkg/model/transactionType.go index e40ddea..7566ac9 100644 --- a/pkg/model/transactionType.go +++ b/pkg/model/transactionType.go @@ -11,3 +11,11 @@ type NewTransactionTypeBody struct { Name string `json:"name" form:"name"` Type string `json:"type" form:"type"` } + +func (body *NewTransactionTypeBody) ToTransactionType() *TransactionType { + tm := new(TransactionType) + tm.Init() + tm.Name = body.Name + tm.Type = body.Type + return tm +} diff --git a/pkg/model/wallet.go b/pkg/model/wallet.go index b0e72c6..5d0c39f 100644 --- a/pkg/model/wallet.go +++ b/pkg/model/wallet.go @@ -33,3 +33,18 @@ type WalletEdit struct { Id string `json:"id" form:"id"` Name string `json:"name" form:"name"` } + +func (body *NewWalletBody) ToWallet() *Wallet { + tm := new(Wallet) + tm.Init() + tm.Name = body.Name + tm.UserID = body.UserID + return tm +} + +func (body *WalletEdit) ToWallet() *Wallet { + tm := new(Wallet) + tm.Name = body.Name + tm.Id = body.Id + return tm +} diff --git a/pkg/repository/repository.go b/pkg/repository/repository.go index f9e9a58..348275d 100644 --- a/pkg/repository/repository.go +++ b/pkg/repository/repository.go @@ -30,14 +30,16 @@ func InitializeRepositories(c *dig.Container) { /* FilteredResponse -Adds filters to query and executes it. +Adds filter 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 { +func FilteredResponse(qry *pg.Query, mdl interface{}, params model.Params) (*model.FilteredResponse, error) { + filtered := new(model.FilteredResponse) + filtered.Params = params if filtered.Page == 0 { filtered.Page = 1 } @@ -55,5 +57,5 @@ func FilteredResponse(qry *pg.Query, mdl interface{}, filtered *model.FilteredRe filtered.TotalRecords = count filtered.Items = mdl - return err + return filtered, err } diff --git a/pkg/repository/subscription.go b/pkg/repository/subscription.go index ae0dfb8..cbb8382 100644 --- a/pkg/repository/subscription.go +++ b/pkg/repository/subscription.go @@ -63,11 +63,14 @@ Gets row from subscription table by id. *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) { +func (as *SubscriptionRepository) Get(ctx context.Context, flt filter.SubscriptionFilter) (*model.Subscription, error) { db := as.db.WithContext(ctx) tx, _ := db.Begin() defer tx.Rollback() + am := new(model.Subscription) + am.Id = flt.Id + qry := tx.Model(am) as.OnBeforeGetSubscriptionFilter(qry, &flt) err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select() @@ -93,22 +96,23 @@ Gets filtered rows from subscription table. Returns: *model.Exception: Exception payload. */ -func (as *SubscriptionRepository) GetAll(ctx context.Context, am *[]model.Subscription, filtered *model.FilteredResponse, flt *filter.SubscriptionFilter) error { +func (as *SubscriptionRepository) GetAll(ctx context.Context, flt *filter.SubscriptionFilter) (*model.FilteredResponse, error) { db := as.db.WithContext(ctx) tx, _ := db.Begin() defer tx.Rollback() + am := new([]model.Subscription) query := tx.Model(am) as.OnBeforeGetSubscriptionFilter(query, flt) - err := FilteredResponse(query, am, filtered) + filtered, err := FilteredResponse(query, am, flt.Params) if err != nil { - return err + return nil, err } tx.Commit() - return nil + return filtered, nil } /* @@ -124,17 +128,18 @@ Gets filtered rows from subscription table. Returns: *model.Exception: Exception payload. */ -func (as *SubscriptionRepository) GetAllTx(tx *pg.Tx, am *[]model.Subscription, flt *filter.SubscriptionFilter) error { +func (as *SubscriptionRepository) GetAllTx(tx *pg.Tx, flt *filter.SubscriptionFilter) (*[]model.Subscription, error) { + am := new([]model.Subscription) query := tx.Model(am) as.OnBeforeGetSubscriptionFilter(query, flt) + common.GenerateEmbed(query, flt.Embed) err := query.Select() if err != nil { - return err + return nil, err } - tx.Commit() - return nil + return am, nil } /* @@ -218,7 +223,6 @@ func (as *SubscriptionRepository) SubToTrans(subModel *model.Subscription, tx *p 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 @@ -271,8 +275,8 @@ func (as *SubscriptionRepository) SubToTrans(subModel *model.Subscription, tx *p } 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.UserId != "" { + qry.Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), flt.UserId) } if flt.WalletId != "" { qry.Where("? = ?", pg.Ident("wallet_id"), flt.WalletId) diff --git a/pkg/repository/subscriptionType.go b/pkg/repository/subscriptionType.go index 3c37301..477445a 100644 --- a/pkg/repository/subscriptionType.go +++ b/pkg/repository/subscriptionType.go @@ -54,7 +54,8 @@ Gets all rows from subscription type table. *[]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) { +func (as *SubscriptionTypeRepository) GetAll(ctx context.Context, flt *filter.SubscriptionTypeFilter) (*[]model.SubscriptionType, error) { + wm := new([]model.SubscriptionType) db := as.db.WithContext(ctx) query := db.Model(wm) diff --git a/pkg/repository/transaction.go b/pkg/repository/transaction.go index 740c37e..289fd70 100644 --- a/pkg/repository/transaction.go +++ b/pkg/repository/transaction.go @@ -37,17 +37,26 @@ Inserts *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) +func (as *TransactionRepository) New(ctx context.Context, tm *model.Transaction, tx *pg.Tx) (*model.Transaction, error) { + var commit = false + if tx == nil { + commit = true + db := as.db.WithContext(ctx) + tx, _ = db.Begin() - tx, _ := db.Begin() - defer tx.Rollback() + } + + if commit { + defer tx.Rollback() + } _, err := tx.Model(tm).Insert() if err != nil { return nil, err } - tx.Commit() + if commit { + tx.Commit() + } return tm, nil } @@ -63,48 +72,76 @@ Gets all rows from subscription type table. *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 { +func (as *TransactionRepository) GetAll(ctx context.Context, flt *filter.TransactionFilter) (*model.FilteredResponse, *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 flt.NoPending { + tsFlt := filter.NewTransactionStatusFilter(model.Params{}) + tsFlt.Status = "completed" + transactionStatus, err := as.transactionStatusRepository.GetTx(tx, tsFlt) - if err != nil { - exceptionReturn.StatusCode = 400 - exceptionReturn.ErrorCode = "400117" - exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatus\" table: %s", err) - return exceptionReturn + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400117" + exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatus\" table: %s", err) + return nil, exceptionReturn + } + + flt.TransactionStatusId = transactionStatus.Id } - flt.TransactionStatusId = transactionStatus.Id - query := tx.Model(wm) as.OnBeforeGetTransactionFilter(query, flt) - err = FilteredResponse(query, wm, filtered) + filtered, err := FilteredResponse(query, wm, flt.Params) 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, exceptionReturn } tx.Commit() - return nil + return filtered, nil +} + +/* +GetAllTx + +Gets filtered rows from transaction 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 *TransactionRepository) GetAllTx(tx *pg.Tx, flt *filter.TransactionFilter) (*[]model.Transaction, error) { + am := new([]model.Transaction) + query := tx.Model(am) + as.OnBeforeGetTransactionFilter(query, flt) + + common.GenerateEmbed(query, flt.Embed) + err := query.Select() + if err != nil { + return nil, err + } + + return am, nil } /* Check -Checks subscriptions and create transacitons. +Checks subscriptions and create transactions. Args: context.Context: Application context string: Relations to embed @@ -112,32 +149,37 @@ Checks subscriptions and create transacitons. *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 { +func (as *TransactionRepository) Check(ctx context.Context, flt *filter.TransactionFilter) (*model.FilteredResponse, *model.Exception) { db := as.db.WithContext(ctx) wm := new([]model.Transaction) - sm := new([]model.Subscription) - transactionStatus := new(model.TransactionStatus) exceptionReturn := new(model.Exception) + filtered := new(model.FilteredResponse) tx, _ := db.Begin() defer tx.Rollback() tsFlt := filter.NewTransactionStatusFilter(model.Params{}) tsFlt.Status = "pending" - _, err := as.transactionStatusRepository.GetTx(tx, transactionStatus, tsFlt) + transactionStatus, err := as.transactionStatusRepository.GetTx(tx, tsFlt) if err != nil { exceptionReturn.StatusCode = 400 exceptionReturn.ErrorCode = "400119" exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatus\" table: %s", err) - return exceptionReturn + return nil, exceptionReturn } flt.TransactionStatusId = transactionStatus.Id smFlt := filter.NewSubscriptionFilter(model.Params{}) smFlt.Id = flt.Id smFlt.WalletId = flt.WalletId - as.subscriptionRepository.GetAllTx(tx, sm, smFlt) + sm, err := as.subscriptionRepository.GetAllTx(tx, smFlt) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400137" + exceptionReturn.Message = fmt.Sprintf("Error selecting rows in \"subscription\" table: %s", err) + return nil, exceptionReturn + } for _, sub := range *sm { if sub.HasNew() { @@ -147,16 +189,16 @@ func (as *TransactionRepository) Check(ctx context.Context, filtered *model.Filt qry := tx.Model(wm) as.OnBeforeGetTransactionFilter(qry, flt) - err = FilteredResponse(qry, wm, filtered) + filtered, err = FilteredResponse(qry, wm, flt.Params) 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, exceptionReturn } tx.Commit() - return nil + return filtered, nil } /* @@ -195,7 +237,7 @@ func (as *TransactionRepository) Edit(ctx context.Context, tm *model.Transaction } /* -Bulk Edit +BulkEdit Updates row in transaction table by id. @@ -239,6 +281,7 @@ Gets row from transaction table by id. func (as *TransactionRepository) Get(ctx context.Context, flt *filter.TransactionFilter) (*model.Transaction, error) { db := as.db.WithContext(ctx) wm := new(model.Transaction) + wm.Id = flt.Id tx, _ := db.Begin() defer tx.Rollback() @@ -259,10 +302,15 @@ func (as *TransactionRepository) OnBeforeGetTransactionFilter(qry *orm.Query, fl 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.UserId != "" { + qry.Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), flt.UserId) } - if flt.NoPending && flt.TransactionStatusId != "" { + if flt.TransactionStatusId != "" { qry.Where("? = ?", pg.Ident("transaction_status_id"), flt.TransactionStatusId) } } + +func (as *TransactionRepository) CreateTx(ctx context.Context) (*pg.Tx, error) { + db := as.db.WithContext(ctx) + return db.Begin() +} diff --git a/pkg/repository/transactionStatus.go b/pkg/repository/transactionStatus.go index 1fdf042..778cc4b 100644 --- a/pkg/repository/transactionStatus.go +++ b/pkg/repository/transactionStatus.go @@ -2,7 +2,6 @@ package repository import ( "context" - "fmt" "github.com/go-pg/pg/v10/orm" "wallet-api/pkg/filter" "wallet-api/pkg/model" @@ -33,22 +32,12 @@ Inserts new row to transaction status table. *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) { +func (as *TransactionStatusRepository) New(ctx context.Context, tm *model.TransactionStatus) (*model.TransactionStatus, error) { 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 nil, err } return tm, nil @@ -66,19 +55,29 @@ Gets all rows from transaction status table. *[]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) +func (as *TransactionStatusRepository) GetAll(ctx context.Context, flt *filter.TransactionStatusFilter, tx *pg.Tx) (*[]model.TransactionStatus, error) { + var commit = false + if tx == nil { + commit = true + db := as.db.WithContext(ctx) + tx, _ = db.Begin() + } + + if commit { + defer tx.Rollback() + } wm := new([]model.TransactionStatus) - exceptionReturn := new(model.Exception) - query := db.Model(wm) - err := common.GenerateEmbed(query, embed).Select() + query := tx.Model(wm) + as.OnBeforeGetTransactionStatusFilter(query, flt) + err := common.GenerateEmbed(query, flt.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 nil, err + } + + if commit { + tx.Commit() } return wm, nil @@ -98,18 +97,25 @@ Gets row from transactionStatus table by id. *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() +func (as *TransactionStatusRepository) Get(ctx context.Context, flt *filter.TransactionStatusFilter, tx *pg.Tx) (*model.TransactionStatus, error) { + am := new(model.TransactionStatus) + commit := false + if tx == nil { + commit = true + db := as.db.WithContext(ctx) + tx, _ = db.Begin() + defer tx.Rollback() + } qry := tx.Model(am) - err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select() + err := common.GenerateEmbed(qry, flt.Embed).Select() if err != nil { return nil, err } - tx.Commit() + if commit { + tx.Commit() + } return am, nil } @@ -128,10 +134,11 @@ Gets row from transactionStatus table by id. *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) { +func (as *TransactionStatusRepository) GetTx(tx *pg.Tx, flt *filter.TransactionStatusFilter) (*model.TransactionStatus, error) { + am := new(model.TransactionStatus) qry := tx.Model(am) as.OnBeforeGetTransactionStatusFilter(qry, flt) - err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select() + err := common.GenerateEmbed(qry, flt.Embed).Select() if err != nil { return nil, err } @@ -140,6 +147,9 @@ func (as *TransactionStatusRepository) GetTx(tx *pg.Tx, am *model.TransactionSta } func (as *TransactionStatusRepository) OnBeforeGetTransactionStatusFilter(qry *orm.Query, flt *filter.TransactionStatusFilter) { + if flt.Id != "" { + qry.Where("? = ?", pg.Ident("id"), flt.Id) + } if flt.Status != "" { qry.Where("? = ?", pg.Ident("status"), flt.Status) } diff --git a/pkg/repository/transactionType.go b/pkg/repository/transactionType.go index 6ed029f..a69a9ff 100644 --- a/pkg/repository/transactionType.go +++ b/pkg/repository/transactionType.go @@ -2,7 +2,7 @@ package repository import ( "context" - "fmt" + "wallet-api/pkg/filter" "wallet-api/pkg/model" "wallet-api/pkg/utl/common" @@ -31,22 +31,12 @@ Inserts new row to transaction type table. *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) { +func (as *TransactionTypeRepository) New(ctx context.Context, tm *model.TransactionType) (*model.TransactionType, error) { 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 nil, err } return tm, nil @@ -64,19 +54,15 @@ Gets all rows from transaction type table. *[]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) { +func (as *TransactionTypeRepository) GetAll(ctx context.Context, flt *filter.TransactionTypeFilter) (*[]model.TransactionType, error) { db := as.db.WithContext(ctx) wm := new([]model.TransactionType) - exceptionReturn := new(model.Exception) query := db.Model(wm) - err := common.GenerateEmbed(query, embed).Select() + err := common.GenerateEmbed(query, flt.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 nil, err } return wm, nil diff --git a/pkg/repository/user.go b/pkg/repository/user.go index b27eb51..0fa4b97 100644 --- a/pkg/repository/user.go +++ b/pkg/repository/user.go @@ -4,6 +4,7 @@ import ( "context" "os" "time" + "wallet-api/pkg/filter" "wallet-api/pkg/model" "wallet-api/pkg/utl/common" "wallet-api/pkg/utl/configs" @@ -24,6 +25,118 @@ func NewUserRepository(db *pg.DB) *UserRepository { } } +/* +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 (us *UserRepository) Get(ctx context.Context, flt *filter.UserFilter, tx *pg.Tx) (*model.User, error) { + wm := new(model.User) + wm.Id = flt.Id + + commit := false + if tx == nil { + commit = true + db := us.db.WithContext(ctx) + tx, _ := db.Begin() + defer tx.Rollback() + } + + qry := tx.Model(wm) + err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select() + if err != nil { + return nil, err + } + + if commit { + tx.Commit() + } + + return wm, 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 (us *UserRepository) Edit(ctx context.Context, tm *model.User, tx *pg.Tx) (*model.User, error) { + commit := false + if tx == nil { + commit = true + db := us.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 + } + + if commit { + tx.Commit() + } + + return tm, nil +} + +/* +Check + +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 *UserRepository) Check(ctx context.Context, tx *pg.Tx, checkBody *model.User) (*model.User, error) { + check := new(model.User) + + commit := false + if tx == nil { + commit = true + db := us.db.WithContext(ctx) + tx, _ := db.Begin() + defer tx.Rollback() + } + + err := tx.Model(check).Where("? = ?", pg.Ident("username"), checkBody.Username).WhereOr("? = ?", pg.Ident("email"), checkBody.Email).Select() + if err != nil { + return nil, err + } + if commit { + tx.Commit() + } + return check, nil +} + /* Create @@ -36,38 +149,31 @@ Inserts new row to users table. *model.User: User object from database *model.Exception */ -func (us *UserRepository) 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 +func (us *UserRepository) Create(ctx context.Context, tx *pg.Tx, registerBody *model.User) (*model.User, error) { + commit := false + if tx == nil { + commit = true + db := us.db.WithContext(ctx) + tx, _ := db.Begin() + defer tx.Rollback() } - hashedPassword, err := bcrypt.GenerateFromPassword([]byte(registerBody.Password), bcrypt.DefaultCost) - common.CheckError(err) - - registerBody.Password = string(hashedPassword) - _, err = tx.Model(registerBody).Insert() + _, err := tx.Model(registerBody).Insert() if err != nil { - exceptionReturn.Message = "Error creating user" - exceptionReturn.ErrorCode = "400102" - exceptionReturn.StatusCode = 400 + return nil, err } - tx.Commit() + if commit { + tx.Commit() + } - return registerBody, exceptionReturn + return registerBody, nil +} + +func (us *UserRepository) CreateTx(ctx context.Context) (*pg.Tx, error) { + db := us.db.WithContext(ctx) + return db.Begin() } /* diff --git a/pkg/repository/wallet.go b/pkg/repository/wallet.go index ea983ee..cf22d7c 100644 --- a/pkg/repository/wallet.go +++ b/pkg/repository/wallet.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "time" + "wallet-api/pkg/filter" "wallet-api/pkg/model" "wallet-api/pkg/utl/common" @@ -34,20 +35,11 @@ Inserts row to wallets table. *model.Wallet: Wallet object from database. *model.Exception: Exception payload. */ -func (as *WalletRepository) New(ctx context.Context, am *model.NewWalletBody) (*model.Wallet, *model.Exception) { +func (as *WalletRepository) New(ctx context.Context, walletModel *model.Wallet) (*model.Wallet, error) { 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 nil, err } return walletModel, nil } @@ -65,23 +57,15 @@ Updates row in wallets table by id. *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) { +func (as *WalletRepository) Edit(ctx context.Context, tm *model.Wallet) (*model.Wallet, error) { 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 + return nil, err } tx.Commit() @@ -102,23 +86,19 @@ Gets row in wallets table by id. *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) { +func (as *WalletRepository) Get(ctx context.Context, flt *filter.WalletFilter) (*model.Wallet, error) { db := as.db.WithContext(ctx) - exceptionReturn := new(model.Exception) wm := new(model.Wallet) - wm.Id = id + wm.Id = flt.Id tx, _ := db.Begin() defer tx.Rollback() qry := tx.Model(wm) - err := common.GenerateEmbed(qry, params.Embed).WherePK().Select() + err := common.GenerateEmbed(qry, flt.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 + return nil, err } tx.Commit() @@ -138,20 +118,20 @@ Gets filtered rows from wallets table. Returns: *model.Exception: Exception payload. */ -func (as *WalletRepository) GetAll(ctx context.Context, am *model.Auth, filtered *model.FilteredResponse) *model.Exception { +func (as *WalletRepository) GetAll(ctx context.Context, flt *filter.WalletFilter) (*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) + query := db.Model(wm).Where("? = ?", pg.Ident("user_id"), flt.UserId) + filtered, err := FilteredResponse(query, wm, flt.Params) 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, exceptionReturn } - return nil + return filtered, nil } /* @@ -169,7 +149,7 @@ Calculates previous month, current and next month totals. *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) { +func (as *WalletRepository) GetHeader(ctx context.Context, flt *filter.WalletHeaderFilter) (*model.WalletHeader, *model.Exception) { db := as.db.WithContext(ctx) wm := new(model.WalletHeader) @@ -189,9 +169,9 @@ func (as *WalletRepository) GetHeader(ctx context.Context, am *model.Auth, walle 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 := tx.Model(subscriptions).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), flt.UserId).Relation("TransactionType").Relation("SubscriptionType") + if flt.WalletId != "" { + query2.Where("? = ?", pg.Ident("wallet_id"), flt.WalletId) } query2.Select() if err != nil { @@ -210,9 +190,9 @@ func (as *WalletRepository) GetHeader(ctx context.Context, am *model.Auth, walle 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 := tx.Model(transactions).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), flt.UserId).Relation("TransactionType") + if flt.WalletId != "" { + query.Where("? = ?", pg.Ident("wallet_id"), flt.WalletId) } query = query.Where("? = ?", pg.Ident("transaction_status_id"), transactionStatus.Id) query.Select() @@ -287,11 +267,16 @@ func (as *WalletRepository) GetHeader(ctx context.Context, am *model.Auth, walle } wm.Currency = "USD" - wm.WalletId = walletId + wm.WalletId = flt.WalletId return wm, nil } +func (as *WalletRepository) CreateTx(ctx context.Context) (*pg.Tx, error) { + db := as.db.WithContext(ctx) + return db.Begin() +} + /* addWhere diff --git a/pkg/service/api.go b/pkg/service/api.go index 4aa8d96..fd2278d 100644 --- a/pkg/service/api.go +++ b/pkg/service/api.go @@ -12,7 +12,7 @@ type ApiService struct { func NewApiService(repository *repository.ApiRepository) *ApiService { return &ApiService{ - repository, + repository: repository, } } @@ -42,6 +42,6 @@ Starts database migration. *model.MessageResponse: Message response object. *model.Exception: Exception response object. */ -func (as ApiService) PostMigrate(ctx context.Context, version string) (*model.MessageResponse, *model.Exception) { +func (as ApiService) PostMigrate(ctx context.Context, version string) []error { return as.repository.PostMigrate(ctx, version) } diff --git a/pkg/service/service.go b/pkg/service/service.go index 5639788..7eaa3cc 100644 --- a/pkg/service/service.go +++ b/pkg/service/service.go @@ -1,8 +1,9 @@ package service import ( - "go.uber.org/dig" "wallet-api/pkg/repository" + + "go.uber.org/dig" ) /* diff --git a/pkg/service/subscription.go b/pkg/service/subscription.go index adf42e3..2f59401 100644 --- a/pkg/service/subscription.go +++ b/pkg/service/subscription.go @@ -3,7 +3,6 @@ package service import ( "context" "fmt" - "math" "time" "wallet-api/pkg/filter" "wallet-api/pkg/model" @@ -16,7 +15,7 @@ type SubscriptionService struct { func NewSubscriptionService(repository *repository.SubscriptionRepository) *SubscriptionService { return &SubscriptionService{ - repository, + repository: repository, } } @@ -32,28 +31,9 @@ Inserts new row to subscription table. *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) +func (as *SubscriptionService) New(ctx context.Context, tm *model.Subscription) (*model.Subscription, *model.Exception) { 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 { @@ -79,11 +59,9 @@ Gets row from subscription table by id. *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) { +func (as *SubscriptionService) Get(ctx context.Context, 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) + response, err := as.repository.Get(ctx, flt) if err != nil { exceptionReturn.StatusCode = 400 exceptionReturn.ErrorCode = "400129" @@ -107,19 +85,18 @@ Gets filtered rows from subscription table. Returns: *model.Exception: Exception payload. */ -func (as *SubscriptionService) GetAll(ctx context.Context, flt *filter.SubscriptionFilter, filtered *model.FilteredResponse) *model.Exception { - wm := new([]model.Subscription) +func (as *SubscriptionService) GetAll(ctx context.Context, flt *filter.SubscriptionFilter) (*model.FilteredResponse, *model.Exception) { exceptionReturn := new(model.Exception) - err := as.repository.GetAll(ctx, wm, filtered, flt) + filtered, err := as.repository.GetAll(ctx, 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, exceptionReturn } - return nil + return filtered, nil } /* @@ -135,17 +112,9 @@ Updates row from subscription table by id. *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) +func (as *SubscriptionService) Edit(ctx context.Context, tm *model.Subscription) (*model.Subscription, *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) + exceptionReturn := new(model.Exception) response, err := as.repository.Edit(ctx, tm) if err != nil { diff --git a/pkg/service/subscriptionType.go b/pkg/service/subscriptionType.go index 87c8696..e1e27d8 100644 --- a/pkg/service/subscriptionType.go +++ b/pkg/service/subscriptionType.go @@ -14,7 +14,7 @@ type SubscriptionTypeService struct { func NewSubscriptionTypeService(repository *repository.SubscriptionTypeRepository) *SubscriptionTypeService { return &SubscriptionTypeService{ - repository, + repository: repository, } } @@ -30,14 +30,9 @@ Inserts new row to subscription type table. *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) +func (as *SubscriptionTypeService) New(ctx context.Context, tm *model.SubscriptionType) (*model.SubscriptionType, *model.Exception) { 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 @@ -61,14 +56,10 @@ Gets all rows from subscription type table. *[]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) +func (as *SubscriptionTypeService) GetAll(ctx context.Context, flt *filter.SubscriptionTypeFilter) (*[]model.SubscriptionType, *model.Exception) { exceptionReturn := new(model.Exception) - flt := filter.NewSubscriptionTypeFilter(model.Params{ - Embed: embed, - }) - response, err := as.repository.GetAll(ctx, flt, wm) + response, err := as.repository.GetAll(ctx, flt) if err != nil { exceptionReturn.StatusCode = 400 exceptionReturn.ErrorCode = "400135" diff --git a/pkg/service/transaction.go b/pkg/service/transaction.go index b4f02ac..1c27d12 100644 --- a/pkg/service/transaction.go +++ b/pkg/service/transaction.go @@ -3,24 +3,23 @@ package service import ( "context" "fmt" - "math" - "time" "wallet-api/pkg/filter" "wallet-api/pkg/model" "wallet-api/pkg/repository" + "wallet-api/pkg/utl/common" ) type TransactionService struct { - repository *repository.TransactionRepository - subscriptionRepository *repository.SubscriptionRepository - transactionStatusService *TransactionStatusService + repository *repository.TransactionRepository + subscriptionRepository *repository.SubscriptionRepository + transactionStatusRepository *repository.TransactionStatusRepository } -func NewTransactionService(repository *repository.TransactionRepository, sr *repository.SubscriptionRepository, tss *TransactionStatusService) *TransactionService { +func NewTransactionService(repository *repository.TransactionRepository, sr *repository.SubscriptionRepository, tsr *repository.TransactionStatusRepository) *TransactionService { return &TransactionService{ - repository: repository, - subscriptionRepository: sr, - transactionStatusService: tss, + repository: repository, + subscriptionRepository: sr, + transactionStatusRepository: tsr, } } @@ -36,39 +35,41 @@ Inserts *model.Transaction: Transaction object *model.Exception: Exception payload. */ -func (as *TransactionService) New(ctx context.Context, body *model.NewTransactionBody) (*model.Transaction, *model.Exception) { +func (as *TransactionService) New(ctx context.Context, tm *model.Transaction) (*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 { + tx, err := as.repository.CreateTx(ctx) + defer tx.Rollback() + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400136" + exceptionReturn.Message = fmt.Sprintf("Error beginning transaction: %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() + tsFlt := filter.NewTransactionStatusFilter(model.Params{}) + tsFlt.Status = "completed" + transactionStatuses, err := as.transactionStatusRepository.GetAll(ctx, tsFlt, tx) + if err != nil { + exceptionReturn.StatusCode = 400 + exceptionReturn.ErrorCode = "400138" + exceptionReturn.Message = fmt.Sprintf("Error fetching transactionStatus: %s", err) + return nil, exceptionReturn } - response, err := as.repository.New(ctx, tm) + var transactionStatus = common.Find[model.TransactionStatus](transactionStatuses, func(status *model.TransactionStatus) bool { + return status.Status == "completed" + }) + tm.TransactionStatusID = transactionStatus.Id + + response, err := as.repository.New(ctx, tm, tx) 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 response, nil } @@ -84,23 +85,23 @@ Gets all rows from subscription type table. *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 { +func (as *TransactionService) GetAll(ctx context.Context, flt *filter.TransactionFilter) (*model.FilteredResponse, *model.Exception) { exceptionReturn := new(model.Exception) - err := as.repository.GetAll(ctx, filtered, flt) + filtered, err := as.repository.GetAll(ctx, 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, exceptionReturn } - return nil + return filtered, nil } /* Check -Checks subscriptions and create transacitons. +Checks subscriptions and create transactions. Args: context.Context: Application context string: Relations to embed @@ -108,18 +109,17 @@ Checks subscriptions and create transacitons. *model.Exception: Exception payload. */ // Gets filtered rows from transaction table. -func (as *TransactionService) Check(ctx context.Context, flt *filter.TransactionFilter) *model.Exception { +func (as *TransactionService) Check(ctx context.Context, flt *filter.TransactionFilter) (*model.FilteredResponse, *model.Exception) { exceptionReturn := new(model.Exception) - filtered := new(model.FilteredResponse) - err := as.repository.Check(ctx, filtered, flt) + filtered, err := as.repository.Check(ctx, 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, exceptionReturn } - return nil + return filtered, nil } /* @@ -135,20 +135,9 @@ Updates row in transaction table by id. *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() - +func (as *TransactionService) Edit(ctx context.Context, tm *model.Transaction) (*model.Transaction, *model.Exception) { 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 { @@ -162,7 +151,7 @@ func (as *TransactionService) Edit(ctx context.Context, body *model.TransactionE } /* -Bulk Edit +BulkEdit Updates row in transaction table by id. @@ -174,25 +163,9 @@ Updates row in transaction table by id. *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) +func (as *TransactionService) BulkEdit(ctx context.Context, transactions *[]model.Transaction) (*[]model.Transaction, *model.Exception) { 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 diff --git a/pkg/service/transactionStatus.go b/pkg/service/transactionStatus.go index f6fe470..e0606c8 100644 --- a/pkg/service/transactionStatus.go +++ b/pkg/service/transactionStatus.go @@ -5,18 +5,16 @@ import ( "fmt" "wallet-api/pkg/filter" "wallet-api/pkg/model" - "wallet-api/pkg/utl/common" - - "github.com/go-pg/pg/v10" + "wallet-api/pkg/repository" ) type TransactionStatusService struct { - db *pg.DB + repository *repository.TransactionStatusRepository } -func NewTransactionStatusService(db *pg.DB) *TransactionStatusService { +func NewTransactionStatusService(repository *repository.TransactionStatusRepository) *TransactionStatusService { return &TransactionStatusService{ - db: db, + repository: repository, } } @@ -32,17 +30,10 @@ Inserts new row to transaction status table. *model.TransactionType: Transaction Type object from database. *model.Exception: Exception payload. */ -func (as *TransactionStatusService) New(ctx context.Context, body *model.NewTransactionStatusBody) (*model.TransactionStatus, *model.Exception) { - db := as.db.WithContext(ctx) - - tm := new(model.TransactionStatus) +func (as *TransactionStatusService) New(ctx context.Context, tm *model.TransactionStatus) (*model.TransactionStatus, *model.Exception) { exceptionReturn := new(model.Exception) - tm.Init() - tm.Name = body.Name - tm.Status = body.Status - - _, err := db.Model(tm).Insert() + response, err := as.repository.New(ctx, tm) if err != nil { exceptionReturn.StatusCode = 400 exceptionReturn.ErrorCode = "400123" @@ -50,7 +41,7 @@ func (as *TransactionStatusService) New(ctx context.Context, body *model.NewTran return nil, exceptionReturn } - return tm, nil + return response, nil } /* @@ -65,14 +56,10 @@ Gets all rows from transaction status table. *[]model.TransactionStatus: List of Transaction status objects from database. *model.Exception: Exception payload. */ -func (as *TransactionStatusService) GetAll(ctx context.Context, embed string) (*[]model.TransactionStatus, *model.Exception) { - db := as.db.WithContext(ctx) - - wm := new([]model.TransactionStatus) +func (as *TransactionStatusService) GetAll(ctx context.Context, flt *filter.TransactionStatusFilter) (*[]model.TransactionStatus, *model.Exception) { exceptionReturn := new(model.Exception) - query := db.Model(wm) - err := common.GenerateEmbed(query, embed).Select() + response, err := as.repository.GetAll(ctx, flt, nil) if err != nil { exceptionReturn.StatusCode = 400 exceptionReturn.ErrorCode = "400124" @@ -80,7 +67,7 @@ func (as *TransactionStatusService) GetAll(ctx context.Context, embed string) (* return nil, exceptionReturn } - return wm, nil + return response, nil } func (as *TransactionStatusService) Get(ctx context.Context, flt *filter.TransactionStatusFilter) (*model.TransactionStatus, *model.Exception) { @@ -92,7 +79,7 @@ func (as *TransactionStatusService) Get(ctx context.Context, flt *filter.Transac if flt.Status != "" { transactionStatus.Status = flt.Status } - response, err := as.repository.Get(ctx, wm, flt) + response, err := as.repository.Get(ctx, flt, nil) if err != nil { exceptionReturn.StatusCode = 400 exceptionReturn.ErrorCode = "400129" diff --git a/pkg/service/transactionType.go b/pkg/service/transactionType.go index 3b6007b..447df56 100644 --- a/pkg/service/transactionType.go +++ b/pkg/service/transactionType.go @@ -3,19 +3,18 @@ package service import ( "context" "fmt" + "wallet-api/pkg/filter" "wallet-api/pkg/model" - "wallet-api/pkg/utl/common" - - "github.com/go-pg/pg/v10" + "wallet-api/pkg/repository" ) type TransactionTypeService struct { - db *pg.DB + repository *repository.TransactionTypeRepository } -func NewTransactionTypeService(db *pg.DB) *TransactionTypeService { +func NewTransactionTypeService(repository *repository.TransactionTypeRepository) *TransactionTypeService { return &TransactionTypeService{ - db: db, + repository: repository, } } @@ -31,17 +30,10 @@ Inserts new row to transaction type table. *model.TransactionType: Transaction Type object from database. *model.Exception: Exception payload. */ -func (as *TransactionTypeService) New(ctx context.Context, body *model.NewTransactionTypeBody) (*model.TransactionType, *model.Exception) { - db := as.db.WithContext(ctx) - - tm := new(model.TransactionType) +func (as *TransactionTypeService) New(ctx context.Context, tm *model.TransactionType) (*model.TransactionType, *model.Exception) { exceptionReturn := new(model.Exception) - tm.Init() - tm.Name = body.Name - tm.Type = body.Type - - _, err := db.Model(tm).Insert() + response, err := as.repository.New(ctx, tm) if err != nil { exceptionReturn.StatusCode = 400 exceptionReturn.ErrorCode = "400125" @@ -49,7 +41,7 @@ func (as *TransactionTypeService) New(ctx context.Context, body *model.NewTransa return nil, exceptionReturn } - return tm, nil + return response, nil } /* @@ -64,14 +56,10 @@ Gets all rows from transaction type table. *[]model.TransactionType: List of Transaction type objects from database. *model.Exception: Exception payload. */ -func (as *TransactionTypeService) GetAll(ctx context.Context, embed string) (*[]model.TransactionType, *model.Exception) { - db := as.db.WithContext(ctx) - - wm := new([]model.TransactionType) +func (as *TransactionTypeService) GetAll(ctx context.Context, flt *filter.TransactionTypeFilter) (*[]model.TransactionType, *model.Exception) { exceptionReturn := new(model.Exception) - query := db.Model(wm) - err := common.GenerateEmbed(query, embed).Select() + response, err := as.repository.GetAll(ctx, flt) if err != nil { exceptionReturn.StatusCode = 400 exceptionReturn.ErrorCode = "400133" @@ -79,5 +67,5 @@ func (as *TransactionTypeService) GetAll(ctx context.Context, embed string) (*[] return nil, exceptionReturn } - return wm, nil + return response, nil } diff --git a/pkg/service/user.go b/pkg/service/user.go index 73a1283..e448451 100644 --- a/pkg/service/user.go +++ b/pkg/service/user.go @@ -4,23 +4,23 @@ import ( "context" "os" "time" + "wallet-api/pkg/filter" "wallet-api/pkg/model" + "wallet-api/pkg/repository" "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 + repository *repository.UserRepository } -func NewUserService(db *pg.DB) *UserService { +func NewUserService(repository *repository.UserRepository) *UserService { return &UserService{ - db: db, + repository: repository, } } @@ -37,37 +37,41 @@ Inserts new row to users table. *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() + tx, _ := us.repository.CreateTx(ctx) defer tx.Rollback() - tx.Model(check).Where("? = ?", pg.Ident("username"), registerBody.Username).WhereOr("? = ?", pg.Ident("email"), registerBody.Email).Select() + check, err := us.repository.Check(ctx, tx, registerBody) + if err != nil { + exceptionReturn.Message = "Error checking user" + exceptionReturn.ErrorCode = "400139" + exceptionReturn.StatusCode = 400 + return nil, exceptionReturn + } + if check.Username != "" || check.Email != "" { exceptionReturn.Message = "User already exists" exceptionReturn.ErrorCode = "400101" exceptionReturn.StatusCode = 400 - return check, exceptionReturn + return nil, exceptionReturn } hashedPassword, err := bcrypt.GenerateFromPassword([]byte(registerBody.Password), bcrypt.DefaultCost) common.CheckError(err) registerBody.Password = string(hashedPassword) - _, err = tx.Model(registerBody).Insert() - + us.repository.Create(ctx, tx, registerBody) if err != nil { exceptionReturn.Message = "Error creating user" exceptionReturn.ErrorCode = "400102" exceptionReturn.StatusCode = 400 + return nil, exceptionReturn } tx.Commit() - return registerBody, exceptionReturn + return registerBody, nil } /* @@ -82,17 +86,24 @@ Gets row from users table by email and valid password. *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) +func (us *UserService) Login(ctx context.Context, body *model.Login) (*model.Token, *model.Exception) { exceptionReturn := new(model.Exception) tokenPayload := new(model.Token) + loginBody := new(model.User) - tx, _ := db.Begin() + loginBody.Email = body.Email + loginBody.Username = body.Email + + tx, _ := us.repository.CreateTx(ctx) defer tx.Rollback() - tx.Model(check).Where("? = ?", pg.Ident("email"), loginBody.Email).Select() + check, err := us.repository.Check(ctx, tx, loginBody) + if err != nil { + exceptionReturn.Message = "Error checking user" + exceptionReturn.ErrorCode = "400139" + exceptionReturn.StatusCode = 400 + return nil, exceptionReturn + } if check.Email == "" { exceptionReturn.Message = "Email not found" @@ -108,20 +119,18 @@ func (us *UserService) Login(ctx context.Context, loginBody *model.Login) (*mode return tokenPayload, exceptionReturn } - if bcrypt.CompareHashAndPassword([]byte(check.Password), []byte(loginBody.Password)) != nil { + if bcrypt.CompareHashAndPassword([]byte(check.Password), []byte(body.Password)) != nil { exceptionReturn.Message = "Incorrect password" exceptionReturn.ErrorCode = "400104" exceptionReturn.StatusCode = 400 return tokenPayload, exceptionReturn } - token, err := CreateToken(check, loginBody.RememberMe) + token, err := CreateToken(check, body.RememberMe) common.CheckError(err) tokenPayload.Token = token - tx.Commit() - return tokenPayload, exceptionReturn } @@ -139,39 +148,35 @@ IsActive column is set to false *model.MessageResponse *model.Exception */ -func (us *UserService) Deactivate(ctx context.Context, auth *model.Auth) (*model.MessageResponse, *model.Exception) { - db := us.db.WithContext(ctx) - +func (us *UserService) Deactivate(ctx context.Context, flt *filter.UserFilter) (*model.MessageResponse, *model.Exception) { mm := new(model.MessageResponse) me := new(model.Exception) - um := new(model.User) - tx, _ := db.Begin() + tx, _ := us.repository.CreateTx(ctx) defer tx.Rollback() - err := tx.Model(um).Where("? = ?", pg.Ident("id"), auth.Id).Select() - + um, err := us.repository.Get(ctx, flt, tx) if err != nil { me.ErrorCode = "404101" me.Message = "User not found" me.StatusCode = 404 - return mm, me + return nil, me } - um.IsActive = false - _, err = tx.Model(um).Where("? = ?", pg.Ident("id"), auth.Id).Update() + um.IsActive = false + _, err = us.repository.Edit(ctx, um, tx) if err != nil { me.ErrorCode = "400105" me.Message = "Could not deactivate user" me.StatusCode = 400 - return mm, me + return nil, me } mm.Message = "User successfully deactivated." tx.Commit() - return mm, me + return mm, nil } /* diff --git a/pkg/service/wallet.go b/pkg/service/wallet.go index a87bb51..242d3ac 100644 --- a/pkg/service/wallet.go +++ b/pkg/service/wallet.go @@ -4,21 +4,24 @@ import ( "context" "fmt" "time" + "wallet-api/pkg/filter" "wallet-api/pkg/model" - "wallet-api/pkg/utl/common" - - "github.com/go-pg/pg/v10" + "wallet-api/pkg/repository" ) type WalletService struct { - db *pg.DB - subscriptionService *SubscriptionService + repository *repository.WalletRepository + subscriptionRepository *repository.SubscriptionRepository + transactionStatusRepository *repository.TransactionStatusRepository + transactionRepository *repository.TransactionRepository } -func NewWalletService(db *pg.DB, ss *SubscriptionService) *WalletService { +func NewWalletService(repository *repository.WalletRepository, subscriptionRepository *repository.SubscriptionRepository, transactionStatusRepository *repository.TransactionStatusRepository, transactionRepository *repository.TransactionRepository) *WalletService { return &WalletService{ - db: db, - subscriptionService: ss, + repository: repository, + subscriptionRepository: subscriptionRepository, + transactionStatusRepository: transactionStatusRepository, + transactionRepository: transactionRepository, } } @@ -35,21 +38,19 @@ Inserts row to wallets table. *model.Exception: Exception payload. */ func (as *WalletService) 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() + response, err := as.repository.New(ctx, walletModel) 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 + return response, nil } /* @@ -65,28 +66,17 @@ Updates row in wallets table by id. *model.Wallet: Wallet object from database. *model.Exception: Exception payload. */ -func (as *WalletService) Edit(ctx context.Context, body *model.WalletEdit, id string) (*model.Wallet, *model.Exception) { - db := as.db.WithContext(ctx) - +func (as *WalletService) Edit(ctx context.Context, tm *model.Wallet) (*model.Wallet, *model.Exception) { 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() + response, err := as.repository.Edit(ctx, tm) 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 + return response, nil } /* @@ -102,18 +92,10 @@ Gets row in wallets table by id. *model.Wallet: Wallet object from database *model.Exception: Exception payload. */ -func (as *WalletService) Get(ctx context.Context, id string, params *model.Params) (*model.Wallet, *model.Exception) { - db := as.db.WithContext(ctx) +func (as *WalletService) Get(ctx context.Context, flt *filter.WalletFilter) (*model.Wallet, *model.Exception) { 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() + response, err := as.repository.Get(ctx, flt) if err != nil { exceptionReturn.StatusCode = 400 exceptionReturn.ErrorCode = "400128" @@ -121,9 +103,7 @@ func (as *WalletService) Get(ctx context.Context, id string, params *model.Param return nil, exceptionReturn } - tx.Commit() - - return wm, nil + return response, nil } /* @@ -138,20 +118,17 @@ Gets filtered rows from wallets table. Returns: *model.Exception: Exception payload. */ -func (as *WalletService) GetAll(ctx context.Context, am *model.Auth, filtered *model.FilteredResponse) *model.Exception { +func (as *WalletService) GetAll(ctx context.Context, flt *filter.WalletFilter) (*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) + response, err := as.repository.GetAll(ctx, flt) 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, exceptionReturn } - return nil + return response, nil } /* @@ -169,31 +146,30 @@ Calculates previous month, current and next month totals. *model.WalletHeader: generated wallet header object *model.Exception: Exception payload. */ -func (as *WalletService) GetHeader(ctx context.Context, am *model.Auth, walletId string) (*model.WalletHeader, *model.Exception) { - db := as.db.WithContext(ctx) - +func (as *WalletService) GetHeader(ctx context.Context, flt *filter.WalletHeaderFilter) (*model.WalletHeader, *model.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() + tx, _ := as.repository.CreateTx(ctx) defer tx.Rollback() - err := tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "completed").Select() + trStFlt := filter.NewTransactionStatusFilter(model.Params{}) + trStFlt.Status = "completed" + transactionStatuses, err := as.transactionStatusRepository.GetAll(ctx, trStFlt, tx) + transactionStatus := (*transactionStatuses)[0] 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() + + subFlt := filter.NewSubscriptionFilter(model.Params{Embed: "TransactionType,SubscriptionType"}) + subFlt.WalletId = flt.WalletId + subscriptions, err = as.subscriptionRepository.GetAllTx(tx, subFlt) if err != nil { exceptionReturn.StatusCode = 400 exceptionReturn.ErrorCode = "400131" @@ -210,12 +186,10 @@ func (as *WalletService) GetHeader(ctx context.Context, am *model.Auth, walletId 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() + trFlt := filter.NewTransactionFilter(model.Params{Embed: "TransactionType,Wallet"}) + trFlt.WalletId = flt.WalletId + trFlt.TransactionStatusId = transactionStatus.Id + transactions, err = as.transactionRepository.GetAllTx(tx, trFlt) if err != nil { exceptionReturn.StatusCode = 400 exceptionReturn.ErrorCode = "400132" @@ -287,7 +261,7 @@ func (as *WalletService) GetHeader(ctx context.Context, am *model.Auth, walletId } wm.Currency = "USD" - wm.WalletId = walletId + wm.WalletId = flt.WalletId return wm, nil } diff --git a/pkg/utl/common/common.go b/pkg/utl/common/common.go index eee7cad..f7a0b0c 100644 --- a/pkg/utl/common/common.go +++ b/pkg/utl/common/common.go @@ -52,3 +52,12 @@ func GetIP() string { } return "" } + +func Find[T any](lst *[]T, callback func(item *T) bool) *T { + for _, item := range *lst { + if callback(&item) { + return &item + } + } + return nil +}