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

322 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
AssignCrossReference(ctx context.Context, productId string, vendorIds []string) error
RemoveCrossReference(ctx context.Context, productId string, vendorIds []string) error
}
type productService struct {
db *gorm.DB
productRepo repository.ProductRepository
}
// AssignCrossReference implements ProductService.
func (s *productService) AssignCrossReference(ctx context.Context, productId string, vendorIds []string) error {
tx := s.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
err := s.productRepo.AssignCrossReference(ctx, tx, productId, vendorIds)
if err != nil {
tx.Rollback()
return err
}
if err := tx.Commit().Error; err != nil {
tx.Rollback()
return err
}
return nil
}
// RemoveCrossReference implements ProductService.
func (s *productService) RemoveCrossReference(ctx context.Context, productId string, vendorIds []string) error {
tx := s.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
err := s.productRepo.RemoveCrossReference(ctx, tx, productId, vendorIds)
if err != nil {
tx.Rollback()
return err
}
if err := tx.Commit().Error; err != nil {
tx.Rollback()
return err
}
return nil
}
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()
}
}()
refNumber, err := entities.GenerateRefNumberProduct(tx, req.ClientID, *req.CategoryID)
if err != nil {
tx.Rollback()
return dto.ProductResponse{}, err
}
product := entities.MProductEntity{
Name: req.Name,
RefNumber: 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)
if req.CategoryID != nil {
id := parseUUID(*req.CategoryID)
product.CategoryID = &id
}
if req.UomID != nil {
id := parseUUID(*req.UomID)
product.UomID = &id
}
// 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 dto.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, dto.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.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 {
id := parseUUID(*req.CategoryID)
product.CategoryID = &id
}
if req.UomID != nil {
id := parseUUID(*req.UomID)
product.UomID = &id
}
if req.DimUomID != nil {
id := parseUUID(*req.DimUomID)
product.DimUomID = &id
}
if req.WeightUomID != nil {
id := parseUUID(*req.WeightUomID)
product.WeightUomID = &id
}
if req.VolumeUomID != nil {
id := parseUUID(*req.VolumeUomID)
product.VolumeUomID = &id
}
if req.MinStockUomID != nil {
id := parseUUID(*req.MinStockUomID)
product.MinStockUomID = &id
}
if req.MaxStockUomID != nil {
id := parseUUID(*req.MaxStockUomID)
product.MaxStockUomID = &id
}
if req.LeadTimeUomID != nil {
id := parseUUID(*req.LeadTimeUomID)
product.LeadTimeUomID = &id
}
if req.UomToUomID != nil {
id := parseUUID(*req.UomToUomID)
product.UomToUomID = &id
}
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
}