wms-be/modules/inventory_request/service/inventory_request_service.go

294 lines
9.7 KiB
Go

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,
}
}