add product image
This commit is contained in:
parent
9ebacf85aa
commit
c7422da71a
3
.gitignore
vendored
3
.gitignore
vendored
@ -1 +1,2 @@
|
||||
*.env
|
||||
*.env
|
||||
public
|
@ -3,33 +3,59 @@ 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 `json:"name" binding:"required"`
|
||||
SellingPrice float64 `json:"selling_price" binding:"required"`
|
||||
ProductTypeID int16 `json:"product_type_id" binding:"required"`
|
||||
PurchasePrice float64 `json:"purchase_price" binding:"required"`
|
||||
ProductCategoryID string `json:"product_category_id" binding:"required"`
|
||||
Stock float64 `json:"stock" binding:"number"`
|
||||
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
|
||||
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
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,
|
||||
@ -38,6 +64,7 @@ func (server *Server) createProduct(ctx *gin.Context) {
|
||||
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)
|
||||
@ -109,19 +136,38 @@ func (server *Server) listProducts(ctx *gin.Context) {
|
||||
}
|
||||
|
||||
type updateProductRequest struct {
|
||||
ProductID uuid.UUID `json:"product_id" binding:"required"`
|
||||
Name string `json:"name" binding:"required"`
|
||||
SellingPrice float64 `json:"selling_price" binding:"required"`
|
||||
PurchasePrice float64 `json:"purchase_price" binding:"required"`
|
||||
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
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
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,
|
||||
|
@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
db "git.nochill.in/nochill/naice_pos/db/sqlc"
|
||||
"git.nochill.in/nochill/naice_pos/token"
|
||||
@ -37,6 +38,7 @@ func (server *Server) getRoutes() {
|
||||
router.POST("/user/login", server.loginUser)
|
||||
router.POST("/user/merchants", server.createUserMerchant)
|
||||
router.POST("/user/renew_token", server.renewAccessToken)
|
||||
router.Static("/public", filepath.Base("public"))
|
||||
|
||||
apiRoutes := router.Group("/api").Use(authMiddleware(server.tokenMaker))
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
ALTER TABLE product DROP COLUMN IF EXISTS image;
|
@ -0,0 +1 @@
|
||||
ALTER TABLE products ADD COLUMN image text;
|
@ -6,9 +6,10 @@ INSERT INTO products (
|
||||
product_type_id,
|
||||
purchase_price,
|
||||
product_category_id,
|
||||
image,
|
||||
stock
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7
|
||||
$1, $2, $3, $4, $5, $6, $7, $8
|
||||
)
|
||||
RETURNING *;
|
||||
|
||||
@ -36,7 +37,12 @@ OFFSET $3;
|
||||
|
||||
-- name: UpdateProduct :one
|
||||
UPDATE products
|
||||
SET name = $2, selling_price = $3, purchase_price = $4, product_category_id = $5, updated_at = $6
|
||||
SET name = $2,
|
||||
selling_price = $3,
|
||||
purchase_price = $4,
|
||||
product_category_id = $5,
|
||||
image = $6,
|
||||
updated_at = $7
|
||||
WHERE id = $1
|
||||
RETURNING *;
|
||||
|
||||
|
@ -77,17 +77,18 @@ type Merchant struct {
|
||||
}
|
||||
|
||||
type Product struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
ProductTypeID int16 `json:"product_type_id"`
|
||||
IndexID int64 `json:"index_id"`
|
||||
Name string `json:"name"`
|
||||
SellingPrice float64 `json:"selling_price"`
|
||||
PurchasePrice float64 `json:"purchase_price"`
|
||||
Stock float64 `json:"stock"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
ProductCategoryID uuid.UUID `json:"product_category_id"`
|
||||
ID uuid.UUID `json:"id"`
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
ProductTypeID int16 `json:"product_type_id"`
|
||||
IndexID int64 `json:"index_id"`
|
||||
Name string `json:"name"`
|
||||
SellingPrice float64 `json:"selling_price"`
|
||||
PurchasePrice float64 `json:"purchase_price"`
|
||||
Stock float64 `json:"stock"`
|
||||
CreatedAt sql.NullTime `json:"created_at"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
ProductCategoryID uuid.UUID `json:"product_category_id"`
|
||||
Image sql.NullString `json:"image"`
|
||||
}
|
||||
|
||||
type ProductCategory struct {
|
||||
|
@ -20,21 +20,23 @@ INSERT INTO products (
|
||||
product_type_id,
|
||||
purchase_price,
|
||||
product_category_id,
|
||||
image,
|
||||
stock
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7
|
||||
$1, $2, $3, $4, $5, $6, $7, $8
|
||||
)
|
||||
RETURNING id, merchant_id, product_type_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at, product_category_id
|
||||
RETURNING id, merchant_id, product_type_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at, product_category_id, image
|
||||
`
|
||||
|
||||
type CreateProductParams struct {
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
Name string `json:"name"`
|
||||
SellingPrice float64 `json:"selling_price"`
|
||||
ProductTypeID int16 `json:"product_type_id"`
|
||||
PurchasePrice float64 `json:"purchase_price"`
|
||||
ProductCategoryID uuid.UUID `json:"product_category_id"`
|
||||
Stock float64 `json:"stock"`
|
||||
MerchantID uuid.UUID `json:"merchant_id"`
|
||||
Name string `json:"name"`
|
||||
SellingPrice float64 `json:"selling_price"`
|
||||
ProductTypeID int16 `json:"product_type_id"`
|
||||
PurchasePrice float64 `json:"purchase_price"`
|
||||
ProductCategoryID uuid.UUID `json:"product_category_id"`
|
||||
Image sql.NullString `json:"image"`
|
||||
Stock float64 `json:"stock"`
|
||||
}
|
||||
|
||||
func (q *Queries) CreateProduct(ctx context.Context, arg CreateProductParams) (Product, error) {
|
||||
@ -45,6 +47,7 @@ func (q *Queries) CreateProduct(ctx context.Context, arg CreateProductParams) (P
|
||||
arg.ProductTypeID,
|
||||
arg.PurchasePrice,
|
||||
arg.ProductCategoryID,
|
||||
arg.Image,
|
||||
arg.Stock,
|
||||
)
|
||||
var i Product
|
||||
@ -60,6 +63,7 @@ func (q *Queries) CreateProduct(ctx context.Context, arg CreateProductParams) (P
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ProductCategoryID,
|
||||
&i.Image,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
@ -74,7 +78,7 @@ func (q *Queries) DeleteProduct(ctx context.Context, id uuid.UUID) error {
|
||||
}
|
||||
|
||||
const getProduct = `-- name: GetProduct :one
|
||||
SELECT id, merchant_id, product_type_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at, product_category_id FROM products
|
||||
SELECT id, merchant_id, product_type_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at, product_category_id, image FROM products
|
||||
WHERE id = $1
|
||||
`
|
||||
|
||||
@ -93,12 +97,13 @@ func (q *Queries) GetProduct(ctx context.Context, id uuid.UUID) (Product, error)
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ProductCategoryID,
|
||||
&i.Image,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getStockForUpdateStock = `-- name: GetStockForUpdateStock :one
|
||||
SELECT id, merchant_id, product_type_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at, product_category_id FROM products
|
||||
SELECT id, merchant_id, product_type_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at, product_category_id, image FROM products
|
||||
WHERE id = $1
|
||||
LIMIT 1
|
||||
FOR NO KEY UPDATE
|
||||
@ -119,12 +124,13 @@ func (q *Queries) GetStockForUpdateStock(ctx context.Context, id uuid.UUID) (Pro
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ProductCategoryID,
|
||||
&i.Image,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listProducts = `-- name: ListProducts :many
|
||||
SELECT id, merchant_id, product_type_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at, product_category_id FROM products
|
||||
SELECT id, merchant_id, product_type_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at, product_category_id, image FROM products
|
||||
WHERE merchant_id = $1
|
||||
ORDER BY index_id
|
||||
LIMIT $2
|
||||
@ -158,6 +164,7 @@ func (q *Queries) ListProducts(ctx context.Context, arg ListProductsParams) ([]P
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ProductCategoryID,
|
||||
&i.Image,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -174,18 +181,24 @@ func (q *Queries) ListProducts(ctx context.Context, arg ListProductsParams) ([]P
|
||||
|
||||
const updateProduct = `-- name: UpdateProduct :one
|
||||
UPDATE products
|
||||
SET name = $2, selling_price = $3, purchase_price = $4, product_category_id = $5, updated_at = $6
|
||||
SET name = $2,
|
||||
selling_price = $3,
|
||||
purchase_price = $4,
|
||||
product_category_id = $5,
|
||||
image = $6,
|
||||
updated_at = $7
|
||||
WHERE id = $1
|
||||
RETURNING id, merchant_id, product_type_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at, product_category_id
|
||||
RETURNING id, merchant_id, product_type_id, index_id, name, selling_price, purchase_price, stock, created_at, updated_at, product_category_id, image
|
||||
`
|
||||
|
||||
type UpdateProductParams struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SellingPrice float64 `json:"selling_price"`
|
||||
PurchasePrice float64 `json:"purchase_price"`
|
||||
ProductCategoryID uuid.UUID `json:"product_category_id"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
ID uuid.UUID `json:"id"`
|
||||
Name string `json:"name"`
|
||||
SellingPrice float64 `json:"selling_price"`
|
||||
PurchasePrice float64 `json:"purchase_price"`
|
||||
ProductCategoryID uuid.UUID `json:"product_category_id"`
|
||||
Image sql.NullString `json:"image"`
|
||||
UpdatedAt sql.NullTime `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateProduct(ctx context.Context, arg UpdateProductParams) (Product, error) {
|
||||
@ -195,6 +208,7 @@ func (q *Queries) UpdateProduct(ctx context.Context, arg UpdateProductParams) (P
|
||||
arg.SellingPrice,
|
||||
arg.PurchasePrice,
|
||||
arg.ProductCategoryID,
|
||||
arg.Image,
|
||||
arg.UpdatedAt,
|
||||
)
|
||||
var i Product
|
||||
@ -210,6 +224,7 @@ func (q *Queries) UpdateProduct(ctx context.Context, arg UpdateProductParams) (P
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.ProductCategoryID,
|
||||
&i.Image,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ func createRandomProduct(t *testing.T) (Product, CreateProductParams) {
|
||||
PurchasePrice: purchasePrice,
|
||||
ProductCategoryID: productCategory.ID,
|
||||
Stock: stock,
|
||||
Image: sql.NullString{Valid: false},
|
||||
}
|
||||
|
||||
product, err := testQueries.CreateProduct(context.Background(), arg)
|
||||
|
Loading…
Reference in New Issue
Block a user