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

457 lines
14 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
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
}
func NewInventoryIssueService(db *gorm.DB, issueRepo repository.InventoryIssueRepository, issueLineRepo repository.InventoryIssueLineRepository) InventoryIssueService {
return &inventoryIssueService{db: db, issueRepo: issueRepo, issueLineRepo: issueLineRepo}
}
func toInventoryIssueResponse(e entities.TInventoryIssueEntity) dtodomain.InventoryIssueResponse {
issuer := pkgdto.IdNameResponse{}
if e.Issuer.ID != uuid.Nil {
issuer = pkgdto.IdNameResponse{
ID: e.Issuer.ID.String(),
Name: e.Issuer.Name,
}
}
invRequest := pkgdto.IdNameResponse{}
if e.InvRequest.ID != uuid.Nil {
invRequest = pkgdto.IdNameResponse{
ID: e.InvRequest.ID.String(),
Name: e.InvRequest.DocumentNumber,
}
}
client := pkgdto.IdNameResponse{}
if e.Client.ID != uuid.Nil {
client = pkgdto.IdNameResponse{
ID: e.Client.ID.String(),
Name: e.Client.Name,
}
}
assignment := dtodomain.AssignmentResponse{}
if e.Assignment.ID != uuid.Nil {
assignment = toAssignmentResponse(e.Assignment)
}
lines := make([]dtodomain.InventoryIssueLineResponse, 0)
for _, line := range e.IssueLines {
product := dtodomain.InventoryIssueProductResponse{}
if line.Product.ID != uuid.Nil {
product = dtodomain.InventoryIssueProductResponse{
ID: line.Product.ID.String(),
RefNumber: line.Product.RefNumber,
Name: line.Product.Name,
}
}
warehouse := pkgdto.IdNameResponse{}
if line.Warehouse.ID != uuid.Nil {
warehouse = pkgdto.IdNameResponse{
ID: line.Warehouse.ID.String(),
Name: line.Warehouse.Name,
}
}
clientLine := pkgdto.IdNameResponse{}
if line.Client.ID != uuid.Nil {
clientLine = pkgdto.IdNameResponse{
ID: line.Client.ID.String(),
Name: line.Client.Name,
}
}
lines = append(lines, dtodomain.InventoryIssueLineResponse{
ID: line.ID.String(),
CurrentStock: line.CurrentStock,
MinStock: line.MinStock,
RequestQuantity: line.RequestQuantity,
IssuedQuantity: line.IssuedQuantity,
Remarks: line.Remarks,
Product: product,
Warehouse: warehouse,
Client: clientLine,
})
}
return dtodomain.InventoryIssueResponse{
ID: e.ID.String(),
DocumentNumber: e.DocumentNumber,
DocumentDate: utils.DateTimeToString(e.DocumentDate),
DueDate: utils.DateTimeToString(e.DueDate),
Status: e.Status,
IssuerBy: issuer,
InvRequest: invRequest,
Client: client,
LineCount: len(lines),
IssueLines: lines,
Assignment: assignment,
}
}
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 (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 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 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, 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 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)
}