Compare commits

..

10 Commits

16 changed files with 115 additions and 253 deletions

View File

@ -6,10 +6,10 @@ import (
"github.com/swaggo/files" "github.com/swaggo/files"
"github.com/swaggo/gin-swagger" "github.com/swaggo/gin-swagger"
docs "git.qowevisa.me/Qowevisa/gonuts/docs" docs "git.qowevisa.me/Qowevisa/fin-check-api/docs"
"git.qowevisa.me/Qowevisa/gonuts/handlers" "git.qowevisa.me/Qowevisa/fin-check-api/handlers"
"git.qowevisa.me/Qowevisa/gonuts/middleware" "git.qowevisa.me/Qowevisa/fin-check-api/middleware"
"git.qowevisa.me/Qowevisa/gonuts/tokens" "git.qowevisa.me/Qowevisa/fin-check-api/tokens"
"github.com/gin-contrib/cors" "github.com/gin-contrib/cors"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@ -95,5 +95,5 @@ func main() {
}) })
go tokens.StartTokens() go tokens.StartTokens()
r.Run("127.0.0.1:3001") r.Run("127.0.0.1:3000")
} }

View File

@ -19,3 +19,18 @@ type Debt struct {
UserID uint UserID uint
User *User User *User
} }
// Implements db.UserIdentifiable:1
func (d Debt) GetID() uint {
return d.ID
}
// Implements db.UserIdentifiable:2
func (d Debt) GetUserID() uint {
return d.UserID
}
// Implements db.UserIdentifiable:3
func (d *Debt) SetUserID(id uint) {
d.UserID = id
}

View File

@ -6,7 +6,12 @@ type ItemBought struct {
gorm.Model gorm.Model
ItemID uint ItemID uint
Item *Item Item *Item
Quantity uint
PaymentID uint PaymentID uint
Payment *Payment Payment *Payment
TypeID uint
Type *Type
Quantity uint
TotalCost uint64
MetricType uint8
MetricValue uint64
} }

View File

@ -13,7 +13,7 @@ type ItemPrice struct {
Item *Item Item *Item
Price uint64 Price uint64
ValidFrom time.Time ValidFrom time.Time
IsValid bool `gorm:"default:true"` ValidTo time.Time
} }
var ( var (

View File

@ -13,7 +13,9 @@ type Payment struct {
Card *Card Card *Card
CategoryID uint CategoryID uint
Category *Category Category *Category
Name string UserID uint
User *User
Title string
Descr string Descr string
Note string Note string
Items []ItemBought Items []ItemBought

2
go.mod
View File

@ -1,4 +1,4 @@
module git.qowevisa.me/Qowevisa/gonuts module git.qowevisa.me/Qowevisa/fin-check-api
go 1.20 go 1.20

View File

@ -1,8 +1,8 @@
package handlers package handlers
import ( import (
"git.qowevisa.me/Qowevisa/gonuts/db" "git.qowevisa.me/Qowevisa/fin-check-api/db"
"git.qowevisa.me/Qowevisa/gonuts/types" "git.qowevisa.me/Qowevisa/fin-check-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -1,8 +1,8 @@
package handlers package handlers
import ( import (
"git.qowevisa.me/Qowevisa/gonuts/db" "git.qowevisa.me/Qowevisa/fin-check-api/db"
"git.qowevisa.me/Qowevisa/gonuts/types" "git.qowevisa.me/Qowevisa/fin-check-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -1,12 +1,8 @@
package handlers package handlers
import ( import (
"fmt" "git.qowevisa.me/Qowevisa/fin-check-api/db"
"strconv" "git.qowevisa.me/Qowevisa/fin-check-api/types"
"git.qowevisa.me/Qowevisa/gonuts/db"
"git.qowevisa.me/Qowevisa/gonuts/types"
"git.qowevisa.me/Qowevisa/gonuts/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@ -20,60 +16,23 @@ import (
// @Success 200 {object} types.DbDebt // @Success 200 {object} types.DbDebt
// @Failure 400 {object} types.ErrorResponse // @Failure 400 {object} types.ErrorResponse
// @Failure 401 {object} types.ErrorResponse // @Failure 401 {object} types.ErrorResponse
// @Failure 403 {object} types.ErrorResponse
// @Failure 500 {object} types.ErrorResponse // @Failure 500 {object} types.ErrorResponse
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Router /debt/:id [get] // @Router /debt/:id [get]
func DebtGetId(c *gin.Context) { func DebtGetId(c *gin.Context) {
userIDAny, exists := c.Get("UserID") GetHandler(func(inp *db.Debt) types.DbDebt {
if !exists { return types.DbDebt{
c.JSON(500, types.ErrorResponse{Message: "Internal error 001"}) ID: inp.ID,
return CardID: inp.CardID,
Comment: inp.Comment,
Value: inp.Value,
IOwe: inp.IOwe,
Date: inp.Date,
DateEnd: inp.DateEnd,
Finished: inp.Finished,
} }
})(c)
var userID uint
if userIDVal, ok := userIDAny.(uint); !ok {
c.JSON(500, types.ErrorResponse{Message: "Internal error 002"})
return
} else {
userID = userIDVal
}
idStr := c.Param("id")
var id uint
if idVal, err := strconv.ParseUint(idStr, 10, 32); err != nil {
c.JSON(400, types.ErrorResponse{Message: "Invalid request"})
return
} else {
id = uint(idVal)
}
var dbDebt db.Debt
dbc := db.Connect()
if err := dbc.Find(&dbDebt, id).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
if dbDebt.ID == 0 {
c.JSON(500, types.ErrorResponse{Message: "DAFUQ003"})
return
}
if dbDebt.UserID != userID {
c.JSON(401, types.ErrorResponse{Message: "This debt.id is not yours, you sneaky."})
return
}
ret := types.DbDebt{
ID: dbDebt.ID,
CardID: dbDebt.CardID,
Comment: dbDebt.Comment,
Value: dbDebt.Value,
IOwe: dbDebt.IOwe,
Date: dbDebt.Date,
DateEnd: dbDebt.DateEnd,
Finished: dbDebt.Finished,
UserID: dbDebt.UserID,
}
c.JSON(200, ret)
} }
// @Summary Get debt by id // @Summary Get debt by id
@ -85,60 +44,22 @@ func DebtGetId(c *gin.Context) {
// @Param debt body types.DbDebt true "Debt" // @Param debt body types.DbDebt true "Debt"
// @Success 200 {object} types.Message // @Success 200 {object} types.Message
// @Failure 400 {object} types.ErrorResponse // @Failure 400 {object} types.ErrorResponse
// @Failure 403 {object} types.ErrorResponse
// @Failure 500 {object} types.ErrorResponse // @Failure 500 {object} types.ErrorResponse
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Router /debt/add [post] // @Router /debt/add [post]
func DebtAdd(c *gin.Context) { func DebtAdd(c *gin.Context) {
userIDAny, exists := c.Get("UserID") debt := &db.Debt{}
if !exists { CreateHandler(debt,
c.JSON(500, types.ErrorResponse{Message: "Internal error 001"}) func(src types.DbDebt, dst *db.Debt) {
return dst.CardID = src.CardID
} dst.Comment = src.Comment
dst.Value = src.Value
var userID uint dst.IOwe = src.IOwe
if userIDVal, ok := userIDAny.(uint); !ok { dst.Date = src.Date
c.JSON(500, types.ErrorResponse{Message: "Internal error 002"}) dst.DateEnd = src.DateEnd
return dst.Finished = src.Finished
} else { },
userID = userIDVal )(c)
}
var debt types.DbDebt
if err := c.ShouldBindJSON(&debt); err != nil {
c.JSON(400, types.ErrorResponse{Message: "Invalid request"})
return
}
if debt.UserID != 0 && userID != debt.UserID {
c.JSON(403, types.ErrorResponse{Message: "UserID in body is different than yours!"})
}
if debt.UserID == 0 {
debt.UserID = userID
}
dbDebt := &db.Debt{
CardID: debt.CardID,
Comment: debt.Comment,
Value: debt.Value,
IOwe: debt.IOwe,
Date: debt.Date,
DateEnd: debt.DateEnd,
Finished: debt.Finished,
UserID: debt.UserID,
}
dbc := db.Connect()
if err := dbc.Create(&dbDebt).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
if dbDebt.ID == 0 {
c.JSON(500, types.ErrorResponse{Message: "DAFUQ004"})
return
}
msg := types.Message{
Message: fmt.Sprintf("Debt with id %d was successfully created!", dbDebt.ID),
}
c.JSON(200, msg)
} }
// @Summary Edit debt by id // @Summary Edit debt by id
@ -152,72 +73,34 @@ func DebtAdd(c *gin.Context) {
// @Success 200 {object} types.DbDebt // @Success 200 {object} types.DbDebt
// @Failure 400 {object} types.ErrorResponse // @Failure 400 {object} types.ErrorResponse
// @Failure 401 {object} types.ErrorResponse // @Failure 401 {object} types.ErrorResponse
// @Failure 403 {object} types.ErrorResponse
// @Failure 500 {object} types.ErrorResponse // @Failure 500 {object} types.ErrorResponse
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Router /debt/edit/:id [put] // @Router /debt/edit/:id [put]
func DebtPutId(c *gin.Context) { func DebtPutId(c *gin.Context) {
userIDAny, exists := c.Get("UserID") UpdateHandler(
if !exists { // Filter used to apply only needed changes from srt to dst before updating dst
c.JSON(500, types.ErrorResponse{Message: "Internal error 001"}) func(src types.DbDebt, dst *db.Debt) {
return dst.CardID = src.CardID
dst.Comment = src.Comment
dst.Value = src.Value
dst.IOwe = src.IOwe
dst.Date = src.Date
dst.DateEnd = src.DateEnd
dst.Finished = src.Finished
},
func(inp *db.Debt) types.DbDebt {
return types.DbDebt{
ID: inp.ID,
CardID: inp.CardID,
Comment: inp.Comment,
Value: inp.Value,
IOwe: inp.IOwe,
Date: inp.Date,
DateEnd: inp.DateEnd,
Finished: inp.Finished,
} }
})(c)
var userID uint
if userIDVal, ok := userIDAny.(uint); !ok {
c.JSON(500, types.ErrorResponse{Message: "Internal error 002"})
return
} else {
userID = userIDVal
}
idStr := c.Param("id")
var id uint
if idVal, err := strconv.ParseUint(idStr, 10, 32); err != nil {
c.JSON(400, types.ErrorResponse{Message: "Invalid request"})
return
} else {
id = uint(idVal)
}
var dbDebt db.Debt
dbc := db.Connect()
if err := dbc.Find(&dbDebt, id).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
if dbDebt.ID == 0 {
c.JSON(500, types.ErrorResponse{Message: "DAFUQ003"})
return
}
if dbDebt.UserID != userID {
c.JSON(401, types.ErrorResponse{Message: "This debt.id is not yours, you sneaky."})
return
}
var debt types.DbDebt
if err := c.ShouldBindJSON(&debt); err != nil {
c.JSON(400, types.ErrorResponse{Message: "Invalid request"})
return
}
utils.MergeNonZeroFields(debt, dbDebt)
if err := dbc.Save(dbDebt).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
ret := types.DbDebt{
ID: dbDebt.ID,
CardID: dbDebt.CardID,
Comment: dbDebt.Comment,
Value: dbDebt.Value,
IOwe: dbDebt.IOwe,
Date: dbDebt.Date,
DateEnd: dbDebt.DateEnd,
Finished: dbDebt.Finished,
UserID: dbDebt.UserID,
}
c.JSON(200, ret)
} }
// @Summary Delete debt by id // @Summary Delete debt by id
@ -230,62 +113,10 @@ func DebtPutId(c *gin.Context) {
// @Success 200 {object} types.DbDebt // @Success 200 {object} types.DbDebt
// @Failure 400 {object} types.ErrorResponse // @Failure 400 {object} types.ErrorResponse
// @Failure 401 {object} types.ErrorResponse // @Failure 401 {object} types.ErrorResponse
// @Failure 403 {object} types.ErrorResponse
// @Failure 500 {object} types.ErrorResponse // @Failure 500 {object} types.ErrorResponse
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Router /debt/delete/:id [delete] // @Router /debt/delete/:id [delete]
func DebtDeleteId(c *gin.Context) { func DebtDeleteId(c *gin.Context) {
userIDAny, exists := c.Get("UserID") DeleteHandler[*db.Debt]()(c)
if !exists {
c.JSON(500, types.ErrorResponse{Message: "Internal error 001"})
return
}
var userID uint
if userIDVal, ok := userIDAny.(uint); !ok {
c.JSON(500, types.ErrorResponse{Message: "Internal error 002"})
return
} else {
userID = userIDVal
}
idStr := c.Param("id")
var id uint
if idVal, err := strconv.ParseUint(idStr, 10, 32); err != nil {
c.JSON(400, types.ErrorResponse{Message: "Invalid request"})
return
} else {
id = uint(idVal)
}
var dbDebt db.Debt
dbc := db.Connect()
if err := dbc.Find(&dbDebt, id).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
if dbDebt.ID == 0 {
c.JSON(500, types.ErrorResponse{Message: "DAFUQ003"})
return
}
if dbDebt.UserID != userID {
c.JSON(401, types.ErrorResponse{Message: "This debt.id is not yours, you sneaky."})
return
}
if err := dbc.Delete(dbDebt).Error; err != nil {
c.JSON(500, types.ErrorResponse{Message: err.Error()})
return
}
ret := types.DbDebt{
ID: dbDebt.ID,
CardID: dbDebt.CardID,
Comment: dbDebt.Comment,
Value: dbDebt.Value,
IOwe: dbDebt.IOwe,
Date: dbDebt.Date,
DateEnd: dbDebt.DateEnd,
Finished: dbDebt.Finished,
UserID: dbDebt.UserID,
}
c.JSON(200, ret)
} }

View File

@ -4,9 +4,9 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"git.qowevisa.me/Qowevisa/gonuts/db" "git.qowevisa.me/Qowevisa/fin-check-api/db"
"git.qowevisa.me/Qowevisa/gonuts/types" "git.qowevisa.me/Qowevisa/fin-check-api/types"
"git.qowevisa.me/Qowevisa/gonuts/utils" "git.qowevisa.me/Qowevisa/fin-check-api/utils"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -1,7 +1,7 @@
package handlers package handlers
import ( import (
"git.qowevisa.me/Qowevisa/gonuts/types" "git.qowevisa.me/Qowevisa/fin-check-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -1,8 +1,8 @@
package handlers package handlers
import ( import (
"git.qowevisa.me/Qowevisa/gonuts/db" "git.qowevisa.me/Qowevisa/fin-check-api/db"
"git.qowevisa.me/Qowevisa/gonuts/types" "git.qowevisa.me/Qowevisa/fin-check-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -3,9 +3,9 @@ package handlers
import ( import (
"log" "log"
"git.qowevisa.me/Qowevisa/gonuts/db" "git.qowevisa.me/Qowevisa/fin-check-api/db"
"git.qowevisa.me/Qowevisa/gonuts/tokens" "git.qowevisa.me/Qowevisa/fin-check-api/tokens"
"git.qowevisa.me/Qowevisa/gonuts/types" "git.qowevisa.me/Qowevisa/fin-check-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -3,8 +3,8 @@ package handlers
import ( import (
"fmt" "fmt"
"git.qowevisa.me/Qowevisa/gonuts/db" "git.qowevisa.me/Qowevisa/fin-check-api/db"
"git.qowevisa.me/Qowevisa/gonuts/types" "git.qowevisa.me/Qowevisa/fin-check-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -3,8 +3,8 @@ package middleware
import ( import (
"strings" "strings"
"git.qowevisa.me/Qowevisa/gonuts/tokens" "git.qowevisa.me/Qowevisa/fin-check-api/tokens"
"git.qowevisa.me/Qowevisa/gonuts/types" "git.qowevisa.me/Qowevisa/fin-check-api/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )

View File

@ -47,7 +47,6 @@ type DbDebt struct {
Date time.Time `json:"date" example:"29/11/2001 12:00"` Date time.Time `json:"date" example:"29/11/2001 12:00"`
DateEnd time.Time `json:"date_end" example:"29/12/2001 12:00"` DateEnd time.Time `json:"date_end" example:"29/12/2001 12:00"`
Finished bool `json:"finished" example:"false"` Finished bool `json:"finished" example:"false"`
UserID uint `json:"user_id" example:"1"`
} }
type DbIncome struct { type DbIncome struct {
@ -65,3 +64,13 @@ type DbType struct {
Comment string `json:"comment" example:""` Comment string `json:"comment" example:""`
Color string `json:"color" example:"red"` Color string `json:"color" example:"red"`
} }
type DbPayment struct {
ID uint `json:"id" example:"1"`
CardID uint `json:"card_id" example:"1"`
CategoryID uint `json:"category_id" example:"1"`
Title string `json:"title" example:"Veggies"`
Descr string `json:"description" example:""`
Note string `json:"not" example:"I'm a teapot"`
Date time.Time `json:"date" example:"29/11/2001 12:00"`
}