package service import ( "context" "github.com/Caknoooo/go-gin-clean-starter/database/entities" dtodomain "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_request/dto" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_request/query" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_request/repository" sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/google/uuid" "gorm.io/gorm" ) type InventoryRequestService interface { Create(ctx context.Context, req dtodomain.InventoryRequestCreateRequest) (dtodomain.InventoryRequestResponse, error) GetById(ctx context.Context, id string) (dtodomain.InventoryRequestResponse, error) GetAll(ctx context.Context, filter query.InventoryRequestFilter) ([]dtodomain.InventoryRequestResponse, int64, error) Update(ctx context.Context, req dtodomain.InventoryRequestUpdateRequest, id string) (dtodomain.InventoryRequestResponse, error) Delete(ctx context.Context, id string) error GetLinesByRequestId(ctx context.Context, requestId string) ([]dtodomain.InventoryRequestLineResponse, error) CreateLine(ctx context.Context, requestId string, req dtodomain.InventoryRequestLineCreateRequest) (dtodomain.InventoryRequestLineResponse, error) UpdateLine(ctx context.Context, lineId string, req dtodomain.InventoryRequestLineUpdateRequest) (dtodomain.InventoryRequestLineResponse, error) DeleteLine(ctx context.Context, lineId string) error } type inventoryRequestService struct { db *gorm.DB requestRepo repository.InventoryRequestRepository requestLineRepo repository.InventoryRequestLineRepository sequenceService sequenceservice.SequenceService } // GetLinesByRequestId implements InventoryRequestService. func (s *inventoryRequestService) GetLinesByRequestId(ctx context.Context, requestId string) ([]dtodomain.InventoryRequestLineResponse, error) { lines, err := s.requestLineRepo.GetAllByRequestId(ctx, requestId) if err != nil { return nil, err } return dtodomain.ToInventoryRequestLineResponses(lines), nil } func (s *inventoryRequestService) DeleteLine(ctx context.Context, lineId string) error { return s.requestLineRepo.Delete(ctx, nil, lineId) } func (s *inventoryRequestService) UpdateLine(ctx context.Context, lineId string, req dtodomain.InventoryRequestLineUpdateRequest) (dtodomain.InventoryRequestLineResponse, error) { line, err := s.requestLineRepo.GetById(ctx, nil, lineId) if err != nil { return dtodomain.InventoryRequestLineResponse{}, err } if req.Quantity != nil { line.Quantity = *req.Quantity } if req.ProductID != nil { if *req.ProductID != "" { tmp, err := uuid.Parse(*req.ProductID) if err != nil { return dtodomain.InventoryRequestLineResponse{}, err } line.ProductID = tmp } else { line.ProductID = uuid.Nil } } updated, err := s.requestLineRepo.Update(ctx, nil, line) if err != nil { return dtodomain.InventoryRequestLineResponse{}, err } product := dtodomain.InventoryRequestLineProductResponse{} if updated.Product.ID != uuid.Nil { product = dtodomain.InventoryRequestLineProductResponse{ ID: updated.Product.ID.String(), Name: updated.Product.Name, RefNumber: updated.Product.RefNumber, Uom: pkgdto.IdNameResponse{ ID: updated.Product.Uom.ID.String(), Name: updated.Product.Uom.Name, }, } } return dtodomain.InventoryRequestLineResponse{ ID: updated.ID.String(), Quantity: updated.Quantity, Product: product, ClientID: updated.ClientID.String(), }, nil } func (s *inventoryRequestService) Create(ctx context.Context, req dtodomain.InventoryRequestCreateRequest) (dtodomain.InventoryRequestResponse, 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.InventoryRequestResponse{}, err } docNum, err := s.sequenceService.GenerateDocumentNumber(ctx, req.ClientID, "RQST", pkgdto.SequenceConfig{ Prefix: "RQST", EntityType: "INV_REQUEST", Period: "", }) if err != nil { tx.Rollback() return dtodomain.InventoryRequestResponse{}, err } request := entities.TInventoryRequestEntity{ ReferenceNumber: req.ReferenceNumber, DocumentNumber: docNum, DueDate: utils.StringToDateTime(req.DueDate), RequestType: req.RequestType, Note: req.Note, ClientID: clientUUID, Status: req.Status, } created, err := s.requestRepo.Create(ctx, tx, request) if err != nil { tx.Rollback() return dtodomain.InventoryRequestResponse{}, err } var lines []entities.TInventoryRequestLineEntity for _, lineReq := range req.RequestLines { var productUUID uuid.UUID if lineReq.ProductID != "" { productUUID, err = uuid.Parse(lineReq.ProductID) if err != nil { tx.Rollback() return dtodomain.InventoryRequestResponse{}, err } } else { productUUID = uuid.Nil } clientLineUUID, err := uuid.Parse(lineReq.ClientID) if err != nil { tx.Rollback() return dtodomain.InventoryRequestResponse{}, err } lines = append(lines, entities.TInventoryRequestLineEntity{ Quantity: lineReq.Quantity, InvRequestID: created.ID, ProductID: productUUID, ClientID: clientLineUUID, }) } if len(lines) > 0 { err = s.requestLineRepo.BulkCreate(ctx, tx, lines) if err != nil { tx.Rollback() return dtodomain.InventoryRequestResponse{}, err } } tx.Commit() result, err := s.requestRepo.GetById(ctx, nil, created.ID.String()) if err != nil { return dtodomain.InventoryRequestResponse{}, err } return dtodomain.ToInventoryRequestResponse(result), nil } func (s *inventoryRequestService) GetById(ctx context.Context, id string) (dtodomain.InventoryRequestResponse, error) { request, err := s.requestRepo.GetById(ctx, nil, id) if err != nil { return dtodomain.InventoryRequestResponse{}, err } return dtodomain.ToInventoryRequestResponse(request), nil } func (s *inventoryRequestService) GetAll(ctx context.Context, filter query.InventoryRequestFilter) ([]dtodomain.InventoryRequestResponse, int64, error) { requests, total, err := s.requestRepo.GetAll(ctx, filter) if err != nil { return nil, 0, err } var responses []dtodomain.InventoryRequestResponse for _, e := range requests { responses = append(responses, dtodomain.ToInventoryRequestResponse(e)) } if responses == nil { responses = make([]dtodomain.InventoryRequestResponse, 0) } return responses, total, nil } func (s *inventoryRequestService) Update(ctx context.Context, req dtodomain.InventoryRequestUpdateRequest, id string) (dtodomain.InventoryRequestResponse, error) { tx := s.db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() request, err := s.requestRepo.GetById(ctx, tx, id) if err != nil { tx.Rollback() return dtodomain.InventoryRequestResponse{}, err } if req.ReferenceNumber != "" { request.ReferenceNumber = req.ReferenceNumber } request.DocumentNumber = req.DocumentNumber request.DueDate = utils.StringToDateTime(req.DueDate) request.RequestType = req.RequestType request.Note = req.Note request.Status = req.Status updated, err := s.requestRepo.Update(ctx, tx, request) if err != nil { tx.Rollback() return dtodomain.InventoryRequestResponse{}, err } tx.Commit() result, err := s.requestRepo.GetById(ctx, nil, updated.ID.String()) if err != nil { return dtodomain.InventoryRequestResponse{}, err } return dtodomain.ToInventoryRequestResponse(result), nil } func (s *inventoryRequestService) Delete(ctx context.Context, id string) error { tx := s.db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() if err := s.requestRepo.Delete(ctx, tx, id); err != nil { tx.Rollback() return err } tx.Commit() return nil } func (s *inventoryRequestService) CreateLine(ctx context.Context, requestId string, req dtodomain.InventoryRequestLineCreateRequest) (dtodomain.InventoryRequestLineResponse, error) { requestUUID, err := uuid.Parse(requestId) if err != nil { return dtodomain.InventoryRequestLineResponse{}, err } var productUUID uuid.UUID if req.ProductID != "" { productUUID, err = uuid.Parse(req.ProductID) if err != nil { return dtodomain.InventoryRequestLineResponse{}, err } } else { productUUID = uuid.Nil } clientLineUUID, err := uuid.Parse(req.ClientID) if err != nil { return dtodomain.InventoryRequestLineResponse{}, err } line := entities.TInventoryRequestLineEntity{ Quantity: req.Quantity, InvRequestID: requestUUID, ProductID: productUUID, ClientID: clientLineUUID, } created, err := s.requestLineRepo.Create(ctx, nil, line) if err != nil { return dtodomain.InventoryRequestLineResponse{}, err } product := dtodomain.InventoryRequestLineProductResponse{} if created.Product.ID != uuid.Nil { product = dtodomain.InventoryRequestLineProductResponse{ ID: created.Product.ID.String(), Name: created.Product.Name, RefNumber: created.Product.RefNumber, Uom: pkgdto.IdNameResponse{ ID: created.Product.Uom.ID.String(), Name: created.Product.Uom.Name, }, } } return dtodomain.InventoryRequestLineResponse{ ID: created.ID.String(), Quantity: created.Quantity, Product: product, ClientID: created.ClientID.String(), }, nil } func NewInventoryRequestService(db *gorm.DB, requestRepo repository.InventoryRequestRepository, requestLineRepo repository.InventoryRequestLineRepository, sequenceService sequenceservice.SequenceService) InventoryRequestService { return &inventoryRequestService{ db: db, requestRepo: requestRepo, requestLineRepo: requestLineRepo, sequenceService: sequenceService, } }