mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
feat(BE-ExpenseApproval): add unit vice president approval step and permissions
This commit is contained in:
@@ -19,18 +19,19 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
P_ExpenseGetAll = "lti.expense.list"
|
P_ExpenseGetAll = "lti.expense.list"
|
||||||
P_ExpenseCreateOne = "lti.expense.create"
|
P_ExpenseCreateOne = "lti.expense.create"
|
||||||
P_ExpenseUpdateOne = "lti.expense.update"
|
P_ExpenseUpdateOne = "lti.expense.update"
|
||||||
P_ExpenseGetOne = "lti.expense.detail"
|
P_ExpenseGetOne = "lti.expense.detail"
|
||||||
P_ExpenseDeleteOne = "lti.expense.delete"
|
P_ExpenseDeleteOne = "lti.expense.delete"
|
||||||
P_ExpenseApprovalManager = "lti.expense.approve.manager"
|
P_ExpenseApprovalManager = "lti.expense.approve.manager"
|
||||||
P_ExpenseApprovalFinance = "lti.expense.approve.finance"
|
P_ExpenseApprovalFinance = "lti.expense.approve.finance"
|
||||||
P_ExpenseCreateRealizations = "lti.expense.create.realization"
|
P_ExpenseApprovalUnitVicePresident = "lti.expense.approve.unit_vice_president"
|
||||||
P_ExpenseUpdateRealizations = "lti.expense.update.realization"
|
P_ExpenseCreateRealizations = "lti.expense.create.realization"
|
||||||
P_ExpenseCompleteExpense = "lti.expense.complete.expense"
|
P_ExpenseUpdateRealizations = "lti.expense.update.realization"
|
||||||
P_ExpenseDocument = "lti.expense.document"
|
P_ExpenseCompleteExpense = "lti.expense.complete.expense"
|
||||||
P_ExpenseDocumentRealizations = "lti.expense.document.realization"
|
P_ExpenseDocument = "lti.expense.document"
|
||||||
|
P_ExpenseDocumentRealizations = "lti.expense.document.realization"
|
||||||
)
|
)
|
||||||
const (
|
const (
|
||||||
P_AdjustmentGetAll = "lti.inventory.list"
|
P_AdjustmentGetAll = "lti.inventory.list"
|
||||||
|
|||||||
@@ -233,6 +233,8 @@ func (u *ExpenseController) Approval(c *fiber.Ctx) error {
|
|||||||
approvalType = "manager"
|
approvalType = "manager"
|
||||||
} else if strings.Contains(path, "/approvals/finance") {
|
} else if strings.Contains(path, "/approvals/finance") {
|
||||||
approvalType = "finance"
|
approvalType = "finance"
|
||||||
|
} else if strings.Contains(path, "/approvals/unit-vice-president") {
|
||||||
|
approvalType = "unit-vice-president"
|
||||||
} else {
|
} else {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid approval path")
|
return fiber.NewError(fiber.StatusBadRequest, "Invalid approval path")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,11 @@ func ExpenseRoutes(v1 fiber.Router, u user.UserService, s expense.ExpenseService
|
|||||||
route.Get("/:id", m.RequirePermissions(m.P_ExpenseGetOne), ctrl.GetOne)
|
route.Get("/:id", m.RequirePermissions(m.P_ExpenseGetOne), ctrl.GetOne)
|
||||||
route.Patch("/:id", m.RequirePermissions(m.P_ExpenseUpdateOne), ctrl.UpdateOne)
|
route.Patch("/:id", m.RequirePermissions(m.P_ExpenseUpdateOne), ctrl.UpdateOne)
|
||||||
route.Delete("/:id", m.RequirePermissions(m.P_ExpenseDeleteOne), ctrl.DeleteOne)
|
route.Delete("/:id", m.RequirePermissions(m.P_ExpenseDeleteOne), ctrl.DeleteOne)
|
||||||
|
|
||||||
route.Post("/approvals/manager", m.RequirePermissions(m.P_ExpenseApprovalManager), ctrl.Approval)
|
route.Post("/approvals/manager", m.RequirePermissions(m.P_ExpenseApprovalManager), ctrl.Approval)
|
||||||
route.Post("/approvals/finance", m.RequirePermissions(m.P_ExpenseApprovalFinance), ctrl.Approval)
|
route.Post("/approvals/finance", m.RequirePermissions(m.P_ExpenseApprovalFinance), ctrl.Approval)
|
||||||
|
route.Post("/approvals/unit-vice-president", m.RequirePermissions(m.P_ExpenseApprovalUnitVicePresident), ctrl.Approval)
|
||||||
|
|
||||||
route.Post("/:id/realizations", m.RequirePermissions(m.P_ExpenseCreateRealizations), ctrl.CreateRealization)
|
route.Post("/:id/realizations", m.RequirePermissions(m.P_ExpenseCreateRealizations), ctrl.CreateRealization)
|
||||||
route.Patch("/:id/realizations", m.RequirePermissions(m.P_ExpenseUpdateRealizations), ctrl.UpdateRealization)
|
route.Patch("/:id/realizations", m.RequirePermissions(m.P_ExpenseUpdateRealizations), ctrl.UpdateRealization)
|
||||||
route.Post("/:id/complete", m.RequirePermissions(m.P_ExpenseCompleteExpense), ctrl.CompleteExpense)
|
route.Post("/:id/complete", m.RequirePermissions(m.P_ExpenseCompleteExpense), ctrl.CompleteExpense)
|
||||||
|
|||||||
@@ -1055,15 +1055,24 @@ func (s *expenseService) Approval(c *fiber.Ctx, req *validation.ApprovalRequest,
|
|||||||
if latestApproval.StepNumber != uint16(utils.ExpenseStepPengajuan) {
|
if latestApproval.StepNumber != uint16(utils.ExpenseStepPengajuan) {
|
||||||
currentStepName := utils.ExpenseApprovalSteps[approvalutils.ApprovalStep(latestApproval.StepNumber)]
|
currentStepName := utils.ExpenseApprovalSteps[approvalutils.ApprovalStep(latestApproval.StepNumber)]
|
||||||
return fiber.NewError(fiber.StatusBadRequest,
|
return fiber.NewError(fiber.StatusBadRequest,
|
||||||
fmt.Sprintf("Cannot process at Manager step. Latest approval is at %s step. Expected previous step: Pengajuan", currentStepName))
|
fmt.Sprintf("Cannot process at Head Area step. Latest approval is at %s step. Expected previous step: Pengajuan", currentStepName))
|
||||||
}
|
}
|
||||||
} else if approvalType == "finance" {
|
} else if approvalType == "unit-vice-president" {
|
||||||
|
|
||||||
stepNumber = utils.ExpenseStepFinance
|
stepNumber = utils.ExpenseStepUnitVicePresident
|
||||||
if latestApproval.StepNumber != uint16(utils.ExpenseStepManager) {
|
if latestApproval.StepNumber != uint16(utils.ExpenseStepManager) {
|
||||||
currentStepName := utils.ExpenseApprovalSteps[approvalutils.ApprovalStep(latestApproval.StepNumber)]
|
currentStepName := utils.ExpenseApprovalSteps[approvalutils.ApprovalStep(latestApproval.StepNumber)]
|
||||||
return fiber.NewError(fiber.StatusBadRequest,
|
return fiber.NewError(fiber.StatusBadRequest,
|
||||||
fmt.Sprintf("Cannot process at Finance step. Latest approval is at %s step. Expected previous step: Manager", currentStepName))
|
fmt.Sprintf("Cannot process at Unit Vice President step. Latest approval is at %s step. Expected previous step: Head Area", currentStepName))
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if approvalType == "finance" {
|
||||||
|
|
||||||
|
stepNumber = utils.ExpenseStepFinance
|
||||||
|
if latestApproval.StepNumber != uint16(utils.ExpenseStepUnitVicePresident) {
|
||||||
|
currentStepName := utils.ExpenseApprovalSteps[approvalutils.ApprovalStep(latestApproval.StepNumber)]
|
||||||
|
return fiber.NewError(fiber.StatusBadRequest,
|
||||||
|
fmt.Sprintf("Cannot process at Finance step. Latest approval is at %s step. Expected previous step: Unit Vice President", currentStepName))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Invalid approval type: %v", approvalType))
|
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Invalid approval type: %v", approvalType))
|
||||||
|
|||||||
@@ -39,12 +39,12 @@ type TransferExpenseReceivingPayload struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type groupedTransferItem struct {
|
type groupedTransferItem struct {
|
||||||
detail *entity.StockTransferDetail
|
detail *entity.StockTransferDetail
|
||||||
payload TransferExpenseReceivingPayload
|
payload TransferExpenseReceivingPayload
|
||||||
projectFK *uint
|
projectFK *uint
|
||||||
kandangID *uint
|
kandangID *uint
|
||||||
totalPrice float64
|
totalPrice float64
|
||||||
shippingCostTotal float64
|
shippingCostTotal float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func groupingKey(supplierID uint, date time.Time, warehouseID uint) string {
|
func groupingKey(supplierID uint, date time.Time, warehouseID uint) string {
|
||||||
@@ -84,7 +84,6 @@ func (b *transferExpenseBridge) OnItemsDeleted(ctx context.Context, _ uint64, it
|
|||||||
expenseIDs := make(map[uint64]struct{})
|
expenseIDs := make(map[uint64]struct{})
|
||||||
expenseNonstockIDs := make([]uint64, 0)
|
expenseNonstockIDs := make([]uint64, 0)
|
||||||
|
|
||||||
|
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
if item.ExpenseNonstockId != nil && *item.ExpenseNonstockId != 0 {
|
if item.ExpenseNonstockId != nil && *item.ExpenseNonstockId != 0 {
|
||||||
expenseNonstockIDs = append(expenseNonstockIDs, *item.ExpenseNonstockId)
|
expenseNonstockIDs = append(expenseNonstockIDs, *item.ExpenseNonstockId)
|
||||||
@@ -92,7 +91,7 @@ func (b *transferExpenseBridge) OnItemsDeleted(ctx context.Context, _ uint64, it
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(expenseNonstockIDs) > 0 {
|
if len(expenseNonstockIDs) > 0 {
|
||||||
|
|
||||||
for _, nsID := range expenseNonstockIDs {
|
for _, nsID := range expenseNonstockIDs {
|
||||||
var expenseID uint64
|
var expenseID uint64
|
||||||
if err := tx.Model(&entity.ExpenseNonstock{}).
|
if err := tx.Model(&entity.ExpenseNonstock{}).
|
||||||
@@ -106,13 +105,11 @@ func (b *transferExpenseBridge) OnItemsDeleted(ctx context.Context, _ uint64, it
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if err := tx.Delete(&entity.ExpenseNonstock{}, expenseNonstockIDs).Error; err != nil {
|
if err := tx.Delete(&entity.ExpenseNonstock{}, expenseNonstockIDs).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
approvalRepoTx := commonRepo.NewApprovalRepository(tx)
|
approvalRepoTx := commonRepo.NewApprovalRepository(tx)
|
||||||
for expenseID := range expenseIDs {
|
for expenseID := range expenseIDs {
|
||||||
var count int64
|
var count int64
|
||||||
@@ -122,7 +119,6 @@ func (b *transferExpenseBridge) OnItemsDeleted(ctx context.Context, _ uint64, it
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
if err := approvalRepoTx.DeleteByTarget(ctx, utils.ApprovalWorkflowExpense.String(), uint(expenseID)); err != nil {
|
if err := approvalRepoTx.DeleteByTarget(ctx, utils.ApprovalWorkflowExpense.String(), uint(expenseID)); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -220,7 +216,6 @@ func (b *transferExpenseBridge) createExpenseViaService(
|
|||||||
for _, gi := range items {
|
for _, gi := range items {
|
||||||
note := fmt.Sprintf("stock_transfer_detail:%d", gi.detail.Id)
|
note := fmt.Sprintf("stock_transfer_detail:%d", gi.detail.Id)
|
||||||
|
|
||||||
|
|
||||||
price := gi.shippingCostTotal
|
price := gi.shippingCostTotal
|
||||||
if gi.payload.TransportPerItem != nil {
|
if gi.payload.TransportPerItem != nil {
|
||||||
price = *gi.payload.TransportPerItem * gi.payload.DeliveredQty
|
price = *gi.payload.TransportPerItem * gi.payload.DeliveredQty
|
||||||
@@ -228,7 +223,7 @@ func (b *transferExpenseBridge) createExpenseViaService(
|
|||||||
|
|
||||||
costItems = append(costItems, expenseValidation.CostItem{
|
costItems = append(costItems, expenseValidation.CostItem{
|
||||||
NonstockID: expeditionNonstockID,
|
NonstockID: expeditionNonstockID,
|
||||||
Quantity: 1,
|
Quantity: 1,
|
||||||
Price: price,
|
Price: price,
|
||||||
Notes: note,
|
Notes: note,
|
||||||
})
|
})
|
||||||
@@ -251,7 +246,6 @@ func (b *transferExpenseBridge) createExpenseViaService(
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
action := entity.ApprovalActionApproved
|
action := entity.ApprovalActionApproved
|
||||||
actorID := uint(transfer.CreatedBy)
|
actorID := uint(transfer.CreatedBy)
|
||||||
if actorID == 0 {
|
if actorID == 0 {
|
||||||
@@ -261,6 +255,9 @@ func (b *transferExpenseBridge) createExpenseViaService(
|
|||||||
if _, err := approvalSvc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(detail.Id), utils.ExpenseStepManager, &action, actorID, nil); err != nil {
|
if _, err := approvalSvc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(detail.Id), utils.ExpenseStepManager, &action, actorID, nil); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if _, err := approvalSvc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(detail.Id), utils.ExpenseStepUnitVicePresident, &action, actorID, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if _, err := approvalSvc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(detail.Id), utils.ExpenseStepFinance, &action, actorID, nil); err != nil {
|
if _, err := approvalSvc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(detail.Id), utils.ExpenseStepFinance, &action, actorID, nil); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -328,7 +325,6 @@ func (b *transferExpenseBridge) OnItemsDelivered(c *fiber.Ctx, transferID uint64
|
|||||||
|
|
||||||
ctx := c.Context()
|
ctx := c.Context()
|
||||||
|
|
||||||
|
|
||||||
transfer, err := b.transferRepo.GetByID(ctx, uint(transferID), func(db *gorm.DB) *gorm.DB {
|
transfer, err := b.transferRepo.GetByID(ctx, uint(transferID), func(db *gorm.DB) *gorm.DB {
|
||||||
return db.
|
return db.
|
||||||
Preload("Details").
|
Preload("Details").
|
||||||
@@ -348,11 +344,10 @@ func (b *transferExpenseBridge) OnItemsDelivered(c *fiber.Ctx, transferID uint64
|
|||||||
for i := range transfer.Details {
|
for i := range transfer.Details {
|
||||||
detailMap[transfer.Details[i].Id] = &transfer.Details[i]
|
detailMap[transfer.Details[i].Id] = &transfer.Details[i]
|
||||||
|
|
||||||
|
|
||||||
for _, deliveryItem := range transfer.Details[i].DeliveryItems {
|
for _, deliveryItem := range transfer.Details[i].DeliveryItems {
|
||||||
if deliveryItem.StockTransferDelivery != nil {
|
if deliveryItem.StockTransferDelivery != nil {
|
||||||
shippingCostMap[transfer.Details[i].Id] = deliveryItem.StockTransferDelivery.ShippingCostTotal
|
shippingCostMap[transfer.Details[i].Id] = deliveryItem.StockTransferDelivery.ShippingCostTotal
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -395,17 +390,14 @@ func (b *transferExpenseBridge) OnItemsDelivered(c *fiber.Ctx, transferID uint64
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
shippingCostTotal := shippingCostMap[detail.Id]
|
shippingCostTotal := shippingCostMap[detail.Id]
|
||||||
|
|
||||||
|
|
||||||
totalPrice := shippingCostTotal
|
totalPrice := shippingCostTotal
|
||||||
if payload.TransportPerItem != nil {
|
if payload.TransportPerItem != nil {
|
||||||
|
|
||||||
totalPrice = *payload.TransportPerItem * payload.DeliveredQty
|
totalPrice = *payload.TransportPerItem * payload.DeliveredQty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
warehouseID := uint(payload.WarehouseID)
|
warehouseID := uint(payload.WarehouseID)
|
||||||
if warehouseID == 0 && transfer.ToWarehouse != nil {
|
if warehouseID == 0 && transfer.ToWarehouse != nil {
|
||||||
warehouseID = uint(transfer.ToWarehouse.Id)
|
warehouseID = uint(transfer.ToWarehouse.Id)
|
||||||
|
|||||||
@@ -621,6 +621,9 @@ func (b *expenseBridge) createExpenseViaService(
|
|||||||
if _, err := approvalSvc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(detail.Id), utils.ExpenseStepManager, &action, actorID, nil); err != nil {
|
if _, err := approvalSvc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(detail.Id), utils.ExpenseStepManager, &action, actorID, nil); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if _, err := approvalSvc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(detail.Id), utils.ExpenseStepUnitVicePresident, &action, actorID, nil); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if _, err := approvalSvc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(detail.Id), utils.ExpenseStepFinance, &action, actorID, nil); err != nil {
|
if _, err := approvalSvc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(detail.Id), utils.ExpenseStepFinance, &action, actorID, nil); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-11
@@ -354,20 +354,22 @@ var MarketingApprovalSteps = map[approvalutils.ApprovalStep]string{
|
|||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ApprovalWorkflowExpense approvalutils.ApprovalWorkflowKey = approvalutils.ApprovalWorkflowKey("EXPENSES")
|
ApprovalWorkflowExpense approvalutils.ApprovalWorkflowKey = approvalutils.ApprovalWorkflowKey("EXPENSES")
|
||||||
ExpenseStepPengajuan approvalutils.ApprovalStep = 1
|
ExpenseStepPengajuan approvalutils.ApprovalStep = 1
|
||||||
ExpenseStepManager approvalutils.ApprovalStep = 2
|
ExpenseStepManager approvalutils.ApprovalStep = 2
|
||||||
ExpenseStepFinance approvalutils.ApprovalStep = 3
|
ExpenseStepUnitVicePresident approvalutils.ApprovalStep = 3
|
||||||
ExpenseStepRealisasi approvalutils.ApprovalStep = 4
|
ExpenseStepFinance approvalutils.ApprovalStep = 4
|
||||||
ExpenseStepSelesai approvalutils.ApprovalStep = 5
|
ExpenseStepRealisasi approvalutils.ApprovalStep = 5
|
||||||
|
ExpenseStepSelesai approvalutils.ApprovalStep = 6
|
||||||
)
|
)
|
||||||
|
|
||||||
var ExpenseApprovalSteps = map[approvalutils.ApprovalStep]string{
|
var ExpenseApprovalSteps = map[approvalutils.ApprovalStep]string{
|
||||||
ExpenseStepPengajuan: "Pengajuan",
|
ExpenseStepPengajuan: "Pengajuan",
|
||||||
ExpenseStepManager: "Approval Manager",
|
ExpenseStepManager: "Approval Head Area",
|
||||||
ExpenseStepFinance: "Approval Finance",
|
ExpenseStepUnitVicePresident: "Approval Business Unit Vice President",
|
||||||
ExpenseStepRealisasi: "Realisasi",
|
ExpenseStepFinance: "Approval Finance",
|
||||||
ExpenseStepSelesai: "Selesai",
|
ExpenseStepRealisasi: "Realisasi",
|
||||||
|
ExpenseStepSelesai: "Selesai",
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user