wms-be/modules/product/service/product_service.go

301 lines
8.2 KiB
Go

package service
import (
"context"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
"github.com/Caknoooo/go-gin-clean-starter/modules/product/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/product/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/product/repository"
"github.com/google/uuid"
"gorm.io/gorm"
)
type ProductService interface {
Create(ctx context.Context, req dto.ProductCreateRequest) (dto.ProductResponse, error)
GetById(ctx context.Context, productId string) (dto.ProductResponse, error)
GetAll(ctx context.Context, filter query.ProductFilter) ([]dto.ProductResponse, int64, error)
Update(ctx context.Context, req dto.ProductUpdateRequest, productId string) (dto.ProductResponse, error)
Delete(ctx context.Context, productId string) error
}
type productService struct {
db *gorm.DB
productRepo repository.ProductRepository
}
func NewProductService(productRepo repository.ProductRepository, db *gorm.DB) ProductService {
return &productService{
productRepo: productRepo,
db: db,
}
}
func (s *productService) Create(ctx context.Context, req dto.ProductCreateRequest) (dto.ProductResponse, error) {
tx := s.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
product := entities.MProductEntity{
Name: req.Name,
RefNumber: req.RefNumber,
SKU: req.SKU,
Description: req.Description,
Status: req.Status,
IsReturnable: req.IsReturnable,
DimLength: req.DimLength,
DimWidth: req.DimWidth,
DimHeight: req.DimHeight,
Weight: req.Weight,
Volume: req.Volume,
MaxStackHeight: req.MaxStackHeight,
Temperature: req.Temperature,
IsHazardous: req.IsHazardous,
MinStock: req.MinStock,
MaxStock: req.MaxStock,
ReplenishType: req.ReplenishType,
CycleCount: req.CycleCount,
LotRules: req.LotRules,
LeadTime: req.LeadTime,
MultiplyRate: req.MultiplyRate,
DivideRate: req.DivideRate,
}
// UUID fields
product.ClientID = parseUUID(req.ClientID)
product.CategoryID = parseUUID(req.CategoryID)
product.UomID = parseUUID(req.UomID)
product.DimUomID = parseUUID(req.DimUomID)
product.WeightUomID = parseUUID(req.WeightUomID)
product.VolumeUomID = parseUUID(req.VolumeUomID)
product.MinStockUomID = parseUUID(req.MinStockUomID)
product.MaxStockUomID = parseUUID(req.MaxStockUomID)
product.LeadTimeUomID = parseUUID(req.LeadTimeUomID)
product.UomToUomID = parseUUID(req.UomToUomID)
created, err := s.productRepo.Create(ctx, tx, product)
if err != nil {
tx.Rollback()
return dto.ProductResponse{}, err
}
err = tx.Commit().Error
if err != nil {
tx.Rollback()
return dto.ProductResponse{}, err
}
return s.GetById(ctx, created.ID.String())
}
func (s *productService) GetById(ctx context.Context, productId string) (dto.ProductResponse, error) {
product, err := s.productRepo.GetById(ctx, nil, productId)
if err != nil {
return dto.ProductResponse{}, err
}
return mapProductToResponse(product), nil
}
func (s *productService) GetAll(ctx context.Context, filter query.ProductFilter) ([]dto.ProductResponse, int64, error) {
products, total, err := s.productRepo.GetAll(ctx, filter)
if err != nil {
return nil, 0, err
}
var responses []dto.ProductResponse
for _, p := range products {
responses = append(responses, mapProductToResponse(p))
}
if len(responses) == 0 {
responses = []dto.ProductResponse{} // <-- pastikan slice kosong, bukan nil
}
return responses, total, nil
}
func (s *productService) Update(ctx context.Context, req dto.ProductUpdateRequest, productId string) (dto.ProductResponse, error) {
tx := s.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
product, err := s.productRepo.GetById(ctx, tx, productId)
if err != nil {
tx.Rollback()
return dto.ProductResponse{}, err
}
if req.Name != nil {
product.Name = *req.Name
}
if req.RefNumber != nil {
product.RefNumber = *req.RefNumber
}
if req.SKU != nil {
product.SKU = *req.SKU
}
if req.Description != nil {
product.Description = *req.Description
}
if req.Status != nil {
product.Status = *req.Status
}
if req.IsReturnable != nil {
product.IsReturnable = *req.IsReturnable
}
if req.DimLength != nil {
product.DimLength = *req.DimLength
}
if req.DimWidth != nil {
product.DimWidth = *req.DimWidth
}
if req.DimHeight != nil {
product.DimHeight = *req.DimHeight
}
if req.Weight != nil {
product.Weight = *req.Weight
}
if req.Volume != nil {
product.Volume = *req.Volume
}
if req.MaxStackHeight != nil {
product.MaxStackHeight = *req.MaxStackHeight
}
if req.Temperature != nil {
product.Temperature = *req.Temperature
}
if req.IsHazardous != nil {
product.IsHazardous = *req.IsHazardous
}
if req.MinStock != nil {
product.MinStock = *req.MinStock
}
if req.MaxStock != nil {
product.MaxStock = *req.MaxStock
}
if req.ReplenishType != nil {
product.ReplenishType = *req.ReplenishType
}
if req.CycleCount != nil {
product.CycleCount = *req.CycleCount
}
if req.LotRules != nil {
product.LotRules = *req.LotRules
}
if req.LeadTime != nil {
product.LeadTime = *req.LeadTime
}
if req.MultiplyRate != nil {
product.MultiplyRate = *req.MultiplyRate
}
if req.DivideRate != nil {
product.DivideRate = *req.DivideRate
}
if req.ClientID != nil {
product.ClientID = parseUUID(*req.ClientID)
}
if req.CategoryID != nil {
product.CategoryID = parseUUID(*req.CategoryID)
}
if req.UomID != nil {
product.UomID = parseUUID(*req.UomID)
}
if req.DimUomID != nil {
product.DimUomID = parseUUID(*req.DimUomID)
}
if req.WeightUomID != nil {
product.WeightUomID = parseUUID(*req.WeightUomID)
}
if req.VolumeUomID != nil {
product.VolumeUomID = parseUUID(*req.VolumeUomID)
}
if req.MinStockUomID != nil {
product.MinStockUomID = parseUUID(*req.MinStockUomID)
}
if req.MaxStockUomID != nil {
product.MaxStockUomID = parseUUID(*req.MaxStockUomID)
}
if req.LeadTimeUomID != nil {
product.LeadTimeUomID = parseUUID(*req.LeadTimeUomID)
}
if req.UomToUomID != nil {
product.UomToUomID = parseUUID(*req.UomToUomID)
}
updated, err := s.productRepo.Update(ctx, tx, product)
if err != nil {
tx.Rollback()
return dto.ProductResponse{}, err
}
err = tx.Commit().Error
if err != nil {
tx.Rollback()
return dto.ProductResponse{}, err
}
return s.GetById(ctx, updated.ID.String())
}
func (s *productService) Delete(ctx context.Context, productId string) error {
tx := s.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
err := s.productRepo.Delete(ctx, tx, productId)
if err != nil {
tx.Rollback()
return err
}
err = tx.Commit().Error
if err != nil {
tx.Rollback()
return err
}
return nil
}
// Helper
func parseUUID(id string) uuid.UUID {
u, err := uuid.Parse(id)
if err != nil {
return uuid.Nil
}
return u
}
func mapProductToResponse(product entities.MProductEntity) dto.ProductResponse {
return dto.ProductResponse{
ID: product.ID.String(),
Name: product.Name,
RefNumber: product.RefNumber,
SKU: product.SKU,
Description: product.Description,
Status: product.Status,
IsReturnable: product.IsReturnable,
DimLength: product.DimLength,
DimWidth: product.DimWidth,
DimHeight: product.DimHeight,
Weight: product.Weight,
Volume: product.Volume,
MaxStackHeight: product.MaxStackHeight,
Temperature: product.Temperature,
IsHazardous: product.IsHazardous,
MinStock: product.MinStock,
MaxStock: product.MaxStock,
ReplenishType: product.ReplenishType,
CycleCount: product.CycleCount,
LotRules: product.LotRules,
LeadTime: product.LeadTime,
MultiplyRate: product.MultiplyRate,
DivideRate: product.DivideRate,
ClientID: product.ClientID.String(),
CategoryID: product.CategoryID.String(),
UomID: product.UomID.String(),
DimUomID: product.DimUomID.String(),
WeightUomID: product.WeightUomID.String(),
VolumeUomID: product.VolumeUomID.String(),
MinStockUomID: product.MinStockUomID.String(),
MaxStockUomID: product.MaxStockUomID.String(),
LeadTimeUomID: product.LeadTimeUomID.String(),
UomToUomID: product.UomToUomID.String(),
}
}