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

344 lines
11 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"
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
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
}
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 toAssignmentResponse(e entities.TAssignmentEntity) dtodomain.AssignmentResponse {
users := make([]dtodomain.AssignmentUserResponse, 0)
for _, user := range e.AssignmentUsers {
userResp := dtodomain.AssignmentUserResponse{
ID: user.ID.String(),
TaskType: user.TaskType,
User: pkgdto.IdNameResponse{ID: user.User.ID.String(), Name: user.User.Name},
Role: pkgdto.IdNameResponse{ID: user.Role.ID.String(), Name: user.Role.Name},
}
users = append(users, userResp)
}
return dtodomain.AssignmentResponse{
ID: e.ID.String(),
DocumentType: e.DocumentType,
DocumentID: e.DocumentID.String(),
AssignmentUsers: users,
}
}
func toInventoryRequestResponse(e entities.TInventoryRequestEntity) dtodomain.InventoryRequestResponse {
client := pkgdto.IdNameResponse{}
if e.Client.ID != uuid.Nil {
client = pkgdto.IdNameResponse{
ID: e.Client.ID.String(),
Name: e.Client.Name,
}
}
lines := make([]dtodomain.InventoryRequestLineResponse, 0)
for _, line := range e.RequestLines {
product := dtodomain.InventoryRequestLineProductResponse{}
if line.Product.ID != uuid.Nil {
product = dtodomain.InventoryRequestLineProductResponse{
ID: line.Product.ID.String(),
Name: line.Product.Name,
RefNumber: line.Product.RefNumber,
Uom: pkgdto.IdNameResponse{
ID: line.Product.Uom.ID.String(),
Name: line.Product.Uom.Name,
},
}
}
lines = append(lines, dtodomain.InventoryRequestLineResponse{
ID: line.ID.String(),
Quantity: line.Quantity,
// CurrentStock: line.Product.CurrentStock,
Product: product,
ClientID: line.ClientID.String(),
})
}
assignment := dtodomain.AssignmentResponse{}
if e.Assignment.ID != uuid.Nil {
assignment = toAssignmentResponse(e.Assignment)
}
return dtodomain.InventoryRequestResponse{
ID: e.ID.String(),
ReferenceNumber: e.ReferenceNumber,
DocumentNumber: e.DocumentNumber,
DueDate: utils.DateTimeToString(e.DueDate),
RequestType: e.RequestType,
Note: e.Note,
Status: e.Status,
Client: client,
LineCount: len(lines),
RequestLines: lines,
Assignment: assignment,
}
}
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 := entities.GenerateDocumentNumberInventoryRequest(s.db, req.ClientID)
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 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 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, 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 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) InventoryRequestService {
return &inventoryRequestService{
db: db,
requestRepo: requestRepo,
requestLineRepo: requestLineRepo,
}
}