Compare commits

...

11 Commits

11 changed files with 149 additions and 26 deletions

View File

@ -127,6 +127,10 @@ func main() {
{
paymentRoutes.POST("/add", handlers.PaymentAdd)
}
currencyRoutes := api.Group("/currency", middleware.AuthMiddleware())
{
currencyRoutes.GET("/all", handlers.CurrencyGetAll)
}
}
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))

View File

@ -10,9 +10,12 @@ import (
type Card struct {
gorm.Model
Name string
LastDigits string
Balance uint64
HaveCreditLine bool
CreditLine uint64
CurrencyID uint
Currency *Currency
UserID uint
User *User
}
@ -35,6 +38,7 @@ func (c *Card) SetUserID(id uint) {
var (
ERROR_CARD_NAME_EMPTY = errors.New("The 'Name' field for 'Card' cannot be empty")
ERROR_CARD_NAME_NOT_UNIQUE = errors.New("The 'Name' field for 'Card' have to be unique for user")
ERROR_CARD_CANT_FIND_CURR = errors.New("The 'CurrencyID' field for 'Card' is invalid")
)
func (c *Card) BeforeSave(tx *gorm.DB) error {
@ -50,6 +54,15 @@ func (c *Card) BeforeSave(tx *gorm.DB) error {
if c.ID != dup.ID && dup.ID != 0 {
return ERROR_CARD_NAME_NOT_UNIQUE
}
if c.CurrencyID != 0 {
var currency Currency
if err := tx.Find(&currency, c.CurrencyID).Error; err != nil {
return err
}
if currency.ID == 0 {
return ERROR_CARD_CANT_FIND_CURR
}
}
return nil
}

14
db/currency.go Normal file
View File

@ -0,0 +1,14 @@
package db
import "gorm.io/gorm"
type Currency struct {
gorm.Model
Name string
ISOName string
Symbol string
}
func (c Currency) GetID() uint {
return c.ID
}

View File

@ -70,6 +70,8 @@ func Connect() *gorm.DB {
gormDB.AutoMigrate(&Session{})
gormDB.AutoMigrate(&Expense{})
gormDB.AutoMigrate(&Metric{})
gormDB.AutoMigrate(&Currency{})
gormDB.AutoMigrate(&ExchangeRate{})
return newUDB
}
@ -77,40 +79,62 @@ var (
CANT_FIND_METRIC = errors.New("Can't find proper metrics in database")
)
func initMetrics(tx *gorm.DB) error {
var metrics []Metric
if err := tx.Find(&metrics).Error; err != nil {
func checkSeededValues[T Identifiable](whatToCheck []*T, errorIfNotFound error, tx *gorm.DB) error {
var valuesInDB []T
if err := tx.Find(&valuesInDB).Error; err != nil {
return err
}
if len(valuesInDB) == 0 {
for _, v := range whatToCheck {
if err := tx.Create(v).Error; err != nil {
return err
}
}
return nil
}
for _, v := range whatToCheck {
var tmp T
if err := tx.Find(&tmp, v).Error; err != nil {
return err
}
if tmp.GetID() == 0 {
return errorIfNotFound
}
}
return nil
}
func initMetrics(tx *gorm.DB) error {
metricsThatNeeded := []*Metric{
&Metric{Name: "None", Short: "pcs", Value: 0},
&Metric{Name: "Gram", Short: "g", Value: 1},
&Metric{Name: "Kilogram", Short: "kg", Value: 2},
&Metric{Name: "Liter", Short: "l", Value: 3},
}
if len(metrics) == 0 {
for _, m := range metricsThatNeeded {
if err := tx.Create(m).Error; err != nil {
return err
}
}
return nil
return checkSeededValues(metricsThatNeeded, CANT_FIND_METRIC, tx)
}
func initCurrencies(tx *gorm.DB) error {
currsThatNeeded := []*Currency{
{Name: "Dollar", Symbol: "$", ISOName: "USD"},
{Name: "Moldavian Leu", Symbol: "L", ISOName: "MDL"},
{Name: "Romanian Leu", Symbol: "RL", ISOName: "RON"},
{Name: "Polish Zloty", Symbol: "zł", ISOName: "PLN"},
{Name: "Ukrainian Hryvnia", Symbol: "₴", ISOName: "UAH"},
{Name: "Euro", Symbol: "€", ISOName: "EUR"},
{Name: "Russian Ruble", Symbol: "₽", ISOName: "RUB"},
{Name: "Kazakhstani Tenge", Symbol: "₸", ISOName: "KZT"},
{Name: "Chinese Yuan", Symbol: "¥", ISOName: "CNY"},
}
for _, m := range metricsThatNeeded {
tmp := &Metric{}
if err := tx.Find(tmp, m).Error; err != nil {
return err
}
if tmp.ID == 0 {
return CANT_FIND_METRIC
}
}
return nil
return checkSeededValues(currsThatNeeded, CANT_FIND_METRIC, tx)
}
func initStateOfDb(tx *gorm.DB) error {
if err := initMetrics(tx); err != nil {
return fmt.Errorf("initMetrics: %w", err)
}
if err := initCurrencies(tx); err != nil {
return fmt.Errorf("initCurrencies: %w", err)
}
return nil
}

14
db/exchange_rate.go Normal file
View File

@ -0,0 +1,14 @@
package db
import "gorm.io/gorm"
type ExchangeRate struct {
gorm.Model
FromCurrID uint
FromCurr *Currency
From uint64
ToCurrID uint
ToCurr *Currency
To uint64
Rate uint64
}

View File

@ -2,7 +2,6 @@ package db
import (
"errors"
"log"
"time"
"gorm.io/gorm"
@ -43,7 +42,6 @@ var (
)
func (e *Expense) BeforeCreate(tx *gorm.DB) error {
log.Printf("BeforeCreate")
card := &Card{}
if err := tx.Find(card, e.CardID).Error; err != nil {
return err
@ -63,9 +61,6 @@ func (e *Expense) BeforeCreate(tx *gorm.DB) error {
if err := tx.Find(typ, e.TypeID).Error; err != nil {
return err
}
log.Printf("e.UserID = %d\n", e.UserID)
log.Printf("e.TypeID= %d\n", e.TypeID)
log.Printf("typ.UserID= %d\n", typ.UserID)
if typ.UserID != e.UserID {
return ERROR_EXPENSE_INVALID_TYPE_USERID
}

View File

@ -2,7 +2,6 @@ package db
type Identifiable interface {
GetID() uint
SetID(id uint)
}
type UserIdentifiable interface {

View File

@ -8,3 +8,7 @@ type Metric struct {
Name string
Short string
}
func (m Metric) GetID() uint {
return m.ID
}

View File

@ -13,6 +13,8 @@ var cardTransform func(inp *db.Card) types.DbCard = func(inp *db.Card) types.DbC
Balance: inp.Balance,
HaveCreditLine: inp.HaveCreditLine,
CreditLine: inp.CreditLine,
LastDigits: inp.LastDigits,
CurrencyID: inp.CurrencyID,
}
}
@ -82,6 +84,8 @@ func CardAdd(c *gin.Context) {
dst.Balance = src.Balance
dst.HaveCreditLine = src.HaveCreditLine
dst.CreditLine = src.CreditLine
dst.LastDigits = src.LastDigits
dst.CurrencyID = src.CurrencyID
})(c)
}
@ -107,6 +111,8 @@ func CardPutId(c *gin.Context) {
dst.Balance = src.Balance
dst.CreditLine = src.CreditLine
dst.HaveCreditLine = src.HaveCreditLine
dst.LastDigits = src.LastDigits
dst.CurrencyID = src.CurrencyID
},
cardTransform)(c)
}

41
handlers/currency.go Normal file
View File

@ -0,0 +1,41 @@
package handlers
import (
"git.qowevisa.me/Qowevisa/fin-check-api/db"
"git.qowevisa.me/Qowevisa/fin-check-api/types"
"github.com/gin-gonic/gin"
)
var currencyTransform func(inp *db.Currency) types.DbCurrency = func(inp *db.Currency) types.DbCurrency {
return types.DbCurrency{
ID: inp.ID,
Name: inp.Name,
ISOName: inp.ISOName,
Symbol: inp.Symbol,
}
}
// @Summary Get all currencies for user
// @Description Get all currencies for user
// @Tags type
// @Produce json
// @Param Authorization header string true "Bearer token"
// @Success 200 {object} []types.DbCurrency
// @Failure 401 {object} types.ErrorResponse
// @Failure 500 {object} types.ErrorResponse
// @Security ApiKeyAuth
// @Router /currency/all [get]
func CurrencyGetAll(c *gin.Context) {
dbc := db.Connect()
var entities []*db.Currency
if err := dbc.Find(&entities).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
var ret []types.DbCurrency
for _, entity := range entities {
ret = append(ret, currencyTransform(entity))
}
c.JSON(200, ret)
}

View File

@ -29,6 +29,8 @@ type DbCard struct {
Balance uint64 `json:"balance" example:"1000"`
HaveCreditLine bool `json:"have_credit_line" example:"true"`
CreditLine uint64 `json:"credit_line" example:"500000"`
LastDigits string `json:"last_digits" example:"1111"`
CurrencyID uint `json:"currency_id" example:"1"`
}
type DbCategory struct {
@ -113,6 +115,13 @@ type DbMetric struct {
Short string `json:"short" example:"kg"`
}
type DbCurrency struct {
ID uint `json:"id" example:"1"`
Name string `json:"name" example:"Dollar"`
ISOName string `json:"iso_name" example:"USD"`
Symbol string `json:"symbol" example:"$"`
}
type Payment struct {
ID uint `json:"id" example:"1"`
CardID uint `json:"card_id" example:"1"`