feat[BE]: Add notes field to Update validation and update approval logic in expense services

This commit is contained in:
aguhh18
2026-01-19 17:44:10 +07:00
parent 768961d7d6
commit b240478ed5
5 changed files with 39 additions and 9 deletions
@@ -396,6 +396,10 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
updateBody["supplier_id"] = *req.SupplierID updateBody["supplier_id"] = *req.SupplierID
} }
if req.Notes != nil {
updateBody["notes"] = *req.Notes
}
if req.LocationID != nil { if req.LocationID != nil {
locationID := uint(*req.LocationID) locationID := uint(*req.LocationID)
updateBody["location_id"] = locationID updateBody["location_id"] = locationID
@@ -568,20 +572,28 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
if err != nil { if err != nil {
return fiber.NewError(fiber.StatusUnauthorized, "Failed to get actor ID from context") 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 approvalAction := entity.ApprovalActionUpdated
previousStep := approvalutils.ApprovalStep(latestApproval.StepNumber) - 1
if previousStep < utils.ExpenseStepPengajuan {
previousStep = utils.ExpenseStepPengajuan
}
if _, err := approvalSvcTx.CreateApproval( if _, err := approvalSvcTx.CreateApproval(
c.Context(), c.Context(),
utils.ApprovalWorkflowExpense, utils.ApprovalWorkflowExpense,
id, id,
utils.ExpenseStepPengajuan, previousStep,
&approvalAction, &approvalAction,
actorID, actorID,
nil); err != nil { nil); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "Failed to reset approval step") return fiber.NewError(fiber.StatusInternalServerError, "Failed to reset approval step")
} }
} }
if s.DocumentSvc != nil && len(req.Documents) > 0 { if s.DocumentSvc != nil && len(req.Documents) > 0 {
@@ -31,6 +31,7 @@ type Update struct {
Category *string `form:"category" json:"category" validate:"omitempty,oneof=BOP NON-BOP"` Category *string `form:"category" json:"category" validate:"omitempty,oneof=BOP NON-BOP"`
SupplierID *uint64 `form:"supplier_id" json:"supplier_id" validate:"omitempty,gt=0"` SupplierID *uint64 `form:"supplier_id" json:"supplier_id" validate:"omitempty,gt=0"`
LocationID *uint64 `form:"location_id" json:"location_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"` Documents []*multipart.FileHeader `form:"documents" json:"documents" validate:"omitempty,dive"`
ExpenseNonstocks *[]ExpenseNonstock `form:"expense_nonstocks" json:"expense_nonstocks" validate:"omitempty,min=1,dive"` ExpenseNonstocks *[]ExpenseNonstock `form:"expense_nonstocks" json:"expense_nonstocks" validate:"omitempty,min=1,dive"`
} }
@@ -140,12 +140,21 @@ func (b *transferExpenseBridge) markExpensesUpdated(ctx context.Context, expense
if actorID == 0 { if actorID == 0 {
actorID = 1 actorID = 1
} }
svc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(b.db)) approvalRepo := commonRepo.NewApprovalRepository(b.db)
action := entity.ApprovalActionUpdated svc := commonSvc.NewApprovalService(approvalRepo)
action := entity.ApprovalActionCreated
for id := range expenseIDs { 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 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 return nil
} }
@@ -133,7 +133,6 @@ func (s transferLayingService) GetAll(c *fiber.Ctx, params *validation.Query) ([
db = db.Order("created_at DESC") db = db.Order("created_at DESC")
// Apply relations for eager loading
db = s.withRelations(db) db = s.withRelations(db)
return db return db
@@ -167,12 +167,21 @@ func (b *expenseBridge) markExpensesUpdated(ctx context.Context, expenseIDs map[
if actorID == 0 { if actorID == 0 {
actorID = 1 actorID = 1
} }
svc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(b.db)) approvalRepo := commonRepo.NewApprovalRepository(b.db)
action := entity.ApprovalActionUpdated svc := commonSvc.NewApprovalService(approvalRepo)
action := entity.ApprovalActionCreated
for id := range expenseIDs { 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 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 return nil
} }