Compare commits

..

4 Commits

Author SHA1 Message Date
giovanni d2aa3ebac7 fix status marketing when edit sales order and edit marketing delivery 2026-05-19 12:15:53 +07:00
Giovanni Gabriel Septriadi 02b86be4c5 Merge branch 'feat/edit-dc' into 'development'
[FIX][BE]: fix detail daily checklist empty kandang; add sorting to report biaya operasional

See merge request mbugroup/lti-api!539
2026-05-19 01:47:53 +00:00
giovanni 99e185a16a ad sorting to laporan biaya operasional 2026-05-19 00:15:08 +07:00
giovanni 995d585f54 fix get detail kandang kosong 2026-05-18 22:45:30 +07:00
6 changed files with 99 additions and 2 deletions
@@ -1030,6 +1030,7 @@ func (s *dailyChecklistService) UpdateByPut(c *fiber.Ctx, req *validation.Create
}
}
var wasBranchC bool // non-empty_kandang → empty_kandang transition
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(tx *gorm.DB) error {
if err := s.lockKandangForChecklistCreation(tx, req.KandangId); err != nil {
return err
@@ -1088,6 +1089,23 @@ func (s *dailyChecklistService) UpdateByPut(c *fiber.Ctx, req *validation.Create
if err := s.upsertEmptyKandangRange(tx, id, req.KandangId, date, emptyEndDate, actorID); err != nil {
return err
}
// Branch C: non-empty → empty_kandang, hard-delete task/progress data
if !existingIsEmpty {
wasBranchC = true
if err := tx.Exec(`
DELETE FROM daily_checklist_activity_task_assignments
WHERE task_id IN (
SELECT id FROM daily_checklist_activity_tasks WHERE checklist_id = ?
)`, id).Error; err != nil {
return err
}
if err := tx.Where("checklist_id = ?", id).Delete(&entity.DailyChecklistActivityTask{}).Error; err != nil {
return err
}
if err := tx.Where("daily_checklist_id = ?", id).Delete(&entity.DailyChecklistTask{}).Error; err != nil {
return err
}
}
} else if existingIsEmpty {
updates := map[string]any{
"deleted_at": time.Now(),
@@ -1108,6 +1126,20 @@ func (s *dailyChecklistService) UpdateByPut(c *fiber.Ctx, req *validation.Create
return nil, err
}
// Branch C: delete DC documents outside transaction (storage is external)
if wasBranchC && s.DocumentSvc != nil {
docs, docErr := s.DocumentSvc.ListByTarget(c.Context(), string(utils.DocumentTypeDailyChecklist), uint64(id))
if docErr == nil && len(docs) > 0 {
docIDs := make([]uint, 0, len(docs))
for _, doc := range docs {
docIDs = append(docIDs, doc.Id)
}
if delErr := s.DocumentSvc.DeleteDocuments(c.Context(), docIDs, true); delErr != nil {
s.Log.Errorf("Failed to delete documents for DC %d during empty_kandang conversion: %+v", id, delErr)
}
}
}
return s.GetOne(c, id)
}
@@ -177,10 +177,48 @@ func (r *ExpenseRealizationRepositoryImpl) GetAllWithFilters(ctx context.Context
return nil, 0, err
}
sortExpr := "expense_realizations.created_at"
order := "DESC"
if filters.SortOrder == "asc" {
order = "ASC"
}
switch filters.SortBy {
case "po_number":
sortExpr = "expenses.po_number"
case "reference_number":
sortExpr = "expenses.reference_number"
case "realization_date":
sortExpr = "expenses.realization_date"
case "transaction_date":
sortExpr = "expenses.transaction_date"
case "category":
sortExpr = "expenses.category"
case "product":
sortExpr = "(SELECT name FROM nonstocks WHERE id = expense_nonstocks.nonstock_id)"
case "supplier":
sortExpr = "suppliers.name"
case "location":
sortExpr = "(SELECT l.name FROM kandangs k JOIN locations l ON l.id = k.location_id WHERE k.id = expense_nonstocks.kandang_id)"
case "kandang":
sortExpr = "(SELECT name FROM kandangs WHERE id = expense_nonstocks.kandang_id)"
case "qty_pengajuan":
sortExpr = "expense_nonstocks.qty"
case "price_pengajuan":
sortExpr = "expense_nonstocks.price"
case "total_pengajuan":
sortExpr = "expense_nonstocks.qty * expense_nonstocks.price"
case "qty_realisasi":
sortExpr = "expense_realizations.qty"
case "price_realisasi":
sortExpr = "expense_realizations.price"
case "total_realisasi":
sortExpr = "expense_realizations.qty * expense_realizations.price"
}
if err := db.
Offset(offset).
Limit(limit).
Order("expense_realizations.created_at DESC").
Order(sortExpr + " " + order).
Find(&realizations).Error; err != nil {
return nil, 0, err
}
@@ -542,9 +542,15 @@ func (s deliveryOrdersService) UpdateOne(c *fiber.Ctx, req *validation.DeliveryO
return nil, err
}
latestApproval, err := s.ApprovalSvc.LatestByTarget(c.Context(), utils.ApprovalWorkflowMarketing, id, nil)
if err != nil {
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to check approval status")
}
err = s.MarketingRepo.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
marketingProductRepositoryTx := marketingRepo.NewMarketingProductRepository(dbTransaction)
marketingDeliveryProductRepositoryTx := marketingRepo.NewMarketingDeliveryProductRepository(dbTransaction)
approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
marketingRepoTx := marketingRepo.NewMarketingRepository(dbTransaction)
marketing, err := marketingRepoTx.GetByID(c.Context(), id, nil)
@@ -630,6 +636,23 @@ func (s deliveryOrdersService) UpdateOne(c *fiber.Ctx, req *validation.DeliveryO
}
}
if latestApproval != nil && latestApproval.StepNumber == uint16(utils.MarketingDeliveryOrder) {
action := entity.ApprovalActionUpdated
_, err := approvalSvcTx.CreateApproval(
c.Context(),
utils.ApprovalWorkflowMarketing,
id,
utils.MarketingStepSalesOrder,
&action,
actorID,
nil)
if err != nil {
if !errors.Is(err, gorm.ErrDuplicatedKey) {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to reset approval to Sales Order")
}
}
}
return nil
})
if err != nil {
@@ -516,7 +516,7 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
c.Context(),
utils.ApprovalWorkflowMarketing,
id,
approvalutils.ApprovalStep(latestApproval.StepNumber),
utils.MarketingStepPengajuan,
&action,
actorID,
nil)
@@ -51,6 +51,8 @@ func (c *RepportController) GetExpense(ctx *fiber.Ctx) error {
AreaId: int64(ctx.QueryInt("area_id", 0)),
LocationId: int64(ctx.QueryInt("location_id", 0)),
RealizationDate: ctx.Query("realization_date", ""),
SortBy: ctx.Query("sort_by", ""),
SortOrder: ctx.Query("sort_order", ""),
}
locationScope, err := m.ResolveLocationScope(ctx, c.RepportService.DB())
@@ -13,6 +13,8 @@ type ExpenseQuery struct {
AreaId int64 `query:"area_id" validate:"omitempty"`
LocationId int64 `query:"location_id" validate:"omitempty"`
RealizationDate string `query:"realization_date" validate:"omitempty"`
SortBy string `query:"sort_by" validate:"omitempty,oneof=po_number reference_number realization_date transaction_date category product supplier location kandang qty_pengajuan price_pengajuan total_pengajuan qty_realisasi price_realisasi total_realisasi"`
SortOrder string `query:"sort_order" validate:"omitempty,oneof=asc desc"`
AllowedAreaIDs []int64 `query:"-"`
AllowedLocationIDs []int64 `query:"-"`
}