package service import ( "context" "github.com/Caknoooo/go-gin-clean-starter/database/entities" dtodomain "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_movement/dto" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_movement/query" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_movement/repository" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/google/uuid" "gorm.io/gorm" ) type InventoryMovementService interface { Create(ctx context.Context, req dtodomain.InventoryMovementCreateRequest) (dtodomain.InventoryMovementResponse, error) GetById(ctx context.Context, id string) (dtodomain.InventoryMovementResponse, error) GetAll(ctx context.Context, filter query.InventoryMovementFilter) ([]dtodomain.InventoryMovementResponse, int64, error) Update(ctx context.Context, req dtodomain.InventoryMovementUpdateRequest, id string) (dtodomain.InventoryMovementResponse, error) Delete(ctx context.Context, id string) error CreateLine(ctx context.Context, movementId string, req dtodomain.InventoryMovementLineCreateRequest) (dtodomain.InventoryMovementLineResponse, error) UpdateLine(ctx context.Context, lineId string, req dtodomain.InventoryMovementLineUpdateRequest) (dtodomain.InventoryMovementLineResponse, error) DeleteLine(ctx context.Context, lineId string) error } type inventoryMovementService struct { db *gorm.DB movementRepo repository.InventoryMovementRepository movementLineRepo repository.InventoryMovementLineRepository } func (s *inventoryMovementService) Create(ctx context.Context, req dtodomain.InventoryMovementCreateRequest) (dtodomain.InventoryMovementResponse, error) { tx := s.db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() clientUUID, err := uuid.Parse(req.ClientID) if err != nil { tx.Rollback() return dtodomain.InventoryMovementResponse{}, err } movNumber, err := entities.GenerateDocumentNumberInvMovement(s.db, req.ClientID) if err != nil { tx.Rollback() return dtodomain.InventoryMovementResponse{}, err } movement := entities.TInventoryMovementEntity{ MovementNumber: movNumber, MovementDate: utils.StringToDateTime(req.MovementDate), MovementType: req.MovementType, ClientID: clientUUID, Status: req.Status, SourceLocationID: uuid.MustParse(req.SourceLocationID), DestinationLocationID: uuid.MustParse(req.DestinationLocationID), } created, err := s.movementRepo.Create(ctx, tx, movement) if err != nil { tx.Rollback() return dtodomain.InventoryMovementResponse{}, err } // Bulk create lines var lines []entities.TInventoryMovementLineEntity for _, lineReq := range req.MovementLines { productUUID := uuid.Nil if lineReq.ProductID != "" { productUUID, err = uuid.Parse(lineReq.ProductID) if err != nil { tx.Rollback() return dtodomain.InventoryMovementResponse{}, err } } clientLineUUID, err := uuid.Parse(lineReq.ClientID) if err != nil { tx.Rollback() return dtodomain.InventoryMovementResponse{}, err } lines = append(lines, entities.TInventoryMovementLineEntity{ MovedQuantity: lineReq.MovedQuantity, InvMovementID: created.ID, ProductID: productUUID, StorageID: uuid.MustParse(lineReq.StorageID), ClientID: clientLineUUID, Status: lineReq.Status, }) } if len(lines) > 0 { err = s.movementLineRepo.BulkCreate(ctx, tx, lines) if err != nil { tx.Rollback() return dtodomain.InventoryMovementResponse{}, err } } tx.Commit() result, err := s.movementRepo.GetById(ctx, nil, created.ID.String()) if err != nil { return dtodomain.InventoryMovementResponse{}, err } return dtodomain.ToInventoryMovementResponse(result), nil } func (s *inventoryMovementService) GetById(ctx context.Context, id string) (dtodomain.InventoryMovementResponse, error) { movement, err := s.movementRepo.GetById(ctx, nil, id) if err != nil { return dtodomain.InventoryMovementResponse{}, err } return dtodomain.ToInventoryMovementResponse(movement), nil } func (s *inventoryMovementService) GetAll(ctx context.Context, filter query.InventoryMovementFilter) ([]dtodomain.InventoryMovementResponse, int64, error) { movements, total, err := s.movementRepo.GetAll(ctx, filter) if err != nil { return nil, 0, err } var responses []dtodomain.InventoryMovementResponse for _, e := range movements { responses = append(responses, dtodomain.ToInventoryMovementResponse(e)) } if responses == nil { responses = make([]dtodomain.InventoryMovementResponse, 0) } return responses, total, nil } func (s *inventoryMovementService) Update(ctx context.Context, req dtodomain.InventoryMovementUpdateRequest, id string) (dtodomain.InventoryMovementResponse, error) { tx := s.db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() movement, err := s.movementRepo.GetById(ctx, tx, id) if err != nil { tx.Rollback() return dtodomain.InventoryMovementResponse{}, err } // if req.MovementNumber != "" { // movement.MovementNumber = req.MovementNumber // } movement.MovementDate = utils.StringToDateTime(req.MovementDate) movement.MovementType = req.MovementType movement.Status = req.Status updated, err := s.movementRepo.Update(ctx, tx, movement) if err != nil { tx.Rollback() return dtodomain.InventoryMovementResponse{}, err } tx.Commit() result, err := s.movementRepo.GetById(ctx, nil, updated.ID.String()) if err != nil { return dtodomain.InventoryMovementResponse{}, err } return dtodomain.ToInventoryMovementResponse(result), nil } func (s *inventoryMovementService) Delete(ctx context.Context, id string) error { tx := s.db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() if err := s.movementRepo.Delete(ctx, tx, id); err != nil { tx.Rollback() return err } tx.Commit() return nil } func (s *inventoryMovementService) CreateLine(ctx context.Context, movementId string, req dtodomain.InventoryMovementLineCreateRequest) (dtodomain.InventoryMovementLineResponse, error) { movementUUID, err := uuid.Parse(movementId) if err != nil { return dtodomain.InventoryMovementLineResponse{}, err } productUUID := uuid.Nil if req.ProductID != "" { productUUID, err = uuid.Parse(req.ProductID) if err != nil { return dtodomain.InventoryMovementLineResponse{}, err } } clientLineUUID, err := uuid.Parse(req.ClientID) if err != nil { return dtodomain.InventoryMovementLineResponse{}, err } line := entities.TInventoryMovementLineEntity{ MovedQuantity: req.MovedQuantity, InvMovementID: movementUUID, ProductID: productUUID, StorageID: uuid.MustParse(req.StorageID), ClientID: clientLineUUID, Status: req.Status, } created, err := s.movementLineRepo.Create(ctx, nil, line) if err != nil { return dtodomain.InventoryMovementLineResponse{}, err } return dtodomain.ToInventoryMovementLineResponse(created), nil } func (s *inventoryMovementService) UpdateLine(ctx context.Context, lineId string, req dtodomain.InventoryMovementLineUpdateRequest) (dtodomain.InventoryMovementLineResponse, error) { line, err := s.movementLineRepo.GetById(ctx, nil, lineId) if err != nil { return dtodomain.InventoryMovementLineResponse{}, err } if req.MovedQuantity != nil { line.MovedQuantity = *req.MovedQuantity } if req.Status != nil { line.Status = *req.Status } updated, err := s.movementLineRepo.Update(ctx, nil, line) if err != nil { return dtodomain.InventoryMovementLineResponse{}, err } return dtodomain.ToInventoryMovementLineResponse(updated), nil } func (s *inventoryMovementService) DeleteLine(ctx context.Context, lineId string) error { return s.movementLineRepo.Delete(ctx, nil, lineId) } func NewInventoryMovementService(db *gorm.DB, movementRepo repository.InventoryMovementRepository, movementLineRepo repository.InventoryMovementLineRepository) InventoryMovementService { return &inventoryMovementService{ db: db, movementRepo: movementRepo, movementLineRepo: movementLineRepo, } }