package api import ( "database/sql" "errors" "fmt" "net/http" "os" "path/filepath" "time" db "git.nochill.in/nochill/naice_pos/db/sqlc" "git.nochill.in/nochill/naice_pos/token" "git.nochill.in/nochill/naice_pos/util" "github.com/gin-gonic/gin" "github.com/google/uuid" ) type createProductRequest struct { Name string `form:"name" binding:"required"` SellingPrice float64 `form:"selling_price" binding:"required"` ProductTypeID int16 `form:"product_type_id" binding:"required"` PurchasePrice float64 `form:"purchase_price" binding:"required"` ProductCategoryID string `form:"product_category_id" binding:"required"` Stock float64 `form:"stock" binding:"number"` } func (server *Server) createProduct(ctx *gin.Context) { var req createProductRequest var imagePath string file, _ := ctx.FormFile("image") if err := ctx.Bind(&req); err != nil { ctx.JSON(http.StatusBadRequest, errorResponse(err, "")) return } authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload) if file != nil { file := file fileExt := filepath.Ext(file.Filename) now := time.Now() dir := fmt.Sprintf("public/upload/images/%s/products", authPayload.MerchantID) filename := fmt.Sprintf("%s%s%s", util.RandomString(5), fmt.Sprintf("%v", now.Unix()), fileExt) imagePath = fmt.Sprintf("%s/%s", dir, filename) if _, err := os.Stat(dir); os.IsNotExist(err) { os.Mkdir(dir, 0775) } if err := ctx.SaveUploadedFile(file, fmt.Sprintf("%s", imagePath)); err != nil { ctx.JSON(http.StatusInternalServerError, errorResponse(err, "")) return } } arg := db.CreateProductParams{ MerchantID: authPayload.MerchantID, Name: req.Name, ProductTypeID: req.ProductTypeID, SellingPrice: req.SellingPrice, PurchasePrice: req.PurchasePrice, ProductCategoryID: uuid.MustParse(req.ProductCategoryID), Stock: req.Stock, Image: sql.NullString{Valid: len(imagePath) > 0, String: imagePath}, } product, err := server.store.CreateProduct(ctx, arg) if err != nil { ctx.JSON(http.StatusInternalServerError, errorResponse(err, "")) return } ctx.JSON(http.StatusOK, product) } type getProductRequest struct { ID string `uri:"id" binding:"required,uuid"` } func (server *Server) getProduct(ctx *gin.Context) { var req getProductRequest if err := ctx.ShouldBindUri(&req); err != nil { ctx.JSON(http.StatusBadRequest, errorResponse(err, "")) return } product, err := server.store.GetProduct(ctx, uuid.MustParse(req.ID)) if err != nil { if err == sql.ErrNoRows { ctx.JSON(http.StatusNotFound, errorResponse(err, "")) return } ctx.JSON(http.StatusInternalServerError, errorResponse(err, "")) return } authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload) if product.MerchantID != authPayload.MerchantID { err := errors.New("Product doesn't belong to the user") ctx.JSON(http.StatusUnauthorized, errorResponse(err, "")) return } ctx.JSON(http.StatusOK, product) } type listProductsRequest struct { PageID int32 `form:"page_id" binding:"required,min=1"` PageSize int32 `form:"page_size" binding:"required,min=5"` } func (server *Server) listProducts(ctx *gin.Context) { var req listProductsRequest if err := ctx.ShouldBindQuery(&req); err != nil { ctx.JSON(http.StatusBadRequest, errorResponse(err, "")) return } authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload) arg := db.ListProductsParams{ MerchantID: authPayload.MerchantID, Limit: req.PageSize, Offset: (req.PageID - 1) * req.PageSize, } products, err := server.store.ListProducts(ctx, arg) if err != nil { ctx.JSON(http.StatusInternalServerError, errorResponse(err, "")) return } ctx.JSON(http.StatusOK, products) } type updateProductRequest struct { ProductID uuid.UUID `form:"product_id" binding:"required"` Name string `form:"name" binding:"required"` SellingPrice float64 `form:"selling_price" binding:"required"` PurchasePrice float64 `form:"purchase_price" binding:"required"` } func (server *Server) updateProduct(ctx *gin.Context) { var req updateProductRequest var imagePath string file, _ := ctx.FormFile("image") if err := ctx.Bind(&req); err != nil { ctx.JSON(http.StatusBadRequest, errorResponse(err, "")) return } authPayload := ctx.MustGet(authorizationPayloadKey).(*token.Payload) if file != nil { file := file fileExt := filepath.Ext(file.Filename) now := time.Now() dir := fmt.Sprintf("public/upload/images/%s/products", authPayload.MerchantID) filename := fmt.Sprintf("%s%s%s", util.RandomString(5), fmt.Sprintf("%v", now.Unix()), fileExt) imagePath = fmt.Sprintf("%s/%s", dir, filename) if err := ctx.SaveUploadedFile(file, fmt.Sprintf("%s", imagePath)); err != nil { ctx.JSON(http.StatusInternalServerError, errorResponse(err, "")) return } } arg := db.UpdateProductParams{ ID: req.ProductID, Name: req.Name, SellingPrice: req.SellingPrice, PurchasePrice: req.PurchasePrice, UpdatedAt: sql.NullTime{Time: time.Now(), Valid: true}, } product, err := server.store.UpdateProduct(ctx, arg) if err != nil { if err == sql.ErrNoRows { ctx.JSON(http.StatusNotFound, errorResponse(err, "")) return } ctx.JSON(http.StatusInternalServerError, errorResponse(err, "")) return } ctx.JSON(http.StatusOK, product) }