mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-26 00:05:44 +00:00
feat(BE): implement expense tracking for stock transfers and enhance related services
This commit is contained in:
@@ -46,9 +46,10 @@ type transferService struct {
|
||||
ProjectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository
|
||||
DocumentSvc commonSvc.DocumentService
|
||||
FifoSvc commonSvc.FifoService
|
||||
ExpenseBridge TransferExpenseBridge
|
||||
}
|
||||
|
||||
func NewTransferService(validate *validator.Validate, stockTransferRepo rStockTransfer.StockTransferRepository, stockTransferDetailRepo rStockTransfer.StockTransferDetailRepository, stockTransferDeliveryRepo rStockTransfer.StockTransferDeliveryRepository, stockTransferDeliveryItemRepo rStockTransfer.StockTransferDeliveryItemRepository, stockLogsRepo rStockLogs.StockLogRepository, productWarehouseRepo rProductWarehouse.ProductWarehouseRepository, supplierRepo rSupplier.SupplierRepository, warehouseRepo warehouseRepo.WarehouseRepository, projectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository, documentSvc commonSvc.DocumentService, fifoSvc commonSvc.FifoService) TransferService {
|
||||
func NewTransferService(validate *validator.Validate, stockTransferRepo rStockTransfer.StockTransferRepository, stockTransferDetailRepo rStockTransfer.StockTransferDetailRepository, stockTransferDeliveryRepo rStockTransfer.StockTransferDeliveryRepository, stockTransferDeliveryItemRepo rStockTransfer.StockTransferDeliveryItemRepository, stockLogsRepo rStockLogs.StockLogRepository, productWarehouseRepo rProductWarehouse.ProductWarehouseRepository, supplierRepo rSupplier.SupplierRepository, warehouseRepo warehouseRepo.WarehouseRepository, projectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository, documentSvc commonSvc.DocumentService, fifoSvc commonSvc.FifoService, expenseBridge TransferExpenseBridge) TransferService {
|
||||
return &transferService{
|
||||
Log: utils.Log,
|
||||
Validate: validate,
|
||||
@@ -63,6 +64,7 @@ func NewTransferService(validate *validator.Validate, stockTransferRepo rStockTr
|
||||
ProjectFlockKandangRepo: projectFlockKandangRepo,
|
||||
DocumentSvc: documentSvc,
|
||||
FifoSvc: fifoSvc,
|
||||
ExpenseBridge: expenseBridge,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +79,9 @@ func (s transferService) withRelations(db *gorm.DB) *gorm.DB {
|
||||
Preload("ToWarehouse.Area").
|
||||
Preload("Details").
|
||||
Preload("Details.Product").
|
||||
Preload("Details.ExpenseNonstock").
|
||||
Preload("Details.ExpenseNonstock.Expense").
|
||||
Preload("Details.ExpenseNonstock.Expense.Supplier").
|
||||
Preload("Deliveries.Items").
|
||||
Preload("Deliveries.Supplier").
|
||||
Preload("Deliveries.Documents", func(db *gorm.DB) *gorm.DB {
|
||||
@@ -192,7 +197,7 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
||||
}
|
||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Gagal cek data supplier")
|
||||
}
|
||||
if supplier.Category != "BOP" {
|
||||
if supplier.Category != string(utils.SupplierCategoryBOP) {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Supplier dengan ID %d bukan kategori BOP", delivery.SupplierID))
|
||||
}
|
||||
}
|
||||
@@ -213,6 +218,8 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
||||
CreatedBy: uint64(actorID),
|
||||
}
|
||||
|
||||
expensePayloads := make([]TransferExpenseReceivingPayload, 0)
|
||||
|
||||
err = s.StockTransferRepo.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error {
|
||||
|
||||
if err := s.StockTransferRepo.WithTx(tx).CreateOne(c.Context(), entityTransfer, nil); err != nil {
|
||||
@@ -362,7 +369,6 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
||||
return fmt.Errorf("gagal update usage tracking: %w", err)
|
||||
}
|
||||
|
||||
// Step 2: Replenish stock to destination warehouse (STOCK_TRANSFER_IN)
|
||||
note := fmt.Sprintf("Transfer #%s", entityTransfer.MovementNumber)
|
||||
replenishResult, err := s.FifoSvc.Replenish(c.Context(), commonSvc.StockReplenishRequest{
|
||||
StockableKey: fifo.StockableKeyStockTransferIn,
|
||||
@@ -385,6 +391,32 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
||||
}
|
||||
}
|
||||
|
||||
if len(req.Deliveries) > 0 {
|
||||
for _, delivery := range req.Deliveries {
|
||||
for _, prod := range delivery.Products {
|
||||
detail := detailMap[uint64(prod.ProductID)]
|
||||
if detail == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
warehouseID := uint(req.DestinationWarehouseID)
|
||||
supplierID := uint(delivery.SupplierID)
|
||||
deliveredDate := transferDate
|
||||
deliveredQty := prod.ProductQty
|
||||
|
||||
payload := TransferExpenseReceivingPayload{
|
||||
TransferDetailID: detail.Id,
|
||||
ProductID: uint64(prod.ProductID),
|
||||
WarehouseID: uint64(warehouseID),
|
||||
SupplierID: uint64(supplierID),
|
||||
DeliveredQty: deliveredQty,
|
||||
DeliveredDate: &deliveredDate,
|
||||
}
|
||||
expensePayloads = append(expensePayloads, payload)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -396,9 +428,31 @@ func (s *transferService) CreateOne(c *fiber.Ctx, req *validation.TransferReques
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(expensePayloads) > 0 {
|
||||
if err := s.notifyExpenseItemsDelivered(c, entityTransfer.Id, expensePayloads); err != nil {
|
||||
s.Log.Errorf("Failed to sync expense for transfer %d: %+v", entityTransfer.Id, err)
|
||||
return nil, fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to sync expense: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *transferService) notifyExpenseItemsDelivered(c *fiber.Ctx, transferID uint64, payloads []TransferExpenseReceivingPayload) error {
|
||||
if s.ExpenseBridge == nil || transferID == 0 || len(payloads) == 0 {
|
||||
return nil
|
||||
}
|
||||
return s.ExpenseBridge.OnItemsDelivered(c, transferID, payloads)
|
||||
}
|
||||
|
||||
func (s *transferService) notifyExpenseDetailsDeleted(ctx context.Context, transferID uint64, items []entity.StockTransferDetail) error {
|
||||
if s.ExpenseBridge == nil || transferID == 0 || len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
return s.ExpenseBridge.OnItemsDeleted(ctx, transferID, items)
|
||||
}
|
||||
|
||||
func (s *transferService) getActiveProjectFlockKandangID(ctx context.Context, warehouseID uint) (uint, error) {
|
||||
warehouse, err := s.WarehouseRepo.GetByID(ctx, warehouseID, nil)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user