wms-be/modules/inventory_receipt/service/inventory_receipt_service.go

428 lines
13 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_receipt/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/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 InventoryReceiptService interface {
Create(ctx context.Context, req dtodomain.InventoryReceiptCreateRequest) (dtodomain.InventoryReceiptResponse, error)
GetById(ctx context.Context, id string) (dtodomain.InventoryReceiptResponse, error)
GetAll(ctx context.Context, filter query.InventoryReceiptFilter) ([]dtodomain.InventoryReceiptResponse, int64, error)
Update(ctx context.Context, req dtodomain.InventoryReceiptUpdateRequest, id string) (dtodomain.InventoryReceiptResponse, error)
Delete(ctx context.Context, id string) error
CreateLine(ctx context.Context, receiptId string, req dtodomain.InventoryReceiptLineCreateRequest) (dtodomain.InventoryReceiptLineResponse, error)
UpdateLine(ctx context.Context, lineId string, req dtodomain.InventoryReceiptLineUpdateRequest) (dtodomain.InventoryReceiptLineResponse, error)
DeleteLine(ctx context.Context, lineId string) error
}
type inventoryReceiptService struct {
db *gorm.DB
receiptRepo repository.InventoryReceiptRepository
receiptLineRepo repository.InventoryReceiptLineRepository
}
// DeleteLine implements InventoryReceiptService.
func (s *inventoryReceiptService) DeleteLine(ctx context.Context, lineId string) error {
return s.receiptLineRepo.Delete(ctx, nil, lineId)
}
// UpdateLine implements InventoryReceiptService.
func (s *inventoryReceiptService) UpdateLine(ctx context.Context, lineId string, req dtodomain.InventoryReceiptLineUpdateRequest) (dtodomain.InventoryReceiptLineResponse, error) {
line, err := s.receiptLineRepo.GetById(ctx, nil, lineId)
if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err
}
if req.Quantity != nil {
line.Quantity = *req.Quantity
}
if req.BatchNumber != nil {
line.BatchNumber = *req.BatchNumber
}
if req.RepackingSuggestion != nil {
line.RepackingSuggestion = *req.RepackingSuggestion
}
if req.RepackUomID != nil {
if *req.RepackUomID != "" {
tmp, err := uuid.Parse(*req.RepackUomID)
if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err
}
line.RepackUomID = &tmp
} else {
line.RepackUomID = nil
}
}
if req.ProductID != nil {
if *req.ProductID != "" {
tmp, err := uuid.Parse(*req.ProductID)
if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err
}
line.ProductID = tmp
} else {
line.ProductID = uuid.Nil
}
}
updated, err := s.receiptLineRepo.Update(ctx, nil, line)
if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err
}
var repackUomID *string
if updated.RepackUomID != nil {
tmp := updated.RepackUomID.String()
repackUomID = &tmp
}
product := dtodomain.InventoryReceiptLineProductResponse{}
if updated.Product.ID != uuid.Nil {
product = dtodomain.InventoryReceiptLineProductResponse{
ID: updated.Product.ID.String(),
Name: updated.Product.Name,
}
}
return dtodomain.InventoryReceiptLineResponse{
ID: updated.ID.String(),
Quantity: updated.Quantity,
BatchNumber: updated.BatchNumber,
RepackingSuggestion: updated.RepackingSuggestion,
RepackUomID: repackUomID,
Product: product,
ClientID: updated.ClientID.String(),
}, nil
}
func toAssignmentResponse(e entities.TAssignmentEntity) dtodomain.AssignmentResponse {
// client := pkgdto.IdNameResponse{}
// if e.Client.ID != uuid.Nil {
// client = pkgdto.IdNameResponse{
// ID: e.Client.ID.String(),
// Name: e.Client.Name,
// }
// }
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},
// Client: pkgdto.IdNameResponse{ID: user.Client.ID.String(), Name: user.Client.Name},
}
users = append(users, userResp)
}
return dtodomain.AssignmentResponse{
ID: e.ID.String(),
DocumentType: e.DocumentType,
DocumentID: e.DocumentID.String(),
// Client: client,
AssignmentUsers: users,
}
}
func toInventoryReceiptResponse(e entities.TInventoryReceiptEntity) dtodomain.InventoryReceiptResponse {
client := pkgdto.IdNameResponse{}
if e.Client.ID != uuid.Nil {
client = pkgdto.IdNameResponse{
ID: e.Client.ID.String(),
Name: e.Client.Name,
}
}
lines := make([]dtodomain.InventoryReceiptLineResponse, 0)
for _, line := range e.ReceiptLines {
product := dtodomain.InventoryReceiptLineProductResponse{}
if line.Product.ID != uuid.Nil {
product = dtodomain.InventoryReceiptLineProductResponse{
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,
},
DimLength: line.Product.DimLength,
DimWidth: line.Product.DimWidth,
DimHeight: line.Product.DimHeight,
DimUom: pkgdto.IdNameResponse{
ID: line.Product.DimUom.ID.String(),
Name: line.Product.DimUom.Name,
},
}
}
var repackUomID *string
if line.RepackUomID != nil {
tmp := line.RepackUomID.String()
repackUomID = &tmp
} else {
repackUomID = nil
}
lines = append(lines, dtodomain.InventoryReceiptLineResponse{
ID: line.ID.String(),
Quantity: line.Quantity,
BatchNumber: line.BatchNumber,
RepackingSuggestion: line.RepackingSuggestion,
RepackUomID: repackUomID,
Product: product,
ClientID: line.ClientID.String(),
})
}
assignment := dtodomain.AssignmentResponse{}
if e.Assignment.ID != uuid.Nil {
assignment = toAssignmentResponse(e.Assignment)
}
return dtodomain.InventoryReceiptResponse{
ID: e.ID.String(),
ReferenceNumber: e.ReferenceNumber,
DocumentNumber: e.DocumentNumber,
ReceiptDate: utils.DateTimeToString(e.ReceiptDate),
Source: e.Source,
QrCodeFile: e.QrCodeFile,
// ClientID: e.ClientID.String(),
Client: client,
LineCount: len(lines),
ReceiptLines: lines,
Assignment: assignment,
}
}
func (s *inventoryReceiptService) Create(ctx context.Context, req dtodomain.InventoryReceiptCreateRequest) (dtodomain.InventoryReceiptResponse, 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.InventoryReceiptResponse{}, err
}
docNum, err := entities.GenerateDocumentNumber(s.db, req.ClientID)
if err != nil {
tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err
}
receipt := entities.TInventoryReceiptEntity{
ReferenceNumber: req.ReferenceNumber,
DocumentNumber: docNum,
ReceiptDate: utils.StringToDateTime(req.ReceiptDate),
Source: req.Source,
QrCodeFile: req.QrCodeFile,
ClientID: clientUUID,
Status: req.Status,
}
created, err := s.receiptRepo.Create(ctx, tx, receipt)
if err != nil {
tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err
}
// Bulk create lines
var lines []entities.TInventoryReceiptLineEntity
for _, lineReq := range req.ReceiptLines {
var productUUID uuid.UUID
if lineReq.ProductID != "" {
productUUID, err = uuid.Parse(lineReq.ProductID)
if err != nil {
tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err
}
} else {
productUUID = uuid.Nil
}
var repackUomUUID *uuid.UUID
if lineReq.RepackUomID != "" {
tmp, err := uuid.Parse(lineReq.RepackUomID)
if err != nil {
tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err
}
repackUomUUID = &tmp
} else {
repackUomUUID = nil
}
clientLineUUID, err := uuid.Parse(lineReq.ClientID)
if err != nil {
tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err
}
lines = append(lines, entities.TInventoryReceiptLineEntity{
Quantity: lineReq.Quantity,
BatchNumber: lineReq.BatchNumber,
RepackingSuggestion: lineReq.RepackingSuggestion,
RepackUomID: repackUomUUID,
InvReceiptID: created.ID,
ProductID: productUUID,
ClientID: clientLineUUID,
})
}
if len(lines) > 0 {
err = s.receiptLineRepo.BulkCreate(ctx, tx, lines)
if err != nil {
tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err
}
}
tx.Commit()
result, err := s.receiptRepo.GetById(ctx, nil, created.ID.String())
if err != nil {
return dtodomain.InventoryReceiptResponse{}, err
}
return toInventoryReceiptResponse(result), nil
}
func (s *inventoryReceiptService) GetById(ctx context.Context, id string) (dtodomain.InventoryReceiptResponse, error) {
receipt, err := s.receiptRepo.GetById(ctx, nil, id)
if err != nil {
return dtodomain.InventoryReceiptResponse{}, err
}
return toInventoryReceiptResponse(receipt), nil
}
func (s *inventoryReceiptService) GetAll(ctx context.Context, filter query.InventoryReceiptFilter) ([]dtodomain.InventoryReceiptResponse, int64, error) {
receipts, total, err := s.receiptRepo.GetAll(ctx, filter)
if err != nil {
return nil, 0, err
}
var responses []dtodomain.InventoryReceiptResponse
for _, e := range receipts {
responses = append(responses, toInventoryReceiptResponse(e))
}
if responses == nil {
responses = make([]dtodomain.InventoryReceiptResponse, 0)
}
return responses, total, nil
}
func (s *inventoryReceiptService) Update(ctx context.Context, req dtodomain.InventoryReceiptUpdateRequest, id string) (dtodomain.InventoryReceiptResponse, error) {
tx := s.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
receipt, err := s.receiptRepo.GetById(ctx, tx, id)
if err != nil {
tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err
}
if req.ReferenceNumber != "" {
receipt.ReferenceNumber = req.ReferenceNumber
}
receipt.ReceiptDate = utils.StringToDateTime(req.ReceiptDate)
receipt.Source = req.Source
receipt.QrCodeFile = req.QrCodeFile
receipt.Status = req.Status
updated, err := s.receiptRepo.Update(ctx, tx, receipt)
if err != nil {
tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err
}
tx.Commit()
result, err := s.receiptRepo.GetById(ctx, nil, updated.ID.String())
if err != nil {
return dtodomain.InventoryReceiptResponse{}, err
}
return toInventoryReceiptResponse(result), nil
}
func (s *inventoryReceiptService) Delete(ctx context.Context, id string) error {
tx := s.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
if err := s.receiptRepo.Delete(ctx, tx, id); err != nil {
tx.Rollback()
return err
}
tx.Commit()
return nil
}
func (s *inventoryReceiptService) CreateLine(ctx context.Context, receiptId string, req dtodomain.InventoryReceiptLineCreateRequest) (dtodomain.InventoryReceiptLineResponse, error) {
receiptUUID, err := uuid.Parse(receiptId)
if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err
}
var productUUID uuid.UUID
if req.ProductID != "" {
productUUID, err = uuid.Parse(req.ProductID)
if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err
}
} else {
productUUID = uuid.Nil
}
var repackUomUUID *uuid.UUID
if req.RepackUomID != "" {
tmp, err := uuid.Parse(req.RepackUomID)
if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err
}
repackUomUUID = &tmp
} else {
repackUomUUID = nil
}
clientLineUUID, err := uuid.Parse(req.ClientID)
if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err
}
line := entities.TInventoryReceiptLineEntity{
Quantity: req.Quantity,
BatchNumber: req.BatchNumber,
RepackingSuggestion: req.RepackingSuggestion,
RepackUomID: repackUomUUID,
InvReceiptID: receiptUUID,
ProductID: productUUID,
ClientID: clientLineUUID,
}
created, err := s.receiptLineRepo.Create(ctx, nil, line)
if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err
}
var repackUomID *string
if created.RepackUomID != nil {
tmp := created.RepackUomID.String()
repackUomID = &tmp
}
product := dtodomain.InventoryReceiptLineProductResponse{}
if created.Product.ID != uuid.Nil {
product = dtodomain.InventoryReceiptLineProductResponse{
ID: created.Product.ID.String(),
Name: created.Product.Name,
}
}
return dtodomain.InventoryReceiptLineResponse{
ID: created.ID.String(),
Quantity: created.Quantity,
BatchNumber: created.BatchNumber,
RepackingSuggestion: created.RepackingSuggestion,
RepackUomID: repackUomID,
Product: product,
ClientID: created.ClientID.String(),
}, nil
}
func NewInventoryReceiptService(db *gorm.DB, receiptRepo repository.InventoryReceiptRepository, receiptLineRepo repository.InventoryReceiptLineRepository) InventoryReceiptService {
return &inventoryReceiptService{
db: db,
receiptRepo: receiptRepo,
receiptLineRepo: receiptLineRepo,
}
}