mirror of
https://github.com/FJurmanovic/wallet-go-api.git
synced 2026-02-06 06:08:16 +00:00
add cron job to sync currencies once in 24 hours
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -29,8 +29,6 @@ _testmain.go
|
||||
*.exe
|
||||
*.test
|
||||
*.prof
|
||||
*.log
|
||||
|
||||
# .Dockerfile
|
||||
|
||||
logs.log
|
||||
querys.log
|
||||
3
go.mod
3
go.mod
@@ -6,6 +6,7 @@ go 1.19
|
||||
require (
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/gin-gonic/gin v1.7.7
|
||||
github.com/go-co-op/gocron v1.20.1
|
||||
github.com/go-pg/pg/v10 v10.10.6
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/joho/godotenv v1.4.0
|
||||
@@ -26,12 +27,14 @@ require (
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
|
||||
github.com/ugorji/go/codec v1.2.6 // indirect
|
||||
github.com/vmihailenco/bufpool v0.1.11 // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.4 // indirect
|
||||
github.com/vmihailenco/tagparser v0.1.2 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/protobuf v1.26.0 // indirect
|
||||
|
||||
8
go.sum
8
go.sum
@@ -17,6 +17,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
|
||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||
github.com/go-co-op/gocron v1.20.1 h1:wCGabII3xf/NrrYeOzJ4voLBBtA5k7Rb99+7l/iiu+g=
|
||||
github.com/go-co-op/gocron v1.20.1/go.mod h1:UqVyvM90I1q/R1qGEX6cBORI6WArLuEgYlbncLMvzRM=
|
||||
github.com/go-pg/pg/v10 v10.10.6 h1:1vNtPZ4Z9dWUw/TjJwOfFUbF5nEq1IkR6yG8Mq/Iwso=
|
||||
github.com/go-pg/pg/v10 v10.10.6/go.mod h1:GLmFXufrElQHf5uzM3BQlcfwV3nsgnHue5uzjQ6Nqxg=
|
||||
github.com/go-pg/zerochecker v0.2.0 h1:pp7f72c3DobMWOb2ErtZsnrPaSvHd2W4o9//8HtF4mU=
|
||||
@@ -100,6 +102,8 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
@@ -109,7 +113,7 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
@@ -152,6 +156,8 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
"wallet-api/pkg/controller"
|
||||
"wallet-api/pkg/job"
|
||||
"wallet-api/pkg/middleware"
|
||||
"wallet-api/pkg/utl/common"
|
||||
"wallet-api/pkg/utl/configs"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-co-op/gocron"
|
||||
"github.com/go-pg/pg/v10"
|
||||
"go.uber.org/dig"
|
||||
)
|
||||
@@ -22,6 +26,10 @@ Initializes web api controllers and its corresponding routes.
|
||||
*/
|
||||
func Routes(s *gin.Engine, db *pg.DB) {
|
||||
c := dig.New()
|
||||
|
||||
scheduler := gocron.NewScheduler(time.UTC)
|
||||
scheduler.SetMaxConcurrentJobs(3, 1)
|
||||
defer scheduler.StartAsync()
|
||||
ver := s.Group(configs.Prefix)
|
||||
|
||||
routeGroups := &common.RouteGroups{
|
||||
@@ -46,5 +54,13 @@ func Routes(s *gin.Engine, db *pg.DB) {
|
||||
c.Provide(func() *pg.DB {
|
||||
return db
|
||||
})
|
||||
c.Provide(func() *gocron.Scheduler {
|
||||
return scheduler
|
||||
})
|
||||
c.Provide(func() *log.Logger {
|
||||
return log.Default()
|
||||
})
|
||||
controller.InitializeControllers(c)
|
||||
job.InitializeJobs(c)
|
||||
|
||||
}
|
||||
|
||||
@@ -2,13 +2,14 @@ package controller
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go.uber.org/dig"
|
||||
"strconv"
|
||||
"strings"
|
||||
"wallet-api/pkg/model"
|
||||
"wallet-api/pkg/service"
|
||||
"wallet-api/pkg/utl/common"
|
||||
|
||||
"go.uber.org/dig"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -21,17 +22,18 @@ Initializes Dependency Injection modules and registers controllers
|
||||
*dig.Container: Dig Container
|
||||
*/
|
||||
func InitializeControllers(c *dig.Container) {
|
||||
service.InitializeServices(c)
|
||||
controllerContainer := c.Scope("controller")
|
||||
service.InitializeServices(controllerContainer)
|
||||
|
||||
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)
|
||||
controllerContainer.Invoke(NewApiController)
|
||||
controllerContainer.Invoke(NewUserController)
|
||||
controllerContainer.Invoke(NewWalletController)
|
||||
controllerContainer.Invoke(NewWalletHeaderController)
|
||||
controllerContainer.Invoke(NewTransactionController)
|
||||
controllerContainer.Invoke(NewTransactionStatusController)
|
||||
controllerContainer.Invoke(NewTransactionTypeController)
|
||||
controllerContainer.Invoke(NewSubscriptionController)
|
||||
controllerContainer.Invoke(NewSubscriptionTypeController)
|
||||
|
||||
}
|
||||
|
||||
|
||||
52
pkg/job/currency.go
Normal file
52
pkg/job/currency.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package job
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"wallet-api/pkg/service"
|
||||
"wallet-api/pkg/utl/common"
|
||||
|
||||
"github.com/go-co-op/gocron"
|
||||
)
|
||||
|
||||
type CurrencyController struct {
|
||||
service *service.CurrencyService
|
||||
logger *log.Logger
|
||||
scheduler *gocron.Scheduler
|
||||
}
|
||||
|
||||
/*
|
||||
NewCurrencyJob
|
||||
|
||||
Initializes CurrencyJob.
|
||||
|
||||
Args:
|
||||
*services.CurrencyService: Currency service
|
||||
*gin.RouterGroup: Gin Router Group
|
||||
Returns:
|
||||
*CurrencyJob: Job for "Currency" route interactions
|
||||
*/
|
||||
func NewCurrencyJob(as *service.CurrencyService, scheduler *gocron.Scheduler, logger *log.Logger) *CurrencyController {
|
||||
currencyScheduler := scheduler.Tag("currency")
|
||||
|
||||
wc := &CurrencyController{
|
||||
service: as,
|
||||
logger: logger,
|
||||
scheduler: currencyScheduler,
|
||||
}
|
||||
|
||||
_, err := currencyScheduler.Every(1).Days().Do(wc.Sync)
|
||||
common.CheckError(err)
|
||||
currencyScheduler.StartAsync()
|
||||
|
||||
log.Println("CurrencyJob started")
|
||||
|
||||
return wc
|
||||
}
|
||||
|
||||
func (wc *CurrencyController) Sync() {
|
||||
wc.logger.Println("CurrencyJob: Syncing currencies")
|
||||
ctx := context.Background()
|
||||
wc.service.Sync(ctx)
|
||||
wc.logger.Println("CurrencyJob: Syncing currencies done")
|
||||
}
|
||||
33
pkg/job/job.go
Normal file
33
pkg/job/job.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package job
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"wallet-api/pkg/service"
|
||||
"wallet-api/pkg/utl/common"
|
||||
|
||||
"go.uber.org/dig"
|
||||
)
|
||||
|
||||
/*
|
||||
InitializeJobs
|
||||
|
||||
Initializes Dependency Injection modules and registers Jobs
|
||||
|
||||
Args:
|
||||
*dig.Container: Dig Container
|
||||
*/
|
||||
func InitializeJobs(c *dig.Container) {
|
||||
file, err := os.OpenFile("job.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
|
||||
common.CheckError(err)
|
||||
logger := log.New(file, "Job: ", log.Ldate|log.Ltime|log.Lshortfile)
|
||||
|
||||
jobContainer := c.Scope("job")
|
||||
jobContainer.Provide(func() *log.Logger {
|
||||
return logger
|
||||
})
|
||||
|
||||
service.InitializeServices(jobContainer)
|
||||
|
||||
jobContainer.Invoke(NewCurrencyJob)
|
||||
}
|
||||
@@ -27,7 +27,7 @@ func CreateTableTransactionStatus(db *pg.Tx) error {
|
||||
|
||||
for _, model := range models {
|
||||
err := db.Model(model).CreateTable(&orm.CreateTableOptions{
|
||||
IfNotExists: false,
|
||||
IfNotExists: true,
|
||||
FKConstraints: true,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
40
pkg/migrate/12_create_table_currencies.go
Normal file
40
pkg/migrate/12_create_table_currencies.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"wallet-api/pkg/model"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
"github.com/go-pg/pg/v10/orm"
|
||||
)
|
||||
|
||||
/*
|
||||
CreateTableCurrencies
|
||||
|
||||
Creates Currencies table if it does not exist.
|
||||
|
||||
Args:
|
||||
*pg.DB: Postgres database client
|
||||
Returns:
|
||||
error: Returns if there is an error with table creation
|
||||
*/
|
||||
func CreateTableCurrencies(db *pg.Tx) error {
|
||||
models := []interface{}{
|
||||
(*model.Currency)(nil),
|
||||
}
|
||||
|
||||
for _, model := range models {
|
||||
err := db.Model(model).CreateTable(&orm.CreateTableOptions{
|
||||
IfNotExists: true,
|
||||
FKConstraints: true,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("Error creating table \"currencies\": %s", err)
|
||||
return err
|
||||
} else {
|
||||
fmt.Println("Table \"currencies\" created successfully")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -27,7 +27,7 @@ func CreateTableWallets(db *pg.Tx) error {
|
||||
|
||||
for _, model := range models {
|
||||
err := db.Model(model).CreateTable(&orm.CreateTableOptions{
|
||||
IfNotExists: false,
|
||||
IfNotExists: true,
|
||||
FKConstraints: true,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -27,7 +27,7 @@ func CreateTableTransactionTypes(db *pg.Tx) error {
|
||||
|
||||
for _, model := range models {
|
||||
err := db.Model(model).CreateTable(&orm.CreateTableOptions{
|
||||
IfNotExists: false,
|
||||
IfNotExists: true,
|
||||
FKConstraints: true,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -27,7 +27,7 @@ func CreateTableTransactions(db *pg.Tx) error {
|
||||
|
||||
for _, model := range models {
|
||||
err := db.Model(model).CreateTable(&orm.CreateTableOptions{
|
||||
IfNotExists: false,
|
||||
IfNotExists: true,
|
||||
FKConstraints: true,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -27,7 +27,7 @@ func CreateTableSubscriptionTypes(db *pg.Tx) error {
|
||||
|
||||
for _, model := range models {
|
||||
err := db.Model(model).CreateTable(&orm.CreateTableOptions{
|
||||
IfNotExists: false,
|
||||
IfNotExists: true,
|
||||
FKConstraints: true,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -26,7 +26,7 @@ func CreateTableSubscriptions(db *pg.Tx) error {
|
||||
|
||||
for _, model := range models {
|
||||
err := db.Model(model).CreateTable(&orm.CreateTableOptions{
|
||||
IfNotExists: false,
|
||||
IfNotExists: true,
|
||||
FKConstraints: true,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -48,12 +48,19 @@ func Start(conn *pg.DB, version string) []error {
|
||||
CreateTableTransactions,
|
||||
},
|
||||
}
|
||||
migration005 := Migration{
|
||||
Version: "005",
|
||||
Migrations: []interface{}{
|
||||
CreateTableCurrencies,
|
||||
},
|
||||
}
|
||||
|
||||
migrationsMap := []Migration{
|
||||
migration001,
|
||||
migration002,
|
||||
migration003,
|
||||
migration004,
|
||||
migration005,
|
||||
}
|
||||
|
||||
var errors []error
|
||||
|
||||
63
pkg/model/currency.go
Normal file
63
pkg/model/currency.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
)
|
||||
|
||||
type Currency struct {
|
||||
tableName struct{} `pg:"currencies,alias:currencies"`
|
||||
BaseModel
|
||||
Rate float32 `json:"rate", pg:"rate,default:0"`
|
||||
Name string `json:"name", pg:"name,unique"`
|
||||
}
|
||||
|
||||
type CurrencyEdit struct {
|
||||
tableName struct{} `pg:"currencies,alias:currencies"`
|
||||
Id string `json:"id" form:"id"`
|
||||
Rate json.Number `json:"rate", form:"rate"`
|
||||
Name string `json:"name", form:"name"`
|
||||
}
|
||||
|
||||
type NewCurrencyBody struct {
|
||||
Rate json.Number `json:"rate", form:"rate"`
|
||||
Name string `json:"name", form:"name"`
|
||||
}
|
||||
|
||||
type ExchangeBody struct {
|
||||
Base string `json:"base"`
|
||||
Rates interface{} `json:"rates"`
|
||||
}
|
||||
|
||||
type Rate struct {
|
||||
Code string `json:"code"`
|
||||
Rate float64 `json:"rate"`
|
||||
}
|
||||
|
||||
func (body *CurrencyEdit) ToCurrency() *Currency {
|
||||
rate, _ := body.Rate.Float64()
|
||||
tm := new(Currency)
|
||||
tm.Id = body.Id
|
||||
tm.Rate = float32(math.Round(rate*100) / 100)
|
||||
tm.Name = body.Name
|
||||
|
||||
return tm
|
||||
}
|
||||
|
||||
func (body *NewCurrencyBody) ToCurrency() *Currency {
|
||||
rate, _ := body.Rate.Float64()
|
||||
tm := new(Currency)
|
||||
tm.Init()
|
||||
tm.Rate = float32(math.Round(rate*100) / 100)
|
||||
tm.Name = body.Name
|
||||
return tm
|
||||
}
|
||||
|
||||
func (body *ExchangeBody) Unmarshal(resp *[]interface{}) *ExchangeBody {
|
||||
body.Base = (*resp)[3].(string)
|
||||
// body.Rates = []Rate{}
|
||||
// for k, v := range (*resp)[5].(map[string]interface{}) {
|
||||
// body.Rates = append(body.Rates, Rate{Code: k, Rate: v.(float64)})
|
||||
// }
|
||||
return body
|
||||
}
|
||||
84
pkg/repository/currency.go
Normal file
84
pkg/repository/currency.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
"wallet-api/pkg/model"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
)
|
||||
|
||||
type CurrencyRepository struct {
|
||||
db *pg.DB
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
func NewCurrencyRepository(db *pg.DB, logger *log.Logger) *CurrencyRepository {
|
||||
return &CurrencyRepository{
|
||||
db: db,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
GetFirst
|
||||
|
||||
Gets first row from Currency table.
|
||||
|
||||
Args:
|
||||
context.Context: Application context
|
||||
Returns:
|
||||
model.CurrencyModel: Currency object from database.
|
||||
*/
|
||||
func (as CurrencyRepository) Sync(ctx context.Context, rate *model.Rate, tx *pg.Tx) *model.Currency {
|
||||
currency := new(model.Currency)
|
||||
currency.Name = rate.Code
|
||||
|
||||
any := tx.Model(currency).Where("name = ?", rate.Code).First()
|
||||
currency.Rate = float32(rate.Rate)
|
||||
if any != nil {
|
||||
currency.Init()
|
||||
_, err := tx.Model(currency).Insert()
|
||||
if err != nil {
|
||||
as.logger.Println(err)
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
currency.DateUpdated = time.Now()
|
||||
_, err := tx.Model(currency).WherePK().Update()
|
||||
if err != nil {
|
||||
as.logger.Println(err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return currency
|
||||
}
|
||||
|
||||
/*
|
||||
GetFirst
|
||||
|
||||
Gets first row from Currency table.
|
||||
|
||||
Args:
|
||||
context.Context: Application context
|
||||
Returns:
|
||||
model.CurrencyModel: Currency object from database.
|
||||
*/
|
||||
func (as CurrencyRepository) SyncBulk(ctx context.Context, rates *[]model.Rate) *[]model.Currency {
|
||||
tx, _ := as.db.BeginContext(ctx)
|
||||
defer tx.Rollback()
|
||||
|
||||
currencies := new([]model.Currency)
|
||||
|
||||
for _, r := range *rates {
|
||||
currency := as.Sync(ctx, &r, tx)
|
||||
if currency != nil {
|
||||
*currencies = append(*currencies, *currency)
|
||||
}
|
||||
}
|
||||
|
||||
tx.Commit()
|
||||
|
||||
return currencies
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"go.uber.org/dig"
|
||||
"wallet-api/pkg/model"
|
||||
"wallet-api/pkg/utl/common"
|
||||
|
||||
"go.uber.org/dig"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
)
|
||||
|
||||
@@ -16,7 +17,7 @@ Initializes Dependency Injection modules for repositories
|
||||
Args:
|
||||
*dig.Container: Dig Container
|
||||
*/
|
||||
func InitializeRepositories(c *dig.Container) {
|
||||
func InitializeRepositories(c *dig.Scope) {
|
||||
c.Provide(NewApiRepository)
|
||||
c.Provide(NewSubscriptionRepository)
|
||||
c.Provide(NewSubscriptionTypeRepository)
|
||||
@@ -25,6 +26,7 @@ func InitializeRepositories(c *dig.Container) {
|
||||
c.Provide(NewTransactionTypeRepository)
|
||||
c.Provide(NewUserRepository)
|
||||
c.Provide(NewWalletRepository)
|
||||
c.Provide(NewCurrencyRepository)
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
50
pkg/service/currency.go
Normal file
50
pkg/service/currency.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"wallet-api/pkg/model"
|
||||
"wallet-api/pkg/repository"
|
||||
"wallet-api/pkg/utl/common"
|
||||
)
|
||||
|
||||
type CurrencyService struct {
|
||||
repository *repository.CurrencyRepository
|
||||
logger *log.Logger
|
||||
}
|
||||
|
||||
func NewCurrencyService(repository *repository.CurrencyRepository, logger *log.Logger) *CurrencyService {
|
||||
return &CurrencyService{
|
||||
repository: repository,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
GetFirst
|
||||
|
||||
Gets first row from Currency table.
|
||||
|
||||
Args:
|
||||
context.Context: Application context
|
||||
Returns:
|
||||
model.CurrencyModel: Currency object from database.
|
||||
*/
|
||||
func (as CurrencyService) Sync(ctx context.Context) {
|
||||
resp, err := common.Fetch[model.ExchangeBody]("GET", "https://api.exchangerate-api.com/v4/latest/euro")
|
||||
if err != nil {
|
||||
as.logger.Println(err)
|
||||
return
|
||||
}
|
||||
m := resp.Rates.(map[string]interface{})
|
||||
|
||||
rates := new([]model.Rate)
|
||||
|
||||
for k, v := range m {
|
||||
rate := new(model.Rate)
|
||||
rate.Code = k
|
||||
rate.Rate = v.(float64)
|
||||
*rates = append(*rates, *rate)
|
||||
}
|
||||
as.repository.SyncBulk(ctx, rates)
|
||||
}
|
||||
@@ -14,7 +14,7 @@ Initializes Dependency Injection modules for services
|
||||
Args:
|
||||
*dig.Container: Dig Container
|
||||
*/
|
||||
func InitializeServices(c *dig.Container) {
|
||||
func InitializeServices(c *dig.Scope) {
|
||||
repository.InitializeRepositories(c)
|
||||
|
||||
c.Provide(NewApiService)
|
||||
@@ -25,4 +25,5 @@ func InitializeServices(c *dig.Container) {
|
||||
c.Provide(NewTransactionTypeService)
|
||||
c.Provide(NewUserService)
|
||||
c.Provide(NewWalletService)
|
||||
c.Provide(NewCurrencyService)
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type RouteGroups struct {
|
||||
@@ -61,3 +65,24 @@ func Find[T any](lst *[]T, callback func(item *T) bool) *T {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Fetch[T any](method string, url string) (*T, error) {
|
||||
req, err := http.NewRequest(method, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := new(T)
|
||||
err = json.Unmarshal(body, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user