partial repository layer added

This commit is contained in:
Fran Jurmanović
2022-09-27 00:33:44 +02:00
parent 13ce0735d0
commit 82e97fc97f
73 changed files with 2686 additions and 1216 deletions

View File

@@ -1,9 +1,8 @@
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/common"
"wallet-api/pkg/utl/configs" "wallet-api/pkg/utl/configs"
@@ -47,22 +46,5 @@ func Routes(s *gin.Engine, db *pg.DB) {
c.Provide(func() *pg.DB { c.Provide(func() *pg.DB {
return db return db
}) })
c.Provide(services.NewApiService) controller.InitializeControllers(c)
c.Provide(services.NewSubscriptionService)
c.Provide(services.NewSubscriptionTypeService)
c.Provide(services.NewTransactionService)
c.Provide(services.NewTransactionStatusService)
c.Provide(services.NewTransactionTypeService)
c.Provide(services.NewUsersService)
c.Provide(services.NewWalletService)
c.Invoke(controllers.NewApiController)
c.Invoke(controllers.NewAuthController)
c.Invoke(controllers.NewWalletsController)
c.Invoke(controllers.NewWalletsHeaderController)
c.Invoke(controllers.NewTransactionController)
c.Invoke(controllers.NewTransactionStatusController)
c.Invoke(controllers.NewTransactionTypeController)
c.Invoke(controllers.NewSubscriptionController)
c.Invoke(controllers.NewSubscriptionTypeController)
} }

View File

@@ -1,15 +1,15 @@
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" "wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type ApiController struct { type ApiController struct {
service *services.ApiService service *service.ApiService
} }
/* /*
@@ -23,7 +23,7 @@ Initializes ApiController.
Returns: Returns:
*ApiController: Controller for "api" interactions *ApiController: Controller for "api" interactions
*/ */
func NewApiController(as *services.ApiService, routeGroups *common.RouteGroups) *ApiController { func NewApiController(as *service.ApiService, routeGroups *common.RouteGroups) *ApiController {
ac := &ApiController{ ac := &ApiController{
service: as, service: as,
} }

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,16 +1,17 @@
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" "wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type SubscriptionController struct { type SubscriptionController struct {
service *services.SubscriptionService service *service.SubscriptionService
} }
/* /*
@@ -24,7 +25,7 @@ Initializes SubscriptionController.
Returns: Returns:
*SubscriptionController: Controller for "subscription" route interactions *SubscriptionController: Controller for "subscription" route interactions
*/ */
func NewSubscriptionController(as *services.SubscriptionService, routeGroups *common.RouteGroups) *SubscriptionController { func NewSubscriptionController(as *service.SubscriptionService, routeGroups *common.RouteGroups) *SubscriptionController {
wc := &SubscriptionController{ wc := &SubscriptionController{
service: as, service: as,
} }
@@ -49,7 +50,7 @@ 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
@@ -72,7 +73,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
@@ -95,18 +96,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) body := new(model.Auth)
params := new(models.Params) params := new(model.Params)
auth := c.MustGet("auth") auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id body.Id = 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.service.Get(c, body, id, params) flt := filter.NewSubscriptionFilter(*params)
flt.Id = id
fr, exception := wc.service.Get(c, body, *flt)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return
@@ -117,12 +121,12 @@ 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) body := new(model.Auth)
auth := c.MustGet("auth") auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id body.Id = auth.(*model.Auth).Id
end := new(models.SubscriptionEnd) end := new(model.SubscriptionEnd)
if err := c.ShouldBind(end); err != nil { if err := c.ShouldBind(end); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return return
@@ -146,14 +150,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) fr := FilteredResponse(c)
wallet, _ := c.GetQuery("walletId") wallet, _ := c.GetQuery("walletId")
exception := wc.service.GetAll(c, body, wallet, fr) flt := filter.NewSubscriptionFilter(model.Params{})
flt.WalletId = wallet
flt.Id = auth.(*model.Auth).Id
exception := wc.service.GetAll(c, flt, fr)
if exception != nil { if exception != nil {
c.JSON(exception.StatusCode, exception) c.JSON(exception.StatusCode, exception)
return return

View File

@@ -1,16 +1,16 @@
package controllers package controller
import ( import (
"net/http" "net/http"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"wallet-api/pkg/services" "wallet-api/pkg/service"
"wallet-api/pkg/utl/common" "wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type SubscriptionTypeController struct { type SubscriptionTypeController struct {
service *services.SubscriptionTypeService service *service.SubscriptionTypeService
} }
/* /*
@@ -24,7 +24,7 @@ Initializes SubscriptionTypeController.
Returns: Returns:
*SubscriptionTypeController: Controller for "subscription-types" route interactions *SubscriptionTypeController: Controller for "subscription-types" route interactions
*/ */
func NewSubscriptionTypeController(as *services.SubscriptionTypeService, routeGroups *common.RouteGroups) *SubscriptionTypeController { func NewSubscriptionTypeController(as *service.SubscriptionTypeService, routeGroups *common.RouteGroups) *SubscriptionTypeController {
wc := &SubscriptionTypeController{ wc := &SubscriptionTypeController{
service: as, service: as,
} }
@@ -42,7 +42,7 @@ 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

View File

@@ -1,16 +1,16 @@
package controllers package controller
import ( import (
"net/http" "net/http"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"wallet-api/pkg/services" "wallet-api/pkg/service"
"wallet-api/pkg/utl/common" "wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type TransactionController struct { type TransactionController struct {
service *services.TransactionService service *service.TransactionService
} }
/* /*
@@ -24,7 +24,7 @@ Initializes TransactionController.
Returns: Returns:
*TransactionController: Controller for "transaction" route interactions *TransactionController: Controller for "transaction" route interactions
*/ */
func NewTransactionController(as *services.TransactionService, routeGroups *common.RouteGroups) *TransactionController { func NewTransactionController(as *service.TransactionService, routeGroups *common.RouteGroups) *TransactionController {
wc := &TransactionController{ wc := &TransactionController{
service: as, service: as,
} }
@@ -54,7 +54,7 @@ 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
@@ -75,9 +75,9 @@ 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) body := new(model.Auth)
auth := c.MustGet("auth") auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id body.Id = auth.(*model.Auth).Id
fr := FilteredResponse(c) fr := FilteredResponse(c)
wallet, _ := c.GetQuery("walletId") wallet, _ := c.GetQuery("walletId")
@@ -101,9 +101,9 @@ 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) body := new(model.Auth)
auth := c.MustGet("auth") auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id body.Id = auth.(*model.Auth).Id
fr := FilteredResponse(c) fr := FilteredResponse(c)
wallet, _ := c.GetQuery("walletId") wallet, _ := c.GetQuery("walletId")
@@ -124,7 +124,7 @@ 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
@@ -147,7 +147,7 @@ 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
@@ -168,11 +168,11 @@ 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) body := new(model.Auth)
params := new(models.Params) params := new(model.Params)
auth := c.MustGet("auth") auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id body.Id = auth.(*model.Auth).Id
id := c.Param("id") id := c.Param("id")

View File

@@ -1,16 +1,16 @@
package controllers package controller
import ( import (
"net/http" "net/http"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"wallet-api/pkg/services" "wallet-api/pkg/service"
"wallet-api/pkg/utl/common" "wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type TransactionStatusController struct { type TransactionStatusController struct {
service *services.TransactionStatusService service *service.TransactionStatusService
} }
/* /*
@@ -24,7 +24,7 @@ Initializes TransactionStatusController.
Returns: Returns:
*TransactionStatusController: Controller for "transaction-status" route interactions *TransactionStatusController: Controller for "transaction-status" route interactions
*/ */
func NewTransactionStatusController(as *services.TransactionStatusService, routeGroups *common.RouteGroups) *TransactionStatusController { func NewTransactionStatusController(as *service.TransactionStatusService, routeGroups *common.RouteGroups) *TransactionStatusController {
wc := &TransactionStatusController{ wc := &TransactionStatusController{
service: as, service: as,
} }
@@ -42,7 +42,7 @@ 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

View File

@@ -1,16 +1,16 @@
package controllers package controller
import ( import (
"net/http" "net/http"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"wallet-api/pkg/services" "wallet-api/pkg/service"
"wallet-api/pkg/utl/common" "wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type TransactionTypeController struct { type TransactionTypeController struct {
service *services.TransactionTypeService service *service.TransactionTypeService
} }
/* /*
@@ -24,7 +24,7 @@ Initializes TransactionTypeController.
Returns: Returns:
*TransactionTypeController: Controller for "transaction-types" route interactions *TransactionTypeController: Controller for "transaction-types" route interactions
*/ */
func NewTransactionTypeController(as *services.TransactionTypeService, routeGroups *common.RouteGroups) *TransactionTypeController { func NewTransactionTypeController(as *service.TransactionTypeService, routeGroups *common.RouteGroups) *TransactionTypeController {
wc := &TransactionTypeController{ wc := &TransactionTypeController{
service: as, service: as,
} }
@@ -42,7 +42,7 @@ 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

View File

@@ -1,32 +1,32 @@
package controllers package controller
import ( import (
"net/http" "net/http"
"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" "wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type AuthController struct { type UserController struct {
service *services.UsersService service *service.UserService
} }
/* /*
NewAuthController NewUserController
Initializes AuthController. Initializes UserController.
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, routeGroups *common.RouteGroups) *AuthController { func NewUserController(rs *service.UserService, routeGroups *common.RouteGroups) *UserController {
rc := &AuthController{ rc := &UserController{
service: rs, service: rs,
} }
@@ -44,8 +44,8 @@ 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
@@ -66,8 +66,8 @@ 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 {
@@ -90,10 +90,10 @@ 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) auth := new(model.Auth)
authGet := c.MustGet("auth") authGet := c.MustGet("auth")
auth.Id = authGet.(*models.Auth).Id auth.Id = authGet.(*model.Auth).Id
mr, er := rc.service.Deactivate(c, auth) mr, er := rc.service.Deactivate(c, auth)
@@ -111,9 +111,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

@@ -1,30 +1,30 @@
package controllers package controller
import ( import (
"wallet-api/pkg/models" "wallet-api/pkg/model"
"wallet-api/pkg/services" "wallet-api/pkg/service"
"wallet-api/pkg/utl/common" "wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type WalletsHeaderController struct { type WalletHeaderController struct {
service *services.WalletService service *service.WalletService
} }
/* /*
NewWalletsHeaderController NewWalletHeaderController
Initializes WalletsHeaderController. Initializes WalletHeaderController.
Args: Args:
*services.WalletService: Wallet service *services.WalletService: Wallet service
*gin.RouterGroup: Gin Router Group *gin.RouterGroup: Gin Router Group
Returns: Returns:
*WalletsHeaderController: Controller for "wallet/wallet-header" route interactions *WalletHeaderController: Controller for "wallet/wallet-header" route interactions
*/ */
func NewWalletsHeaderController(as *services.WalletService, routeGroups *common.RouteGroups) *WalletsHeaderController { func NewWalletHeaderController(as *service.WalletService, routeGroups *common.RouteGroups) *WalletHeaderController {
wc := &WalletsHeaderController{ wc := &WalletHeaderController{
service: as, service: as,
} }
@@ -39,13 +39,13 @@ Get
*gin.Context: Gin Application Context *gin.Context: Gin Application Context
*/ */
// ROUTE (GET /wallet/wallet-header) // ROUTE (GET /wallet/wallet-header)
func (wc *WalletsHeaderController) Get(c *gin.Context) { func (wc *WalletHeaderController) Get(c *gin.Context) {
body := new(models.Auth) body := new(model.Auth)
walletId, _ := c.GetQuery("walletId") walletId, _ := c.GetQuery("walletId")
auth := c.MustGet("auth") auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id body.Id = auth.(*model.Auth).Id
wm, exception := wc.service.GetHeader(c, body, walletId) wm, exception := wc.service.GetHeader(c, body, walletId)
if exception != nil { if exception != nil {

View File

@@ -1,31 +1,31 @@
package controllers package controller
import ( import (
"net/http" "net/http"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"wallet-api/pkg/services" "wallet-api/pkg/service"
"wallet-api/pkg/utl/common" "wallet-api/pkg/utl/common"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
type WalletsController struct { type WalletController struct {
service *services.WalletService service *service.WalletService
} }
/* /*
NewWalletsController NewWalletController
Initializes WalletsController. Initializes WalletController.
Args: Args:
*services.WalletService: Wallet service *services.WalletService: Wallet service
*gin.RouterGroup: Gin Router Group *gin.RouterGroup: Gin Router Group
Returns: Returns:
*WalletsController: Controller for "wallet" route interactions *WalletController: Controller for "wallet" route interactions
*/ */
func NewWalletsController(as *services.WalletService, routeGroups *common.RouteGroups) *WalletsController { func NewWalletController(as *service.WalletService, routeGroups *common.RouteGroups) *WalletController {
wc := &WalletsController{ wc := &WalletController{
service: as, service: as,
} }
@@ -43,8 +43,8 @@ New
*gin.Context: Gin Application Context *gin.Context: Gin Application Context
*/ */
// ROUTE (POST /wallet) // ROUTE (POST /wallet)
func (wc *WalletsController) New(c *gin.Context) { func (wc *WalletController) New(c *gin.Context) {
body := new(models.NewWalletBody) body := new(model.NewWalletBody)
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()})
@@ -52,7 +52,7 @@ func (wc *WalletsController) New(c *gin.Context) {
} }
get := c.MustGet("auth") get := c.MustGet("auth")
body.UserID = get.(*models.Auth).Id body.UserID = get.(*model.Auth).Id
wm, exception := wc.service.New(c, body) wm, exception := wc.service.New(c, body)
if exception != nil { if exception != nil {
@@ -68,10 +68,10 @@ GetAll
*gin.Context: Gin Application Context *gin.Context: Gin Application Context
*/ */
// ROUTE (GET /wallet) // ROUTE (GET /wallet)
func (wc *WalletsController) GetAll(c *gin.Context) { func (wc *WalletController) GetAll(c *gin.Context) {
body := new(models.Auth) body := new(model.Auth)
auth := c.MustGet("auth") auth := c.MustGet("auth")
body.Id = auth.(*models.Auth).Id body.Id = auth.(*model.Auth).Id
fr := FilteredResponse(c) fr := FilteredResponse(c)
@@ -90,8 +90,8 @@ Edit
*gin.Context: Gin Application Context *gin.Context: Gin Application Context
*/ */
// ROUTE (PUT /wallet/:id) // ROUTE (PUT /wallet/:id)
func (wc *WalletsController) Edit(c *gin.Context) { func (wc *WalletController) Edit(c *gin.Context) {
body := new(models.WalletEdit) body := new(model.WalletEdit)
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
@@ -113,8 +113,8 @@ Get
*gin.Context: Gin Application Context *gin.Context: Gin Application Context
*/ */
// ROUTE (GET /wallet/:id) // ROUTE (GET /wallet/:id)
func (wc *WalletsController) Get(c *gin.Context) { func (wc *WalletController) Get(c *gin.Context) {
params := new(models.Params) params := new(model.Params)
id := c.Param("id") id := c.Param("id")

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
}

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

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

@@ -0,0 +1,27 @@
package filter
import "go.uber.org/dig"
/*
InitializeFilters
Initializes Dependency Injection modules for filters
Args:
*dig.Container: Dig Container
*/
func InitializeFilters(c *dig.Container) {
c.Provide(NewApiFilter)
c.Provide(NewSubscriptionFilter)
c.Provide(NewSubscriptionTypeFilter)
c.Provide(NewTransactionFilter)
c.Provide(NewTransactionStatusFilter)
c.Provide(NewTransactionTypeFilter)
c.Provide(NewUserFilter)
c.Provide(NewWalletFilter)
}
type BaseFilter struct {
Id string
WalletId string
}

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,4 +1,4 @@
package models package model
type ApiModel struct { type ApiModel struct {
tableName struct{} `pg:"api,alias:api"` tableName struct{} `pg:"api,alias: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"`

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

@@ -0,0 +1,22 @@
package model
import "github.com/gin-gonic/gin"
type FilteredResponse struct {
Items interface{} `json:"items"`
Params
}
type ResponseFunc func(*gin.Context) *[]interface{}
type MessageResponse struct {
Message string `json:"message"`
}
type Params struct {
SortBy string `json:"sortBy"`
Embed string `json:"embed"`
Page int `json:"page"`
Rpp int `json:"rpp"`
TotalRecords int `json:"totalRecords"`
}

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,4 +1,4 @@
package models package model
import ( import (
"encoding/json" "encoding/json"
@@ -53,6 +53,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 +75,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"`

View File

@@ -1,4 +1,4 @@
package models package model
import ( import (
"encoding/json" "encoding/json"

View File

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

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

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

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

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,59 @@
package repository
import (
"go.uber.org/dig"
"wallet-api/pkg/model"
"wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10"
)
/*
InitializeRepositories
Initializes Dependency Injection modules for repositories
Args:
*dig.Container: Dig Container
*/
func InitializeRepositories(c *dig.Container) {
c.Provide(NewApiRepository)
c.Provide(NewSubscriptionRepository)
c.Provide(NewSubscriptionTypeRepository)
c.Provide(NewTransactionRepository)
c.Provide(NewTransactionStatusRepository)
c.Provide(NewTransactionTypeRepository)
c.Provide(NewUserRepository)
c.Provide(NewWalletRepository)
}
/*
FilteredResponse
Adds filters to query and executes it.
Args:
*pg.Query: postgres query
interface{}: model to be mapped from query execution.
*model.FilteredResponse: filter options.
*/
func FilteredResponse(qry *pg.Query, mdl interface{}, filtered *model.FilteredResponse) error {
if filtered.Page == 0 {
filtered.Page = 1
}
if filtered.Rpp == 0 {
filtered.Rpp = 20
}
if filtered.SortBy == "" {
filtered.SortBy = "date_created DESC"
}
qry = qry.Limit(filtered.Rpp).Offset((filtered.Page - 1) * filtered.Rpp).Order(filtered.SortBy)
common.GenerateEmbed(qry, filtered.Embed)
count, err := qry.SelectAndCount()
common.CheckError(err)
filtered.TotalRecords = count
filtered.Items = mdl
return err
}

View File

@@ -0,0 +1,280 @@
package repository
import (
"context"
"fmt"
"github.com/go-pg/pg/v10/orm"
"time"
"wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10"
)
type SubscriptionRepository struct {
db *pg.DB
}
func NewSubscriptionRepository(db *pg.DB) *SubscriptionRepository {
return &SubscriptionRepository{
db: db,
}
}
/*
New
Inserts new row to subscription table.
Args:
context.Context: Application context
*model.NewSubscriptionBody: Request body
Returns:
*model.Subscription: Created Subscription row object from database.
*model.Exception: Exception payload.
*/
func (as *SubscriptionRepository) New(ctx context.Context, tm *model.Subscription) (*model.Subscription, error) {
db := as.db.WithContext(ctx)
tx, _ := db.Begin()
defer tx.Rollback()
_, err := tx.Model(tm).Insert()
if err != nil {
return nil, err
}
tx.Commit()
return tm, nil
}
/*
Get
Gets row from subscription table by id.
Args:
context.Context: Application context
*model.Auth: Authentication model
string: subscription id to search
params: *model.Params
Returns:
*model.Subscription: Subscription row object from database.
*model.Exception: Exception payload.
*/
func (as *SubscriptionRepository) Get(ctx context.Context, am *model.Subscription, flt filter.SubscriptionFilter) (*model.Subscription, error) {
db := as.db.WithContext(ctx)
tx, _ := db.Begin()
defer tx.Rollback()
qry := tx.Model(am)
as.OnBeforeGetSubscriptionFilter(qry, &flt)
err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select()
if err != nil {
return nil, err
}
tx.Commit()
return am, nil
}
/*
GetAll
Gets filtered rows from subscription table.
Args:
context.Context: Application context
*model.Auth: Authentication object
string: Wallet id to search
*model.FilteredResponse: filter options
Returns:
*model.Exception: Exception payload.
*/
func (as *SubscriptionRepository) GetAll(ctx context.Context, am *[]model.Subscription, filtered *model.FilteredResponse, flt *filter.SubscriptionFilter) error {
db := as.db.WithContext(ctx)
tx, _ := db.Begin()
defer tx.Rollback()
query := tx.Model(am)
as.OnBeforeGetSubscriptionFilter(query, flt)
err := FilteredResponse(query, am, filtered)
if err != nil {
return err
}
tx.Commit()
return nil
}
/*
GetAllTx
Gets filtered rows from subscription table.
Args:
context.Context: Application context
*model.Auth: Authentication object
string: Wallet id to search
*model.FilteredResponse: filter options
Returns:
*model.Exception: Exception payload.
*/
func (as *SubscriptionRepository) GetAllTx(tx *pg.Tx, am *[]model.Subscription, flt *filter.SubscriptionFilter) error {
query := tx.Model(am)
as.OnBeforeGetSubscriptionFilter(query, flt)
err := query.Select()
if err != nil {
return err
}
tx.Commit()
return nil
}
/*
Edit
Updates row from subscription table by id.
Args:
context.Context: Application context
*model.SubscriptionEdit: Values to edit
string: id to search
Returns:
*model.Subscription: Edited Subscription row object from database.
*model.Exception: Exception payload.
*/
func (as *SubscriptionRepository) Edit(ctx context.Context, tm *model.Subscription) (*model.Subscription, error) {
db := as.db.WithContext(ctx)
tx, _ := db.Begin()
defer tx.Rollback()
_, err := tx.Model(tm).WherePK().UpdateNotZero()
if err != nil {
return nil, err
}
tx.Commit()
return tm, nil
}
/*
End
Updates row in subscription table by id.
Ends subscription with current date.
Args:
context.Context: Application context
string: id to search
Returns:
*model.Subscription: Created Subscription row object from database.
*model.Exception: Exception payload.
*/
func (as *SubscriptionRepository) End(ctx context.Context, tm *model.Subscription) (*model.Subscription, error) {
db := as.db.WithContext(ctx)
tx, _ := db.Begin()
defer tx.Rollback()
_, err := tx.Model(tm).WherePK().UpdateNotZero()
if err != nil {
return nil, err
}
tx.Commit()
return tm, nil
}
/*
SubToTrans
Generates and Inserts new Transaction rows from the subscription model.
Args:
*model.Subscription: Subscription model to generate new transactions from
*pg.Tx: Postgres query context
Returns:
*model.Exception: Exception payload.
*/
func (as *SubscriptionRepository) SubToTrans(subModel *model.Subscription, tx *pg.Tx) *model.Exception {
exceptionReturn := new(model.Exception)
now := time.Now()
currentYear, currentMonth, _ := now.Date()
currentLocation := now.Location()
transactionStatus := new(model.TransactionStatus)
firstOfNextMonth := time.Date(currentYear, currentMonth+1, 1, 0, 0, 0, 0, currentLocation)
tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "pending").Select()
//tzFirstOfNextMonth := firstOfNextMonth.In(subModel.StartDate.Location())
startDate := subModel.StartDate
stopDate := firstOfNextMonth
if subModel.HasEnd && subModel.EndDate.Before(firstOfNextMonth) {
stopDate = subModel.EndDate
}
transactions := new([]model.Transaction)
if subModel.SubscriptionType == nil {
st := new(model.SubscriptionType)
tx.Model(st).Where("? = ?", pg.Ident("id"), subModel.SubscriptionTypeID).Select()
subModel.SubscriptionType = st
}
for startDate.Before(stopDate) {
trans := subModel.ToTrans()
trans.TransactionDate = startDate
trans.TransactionStatusID = transactionStatus.Id
if startDate.After(subModel.LastTransactionDate) && (startDate.Before(now) || startDate.Equal(now)) {
*transactions = append(*transactions, *trans)
}
if subModel.SubscriptionType.Type == "monthly" {
startDate = startDate.AddDate(0, subModel.CustomRange, 0)
} else if subModel.SubscriptionType.Type == "weekly" {
startDate = startDate.AddDate(0, 0, 7*subModel.CustomRange)
} else if subModel.SubscriptionType.Type == "daily" {
startDate = startDate.AddDate(0, 0, subModel.CustomRange)
} else {
startDate = startDate.AddDate(subModel.CustomRange, 0, 0)
}
}
var err error
if len(*transactions) > 0 {
for _, trans := range *transactions {
_, err = tx.Model(&trans).Where("? = ?", pg.Ident("transaction_date"), trans.TransactionDate).Where("? = ?", pg.Ident("subscription_id"), trans.SubscriptionID).OnConflict("DO NOTHING").SelectOrInsert()
if err != nil {
_, err = tx.Model(subModel).Set("? = ?", pg.Ident("last_transaction_date"), trans.TransactionDate).WherePK().Update()
}
}
}
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400113"
exceptionReturn.Message = fmt.Sprintf("Error updating row in \"subscription\" table: %s", err)
return exceptionReturn
}
return nil
}
func (as *SubscriptionRepository) OnBeforeGetSubscriptionFilter(qry *orm.Query, flt *filter.SubscriptionFilter) {
if flt.Id != "" {
qry.Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), flt.Id)
}
if flt.WalletId != "" {
qry.Where("? = ?", pg.Ident("wallet_id"), flt.WalletId)
}
}

View File

@@ -0,0 +1,67 @@
package repository
import (
"context"
"wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10"
)
type SubscriptionTypeRepository struct {
db *pg.DB
}
func NewSubscriptionTypeRepository(db *pg.DB) *SubscriptionTypeRepository {
return &SubscriptionTypeRepository{
db: db,
}
}
/*
New
Inserts new row to subscription type table.
Args:
context.Context: Application context
*model.NewSubscriptionTypeBody: Values to create new row
Returns:
*model.SubscriptionType: Created row from database.
*model.Exception: Exception payload.
*/
func (as *SubscriptionTypeRepository) New(ctx context.Context, tm *model.SubscriptionType) (*model.SubscriptionType, error) {
db := as.db.WithContext(ctx)
_, err := db.Model(tm).Insert()
if err != nil {
return nil, err
}
return tm, nil
}
/*
GetAll
Gets all rows from subscription type table.
Args:
context.Context: Application context
string: Relations to embed
Returns:
*[]model.SubscriptionType: List of subscription type objects.
*model.Exception: Exception payload.
*/
func (as *SubscriptionTypeRepository) GetAll(ctx context.Context, flt *filter.SubscriptionTypeFilter, wm *[]model.SubscriptionType) (*[]model.SubscriptionType, error) {
db := as.db.WithContext(ctx)
query := db.Model(wm)
err := common.GenerateEmbed(query, flt.Embed).Select()
if err != nil {
return nil, err
}
return wm, nil
}

View File

@@ -0,0 +1,268 @@
package repository
import (
"context"
"fmt"
"github.com/go-pg/pg/v10/orm"
"wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10"
)
type TransactionRepository struct {
db *pg.DB
subscriptionRepository *SubscriptionRepository
transactionStatusRepository *TransactionStatusRepository
}
func NewTransactionRepository(db *pg.DB, ss *SubscriptionRepository, tsr *TransactionStatusRepository) *TransactionRepository {
return &TransactionRepository{
db: db,
subscriptionRepository: ss,
transactionStatusRepository: tsr,
}
}
/*
New row into transaction table
Inserts
Args:
context.Context: Application context
*model.NewTransactionBody: Transaction body object
Returns:
*model.Transaction: Transaction object
*model.Exception: Exception payload.
*/
func (as *TransactionRepository) New(ctx context.Context, tm *model.Transaction) (*model.Transaction, error) {
db := as.db.WithContext(ctx)
tx, _ := db.Begin()
defer tx.Rollback()
_, err := tx.Model(tm).Insert()
if err != nil {
return nil, err
}
tx.Commit()
return tm, nil
}
/*
GetAll
Gets all rows from subscription type table.
Args:
context.Context: Application context
string: Relations to embed
Returns:
*model.Exception: Exception payload.
*/
// Gets filtered rows from transaction table.
func (as *TransactionRepository) GetAll(ctx context.Context, filtered *model.FilteredResponse, flt *filter.TransactionFilter) *model.Exception {
db := as.db.WithContext(ctx)
exceptionReturn := new(model.Exception)
wm := new([]model.Transaction)
transactionStatus := new(model.TransactionStatus)
tx, _ := db.Begin()
defer tx.Rollback()
tsFlt := filter.NewTransactionStatusFilter(model.Params{})
tsFlt.Status = "completed"
_, err := as.transactionStatusRepository.GetTx(tx, transactionStatus, tsFlt)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400117"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatus\" table: %s", err)
return exceptionReturn
}
flt.TransactionStatusId = transactionStatus.Id
query := tx.Model(wm)
as.OnBeforeGetTransactionFilter(query, flt)
err = FilteredResponse(query, wm, filtered)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400118"
exceptionReturn.Message = fmt.Sprintf("Error selecting row(s) in \"transaction\" table: %s", err)
return exceptionReturn
}
tx.Commit()
return nil
}
/*
Check
Checks subscriptions and create transacitons.
Args:
context.Context: Application context
string: Relations to embed
Returns:
*model.Exception: Exception payload.
*/
// Gets filtered rows from transaction table.
func (as *TransactionRepository) Check(ctx context.Context, filtered *model.FilteredResponse, flt *filter.TransactionFilter) *model.Exception {
db := as.db.WithContext(ctx)
wm := new([]model.Transaction)
sm := new([]model.Subscription)
transactionStatus := new(model.TransactionStatus)
exceptionReturn := new(model.Exception)
tx, _ := db.Begin()
defer tx.Rollback()
tsFlt := filter.NewTransactionStatusFilter(model.Params{})
tsFlt.Status = "pending"
_, err := as.transactionStatusRepository.GetTx(tx, transactionStatus, tsFlt)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400119"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatus\" table: %s", err)
return exceptionReturn
}
flt.TransactionStatusId = transactionStatus.Id
smFlt := filter.NewSubscriptionFilter(model.Params{})
smFlt.Id = flt.Id
smFlt.WalletId = flt.WalletId
as.subscriptionRepository.GetAllTx(tx, sm, smFlt)
for _, sub := range *sm {
if sub.HasNew() {
as.subscriptionRepository.SubToTrans(&sub, tx)
}
}
qry := tx.Model(wm)
as.OnBeforeGetTransactionFilter(qry, flt)
err = FilteredResponse(qry, wm, filtered)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400120"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transaction\" table: %s", err)
return exceptionReturn
}
tx.Commit()
return nil
}
/*
Edit
Updates row in transaction table by id.
Args:
context.Context: Application context
*model.TransactionEdit: Object to edit
string: id to search
Returns:
*model.Transaction: Transaction object from database.
*model.Exception: Exception payload.
*/
func (as *TransactionRepository) Edit(ctx context.Context, tm *model.Transaction) (*model.Transaction, error) {
db := as.db.WithContext(ctx)
tx, _ := db.Begin()
defer tx.Rollback()
_, err := tx.Model(tm).WherePK().UpdateNotZero()
if err != nil {
return nil, err
}
err = tx.Model(tm).WherePK().Select()
if err != nil {
return nil, err
}
tx.Commit()
return tm, nil
}
/*
Bulk Edit
Updates row in transaction table by id.
Args:
context.Context: Application context
?[]model.Transaction Bulk Edit: Object to edit
string: id to search
Returns:
*model.Transaction: Transaction object from database.
*model.Exception: Exception payload.
*/
func (as *TransactionRepository) BulkEdit(ctx context.Context, transactions *[]model.Transaction) (*[]model.Transaction, error) {
db := as.db.WithContext(ctx)
tx, _ := db.Begin()
defer tx.Rollback()
_, err := tx.Model(transactions).WherePK().UpdateNotZero()
if err != nil {
return nil, err
}
tx.Commit()
return transactions, nil
}
/*
Get
Gets row from transaction table by id.
Args:
context.Context: Application context
*model.Auth: Authentication object
string: id to search
*model.Params: url query parameters
Returns:
*model.Transaction: Transaction object from database.
*model.Exception: Exception payload.
*/
func (as *TransactionRepository) Get(ctx context.Context, flt *filter.TransactionFilter) (*model.Transaction, error) {
db := as.db.WithContext(ctx)
wm := new(model.Transaction)
tx, _ := db.Begin()
defer tx.Rollback()
qry := tx.Model(wm)
as.OnBeforeGetTransactionFilter(qry, flt)
err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select()
if err != nil {
return nil, err
}
tx.Commit()
return wm, nil
}
func (as *TransactionRepository) OnBeforeGetTransactionFilter(qry *orm.Query, flt *filter.TransactionFilter) {
if flt.WalletId != "" {
qry.Where("? = ?", pg.Ident("wallet_id"), flt.WalletId)
}
if flt.Id != "" {
qry.Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), flt.Id)
}
if flt.NoPending && flt.TransactionStatusId != "" {
qry.Where("? = ?", pg.Ident("transaction_status_id"), flt.TransactionStatusId)
}
}

View File

@@ -0,0 +1,146 @@
package repository
import (
"context"
"fmt"
"github.com/go-pg/pg/v10/orm"
"wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10"
)
type TransactionStatusRepository struct {
db *pg.DB
}
func NewTransactionStatusRepository(db *pg.DB) *TransactionStatusRepository {
return &TransactionStatusRepository{
db: db,
}
}
/*
New
Inserts new row to transaction status table.
Args:
context.Context: Application context
*model.NewTransactionStatusBody: object to create
Returns:
*model.TransactionType: Transaction Type object from database.
*model.Exception: Exception payload.
*/
func (as *TransactionStatusRepository) New(ctx context.Context, body *model.NewTransactionStatusBody) (*model.TransactionStatus, *model.Exception) {
db := as.db.WithContext(ctx)
tm := new(model.TransactionStatus)
exceptionReturn := new(model.Exception)
tm.Init()
tm.Name = body.Name
tm.Status = body.Status
_, err := db.Model(tm).Insert()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400123"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"transactionStatus\" table: %s", err)
return nil, exceptionReturn
}
return tm, nil
}
/*
GetAll
Gets all rows from transaction status table.
Args:
context.Context: Application context
string: Relations to embed
Returns:
*[]model.TransactionStatus: List of Transaction status objects from database.
*model.Exception: Exception payload.
*/
func (as *TransactionStatusRepository) GetAll(ctx context.Context, embed string) (*[]model.TransactionStatus, *model.Exception) {
db := as.db.WithContext(ctx)
wm := new([]model.TransactionStatus)
exceptionReturn := new(model.Exception)
query := db.Model(wm)
err := common.GenerateEmbed(query, embed).Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400124"
exceptionReturn.Message = fmt.Sprintf("Error selecting rows in \"transactionStatus\" table: %s", err)
return nil, exceptionReturn
}
return wm, nil
}
/*
Get
Gets row from transactionStatus table by id.
Args:
context.Context: Application context
*model.Auth: Authentication model
string: transactionStatus id to search
params: *model.Params
Returns:
*model.Subscription: Subscription row object from database.
*model.Exception: Exception payload.
*/
func (as *TransactionStatusRepository) Get(ctx context.Context, am *model.TransactionStatus, flt filter.TransactionStatusFilter) (*model.TransactionStatus, error) {
db := as.db.WithContext(ctx)
tx, _ := db.Begin()
defer tx.Rollback()
qry := tx.Model(am)
err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select()
if err != nil {
return nil, err
}
tx.Commit()
return am, nil
}
/*
GetTx
Gets row from transactionStatus table by id.
Args:
context.Context: Application context
*model.Auth: Authentication model
string: transactionStatus id to search
params: *model.Params
Returns:
*model.Subscription: Subscription row object from database.
*model.Exception: Exception payload.
*/
func (as *TransactionStatusRepository) GetTx(tx *pg.Tx, am *model.TransactionStatus, flt *filter.TransactionStatusFilter) (*model.TransactionStatus, error) {
qry := tx.Model(am)
as.OnBeforeGetTransactionStatusFilter(qry, flt)
err := common.GenerateEmbed(qry, flt.Embed).WherePK().Select()
if err != nil {
return nil, err
}
return am, nil
}
func (as *TransactionStatusRepository) OnBeforeGetTransactionStatusFilter(qry *orm.Query, flt *filter.TransactionStatusFilter) {
if flt.Status != "" {
qry.Where("? = ?", pg.Ident("status"), flt.Status)
}
}

View File

@@ -0,0 +1,83 @@
package repository
import (
"context"
"fmt"
"wallet-api/pkg/model"
"wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10"
)
type TransactionTypeRepository struct {
db *pg.DB
}
func NewTransactionTypeRepository(db *pg.DB) *TransactionTypeRepository {
return &TransactionTypeRepository{
db: db,
}
}
/*
New
Inserts new row to transaction type table.
Args:
context.Context: Application context
*model.NewTransactionTypeBody: object to create
Returns:
*model.TransactionType: Transaction Type object from database.
*model.Exception: Exception payload.
*/
func (as *TransactionTypeRepository) New(ctx context.Context, body *model.NewTransactionTypeBody) (*model.TransactionType, *model.Exception) {
db := as.db.WithContext(ctx)
tm := new(model.TransactionType)
exceptionReturn := new(model.Exception)
tm.Init()
tm.Name = body.Name
tm.Type = body.Type
_, err := db.Model(tm).Insert()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400125"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"transactionTypes\" table: %s", err)
return nil, exceptionReturn
}
return tm, nil
}
/*
GetAll
Gets all rows from transaction type table.
Args:
context.Context: Application context
string: Relations to embed
Returns:
*[]model.TransactionType: List of Transaction type objects from database.
*model.Exception: Exception payload.
*/
func (as *TransactionTypeRepository) GetAll(ctx context.Context, embed string) (*[]model.TransactionType, *model.Exception) {
db := as.db.WithContext(ctx)
wm := new([]model.TransactionType)
exceptionReturn := new(model.Exception)
query := db.Model(wm)
err := common.GenerateEmbed(query, embed).Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400133"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionTypes\" table: %s", err)
return nil, exceptionReturn
}
return wm, nil
}

View File

@@ -1,10 +1,10 @@
package services package repository
import ( import (
"context" "context"
"os" "os"
"time" "time"
"wallet-api/pkg/models" "wallet-api/pkg/model"
"wallet-api/pkg/utl/common" "wallet-api/pkg/utl/common"
"wallet-api/pkg/utl/configs" "wallet-api/pkg/utl/configs"
@@ -14,12 +14,12 @@ import (
"github.com/go-pg/pg/v10" "github.com/go-pg/pg/v10"
) )
type UsersService struct { type UserRepository struct {
db *pg.DB db *pg.DB
} }
func NewUsersService(db *pg.DB) *UsersService { func NewUserRepository(db *pg.DB) *UserRepository {
return &UsersService{ return &UserRepository{
db: db, db: db,
} }
} }
@@ -31,16 +31,16 @@ Inserts new row to users table.
Args: Args:
context.Context: Application context context.Context: Application context
*models.User: User object to create *model.User: User object to create
Returns: Returns:
*models.User: User object from database *model.User: User object from database
*models.Exception *model.Exception
*/ */
func (us *UsersService) Create(ctx context.Context, registerBody *models.User) (*models.User, *models.Exception) { func (us *UserRepository) Create(ctx context.Context, registerBody *model.User) (*model.User, *model.Exception) {
db := us.db.WithContext(ctx) db := us.db.WithContext(ctx)
check := new(models.User) check := new(model.User)
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
tx, _ := db.Begin() tx, _ := db.Begin()
defer tx.Rollback() defer tx.Rollback()
@@ -77,17 +77,17 @@ Gets row from users table by email and valid password.
Args: Args:
context.Context: Application context context.Context: Application context
*models.Login: object to search *model.Login: object to search
Returns: Returns:
*models.Token: new session token *model.Token: new session token
*models.Exception *model.Exception
*/ */
func (us *UsersService) Login(ctx context.Context, loginBody *models.Login) (*models.Token, *models.Exception) { func (us *UserRepository) Login(ctx context.Context, loginBody *model.Login) (*model.Token, *model.Exception) {
db := us.db.WithContext(ctx) db := us.db.WithContext(ctx)
check := new(models.User) check := new(model.User)
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
tokenPayload := new(models.Token) tokenPayload := new(model.Token)
tx, _ := db.Begin() tx, _ := db.Begin()
defer tx.Rollback() defer tx.Rollback()
@@ -134,17 +134,17 @@ IsActive column is set to false
Args: Args:
context.Context: Application context context.Context: Application context
*models.Auth: Authentication object *model.Auth: Authentication object
Returns: Returns:
*models.MessageResponse *model.MessageResponse
*models.Exception *model.Exception
*/ */
func (us *UsersService) Deactivate(ctx context.Context, auth *models.Auth) (*models.MessageResponse, *models.Exception) { func (us *UserRepository) Deactivate(ctx context.Context, auth *model.Auth) (*model.MessageResponse, *model.Exception) {
db := us.db.WithContext(ctx) db := us.db.WithContext(ctx)
mm := new(models.MessageResponse) mm := new(model.MessageResponse)
me := new(models.Exception) me := new(model.Exception)
um := new(models.User) um := new(model.User)
tx, _ := db.Begin() tx, _ := db.Begin()
defer tx.Rollback() defer tx.Rollback()
@@ -182,13 +182,13 @@ Generates new jwt token.
It encodes the user id. Based on rememberMe it is valid through 48hours or 2hours. It encodes the user id. Based on rememberMe it is valid through 48hours or 2hours.
Args: Args:
*models.User: User object to encode *model.User: User object to encode
bool: Should function generate longer lasting token (48hrs) bool: Should function generate longer lasting token (48hrs)
Returns: Returns:
string: Generated token string: Generated token
error: Error that occured in the process 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

323
pkg/repository/wallet.go Normal file
View File

@@ -0,0 +1,323 @@
package repository
import (
"context"
"fmt"
"time"
"wallet-api/pkg/model"
"wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10"
)
type WalletRepository struct {
db *pg.DB
subscriptionRepository *SubscriptionRepository
}
func NewWalletRepository(db *pg.DB, ss *SubscriptionRepository) *WalletRepository {
return &WalletRepository{
db: db,
subscriptionRepository: ss,
}
}
/*
New
Inserts row to wallets table.
Args:
context.Context: Application context
*model.NewWalletBody: Object to be inserted
Returns:
*model.Wallet: Wallet object from database.
*model.Exception: Exception payload.
*/
func (as *WalletRepository) New(ctx context.Context, am *model.NewWalletBody) (*model.Wallet, *model.Exception) {
db := as.db.WithContext(ctx)
exceptionReturn := new(model.Exception)
walletModel := new(model.Wallet)
walletModel.Init()
walletModel.UserID = am.UserID
walletModel.Name = am.Name
_, err := db.Model(walletModel).Insert()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400126"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"wallets\" table: %s", err)
return nil, exceptionReturn
}
return walletModel, nil
}
/*
Edit
Updates row in wallets table by id.
Args:
context.Context: Application context
*model.WalletEdit: Object to be edited
string: id to search
Returns:
*model.Wallet: Wallet object from database.
*model.Exception: Exception payload.
*/
func (as *WalletRepository) Edit(ctx context.Context, body *model.WalletEdit, id string) (*model.Wallet, *model.Exception) {
db := as.db.WithContext(ctx)
exceptionReturn := new(model.Exception)
tm := new(model.Wallet)
tm.Id = id
tm.Name = body.Name
tx, _ := db.Begin()
defer tx.Rollback()
_, err := tx.Model(tm).WherePK().UpdateNotZero()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400127"
exceptionReturn.Message = fmt.Sprintf("Error updating row in \"wallets\" table: %s", err)
return nil, exceptionReturn
}
tx.Commit()
return tm, nil
}
/*
Get
Gets row in wallets table by id.
Args:
context.Context: Application context
string: id to search
*model.Params: url query parameters
Returns:
*model.Wallet: Wallet object from database
*model.Exception: Exception payload.
*/
func (as *WalletRepository) Get(ctx context.Context, id string, params *model.Params) (*model.Wallet, *model.Exception) {
db := as.db.WithContext(ctx)
exceptionReturn := new(model.Exception)
wm := new(model.Wallet)
wm.Id = id
tx, _ := db.Begin()
defer tx.Rollback()
qry := tx.Model(wm)
err := common.GenerateEmbed(qry, params.Embed).WherePK().Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400128"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"wallets\" table: %s", err)
return nil, exceptionReturn
}
tx.Commit()
return wm, nil
}
/*
GetAll
Gets filtered rows from wallets table.
Args:
context.Context: Application context
*model.Auth: Authentication object
*model.FilteredResponse: filter options
Returns:
*model.Exception: Exception payload.
*/
func (as *WalletRepository) GetAll(ctx context.Context, am *model.Auth, filtered *model.FilteredResponse) *model.Exception {
exceptionReturn := new(model.Exception)
db := as.db.WithContext(ctx)
wm := new([]model.Wallet)
query := db.Model(wm).Where("? = ?", pg.Ident("user_id"), am.Id)
err := FilteredResponse(query, wm, filtered)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400134"
exceptionReturn.Message = fmt.Sprintf("Error selecting rows in \"wallets\" table: %s", err)
return exceptionReturn
}
return nil
}
/*
GetHeader
Gets row from wallets table.
Calculates previous month, current and next month totals.
Args:
context.Context: Application context
*model.Auth: Authentication object
string: wallet id to search
Returns:
*model.WalletHeader: generated wallet header object
*model.Exception: Exception payload.
*/
func (as *WalletRepository) GetHeader(ctx context.Context, am *model.Auth, walletId string) (*model.WalletHeader, *model.Exception) {
db := as.db.WithContext(ctx)
wm := new(model.WalletHeader)
wallets := new([]model.WalletTransactions)
transactions := new([]model.Transaction)
subscriptions := new([]model.Subscription)
transactionStatus := new(model.TransactionStatus)
exceptionReturn := new(model.Exception)
tx, _ := db.Begin()
defer tx.Rollback()
err := tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "completed").Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400130"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatuses\" table: %s", err)
return nil, exceptionReturn
}
query2 := tx.Model(subscriptions).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id).Relation("TransactionType").Relation("SubscriptionType")
if walletId != "" {
query2.Where("? = ?", pg.Ident("wallet_id"), walletId)
}
query2.Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400131"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"subscriptions\" table: %s", err)
return nil, exceptionReturn
}
now := time.Now()
currentYear, currentMonth, _ := now.Date()
currentLocation := now.Location()
firstOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, currentLocation)
firstOfNextMonth := time.Date(currentYear, currentMonth+1, 1, 0, 0, 0, 0, currentLocation)
firstOfMonthAfterNext := time.Date(currentYear, currentMonth+2, 1, 0, 0, 0, 0, currentLocation)
query := tx.Model(transactions).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id).Relation("TransactionType")
if walletId != "" {
query.Where("? = ?", pg.Ident("wallet_id"), walletId)
}
query = query.Where("? = ?", pg.Ident("transaction_status_id"), transactionStatus.Id)
query.Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400132"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactions\" table: %s", err)
return nil, exceptionReturn
}
tx.Commit()
for _, sub := range *subscriptions {
stopDate := firstOfMonthAfterNext
if sub.HasEnd && sub.EndDate.Before(firstOfMonthAfterNext) {
stopDate = sub.EndDate
}
startDate := sub.StartDate
for startDate.Before(stopDate) {
trans := sub.ToTrans()
trans.TransactionDate = startDate
if startDate.After(firstOfNextMonth) || startDate.Equal(firstOfNextMonth) {
*transactions = append(*transactions, *trans)
}
if sub.SubscriptionType.Type == "monthly" {
startDate = startDate.AddDate(0, sub.CustomRange, 0)
} else if sub.SubscriptionType.Type == "weekly" {
startDate = startDate.AddDate(0, 0, 7*sub.CustomRange)
} else if sub.SubscriptionType.Type == "daily" {
startDate = startDate.AddDate(0, 0, sub.CustomRange)
} else {
startDate = startDate.AddDate(sub.CustomRange, 0, 0)
}
}
}
for _, trans := range *transactions {
addWhere(wallets, trans.WalletID, trans)
}
for i, wallet := range *wallets {
for _, trans := range wallet.Transactions {
// tzFirstOfMonthAfterNext := firstOfMonthAfterNext.In(trans.TransactionDate.Location())
// tzFirstOfNextMonth := firstOfNextMonth.In(trans.TransactionDate.Location())
// tzFirstOfMonth := firstOfMonth.In(trans.TransactionDate.Location())
if trans.TransactionDate.Before(firstOfNextMonth) && trans.TransactionDate.After(firstOfMonth) || trans.TransactionDate.Equal(firstOfMonth) {
if trans.TransactionType.Type == "expense" {
(*wallets)[i].CurrentBalance -= trans.Amount
} else {
(*wallets)[i].CurrentBalance += trans.Amount
}
} else if trans.TransactionDate.Before(firstOfMonthAfterNext) && trans.TransactionDate.After(firstOfNextMonth) {
if trans.TransactionType.Type == "expense" {
(*wallets)[i].NextMonth -= trans.Amount
} else {
(*wallets)[i].NextMonth += trans.Amount
}
} else if trans.TransactionDate.Before(firstOfMonth) {
if trans.TransactionType.Type == "expense" {
(*wallets)[i].LastMonth -= trans.Amount
} else {
(*wallets)[i].LastMonth += trans.Amount
}
}
}
}
for _, wallet := range *wallets {
wm.LastMonth += wallet.LastMonth
wm.CurrentBalance += wallet.CurrentBalance + wallet.LastMonth
wm.NextMonth += wallet.NextMonth + wallet.CurrentBalance + wallet.LastMonth
}
wm.Currency = "USD"
wm.WalletId = walletId
return wm, nil
}
/*
addWhere
Appends Transaction to the belonging walletId.
If missing, it creates the item list.
Args:
*[]model.WalletTransactions: list to append to
string: wallet id to check
model.Transaction: Transaction to append
Returns:
*model.Exception: Exception payload.
*/
func addWhere(s *[]model.WalletTransactions, walletId string, e model.Transaction) {
var exists bool
for a := range *s {
if (*s)[a].WalletId == walletId {
(*s)[a].Transactions = append((*s)[a].Transactions, e)
exists = true
}
}
if !exists {
var walletTransaction model.WalletTransactions
walletTransaction.WalletId = walletId
walletTransaction.Transactions = append(walletTransaction.Transactions, e)
*s = append(*s, walletTransaction)
}
}

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,
}
}
/*
GetFirst
Gets first row from API table.
Args:
context.Context: Application context
Returns:
model.ApiModel: Api object from database.
*/
func (as ApiService) GetFirst(ctx context.Context) model.ApiModel {
return as.repository.GetFirst(ctx)
}
/*
PostMigrate
Starts database migration.
Args:
context.Context: Application context
string: Migration version
Returns:
*model.MessageResponse: Message response object.
*model.Exception: Exception response object.
*/
func (as ApiService) PostMigrate(ctx context.Context, version string) (*model.MessageResponse, *model.Exception) {
return as.repository.PostMigrate(ctx, version)
}

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

@@ -0,0 +1,27 @@
package service
import (
"go.uber.org/dig"
"wallet-api/pkg/repository"
)
/*
InitializeServices
Initializes Dependency Injection modules for services
Args:
*dig.Container: Dig Container
*/
func InitializeServices(c *dig.Container) {
repository.InitializeRepositories(c)
c.Provide(NewApiService)
c.Provide(NewSubscriptionService)
c.Provide(NewSubscriptionTypeService)
c.Provide(NewTransactionService)
c.Provide(NewTransactionStatusService)
c.Provide(NewTransactionTypeService)
c.Provide(NewUserService)
c.Provide(NewWalletService)
}

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

@@ -0,0 +1,192 @@
package service
import (
"context"
"fmt"
"math"
"time"
"wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/repository"
)
type SubscriptionService struct {
repository *repository.SubscriptionRepository
}
func NewSubscriptionService(repository *repository.SubscriptionRepository) *SubscriptionService {
return &SubscriptionService{
repository,
}
}
/*
New
Inserts new row to subscription table.
Args:
context.Context: Application context
*model.NewSubscriptionBody: Request body
Returns:
*model.Subscription: Created Subscription row object from database.
*model.Exception: Exception payload.
*/
func (as *SubscriptionService) New(ctx context.Context, body *model.NewSubscriptionBody) (*model.Subscription, *model.Exception) {
tm := new(model.Subscription)
exceptionReturn := new(model.Exception)
amount, _ := body.Amount.Float64()
customRange, _ := body.CustomRange.Int64()
tm.Init()
tm.WalletID = body.WalletID
tm.TransactionTypeID = body.TransactionTypeID
tm.SubscriptionTypeID = body.SubscriptionTypeID
tm.CustomRange = int(customRange)
tm.Description = body.Description
tm.StartDate = body.StartDate
tm.HasEnd = body.HasEnd
tm.EndDate = body.EndDate
tm.Amount = float32(math.Round(amount*100) / 100)
if body.StartDate.IsZero() {
tm.StartDate = time.Now()
}
response, err := as.repository.New(ctx, tm)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400109"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscription\" table: %s", err)
return nil, exceptionReturn
}
return response, nil
}
/*
Get
Gets row from subscription table by id.
Args:
context.Context: Application context
*model.Auth: Authentication model
string: subscription id to search
params: *model.Params
Returns:
*model.Subscription: Subscription row object from database.
*model.Exception: Exception payload.
*/
func (as *SubscriptionService) Get(ctx context.Context, am *model.Auth, flt filter.SubscriptionFilter) (*model.Subscription, *model.Exception) {
exceptionReturn := new(model.Exception)
wm := new(model.Subscription)
wm.Id = flt.Id
response, err := as.repository.Get(ctx, wm, flt)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400129"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscription\" table: %s", err)
return nil, exceptionReturn
}
return response, nil
}
/*
GetAll
Gets filtered rows from subscription table.
Args:
context.Context: Application context
*model.Auth: Authentication object
string: Wallet id to search
*model.FilteredResponse: filter options
Returns:
*model.Exception: Exception payload.
*/
func (as *SubscriptionService) GetAll(ctx context.Context, flt *filter.SubscriptionFilter, filtered *model.FilteredResponse) *model.Exception {
wm := new([]model.Subscription)
exceptionReturn := new(model.Exception)
err := as.repository.GetAll(ctx, wm, filtered, flt)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400110"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"subscription\" table: %s", err)
return exceptionReturn
}
return nil
}
/*
Edit
Updates row from subscription table by id.
Args:
context.Context: Application context
*model.SubscriptionEdit: Values to edit
string: id to search
Returns:
*model.Subscription: Edited Subscription row object from database.
*model.Exception: Exception payload.
*/
func (as *SubscriptionService) Edit(ctx context.Context, body *model.SubscriptionEdit, id string) (*model.Subscription, *model.Exception) {
amount, _ := body.Amount.Float64()
exceptionReturn := new(model.Exception)
tm := new(model.Subscription)
tm.Id = id
tm.EndDate = body.EndDate
tm.HasEnd = body.HasEnd
tm.Description = body.Description
tm.WalletID = body.WalletID
tm.Amount = float32(math.Round(amount*100) / 100)
response, err := as.repository.Edit(ctx, tm)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400111"
exceptionReturn.Message = fmt.Sprintf("Error updating row in \"subscription\" table: %s", err)
return nil, exceptionReturn
}
return response, nil
}
/*
End
Updates row in subscription table by id.
Ends subscription with current date.
Args:
context.Context: Application context
string: id to search
Returns:
*model.Subscription: Created Subscription row object from database.
*model.Exception: Exception payload.
*/
func (as *SubscriptionService) End(ctx context.Context, id string) (*model.Subscription, *model.Exception) {
exceptionReturn := new(model.Exception)
tm := new(model.Subscription)
tm.Id = id
tm.EndDate = time.Now()
tm.HasEnd = true
response, err := as.repository.End(ctx, tm)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400112"
exceptionReturn.Message = fmt.Sprintf("Error updating row in \"subscription\" table: %s", err)
return nil, exceptionReturn
}
return response, nil
}

View File

@@ -0,0 +1,80 @@
package service
import (
"context"
"fmt"
"wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/repository"
)
type SubscriptionTypeService struct {
repository *repository.SubscriptionTypeRepository
}
func NewSubscriptionTypeService(repository *repository.SubscriptionTypeRepository) *SubscriptionTypeService {
return &SubscriptionTypeService{
repository,
}
}
/*
New
Inserts new row to subscription type table.
Args:
context.Context: Application context
*model.NewSubscriptionTypeBody: Values to create new row
Returns:
*model.SubscriptionType: Created row from database.
*model.Exception: Exception payload.
*/
func (as *SubscriptionTypeService) New(ctx context.Context, body *model.NewSubscriptionTypeBody) (*model.SubscriptionType, *model.Exception) {
tm := new(model.SubscriptionType)
exceptionReturn := new(model.Exception)
tm.Init()
tm.Name = body.Name
tm.Type = body.Type
response, err := as.repository.New(ctx, tm)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400114"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscriptionTypes\" table: %s", err)
return nil, exceptionReturn
}
return response, nil
}
/*
GetAll
Gets all rows from subscription type table.
Args:
context.Context: Application context
string: Relations to embed
Returns:
*[]model.SubscriptionType: List of subscription type objects.
*model.Exception: Exception payload.
*/
func (as *SubscriptionTypeService) GetAll(ctx context.Context, embed string) (*[]model.SubscriptionType, *model.Exception) {
wm := new([]model.SubscriptionType)
exceptionReturn := new(model.Exception)
flt := filter.NewSubscriptionTypeFilter(model.Params{
Embed: embed,
})
response, err := as.repository.GetAll(ctx, flt, wm)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400135"
exceptionReturn.Message = fmt.Sprintf("Error selecting rows in \"subscriptionTypes\" table: %s", err)
return nil, exceptionReturn
}
return response, nil
}

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

@@ -0,0 +1,234 @@
package service
import (
"context"
"fmt"
"math"
"time"
"wallet-api/pkg/filter"
"wallet-api/pkg/model"
"wallet-api/pkg/repository"
)
type TransactionService struct {
repository *repository.TransactionRepository
subscriptionRepository *repository.SubscriptionRepository
transactionStatusService *TransactionStatusService
}
func NewTransactionService(repository *repository.TransactionRepository, sr *repository.SubscriptionRepository, tss *TransactionStatusService) *TransactionService {
return &TransactionService{
repository: repository,
subscriptionRepository: sr,
transactionStatusService: tss,
}
}
/*
New row into transaction table
Inserts
Args:
context.Context: Application context
*model.NewTransactionBody: Transaction body object
Returns:
*model.Transaction: Transaction object
*model.Exception: Exception payload.
*/
func (as *TransactionService) New(ctx context.Context, body *model.NewTransactionBody) (*model.Transaction, *model.Exception) {
exceptionReturn := new(model.Exception)
tm := new(model.Transaction)
tsFlt := filter.NewTransactionStatusFilter(model.Params{})
tsFlt.Status = "completed"
transactionStatus, exceptionReturn := as.transactionStatusService.Get(ctx, tsFlt)
if exceptionReturn != nil {
return nil, exceptionReturn
}
amount, _ := body.Amount.Float64()
tm.Init()
tm.WalletID = body.WalletID
tm.TransactionTypeID = body.TransactionTypeID
tm.Description = body.Description
tm.TransactionDate = body.TransactionDate
tm.Amount = float32(math.Round(amount*100) / 100)
tm.TransactionStatusID = transactionStatus.Id
if body.TransactionDate.IsZero() {
tm.TransactionDate = time.Now()
}
response, err := as.repository.New(ctx, tm)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400116"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"transaction\" table: %s", err)
return nil, exceptionReturn
}
return response, nil
}
/*
GetAll
Gets all rows from subscription type table.
Args:
context.Context: Application context
string: Relations to embed
Returns:
*model.Exception: Exception payload.
*/
// Gets filtered rows from transaction table.
func (as *TransactionService) GetAll(ctx context.Context, filtered *model.FilteredResponse, flt *filter.TransactionFilter) *model.Exception {
exceptionReturn := new(model.Exception)
err := as.repository.GetAll(ctx, filtered, flt)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400118"
exceptionReturn.Message = fmt.Sprintf("Error selecting row(s) in \"transaction\" table: %s", err)
return exceptionReturn
}
return nil
}
/*
Check
Checks subscriptions and create transacitons.
Args:
context.Context: Application context
string: Relations to embed
Returns:
*model.Exception: Exception payload.
*/
// Gets filtered rows from transaction table.
func (as *TransactionService) Check(ctx context.Context, flt *filter.TransactionFilter) *model.Exception {
exceptionReturn := new(model.Exception)
filtered := new(model.FilteredResponse)
err := as.repository.Check(ctx, filtered, flt)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400120"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transaction\" table: %s", err)
return exceptionReturn
}
return nil
}
/*
Edit
Updates row in transaction table by id.
Args:
context.Context: Application context
*model.TransactionEdit: Object to edit
string: id to search
Returns:
*model.Transaction: Transaction object from database.
*model.Exception: Exception payload.
*/
func (as *TransactionService) Edit(ctx context.Context, body *model.TransactionEdit, id string) (*model.Transaction, *model.Exception) {
amount, _ := body.Amount.Float64()
exceptionReturn := new(model.Exception)
tm := new(model.Transaction)
tm.Id = id
tm.Description = body.Description
tm.WalletID = body.WalletID
tm.TransactionTypeID = body.TransactionTypeID
tm.TransactionDate = body.TransactionDate
tm.TransactionStatusID = body.TransactionStatusID
tm.Amount = float32(math.Round(amount*100) / 100)
response, err := as.repository.Edit(ctx, tm)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400107"
exceptionReturn.Message = fmt.Sprintf("Error updating row in \"transaction\" table: %s", err)
return nil, exceptionReturn
}
return response, nil
}
/*
Bulk Edit
Updates row in transaction table by id.
Args:
context.Context: Application context
?[]model.Transaction Bulk Edit: Object to edit
string: id to search
Returns:
*model.Transaction: Transaction object from database.
*model.Exception: Exception payload.
*/
func (as *TransactionService) BulkEdit(ctx context.Context, body *[]model.TransactionEdit) (*[]model.Transaction, *model.Exception) {
transactions := new([]model.Transaction)
exceptionReturn := new(model.Exception)
for _, transaction := range *body {
amount, _ := transaction.Amount.Float64()
tm := new(model.Transaction)
tm.Id = transaction.Id
tm.Description = transaction.Description
tm.WalletID = transaction.WalletID
tm.TransactionTypeID = transaction.TransactionTypeID
tm.TransactionDate = transaction.TransactionDate
tm.Amount = float32(math.Round(amount*100) / 100)
*transactions = append(*transactions, *tm)
}
response, err := as.repository.BulkEdit(ctx, transactions)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400121"
exceptionReturn.Message = fmt.Sprintf("Error updating rows in \"transactions\" table: %s", err)
return nil, exceptionReturn
}
return response, nil
}
/*
Get
Gets row from transaction table by id.
Args:
context.Context: Application context
*model.Auth: Authentication object
string: id to search
*model.Params: url query parameters
Returns:
*model.Transaction: Transaction object from database.
*model.Exception: Exception payload.
*/
func (as *TransactionService) Get(ctx context.Context, flt *filter.TransactionFilter) (*model.Transaction, *model.Exception) {
exceptionReturn := new(model.Exception)
response, err := as.repository.Get(ctx, flt)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400122"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactions\" table: %s", err)
return nil, exceptionReturn
}
return response, nil
}

View File

@@ -1,9 +1,10 @@
package services package service
import ( import (
"context" "context"
"fmt" "fmt"
"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"
@@ -26,16 +27,16 @@ Inserts new row to transaction status table.
Args: Args:
context.Context: Application context context.Context: Application context
*models.NewTransactionStatusBody: object to create *model.NewTransactionStatusBody: object to create
Returns: Returns:
*models.TransactionType: Transaction Type object from database. *model.TransactionType: Transaction Type object from database.
*models.Exception: Exception payload. *model.Exception: Exception payload.
*/ */
func (as *TransactionStatusService) New(ctx context.Context, body *models.NewTransactionStatusBody) (*models.TransactionStatus, *models.Exception) { func (as *TransactionStatusService) New(ctx context.Context, body *model.NewTransactionStatusBody) (*model.TransactionStatus, *model.Exception) {
db := as.db.WithContext(ctx) db := as.db.WithContext(ctx)
tm := new(models.TransactionStatus) tm := new(model.TransactionStatus)
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
tm.Init() tm.Init()
tm.Name = body.Name tm.Name = body.Name
@@ -61,14 +62,14 @@ Gets all rows from transaction status table.
context.Context: Application context context.Context: Application context
string: Relations to embed string: Relations to embed
Returns: Returns:
*[]models.TransactionStatus: List of Transaction status objects from database. *[]model.TransactionStatus: List of Transaction status objects from database.
*models.Exception: Exception payload. *model.Exception: Exception payload.
*/ */
func (as *TransactionStatusService) GetAll(ctx context.Context, embed string) (*[]models.TransactionStatus, *models.Exception) { func (as *TransactionStatusService) GetAll(ctx context.Context, embed string) (*[]model.TransactionStatus, *model.Exception) {
db := as.db.WithContext(ctx) db := as.db.WithContext(ctx)
wm := new([]models.TransactionStatus) wm := new([]model.TransactionStatus)
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
query := db.Model(wm) query := db.Model(wm)
err := common.GenerateEmbed(query, embed).Select() err := common.GenerateEmbed(query, embed).Select()
@@ -81,3 +82,23 @@ func (as *TransactionStatusService) GetAll(ctx context.Context, embed string) (*
return wm, nil return wm, nil
} }
func (as *TransactionStatusService) Get(ctx context.Context, flt *filter.TransactionStatusFilter) (*model.TransactionStatus, *model.Exception) {
transactionStatus := new(model.TransactionStatus)
exceptionReturn := new(model.Exception)
if flt.Id != "" {
transactionStatus.Id = flt.Id
}
if flt.Status != "" {
transactionStatus.Status = flt.Status
}
response, err := as.repository.Get(ctx, wm, flt)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400129"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscription\" table: %s", err)
return nil, exceptionReturn
}
return response, nil
}

View File

@@ -1,9 +1,9 @@
package services package service
import ( import (
"context" "context"
"fmt" "fmt"
"wallet-api/pkg/models" "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"
@@ -26,16 +26,16 @@ Inserts new row to transaction type table.
Args: Args:
context.Context: Application context context.Context: Application context
*models.NewTransactionTypeBody: object to create *model.NewTransactionTypeBody: object to create
Returns: Returns:
*models.TransactionType: Transaction Type object from database. *model.TransactionType: Transaction Type object from database.
*models.Exception: Exception payload. *model.Exception: Exception payload.
*/ */
func (as *TransactionTypeService) New(ctx context.Context, body *models.NewTransactionTypeBody) (*models.TransactionType, *models.Exception) { func (as *TransactionTypeService) New(ctx context.Context, body *model.NewTransactionTypeBody) (*model.TransactionType, *model.Exception) {
db := as.db.WithContext(ctx) db := as.db.WithContext(ctx)
tm := new(models.TransactionType) tm := new(model.TransactionType)
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
tm.Init() tm.Init()
tm.Name = body.Name tm.Name = body.Name
@@ -61,14 +61,14 @@ Gets all rows from transaction type table.
context.Context: Application context context.Context: Application context
string: Relations to embed string: Relations to embed
Returns: Returns:
*[]models.TransactionType: List of Transaction type objects from database. *[]model.TransactionType: List of Transaction type objects from database.
*models.Exception: Exception payload. *model.Exception: Exception payload.
*/ */
func (as *TransactionTypeService) GetAll(ctx context.Context, embed string) (*[]models.TransactionType, *models.Exception) { func (as *TransactionTypeService) GetAll(ctx context.Context, embed string) (*[]model.TransactionType, *model.Exception) {
db := as.db.WithContext(ctx) db := as.db.WithContext(ctx)
wm := new([]models.TransactionType) wm := new([]model.TransactionType)
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
query := db.Model(wm) query := db.Model(wm)
err := common.GenerateEmbed(query, embed).Select() err := common.GenerateEmbed(query, embed).Select()

210
pkg/service/user.go Normal file
View File

@@ -0,0 +1,210 @@
package service
import (
"context"
"os"
"time"
"wallet-api/pkg/model"
"wallet-api/pkg/utl/common"
"wallet-api/pkg/utl/configs"
jwt "github.com/dgrijalva/jwt-go"
"golang.org/x/crypto/bcrypt"
"github.com/go-pg/pg/v10"
)
type UserService struct {
db *pg.DB
}
func NewUserService(db *pg.DB) *UserService {
return &UserService{
db: db,
}
}
/*
Create
Inserts new row to users table.
Args:
context.Context: Application context
*model.User: User object to create
Returns:
*model.User: User object from database
*model.Exception
*/
func (us *UserService) Create(ctx context.Context, registerBody *model.User) (*model.User, *model.Exception) {
db := us.db.WithContext(ctx)
check := new(model.User)
exceptionReturn := new(model.Exception)
tx, _ := db.Begin()
defer tx.Rollback()
tx.Model(check).Where("? = ?", pg.Ident("username"), registerBody.Username).WhereOr("? = ?", pg.Ident("email"), registerBody.Email).Select()
if check.Username != "" || check.Email != "" {
exceptionReturn.Message = "User already exists"
exceptionReturn.ErrorCode = "400101"
exceptionReturn.StatusCode = 400
return check, exceptionReturn
}
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(registerBody.Password), bcrypt.DefaultCost)
common.CheckError(err)
registerBody.Password = string(hashedPassword)
_, err = tx.Model(registerBody).Insert()
if err != nil {
exceptionReturn.Message = "Error creating user"
exceptionReturn.ErrorCode = "400102"
exceptionReturn.StatusCode = 400
}
tx.Commit()
return registerBody, exceptionReturn
}
/*
Login
Gets row from users table by email and valid password.
Args:
context.Context: Application context
*model.Login: object to search
Returns:
*model.Token: new session token
*model.Exception
*/
func (us *UserService) Login(ctx context.Context, loginBody *model.Login) (*model.Token, *model.Exception) {
db := us.db.WithContext(ctx)
check := new(model.User)
exceptionReturn := new(model.Exception)
tokenPayload := new(model.Token)
tx, _ := db.Begin()
defer tx.Rollback()
tx.Model(check).Where("? = ?", pg.Ident("email"), loginBody.Email).Select()
if check.Email == "" {
exceptionReturn.Message = "Email not found"
exceptionReturn.ErrorCode = "400103"
exceptionReturn.StatusCode = 400
return tokenPayload, exceptionReturn
}
if !check.IsActive {
exceptionReturn.Message = "Can't log in. User is deactivated."
exceptionReturn.ErrorCode = "400106"
exceptionReturn.StatusCode = 400
return tokenPayload, exceptionReturn
}
if bcrypt.CompareHashAndPassword([]byte(check.Password), []byte(loginBody.Password)) != nil {
exceptionReturn.Message = "Incorrect password"
exceptionReturn.ErrorCode = "400104"
exceptionReturn.StatusCode = 400
return tokenPayload, exceptionReturn
}
token, err := CreateToken(check, loginBody.RememberMe)
common.CheckError(err)
tokenPayload.Token = token
tx.Commit()
return tokenPayload, exceptionReturn
}
/*
Deactivate
Updates row in users table.
IsActive column is set to false
Args:
context.Context: Application context
*model.Auth: Authentication object
Returns:
*model.MessageResponse
*model.Exception
*/
func (us *UserService) Deactivate(ctx context.Context, auth *model.Auth) (*model.MessageResponse, *model.Exception) {
db := us.db.WithContext(ctx)
mm := new(model.MessageResponse)
me := new(model.Exception)
um := new(model.User)
tx, _ := db.Begin()
defer tx.Rollback()
err := tx.Model(um).Where("? = ?", pg.Ident("id"), auth.Id).Select()
if err != nil {
me.ErrorCode = "404101"
me.Message = "User not found"
me.StatusCode = 404
return mm, me
}
um.IsActive = false
_, err = tx.Model(um).Where("? = ?", pg.Ident("id"), auth.Id).Update()
if err != nil {
me.ErrorCode = "400105"
me.Message = "Could not deactivate user"
me.StatusCode = 400
return mm, me
}
mm.Message = "User successfully deactivated."
tx.Commit()
return mm, me
}
/*
CreateToken
Generates new jwt token.
It encodes the user id. Based on rememberMe it is valid through 48hours or 2hours.
Args:
*model.User: User object to encode
bool: Should function generate longer lasting token (48hrs)
Returns:
string: Generated token
error: Error that occured in the process
*/
func CreateToken(user *model.User, rememberMe bool) (string, error) {
atClaims := jwt.MapClaims{}
atClaims["authorized"] = true
atClaims["id"] = user.Id
if rememberMe {
atClaims["exp"] = time.Now().Add(time.Hour * 48).Unix()
} else {
atClaims["exp"] = time.Now().Add(time.Hour * 2).Unix()
}
secret := os.Getenv("ACCESS_SECRET")
if secret == "" {
secret = configs.Secret
}
at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims)
token, err := at.SignedString([]byte(secret))
return token, err
}

View File

@@ -1,10 +1,10 @@
package services package service
import ( import (
"context" "context"
"fmt" "fmt"
"time" "time"
"wallet-api/pkg/models" "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"
@@ -29,16 +29,16 @@ Inserts row to wallets table.
Args: Args:
context.Context: Application context context.Context: Application context
*models.NewWalletBody: Object to be inserted *model.NewWalletBody: Object to be inserted
Returns: Returns:
*models.Wallet: Wallet object from database. *model.Wallet: Wallet object from database.
*models.Exception: Exception payload. *model.Exception: Exception payload.
*/ */
func (as *WalletService) New(ctx context.Context, am *models.NewWalletBody) (*models.Wallet, *models.Exception) { func (as *WalletService) New(ctx context.Context, am *model.NewWalletBody) (*model.Wallet, *model.Exception) {
db := as.db.WithContext(ctx) db := as.db.WithContext(ctx)
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
walletModel := new(models.Wallet) walletModel := new(model.Wallet)
walletModel.Init() walletModel.Init()
walletModel.UserID = am.UserID walletModel.UserID = am.UserID
walletModel.Name = am.Name walletModel.Name = am.Name
@@ -59,17 +59,17 @@ Updates row in wallets table by id.
Args: Args:
context.Context: Application context context.Context: Application context
*models.WalletEdit: Object to be edited *model.WalletEdit: Object to be edited
string: id to search string: id to search
Returns: Returns:
*models.Wallet: Wallet object from database. *model.Wallet: Wallet object from database.
*models.Exception: Exception payload. *model.Exception: Exception payload.
*/ */
func (as *WalletService) Edit(ctx context.Context, body *models.WalletEdit, id string) (*models.Wallet, *models.Exception) { func (as *WalletService) Edit(ctx context.Context, body *model.WalletEdit, id string) (*model.Wallet, *model.Exception) {
db := as.db.WithContext(ctx) db := as.db.WithContext(ctx)
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
tm := new(models.Wallet) tm := new(model.Wallet)
tm.Id = id tm.Id = id
tm.Name = body.Name tm.Name = body.Name
@@ -97,16 +97,16 @@ Gets row in wallets table by id.
Args: Args:
context.Context: Application context context.Context: Application context
string: id to search string: id to search
*models.Params: url query parameters *model.Params: url query parameters
Returns: Returns:
*models.Wallet: Wallet object from database *model.Wallet: Wallet object from database
*models.Exception: Exception payload. *model.Exception: Exception payload.
*/ */
func (as *WalletService) Get(ctx context.Context, id string, params *models.Params) (*models.Wallet, *models.Exception) { func (as *WalletService) Get(ctx context.Context, id string, params *model.Params) (*model.Wallet, *model.Exception) {
db := as.db.WithContext(ctx) db := as.db.WithContext(ctx)
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
wm := new(models.Wallet) wm := new(model.Wallet)
wm.Id = id wm.Id = id
tx, _ := db.Begin() tx, _ := db.Begin()
@@ -133,15 +133,15 @@ Gets filtered rows from wallets table.
Args: Args:
context.Context: Application context context.Context: Application context
*models.Auth: Authentication object *model.Auth: Authentication object
*models.FilteredResponse: filter options *model.FilteredResponse: filter options
Returns: Returns:
*models.Exception: Exception payload. *model.Exception: Exception payload.
*/ */
func (as *WalletService) GetAll(ctx context.Context, am *models.Auth, filtered *models.FilteredResponse) *models.Exception { func (as *WalletService) GetAll(ctx context.Context, am *model.Auth, filtered *model.FilteredResponse) *model.Exception {
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
db := as.db.WithContext(ctx) db := as.db.WithContext(ctx)
wm := new([]models.Wallet) wm := new([]model.Wallet)
query := db.Model(wm).Where("? = ?", pg.Ident("user_id"), am.Id) query := db.Model(wm).Where("? = ?", pg.Ident("user_id"), am.Id)
err := FilteredResponse(query, wm, filtered) err := FilteredResponse(query, wm, filtered)
@@ -163,21 +163,21 @@ Calculates previous month, current and next month totals.
Args: Args:
context.Context: Application context context.Context: Application context
*models.Auth: Authentication object *model.Auth: Authentication object
string: wallet id to search string: wallet id to search
Returns: Returns:
*models.WalletHeader: generated wallet header object *model.WalletHeader: generated wallet header object
*models.Exception: Exception payload. *model.Exception: Exception payload.
*/ */
func (as *WalletService) GetHeader(ctx context.Context, am *models.Auth, walletId string) (*models.WalletHeader, *models.Exception) { func (as *WalletService) GetHeader(ctx context.Context, am *model.Auth, walletId string) (*model.WalletHeader, *model.Exception) {
db := as.db.WithContext(ctx) db := as.db.WithContext(ctx)
wm := new(models.WalletHeader) wm := new(model.WalletHeader)
wallets := new([]models.WalletTransactions) wallets := new([]model.WalletTransactions)
transactions := new([]models.Transaction) transactions := new([]model.Transaction)
subscriptions := new([]models.Subscription) subscriptions := new([]model.Subscription)
transactionStatus := new(models.TransactionStatus) transactionStatus := new(model.TransactionStatus)
exceptionReturn := new(models.Exception) exceptionReturn := new(model.Exception)
tx, _ := db.Begin() tx, _ := db.Begin()
defer tx.Rollback() defer tx.Rollback()
@@ -300,13 +300,13 @@ Appends Transaction to the belonging walletId.
If missing, it creates the item list. If missing, it creates the item list.
Args: Args:
*[]models.WalletTransactions: list to append to *[]model.WalletTransactions: list to append to
string: wallet id to check string: wallet id to check
models.Transaction: Transaction to append model.Transaction: Transaction to append
Returns: Returns:
*models.Exception: Exception payload. *model.Exception: Exception payload.
*/ */
func addWhere(s *[]models.WalletTransactions, walletId string, e models.Transaction) { func addWhere(s *[]model.WalletTransactions, walletId string, e model.Transaction) {
var exists bool var exists bool
for a := range *s { for a := range *s {
if (*s)[a].WalletId == walletId { if (*s)[a].WalletId == walletId {
@@ -315,7 +315,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)

View File

@@ -1,59 +0,0 @@
package services
import (
"context"
"wallet-api/pkg/migrate"
"wallet-api/pkg/models"
"github.com/go-pg/pg/v10"
)
type ApiService struct {
db *pg.DB
}
func NewApiService(db *pg.DB) *ApiService {
return &ApiService{
db: db,
}
}
/*
GetFirst
Gets first row from API table.
Args:
context.Context: Application context
Returns:
models.ApiModel: Api object from database.
*/
func (as ApiService) GetFirst(ctx context.Context) models.ApiModel {
db := as.db.WithContext(ctx)
apiModel := models.ApiModel{Api: "Works"}
db.Model(&apiModel).First()
return apiModel
}
/*
PostMigrate
Starts database migration.
Args:
context.Context: Application context
string: Migration version
Returns:
*models.MessageResponse: Message response object.
*models.Exception: Exception response object.
*/
func (as ApiService) PostMigrate(ctx context.Context, version string) (*models.MessageResponse, *models.Exception) {
db := as.db.WithContext(ctx)
mr := new(models.MessageResponse)
er := new(models.Exception)
migrate.Start(db, version)
return mr, er
}

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,83 +0,0 @@
package services
import (
"context"
"fmt"
"wallet-api/pkg/models"
"wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10"
)
type SubscriptionTypeService struct {
db *pg.DB
}
func NewSubscriptionTypeService(db *pg.DB) *SubscriptionTypeService {
return &SubscriptionTypeService{
db: db,
}
}
/*
New
Inserts new row to subscription type table.
Args:
context.Context: Application context
*models.NewSubscriptionTypeBody: Values to create new row
Returns:
*models.SubscriptionType: Created row from database.
*models.Exception: Exception payload.
*/
func (as *SubscriptionTypeService) New(ctx context.Context, body *models.NewSubscriptionTypeBody) (*models.SubscriptionType, *models.Exception) {
db := as.db.WithContext(ctx)
tm := new(models.SubscriptionType)
exceptionReturn := new(models.Exception)
tm.Init()
tm.Name = body.Name
tm.Type = body.Type
_, err := db.Model(tm).Insert()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400114"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscriptionTypes\" table: %s", err)
return nil, exceptionReturn
}
return tm, nil
}
/*
GetAll
Gets all rows from subscription type table.
Args:
context.Context: Application context
string: Relations to embed
Returns:
*[]models.SubscriptionType: List of subscription type objects.
*models.Exception: Exception payload.
*/
func (as *SubscriptionTypeService) GetAll(ctx context.Context, embed string) (*[]models.SubscriptionType, *models.Exception) {
db := as.db.WithContext(ctx)
wm := new([]models.SubscriptionType)
exceptionReturn := new(models.Exception)
query := db.Model(wm)
err := common.GenerateEmbed(query, embed).Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400135"
exceptionReturn.Message = fmt.Sprintf("Error selecting rows in \"subscriptionTypes\" table: %s", err)
return nil, exceptionReturn
}
return wm, nil
}

View File

@@ -1,306 +0,0 @@
package services
import (
"context"
"fmt"
"math"
"time"
"wallet-api/pkg/models"
"wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10"
)
type SubscriptionService struct {
db *pg.DB
}
func NewSubscriptionService(db *pg.DB) *SubscriptionService {
return &SubscriptionService{
db: db,
}
}
/*
New
Inserts new row to subscription table.
Args:
context.Context: Application context
*models.NewSubscriptionBody: Request body
Returns:
*models.Subscription: Created Subscription row object from database.
*models.Exception: Exception payload.
*/
func (as *SubscriptionService) New(ctx context.Context, body *models.NewSubscriptionBody) (*models.Subscription, *models.Exception) {
db := as.db.WithContext(ctx)
tm := new(models.Subscription)
exceptionReturn := new(models.Exception)
amount, _ := body.Amount.Float64()
customRange, _ := body.CustomRange.Int64()
tm.Init()
tm.WalletID = body.WalletID
tm.TransactionTypeID = body.TransactionTypeID
tm.SubscriptionTypeID = body.SubscriptionTypeID
tm.CustomRange = int(customRange)
tm.Description = body.Description
tm.StartDate = body.StartDate
tm.HasEnd = body.HasEnd
tm.EndDate = body.EndDate
tm.Amount = float32(math.Round(amount*100) / 100)
if body.StartDate.IsZero() {
tm.StartDate = time.Now()
}
tx, _ := db.Begin()
defer tx.Rollback()
_, err := tx.Model(tm).Insert()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400109"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscription\" table: %s", err)
return nil, exceptionReturn
}
tx.Commit()
return tm, nil
}
/*
Get
Gets row from subscription table by id.
Args:
context.Context: Application context
*models.Auth: Authentication model
string: subscription id to search
params: *models.Params
Returns:
*models.Subscription: Subscription row object from database.
*models.Exception: Exception payload.
*/
func (as *SubscriptionService) Get(ctx context.Context, am *models.Auth, id string, params *models.Params) (*models.Subscription, *models.Exception) {
db := as.db.WithContext(ctx)
exceptionReturn := new(models.Exception)
wm := new(models.Subscription)
wm.Id = id
tx, _ := db.Begin()
defer tx.Rollback()
qry := tx.Model(wm)
err := common.GenerateEmbed(qry, params.Embed).WherePK().Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400129"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"subscription\" table: %s", err)
return nil, exceptionReturn
}
tx.Commit()
return wm, nil
}
/*
GetAll
Gets filtered rows from subscription table.
Args:
context.Context: Application context
*models.Auth: Authentication object
string: Wallet id to search
*models.FilteredResponse: filter options
Returns:
*models.Exception: Exception payload.
*/
func (as *SubscriptionService) GetAll(ctx context.Context, am *models.Auth, walletId string, filtered *models.FilteredResponse) *models.Exception {
db := as.db.WithContext(ctx)
wm := new([]models.Subscription)
exceptionReturn := new(models.Exception)
tx, _ := db.Begin()
defer tx.Rollback()
query := tx.Model(wm).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id)
if walletId != "" {
query = query.Where("? = ?", pg.Ident("wallet_id"), walletId)
}
err := FilteredResponse(query, wm, filtered)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400110"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"subscription\" table: %s", err)
return exceptionReturn
}
tx.Commit()
return nil
}
/*
Edit
Updates row from subscription table by id.
Args:
context.Context: Application context
*models.SubscriptionEdit: Values to edit
string: id to search
Returns:
*models.Subscription: Edited Subscription row object from database.
*models.Exception: Exception payload.
*/
func (as *SubscriptionService) Edit(ctx context.Context, body *models.SubscriptionEdit, id string) (*models.Subscription, *models.Exception) {
db := as.db.WithContext(ctx)
amount, _ := body.Amount.Float64()
exceptionReturn := new(models.Exception)
tm := new(models.Subscription)
tm.Id = id
tm.EndDate = body.EndDate
tm.HasEnd = body.HasEnd
tm.Description = body.Description
tm.WalletID = body.WalletID
tm.Amount = float32(math.Round(amount*100) / 100)
tx, _ := db.Begin()
defer tx.Rollback()
_, err := tx.Model(tm).WherePK().UpdateNotZero()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400111"
exceptionReturn.Message = fmt.Sprintf("Error updating row in \"subscription\" table: %s", err)
return nil, exceptionReturn
}
tx.Commit()
return tm, nil
}
/*
End
Updates row in subscription table by id.
Ends subscription with current date.
Args:
context.Context: Application context
string: id to search
Returns:
*models.Subscription: Created Subscription row object from database.
*models.Exception: Exception payload.
*/
func (as *SubscriptionService) End(ctx context.Context, id string) (*models.Subscription, *models.Exception) {
db := as.db.WithContext(ctx)
exceptionReturn := new(models.Exception)
tm := new(models.Subscription)
tm.Id = id
tm.EndDate = time.Now()
tm.HasEnd = true
tx, _ := db.Begin()
defer tx.Rollback()
_, err := tx.Model(tm).WherePK().UpdateNotZero()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400112"
exceptionReturn.Message = fmt.Sprintf("Error updating row in \"subscription\" table: %s", err)
return nil, exceptionReturn
}
tx.Commit()
return tm, nil
}
/*
SubToTrans
Generates and Inserts new Transaction rows from the subscription model.
Args:
*models.Subscription: Subscription model to generate new transactions from
*pg.Tx: Postgres query context
Returns:
*models.Exception: Exception payload.
*/
func (as *SubscriptionService) SubToTrans(subModel *models.Subscription, tx *pg.Tx) *models.Exception {
exceptionReturn := new(models.Exception)
now := time.Now()
currentYear, currentMonth, _ := now.Date()
currentLocation := now.Location()
transactionStatus := new(models.TransactionStatus)
firstOfNextMonth := time.Date(currentYear, currentMonth+1, 1, 0, 0, 0, 0, currentLocation)
tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "pending").Select()
//tzFirstOfNextMonth := firstOfNextMonth.In(subModel.StartDate.Location())
startDate := subModel.StartDate
stopDate := firstOfNextMonth
if subModel.HasEnd && subModel.EndDate.Before(firstOfNextMonth) {
stopDate = subModel.EndDate
}
transactions := new([]models.Transaction)
if subModel.SubscriptionType == nil {
st := new(models.SubscriptionType)
tx.Model(st).Where("? = ?", pg.Ident("id"), subModel.SubscriptionTypeID).Select()
subModel.SubscriptionType = st
}
for startDate.Before(stopDate) {
trans := subModel.ToTrans()
trans.TransactionDate = startDate
trans.TransactionStatusID = transactionStatus.Id
if startDate.After(subModel.LastTransactionDate) && (startDate.Before(now) || startDate.Equal(now)) {
*transactions = append(*transactions, *trans)
}
if subModel.SubscriptionType.Type == "monthly" {
startDate = startDate.AddDate(0, subModel.CustomRange, 0)
} else if subModel.SubscriptionType.Type == "weekly" {
startDate = startDate.AddDate(0, 0, 7*subModel.CustomRange)
} else if subModel.SubscriptionType.Type == "daily" {
startDate = startDate.AddDate(0, 0, subModel.CustomRange)
} else {
startDate = startDate.AddDate(subModel.CustomRange, 0, 0)
}
}
var err error
if len(*transactions) > 0 {
for _, trans := range *transactions {
_, err = tx.Model(&trans).Where("? = ?", pg.Ident("transaction_date"), trans.TransactionDate).Where("? = ?", pg.Ident("subscription_id"), trans.SubscriptionID).OnConflict("DO NOTHING").SelectOrInsert()
if err != nil {
_, err = tx.Model(subModel).Set("? = ?", pg.Ident("last_transaction_date"), trans.TransactionDate).WherePK().Update()
}
}
}
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400113"
exceptionReturn.Message = fmt.Sprintf("Error updating row in \"subscription\" table: %s", err)
return exceptionReturn
}
return nil
}

View File

@@ -1,329 +0,0 @@
package services
import (
"context"
"fmt"
"math"
"time"
"wallet-api/pkg/models"
"wallet-api/pkg/utl/common"
"github.com/go-pg/pg/v10"
)
type TransactionService struct {
db *pg.DB
subscriptionService *SubscriptionService
}
func NewTransactionService(db *pg.DB, ss *SubscriptionService) *TransactionService {
return &TransactionService{
db: db,
subscriptionService: ss,
}
}
/*
New row into transaction table
Inserts
Args:
context.Context: Application context
*models.NewTransactionBody: Transaction body object
Returns:
*models.Transaction: Transaction object
*models.Exception: Exception payload.
*/
func (as *TransactionService) New(ctx context.Context, body *models.NewTransactionBody) (*models.Transaction, *models.Exception) {
db := as.db.WithContext(ctx)
exceptionReturn := new(models.Exception)
tm := new(models.Transaction)
transactionStatus := new(models.TransactionStatus)
tx, _ := db.Begin()
defer tx.Rollback()
err := tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "completed").Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400115"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionsStatus\" table: %s", err)
return nil, exceptionReturn
}
amount, _ := body.Amount.Float64()
tm.Init()
tm.WalletID = body.WalletID
tm.TransactionTypeID = body.TransactionTypeID
tm.Description = body.Description
tm.TransactionDate = body.TransactionDate
tm.Amount = float32(math.Round(amount*100) / 100)
tm.TransactionStatusID = transactionStatus.Id
if body.TransactionDate.IsZero() {
tm.TransactionDate = time.Now()
}
_, err = tx.Model(tm).Insert()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400116"
exceptionReturn.Message = fmt.Sprintf("Error inserting row in \"transaction\" table: %s", err)
return nil, exceptionReturn
}
tx.Commit()
return tm, nil
}
/*
GetAll
Gets all rows from subscription type table.
Args:
context.Context: Application context
string: Relations to embed
Returns:
*models.Exception: Exception payload.
*/
// Gets filtered rows from transaction table.
func (as *TransactionService) GetAll(ctx context.Context, am *models.Auth, walletId string, filtered *models.FilteredResponse, noPending bool) *models.Exception {
db := as.db.WithContext(ctx)
exceptionReturn := new(models.Exception)
wm := new([]models.Transaction)
transactionStatus := new(models.TransactionStatus)
tx, _ := db.Begin()
defer tx.Rollback()
err := tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "completed").Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400117"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatus\" table: %s", err)
return exceptionReturn
}
query := tx.Model(wm).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id)
if walletId != "" {
query = query.Where("? = ?", pg.Ident("wallet_id"), walletId)
}
if noPending {
query = query.Where("? = ?", pg.Ident("transaction_status_id"), transactionStatus.Id)
}
err = FilteredResponse(query, wm, filtered)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400118"
exceptionReturn.Message = fmt.Sprintf("Error selecting row(s) in \"transaction\" table: %s", err)
return exceptionReturn
}
tx.Commit()
return nil
}
/*
Check
Checks subscriptions and create transacitons.
Args:
context.Context: Application context
string: Relations to embed
Returns:
*models.Exception: Exception payload.
*/
// Gets filtered rows from transaction table.
func (as *TransactionService) Check(ctx context.Context, am *models.Auth, walletId string, filtered *models.FilteredResponse) *models.Exception {
db := as.db.WithContext(ctx)
wm := new([]models.Transaction)
sm := new([]models.Subscription)
transactionStatus := new(models.TransactionStatus)
exceptionReturn := new(models.Exception)
tx, _ := db.Begin()
defer tx.Rollback()
err := tx.Model(transactionStatus).Where("? = ?", pg.Ident("status"), "pending").Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400119"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactionStatus\" table: %s", err)
return exceptionReturn
}
query2 := tx.Model(sm).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id)
if walletId != "" {
query2 = query2.Where("? = ?", pg.Ident("wallet_id"), walletId)
}
query2.Select()
for _, sub := range *sm {
if sub.HasNew() {
as.subscriptionService.SubToTrans(&sub, tx)
}
}
query := tx.Model(wm).Relation("Wallet").Where("wallet.? = ?", pg.Ident("user_id"), am.Id)
if walletId != "" {
query = query.Where("? = ?", pg.Ident("wallet_id"), walletId)
}
query = query.Where("? = ?", pg.Ident("transaction_status_id"), transactionStatus.Id)
err = FilteredResponse(query, wm, filtered)
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400120"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transaction\" table: %s", err)
return exceptionReturn
}
tx.Commit()
return nil
}
/*
Edit
Updates row in transaction table by id.
Args:
context.Context: Application context
*models.TransactionEdit: Object to edit
string: id to search
Returns:
*models.Transaction: Transaction object from database.
*models.Exception: Exception payload.
*/
func (as *TransactionService) Edit(ctx context.Context, body *models.TransactionEdit, id string) (*models.Transaction, *models.Exception) {
db := as.db.WithContext(ctx)
amount, _ := body.Amount.Float64()
exceptionReturn := new(models.Exception)
tm := new(models.Transaction)
tm.Id = id
tm.Description = body.Description
tm.WalletID = body.WalletID
tm.TransactionTypeID = body.TransactionTypeID
tm.TransactionDate = body.TransactionDate
tm.TransactionStatusID = body.TransactionStatusID
tm.Amount = float32(math.Round(amount*100) / 100)
tx, _ := db.Begin()
defer tx.Rollback()
_, err := tx.Model(tm).WherePK().UpdateNotZero()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400107"
exceptionReturn.Message = fmt.Sprintf("Error updating row in \"transaction\" table: %s", err)
return nil, exceptionReturn
}
err = tx.Model(tm).WherePK().Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400108"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transaction\" table: %s", err)
return nil, exceptionReturn
}
tx.Commit()
return tm, nil
}
/*
Bulk Edit
Updates row in transaction table by id.
Args:
context.Context: Application context
?[]models.Transaction Bulk Edit: Object to edit
string: id to search
Returns:
*models.Transaction: Transaction object from database.
*models.Exception: Exception payload.
*/
func (as *TransactionService) BulkEdit(ctx context.Context, body *[]models.TransactionEdit) (*[]models.Transaction, *models.Exception) {
db := as.db.WithContext(ctx)
tx, _ := db.Begin()
defer tx.Rollback()
transactions := new([]models.Transaction)
exceptionReturn := new(models.Exception)
for _, transaction := range *body {
amount, _ := transaction.Amount.Float64()
tm := new(models.Transaction)
tm.Id = transaction.Id
tm.Description = transaction.Description
tm.WalletID = transaction.WalletID
tm.TransactionTypeID = transaction.TransactionTypeID
tm.TransactionDate = transaction.TransactionDate
tm.Amount = float32(math.Round(amount*100) / 100)
*transactions = append(*transactions, *tm)
}
_, err := tx.Model(transactions).WherePK().UpdateNotZero()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400121"
exceptionReturn.Message = fmt.Sprintf("Error updating rows in \"transactions\" table: %s", err)
return nil, exceptionReturn
}
tx.Commit()
return transactions, nil
}
/*
Get
Gets row from transaction table by id.
Args:
context.Context: Application context
*models.Auth: Authentication object
string: id to search
*model.Params: url query parameters
Returns:
*models.Transaction: Transaction object from database.
*models.Exception: Exception payload.
*/
func (as *TransactionService) Get(ctx context.Context, am *models.Auth, id string, params *models.Params) (*models.Transaction, *models.Exception) {
db := as.db.WithContext(ctx)
exceptionReturn := new(models.Exception)
wm := new(models.Transaction)
wm.Id = id
tx, _ := db.Begin()
defer tx.Rollback()
qry := tx.Model(wm)
err := common.GenerateEmbed(qry, params.Embed).WherePK().Select()
if err != nil {
exceptionReturn.StatusCode = 400
exceptionReturn.ErrorCode = "400122"
exceptionReturn.Message = fmt.Sprintf("Error selecting row in \"transactions\" table: %s", err)
return nil, exceptionReturn
}
tx.Commit()
return wm, nil
}