mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
FEAT[BE] :Fixing fifo stock when marketing deleted
This commit is contained in:
@@ -64,7 +64,7 @@ func (MarketingModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate
|
|||||||
warehouseRepo := rWarehouse.NewWarehouseRepository(db)
|
warehouseRepo := rWarehouse.NewWarehouseRepository(db)
|
||||||
projectFlockKandangRepo := rProjectFlockKandang.NewProjectFlockKandangRepository(db)
|
projectFlockKandangRepo := rProjectFlockKandang.NewProjectFlockKandangRepository(db)
|
||||||
|
|
||||||
salesOrdersService := service.NewSalesOrdersService(marketingRepo, customerRepo, productWarehouseRepo, userRepo, approvalSvc, warehouseRepo, projectFlockKandangRepo, validate)
|
salesOrdersService := service.NewSalesOrdersService(marketingRepo, customerRepo, productWarehouseRepo, userRepo, approvalSvc, fifoService, warehouseRepo, projectFlockKandangRepo, validate)
|
||||||
deliveryOrdersService := service.NewDeliveryOrdersService(marketingRepo, marketingProductRepo, marketingDeliveryProductRepo, stockLogRepo, approvalSvc, fifoService, validate)
|
deliveryOrdersService := service.NewDeliveryOrdersService(marketingRepo, marketingProductRepo, marketingDeliveryProductRepo, stockLogRepo, approvalSvc, fifoService, validate)
|
||||||
userService := sUser.NewUserService(userRepo, validate)
|
userService := sUser.NewUserService(userRepo, validate)
|
||||||
|
|
||||||
|
|||||||
@@ -563,6 +563,10 @@ func (s deliveryOrdersService) releaseDeliveryStock(ctx context.Context, tx *gor
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := deliveryProductRepo.ResetFifoFields(ctx, deliveryProduct.Id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if actorID > 0 && currentUsage > 0 {
|
if actorID > 0 && currentUsage > 0 {
|
||||||
increaseLog := &entity.StockLog{
|
increaseLog := &entity.StockLog{
|
||||||
Increase: currentUsage,
|
Increase: currentUsage,
|
||||||
@@ -570,7 +574,7 @@ func (s deliveryOrdersService) releaseDeliveryStock(ctx context.Context, tx *gor
|
|||||||
LoggableId: deliveryProduct.Id,
|
LoggableId: deliveryProduct.Id,
|
||||||
ProductWarehouseId: marketingProduct.ProductWarehouseId,
|
ProductWarehouseId: marketingProduct.ProductWarehouseId,
|
||||||
CreatedBy: actorID,
|
CreatedBy: actorID,
|
||||||
Notes: "",
|
Notes: fmt.Sprintf("Release delivery stock (%.2f)", currentUsage),
|
||||||
}
|
}
|
||||||
stockLogs, err := s.StockLogRepo.GetByProductWarehouse(ctx, marketingProduct.ProductWarehouseId, 1)
|
stockLogs, err := s.StockLogRepo.GetByProductWarehouse(ctx, marketingProduct.ProductWarehouseId, 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -578,8 +582,7 @@ func (s deliveryOrdersService) releaseDeliveryStock(ctx context.Context, tx *gor
|
|||||||
}
|
}
|
||||||
if len(stockLogs) > 0 {
|
if len(stockLogs) > 0 {
|
||||||
latestStockLog := stockLogs[0]
|
latestStockLog := stockLogs[0]
|
||||||
increaseLog.Stock = latestStockLog.Stock
|
increaseLog.Stock = latestStockLog.Stock + increaseLog.Increase
|
||||||
increaseLog.Stock += increaseLog.Increase
|
|
||||||
} else {
|
} else {
|
||||||
increaseLog.Stock += increaseLog.Increase
|
increaseLog.Stock += increaseLog.Increase
|
||||||
}
|
}
|
||||||
@@ -587,9 +590,5 @@ func (s deliveryOrdersService) releaseDeliveryStock(ctx context.Context, tx *gor
|
|||||||
s.StockLogRepo.WithTx(tx).CreateOne(ctx, increaseLog, nil)
|
s.StockLogRepo.WithTx(tx).CreateOne(ctx, increaseLog, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := deliveryProductRepo.ResetFifoFields(ctx, deliveryProduct.Id); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import (
|
|||||||
userRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories"
|
userRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories"
|
||||||
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||||
approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
|
approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
|
||||||
|
"gitlab.com/mbugroup/lti-api.git/internal/utils/fifo"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
@@ -41,11 +42,12 @@ type salesOrdersService struct {
|
|||||||
ProductWarehouseRepo productWarehouseRepo.ProductWarehouseRepository
|
ProductWarehouseRepo productWarehouseRepo.ProductWarehouseRepository
|
||||||
UserRepo userRepo.UserRepository
|
UserRepo userRepo.UserRepository
|
||||||
ApprovalSvc commonSvc.ApprovalService
|
ApprovalSvc commonSvc.ApprovalService
|
||||||
|
FifoSvc commonSvc.FifoService
|
||||||
WarehouseRepo warehouseRepo.WarehouseRepository
|
WarehouseRepo warehouseRepo.WarehouseRepository
|
||||||
ProjectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository
|
ProjectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSalesOrdersService(marketingRepo repository.MarketingRepository, customerRepo customerRepo.CustomerRepository, productWarehouseRepo productWarehouseRepo.ProductWarehouseRepository, userRepo userRepo.UserRepository, approvalSvc commonSvc.ApprovalService, warehouseRepo warehouseRepo.WarehouseRepository,
|
func NewSalesOrdersService(marketingRepo repository.MarketingRepository, customerRepo customerRepo.CustomerRepository, productWarehouseRepo productWarehouseRepo.ProductWarehouseRepository, userRepo userRepo.UserRepository, approvalSvc commonSvc.ApprovalService, fifoSvc commonSvc.FifoService, warehouseRepo warehouseRepo.WarehouseRepository,
|
||||||
projectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository, validate *validator.Validate) SalesOrdersService {
|
projectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository, validate *validator.Validate) SalesOrdersService {
|
||||||
return &salesOrdersService{
|
return &salesOrdersService{
|
||||||
Log: utils.Log,
|
Log: utils.Log,
|
||||||
@@ -55,6 +57,7 @@ func NewSalesOrdersService(marketingRepo repository.MarketingRepository, custome
|
|||||||
ProductWarehouseRepo: productWarehouseRepo,
|
ProductWarehouseRepo: productWarehouseRepo,
|
||||||
UserRepo: userRepo,
|
UserRepo: userRepo,
|
||||||
ApprovalSvc: approvalSvc,
|
ApprovalSvc: approvalSvc,
|
||||||
|
FifoSvc: fifoSvc,
|
||||||
WarehouseRepo: warehouseRepo,
|
WarehouseRepo: warehouseRepo,
|
||||||
ProjectFlockKandangRepo: projectFlockKandangRepo,
|
ProjectFlockKandangRepo: projectFlockKandangRepo,
|
||||||
}
|
}
|
||||||
@@ -230,14 +233,14 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(req.MarketingProducts) > 0 {
|
if len(req.MarketingProducts) > 0 {
|
||||||
for _, item := range req.MarketingProducts {
|
for _, item := range req.MarketingProducts {
|
||||||
if err := m.EnsureProductWarehouseAccess(c, s.MarketingRepo.DB(), item.ProductWarehouseId); err != nil {
|
if err := m.EnsureProductWarehouseAccess(c, s.MarketingRepo.DB(), item.ProductWarehouseId); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := commonSvc.EnsureRelations(c.Context(),
|
if err := commonSvc.EnsureRelations(c.Context(),
|
||||||
commonSvc.RelationCheck{Name: "ProductWarehouse", ID: &item.ProductWarehouseId, Exists: s.ProductWarehouseRepo.IdExists},
|
commonSvc.RelationCheck{Name: "ProductWarehouse", ID: &item.ProductWarehouseId, Exists: s.ProductWarehouseRepo.IdExists},
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,6 +336,32 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
|
|||||||
totalPrice = totalWeight * rp.UnitPrice
|
totalPrice = totalWeight * rp.UnitPrice
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deliveryProduct, err := invDeliveryRepoTx.GetByMarketingProductID(c.Context(), old.Id)
|
||||||
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to check delivery product")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil && deliveryProduct.Id != 0 {
|
||||||
|
oldQty := old.Qty
|
||||||
|
newQty := rp.Qty
|
||||||
|
qtyDiff := newQty - oldQty
|
||||||
|
|
||||||
|
if qtyDiff < 0 {
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest, "Cannot decrease quantity after stock has been allocated. Please delete and create new product.")
|
||||||
|
} else if qtyDiff > 0 {
|
||||||
|
_, err := s.FifoSvc.Consume(c.Context(), commonSvc.StockConsumeRequest{
|
||||||
|
UsableKey: fifo.UsableKeyMarketingDelivery,
|
||||||
|
UsableID: deliveryProduct.Id,
|
||||||
|
ProductWarehouseID: rp.ProductWarehouseId,
|
||||||
|
Quantity: qtyDiff,
|
||||||
|
Tx: dbTransaction,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Insufficient stock for additional quantity: %v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateBody := map[string]any{
|
updateBody := map[string]any{
|
||||||
"product_warehouse_id": rp.ProductWarehouseId,
|
"product_warehouse_id": rp.ProductWarehouseId,
|
||||||
"qty": rp.Qty,
|
"qty": rp.Qty,
|
||||||
@@ -345,25 +374,20 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
|
|||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update marketing product")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update marketing product")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := invDeliveryRepoTx.GetByMarketingProductID(c.Context(), old.Id); err != nil {
|
if deliveryProduct.Id == 0 {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
mdp := &entity.MarketingDeliveryProduct{
|
||||||
|
MarketingProductId: old.Id,
|
||||||
mdp := &entity.MarketingDeliveryProduct{
|
UnitPrice: 0,
|
||||||
MarketingProductId: old.Id,
|
TotalWeight: 0,
|
||||||
UnitPrice: 0,
|
AvgWeight: 0,
|
||||||
TotalWeight: 0,
|
TotalPrice: 0,
|
||||||
AvgWeight: 0,
|
DeliveryDate: nil,
|
||||||
TotalPrice: 0,
|
VehicleNumber: rp.VehicleNumber,
|
||||||
DeliveryDate: nil,
|
UsageQty: 0,
|
||||||
VehicleNumber: rp.VehicleNumber,
|
PendingQty: 0,
|
||||||
UsageQty: 0,
|
}
|
||||||
PendingQty: 0,
|
if err := invDeliveryRepoTx.CreateOne(c.Context(), mdp, nil); err != nil {
|
||||||
}
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create marketing delivery product")
|
||||||
if err := invDeliveryRepoTx.CreateOne(c.Context(), mdp, nil); err != nil {
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create marketing delivery product")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to check delivery product")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -380,10 +404,18 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
|
|||||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to check existing delivery product")
|
return fiber.NewError(fiber.StatusInternalServerError, "Failed to check existing delivery product")
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil && deliveryProduct.Id != 0 {
|
||||||
|
|
||||||
if deliveryProduct.DeliveryDate != nil || deliveryProduct.UsageQty > 0 || deliveryProduct.PendingQty > 0 {
|
if deliveryProduct.DeliveryDate != nil {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Cannot delete marketing product %d because it has delivery records", old.Id))
|
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Cannot delete marketing product %d because it has been delivered", old.Id))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.FifoSvc.ReleaseUsage(c.Context(), commonSvc.StockReleaseRequest{
|
||||||
|
UsableKey: fifo.UsableKeyMarketingDelivery,
|
||||||
|
UsableID: deliveryProduct.Id,
|
||||||
|
Tx: dbTransaction,
|
||||||
|
}); err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to release stock: %v", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := invDeliveryRepoTx.DeleteOne(c.Context(), deliveryProduct.Id); err != nil {
|
if err := invDeliveryRepoTx.DeleteOne(c.Context(), deliveryProduct.Id); err != nil {
|
||||||
@@ -459,6 +491,19 @@ func (s salesOrdersService) DeleteOne(c *fiber.Ctx, id uint) error {
|
|||||||
marketingRepoTx := repository.NewMarketingRepository(dbTransaction)
|
marketingRepoTx := repository.NewMarketingRepository(dbTransaction)
|
||||||
|
|
||||||
if len(marketing.Products) > 0 {
|
if len(marketing.Products) > 0 {
|
||||||
|
deliveryProducts, err := marketingDeliveryProductRepoTx.GetByMarketingId(c.Context(), marketing.Id)
|
||||||
|
if err == nil && len(deliveryProducts) > 0 {
|
||||||
|
for _, dp := range deliveryProducts {
|
||||||
|
if err := s.FifoSvc.ReleaseUsage(c.Context(), commonSvc.StockReleaseRequest{
|
||||||
|
UsableKey: fifo.UsableKeyMarketingDelivery,
|
||||||
|
UsableID: dp.Id,
|
||||||
|
Tx: dbTransaction,
|
||||||
|
}); err != nil {
|
||||||
|
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to release stock for delivery product %d: %v", dp.Id, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, product := range marketing.Products {
|
for _, product := range marketing.Products {
|
||||||
if err := marketingDeliveryProductRepoTx.DeleteMany(c.Context(), func(db *gorm.DB) *gorm.DB {
|
if err := marketingDeliveryProductRepoTx.DeleteMany(c.Context(), func(db *gorm.DB) *gorm.DB {
|
||||||
return db.Where("marketing_product_id = ?", product.Id).Unscoped()
|
return db.Where("marketing_product_id = ?", product.Id).Unscoped()
|
||||||
|
|||||||
Reference in New Issue
Block a user