410 lines
13 KiB
Go
410 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_issue/dto"
|
|
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_issue/query"
|
|
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_issue/repository"
|
|
sequenceservice "github.com/Caknoooo/go-gin-clean-starter/modules/sequence/service"
|
|
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
|
|
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
|
|
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
|
|
"github.com/google/uuid"
|
|
"github.com/sirupsen/logrus"
|
|
"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
|
|
sequenceService sequenceservice.SequenceService
|
|
log *logrus.Logger
|
|
}
|
|
|
|
// 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, sequenceService sequenceservice.SequenceService, log *logrus.Logger) InventoryIssueService {
|
|
return &inventoryIssueService{db: db, issueRepo: issueRepo, issueLineRepo: issueLineRepo, sequenceService: sequenceService, log: log}
|
|
}
|
|
|
|
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 := s.sequenceService.GenerateDocumentNumber(ctx, req.ClientID, "ISSUE", pkgdto.SequenceConfig{
|
|
Prefix: "ISSUE",
|
|
EntityType: "INV_ISSUE",
|
|
Period: "",
|
|
})
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return dtodomain.InventoryIssueResponse{}, err
|
|
}
|
|
issue := entities.TInventoryIssueEntity{
|
|
DocumentNumber: docNum,
|
|
DocumentType: req.DocumentType,
|
|
DocumentDate: utils.StringToDateTime(req.DocumentDate),
|
|
DueDate: utils.StringToDateTime(req.DueDate),
|
|
IssuerBy: issuerUUID,
|
|
InvRequestID: invRequestUUID,
|
|
ClientID: clientUUID,
|
|
Status: req.Status,
|
|
FullAuditTrail: utils.FillAuditTrail(ctx, constants.CREATE),
|
|
}
|
|
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()
|
|
s.log.WithFields(logrus.Fields{
|
|
"user_id": utils.GetUserID(ctx),
|
|
"action": "create",
|
|
"entity": "inventory_issue",
|
|
"entity_id": created.ID.String(),
|
|
}).Info("Inventory Issue created")
|
|
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
|
|
}
|
|
|
|
before := issue
|
|
|
|
issue.DocumentDate = utils.StringToDateTime(req.DocumentDate)
|
|
issue.DocumentType = req.DocumentType
|
|
issue.DueDate = utils.StringToDateTime(req.DueDate)
|
|
issue.Status = req.Status
|
|
issue.FullAuditTrail = utils.FillAuditTrail(ctx, constants.UPDATE)
|
|
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
|
|
}
|
|
|
|
changes := utils.GetChangedFields(before, result)
|
|
s.log.WithFields(logrus.Fields{
|
|
"user_id": utils.GetUserID(ctx),
|
|
"action": "update",
|
|
"entity": "inventory_issue",
|
|
"entity_id": id,
|
|
"changes": changes,
|
|
}).Info("Inventory Issue updated")
|
|
|
|
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()
|
|
}
|
|
}()
|
|
issue, err := s.issueRepo.GetById(ctx, tx, id)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
issue.FullAuditTrail = utils.FillAuditTrail(ctx, constants.DELETE)
|
|
if _, err := s.issueRepo.Update(ctx, tx, issue); err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
if err := s.issueRepo.Delete(ctx, tx, id); err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
tx.Commit()
|
|
s.log.WithFields(logrus.Fields{
|
|
"user_id": utils.GetUserID(ctx),
|
|
"action": "delete",
|
|
"entity": "inventory_issue",
|
|
"entity_id": id,
|
|
}).Info("Inventory Issue deleted")
|
|
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)
|
|
}
|