From b240478ed5e19504cb5663cec8c29f6ba5b6de7b Mon Sep 17 00:00:00 2001 From: aguhh18 Date: Mon, 19 Jan 2026 17:44:10 +0700 Subject: [PATCH] feat[BE]: Add notes field to Update validation and update approval logic in expense services --- .../modules/expenses/services/expense.service.go | 16 ++++++++++++++-- .../expenses/validations/expense.validation.go | 1 + .../services/transfer_expense_bridge.go | 15 ++++++++++++--- .../services/transfer_laying.service.go | 1 - .../modules/purchases/services/expense_bridge.go | 15 ++++++++++++--- 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/internal/modules/expenses/services/expense.service.go b/internal/modules/expenses/services/expense.service.go index 3bf2db55..8b42fbdf 100644 --- a/internal/modules/expenses/services/expense.service.go +++ b/internal/modules/expenses/services/expense.service.go @@ -396,6 +396,10 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint) updateBody["supplier_id"] = *req.SupplierID } + if req.Notes != nil { + updateBody["notes"] = *req.Notes + } + if req.LocationID != nil { locationID := uint(*req.LocationID) updateBody["location_id"] = locationID @@ -568,20 +572,28 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint) if err != nil { return fiber.NewError(fiber.StatusUnauthorized, "Failed to get actor ID from context") } - if *latestApproval.Action != entity.ApprovalActionUpdated { + + if *latestApproval.Action != entity.ApprovalActionUpdated && latestApproval.StepNumber > uint16(utils.ExpenseStepPengajuan) { approvalAction := entity.ApprovalActionUpdated + previousStep := approvalutils.ApprovalStep(latestApproval.StepNumber) - 1 + + if previousStep < utils.ExpenseStepPengajuan { + previousStep = utils.ExpenseStepPengajuan + } + if _, err := approvalSvcTx.CreateApproval( c.Context(), utils.ApprovalWorkflowExpense, id, - utils.ExpenseStepPengajuan, + previousStep, &approvalAction, actorID, nil); err != nil { return fiber.NewError(fiber.StatusInternalServerError, "Failed to reset approval step") } + } if s.DocumentSvc != nil && len(req.Documents) > 0 { diff --git a/internal/modules/expenses/validations/expense.validation.go b/internal/modules/expenses/validations/expense.validation.go index 4501b87d..3fb9ccd5 100644 --- a/internal/modules/expenses/validations/expense.validation.go +++ b/internal/modules/expenses/validations/expense.validation.go @@ -31,6 +31,7 @@ type Update struct { Category *string `form:"category" json:"category" validate:"omitempty,oneof=BOP NON-BOP"` SupplierID *uint64 `form:"supplier_id" json:"supplier_id" validate:"omitempty,gt=0"` LocationID *uint64 `form:"location_id" json:"location_id" validate:"omitempty,gt=0"` + Notes *string `form:"notes" json:"notes" validate:"omitempty,max=500"` Documents []*multipart.FileHeader `form:"documents" json:"documents" validate:"omitempty,dive"` ExpenseNonstocks *[]ExpenseNonstock `form:"expense_nonstocks" json:"expense_nonstocks" validate:"omitempty,min=1,dive"` } diff --git a/internal/modules/inventory/transfers/services/transfer_expense_bridge.go b/internal/modules/inventory/transfers/services/transfer_expense_bridge.go index c4f28354..7b69c22a 100644 --- a/internal/modules/inventory/transfers/services/transfer_expense_bridge.go +++ b/internal/modules/inventory/transfers/services/transfer_expense_bridge.go @@ -140,12 +140,21 @@ func (b *transferExpenseBridge) markExpensesUpdated(ctx context.Context, expense if actorID == 0 { actorID = 1 } - svc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(b.db)) - action := entity.ApprovalActionUpdated + approvalRepo := commonRepo.NewApprovalRepository(b.db) + svc := commonSvc.NewApprovalService(approvalRepo) + action := entity.ApprovalActionCreated + for id := range expenseIDs { - if _, err := svc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(id), utils.ExpenseStepFinance, &action, actorID, nil); err != nil { + latestApproval, err := approvalRepo.LatestByTarget(ctx, string(utils.ApprovalWorkflowExpense), uint(id), nil) + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return err } + + if latestApproval == nil { + if _, err := svc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(id), utils.ExpenseStepFinance, &action, actorID, nil); err != nil { + return err + } + } } return nil } diff --git a/internal/modules/production/transfer_layings/services/transfer_laying.service.go b/internal/modules/production/transfer_layings/services/transfer_laying.service.go index 3fe0b0b7..e64b9cc2 100644 --- a/internal/modules/production/transfer_layings/services/transfer_laying.service.go +++ b/internal/modules/production/transfer_layings/services/transfer_laying.service.go @@ -133,7 +133,6 @@ func (s transferLayingService) GetAll(c *fiber.Ctx, params *validation.Query) ([ db = db.Order("created_at DESC") - // Apply relations for eager loading db = s.withRelations(db) return db diff --git a/internal/modules/purchases/services/expense_bridge.go b/internal/modules/purchases/services/expense_bridge.go index 56097a90..1210b3a1 100644 --- a/internal/modules/purchases/services/expense_bridge.go +++ b/internal/modules/purchases/services/expense_bridge.go @@ -167,12 +167,21 @@ func (b *expenseBridge) markExpensesUpdated(ctx context.Context, expenseIDs map[ if actorID == 0 { actorID = 1 } - svc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(b.db)) - action := entity.ApprovalActionUpdated + approvalRepo := commonRepo.NewApprovalRepository(b.db) + svc := commonSvc.NewApprovalService(approvalRepo) + action := entity.ApprovalActionCreated + for id := range expenseIDs { - if _, err := svc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(id), utils.ExpenseStepFinance, &action, actorID, nil); err != nil { + latestApproval, err := approvalRepo.LatestByTarget(ctx, string(utils.ApprovalWorkflowExpense), uint(id), nil) + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return err } + + if latestApproval == nil { + if _, err := svc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(id), utils.ExpenseStepFinance, &action, actorID, nil); err != nil { + return err + } + } } return nil }