wms-be/modules/inventory_issue/service/inventory_issue_service.go

361 lines
12 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_issue/dto"
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_issue/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_issue/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 InventoryIssueService interface {
Create(ctx context.Context, req dtodomain.InventoryIssueCreateRequest) (dtodomain.InventoryIssueResponse, error)
GetById(ctx context.Context, id string) (dtodomain.InventoryIssueResponse, error)
GetAll(ctx context.Context, filter query.InventoryIssueFilter) ([]dtodomain.InventoryIssueResponse, int64, error)
Update(ctx context.Context, req dtodomain.InventoryIssueUpdateRequest, id string) (dtodomain.InventoryIssueResponse, error)
Delete(ctx context.Context, id string) error
GetLinesByIssueId(ctx context.Context, issueId string) ([]dtodomain.InventoryIssueLineResponse, error)
CreateLine(ctx context.Context, issueId string, req dtodomain.InventoryIssueLineCreateRequest) (dtodomain.InventoryIssueLineResponse, error)
UpdateLine(ctx context.Context, lineId string, req dtodomain.InventoryIssueLineUpdateRequest) (dtodomain.InventoryIssueLineResponse, error)
DeleteLine(ctx context.Context, lineId string) error
}
type inventoryIssueService struct {
db *gorm.DB
issueRepo repository.InventoryIssueRepository
issueLineRepo repository.InventoryIssueLineRepository
}
// GetLinesByIssueId implements InventoryIssueService.
func (s *inventoryIssueService) GetLinesByIssueId(ctx context.Context, issueId string) ([]dtodomain.InventoryIssueLineResponse, error) {
lines, err := s.issueLineRepo.GetAllByIssueId(ctx, issueId)
if err != nil {
return nil, err
}
return dtodomain.ToInventoryIssueLineResponses(lines), nil
}
func NewInventoryIssueService(db *gorm.DB, issueRepo repository.InventoryIssueRepository, issueLineRepo repository.InventoryIssueLineRepository) InventoryIssueService {
return &inventoryIssueService{db: db, issueRepo: issueRepo, issueLineRepo: issueLineRepo}
}
func (s *inventoryIssueService) Create(ctx context.Context, req dtodomain.InventoryIssueCreateRequest) (dtodomain.InventoryIssueResponse, 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.InventoryIssueResponse{}, err
}
issuerUUID, err := uuid.Parse(req.IssuerBy)
if err != nil {
tx.Rollback()
return dtodomain.InventoryIssueResponse{}, err
}
invRequestUUID, err := uuid.Parse(req.InvRequestID)
if err != nil && req.InvRequestID != "" {
tx.Rollback()
return dtodomain.InventoryIssueResponse{}, err
}
docNum, err := entities.GenerateDocumentNumberInvIssue(s.db, req.ClientID)
if err != nil {
tx.Rollback()
return dtodomain.InventoryIssueResponse{}, err
}
issue := entities.TInventoryIssueEntity{
DocumentNumber: docNum,
DocumentDate: utils.StringToDateTime(req.DocumentDate),
DueDate: utils.StringToDateTime(req.DueDate),
IssuerBy: issuerUUID,
InvRequestID: invRequestUUID,
ClientID: clientUUID,
Status: req.Status,
}
created, err := s.issueRepo.Create(ctx, tx, issue)
if err != nil {
tx.Rollback()
return dtodomain.InventoryIssueResponse{}, err
}
// Bulk create lines
var lines []entities.TInventoryIssueLineEntity
for _, lineReq := range req.IssueLines {
productUUID, err := uuid.Parse(lineReq.ProductID)
if err != nil && lineReq.ProductID != "" {
tx.Rollback()
return dtodomain.InventoryIssueResponse{}, err
}
warehouseUUID, err := uuid.Parse(lineReq.WarehouseID)
if err != nil && lineReq.WarehouseID != "" {
tx.Rollback()
return dtodomain.InventoryIssueResponse{}, err
}
clientLineUUID, err := uuid.Parse(lineReq.ClientID)
if err != nil {
tx.Rollback()
return dtodomain.InventoryIssueResponse{}, err
}
lines = append(lines, entities.TInventoryIssueLineEntity{
CurrentStock: lineReq.CurrentStock,
MinStock: lineReq.MinStock,
RequestQuantity: lineReq.RequestQuantity,
IssuedQuantity: lineReq.IssuedQuantity,
Remarks: lineReq.Remarks,
InvIssueID: created.ID,
ProductID: productUUID,
WarehouseID: warehouseUUID,
ClientID: clientLineUUID,
})
}
if len(lines) > 0 {
err = s.issueLineRepo.BulkCreate(ctx, tx, lines)
if err != nil {
tx.Rollback()
return dtodomain.InventoryIssueResponse{}, err
}
}
tx.Commit()
result, err := s.issueRepo.GetById(ctx, nil, created.ID.String())
if err != nil {
return dtodomain.InventoryIssueResponse{}, err
}
return dtodomain.ToInventoryIssueResponse(result), nil
}
func (s *inventoryIssueService) GetById(ctx context.Context, id string) (dtodomain.InventoryIssueResponse, error) {
issue, err := s.issueRepo.GetById(ctx, nil, id)
if err != nil {
return dtodomain.InventoryIssueResponse{}, err
}
return dtodomain.ToInventoryIssueResponse(issue), nil
}
func (s *inventoryIssueService) GetAll(ctx context.Context, filter query.InventoryIssueFilter) ([]dtodomain.InventoryIssueResponse, int64, error) {
issues, total, err := s.issueRepo.GetAll(ctx, filter)
if err != nil {
return nil, 0, err
}
var responses []dtodomain.InventoryIssueResponse
for _, e := range issues {
responses = append(responses, dtodomain.ToInventoryIssueResponse(e))
}
if responses == nil {
responses = make([]dtodomain.InventoryIssueResponse, 0)
}
return responses, total, nil
}
func (s *inventoryIssueService) Update(ctx context.Context, req dtodomain.InventoryIssueUpdateRequest, id string) (dtodomain.InventoryIssueResponse, error) {
tx := s.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
issue, err := s.issueRepo.GetById(ctx, tx, id)
if err != nil {
tx.Rollback()
return dtodomain.InventoryIssueResponse{}, err
}
issue.DocumentDate = utils.StringToDateTime(req.DocumentDate)
issue.DueDate = utils.StringToDateTime(req.DueDate)
issue.Status = req.Status
updated, err := s.issueRepo.Update(ctx, tx, issue)
if err != nil {
tx.Rollback()
return dtodomain.InventoryIssueResponse{}, err
}
tx.Commit()
result, err := s.issueRepo.GetById(ctx, nil, updated.ID.String())
if err != nil {
return dtodomain.InventoryIssueResponse{}, err
}
return dtodomain.ToInventoryIssueResponse(result), nil
}
func (s *inventoryIssueService) Delete(ctx context.Context, id string) error {
tx := s.db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
if err := s.issueRepo.Delete(ctx, tx, id); err != nil {
tx.Rollback()
return err
}
tx.Commit()
return nil
}
func (s *inventoryIssueService) CreateLine(ctx context.Context, issueId string, req dtodomain.InventoryIssueLineCreateRequest) (dtodomain.InventoryIssueLineResponse, error) {
issueUUID, err := uuid.Parse(issueId)
if err != nil {
return dtodomain.InventoryIssueLineResponse{}, err
}
productUUID, err := uuid.Parse(req.ProductID)
if err != nil && req.ProductID != "" {
return dtodomain.InventoryIssueLineResponse{}, err
}
warehouseUUID, err := uuid.Parse(req.WarehouseID)
if err != nil && req.WarehouseID != "" {
return dtodomain.InventoryIssueLineResponse{}, err
}
clientLineUUID, err := uuid.Parse(req.ClientID)
if err != nil {
return dtodomain.InventoryIssueLineResponse{}, err
}
line := entities.TInventoryIssueLineEntity{
CurrentStock: req.CurrentStock,
MinStock: req.MinStock,
RequestQuantity: req.RequestQuantity,
IssuedQuantity: req.IssuedQuantity,
Remarks: req.Remarks,
InvIssueID: issueUUID,
ProductID: productUUID,
WarehouseID: warehouseUUID,
ClientID: clientLineUUID,
}
created, err := s.issueLineRepo.Create(ctx, nil, line)
if err != nil {
return dtodomain.InventoryIssueLineResponse{}, err
}
product := dtodomain.InventoryIssueProductResponse{}
if created.Product.ID != uuid.Nil {
product = dtodomain.InventoryIssueProductResponse{
ID: created.Product.ID.String(),
RefNumber: created.Product.RefNumber,
Name: created.Product.Name,
}
}
warehouse := pkgdto.IdNameResponse{}
if created.Warehouse.ID != uuid.Nil {
warehouse = pkgdto.IdNameResponse{
ID: created.Warehouse.ID.String(),
Name: created.Warehouse.Name,
}
}
clientLine := pkgdto.IdNameResponse{}
if created.Client.ID != uuid.Nil {
clientLine = pkgdto.IdNameResponse{
ID: created.Client.ID.String(),
Name: created.Client.Name,
}
}
return dtodomain.InventoryIssueLineResponse{
ID: created.ID.String(),
CurrentStock: created.CurrentStock,
MinStock: created.MinStock,
RequestQuantity: created.RequestQuantity,
IssuedQuantity: created.IssuedQuantity,
Remarks: created.Remarks,
Product: product,
Warehouse: warehouse,
Client: clientLine,
}, nil
}
func (s *inventoryIssueService) UpdateLine(ctx context.Context, lineId string, req dtodomain.InventoryIssueLineUpdateRequest) (dtodomain.InventoryIssueLineResponse, error) {
line, err := s.issueLineRepo.GetById(ctx, nil, lineId)
if err != nil {
return dtodomain.InventoryIssueLineResponse{}, err
}
if req.CurrentStock != nil {
line.CurrentStock = *req.CurrentStock
}
if req.MinStock != nil {
line.MinStock = *req.MinStock
}
if req.RequestQuantity != nil {
line.RequestQuantity = *req.RequestQuantity
}
if req.IssuedQuantity != nil {
line.IssuedQuantity = *req.IssuedQuantity
}
if req.Remarks != nil {
line.Remarks = *req.Remarks
}
if req.ProductID != nil {
if *req.ProductID != "" {
tmp, err := uuid.Parse(*req.ProductID)
if err != nil {
return dtodomain.InventoryIssueLineResponse{}, err
}
line.ProductID = tmp
} else {
line.ProductID = uuid.Nil
}
}
if req.WarehouseID != nil {
if *req.WarehouseID != "" {
tmp, err := uuid.Parse(*req.WarehouseID)
if err != nil {
return dtodomain.InventoryIssueLineResponse{}, err
}
line.WarehouseID = tmp
} else {
line.WarehouseID = uuid.Nil
}
}
if req.ClientID != nil {
if *req.ClientID != "" {
tmp, err := uuid.Parse(*req.ClientID)
if err != nil {
return dtodomain.InventoryIssueLineResponse{}, err
}
line.ClientID = tmp
} else {
line.ClientID = uuid.Nil
}
}
updated, err := s.issueLineRepo.Update(ctx, nil, line)
if err != nil {
return dtodomain.InventoryIssueLineResponse{}, err
}
product := dtodomain.InventoryIssueProductResponse{}
if updated.Product.ID != uuid.Nil {
product = dtodomain.InventoryIssueProductResponse{
ID: updated.Product.ID.String(),
RefNumber: updated.Product.RefNumber,
Name: updated.Product.Name,
}
}
warehouse := pkgdto.IdNameResponse{}
if updated.Warehouse.ID != uuid.Nil {
warehouse = pkgdto.IdNameResponse{
ID: updated.Warehouse.ID.String(),
Name: updated.Warehouse.Name,
}
}
clientLine := pkgdto.IdNameResponse{}
if updated.Client.ID != uuid.Nil {
clientLine = pkgdto.IdNameResponse{
ID: updated.Client.ID.String(),
Name: updated.Client.Name,
}
}
return dtodomain.InventoryIssueLineResponse{
ID: updated.ID.String(),
CurrentStock: updated.CurrentStock,
MinStock: updated.MinStock,
RequestQuantity: updated.RequestQuantity,
IssuedQuantity: updated.IssuedQuantity,
Remarks: updated.Remarks,
Product: product,
Warehouse: warehouse,
Client: clientLine,
}, nil
}
func (s *inventoryIssueService) DeleteLine(ctx context.Context, lineId string) error {
return s.issueLineRepo.Delete(ctx, nil, lineId)
}