Merge branch 'feature/upgrade-go-version-and-add-di' into main

This commit is contained in:
Fran Jurmanović
2022-10-07 23:49:35 +02:00
82 changed files with 3482 additions and 1660 deletions

3
.gitignore vendored
View File

@@ -31,3 +31,6 @@ _testmain.go
*.prof *.prof
.Dockerfile .Dockerfile
logs.txt
querys.txt

33
go.mod
View File

@@ -1,21 +1,40 @@
module wallet-api module wallet-api
// +heroku goVersion go1.15 // +heroku goVersion go1.19
go 1.15 go 1.19
require ( require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/gin-gonic/gin v1.7.7 github.com/gin-gonic/gin v1.7.7
github.com/go-pg/pg/v10 v10.10.6 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/google/uuid v1.3.0
github.com/joho/godotenv v1.4.0 github.com/joho/godotenv v1.4.0
github.com/json-iterator/go v1.1.12 // indirect go.uber.org/dig v1.15.0
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/ugorji/go v1.2.6 // indirect
golang.org/x/crypto v0.0.0-20220214200702-86341886e292 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/sys v0.0.0-20220209214540-3681064d5158 // indirect
golang.org/x/text v0.3.7 // 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 gopkg.in/yaml.v2 v2.4.0 // indirect
mellium.im/sasl v0.2.1 // indirect
) )

9
go.sum
View File

@@ -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.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.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.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.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 h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs= 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.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 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.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= 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 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 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= 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-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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 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-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-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 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/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-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/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-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-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-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-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-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210923061019-b8560ed6a9b7/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 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 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-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.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-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/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= mellium.im/sasl v0.2.1 h1:nspKSRg7/SyO0cRGY71OkfHab8tf9kCts6a6oTDut0w=

View File

@@ -1,60 +1,50 @@
package api package api
import ( import (
"wallet-api/pkg/controllers" "wallet-api/pkg/controller"
"wallet-api/pkg/middleware" "wallet-api/pkg/middleware"
"wallet-api/pkg/services" "wallet-api/pkg/utl/common"
"wallet-api/pkg/utl/configs" "wallet-api/pkg/utl/configs"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
"go.uber.org/dig"
) )
/* /*
Routes Routes
Initializes web api controllers and its corresponding routes. Initializes web api controllers and its corresponding routes.
Args: Args:
*gin.Engine: Gin Engine *gin.Engine: Gin Engine
*pg.DB: Postgres database client *pg.DB: Postgres database client
*/ */
func Routes(s *gin.Engine, db *pg.DB) { func Routes(s *gin.Engine, db *pg.DB) {
c := dig.New()
ver := s.Group(configs.Prefix) ver := s.Group(configs.Prefix)
api := ver.Group("api") routeGroups := &common.RouteGroups{
auth := ver.Group("auth") Api: ver.Group("api"),
wallet := ver.Group("wallet", middleware.Auth) Auth: ver.Group("auth"),
walletHeader := ver.Group("wallet/wallet-header", middleware.Auth) Wallet: ver.Group("wallet", middleware.Auth),
transaction := ver.Group("transaction", middleware.Auth) WalletHeader: ver.Group("wallet/wallet-header", middleware.Auth),
transactionType := ver.Group("transaction-type", middleware.Auth) Transaction: ver.Group("transaction", middleware.Auth),
subscription := ver.Group("subscription", middleware.Auth) TransactionType: ver.Group("transaction-type", middleware.Auth),
subscriptionType := ver.Group("subscription-type", middleware.Auth) Subscription: ver.Group("subscription", middleware.Auth),
transactionStatus := ver.Group("transaction-status", middleware.Auth) SubscriptionType: ver.Group("subscription-type", middleware.Auth),
TransactionStatus: ver.Group("transaction-status", middleware.Auth),
}
s.NoRoute(func(c *gin.Context) { s.NoRoute(func(c *gin.Context) {
c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Page not found"}) c.JSON(404, gin.H{"code": "PAGE_NOT_FOUND", "message": "Page not found"})
}) })
apiService := services.ApiService{Db: db} c.Provide(func() *common.RouteGroups {
usersService := services.UsersService{Db: db} return routeGroups
walletService := services.WalletService{Db: db} })
transactionService := services.TransactionService{Db: db} c.Provide(func() *pg.DB {
transactionTypeService := services.TransactionTypeService{Db: db} return db
subscriptionService := services.SubscriptionService{Db: db} })
subscriptionTypeService := services.SubscriptionTypeService{Db: db} controller.InitializeControllers(c)
transactionStatusService := services.TransactionStatusService{Db: db}
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)
} }

View File

@@ -1,32 +1,35 @@
package controllers package controller
import ( import (
"wallet-api/pkg/middleware" "wallet-api/pkg/middleware"
"wallet-api/pkg/services" "wallet-api/pkg/service"
"wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type ApiController struct { type ApiController struct {
ApiService *services.ApiService service *service.ApiService
} }
/* /*
NewApiController NewApiController
Initializes ApiController. Initializes ApiController.
Args: Args:
*services.ApiService: API service *services.ApiService: API service
*gin.RouterGroup: Gin Router Group *gin.RouterGroup: Gin Router Group
Returns: Returns:
*ApiController: Controller for "api" interactions *ApiController: Controller for "api" interactions
*/ */
func NewApiController(as *services.ApiService, s *gin.RouterGroup) *ApiController { func NewApiController(as *service.ApiService, routeGroups *common.RouteGroups) *ApiController {
ac := new(ApiController) ac := &ApiController{
ac.ApiService = as service: as,
}
s.GET("", ac.getFirst) routeGroups.Api.GET("", ac.getFirst)
s.POST("migrate", middleware.SecretCode, ac.postMigrate) routeGroups.Api.POST("migrate", middleware.SecretCode, ac.postMigrate)
return ac return ac
} }
@@ -38,7 +41,7 @@ getFirst
*/ */
// ROUTE (GET /api). // ROUTE (GET /api).
func (ac *ApiController) getFirst(c *gin.Context) { func (ac *ApiController) getFirst(c *gin.Context) {
apiModel := ac.ApiService.GetFirst(c) apiModel := ac.service.GetFirst(c)
c.JSON(200, apiModel) c.JSON(200, apiModel)
} }
@@ -53,11 +56,11 @@ Requires "SECRET_CODE", "VERSION" (optional) from body.
func (ac *ApiController) postMigrate(c *gin.Context) { func (ac *ApiController) postMigrate(c *gin.Context) {
migrateModel := c.MustGet("migrate") migrateModel := c.MustGet("migrate")
version := migrateModel.(middleware.SecretCodeModel).Version version := migrateModel.(middleware.SecretCodeModel).Version
mr, er := ac.ApiService.PostMigrate(c, version) er := ac.service.PostMigrate(c, version)
if er.Message != "" { if len(er) > 0 {
c.JSON(er.StatusCode, er) c.JSON(500, er)
} else { } else {
c.JSON(200, mr) c.JSON(200, nil)
} }
} }

View File

@@ -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
}

View File

@@ -1,37 +1,41 @@
package controllers package controller
import ( import (
"net/http" "net/http"
"wallet-api/pkg/models" "wallet-api/pkg/filter"
"wallet-api/pkg/services" "wallet-api/pkg/model"
"wallet-api/pkg/service"
"wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type SubscriptionController struct { type SubscriptionController struct {
SubscriptionService *services.SubscriptionService service *service.SubscriptionService
} }
/* /*
NewSubscriptionController NewSubscriptionController
Initializes SubscriptionController. Initializes SubscriptionController.
Args: Args:
*services.SubscriptionService: Subscription service *services.SubscriptionService: Subscription service
*gin.RouterGroup: Gin Router Group *gin.RouterGroup: Gin Router Group
Returns: Returns:
*SubscriptionController: Controller for "subscription" route interactions *SubscriptionController: Controller for "subscription" route interactions
*/ */
func NewSubscriptionController(as *services.SubscriptionService, s *gin.RouterGroup) *SubscriptionController { func NewSubscriptionController(as *service.SubscriptionService, routeGroups *common.RouteGroups) *SubscriptionController {
wc := new(SubscriptionController) wc := &SubscriptionController{
wc.SubscriptionService = as service: as,
}
s.POST("", wc.New) routeGroups.Subscription.POST("", wc.New)
s.PUT("/:id", wc.Edit) routeGroups.Subscription.PUT("/:id", wc.Edit)
s.GET("/:id", wc.Get) routeGroups.Subscription.GET("/:id", wc.Get)
s.GET("", wc.GetAll) routeGroups.Subscription.GET("", wc.GetAll)
se := s.Group("/end") se := routeGroups.Subscription.Group("/end")
{ {
se.PUT("/:id", wc.End) se.PUT("/:id", wc.End)
} }
@@ -46,13 +50,15 @@ New
*/ */
// ROUTE (POST /subscription) // ROUTE (POST /subscription)
func (wc *SubscriptionController) New(c *gin.Context) { func (wc *SubscriptionController) New(c *gin.Context) {
body := new(models.NewSubscriptionBody) body := new(model.NewSubscriptionBody)
if err := c.ShouldBind(body); err != nil { if err := c.ShouldBind(body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
} }
wm, exception := wc.SubscriptionService.New(c, body) mdl := body.ToSubscription()
wm, exception := wc.service.New(c, mdl)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
@@ -69,7 +75,7 @@ Edit
*/ */
// ROUTE (PUT /subscription/:id) // ROUTE (PUT /subscription/:id)
func (wc *SubscriptionController) Edit(c *gin.Context) { func (wc *SubscriptionController) Edit(c *gin.Context) {
body := new(models.SubscriptionEdit) body := new(model.SubscriptionEdit)
if err := c.ShouldBind(body); err != nil { if err := c.ShouldBind(body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
@@ -77,7 +83,10 @@ func (wc *SubscriptionController) Edit(c *gin.Context) {
id := c.Param("id") id := c.Param("id")
wm, exception := wc.SubscriptionService.Edit(c, body, id) mdl := body.ToSubscription()
mdl.Id = id
wm, exception := wc.service.Edit(c, mdl)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return
@@ -92,18 +101,21 @@ Get
*/ */
// ROUTE (GET /subscription/:id) // ROUTE (GET /subscription/:id)
func (wc *SubscriptionController) Get(c *gin.Context) { func (wc *SubscriptionController) Get(c *gin.Context) {
body := new(models.Auth) params := new(model.Params)
params := new(models.Params)
auth := c.MustGet("auth") auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id userId := auth.(*model.Auth).Id
id := c.Param("id") id := c.Param("id")
embed, _ := c.GetQuery("embed") embed, _ := c.GetQuery("embed")
params.Embed = embed params.Embed = embed
fr, exception := wc.SubscriptionService.Get(c, body, id, params) flt := filter.NewSubscriptionFilter(*params)
flt.Id = id
flt.UserId = userId
fr, exception := wc.service.Get(c, *flt)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return
@@ -114,20 +126,9 @@ func (wc *SubscriptionController) Get(c *gin.Context) {
// ROUTE (PUT /subscription/end/:id) // ROUTE (PUT /subscription/end/:id)
func (wc *SubscriptionController) End(c *gin.Context) { func (wc *SubscriptionController) End(c *gin.Context) {
body := new(models.Auth)
auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id
end := new(models.SubscriptionEnd)
if err := c.ShouldBind(end); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
id := c.Param("id") id := c.Param("id")
fr, exception := wc.SubscriptionService.End(c, id) fr, exception := wc.service.End(c, id)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return
@@ -143,14 +144,16 @@ GetAll
*/ */
// ROUTE (GET /subscription) // ROUTE (GET /subscription)
func (wc *SubscriptionController) GetAll(c *gin.Context) { func (wc *SubscriptionController) GetAll(c *gin.Context) {
body := new(models.Auth)
auth := c.MustGet("auth") auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id
fr := FilteredResponse(c)
wallet, _ := c.GetQuery("walletId") wallet, _ := c.GetQuery("walletId")
embed, _ := c.GetQuery("embed")
exception := wc.SubscriptionService.GetAll(c, body, wallet, fr) flt := filter.NewSubscriptionFilter(model.Params{Embed: embed})
flt.WalletId = wallet
flt.UserId = auth.(*model.Auth).Id
fr, exception := wc.service.GetAll(c, flt)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return

View File

@@ -1,33 +1,37 @@
package controllers package controller
import ( import (
"net/http" "net/http"
"wallet-api/pkg/models" "wallet-api/pkg/filter"
"wallet-api/pkg/services" "wallet-api/pkg/model"
"wallet-api/pkg/service"
"wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type SubscriptionTypeController struct { type SubscriptionTypeController struct {
SubscriptionTypeService *services.SubscriptionTypeService service *service.SubscriptionTypeService
} }
/* /*
NewSubscriptionTypeController NewSubscriptionTypeController
Initializes SubscriptionTypeController. Initializes SubscriptionTypeController.
Args: Args:
*services.SubscriptionTypeService: Subscription type service *services.SubscriptionTypeService: Subscription type service
*gin.RouterGroup: Gin Router Group *gin.RouterGroup: Gin Router Group
Returns: Returns:
*SubscriptionTypeController: Controller for "subscription-types" route interactions *SubscriptionTypeController: Controller for "subscription-types" route interactions
*/ */
func NewSubscriptionTypeController(as *services.SubscriptionTypeService, s *gin.RouterGroup) *SubscriptionTypeController { func NewSubscriptionTypeController(as *service.SubscriptionTypeService, routeGroups *common.RouteGroups) *SubscriptionTypeController {
wc := new(SubscriptionTypeController) wc := &SubscriptionTypeController{
wc.SubscriptionTypeService = as service: as,
}
s.POST("", wc.New) routeGroups.SubscriptionType.POST("", wc.New)
s.GET("", wc.GetAll) routeGroups.SubscriptionType.GET("", wc.GetAll)
return wc return wc
} }
@@ -39,13 +43,15 @@ New
*/ */
// ROUTE (POST /subscription-types) // ROUTE (POST /subscription-types)
func (wc *SubscriptionTypeController) New(c *gin.Context) { func (wc *SubscriptionTypeController) New(c *gin.Context) {
body := new(models.NewSubscriptionTypeBody) body := new(model.NewSubscriptionTypeBody)
if err := c.ShouldBind(body); err != nil { if err := c.ShouldBind(body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
} }
wm, exception := wc.SubscriptionTypeService.New(c, body) mdl := body.ToSubscriptionType()
wm, exception := wc.service.New(c, mdl)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return
@@ -62,7 +68,9 @@ GetAll
func (wc *SubscriptionTypeController) GetAll(c *gin.Context) { func (wc *SubscriptionTypeController) GetAll(c *gin.Context) {
embed, _ := c.GetQuery("embed") embed, _ := c.GetQuery("embed")
wm, exception := wc.SubscriptionTypeService.GetAll(c, embed) flt := filter.NewSubscriptionTypeFilter(model.Params{Embed: embed})
wm, exception := wc.service.GetAll(c, flt)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return

View File

@@ -1,42 +1,46 @@
package controllers package controller
import ( import (
"net/http" "net/http"
"wallet-api/pkg/models" "wallet-api/pkg/filter"
"wallet-api/pkg/services" "wallet-api/pkg/model"
"wallet-api/pkg/service"
"wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type TransactionController struct { type TransactionController struct {
TransactionService *services.TransactionService service *service.TransactionService
} }
/* /*
NewTransactionController NewTransactionController
Initializes TransactionController. Initializes TransactionController.
Args: Args:
*services.TransactionService: Transaction service *services.TransactionService: Transaction service
*gin.RouterGroup: Gin Router Group *gin.RouterGroup: Gin Router Group
Returns: Returns:
*TransactionController: Controller for "transaction" route interactions *TransactionController: Controller for "transaction" route interactions
*/ */
func NewTransactionController(as *services.TransactionService, s *gin.RouterGroup) *TransactionController { func NewTransactionController(as *service.TransactionService, routeGroups *common.RouteGroups) *TransactionController {
wc := new(TransactionController) wc := &TransactionController{
wc.TransactionService = as service: as,
}
s.POST("", wc.New) routeGroups.Transaction.POST("", wc.New)
s.GET("", wc.GetAll) routeGroups.Transaction.GET("", wc.GetAll)
s.PUT("/:id", wc.Edit) routeGroups.Transaction.PUT("/:id", wc.Edit)
s.GET("/:id", wc.Get) routeGroups.Transaction.GET("/:id", wc.Get)
bulkGroup := s.Group("bulk") bulkGroup := routeGroups.Transaction.Group("bulk")
{ {
bulkGroup.PUT("", wc.BulkEdit) bulkGroup.PUT("", wc.BulkEdit)
} }
checkGroup := s.Group("check") checkGroup := routeGroups.Transaction.Group("check")
{ {
checkGroup.GET("", wc.Check) checkGroup.GET("", wc.Check)
} }
@@ -51,13 +55,15 @@ New
*/ */
// ROUTE (POST /transactions) // ROUTE (POST /transactions)
func (wc *TransactionController) New(c *gin.Context) { func (wc *TransactionController) New(c *gin.Context) {
body := new(models.NewTransactionBody) body := new(model.NewTransactionBody)
if err := c.ShouldBind(body); err != nil { if err := c.ShouldBind(body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
} }
wm, exception := wc.TransactionService.New(c, body) mdl := body.ToTransaction()
wm, exception := wc.service.New(c, mdl)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return
@@ -72,17 +78,22 @@ GetAll
*/ */
// ROUTE (GET /transactions) // ROUTE (GET /transactions)
func (wc *TransactionController) GetAll(c *gin.Context) { func (wc *TransactionController) GetAll(c *gin.Context) {
body := new(models.Auth)
auth := c.MustGet("auth") auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id userId := auth.(*model.Auth).Id
fr := FilteredResponse(c) fr := FilteredResponse(c)
wallet, _ := c.GetQuery("walletId") wallet, _ := c.GetQuery("walletId")
embed, _ := c.GetQuery("embed")
noPendingQry, _ := c.GetQuery("noPending") noPendingQry, _ := c.GetQuery("noPending")
noPending := noPendingQry != "" noPending := noPendingQry != ""
exception := wc.TransactionService.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 { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return
@@ -98,14 +109,17 @@ Check
*/ */
// ROUTE (GET /transactions) // ROUTE (GET /transactions)
func (wc *TransactionController) Check(c *gin.Context) { func (wc *TransactionController) Check(c *gin.Context) {
body := new(models.Auth)
auth := c.MustGet("auth") auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id userId := auth.(*model.Auth).Id
fr := FilteredResponse(c) fr := FilteredResponse(c)
wallet, _ := c.GetQuery("walletId") wallet, _ := c.GetQuery("walletId")
exception := wc.TransactionService.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 { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return
@@ -121,15 +135,17 @@ Edit
*/ */
// ROUTE (PUT /transactions/:id) // ROUTE (PUT /transactions/:id)
func (wc *TransactionController) Edit(c *gin.Context) { func (wc *TransactionController) Edit(c *gin.Context) {
body := new(models.TransactionEdit) body := new(model.TransactionEdit)
if err := c.ShouldBind(body); err != nil { if err := c.ShouldBind(body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
} }
id := c.Param("id") id := c.Param("id")
mdl := body.ToTransaction()
mdl.Id = id
wm, exception := wc.TransactionService.Edit(c, body, id) wm, exception := wc.service.Edit(c, mdl)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return
@@ -144,13 +160,19 @@ BulkEdit
*/ */
// ROUTE (PUT /transactions/:id) // ROUTE (PUT /transactions/:id)
func (wc *TransactionController) BulkEdit(c *gin.Context) { func (wc *TransactionController) BulkEdit(c *gin.Context) {
body := new([]models.TransactionEdit) body := new([]model.TransactionEdit)
if err := c.ShouldBind(body); err != nil { if err := c.ShouldBind(body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
} }
wm, exception := wc.TransactionService.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 { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return
@@ -165,18 +187,21 @@ Get
*/ */
// ROUTE (GET /transactions/:id) // ROUTE (GET /transactions/:id)
func (wc *TransactionController) Get(c *gin.Context) { func (wc *TransactionController) Get(c *gin.Context) {
body := new(models.Auth) params := new(model.Params)
params := new(models.Params)
auth := c.MustGet("auth") auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id userId := auth.(*model.Auth).Id
id := c.Param("id") id := c.Param("id")
embed, _ := c.GetQuery("embed") embed, _ := c.GetQuery("embed")
params.Embed = embed params.Embed = embed
fr, exception := wc.TransactionService.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 { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return

View File

@@ -1,33 +1,37 @@
package controllers package controller
import ( import (
"net/http" "net/http"
"wallet-api/pkg/models" "wallet-api/pkg/filter"
"wallet-api/pkg/services" "wallet-api/pkg/model"
"wallet-api/pkg/service"
"wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type TransactionStatusController struct { type TransactionStatusController struct {
TransactionStatusService *services.TransactionStatusService service *service.TransactionStatusService
} }
/* /*
NewTransactionStatusController NewTransactionStatusController
Initializes TransactionStatusController. Initializes TransactionStatusController.
Args: Args:
*services.TransactionStatusService: Transaction Staus service *services.TransactionStatusService: Transaction Staus service
*gin.RouterGroup: Gin Router Group *gin.RouterGroup: Gin Router Group
Returns: Returns:
*TransactionStatusController: Controller for "transaction-status" route interactions *TransactionStatusController: Controller for "transaction-status" route interactions
*/ */
func NewTransactionStatusController(as *services.TransactionStatusService, s *gin.RouterGroup) *TransactionStatusController { func NewTransactionStatusController(as *service.TransactionStatusService, routeGroups *common.RouteGroups) *TransactionStatusController {
wc := new(TransactionStatusController) wc := &TransactionStatusController{
wc.TransactionStatusService = as service: as,
}
s.POST("", wc.New) routeGroups.TransactionStatus.POST("", wc.New)
s.GET("", wc.GetAll) routeGroups.TransactionStatus.GET("", wc.GetAll)
return wc return wc
} }
@@ -39,13 +43,15 @@ New
*/ */
// ROUTE (POST /transaction-status) // ROUTE (POST /transaction-status)
func (wc *TransactionStatusController) New(c *gin.Context) { func (wc *TransactionStatusController) New(c *gin.Context) {
body := new(models.NewTransactionStatusBody) body := new(model.NewTransactionStatusBody)
if err := c.ShouldBind(body); err != nil { if err := c.ShouldBind(body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
} }
wm, exception := wc.TransactionStatusService.New(c, body) mdl := body.ToTransactionStatus()
wm, exception := wc.service.New(c, mdl)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return
@@ -61,8 +67,9 @@ GetAll
// ROUTE (GET /transaction-status) // ROUTE (GET /transaction-status)
func (wc *TransactionStatusController) GetAll(c *gin.Context) { func (wc *TransactionStatusController) GetAll(c *gin.Context) {
embed, _ := c.GetQuery("embed") embed, _ := c.GetQuery("embed")
flt := filter.NewTransactionStatusFilter(model.Params{Embed: embed})
wm, exception := wc.TransactionStatusService.GetAll(c, embed) wm, exception := wc.service.GetAll(c, flt)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return

View File

@@ -1,33 +1,37 @@
package controllers package controller
import ( import (
"net/http" "net/http"
"wallet-api/pkg/models" "wallet-api/pkg/filter"
"wallet-api/pkg/services" "wallet-api/pkg/model"
"wallet-api/pkg/service"
"wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type TransactionTypeController struct { type TransactionTypeController struct {
TransactionTypeService *services.TransactionTypeService service *service.TransactionTypeService
} }
/* /*
NewTransactionTypeController NewTransactionTypeController
Initializes TransactionTypeController. Initializes TransactionTypeController.
Args: Args:
*services.TransactionTypeService: Transaction Type service *services.TransactionTypeService: Transaction Type service
*gin.RouterGroup: Gin Router Group *gin.RouterGroup: Gin Router Group
Returns: Returns:
*TransactionTypeController: Controller for "transaction-types" route interactions *TransactionTypeController: Controller for "transaction-types" route interactions
*/ */
func NewTransactionTypeController(as *services.TransactionTypeService, s *gin.RouterGroup) *TransactionTypeController { func NewTransactionTypeController(as *service.TransactionTypeService, routeGroups *common.RouteGroups) *TransactionTypeController {
wc := new(TransactionTypeController) wc := &TransactionTypeController{
wc.TransactionTypeService = as service: as,
}
s.POST("", wc.New) routeGroups.TransactionType.POST("", wc.New)
s.GET("", wc.GetAll) routeGroups.TransactionType.GET("", wc.GetAll)
return wc return wc
} }
@@ -39,13 +43,14 @@ New
*/ */
// ROUTE (POST /transaction-types) // ROUTE (POST /transaction-types)
func (wc *TransactionTypeController) New(c *gin.Context) { func (wc *TransactionTypeController) New(c *gin.Context) {
body := new(models.NewTransactionTypeBody) body := new(model.NewTransactionTypeBody)
if err := c.ShouldBind(body); err != nil { if err := c.ShouldBind(body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
} }
mdl := body.ToTransactionType()
wm, exception := wc.TransactionTypeService.New(c, body) wm, exception := wc.service.New(c, mdl)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return
@@ -62,7 +67,9 @@ GetAll
func (wc *TransactionTypeController) GetAll(c *gin.Context) { func (wc *TransactionTypeController) GetAll(c *gin.Context) {
embed, _ := c.GetQuery("embed") embed, _ := c.GetQuery("embed")
wm, exception := wc.TransactionTypeService.GetAll(c, embed) flt := filter.NewTransactionTypeFilter(model.Params{Embed: embed})
wm, exception := wc.service.GetAll(c, flt)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return

View File

@@ -1,36 +1,40 @@
package controllers package controller
import ( import (
"net/http" "net/http"
"wallet-api/pkg/filter"
"wallet-api/pkg/middleware" "wallet-api/pkg/middleware"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"wallet-api/pkg/services" "wallet-api/pkg/service"
"wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type AuthController struct { type UserController struct {
UsersService *services.UsersService service *service.UserService
} }
/* /*
NewAuthController NewUserController
Initializes UserController.
Initializes AuthController.
Args: Args:
*services.UsersService: Users service *services.UserService: User service
*gin.RouterGroup: Gin Router Group *gin.RouterGroup: Gin Router Group
Returns: Returns:
*AuthController: Controller for "auth" interactions *UserController: Controller for "auth" interactions
*/ */
func NewAuthController(rs *services.UsersService, s *gin.RouterGroup) *AuthController { func NewUserController(rs *service.UserService, routeGroups *common.RouteGroups) *UserController {
rc := new(AuthController) rc := &UserController{
rc.UsersService = rs service: rs,
}
s.POST("login", rc.PostLogin) routeGroups.Auth.POST("login", rc.PostLogin)
s.POST("register", rc.PostRegister) routeGroups.Auth.POST("register", rc.PostRegister)
s.DELETE("deactivate", middleware.Auth, rc.Delete) routeGroups.Auth.DELETE("deactivate", middleware.Auth, rc.Delete)
s.GET("check-token", rc.CheckToken) routeGroups.Auth.GET("check-token", rc.CheckToken)
return rc return rc
} }
@@ -41,13 +45,13 @@ PostLogin
*gin.Context: Gin Application Context *gin.Context: Gin Application Context
*/ */
// ROUTE (POST /auth/login). // ROUTE (POST /auth/login).
func (rc *AuthController) PostLogin(c *gin.Context) { func (rc *UserController) PostLogin(c *gin.Context) {
body := new(models.Login) body := new(model.Login)
if err := c.ShouldBind(&body); err != nil { if err := c.ShouldBind(&body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
} }
returnedUser, exceptionReturn := rc.UsersService.Login(c, body) returnedUser, exceptionReturn := rc.service.Login(c, body)
if exceptionReturn.Message != "" { if exceptionReturn.Message != "" {
c.JSON(exceptionReturn.StatusCode, exceptionReturn) c.JSON(exceptionReturn.StatusCode, exceptionReturn)
@@ -63,15 +67,15 @@ PostRegister
*gin.Context: Gin Application Context *gin.Context: Gin Application Context
*/ */
// ROUTE (POST /auth/register). // ROUTE (POST /auth/register).
func (rc *AuthController) PostRegister(c *gin.Context) { func (rc *UserController) PostRegister(c *gin.Context) {
body := new(models.User) body := new(model.User)
body.Init() body.Init()
body.IsActive = true body.IsActive = true
if err := c.ShouldBind(body); err != nil { if err := c.ShouldBind(body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
} }
returnedUser, exceptionReturn := rc.UsersService.Create(c, body) returnedUser, exceptionReturn := rc.service.Create(c, body)
if exceptionReturn.Message != "" { if exceptionReturn.Message != "" {
c.JSON(exceptionReturn.StatusCode, exceptionReturn) c.JSON(exceptionReturn.StatusCode, exceptionReturn)
@@ -87,12 +91,14 @@ Delete
*gin.Context: Gin Application Context *gin.Context: Gin Application Context
*/ */
// ROUTE (DELETE /auth/deactivate). // ROUTE (DELETE /auth/deactivate).
func (rc *AuthController) Delete(c *gin.Context) { func (rc *UserController) Delete(c *gin.Context) {
auth := new(models.Auth)
authGet := c.MustGet("auth") authGet := c.MustGet("auth")
auth.Id = authGet.(*models.Auth).Id userId := authGet.(*model.Auth).Id
mr, er := rc.UsersService.Deactivate(c, auth) flt := filter.NewUserFilter(model.Params{})
flt.UserId = userId
mr, er := rc.service.Deactivate(c, flt)
if er.Message != "" { if er.Message != "" {
c.JSON(er.StatusCode, er) c.JSON(er.StatusCode, er)
@@ -108,9 +114,9 @@ CheckToken
*gin.Context: Gin Application Context *gin.Context: Gin Application Context
*/ */
// ROUTE (GET /auth/check-token). // ROUTE (GET /auth/check-token).
func (rc *AuthController) CheckToken(c *gin.Context) { func (rc *UserController) CheckToken(c *gin.Context) {
token, _ := c.GetQuery("token") token, _ := c.GetQuery("token")
re := new(models.CheckToken) re := new(model.CheckToken)
_, err := middleware.CheckToken(token) _, err := middleware.CheckToken(token)

View File

@@ -0,0 +1,61 @@
package controller
import (
"wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/service"
"wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin"
)
type WalletHeaderController struct {
service *service.WalletService
}
/*
NewWalletHeaderController
Initializes WalletHeaderController.
Args:
*services.WalletService: Wallet service
*gin.RouterGroup: Gin Router Group
Returns:
*WalletHeaderController: Controller for "wallet/wallet-header" route interactions
*/
func NewWalletHeaderController(as *service.WalletService, routeGroups *common.RouteGroups) *WalletHeaderController {
wc := &WalletHeaderController{
service: as,
}
routeGroups.WalletHeader.GET("", wc.Get)
return wc
}
/*
Get
Args:
*gin.Context: Gin Application Context
*/
// ROUTE (GET /wallet/wallet-header)
func (wc *WalletHeaderController) Get(c *gin.Context) {
walletId, _ := c.GetQuery("walletId")
auth := c.MustGet("auth")
userId := auth.(*model.Auth).Id
embed, _ := c.GetQuery("embed")
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
}
c.JSON(200, wm)
}

139
pkg/controller/wallet.go Normal file
View File

@@ -0,0 +1,139 @@
package controller
import (
"net/http"
"wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/service"
"wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin"
)
type WalletController struct {
service *service.WalletService
}
/*
NewWalletController
Initializes WalletController.
Args:
*services.WalletService: Wallet service
*gin.RouterGroup: Gin Router Group
Returns:
*WalletController: Controller for "wallet" route interactions
*/
func NewWalletController(as *service.WalletService, routeGroups *common.RouteGroups) *WalletController {
wc := &WalletController{
service: as,
}
routeGroups.Wallet.POST("", wc.New)
routeGroups.Wallet.GET("", wc.GetAll)
routeGroups.Wallet.PUT("/:id", wc.Edit)
routeGroups.Wallet.GET("/:id", wc.Get)
return wc
}
/*
New
Args:
*gin.Context: Gin Application Context
*/
// ROUTE (POST /wallet)
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()})
return
}
get := c.MustGet("auth")
body.UserID = get.(*model.Auth).Id
wm, exception := wc.service.New(c, body)
if exception != nil {
c.JSON(exception.StatusCode, exception)
return
}
c.JSON(200, wm)
}
/*
GetAll
Args:
*gin.Context: Gin Application Context
*/
// ROUTE (GET /wallet)
func (wc *WalletController) GetAll(c *gin.Context) {
auth := c.MustGet("auth")
userId := auth.(*model.Auth).Id
embed, _ := c.GetQuery("embed")
flt := filter.NewWalletFilter(model.Params{Embed: embed})
flt.UserId = userId
fr, exception := wc.service.GetAll(c, flt)
if exception != nil {
c.JSON(exception.StatusCode, exception)
return
}
c.JSON(200, fr)
}
/*
Edit
Args:
*gin.Context: Gin Application Context
*/
// ROUTE (PUT /wallet/:id)
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
}
id := c.Param("id")
mdl := body.ToWallet()
mdl.Id = id
wm, exception := wc.service.Edit(c, mdl)
if exception != nil {
c.JSON(exception.StatusCode, exception)
return
}
c.JSON(200, wm)
}
/*
Get
Args:
*gin.Context: Gin Application Context
*/
// ROUTE (GET /wallet/:id)
func (wc *WalletController) Get(c *gin.Context) {
params := new(model.Params)
id := c.Param("id")
embed, _ := c.GetQuery("embed")
params.Embed = embed
flt := filter.NewWalletFilter(*params)
flt.Id = id
fr, exception := wc.service.Get(c, flt)
if exception != nil {
c.JSON(exception.StatusCode, exception)
return
}
c.JSON(200, fr)
}

View File

@@ -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
}

View File

@@ -1,54 +0,0 @@
package controllers
import (
"wallet-api/pkg/models"
"wallet-api/pkg/services"
"github.com/gin-gonic/gin"
)
type WalletsHeaderController struct {
WalletService *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
s.GET("", wc.Get)
return wc
}
/*
Get
Args:
*gin.Context: Gin Application Context
*/
// ROUTE (GET /wallet/wallet-header)
func (wc *WalletsHeaderController) Get(c *gin.Context) {
body := new(models.Auth)
walletId, _ := c.GetQuery("walletId")
auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id
wm, exception := wc.WalletService.GetHeader(c, body, walletId)
if exception != nil {
c.JSON(exception.StatusCode, exception)
return
}
c.JSON(200, wm)
}

View File

@@ -1,128 +0,0 @@
package controllers
import (
"net/http"
"wallet-api/pkg/models"
"wallet-api/pkg/services"
"github.com/gin-gonic/gin"
)
type WalletsController struct {
WalletService *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
s.POST("", wc.New)
s.GET("", wc.GetAll)
s.PUT("/:id", wc.Edit)
s.GET("/:id", wc.Get)
return wc
}
/*
New
Args:
*gin.Context: Gin Application Context
*/
// ROUTE (POST /wallet)
func (wc *WalletsController) New(c *gin.Context) {
body := new(models.NewWalletBody)
if err := c.ShouldBind(body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
get := c.MustGet("auth")
body.UserID = get.(*models.Auth).Id
wm, exception := wc.WalletService.New(c, body)
if exception != nil {
c.JSON(exception.StatusCode, exception)
return
}
c.JSON(200, wm)
}
/*
GetAll
Args:
*gin.Context: Gin Application Context
*/
// ROUTE (GET /wallet)
func (wc *WalletsController) GetAll(c *gin.Context) {
body := new(models.Auth)
auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id
fr := FilteredResponse(c)
exception := wc.WalletService.GetAll(c, body, fr)
if exception != nil {
c.JSON(exception.StatusCode, exception)
return
}
c.JSON(200, fr)
}
/*
Edit
Args:
*gin.Context: Gin Application Context
*/
// ROUTE (PUT /wallet/:id)
func (wc *WalletsController) Edit(c *gin.Context) {
body := new(models.WalletEdit)
if err := c.ShouldBind(body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
id := c.Param("id")
wm, exception := wc.WalletService.Edit(c, body, id)
if exception != nil {
c.JSON(exception.StatusCode, exception)
return
}
c.JSON(200, wm)
}
/*
Get
Args:
*gin.Context: Gin Application Context
*/
// ROUTE (GET /wallet/:id)
func (wc *WalletsController) Get(c *gin.Context) {
params := new(models.Params)
id := c.Param("id")
embed, _ := c.GetQuery("embed")
params.Embed = embed
fr, exception := wc.WalletService.Get(c, id, params)
if exception != nil {
c.JSON(exception.StatusCode, exception)
return
}
c.JSON(200, fr)
}

13
pkg/filter/api.go Normal file
View File

@@ -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,
}
}

37
pkg/filter/filter.go Normal file
View File

@@ -0,0 +1,37 @@
package filter
import (
"go.uber.org/dig"
"wallet-api/pkg/model"
)
/*
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 {
model.Params
Id string
WalletId string
UserId string
}
type BBa interface {
BaseFilter
some() bool
}

View File

@@ -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,
}
}

View File

@@ -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,
}
}

16
pkg/filter/transaction.go Normal file
View File

@@ -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,
}
}

View File

@@ -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,
}
}

View File

@@ -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,
}
}

14
pkg/filter/user.go Normal file
View File

@@ -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,
}
}

View File

@@ -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,
}
}

14
pkg/filter/wallet.go Normal file
View File

@@ -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,
}
}

View File

@@ -4,7 +4,7 @@ import (
"errors" "errors"
"os" "os"
"strings" "strings"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"wallet-api/pkg/utl/configs" "wallet-api/pkg/utl/configs"
"github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go"
@@ -16,11 +16,12 @@ import (
Auth Auth
Checks if token from header is valid and extracts the id. Checks if token from header is valid and extracts the id.
Args: Args:
*gin.Context: Gin Application Context. *gin.Context: Gin Application Context.
*/ */
func Auth(c *gin.Context) { func Auth(c *gin.Context) {
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
tokenString := ExtractToken(c) tokenString := ExtractToken(c)
token, err := CheckToken(tokenString) token, err := CheckToken(tokenString)
if err != nil { if err != nil {
@@ -33,7 +34,7 @@ func Auth(c *gin.Context) {
if ok && token.Valid { if ok && token.Valid {
userId, _ := claims["id"].(string) userId, _ := claims["id"].(string)
authModel := new(models.Auth) authModel := new(model.Auth)
authModel.Id = userId authModel.Id = userId
c.Set("auth", authModel) c.Set("auth", authModel)
@@ -45,6 +46,7 @@ func Auth(c *gin.Context) {
ExtractToken ExtractToken
Extracts token from header Extracts token from header
Args: Args:
*gin.Context: Gin Application Context. *gin.Context: Gin Application Context.
Returns: Returns:
@@ -66,6 +68,7 @@ func ExtractToken(c *gin.Context) string {
CheckToken CheckToken
Checks if token is valid Checks if token is valid
Args: Args:
string: Token to check string: Token to check
Returns: Returns:

View File

@@ -3,7 +3,7 @@ package middleware
import ( import (
"net/http" "net/http"
"os" "os"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"wallet-api/pkg/utl/configs" "wallet-api/pkg/utl/configs"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@@ -13,11 +13,12 @@ import (
SecretCode SecretCode
Checks if secret code from body is valid. 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) { func SecretCode(c *gin.Context) {
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
secretCode := ExtractCode(c) secretCode := ExtractCode(c)
secret := os.Getenv("SECRET_CODE") secret := os.Getenv("SECRET_CODE")
if secret == "" { if secret == "" {
@@ -37,8 +38,9 @@ func SecretCode(c *gin.Context) {
ExtractCode ExtractCode
Extracts the secret code from body. Extracts the secret code from body.
Args:
*gin.Context: Gin Application Context. Args:
*gin.Context: Gin Application Context.
*/ */
func ExtractCode(c *gin.Context) SecretCodeModel { func ExtractCode(c *gin.Context) SecretCodeModel {
secret := new(SecretCodeModel) secret := new(SecretCodeModel)

View File

@@ -3,7 +3,7 @@ package migrate
import ( import (
"fmt" "fmt"
"log" "log"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
@@ -14,14 +14,15 @@ import (
CreateTableTransactionStatus CreateTableTransactionStatus
Creates transaction_status table if it does not exist. Creates transaction_status table if it does not exist.
Args:
*pg.DB: Postgres database client Args:
Returns: *pg.DB: Postgres database client
error: Returns if there is an error with table creation Returns:
error: Returns if there is an error with table creation
*/ */
func CreateTableTransactionStatus(db pg.DB) error { func CreateTableTransactionStatus(db pg.DB) error {
models := []interface{}{ models := []interface{}{
(*models.TransactionStatus)(nil), (*model.TransactionStatus)(nil),
} }
for _, model := range models { for _, model := range models {

View File

@@ -3,7 +3,7 @@ package migrate
import ( import (
"fmt" "fmt"
"log" "log"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
) )
@@ -12,15 +12,16 @@ import (
PopulateTransactionStatus PopulateTransactionStatus
Populates transaction_status table if it exists. Populates transaction_status table if it exists.
Args:
*pg.DB: Postgres database client Args:
Returns: *pg.DB: Postgres database client
error: Returns if there is an error with populating table Returns:
error: Returns if there is an error with populating table
*/ */
func PopulateTransactionStatus(db pg.DB) error { func PopulateTransactionStatus(db pg.DB) error {
completed := new(models.TransactionStatus) completed := new(model.TransactionStatus)
pending := new(models.TransactionStatus) pending := new(model.TransactionStatus)
deleted := new(models.TransactionStatus) deleted := new(model.TransactionStatus)
completed.Init() completed.Init()
completed.Name = "Completed" completed.Name = "Completed"

View File

@@ -3,7 +3,7 @@ package migrate
import ( import (
"fmt" "fmt"
"log" "log"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
@@ -14,15 +14,16 @@ import (
CreateTableApi CreateTableApi
Creates api table if it does not exist. Creates api table if it does not exist.
Args:
*pg.DB: Postgres database client Args:
Returns: *pg.DB: Postgres database client
error: Returns if there is an error with table creation Returns:
error: Returns if there is an error with table creation
*/ */
func CreateTableApi(db pg.DB) error { func CreateTableApi(db pg.DB) error {
models := []interface{}{ models := []interface{}{
(*models.ApiModel)(nil), (*model.ApiModel)(nil),
} }
for _, model := range models { for _, model := range models {

View File

@@ -3,7 +3,7 @@ package migrate
import ( import (
"fmt" "fmt"
"log" "log"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
@@ -14,14 +14,15 @@ import (
CreateTableUsers CreateTableUsers
Creates users table if it does not exist. Creates users table if it does not exist.
Args:
*pg.DB: Postgres database client Args:
Returns: *pg.DB: Postgres database client
error: Returns if there is an error with table creation Returns:
error: Returns if there is an error with table creation
*/ */
func CreateTableUsers(db pg.DB) error { func CreateTableUsers(db pg.DB) error {
models := []interface{}{ models := []interface{}{
(*models.User)(nil), (*model.User)(nil),
} }
for _, model := range models { for _, model := range models {

View File

@@ -3,7 +3,7 @@ package migrate
import ( import (
"fmt" "fmt"
"log" "log"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
@@ -14,14 +14,15 @@ import (
CreateTableWallets CreateTableWallets
Creates wallets table if it does not exist. Creates wallets table if it does not exist.
Args:
*pg.DB: Postgres database client Args:
Returns: *pg.DB: Postgres database client
error: Returns if there is an error with table creation Returns:
error: Returns if there is an error with table creation
*/ */
func CreateTableWallets(db pg.DB) error { func CreateTableWallets(db pg.DB) error {
models := []interface{}{ models := []interface{}{
(*models.Wallet)(nil), (*model.Wallet)(nil),
} }
for _, model := range models { for _, model := range models {

View File

@@ -3,7 +3,7 @@ package migrate
import ( import (
"fmt" "fmt"
"log" "log"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
@@ -14,14 +14,15 @@ import (
CreateTableTransactionTypes CreateTableTransactionTypes
Creates transaction_types table if it does not exist. Creates transaction_types table if it does not exist.
Args:
*pg.DB: Postgres database client Args:
Returns: *pg.DB: Postgres database client
error: Returns if there is an error with table creation Returns:
error: Returns if there is an error with table creation
*/ */
func CreateTableTransactionTypes(db pg.DB) error { func CreateTableTransactionTypes(db pg.DB) error {
models := []interface{}{ models := []interface{}{
(*models.TransactionType)(nil), (*model.TransactionType)(nil),
} }
for _, model := range models { for _, model := range models {

View File

@@ -3,7 +3,7 @@ package migrate
import ( import (
"fmt" "fmt"
"log" "log"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
@@ -14,14 +14,15 @@ import (
CreateTableTransactions CreateTableTransactions
Creates transactions table if it does not exist. Creates transactions table if it does not exist.
Args:
*pg.DB: Postgres database client Args:
Returns: *pg.DB: Postgres database client
error: Returns if there is an error with table creation Returns:
error: Returns if there is an error with table creation
*/ */
func CreateTableTransactions(db pg.DB) error { func CreateTableTransactions(db pg.DB) error {
models := []interface{}{ models := []interface{}{
(*models.Transaction)(nil), (*model.Transaction)(nil),
} }
for _, model := range models { for _, model := range models {

View File

@@ -3,7 +3,7 @@ package migrate
import ( import (
"fmt" "fmt"
"log" "log"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
@@ -14,14 +14,15 @@ import (
CreateTableSubscriptionTypes CreateTableSubscriptionTypes
Creates subscription_types table if it does not exist. Creates subscription_types table if it does not exist.
Args:
*pg.DB: Postgres database client Args:
Returns: *pg.DB: Postgres database client
error: Returns if there is an error with table creation Returns:
error: Returns if there is an error with table creation
*/ */
func CreateTableSubscriptionTypes(db pg.DB) error { func CreateTableSubscriptionTypes(db pg.DB) error {
models := []interface{}{ models := []interface{}{
(*models.SubscriptionType)(nil), (*model.SubscriptionType)(nil),
} }
for _, model := range models { for _, model := range models {

View File

@@ -3,7 +3,7 @@ package migrate
import ( import (
"fmt" "fmt"
"log" "log"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
"github.com/go-pg/pg/v10/orm" "github.com/go-pg/pg/v10/orm"
@@ -13,14 +13,15 @@ import (
CreateTableSubscriptions CreateTableSubscriptions
Creates subscriptions table if it does not exist. Creates subscriptions table if it does not exist.
Args:
*pg.DB: Postgres database client Args:
Returns: *pg.DB: Postgres database client
error: Returns if there is an error with table creation Returns:
error: Returns if there is an error with table creation
*/ */
func CreateTableSubscriptions(db pg.DB) error { func CreateTableSubscriptions(db pg.DB) error {
models := []interface{}{ models := []interface{}{
(*models.Subscription)(nil), (*model.Subscription)(nil),
} }
for _, model := range models { for _, model := range models {

View File

@@ -3,7 +3,7 @@ package migrate
import ( import (
"fmt" "fmt"
"log" "log"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
) )
@@ -12,16 +12,17 @@ import (
PopulateSubscriptionTypes PopulateSubscriptionTypes
Populates subscription_types table if it exists. Populates subscription_types table if it exists.
Args:
*pg.DB: Postgres database client Args:
Returns: *pg.DB: Postgres database client
error: Returns if there is an error with populating table Returns:
error: Returns if there is an error with populating table
*/ */
func PopulateSubscriptionTypes(db pg.DB) error { func PopulateSubscriptionTypes(db pg.DB) error {
daily := new(models.SubscriptionType) daily := new(model.SubscriptionType)
weekly := new(models.SubscriptionType) weekly := new(model.SubscriptionType)
monthly := new(models.SubscriptionType) monthly := new(model.SubscriptionType)
yearly := new(models.SubscriptionType) yearly := new(model.SubscriptionType)
daily.Init() daily.Init()
daily.Name = "Daily" daily.Name = "Daily"

View File

@@ -3,7 +3,7 @@ package migrate
import ( import (
"fmt" "fmt"
"log" "log"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
) )
@@ -12,14 +12,15 @@ import (
PopulateTransactionTypes PopulateTransactionTypes
Populates transaction_types table if it exists. Populates transaction_types table if it exists.
Args:
*pg.DB: Postgres database client Args:
Returns: *pg.DB: Postgres database client
error: Returns if there is an error with populating table Returns:
error: Returns if there is an error with populating table
*/ */
func PopulateTransactionTypes(db pg.DB) error { func PopulateTransactionTypes(db pg.DB) error {
gain := new(models.TransactionType) gain := new(model.TransactionType)
expense := new(models.TransactionType) expense := new(model.TransactionType)
gain.Init() gain.Init()
gain.Name = "Gain" gain.Name = "Gain"

View File

@@ -13,7 +13,7 @@ Starts database migration.
Returns: Returns:
error: Returns if there is an error with populating table 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{ migration001 := Migration{
Version: "001", Version: "001",
Migrations: []interface{}{ Migrations: []interface{}{
@@ -53,16 +53,23 @@ func Start(conn *pg.DB, version string) {
migration004, migration004,
} }
var errors []error
for _, migrationCol := range migrationsMap { for _, migrationCol := range migrationsMap {
if version != "" && version == migrationCol.Version || version == "" { if version != "" && version == migrationCol.Version || version == "" {
for _, migration := range migrationCol.Migrations { for _, migration := range migrationCol.Migrations {
mgFunc, isFunc := migration.(func(pg.DB) error) mgFunc, isFunc := migration.(func(pg.DB) error)
if isFunc { if isFunc {
mgFunc(*conn) err := mgFunc(*conn)
if err != nil {
errors = append(errors, err)
}
} }
} }
} }
} }
return errors
} }
type Migration struct { type Migration struct {

View File

@@ -1,6 +1,7 @@
package models package model
type ApiModel struct { type ApiModel struct {
BaseModel
tableName struct{} `pg:"api,alias:api"` tableName struct{} `pg:"api,alias:api"`
Api string `json:"api"` Api string `json:"api"`
} }

19
pkg/model/auth.go Normal file
View File

@@ -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"`
}

View File

@@ -1,4 +1,4 @@
package models package model
import ( import (
"time" "time"

View File

@@ -1,4 +1,4 @@
package models package model
type Exception struct { type Exception struct {
ErrorCode string `json:"errorCode"` ErrorCode string `json:"errorCode"`

24
pkg/model/model.go Normal file
View File

@@ -0,0 +1,24 @@
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"`
}

View File

@@ -1,4 +1,4 @@
package models package model
type User struct { type User struct {
tableName struct{} `pg:"users,alias:users"` tableName struct{} `pg:"users,alias:users"`
@@ -20,6 +20,7 @@ type UserReturnInfo struct {
Payload Payload
Maps User object to UserReturnInfo object. Maps User object to UserReturnInfo object.
Returns: Returns:
*UserReturnInfo: mapped UserReturnInfo object *UserReturnInfo: mapped UserReturnInfo object
*/ */

View File

@@ -1,7 +1,8 @@
package models package model
import ( import (
"encoding/json" "encoding/json"
"math"
"time" "time"
) )
@@ -45,6 +46,41 @@ type NewSubscriptionBody struct {
Amount json.Number `json:"amount" form:"amount"` 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 { type SubscriptionEnd struct {
Id string `json:"id" form:"id"` Id string `json:"id" form:"id"`
} }
@@ -53,6 +89,7 @@ type SubscriptionEnd struct {
ToTrans ToTrans
Maps Subscription object to Transaction object. Maps Subscription object to Transaction object.
Returns: Returns:
*Transaction: mapped Transaction object *Transaction: mapped Transaction object
*/ */
@@ -74,6 +111,7 @@ func (cm *Subscription) ToTrans() *Transaction {
HasNew HasNew
Checks if Subscription reached new transaction interval. Checks if Subscription reached new transaction interval.
Returns: Returns:
bool: Is new transaction interval reached bool: Is new transaction interval reached
*/ */

View File

@@ -1,4 +1,4 @@
package models package model
type SubscriptionType struct { type SubscriptionType struct {
tableName struct{} `pg:"subscriptionTypes,alias:subscriptionTypes"` tableName struct{} `pg:"subscriptionTypes,alias:subscriptionTypes"`
@@ -11,3 +11,13 @@ type NewSubscriptionTypeBody struct {
Name string `json:"name" form:"name"` Name string `json:"name" form:"name"`
Type string `json:"type" form:"type"` 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
}

View File

@@ -1,7 +1,8 @@
package models package model
import ( import (
"encoding/json" "encoding/json"
"math"
"time" "time"
) )
@@ -29,6 +30,23 @@ type NewTransactionBody struct {
Amount json.Number `json:"amount" form:"amount"` 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 { type TransactionEdit struct {
Id string `json:"id" form:"id"` Id string `json:"id" form:"id"`
WalletID string `json:"walletId" form:"walletId"` WalletID string `json:"walletId" form:"walletId"`
@@ -38,3 +56,18 @@ type TransactionEdit struct {
Description string `json:"description" form:"description"` Description string `json:"description" form:"description"`
Amount json.Number `json:"amount" form:"amount"` 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
}

View File

@@ -0,0 +1,21 @@
package model
type TransactionStatus struct {
tableName struct{} `pg:"transactionStatus,alias:transactionStatus"`
BaseModel
Name string `json:"name" pg:"name"`
Status string `json:"status" pg:"status,notnull"`
}
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
}

View File

@@ -1,4 +1,4 @@
package models package model
type TransactionType struct { type TransactionType struct {
tableName struct{} `pg:"transactionTypes,alias:transactionTypes"` tableName struct{} `pg:"transactionTypes,alias:transactionTypes"`
@@ -11,3 +11,11 @@ type NewTransactionTypeBody struct {
Name string `json:"name" form:"name"` Name string `json:"name" form:"name"`
Type string `json:"type" form:"type"` 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
}

View File

@@ -1,4 +1,4 @@
package models package model
type Wallet struct { type Wallet struct {
tableName struct{} `pg:"wallets,alias:wallets"` tableName struct{} `pg:"wallets,alias:wallets"`
@@ -33,3 +33,18 @@ type WalletEdit struct {
Id string `json:"id" form:"id"` Id string `json:"id" form:"id"`
Name string `json:"name" form:"name"` 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
}

View File

@@ -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"`
}

View File

@@ -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"`
}

View File

@@ -1,13 +0,0 @@
package models
type TransactionStatus struct {
tableName struct{} `pg:"transactionStatus,alias:transactionStatus"`
BaseModel
Name string `json:"name" pg:"name"`
Status string `json:"status" pg:"status,notnull"`
}
type NewTransactionStatusBody struct {
Name string `json:"name" form:"name"`
Status string `json:"status" form:"status"`
}

53
pkg/repository/api.go Normal file
View File

@@ -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)
}

View File

@@ -0,0 +1,61 @@
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 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{}, params model.Params) (*model.FilteredResponse, error) {
filtered := new(model.FilteredResponse)
filtered.Params = params
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 filtered, err
}

View File

@@ -0,0 +1,284 @@
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, 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()
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, 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)
filtered, err := FilteredResponse(query, am, flt.Params)
if err != nil {
return nil, err
}
tx.Commit()
return filtered, 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, 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 nil, err
}
return am, 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()
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.UserId != "" {
qry.Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), flt.UserId)
}
if flt.WalletId != "" {
qry.Where("? = ?", pg.Ident("wallet_id"), flt.WalletId)
}
}

View File

@@ -0,0 +1,68 @@
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) (*[]model.SubscriptionType, error) {
wm := new([]model.SubscriptionType)
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
}

View File

@@ -0,0 +1,316 @@
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, tx *pg.Tx) (*model.Transaction, error) {
var commit = false
if tx == nil {
commit = true
db := as.db.WithContext(ctx)
tx, _ = db.Begin()
}
if commit {
defer tx.Rollback()
}
_, err := tx.Model(tm).Insert()
if err != nil {
return nil, err
}
if commit {
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, flt *filter.TransactionFilter) (*model.FilteredResponse, *model.Exception) {
db := as.db.WithContext(ctx)
exceptionReturn := new(model.Exception)
wm := new([]model.Transaction)
tx, _ := db.Begin()
defer tx.Rollback()
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 nil, exceptionReturn
}
flt.TransactionStatusId = transactionStatus.Id
}
query := tx.Model(wm)
as.OnBeforeGetTransactionFilter(query, flt)
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 nil, exceptionReturn
}
tx.Commit()
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 transactions.
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, flt *filter.TransactionFilter) (*model.FilteredResponse, *model.Exception) {
db := as.db.WithContext(ctx)
wm := new([]model.Transaction)
exceptionReturn := new(model.Exception)
filtered := new(model.FilteredResponse)
tx, _ := db.Begin()
defer tx.Rollback()
tsFlt := filter.NewTransactionStatusFilter(model.Params{})
tsFlt.Status = "pending"
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 nil, exceptionReturn
}
flt.TransactionStatusId = transactionStatus.Id
smFlt := filter.NewSubscriptionFilter(model.Params{})
smFlt.Id = flt.Id
smFlt.WalletId = flt.WalletId
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() {
as.subscriptionRepository.SubToTrans(&sub, tx)
}
}
qry := tx.Model(wm)
as.OnBeforeGetTransactionFilter(qry, flt)
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 nil, exceptionReturn
}
tx.Commit()
return filtered, 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
}
/*
BulkEdit
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)
wm.Id = flt.Id
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.UserId != "" {
qry.Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), flt.UserId)
}
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()
}

View File

@@ -0,0 +1,156 @@
package repository
import (
"context"
"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, tm *model.TransactionStatus) (*model.TransactionStatus, 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 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, 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)
query := tx.Model(wm)
as.OnBeforeGetTransactionStatusFilter(query, flt)
err := common.GenerateEmbed(query, flt.Embed).Select()
if err != nil {
return nil, err
}
if commit {
tx.Commit()
}
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, 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).Select()
if err != nil {
return nil, err
}
if commit {
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, flt *filter.TransactionStatusFilter) (*model.TransactionStatus, error) {
am := new(model.TransactionStatus)
qry := tx.Model(am)
as.OnBeforeGetTransactionStatusFilter(qry, flt)
err := common.GenerateEmbed(qry, flt.Embed).Select()
if err != nil {
return nil, err
}
return am, nil
}
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)
}
}

View File

@@ -0,0 +1,69 @@
package repository
import (
"context"
"wallet-api/pkg/filter"
"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, tm *model.TransactionType) (*model.TransactionType, 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 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, flt *filter.TransactionTypeFilter) (*[]model.TransactionType, error) {
db := as.db.WithContext(ctx)
wm := new([]model.TransactionType)
query := db.Model(wm)
err := common.GenerateEmbed(query, flt.Embed).Select()
if err != nil {
return nil, err
}
return wm, nil
}

316
pkg/repository/user.go Normal file
View File

@@ -0,0 +1,316 @@
package repository
import (
"context"
"os"
"time"
"wallet-api/pkg/filter"
"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 UserRepository struct {
db *pg.DB
}
func NewUserRepository(db *pg.DB) *UserRepository {
return &UserRepository{
db: db,
}
}
/*
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
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) 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()
}
_, err := tx.Model(registerBody).Insert()
if err != nil {
return nil, err
}
if commit {
tx.Commit()
}
return registerBody, nil
}
func (us *UserRepository) CreateTx(ctx context.Context) (*pg.Tx, error) {
db := us.db.WithContext(ctx)
return db.Begin()
}
/*
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 *UserRepository) 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 *UserRepository) 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
}

View File

@@ -1,45 +1,45 @@
package services package repository
import ( import (
"context" "context"
"fmt" "fmt"
"time" "time"
"wallet-api/pkg/models" "wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/utl/common" "wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
) )
type WalletService struct { type WalletRepository struct {
Db *pg.DB db *pg.DB
Ss *SubscriptionService subscriptionRepository *SubscriptionRepository
}
func NewWalletRepository(db *pg.DB, ss *SubscriptionRepository) *WalletRepository {
return &WalletRepository{
db: db,
subscriptionRepository: ss,
}
} }
/* /*
New New
Inserts row to wallets table. 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.
*/
func (as *WalletService) New(ctx context.Context, am *models.NewWalletBody) (*models.Wallet, *models.Exception) {
db := as.Db.WithContext(ctx)
exceptionReturn := new(models.Exception) Args:
walletModel := new(models.Wallet) context.Context: Application context
walletModel.Init() *model.NewWalletBody: Object to be inserted
walletModel.UserID = am.UserID Returns:
walletModel.Name = am.Name *model.Wallet: Wallet object from database.
*model.Exception: Exception payload.
*/
func (as *WalletRepository) New(ctx context.Context, walletModel *model.Wallet) (*model.Wallet, error) {
db := as.db.WithContext(ctx)
_, err := db.Model(walletModel).Insert() _, err := db.Model(walletModel).Insert()
if err != nil { if err != nil {
exceptionReturn.StatusCode = 400 return nil, err
exceptionReturn.ErrorCode = "400126"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"wallets\" table: %s", err)
return nil, exceptionReturn
} }
return walletModel, nil return walletModel, nil
} }
@@ -48,31 +48,24 @@ func (as *WalletService) New(ctx context.Context, am *models.NewWalletBody) (*mo
Edit Edit
Updates row in wallets table by id. 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.
*/
func (as *WalletService) Edit(ctx context.Context, body *models.WalletEdit, id string) (*models.Wallet, *models.Exception) {
db := as.Db.WithContext(ctx)
exceptionReturn := new(models.Exception) Args:
tm := new(models.Wallet) context.Context: Application context
tm.Id = id *model.WalletEdit: Object to be edited
tm.Name = body.Name string: id to search
Returns:
*model.Wallet: Wallet object from database.
*model.Exception: Exception payload.
*/
func (as *WalletRepository) Edit(ctx context.Context, tm *model.Wallet) (*model.Wallet, error) {
db := as.db.WithContext(ctx)
tx, _ := db.Begin() tx, _ := db.Begin()
defer tx.Rollback() defer tx.Rollback()
_, err := tx.Model(tm).WherePK().UpdateNotZero() _, err := tx.Model(tm).WherePK().UpdateNotZero()
if err != nil { if err != nil {
exceptionReturn.StatusCode = 400 return nil, err
exceptionReturn.ErrorCode = "400127"
exceptionReturn.Message = fmt.Sprintf("Error updating row in \"wallets\" table: %s", err)
return nil, exceptionReturn
} }
tx.Commit() tx.Commit()
@@ -84,31 +77,28 @@ func (as *WalletService) Edit(ctx context.Context, body *models.WalletEdit, id s
Get Get
Gets row in wallets table by id. 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.
*/
func (as *WalletService) Get(ctx context.Context, id string, params *models.Params) (*models.Wallet, *models.Exception) {
db := as.Db.WithContext(ctx)
exceptionReturn := new(models.Exception)
wm := new(models.Wallet) Args:
wm.Id = id 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, flt *filter.WalletFilter) (*model.Wallet, error) {
db := as.db.WithContext(ctx)
wm := new(model.Wallet)
wm.Id = flt.Id
tx, _ := db.Begin() tx, _ := db.Begin()
defer tx.Rollback() defer tx.Rollback()
qry := tx.Model(wm) qry := tx.Model(wm)
err := common.GenerateEmbed(qry, params.Embed).WherePK().Select() err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select()
if err != nil { if err != nil {
exceptionReturn.StatusCode = 400 return nil, err
exceptionReturn.ErrorCode = "400128"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"wallets\" table: %s", err)
return nil, exceptionReturn
} }
tx.Commit() tx.Commit()
@@ -120,27 +110,28 @@ func (as *WalletService) Get(ctx context.Context, id string, params *models.Para
GetAll GetAll
Gets filtered rows from wallets table. Gets filtered rows from wallets table.
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)
wm := new([]models.Wallet)
query := db.Model(wm).Where("? = ?", pg.Ident("user_id"), am.Id) Args:
err := FilteredResponse(query, wm, filtered) context.Context: Application context
*model.Auth: Authentication object
*model.FilteredResponse: filter options
Returns:
*model.Exception: Exception payload.
*/
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"), flt.UserId)
filtered, err := FilteredResponse(query, wm, flt.Params)
if err != nil { if err != nil {
exceptionReturn.StatusCode = 400 exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400134" exceptionReturn.ErrorCode = "400134"
exceptionReturn.Message = fmt.Sprintf("Error selecting rows in \"wallets\" table: %s", err) exceptionReturn.Message = fmt.Sprintf("Error selecting rows in \"wallets\" table: %s", err)
return exceptionReturn return nil, exceptionReturn
} }
return nil return filtered, nil
} }
/* /*
@@ -149,23 +140,24 @@ GetHeader
Gets row from wallets table. Gets row from wallets table.
Calculates previous month, current and next month totals. 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.
*/
func (as *WalletService) GetHeader(ctx context.Context, am *models.Auth, walletId string) (*models.WalletHeader, *models.Exception) {
db := as.Db.WithContext(ctx)
wm := new(models.WalletHeader) Args:
wallets := new([]models.WalletTransactions) context.Context: Application context
transactions := new([]models.Transaction) *model.Auth: Authentication object
subscriptions := new([]models.Subscription) string: wallet id to search
transactionStatus := new(models.TransactionStatus) Returns:
exceptionReturn := new(models.Exception) *model.WalletHeader: generated wallet header object
*model.Exception: Exception payload.
*/
func (as *WalletRepository) GetHeader(ctx context.Context, flt *filter.WalletHeaderFilter) (*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() tx, _ := db.Begin()
defer tx.Rollback() defer tx.Rollback()
@@ -177,9 +169,9 @@ func (as *WalletService) GetHeader(ctx context.Context, am *models.Auth, walletI
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatuses\" table: %s", err) exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatuses\" table: %s", err)
return nil, exceptionReturn return nil, exceptionReturn
} }
query2 := tx.Model(subscriptions).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id).Relation("TransactionType").Relation("SubscriptionType") query2 := tx.Model(subscriptions).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), flt.UserId).Relation("TransactionType").Relation("SubscriptionType")
if walletId != "" { if flt.WalletId != "" {
query2.Where("? = ?", pg.Ident("wallet_id"), walletId) query2.Where("? = ?", pg.Ident("wallet_id"), flt.WalletId)
} }
query2.Select() query2.Select()
if err != nil { if err != nil {
@@ -198,9 +190,9 @@ func (as *WalletService) GetHeader(ctx context.Context, am *models.Auth, walletI
firstOfNextMonth := time.Date(currentYear, currentMonth+1, 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) 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") query := tx.Model(transactions).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), flt.UserId).Relation("TransactionType")
if walletId != "" { if flt.WalletId != "" {
query.Where("? = ?", pg.Ident("wallet_id"), walletId) query.Where("? = ?", pg.Ident("wallet_id"), flt.WalletId)
} }
query = query.Where("? = ?", pg.Ident("transaction_status_id"), transactionStatus.Id) query = query.Where("? = ?", pg.Ident("transaction_status_id"), transactionStatus.Id)
query.Select() query.Select()
@@ -275,25 +267,31 @@ func (as *WalletService) GetHeader(ctx context.Context, am *models.Auth, walletI
} }
wm.Currency = "USD" wm.Currency = "USD"
wm.WalletId = walletId wm.WalletId = flt.WalletId
return wm, nil return wm, nil
} }
func (as *WalletRepository) CreateTx(ctx context.Context) (*pg.Tx, error) {
db := as.db.WithContext(ctx)
return db.Begin()
}
/* /*
addWhere addWhere
Appends Transaction to the belonging walletId. Appends Transaction to the belonging walletId.
If missing, it creates the item list. If missing, it creates the item list.
Args:
*[]models.WalletTransactions: list to append to Args:
string: wallet id to check *[]model.WalletTransactions: list to append to
models.Transaction: Transaction to append string: wallet id to check
Returns: model.Transaction: Transaction to append
*models.Exception: Exception payload. Returns:
*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 var exists bool
for a := range *s { for a := range *s {
if (*s)[a].WalletId == walletId { if (*s)[a].WalletId == walletId {
@@ -302,7 +300,7 @@ func addWhere(s *[]models.WalletTransactions, walletId string, e models.Transact
} }
} }
if !exists { if !exists {
var walletTransaction models.WalletTransactions var walletTransaction model.WalletTransactions
walletTransaction.WalletId = walletId walletTransaction.WalletId = walletId
walletTransaction.Transactions = append(walletTransaction.Transactions, e) walletTransaction.Transactions = append(walletTransaction.Transactions, e)
*s = append(*s, walletTransaction) *s = append(*s, walletTransaction)

47
pkg/service/api.go Normal file
View File

@@ -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: 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) []error {
return as.repository.PostMigrate(ctx, version)
}

28
pkg/service/service.go Normal file
View File

@@ -0,0 +1,28 @@
package service
import (
"wallet-api/pkg/repository"
"go.uber.org/dig"
)
/*
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)
}

161
pkg/service/subscription.go Normal file
View File

@@ -0,0 +1,161 @@
package service
import (
"context"
"fmt"
"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: 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, tm *model.Subscription) (*model.Subscription, *model.Exception) {
exceptionReturn := new(model.Exception)
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, flt filter.SubscriptionFilter) (*model.Subscription, *model.Exception) {
exceptionReturn := new(model.Exception)
response, err := as.repository.Get(ctx, 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) (*model.FilteredResponse, *model.Exception) {
exceptionReturn := new(model.Exception)
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 nil, exceptionReturn
}
return filtered, 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, tm *model.Subscription) (*model.Subscription, *model.Exception) {
exceptionReturn := new(model.Exception)
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
}

View File

@@ -0,0 +1,71 @@
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: 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, tm *model.SubscriptionType) (*model.SubscriptionType, *model.Exception) {
exceptionReturn := new(model.Exception)
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, flt *filter.SubscriptionTypeFilter) (*[]model.SubscriptionType, *model.Exception) {
exceptionReturn := new(model.Exception)
response, err := as.repository.GetAll(ctx, flt)
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
}

207
pkg/service/transaction.go Normal file
View File

@@ -0,0 +1,207 @@
package service
import (
"context"
"fmt"
"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
transactionStatusRepository *repository.TransactionStatusRepository
}
func NewTransactionService(repository *repository.TransactionRepository, sr *repository.SubscriptionRepository, tsr *repository.TransactionStatusRepository) *TransactionService {
return &TransactionService{
repository: repository,
subscriptionRepository: sr,
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 *TransactionService) New(ctx context.Context, tm *model.Transaction) (*model.Transaction, *model.Exception) {
exceptionReturn := new(model.Exception)
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
}
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
}
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
}
/*
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, flt *filter.TransactionFilter) (*model.FilteredResponse, *model.Exception) {
exceptionReturn := new(model.Exception)
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 nil, exceptionReturn
}
return filtered, nil
}
/*
Check
Checks subscriptions and create transactions.
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.FilteredResponse, *model.Exception) {
exceptionReturn := new(model.Exception)
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 nil, exceptionReturn
}
return filtered, 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, tm *model.Transaction) (*model.Transaction, *model.Exception) {
exceptionReturn := new(model.Exception)
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
}
/*
BulkEdit
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, transactions *[]model.Transaction) (*[]model.Transaction, *model.Exception) {
exceptionReturn := new(model.Exception)
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
}

View File

@@ -0,0 +1,91 @@
package service
import (
"context"
"fmt"
"wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/repository"
)
type TransactionStatusService struct {
repository *repository.TransactionStatusRepository
}
func NewTransactionStatusService(repository *repository.TransactionStatusRepository) *TransactionStatusService {
return &TransactionStatusService{
repository: repository,
}
}
/*
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 *TransactionStatusService) New(ctx context.Context, tm *model.TransactionStatus) (*model.TransactionStatus, *model.Exception) {
exceptionReturn := new(model.Exception)
response, err := as.repository.New(ctx, tm)
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 response, 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 *TransactionStatusService) GetAll(ctx context.Context, flt *filter.TransactionStatusFilter) (*[]model.TransactionStatus, *model.Exception) {
exceptionReturn := new(model.Exception)
response, err := as.repository.GetAll(ctx, flt, nil)
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 response, 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, flt, nil)
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
}

View File

@@ -0,0 +1,71 @@
package service
import (
"context"
"fmt"
"wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/repository"
)
type TransactionTypeService struct {
repository *repository.TransactionTypeRepository
}
func NewTransactionTypeService(repository *repository.TransactionTypeRepository) *TransactionTypeService {
return &TransactionTypeService{
repository: repository,
}
}
/*
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 *TransactionTypeService) New(ctx context.Context, tm *model.TransactionType) (*model.TransactionType, *model.Exception) {
exceptionReturn := new(model.Exception)
response, err := as.repository.New(ctx, tm)
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 response, 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 *TransactionTypeService) GetAll(ctx context.Context, flt *filter.TransactionTypeFilter) (*[]model.TransactionType, *model.Exception) {
exceptionReturn := new(model.Exception)
response, err := as.repository.GetAll(ctx, flt)
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 response, nil
}

View File

@@ -1,90 +1,109 @@
package services package service
import ( import (
"context" "context"
"os" "os"
"time" "time"
"wallet-api/pkg/models" "wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/repository"
"wallet-api/pkg/utl/common" "wallet-api/pkg/utl/common"
"wallet-api/pkg/utl/configs" "wallet-api/pkg/utl/configs"
jwt "github.com/dgrijalva/jwt-go" jwt "github.com/dgrijalva/jwt-go"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"github.com/go-pg/pg/v10"
) )
type UsersService struct { type UserService struct {
Db *pg.DB repository *repository.UserRepository
}
func NewUserService(repository *repository.UserRepository) *UserService {
return &UserService{
repository: repository,
}
} }
/* /*
Create Create
Inserts new row to users table. Inserts new row to users table.
Args:
context.Context: Application context Args:
*models.User: User object to create context.Context: Application context
Returns: *model.User: User object to create
*models.User: User object from database Returns:
*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 *UserService) Create(ctx context.Context, registerBody *model.User) (*model.User, *model.Exception) {
db := us.Db.WithContext(ctx) exceptionReturn := new(model.Exception)
check := new(models.User) tx, _ := us.repository.CreateTx(ctx)
exceptionReturn := new(models.Exception)
tx, _ := db.Begin()
defer tx.Rollback() 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 != "" { if check.Username != "" || check.Email != "" {
exceptionReturn.Message = "User already exists" exceptionReturn.Message = "User already exists"
exceptionReturn.ErrorCode = "400101" exceptionReturn.ErrorCode = "400101"
exceptionReturn.StatusCode = 400 exceptionReturn.StatusCode = 400
return check, exceptionReturn return nil, exceptionReturn
} }
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(registerBody.Password), bcrypt.DefaultCost) hashedPassword, err := bcrypt.GenerateFromPassword([]byte(registerBody.Password), bcrypt.DefaultCost)
common.CheckError(err) common.CheckError(err)
registerBody.Password = string(hashedPassword) registerBody.Password = string(hashedPassword)
_, err = tx.Model(registerBody).Insert() us.repository.Create(ctx, tx, registerBody)
if err != nil { if err != nil {
exceptionReturn.Message = "Error creating user" exceptionReturn.Message = "Error creating user"
exceptionReturn.ErrorCode = "400102" exceptionReturn.ErrorCode = "400102"
exceptionReturn.StatusCode = 400 exceptionReturn.StatusCode = 400
return nil, exceptionReturn
} }
tx.Commit() tx.Commit()
return registerBody, exceptionReturn return registerBody, nil
} }
/* /*
Login Login
Gets row from users table by email and valid password. Gets row from users table by email and valid password.
Args:
context.Context: Application context Args:
*models.Login: object to search context.Context: Application context
Returns: *model.Login: object to search
*models.Token: new session token Returns:
*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 *UserService) Login(ctx context.Context, body *model.Login) (*model.Token, *model.Exception) {
db := us.Db.WithContext(ctx) exceptionReturn := new(model.Exception)
tokenPayload := new(model.Token)
loginBody := new(model.User)
check := new(models.User) loginBody.Email = body.Email
exceptionReturn := new(models.Exception) loginBody.Username = body.Email
tokenPayload := new(models.Token)
tx, _ := db.Begin() tx, _ := us.repository.CreateTx(ctx)
defer tx.Rollback() 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 == "" { if check.Email == "" {
exceptionReturn.Message = "Email not found" exceptionReturn.Message = "Email not found"
@@ -100,20 +119,18 @@ func (us *UsersService) Login(ctx context.Context, loginBody *models.Login) (*mo
return tokenPayload, exceptionReturn 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.Message = "Incorrect password"
exceptionReturn.ErrorCode = "400104" exceptionReturn.ErrorCode = "400104"
exceptionReturn.StatusCode = 400 exceptionReturn.StatusCode = 400
return tokenPayload, exceptionReturn return tokenPayload, exceptionReturn
} }
token, err := CreateToken(check, loginBody.RememberMe) token, err := CreateToken(check, body.RememberMe)
common.CheckError(err) common.CheckError(err)
tokenPayload.Token = token tokenPayload.Token = token
tx.Commit()
return tokenPayload, exceptionReturn return tokenPayload, exceptionReturn
} }
@@ -123,46 +140,43 @@ Deactivate
Updates row in users table. Updates row in users table.
IsActive column is set to false IsActive column is set to false
Args:
context.Context: Application context Args:
*models.Auth: Authentication object context.Context: Application context
Returns: *model.Auth: Authentication object
*models.MessageResponse Returns:
*models.Exception *model.MessageResponse
*model.Exception
*/ */
func (us *UsersService) Deactivate(ctx context.Context, auth *models.Auth) (*models.MessageResponse, *models.Exception) { func (us *UserService) Deactivate(ctx context.Context, flt *filter.UserFilter) (*model.MessageResponse, *model.Exception) {
db := us.Db.WithContext(ctx) mm := new(model.MessageResponse)
me := new(model.Exception)
mm := new(models.MessageResponse) tx, _ := us.repository.CreateTx(ctx)
me := new(models.Exception)
um := new(models.User)
tx, _ := db.Begin()
defer tx.Rollback() 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 { if err != nil {
me.ErrorCode = "404101" me.ErrorCode = "404101"
me.Message = "User not found" me.Message = "User not found"
me.StatusCode = 404 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 { if err != nil {
me.ErrorCode = "400105" me.ErrorCode = "400105"
me.Message = "Could not deactivate user" me.Message = "Could not deactivate user"
me.StatusCode = 400 me.StatusCode = 400
return mm, me return nil, me
} }
mm.Message = "User successfully deactivated." mm.Message = "User successfully deactivated."
tx.Commit() tx.Commit()
return mm, me return mm, nil
} }
/* /*
@@ -171,14 +185,15 @@ CreateToken
Generates new jwt token. Generates new jwt token.
It encodes the user id. Based on rememberMe it is valid through 48hours or 2hours. It encodes the user id. Based on rememberMe it is valid through 48hours or 2hours.
Args:
*models.User: User object to encode Args:
bool: Should function generate longer lasting token (48hrs) *model.User: User object to encode
Returns: bool: Should function generate longer lasting token (48hrs)
string: Generated token Returns:
error: Error that occured in the process 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 := jwt.MapClaims{}
atClaims["authorized"] = true atClaims["authorized"] = true
atClaims["id"] = user.Id atClaims["id"] = user.Id

297
pkg/service/wallet.go Normal file
View File

@@ -0,0 +1,297 @@
package service
import (
"context"
"fmt"
"time"
"wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/repository"
)
type WalletService struct {
repository *repository.WalletRepository
subscriptionRepository *repository.SubscriptionRepository
transactionStatusRepository *repository.TransactionStatusRepository
transactionRepository *repository.TransactionRepository
}
func NewWalletService(repository *repository.WalletRepository, subscriptionRepository *repository.SubscriptionRepository, transactionStatusRepository *repository.TransactionStatusRepository, transactionRepository *repository.TransactionRepository) *WalletService {
return &WalletService{
repository: repository,
subscriptionRepository: subscriptionRepository,
transactionStatusRepository: transactionStatusRepository,
transactionRepository: transactionRepository,
}
}
/*
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 *WalletService) New(ctx context.Context, am *model.NewWalletBody) (*model.Wallet, *model.Exception) {
exceptionReturn := new(model.Exception)
walletModel := new(model.Wallet)
walletModel.Init()
walletModel.UserID = am.UserID
walletModel.Name = am.Name
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 response, 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 *WalletService) Edit(ctx context.Context, tm *model.Wallet) (*model.Wallet, *model.Exception) {
exceptionReturn := new(model.Exception)
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
}
return response, 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 *WalletService) Get(ctx context.Context, flt *filter.WalletFilter) (*model.Wallet, *model.Exception) {
exceptionReturn := new(model.Exception)
response, err := as.repository.Get(ctx, flt)
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 response, 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 *WalletService) GetAll(ctx context.Context, flt *filter.WalletFilter) (*model.FilteredResponse, *model.Exception) {
exceptionReturn := new(model.Exception)
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 nil, exceptionReturn
}
return response, 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 *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)
exceptionReturn := new(model.Exception)
tx, _ := as.repository.CreateTx(ctx)
defer tx.Rollback()
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
}
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"
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)
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"
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 = flt.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)
}
}

View File

@@ -1,52 +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
}
/*
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
}

View File

@@ -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
}

View File

@@ -1,75 +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
}
/*
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
}

View File

@@ -1,294 +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
}
/*
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
}

View File

@@ -1,75 +0,0 @@
package services
import (
"context"
"fmt"
"wallet-api/pkg/models"
"wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10"
)
type TransactionStatusService struct {
Db *pg.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.
*/
func (as *TransactionStatusService) New(ctx context.Context, body *models.NewTransactionStatusBody) (*models.TransactionStatus, *models.Exception) {
db := as.Db.WithContext(ctx)
tm := new(models.TransactionStatus)
exceptionReturn := new(models.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:
*[]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)
wm := new([]models.TransactionStatus)
exceptionReturn := new(models.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
}

View File

@@ -1,75 +0,0 @@
package services
import (
"context"
"fmt"
"wallet-api/pkg/models"
"wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10"
)
type TransactionTypeService struct {
Db *pg.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.
*/
func (as *TransactionTypeService) New(ctx context.Context, body *models.NewTransactionTypeBody) (*models.TransactionType, *models.Exception) {
db := as.Db.WithContext(ctx)
tm := new(models.TransactionType)
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 = "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:
*[]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)
wm := new([]models.TransactionType)
exceptionReturn := new(models.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
}

View File

@@ -1,318 +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
Ss *SubscriptionService
}
/*
New 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.Ss.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
}

View File

@@ -1,6 +1,7 @@
package common package common
import ( import (
"github.com/gin-gonic/gin"
"log" "log"
"net" "net"
"os" "os"
@@ -8,6 +9,18 @@ import (
"strings" "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) { func CheckError(err error) {
if err != nil { if err != nil {
log.Printf("Error occured. %v", err) log.Printf("Error occured. %v", err)
@@ -38,4 +51,13 @@ func GetIP() string {
} }
} }
return "" return ""
} }
func Find[T any](lst *[]T, callback func(item *T) bool) *T {
for _, item := range *lst {
if callback(&item) {
return &item
}
}
return nil
}