wms-be/modules/quarantine/service/quarantine_service.go

237 lines
8.4 KiB
Go

package service
import (
"context"
"time"
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
invstoragerepository "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_storage/repository"
productrepository "github.com/Caknoooo/go-gin-clean-starter/modules/product/repository"
dtodomain "github.com/Caknoooo/go-gin-clean-starter/modules/quarantine/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/quarantine/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/quarantine/repository"
uomrepository "github.com/Caknoooo/go-gin-clean-starter/modules/uom/repository"
"github.com/google/uuid"
"gorm.io/gorm"
)
type QuarantineService interface {
Create(ctx context.Context, req dtodomain.QuarantineCreateRequest) (dtodomain.QuarantineResponse, error)
GetById(ctx context.Context, id string) (dtodomain.QuarantineResponse, error)
GetAll(ctx context.Context, filter query.QuarantineFilter) ([]dtodomain.QuarantineResponse, int64, error)
Update(ctx context.Context, req dtodomain.QuarantineUpdateRequest, id string) (dtodomain.QuarantineResponse, error)
Delete(ctx context.Context, id string) error
CreateLine(ctx context.Context, quarantineId string, req dtodomain.QuarantineLineCreateRequest) (dtodomain.QuarantineLineResponse, error)
UpdateLine(ctx context.Context, lineId string, req dtodomain.QuarantineLineUpdateRequest) (dtodomain.QuarantineLineResponse, error)
DeleteLine(ctx context.Context, lineId string) error
OnComplete(ctx context.Context, id string) (dtodomain.QuarantineResponse, error)
}
type quarantineService struct {
db *gorm.DB
quarantineRepo repository.QuarantineRepository
quarantineLineRepo repository.QuarantineLineRepository
productRepo productrepository.ProductRepository
}
func NewQuarantineService(db *gorm.DB, quarantineRepo repository.QuarantineRepository, quarantineLineRepo repository.QuarantineLineRepository, productRepo productrepository.ProductRepository, uomRepo uomrepository.UomRepository, invStorageRepository invstoragerepository.InventoryStorageRepository) QuarantineService {
return &quarantineService{
db: db,
quarantineRepo: quarantineRepo,
quarantineLineRepo: quarantineLineRepo,
productRepo: productRepo,
}
}
func (s *quarantineService) Create(ctx context.Context, req dtodomain.QuarantineCreateRequest) (dtodomain.QuarantineResponse, error) {
tx := s.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
entity := entities.TInventoryQuarantineEntity{
DocumentNumber: req.ReferenceNumber,
DocumentDate: parseDate(req.DocumentDate),
Status: req.Status,
ClientID: parseUUID(req.ClientID),
}
created, err := s.quarantineRepo.Create(ctx, tx, entity)
if err != nil {
tx.Rollback()
return dtodomain.QuarantineResponse{}, err
}
var lines []entities.TInventoryQuarantineLineEntity
for _, lineReq := range req.QuarantineLines {
line := entities.TInventoryQuarantineLineEntity{
QuarantineID: created.ID,
ProductID: parseUUID(lineReq.ProductID),
ClientID: parseUUID(lineReq.ClientID),
}
lines = append(lines, line)
}
if len(lines) > 0 {
err = s.quarantineLineRepo.BulkCreate(ctx, tx, lines)
if err != nil {
tx.Rollback()
return dtodomain.QuarantineResponse{}, err
}
}
tx.Commit()
return mapQuarantineToResponse(created, lines), nil
}
func (s *quarantineService) GetById(ctx context.Context, id string) (dtodomain.QuarantineResponse, error) {
entity, err := s.quarantineRepo.GetById(ctx, nil, id)
if err != nil {
return dtodomain.QuarantineResponse{}, err
}
lines, _ := s.quarantineLineRepo.GetAllByQuarantineId(ctx, id)
return mapQuarantineToResponse(entity, lines), nil
}
func (s *quarantineService) GetAll(ctx context.Context, filter query.QuarantineFilter) ([]dtodomain.QuarantineResponse, int64, error) {
entities, total, err := s.quarantineRepo.GetAll(ctx, filter)
if err != nil {
return nil, 0, err
}
var responses []dtodomain.QuarantineResponse
for _, entity := range entities {
lines, _ := s.quarantineLineRepo.GetAllByQuarantineId(ctx, entity.ID.String())
responses = append(responses, mapQuarantineToResponse(entity, lines))
}
return responses, total, nil
}
func (s *quarantineService) Update(ctx context.Context, req dtodomain.QuarantineUpdateRequest, id string) (dtodomain.QuarantineResponse, error) {
tx := s.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
entity, err := s.quarantineRepo.GetById(ctx, tx, id)
if err != nil {
tx.Rollback()
return dtodomain.QuarantineResponse{}, err
}
entity.DocumentNumber = req.ReferenceNumber
entity.DocumentDate = parseDate(req.DocumentDate)
entity.Status = req.Status
updated, err := s.quarantineRepo.Update(ctx, tx, entity)
if err != nil {
tx.Rollback()
return dtodomain.QuarantineResponse{}, err
}
tx.Commit()
lines, _ := s.quarantineLineRepo.GetAllByQuarantineId(ctx, id)
return mapQuarantineToResponse(updated, lines), nil
}
func (s *quarantineService) Delete(ctx context.Context, id string) error {
tx := s.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
if err := s.quarantineLineRepo.DeleteByQuarantineId(ctx, tx, id); err != nil {
tx.Rollback()
return err
}
if err := s.quarantineRepo.Delete(ctx, tx, id); err != nil {
tx.Rollback()
return err
}
tx.Commit()
return nil
}
func (s *quarantineService) CreateLine(ctx context.Context, quarantineId string, req dtodomain.QuarantineLineCreateRequest) (dtodomain.QuarantineLineResponse, error) {
line := entities.TInventoryQuarantineLineEntity{
QuarantineID: parseUUID(quarantineId),
ProductID: parseUUID(req.ProductID),
ClientID: parseUUID(req.ClientID),
}
created, err := s.quarantineLineRepo.Create(ctx, nil, line)
if err != nil {
return dtodomain.QuarantineLineResponse{}, err
}
return mapQuarantineLineToResponse(created), nil
}
func (s *quarantineService) UpdateLine(ctx context.Context, lineId string, req dtodomain.QuarantineLineUpdateRequest) (dtodomain.QuarantineLineResponse, error) {
line, err := s.quarantineLineRepo.GetById(ctx, nil, lineId)
if err != nil {
return dtodomain.QuarantineLineResponse{}, err
}
line.ProductID = parseUUID(req.ProductID)
line.ClientID = parseUUID(req.ClientID)
updated, err := s.quarantineLineRepo.Update(ctx, nil, line)
if err != nil {
return dtodomain.QuarantineLineResponse{}, err
}
return mapQuarantineLineToResponse(updated), nil
}
func (s *quarantineService) DeleteLine(ctx context.Context, lineId string) error {
return s.quarantineLineRepo.Delete(ctx, nil, lineId)
}
func (s *quarantineService) OnComplete(ctx context.Context, id string) (dtodomain.QuarantineResponse, error) {
entity, err := s.quarantineRepo.GetById(ctx, nil, id)
if err != nil {
return dtodomain.QuarantineResponse{}, err
}
entity.Status = "completed"
updated, err := s.quarantineRepo.Update(ctx, nil, entity)
if err != nil {
return dtodomain.QuarantineResponse{}, err
}
lines, _ := s.quarantineLineRepo.GetAllByQuarantineId(ctx, id)
return mapQuarantineToResponse(updated, lines), nil
}
func parseUUID(id string) uuid.UUID {
uid, _ := uuid.Parse(id)
return uid
}
func parseDate(dateStr string) time.Time {
t, _ := time.Parse("2006-01-02", dateStr)
return t
}
func mapQuarantineToResponse(entity entities.TInventoryQuarantineEntity, lines []entities.TInventoryQuarantineLineEntity) dtodomain.QuarantineResponse {
resp := dtodomain.QuarantineResponse{
ID: entity.ID.String(),
DocumentNumber: entity.DocumentNumber,
DocumentDate: entity.DocumentDate.Format("2006-01-02"),
Status: entity.Status,
WarehouseID: entity.WarehouseID.String(),
ZonaID: entity.ZonaID.String(),
ClientID: entity.ClientID.String(),
Warehouse: entity.Warehouse.Name,
Zona: entity.Zona.Name,
Client: entity.Client.Name,
}
for _, line := range lines {
resp.QuarantineLines = append(resp.QuarantineLines, mapQuarantineLineToResponse(line))
}
return resp
}
func mapQuarantineLineToResponse(line entities.TInventoryQuarantineLineEntity) dtodomain.QuarantineLineResponse {
return dtodomain.QuarantineLineResponse{
ID: line.ID.String(),
QuarantineID: line.QuarantineID.String(),
StorageID: line.StorageID.String(),
ProductID: line.ProductID.String(),
ClientID: line.ClientID.String(),
Product: line.Product.Name,
Storage: line.StorageID.String(), // gunakan StorageID, karena field Name tidak ada
Quarantine: line.Quarantine.DocumentNumber,
Client: line.Client.Name,
}
}