diff --git a/internal/modules/marketing/services/deliveryorder.service.go b/internal/modules/marketing/services/deliveryorder.service.go index 2022cc78..b145fc98 100644 --- a/internal/modules/marketing/services/deliveryorder.service.go +++ b/internal/modules/marketing/services/deliveryorder.service.go @@ -410,6 +410,7 @@ func (s deliveryOrdersService) UpdateOne(c *fiber.Ctx, req *validation.DeliveryO return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch delivery product") } + oldRequestedQty := deliveryProduct.UsageQty + deliveryProduct.PendingQty var itemDeliveryDate *time.Time if requestedProduct.DeliveryDate != "" { parsedDate, err := utils.ParseDateString(requestedProduct.DeliveryDate) @@ -421,11 +422,8 @@ func (s deliveryOrdersService) UpdateOne(c *fiber.Ctx, req *validation.DeliveryO itemDeliveryDate = deliveryProduct.DeliveryDate } - oldRequestedQty := deliveryProduct.UsageQty + deliveryProduct.PendingQty - - // Cek apakah product punya flag PAKAN atau OVK isPakanOrOVK := false - if foundMarketingProduct.ProductWarehouse.Product.Id != 0 && len(foundMarketingProduct.ProductWarehouse.Product.Flags) > 0 { + if foundMarketingProduct.ProductWarehouse.Id != 0 && foundMarketingProduct.ProductWarehouse.Product.Id != 0 && len(foundMarketingProduct.ProductWarehouse.Product.Flags) > 0 { for _, flag := range foundMarketingProduct.ProductWarehouse.Product.Flags { if flag.Name == string(utils.FlagPakan) || flag.Name == string(utils.FlagOVK) { isPakanOrOVK = true @@ -506,60 +504,71 @@ func (s deliveryOrdersService) consumeDeliveryStock(ctx context.Context, tx *gor deliveryProductRepo := marketingRepo.NewMarketingDeliveryProductRepository(tx) - if err == nil && result.UsageQuantity > 0 { - if actorID > 0 { - decreaseLog := &entity.StockLog{ - Decrease: result.UsageQuantity, - LoggableType: string(utils.StockLogTypeMarketing), - LoggableId: deliveryProduct.Id, - ProductWarehouseId: marketingProduct.ProductWarehouseId, - CreatedBy: actorID, - Notes: "", - } - s.StockLogRepo.WithTx(tx).CreateOne(ctx, decreaseLog, nil) - } + totalConsumed := 0.0 + var fifoConsumed float64 + var directConsumed float64 + + if result != nil && result.UsageQuantity > 0 { + fifoConsumed = result.UsageQuantity + totalConsumed = result.UsageQuantity } - if err != nil { + if err != nil || (totalConsumed < requestedQty) { + remainder := requestedQty - totalConsumed + pwRepo := productWarehouseRepo.NewProductWarehouseRepository(tx) pw, err2 := pwRepo.GetByID(ctx, marketingProduct.ProductWarehouseId, nil) if err2 != nil { return fiber.NewError(fiber.StatusInternalServerError, "Failed to check product warehouse stock") } - if pw == nil || pw.Quantity < requestedQty { - return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Insufficient stock. Available: %.2f, Requested: %.2f", func() float64 { + if pw == nil || pw.Quantity < remainder { + return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Insufficient stock. FIFO: %.2f, Direct Available: %.2f, Total Needed: %.2f", func() float64 { if pw != nil { return pw.Quantity } else { return 0 } - }(), requestedQty)) + }(), remainder, requestedQty)) } - if err := deliveryProductRepo.UpdateFifoFields(ctx, deliveryProduct.Id, requestedQty, 0); err != nil { - return fiber.NewError(fiber.StatusInternalServerError, "Failed to update delivery product") + if err := pwRepo.AdjustQuantities(ctx, map[uint]float64{ + marketingProduct.ProductWarehouseId: -remainder, + }, func(db *gorm.DB) *gorm.DB { + return tx + }); err != nil { + return fiber.NewError(fiber.StatusInternalServerError, "Failed to adjust product warehouse quantity") } - if actorID > 0 { - decreaseLog := &entity.StockLog{ - Decrease: requestedQty, - LoggableType: string(utils.StockLogTypeMarketing), - LoggableId: deliveryProduct.Id, - ProductWarehouseId: marketingProduct.ProductWarehouseId, - CreatedBy: actorID, - Notes: "", - } - s.StockLogRepo.WithTx(tx).CreateOne(ctx, decreaseLog, nil) - } - - return nil + directConsumed = remainder + totalConsumed += remainder } - if err := deliveryProductRepo.UpdateFifoFields(ctx, deliveryProduct.Id, result.UsageQuantity, result.PendingQuantity); err != nil { + if err := deliveryProductRepo.UpdateFifoFields(ctx, deliveryProduct.Id, totalConsumed, 0); err != nil { return fiber.NewError(fiber.StatusInternalServerError, "Failed to update delivery product") } + if actorID > 0 && totalConsumed > 0 { + notes := "" + if fifoConsumed > 0 && directConsumed > 0 { + notes = fmt.Sprintf("Partial FIFO (%.2f) + Direct (%.2f)", fifoConsumed, directConsumed) + } else if fifoConsumed > 0 { + notes = fmt.Sprintf("FIFO stock only (%.2f)", fifoConsumed) + } else if directConsumed > 0 { + notes = fmt.Sprintf("Direct stock only (%.2f)", directConsumed) + } + + decreaseLog := &entity.StockLog{ + Decrease: totalConsumed, + LoggableType: string(utils.StockLogTypeMarketing), + LoggableId: deliveryProduct.Id, + ProductWarehouseId: marketingProduct.ProductWarehouseId, + CreatedBy: actorID, + Notes: notes, + } + s.StockLogRepo.WithTx(tx).CreateOne(ctx, decreaseLog, nil) + } + return nil }