FIX[BE]: fix error handling on chickin service to better handler

This commit is contained in:
aguhh18
2025-11-04 16:34:36 +07:00
parent 8220e34302
commit 48730e1b74
@@ -152,7 +152,7 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti
for _, productWarehouse := range productWarehouses { for _, productWarehouse := range productWarehouses {
availableQty, err := s.calculateAvailableQuantity(c, req.ProjectFlockKandangId, &productWarehouse, category) availableQty, err := s.calculateAvailableQuantity(c, req.ProjectFlockKandangId, &productWarehouse, category)
if err != nil { if err != nil {
s.Log.Warnf("Failed to calculate available quantity for product warehouse %d: %v", productWarehouse.Id, err) return nil, fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to calculate available quantity for product warehouse %d", productWarehouse.Id))
} }
if availableQty <= 0 { if availableQty <= 0 {
@@ -189,12 +189,12 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti
productWarehouseTx := s.ProductWarehouseRepo.WithTx(dbTransaction) productWarehouseTx := s.ProductWarehouseRepo.WithTx(dbTransaction)
if err := s.Repository.WithTx(dbTransaction).CreateMany(c.Context(), newChikins, nil); err != nil { if err := s.Repository.WithTx(dbTransaction).CreateMany(c.Context(), newChikins, nil); err != nil {
return err return fiber.NewError(fiber.StatusInternalServerError, "Failed to create chickins")
} }
latest, err := approvalSvcTx.LatestByTarget(c.Context(), utils.ApprovalWorkflowProjectFlockKandang, projectFlockKandang.Id, nil) latest, err := approvalSvcTx.LatestByTarget(c.Context(), utils.ApprovalWorkflowProjectFlockKandang, projectFlockKandang.Id, nil)
if err != nil { if err != nil {
return err return fiber.NewError(fiber.StatusInternalServerError, "Failed to get latest approval")
} }
if category == string(utils.ProjectFlockCategoryLaying) { if category == string(utils.ProjectFlockCategoryLaying) {
@@ -218,17 +218,29 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti
} }
if latest == nil { if latest == nil {
if _, err := approvalSvcTx.CreateApproval(c.Context(), utils.ApprovalWorkflowProjectFlockKandang, projectFlockKandang.Id, utils.ProjectFlockKandangStepPengajuan, &approvalAction, actorID, nil); err != nil { if _, err := approvalSvcTx.CreateApproval(
lower := strings.ToLower(err.Error()) c.Context(),
if !(strings.Contains(lower, "duplicate") || strings.Contains(lower, "unique constraint") || strings.Contains(lower, "23505")) { utils.ApprovalWorkflowProjectFlockKandang,
return err projectFlockKandang.Id,
utils.ProjectFlockKandangStepPengajuan,
&approvalAction,
actorID,
nil); err != nil {
if !errors.Is(err, gorm.ErrDuplicatedKey) {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create approval")
} }
} }
} else if latest.StepNumber != uint16(utils.ProjectFlockKandangStepPengajuan) { } else if latest.StepNumber != uint16(utils.ProjectFlockKandangStepPengajuan) {
if _, err := approvalSvcTx.CreateApproval(c.Context(), utils.ApprovalWorkflowProjectFlockKandang, projectFlockKandang.Id, utils.ProjectFlockKandangStepPengajuan, &approvalAction, actorID, nil); err != nil { if _, err := approvalSvcTx.CreateApproval(
lower := strings.ToLower(err.Error()) c.Context(),
if !(strings.Contains(lower, "duplicate") || strings.Contains(lower, "unique constraint") || strings.Contains(lower, "23505")) { utils.ApprovalWorkflowProjectFlockKandang,
return err projectFlockKandang.Id,
utils.ProjectFlockKandangStepPengajuan,
&approvalAction,
actorID,
nil); err != nil {
if !errors.Is(err, gorm.ErrDuplicatedKey) {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create approval")
} }
} }
} }
@@ -236,7 +248,10 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti
return nil return nil
}) })
if err != nil { if err != nil {
return nil, fiber.NewError(fiber.StatusBadRequest, err.Error()) if fiberErr, ok := err.(*fiber.Error); ok {
return nil, fiberErr
}
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to create chickins")
} }
result := make([]entity.ProjectChickin, 0, len(newChikins)) result := make([]entity.ProjectChickin, 0, len(newChikins))
@@ -324,7 +339,6 @@ func (s chickinService) calculateAvailableQuantity(ctx *fiber.Ctx, projectFlockK
totalPopulation += pop.TotalQty totalPopulation += pop.TotalQty
} }
} }
chickins, err := s.Repository.GetByProjectFlockKandangID(ctx.Context(), projectFlockKandangID) chickins, err := s.Repository.GetByProjectFlockKandangID(ctx.Context(), projectFlockKandangID)
if err == nil { if err == nil {
for _, chickin := range chickins { for _, chickin := range chickins {
@@ -334,7 +348,6 @@ func (s chickinService) calculateAvailableQuantity(ctx *fiber.Ctx, projectFlockK
} }
} }
} }
availableQty = productWarehouse.Quantity - totalPopulation - totalPendingQty availableQty = productWarehouse.Quantity - totalPopulation - totalPendingQty
if availableQty < 0 { if availableQty < 0 {
availableQty = 0 availableQty = 0
@@ -397,7 +410,6 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
productWarehouseTx := s.ProductWarehouseRepo.WithTx(dbTransaction) productWarehouseTx := s.ProductWarehouseRepo.WithTx(dbTransaction)
for _, approvableID := range approvableIDs { for _, approvableID := range approvableIDs {
actorID := uint(1) // todo nanti ambil dari auth context actorID := uint(1) // todo nanti ambil dari auth context
if _, err := approvalSvc.CreateApproval( if _, err := approvalSvc.CreateApproval(
c.Context(), c.Context(),
@@ -408,19 +420,13 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
actorID, actorID,
req.Notes, req.Notes,
); err != nil { ); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to create approval")
lower := strings.ToLower(err.Error())
if !(strings.Contains(lower, "duplicate") || strings.Contains(lower, "unique constraint") || strings.Contains(lower, "23505")) {
return err
}
} }
if action == entity.ApprovalActionApproved { if action == entity.ApprovalActionApproved {
chickins, err := chickinRepoTx.GetByProjectFlockKandangID(c.Context(), approvableID) chickins, err := chickinRepoTx.GetByProjectFlockKandangID(c.Context(), approvableID)
if err != nil { if err != nil {
return err return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to get chickins for approval %d", approvableID))
} }
kandangForApproval, err := s.ProjectflockKandangRepo.GetByID(c.Context(), approvableID) kandangForApproval, err := s.ProjectflockKandangRepo.GetByID(c.Context(), approvableID)
@@ -428,7 +434,7 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("ProjectFlockKandang %d not found", approvableID)) return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("ProjectFlockKandang %d not found", approvableID))
} }
return err return fiber.NewError(fiber.StatusInternalServerError, "Failed to get ProjectFlockKandang")
} }
category := strings.ToUpper(strings.TrimSpace(kandangForApproval.ProjectFlock.Category)) category := strings.ToUpper(strings.TrimSpace(kandangForApproval.ProjectFlock.Category))
@@ -439,41 +445,38 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Warehouse for kandang %d not found", kandangForApproval.KandangId)) return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Warehouse for kandang %d not found", kandangForApproval.KandangId))
} }
return err return fiber.NewError(fiber.StatusInternalServerError, "Failed to get warehouse")
} }
targetPW, err := s.getOrCreateProductWarehouse(c, warehouse.Id, "PULLET", dbTransaction, actorID) targetPW, err := s.getOrCreateProductWarehouse(c, warehouse.Id, "PULLET", dbTransaction, actorID)
if err != nil { if err != nil {
return fmt.Errorf("failed to get/create PULLET product warehouse: %w", err) return fiber.NewError(fiber.StatusInternalServerError, "Failed to get/create PULLET product warehouse")
} }
if err := s.convertChickinsToTarget(c, chickins, targetPW, dbTransaction, actorID); err != nil { if err := s.convertChickinsToTarget(c, chickins, targetPW, dbTransaction, actorID); err != nil {
return err return fiber.NewError(fiber.StatusInternalServerError, "Failed to convert chickins to target")
} }
} else if category == string(utils.ProjectFlockCategoryLaying) { } else if category == string(utils.ProjectFlockCategoryLaying) {
warehouse, err := s.WarehouseRepo.GetByKandangID(c.Context(), kandangForApproval.KandangId) warehouse, err := s.WarehouseRepo.GetByKandangID(c.Context(), kandangForApproval.KandangId)
if err != nil { if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Warehouse for kandang %d not found", kandangForApproval.KandangId)) return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Warehouse for kandang %d not found", kandangForApproval.KandangId))
} }
return err return fiber.NewError(fiber.StatusInternalServerError, "Failed to get warehouse")
} }
targetPW, err := s.getOrCreateProductWarehouse(c, warehouse.Id, "PULLET", dbTransaction, actorID) targetPW, err := s.getOrCreateProductWarehouse(c, warehouse.Id, "PULLET", dbTransaction, actorID)
if err != nil { if err != nil {
return fmt.Errorf("failed to get/create PULLET product warehouse: %w", err) return fiber.NewError(fiber.StatusInternalServerError, "Failed to get/create PULLET product warehouse")
} }
if err := s.convertChickinsToTarget(c, chickins, targetPW, dbTransaction, actorID); err != nil { if err := s.convertChickinsToTarget(c, chickins, targetPW, dbTransaction, actorID); err != nil {
return err return fiber.NewError(fiber.StatusInternalServerError, "Failed to convert chickins to target")
} }
} }
} }
if action == entity.ApprovalActionRejected { if action == entity.ApprovalActionRejected {
chickins, err := chickinRepoTx.GetPendingByProjectFlockKandangID(c.Context(), approvableID) chickins, err := chickinRepoTx.GetPendingByProjectFlockKandangID(c.Context(), approvableID)
if err != nil { if err != nil {
return fmt.Errorf("failed to get pending chickins for rejection %d: %w", approvableID, err) return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to get pending chickins for rejection %d", approvableID))
} }
if len(chickins) == 0 { if len(chickins) == 0 {
@@ -485,7 +488,7 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("ProjectFlockKandang %d not found", approvableID)) return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("ProjectFlockKandang %d not found", approvableID))
} }
return err return fiber.NewError(fiber.StatusInternalServerError, "Failed to get ProjectFlockKandang")
} }
categoryForRejection := strings.ToUpper(strings.TrimSpace(kandangForRejection.ProjectFlock.Category)) categoryForRejection := strings.ToUpper(strings.TrimSpace(kandangForRejection.ProjectFlock.Category))
@@ -499,15 +502,14 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Product warehouse %d not found during rejection", chickin.ProductWarehouseId)) return fiber.NewError(fiber.StatusNotFound, fmt.Sprintf("Product warehouse %d not found during rejection", chickin.ProductWarehouseId))
} }
return fmt.Errorf("failed to restore product warehouse quantity for chickin %d: %w", chickin.Id, err) return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to restore product warehouse quantity for chickin %d", chickin.Id))
} }
} }
if err := chickinRepoTx.DeleteOne(c.Context(), chickin.Id); err != nil { if err := chickinRepoTx.DeleteOne(c.Context(), chickin.Id); err != nil {
if !errors.Is(err, gorm.ErrRecordNotFound) { if !errors.Is(err, gorm.ErrRecordNotFound) {
return fmt.Errorf("failed to delete rejected chickin %d: %w", chickin.Id, err) return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to delete rejected chickin %d", chickin.Id))
} }
s.Log.Infof("chickin %d already deleted during rejection", chickin.Id)
} }
} }
} }
@@ -519,9 +521,6 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
if fiberErr, ok := err.(*fiber.Error); ok { if fiberErr, ok := err.(*fiber.Error); ok {
return nil, fiberErr return nil, fiberErr
} }
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fiber.NewError(fiber.StatusNotFound, "Chickin not found")
}
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to record approval") return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to record approval")
} }
@@ -529,7 +528,7 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
for _, kandangID := range approvableIDs { for _, kandangID := range approvableIDs {
var chickins []entity.ProjectChickin var chickins []entity.ProjectChickin
if err := s.Repository.DB().WithContext(c.Context()).Where("project_flock_kandang_id = ?", kandangID).Find(&chickins).Error; err != nil { if err := s.Repository.DB().WithContext(c.Context()).Where("project_flock_kandang_id = ?", kandangID).Find(&chickins).Error; err != nil {
return nil, err return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to load approved chickins")
} }
updated = append(updated, chickins...) updated = append(updated, chickins...)
} }
@@ -608,7 +607,6 @@ func (s *chickinService) convertChickinsToTarget(ctx *fiber.Ctx, chickins []enti
} }
} }
// Add to target product warehouse
if err := productWarehouseTx.PatchOne(ctx.Context(), targetPW.Id, map[string]any{ if err := productWarehouseTx.PatchOne(ctx.Context(), targetPW.Id, map[string]any{
"quantity": gorm.Expr("quantity + ?", quantityToConvert), "quantity": gorm.Expr("quantity + ?", quantityToConvert),
}, nil); err != nil { }, nil); err != nil {
@@ -627,11 +625,7 @@ func (s *chickinService) convertChickinsToTarget(ctx *fiber.Ctx, chickins []enti
CreatedBy: actorID, CreatedBy: actorID,
} }
if err := ProjectFlockPopulationRepotx.CreateOne(ctx.Context(), population, nil); err != nil { if err := ProjectFlockPopulationRepotx.CreateOne(ctx.Context(), population, nil); err != nil {
lower := strings.ToLower(err.Error()) return err
if !(strings.Contains(lower, "duplicate") || strings.Contains(lower, "unique constraint") || strings.Contains(lower, "23505")) {
return err
}
s.Log.Infof("ignored duplicate population for chickin %d: %v", chickin.Id, err)
} }
} }