We would like to display an error to the user if the Project Budget exceeds while adding the details in Purchase Order and stop them from removing it from hold.
Acumatica does some calculation on page load and displays a warning when the budget is exceeded as shown below:
This is the budget in the project:
For the Project, Project Task, Cost Code and Account Group combination, the budget in project is 1500 but in PO is 1501, so it is displaying the warning message.
There are other logic as well which I do not know yet and it is complex if I have to replicate the logic.
My job is to see if the budget is exceeded or not if it is exceeding, I need to give a message to user and stop from proceeding further.
Things I have tried:
Tried to implement the logic by myself but I am missing certain scenarios like the line item in PO can be marked as closed/cancelled, so they need to be treated differently.
Catch the warning and show it as an error but the warning message is inconsistent. There are many instances where the warning was not shown although the budget exceeded and after reload it comes back.
From my analysis the code from Acumatica is in class BudgetControlGraph. Is there a way I could re-use the logic or replicate it for my requirement and How?
You can override the persist method for POOrderEntry graph and fetch the budget based on Projects and show the exception based on data fetched.
you can try below code snippet.
// Override the method that handles the removal of the hold statuspublicdelegatevoidPersistDelegate();
[PXOverride]
publicvoidPersist(PersistDelegate baseMethod)
{
// Get the current Purchase Order record
POOrder currentOrder = Base.Document.Current;
if (currentOrder != null)
{
// Check if the budget is exceededbool isBudgetExceeded = CheckProjectBudgetExceeded(currentOrder);
// If the budget is exceeded, display an error and stop the processif (isBudgetExceeded)
{
thrownew PXException("The project budget has been exceeded. You cannot proceed.");
}
}
// Call the base method to proceed with saving the order
baseMethod();
}
privateboolCheckProjectBudgetExceeded(POOrder currentOrder)
{
// Flag to track whether the budget is exceededbool isExceeded = false;
foreach (POLine line in Base.Transactions.Select())
{
// Skip lines that are closed or cancelledif (line.Closed == true || line.Cancelled == true)
continue;
// Fetch the budget for the project, task, cost code, and account group combination
PMBudget projectBudget = PXSelect<PMBudget,
Where<PMBudget.projectID, Equal<Required<PMBudget.projectID>>,
And<PMBudget.projectTaskID, Equal<Required<PMBudget.projectTaskID>>,
And<PMBudget.costCodeID, Equal<Required<PMBudget.costCodeID>>,
And<PMBudget.accountGroupID, Equal<Required<PMBudget.accountGroupID>>>>>>>
.Select(Base, line.ProjectID, line.TaskID, line.CostCodeID, line.ExpenseAcctID);
if (projectBudget != null)
{
// Calculate the total committed amount (in this case, the amount from PO lines)decimal totalAmount = line.CuryLineAmt ?? 0m;
// Compare the committed amount with the budgeted amountif (projectBudget.CuryAmount.GetValueOrDefault() < totalAmount)
{
isExceeded = true;
break;
}
}
}
return isExceeded;
}
Hope, it helps!
Note: I have not tried above code as working , you can change logic as per your scenario.
You can override the persist method for POOrderEntry graph and fetch the budget based on Projects and show the exception based on data fetched.
you can try below code snippet.
// Override the method that handles the removal of the hold statuspublicdelegatevoidPersistDelegate();
[PXOverride]
publicvoidPersist(PersistDelegate baseMethod)
{
// Get the current Purchase Order record
POOrder currentOrder = Base.Document.Current;
if (currentOrder != null)
{
// Check if the budget is exceededbool isBudgetExceeded = CheckProjectBudgetExceeded(currentOrder);
// If the budget is exceeded, display an error and stop the processif (isBudgetExceeded)
{
thrownew PXException("The project budget has been exceeded. You cannot proceed.");
}
}
// Call the base method to proceed with saving the order
baseMethod();
}
privateboolCheckProjectBudgetExceeded(POOrder currentOrder)
{
// Flag to track whether the budget is exceededbool isExceeded = false;
foreach (POLine line in Base.Transactions.Select())
{
// Skip lines that are closed or cancelledif (line.Closed == true || line.Cancelled == true)
continue;
// Fetch the budget for the project, task, cost code, and account group combination
PMBudget projectBudget = PXSelect<PMBudget,
Where<PMBudget.projectID, Equal<Required<PMBudget.projectID>>,
And<PMBudget.projectTaskID, Equal<Required<PMBudget.projectTaskID>>,
And<PMBudget.costCodeID, Equal<Required<PMBudget.costCodeID>>,
And<PMBudget.accountGroupID, Equal<Required<PMBudget.accountGroupID>>>>>>>
.Select(Base, line.ProjectID, line.TaskID, line.CostCodeID, line.ExpenseAcctID);
if (projectBudget != null)
{
// Calculate the total committed amount (in this case, the amount from PO lines)decimal totalAmount = line.CuryLineAmt ?? 0m;
// Compare the committed amount with the budgeted amountif (projectBudget.CuryAmount.GetValueOrDefault() < totalAmount)
{
isExceeded = true;
break;
}
}
}
return isExceeded;
}
Hope, it helps!
Note: I have not tried above code as working , you can change logic as per your scenario.
We use 3 different kinds of cookies. You can choose which cookies you want to accept. We need basic cookies to make this site work, therefore these are the minimum you can select. Learn more about our cookies.