feat: add feature create post product
This commit is contained in:
parent
e465ebcd6b
commit
89f0df69af
|
@ -6,7 +6,7 @@ type Product struct {
|
||||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||||
UserID string `gorm:"type:uuid;not null" json:"user_id"`
|
UserID string `gorm:"type:uuid;not null" json:"user_id"`
|
||||||
ProductTitle string `gorm:"not null" json:"product_title"`
|
ProductTitle string `gorm:"not null" json:"product_title"`
|
||||||
ProductImages []ProductImage `gorm:"foreignKey:ProductID" json:"product_images"`
|
ProductImages []ProductImage `gorm:"foreignKey:ProductID;constraint:OnDelete:CASCADE;" json:"product_images"`
|
||||||
TrashDetailID string `gorm:"type:uuid;not null" json:"trash_detail_id"`
|
TrashDetailID string `gorm:"type:uuid;not null" json:"trash_detail_id"`
|
||||||
TrashDetail TrashDetail `gorm:"foreignKey:TrashDetailID" json:"trash_detail"`
|
TrashDetail TrashDetail `gorm:"foreignKey:TrashDetailID" json:"trash_detail"`
|
||||||
SalePrice int64 `gorm:"not null" json:"sale_price"`
|
SalePrice int64 `gorm:"not null" json:"sale_price"`
|
||||||
|
|
|
@ -1,18 +1,19 @@
|
||||||
package dto
|
package dto
|
||||||
|
|
||||||
type ProductResponseDTO struct {
|
import "errors"
|
||||||
ID string `json:"id"`
|
|
||||||
UserID string `json:"user_id"`
|
|
||||||
ProductTitle string `json:"product_title"`
|
|
||||||
ProductImages []ProductImageDTO `json:"product_images"`
|
|
||||||
TrashDetail TrashDetailResponseDTO `json:"trash_detail"`
|
|
||||||
|
|
||||||
SalePrice int64 `json:"sale_price"`
|
type ProductResponseDTO struct {
|
||||||
Quantity int `json:"quantity"`
|
ID string `json:"id"`
|
||||||
ProductDescribe string `json:"product_describe"`
|
UserID string `json:"user_id"`
|
||||||
Sold int `json:"sold"`
|
ProductTitle string `json:"product_title"`
|
||||||
CreatedAt string `json:"created_at"`
|
ProductImages []ProductImageDTO `json:"product_images"`
|
||||||
UpdatedAt string `json:"updated_at"`
|
TrashDetail TrashDetailResponseDTO `json:"trash_detail"`
|
||||||
|
SalePrice int64 `json:"sale_price"`
|
||||||
|
Quantity int `json:"quantity"`
|
||||||
|
ProductDescribe string `json:"product_describe"`
|
||||||
|
Sold int `json:"sold"`
|
||||||
|
CreatedAt string `json:"created_at"`
|
||||||
|
UpdatedAt string `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProductImageDTO struct {
|
type ProductImageDTO struct {
|
||||||
|
@ -24,3 +25,30 @@ type TrashDetailResponseDTO struct {
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Price int `json:"price"`
|
Price int `json:"price"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CreateProductRequestDTO struct {
|
||||||
|
ProductTitle string `json:"product_title" validate:"required,min=3,max=255"`
|
||||||
|
ProductImages []string `json:"product_images" validate:"required,min=1,dive,url"`
|
||||||
|
TrashDetailID string `json:"trash_detail_id" validate:"required,uuid"`
|
||||||
|
SalePrice int64 `json:"sale_price" validate:"required,gt=0"`
|
||||||
|
Quantity int `json:"quantity" validate:"required,gt=0"`
|
||||||
|
ProductDescribe string `json:"product_describe,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateProductResponseDTO struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
UserID string `json:"user_id"`
|
||||||
|
ProductTitle string `json:"product_title"`
|
||||||
|
ProductImages []string `json:"product_images"`
|
||||||
|
TrashDetailID string `json:"trash_detail_id"`
|
||||||
|
SalePrice int64 `json:"sale_price"`
|
||||||
|
Quantity int `json:"quantity"`
|
||||||
|
ProductDescribe string `json:"product_describe,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateSalePrice(marketPrice, salePrice int64) error {
|
||||||
|
if salePrice > marketPrice {
|
||||||
|
return errors.New("sale price cannot be greater than market price")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -3,3 +3,7 @@ package dto
|
||||||
import "github.com/go-playground/validator/v10"
|
import "github.com/go-playground/validator/v10"
|
||||||
|
|
||||||
var validate = validator.New()
|
var validate = validator.New()
|
||||||
|
|
||||||
|
func GetValidator() *validator.Validate {
|
||||||
|
return validate
|
||||||
|
}
|
||||||
|
|
|
@ -102,11 +102,12 @@ func AppRouter(app *fiber.App) {
|
||||||
api.Get("/wilayah-indonesia/villages/:id", controllers.GetVillageByID)
|
api.Get("/wilayah-indonesia/villages/:id", controllers.GetVillageByID)
|
||||||
|
|
||||||
// # request pickup by user (masyarakat) #
|
// # request pickup by user (masyarakat) #
|
||||||
api.Get("/requestpickup", middleware.RoleRequired(utils.RoleMasyarakat), controllers.GetRequestPickupsByUser)
|
api.Get("/requestpickup", middleware.RoleRequired(utils.RoleMasyarakat, utils.RolePengepul), controllers.GetRequestPickupsByUser)
|
||||||
api.Post("/addrequestpickup", middleware.RoleRequired(utils.RoleMasyarakat), controllers.CreateRequestPickup)
|
api.Post("/addrequestpickup", middleware.RoleRequired(utils.RoleMasyarakat), controllers.CreateRequestPickup)
|
||||||
api.Delete("/deleterequestpickup/:id", middleware.RoleRequired(utils.RoleMasyarakat), controllers.DeleteRequestPickup)
|
api.Delete("/deleterequestpickup/:id", middleware.RoleRequired(utils.RoleMasyarakat), controllers.DeleteRequestPickup)
|
||||||
|
|
||||||
// # product post by pengepul
|
// # product post by pengepul
|
||||||
api.Get("/post/products", middleware.RoleRequired(utils.RolePengepul), controllers.GetAllProducts)
|
api.Get("/post/products", middleware.RoleRequired(utils.RolePengepul), controllers.GetAllProducts)
|
||||||
api.Get("/post/product/:productid", middleware.RoleRequired(utils.RolePengepul), controllers.GetProductByID)
|
api.Get("/post/product/:productid", middleware.RoleRequired(utils.RolePengepul), controllers.GetProductByID)
|
||||||
|
api.Post("/post/addproduct", middleware.RoleRequired(utils.RolePengepul), controllers.CreateProduct)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,15 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetAllProducts(c *fiber.Ctx) error {
|
func GetAllProducts(c *fiber.Ctx) error {
|
||||||
|
userID, ok := c.Locals("userID").(string)
|
||||||
|
if !ok || userID == "" {
|
||||||
|
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusUnauthorized,
|
||||||
|
"Unauthorized: user ID is missing",
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
limit := c.QueryInt("limit", 0)
|
limit := c.QueryInt("limit", 0)
|
||||||
page := c.QueryInt("page", 1)
|
page := c.QueryInt("page", 1)
|
||||||
|
|
||||||
|
@ -19,15 +28,7 @@ func GetAllProducts(c *fiber.Ctx) error {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
var products []dto.ProductResponseDTO
|
products, err := services.GetProductsByUserID(userID, limit, page)
|
||||||
var err error
|
|
||||||
|
|
||||||
if limit == 0 {
|
|
||||||
products, err = services.GetProducts(0, 0)
|
|
||||||
} else {
|
|
||||||
products, err = services.GetProducts(limit, page)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
return c.Status(fiber.StatusInternalServerError).JSON(utils.FormatResponse(
|
||||||
fiber.StatusInternalServerError,
|
fiber.StatusInternalServerError,
|
||||||
|
@ -44,6 +45,15 @@ func GetAllProducts(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetProductByID(c *fiber.Ctx) error {
|
func GetProductByID(c *fiber.Ctx) error {
|
||||||
|
userID, ok := c.Locals("userID").(string)
|
||||||
|
if !ok || userID == "" {
|
||||||
|
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusUnauthorized,
|
||||||
|
"Unauthorized: user ID is missing",
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
productID := c.Params("productid")
|
productID := c.Params("productid")
|
||||||
if productID == "" {
|
if productID == "" {
|
||||||
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||||
|
@ -53,7 +63,7 @@ func GetProductByID(c *fiber.Ctx) error {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
product, err := services.GetProductByID(productID)
|
product, err := services.GetProductByIDAndUserID(productID, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
return c.Status(fiber.StatusNotFound).JSON(utils.FormatResponse(
|
||||||
fiber.StatusNotFound,
|
fiber.StatusNotFound,
|
||||||
|
@ -68,3 +78,38 @@ func GetProductByID(c *fiber.Ctx) error {
|
||||||
product,
|
product,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateProduct(c *fiber.Ctx) error {
|
||||||
|
var input dto.CreateProductRequestDTO
|
||||||
|
if err := c.BodyParser(&input); err != nil {
|
||||||
|
return c.Status(fiber.StatusBadRequest).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusBadRequest,
|
||||||
|
"lengkapi data dengan benar",
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
userID, ok := c.Locals("userID").(string)
|
||||||
|
if !ok || userID == "" {
|
||||||
|
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusUnauthorized,
|
||||||
|
"Unauthorized: user ID is missing",
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
product, err := services.CreateProduct(input, userID)
|
||||||
|
if err != nil {
|
||||||
|
return c.Status(fiber.StatusUnprocessableEntity).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusUnprocessableEntity,
|
||||||
|
err.Error(),
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Status(fiber.StatusCreated).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusCreated,
|
||||||
|
"Product created successfully",
|
||||||
|
product,
|
||||||
|
))
|
||||||
|
}
|
|
@ -12,7 +12,6 @@ import (
|
||||||
|
|
||||||
func RoleRequired(roles ...string) fiber.Handler {
|
func RoleRequired(roles ...string) fiber.Handler {
|
||||||
return func(c *fiber.Ctx) error {
|
return func(c *fiber.Ctx) error {
|
||||||
|
|
||||||
tokenString := c.Get("Authorization")
|
tokenString := c.Get("Authorization")
|
||||||
if tokenString == "" {
|
if tokenString == "" {
|
||||||
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||||
|
@ -47,7 +46,26 @@ func RoleRequired(roles ...string) fiber.Handler {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
role := claims["role"].(string)
|
userID, ok := claims["sub"].(string)
|
||||||
|
if !ok || userID == "" {
|
||||||
|
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusUnauthorized,
|
||||||
|
"Invalid or missing user ID in token",
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
role, ok := claims["role"].(string)
|
||||||
|
if !ok || role == "" {
|
||||||
|
return c.Status(fiber.StatusUnauthorized).JSON(utils.FormatResponse(
|
||||||
|
fiber.StatusUnauthorized,
|
||||||
|
"Invalid or missing role in token",
|
||||||
|
nil,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Locals("userID", userID)
|
||||||
|
c.Locals("role", role)
|
||||||
|
|
||||||
for _, r := range roles {
|
for _, r := range roles {
|
||||||
if r == role {
|
if r == role {
|
||||||
|
|
|
@ -3,28 +3,46 @@ package repositories
|
||||||
import (
|
import (
|
||||||
"github.com/pahmiudahgede/senggoldong/config"
|
"github.com/pahmiudahgede/senggoldong/config"
|
||||||
"github.com/pahmiudahgede/senggoldong/domain"
|
"github.com/pahmiudahgede/senggoldong/domain"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetAllProducts(limit, offset int) ([]domain.Product, error) {
|
func GetProductsByUserID(userID string, limit, offset int) ([]domain.Product, error) {
|
||||||
var products []domain.Product
|
var products []domain.Product
|
||||||
|
query := config.DB.Preload("ProductImages").Preload("TrashDetail").Where("user_id = ?", userID)
|
||||||
|
|
||||||
query := config.DB.Preload("ProductImages").Preload("TrashDetail")
|
|
||||||
if limit > 0 {
|
if limit > 0 {
|
||||||
query = query.Limit(limit).Offset(offset)
|
query = query.Limit(limit).Offset(offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := query.Find(&products).Error
|
err := query.Find(&products).Error
|
||||||
if err != nil {
|
return products, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return products, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetProductByID(productID string) (domain.Product, error) {
|
func GetProductByIDAndUserID(productID, userID string) (domain.Product, error) {
|
||||||
var product domain.Product
|
var product domain.Product
|
||||||
err := config.DB.Preload("ProductImages").Preload("TrashDetail").Where("id = ?", productID).First(&product).Error
|
err := config.DB.Preload("ProductImages").Preload("TrashDetail").
|
||||||
if err != nil {
|
Where("id = ? AND user_id = ?", productID, userID).
|
||||||
return domain.Product{}, err
|
First(&product).Error
|
||||||
}
|
|
||||||
return product, nil
|
return product, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateProduct(product *domain.Product, images []domain.ProductImage) error {
|
||||||
|
err := config.DB.Transaction(func(tx *gorm.DB) error {
|
||||||
|
|
||||||
|
if err := tx.Create(product).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(images) > 0 {
|
||||||
|
for i := range images {
|
||||||
|
images[i].ProductID = product.ID
|
||||||
|
}
|
||||||
|
if err := tx.Create(&images).Error; err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/pahmiudahgede/senggoldong/domain"
|
||||||
"github.com/pahmiudahgede/senggoldong/dto"
|
"github.com/pahmiudahgede/senggoldong/dto"
|
||||||
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
"github.com/pahmiudahgede/senggoldong/internal/repositories"
|
||||||
"github.com/pahmiudahgede/senggoldong/utils"
|
"github.com/pahmiudahgede/senggoldong/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetProducts(limit, page int) ([]dto.ProductResponseDTO, error) {
|
func GetProductsByUserID(userID string, limit, page int) ([]dto.ProductResponseDTO, error) {
|
||||||
offset := (page - 1) * limit
|
offset := (page - 1) * limit
|
||||||
|
products, err := repositories.GetProductsByUserID(userID, limit, offset)
|
||||||
products, err := repositories.GetAllProducts(limit, offset)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -21,18 +21,16 @@ func GetProducts(limit, page int) ([]dto.ProductResponseDTO, error) {
|
||||||
images = append(images, dto.ProductImageDTO{ImageURL: img.ImageURL})
|
images = append(images, dto.ProductImageDTO{ImageURL: img.ImageURL})
|
||||||
}
|
}
|
||||||
|
|
||||||
trashDetail := dto.TrashDetailResponseDTO{
|
|
||||||
ID: product.TrashDetail.ID,
|
|
||||||
Description: product.TrashDetail.Description,
|
|
||||||
Price: product.TrashDetail.Price,
|
|
||||||
}
|
|
||||||
|
|
||||||
productResponses = append(productResponses, dto.ProductResponseDTO{
|
productResponses = append(productResponses, dto.ProductResponseDTO{
|
||||||
ID: product.ID,
|
ID: product.ID,
|
||||||
UserID: product.UserID,
|
UserID: product.UserID,
|
||||||
ProductTitle: product.ProductTitle,
|
ProductTitle: product.ProductTitle,
|
||||||
ProductImages: images,
|
ProductImages: images,
|
||||||
TrashDetail: trashDetail,
|
TrashDetail: dto.TrashDetailResponseDTO{
|
||||||
|
ID: product.TrashDetail.ID,
|
||||||
|
Description: product.TrashDetail.Description,
|
||||||
|
Price: product.TrashDetail.Price,
|
||||||
|
},
|
||||||
SalePrice: product.SalePrice,
|
SalePrice: product.SalePrice,
|
||||||
Quantity: product.Quantity,
|
Quantity: product.Quantity,
|
||||||
ProductDescribe: product.ProductDescribe,
|
ProductDescribe: product.ProductDescribe,
|
||||||
|
@ -45,8 +43,8 @@ func GetProducts(limit, page int) ([]dto.ProductResponseDTO, error) {
|
||||||
return productResponses, nil
|
return productResponses, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetProductByID(productID string) (dto.ProductResponseDTO, error) {
|
func GetProductByIDAndUserID(productID, userID string) (dto.ProductResponseDTO, error) {
|
||||||
product, err := repositories.GetProductByID(productID)
|
product, err := repositories.GetProductByIDAndUserID(productID, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return dto.ProductResponseDTO{}, err
|
return dto.ProductResponseDTO{}, err
|
||||||
}
|
}
|
||||||
|
@ -56,25 +54,56 @@ func GetProductByID(productID string) (dto.ProductResponseDTO, error) {
|
||||||
images = append(images, dto.ProductImageDTO{ImageURL: img.ImageURL})
|
images = append(images, dto.ProductImageDTO{ImageURL: img.ImageURL})
|
||||||
}
|
}
|
||||||
|
|
||||||
trashDetail := dto.TrashDetailResponseDTO{
|
return dto.ProductResponseDTO{
|
||||||
ID: product.TrashDetail.ID,
|
ID: product.ID,
|
||||||
Description: product.TrashDetail.Description,
|
UserID: product.UserID,
|
||||||
Price: product.TrashDetail.Price,
|
ProductTitle: product.ProductTitle,
|
||||||
}
|
ProductImages: images,
|
||||||
|
TrashDetail: dto.TrashDetailResponseDTO{
|
||||||
productResponse := dto.ProductResponseDTO{
|
ID: product.TrashDetail.ID,
|
||||||
ID: product.ID,
|
Description: product.TrashDetail.Description,
|
||||||
UserID: product.UserID,
|
Price: product.TrashDetail.Price,
|
||||||
ProductTitle: product.ProductTitle,
|
},
|
||||||
ProductImages: images,
|
|
||||||
TrashDetail: trashDetail,
|
|
||||||
SalePrice: product.SalePrice,
|
SalePrice: product.SalePrice,
|
||||||
Quantity: product.Quantity,
|
Quantity: product.Quantity,
|
||||||
ProductDescribe: product.ProductDescribe,
|
ProductDescribe: product.ProductDescribe,
|
||||||
Sold: product.Sold,
|
Sold: product.Sold,
|
||||||
CreatedAt: utils.FormatDateToIndonesianFormat(product.CreatedAt),
|
CreatedAt: utils.FormatDateToIndonesianFormat(product.CreatedAt),
|
||||||
UpdatedAt: utils.FormatDateToIndonesianFormat(product.UpdatedAt),
|
UpdatedAt: utils.FormatDateToIndonesianFormat(product.UpdatedAt),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateProduct(input dto.CreateProductRequestDTO, userID string) (dto.CreateProductResponseDTO, error) {
|
||||||
|
if err := dto.GetValidator().Struct(input); err != nil {
|
||||||
|
return dto.CreateProductResponseDTO{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return productResponse, nil
|
product := &domain.Product{
|
||||||
|
UserID: userID,
|
||||||
|
ProductTitle: input.ProductTitle,
|
||||||
|
TrashDetailID: input.TrashDetailID,
|
||||||
|
SalePrice: input.SalePrice,
|
||||||
|
Quantity: input.Quantity,
|
||||||
|
ProductDescribe: input.ProductDescribe,
|
||||||
|
}
|
||||||
|
|
||||||
|
var images []domain.ProductImage
|
||||||
|
for _, imageURL := range input.ProductImages {
|
||||||
|
images = append(images, domain.ProductImage{ImageURL: imageURL})
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := repositories.CreateProduct(product, images); err != nil {
|
||||||
|
return dto.CreateProductResponseDTO{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return dto.CreateProductResponseDTO{
|
||||||
|
ID: product.ID,
|
||||||
|
UserID: product.UserID,
|
||||||
|
ProductTitle: product.ProductTitle,
|
||||||
|
ProductImages: input.ProductImages,
|
||||||
|
TrashDetailID: product.TrashDetailID,
|
||||||
|
SalePrice: product.SalePrice,
|
||||||
|
Quantity: product.Quantity,
|
||||||
|
ProductDescribe: product.ProductDescribe,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue