diff --git a/cmd/http-server/main.go b/cmd/http-server/main.go index 2f90b4f..8003c4b 100644 --- a/cmd/http-server/main.go +++ b/cmd/http-server/main.go @@ -123,6 +123,10 @@ func main() { { metricRoutes.GET("/all", handlers.MetricGetAll) } + paymentRoutes := api.Group("/payment", middleware.AuthMiddleware()) + { + paymentRoutes.POST("/add", handlers.PaymentAdd) + } } r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) diff --git a/handlers/payment.go b/handlers/payment.go new file mode 100644 index 0000000..91b8dd3 --- /dev/null +++ b/handlers/payment.go @@ -0,0 +1,146 @@ +package handlers + +import ( + "fmt" + "log" + + "git.qowevisa.me/Qowevisa/fin-check-api/db" + "git.qowevisa.me/Qowevisa/fin-check-api/types" + "github.com/gin-gonic/gin" +) + +var itemBoughtTransform func(inp *db.ItemBought) types.ItemBought = func(inp *db.ItemBought) types.ItemBought { + return types.ItemBought{} +} + +var paymentTransform func(inp *db.Payment) types.Payment = func(inp *db.Payment) types.Payment { + var items []types.ItemBought + for _, item := range inp.Items { + items = append(items, itemBoughtTransform(&item)) + } + return types.Payment{ + ID: inp.ID, + CardID: inp.CardID, + CategoryID: inp.CategoryID, + Title: inp.Title, + Description: inp.Descr, + Note: inp.Note, + Date: inp.Date, + Items: items, + } +} + +// @Summary Add payment +// @Description Add payment +// @Tags payment +// @Accept json +// @Produce json +// @Param Authorization header string true "Bearer token" +// @Param payment body types.Payment true "Payment" +// @Success 200 {object} types.Message +// @Failure 400 {object} types.ErrorResponse +// @Failure 500 {object} types.ErrorResponse +// @Security ApiKeyAuth +// @Router /payment/add [post] +func PaymentAdd(c *gin.Context) { + userID, err := GetUserID(c) + if err != nil { + c.JSON(500, types.ErrorResponse{Message: err.Error()}) + return + } + + var updates types.Payment + if err := c.ShouldBindJSON(&updates); err != nil { + log.Printf("err is %v\n", err) + c.JSON(400, types.ErrorResponse{Message: "Invalid request"}) + return + } + // As this handler will likely create more than one row in database we need to + // create some sort of defer func that will rollback all created rows + weNeedRollback := false + var deletableIfRollback []db.PaymentGroup + defer func() { + if weNeedRollback { + dbc := db.Connect() + for _, deleteIt := range deletableIfRollback { + if err := dbc.Debug().Delete(deleteIt).Error; err != nil { + log.Printf("ERROR: dbc.Delete: %v\n", err) + continue + } + } + } + }() + dbc := db.Connect() + + payment := &db.Payment{ + CardID: updates.CardID, + CategoryID: updates.CategoryID, + UserID: userID, + Title: updates.Title, + Descr: updates.Description, + Note: updates.Note, + Date: updates.Date, + } + if err := dbc.Debug().Create(payment).Error; err != nil { + c.JSON(500, types.ErrorResponse{Message: err.Error()}) + weNeedRollback = true + return + } + if payment.ID == 0 { + c.JSON(500, types.ErrorResponse{Message: "Internal error: ERR.P.A.1"}) + weNeedRollback = true + return + } + deletableIfRollback = append(deletableIfRollback, payment) + for _, uItemBought := range updates.Items { + // Creating item and adding it to rollback if itemID is set to 0 + if uItemBought.ItemID == 0 { + newItem := &db.Item{ + Name: uItemBought.NewName, + Comment: uItemBought.NewComment, + Price: uItemBought.Price, + MetricType: uItemBought.MetricType, + MetricValue: uItemBought.MetricValue, + CategoryID: updates.CategoryID, + TypeID: uItemBought.TypeID, + UserID: userID, + } + if err := dbc.Create(newItem).Error; err != nil { + c.JSON(500, types.ErrorResponse{Message: err.Error()}) + weNeedRollback = true + return + } + if newItem.ID == 0 { + c.JSON(500, types.ErrorResponse{Message: "Internal error: ERR.P.A.2"}) + weNeedRollback = true + return + } + deletableIfRollback = append(deletableIfRollback, newItem) + newItemBought := &db.ItemBought{ + ItemID: newItem.ID, + PaymentID: payment.ID, + TypeID: uItemBought.TypeID, + Quantity: uItemBought.Quantity, + TotalCost: newItem.Price * uint64(uItemBought.Quantity), + MetricType: uItemBought.MetricType, + MetricValue: uItemBought.MetricValue, + } + if err := dbc.Create(newItemBought).Error; err != nil { + c.JSON(500, types.ErrorResponse{Message: err.Error()}) + weNeedRollback = true + return + } + if newItemBought.ID == 0 { + c.JSON(500, types.ErrorResponse{Message: "Internal error: ERR.P.A.3"}) + weNeedRollback = true + return + } + deletableIfRollback = append(deletableIfRollback, newItemBought) + newItemBought.Item = newItem + } else { + // TODO: check if Item has same userID and potentially update Item + } + } + + c.JSON(200, types.Message{Info: fmt.Sprintf("Entity with %d ID is created successfully!", payment.ID)}) +}