feat: enhance inventory receipt service with product and UOM code handling
Deploy Application / deploy (push) Successful in 20s Details

This commit is contained in:
Habib Fatkhul Rohman 2025-11-25 11:23:14 +07:00
parent 3197b693b3
commit e22c76abe3
5 changed files with 96 additions and 4 deletions

View File

@ -34,8 +34,10 @@ type InventoryReceiptLineCreateRequest struct {
Quantity float64 `json:"quantity"` Quantity float64 `json:"quantity"`
BatchNumber string `json:"batch_number"` BatchNumber string `json:"batch_number"`
RepackingSuggestion string `json:"repacking_suggestion"` RepackingSuggestion string `json:"repacking_suggestion"`
RepackUomID string `json:"repack_uom_id"` RepackUomID string `json:"repack_uom_id"`
ProductID string `json:"product_id"` RepackUomCode string `json:"repack_uom_code"`
ProductID string `json:"product_id"`
ProductCode string `json:"product_code"`
ClientID string `json:"client_id"` ClientID string `json:"client_id"`
} }

View File

@ -7,6 +7,8 @@ import (
dtodomain "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/dto" 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/query"
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/repository" "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/repository"
productrepository "github.com/Caknoooo/go-gin-clean-starter/modules/product/repository"
uomrepository "github.com/Caknoooo/go-gin-clean-starter/modules/uom/repository"
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils" "github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
"github.com/google/uuid" "github.com/google/uuid"
@ -28,6 +30,8 @@ type inventoryReceiptService struct {
db *gorm.DB db *gorm.DB
receiptRepo repository.InventoryReceiptRepository receiptRepo repository.InventoryReceiptRepository
receiptLineRepo repository.InventoryReceiptLineRepository receiptLineRepo repository.InventoryReceiptLineRepository
productRepo productrepository.ProductRepository
uomRepo uomrepository.UomRepository
} }
// DeleteLine implements InventoryReceiptService. // DeleteLine implements InventoryReceiptService.
@ -239,6 +243,13 @@ func (s *inventoryReceiptService) Create(ctx context.Context, req dtodomain.Inve
tx.Rollback() tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err return dtodomain.InventoryReceiptResponse{}, err
} }
} else if lineReq.ProductCode != "" {
product, err := s.productRepo.GetByCode(ctx, tx, lineReq.ProductCode, req.ClientID)
if err != nil {
tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err
}
productUUID = product.ID
} else { } else {
productUUID = uuid.Nil productUUID = uuid.Nil
} }
@ -250,6 +261,13 @@ func (s *inventoryReceiptService) Create(ctx context.Context, req dtodomain.Inve
return dtodomain.InventoryReceiptResponse{}, err return dtodomain.InventoryReceiptResponse{}, err
} }
repackUomUUID = &tmp repackUomUUID = &tmp
} else if lineReq.RepackUomCode != "" {
uom, err := s.uomRepo.GetByCode(ctx, tx, lineReq.RepackUomCode, req.ClientID)
if err != nil {
tx.Rollback()
return dtodomain.InventoryReceiptResponse{}, err
}
repackUomUUID = &uom.ID
} else { } else {
repackUomUUID = nil repackUomUUID = nil
} }
@ -364,6 +382,12 @@ func (s *inventoryReceiptService) CreateLine(ctx context.Context, receiptId stri
if err != nil { if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err return dtodomain.InventoryReceiptLineResponse{}, err
} }
} else if req.ProductCode != "" {
product, err := s.productRepo.GetByCode(ctx, nil, req.ProductCode, req.ClientID)
if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err
}
productUUID = product.ID
} else { } else {
productUUID = uuid.Nil productUUID = uuid.Nil
} }
@ -374,6 +398,12 @@ func (s *inventoryReceiptService) CreateLine(ctx context.Context, receiptId stri
return dtodomain.InventoryReceiptLineResponse{}, err return dtodomain.InventoryReceiptLineResponse{}, err
} }
repackUomUUID = &tmp repackUomUUID = &tmp
} else if req.RepackUomCode != "" {
uom, err := s.uomRepo.GetByCode(ctx, nil, req.RepackUomCode, req.ClientID)
if err != nil {
return dtodomain.InventoryReceiptLineResponse{}, err
}
repackUomUUID = &uom.ID
} else { } else {
repackUomUUID = nil repackUomUUID = nil
} }
@ -419,10 +449,16 @@ func (s *inventoryReceiptService) CreateLine(ctx context.Context, receiptId stri
}, nil }, nil
} }
func NewInventoryReceiptService(db *gorm.DB, receiptRepo repository.InventoryReceiptRepository, receiptLineRepo repository.InventoryReceiptLineRepository) InventoryReceiptService { func NewInventoryReceiptService(db *gorm.DB,
receiptRepo repository.InventoryReceiptRepository,
receiptLineRepo repository.InventoryReceiptLineRepository,
productRepo productrepository.ProductRepository,
uomRepo uomrepository.UomRepository) InventoryReceiptService {
return &inventoryReceiptService{ return &inventoryReceiptService{
db: db, db: db,
receiptRepo: receiptRepo, receiptRepo: receiptRepo,
receiptLineRepo: receiptLineRepo, receiptLineRepo: receiptLineRepo,
productRepo: productRepo,
uomRepo: uomRepo,
} }
} }

View File

@ -13,6 +13,7 @@ import (
type ProductRepository interface { type ProductRepository interface {
Create(ctx context.Context, tx *gorm.DB, product entities.MProductEntity) (entities.MProductEntity, error) Create(ctx context.Context, tx *gorm.DB, product entities.MProductEntity) (entities.MProductEntity, error)
GetById(ctx context.Context, tx *gorm.DB, productId string) (entities.MProductEntity, error) GetById(ctx context.Context, tx *gorm.DB, productId string) (entities.MProductEntity, error)
GetByCode(ctx context.Context, tx *gorm.DB, productCode string, clientId string) (entities.MProductEntity, error)
GetAll(ctx context.Context, filter query.ProductFilter) ([]entities.MProductEntity, int64, error) GetAll(ctx context.Context, filter query.ProductFilter) ([]entities.MProductEntity, int64, error)
Update(ctx context.Context, tx *gorm.DB, product entities.MProductEntity) (entities.MProductEntity, error) Update(ctx context.Context, tx *gorm.DB, product entities.MProductEntity) (entities.MProductEntity, error)
Delete(ctx context.Context, tx *gorm.DB, productId string) error Delete(ctx context.Context, tx *gorm.DB, productId string) error
@ -24,6 +25,44 @@ type productRepository struct {
db *gorm.DB db *gorm.DB
} }
// GetByCode implements ProductRepository.
func (r *productRepository) GetByCode(ctx context.Context, tx *gorm.DB, productCode string, clientId string) (entities.MProductEntity, error) {
if tx == nil {
tx = r.db
}
var product entities.MProductEntity
if err := tx.WithContext(ctx).
Preload("Client").
Preload("Category").
Preload("Uom").
// Preload("DimUom").
// Preload("WeightUom").
// Preload("VolumeUom").
// Preload("MinStockUom").
// Preload("MaxStockUom").
// Preload("LeadTimeUom").
// Preload("UomToUom").
// Preload("CrossReferences").
// Preload("CrossReferences.Vendor").
// Preload("InventoryStorages").
// Preload("InventoryTransactions").
// Preload("InventoryTransactions.Client").
// Preload("InventoryTransactions.Aisle").
// Preload("InventoryTransactions.InvReceipt").
// Preload("InventoryTransactions.InvReceipt.ReceiptLines").
// Preload("InventoryTransactions.InvReceipt.ReceiptLines.Product").
// Preload("InventoryTransactions.InvIssue").
// Preload("InventoryTransactions.InvIssue.IssueLines").
// Preload("InventoryTransactions.InvIssue.IssueLines.Product").
// Preload("InventoryTransactions.InvMove").
// Preload("InventoryTransactions.InvMove.MovementLines").
// Preload("InventoryTransactions.InvMove.MovementLines.Product").
First(&product, "ref_number = ? AND client_id = ?", productCode, clientId).Error; err != nil {
return product, err
}
return product, nil
}
func (r *productRepository) AssignCrossReference(ctx context.Context, tx *gorm.DB, productId string, vendorIds []string) error { func (r *productRepository) AssignCrossReference(ctx context.Context, tx *gorm.DB, productId string, vendorIds []string) error {
if tx == nil { if tx == nil {
tx = r.db tx = r.db

View File

@ -11,6 +11,7 @@ import (
type UomRepository interface { type UomRepository interface {
Create(ctx context.Context, tx *gorm.DB, uom entities.MUomEntity) (entities.MUomEntity, error) Create(ctx context.Context, tx *gorm.DB, uom entities.MUomEntity) (entities.MUomEntity, error)
GetById(ctx context.Context, tx *gorm.DB, uomId string) (entities.MUomEntity, error) GetById(ctx context.Context, tx *gorm.DB, uomId string) (entities.MUomEntity, error)
GetByCode(ctx context.Context, tx *gorm.DB, uomCode string, clientId string) (entities.MUomEntity, error)
GetAll(ctx context.Context, filter query.UomFilter) ([]entities.MUomEntity, int64, error) GetAll(ctx context.Context, filter query.UomFilter) ([]entities.MUomEntity, int64, error)
Update(ctx context.Context, tx *gorm.DB, uom entities.MUomEntity) (entities.MUomEntity, error) Update(ctx context.Context, tx *gorm.DB, uom entities.MUomEntity) (entities.MUomEntity, error)
Delete(ctx context.Context, tx *gorm.DB, uomId string) error Delete(ctx context.Context, tx *gorm.DB, uomId string) error
@ -20,6 +21,20 @@ type uomRepository struct {
db *gorm.DB db *gorm.DB
} }
// GetByCode implements UomRepository.
func (r *uomRepository) GetByCode(ctx context.Context, tx *gorm.DB, uomCode string, clientId string) (entities.MUomEntity, error) {
if tx == nil {
tx = r.db
}
var uom entities.MUomEntity
if err := tx.WithContext(ctx).
Preload("Client").
First(&uom, "code = ? AND client_id = ?", uomCode, clientId).Error; err != nil {
return uom, err
}
return uom, nil
}
func NewUomRepository(db *gorm.DB) UomRepository { func NewUomRepository(db *gorm.DB) UomRepository {
return &uomRepository{db: db} return &uomRepository{db: db}
} }

View File

@ -174,7 +174,7 @@ func RegisterDependencies(injector *do.Injector) {
warehouseServ := warehouseService.NewWarehouseService(warehouseRepository, db) warehouseServ := warehouseService.NewWarehouseService(warehouseRepository, db)
zonaServ := zonaService.NewZonaService(zonaRepository, db) zonaServ := zonaService.NewZonaService(zonaRepository, db)
aisleServ := aisleService.NewAisleService(aisleRepository, db) aisleServ := aisleService.NewAisleService(aisleRepository, db)
inventoryReceiptServ := inventoryReceiptService.NewInventoryReceiptService(db, inventoryReceiptRepository, inventoryReceiptLineRepository) inventoryReceiptServ := inventoryReceiptService.NewInventoryReceiptService(db, inventoryReceiptRepository, inventoryReceiptLineRepository, productRepository, uomRepository)
assignmentServ := assignmentService.NewAssignmentService(db, assignmentRepository, assignmentUserRepository) assignmentServ := assignmentService.NewAssignmentService(db, assignmentRepository, assignmentUserRepository)
inventoryRequestServ := inventoryRequestService.NewInventoryRequestService(db, inventoryRequestRepository, inventoryRequestLineRepository) inventoryRequestServ := inventoryRequestService.NewInventoryRequestService(db, inventoryRequestRepository, inventoryRequestLineRepository)
inventoryIssueServ := inventoryIssueService.NewInventoryIssueService(db, inventoryIssueRepository, inventoryIssueLineRepository) inventoryIssueServ := inventoryIssueService.NewInventoryIssueService(db, inventoryIssueRepository, inventoryIssueLineRepository)