FEAT[BE] :add marketing type field to delivery and sales order DTOs, enhance validation and service logic for consistent marketing type handling

This commit is contained in:
aguhh18
2026-02-04 14:47:56 +07:00
parent 357b5709f5
commit 1d95976360
4 changed files with 53 additions and 25 deletions
@@ -104,8 +104,23 @@ func (s *salesOrdersService) CreateOne(c *fiber.Ctx, req *validation.Create) (*e
return nil, err
}
if !utils.IsValidMarketingType(req.MarketingType) {
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid marketing_type. Must be one of: AYAM, TELUR, TRADING, AYAM_PULLET")
// Validasi semua product harus punya marketing_type yang sama
if len(req.MarketingProducts) == 0 {
return nil, fiber.NewError(fiber.StatusBadRequest, "marketing_products is required")
}
firstMarketingType := req.MarketingProducts[0].MarketingType
if !utils.IsValidMarketingType(firstMarketingType) {
return nil, fiber.NewError(fiber.StatusBadRequest, "Tipe penjualan tidak valid")
}
for i, item := range req.MarketingProducts {
if !utils.IsValidMarketingType(item.MarketingType) {
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Tipe penjualan tidak valid pada produk ke-%d", i+1))
}
if item.MarketingType != firstMarketingType {
return nil, fiber.NewError(fiber.StatusBadRequest, "Semua produk harus memiliki tipe penjualan yang sama")
}
}
actorID, err := m.ActorIDFromContext(c)
@@ -120,11 +135,11 @@ func (s *salesOrdersService) CreateOne(c *fiber.Ctx, req *validation.Create) (*e
}
for _, item := range req.MarketingProducts {
if req.MarketingType != string(utils.MarketingTypeTrading) && item.AvgWeight == 0 {
return nil, fiber.NewError(fiber.StatusBadRequest, "avg_weight is required for non-TRADING marketing type")
if item.MarketingType != string(utils.MarketingTypeTrading) && item.AvgWeight == 0 {
return nil, fiber.NewError(fiber.StatusBadRequest, "Berat rata-rata harus diisi")
}
if item.ConvertionUnit != nil && !utils.IsValidConvertionUnit(*item.ConvertionUnit) {
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid convertion_unit. Must be one of: PETI, KG")
return nil, fiber.NewError(fiber.StatusBadRequest, "Unit konversi tidak valid")
}
if err := m.EnsureProductWarehouseAccess(c, s.MarketingRepo.DB(), item.ProductWarehouseId); err != nil {
return nil, err
@@ -160,7 +175,7 @@ func (s *salesOrdersService) CreateOne(c *fiber.Ctx, req *validation.Create) (*e
SoDate: soDate,
SalesPersonId: req.SalesPersonId,
Notes: req.Notes,
MarketingType: req.MarketingType,
MarketingType: firstMarketingType,
CreatedBy: actorID,
}
if err := marketingRepoTx.CreateOne(c.Context(), marketing, nil); err != nil {
@@ -173,7 +188,7 @@ func (s *salesOrdersService) CreateOne(c *fiber.Ctx, req *validation.Create) (*e
if product.ProductWarehouseId != 0 {
pwIDs = append(pwIDs, product.ProductWarehouseId)
}
if err := s.createMarketingProductWithDelivery(c.Context(), marketing.Id, marketing.MarketingType, product, marketingProductRepoTx, invDeliveryRepoTx); err != nil {
if err := s.createMarketingProductWithDelivery(c.Context(), marketing.Id, product.MarketingType, product, marketingProductRepoTx, invDeliveryRepoTx); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create marketing product")
}
}
@@ -218,8 +233,21 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
return nil, err
}
if req.MarketingType != "" && !utils.IsValidMarketingType(req.MarketingType) {
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid marketing_type. Must be one of: AYAM, TELUR, TRADING, AYAM_PULLET")
// Validasi semua product harus punya marketing_type yang sama
if len(req.MarketingProducts) > 0 {
firstMarketingType := req.MarketingProducts[0].MarketingType
if !utils.IsValidMarketingType(firstMarketingType) {
return nil, fiber.NewError(fiber.StatusBadRequest, "Tipe penjualan tidak valid")
}
for i, item := range req.MarketingProducts {
if !utils.IsValidMarketingType(item.MarketingType) {
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Tipe penjualan tidak valid pada produk ke-%d", i+1))
}
if item.MarketingType != firstMarketingType {
return nil, fiber.NewError(fiber.StatusBadRequest, "Semua produk harus memiliki tipe penjualan yang sama")
}
}
}
if err := m.EnsureMarketingAccess(c, s.MarketingRepo.DB(), id); err != nil {
@@ -249,11 +277,11 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
if len(req.MarketingProducts) > 0 {
for _, item := range req.MarketingProducts {
if req.MarketingType != "" && req.MarketingType != string(utils.MarketingTypeTrading) && item.AvgWeight == 0 {
return nil, fiber.NewError(fiber.StatusBadRequest, "avg_weight is required for non-TRADING marketing type")
if item.MarketingType != string(utils.MarketingTypeTrading) && item.AvgWeight == 0 {
return nil, fiber.NewError(fiber.StatusBadRequest, "Berat rata-rata harus diisi")
}
if item.ConvertionUnit != nil && !utils.IsValidConvertionUnit(*item.ConvertionUnit) {
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid convertion_unit. Must be one of: PETI, KG")
return nil, fiber.NewError(fiber.StatusBadRequest, "Unit konversi tidak valid")
}
if err := m.EnsureProductWarehouseAccess(c, s.MarketingRepo.DB(), item.ProductWarehouseId); err != nil {
return nil, err
@@ -302,8 +330,8 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
if req.Notes != "" {
updateBody["notes"] = req.Notes
}
if req.MarketingType != "" {
updateBody["marketing_type"] = req.MarketingType
if len(req.MarketingProducts) > 0 {
updateBody["marketing_type"] = req.MarketingProducts[0].MarketingType
}
if len(updateBody) > 0 {
@@ -330,15 +358,10 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
reqByPW[rp.ProductWarehouseId] = rp
}
marketing, err := marketingRepoTx.GetByID(c.Context(), id, nil)
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch marketing")
}
for _, rp := range req.MarketingProducts {
if old, ok := oldByPW[rp.ProductWarehouseId]; ok {
totalWeight, totalPrice := s.calculatePriceByMarketingType(marketing.MarketingType, rp.Qty, rp.AvgWeight, rp.UnitPrice, rp.Week)
totalWeight, totalPrice := s.calculatePriceByMarketingType(rp.MarketingType, rp.Qty, rp.AvgWeight, rp.UnitPrice, rp.Week)
deliveryProduct, err := invDeliveryRepoTx.GetByMarketingProductID(c.Context(), old.Id)
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
@@ -397,7 +420,7 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
}
}
} else {
if err := s.createMarketingProductWithDelivery(c.Context(), id, marketing.MarketingType, rp, marketingProductRepoTx, invDeliveryRepoTx); err != nil {
if err := s.createMarketingProductWithDelivery(c.Context(), id, rp.MarketingType, rp, marketingProductRepoTx, invDeliveryRepoTx); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create marketing product")
}
}