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" dto "github.com/Caknoooo/go-gin-clean-starter/modules/quarantine/dto" 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 GetLinesByQuarantineId(ctx context.Context, quarantineId string) ([]dtodomain.QuarantineLineResponse, 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 } // GetLinesByQuarantineId implements QuarantineService. func (s *quarantineService) GetLinesByQuarantineId(ctx context.Context, quarantineId string) ([]dtodomain.QuarantineLineResponse, error) { lines, err := s.quarantineLineRepo.GetAllByQuarantineId(ctx, quarantineId) if err != nil { return nil, err } return dto.MapQuarantineLinesToResponse(lines), nil } 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 dto.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 dto.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, dto.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 dto.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 dto.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 dto.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 dto.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 }