Hi Just wondering if you managed to find a solution for this as requirement has come up for a client, thanks
Hi @rajeshmishra90,
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 status
public delegate void PersistDelegate();
>PXOverride]
public void Persist(PersistDelegate baseMethod)
{
// Get the current Purchase Order record
POOrder currentOrder = Base.Document.Current;
if (currentOrder != null)
{
// Check if the budget is exceeded
bool isBudgetExceeded = CheckProjectBudgetExceeded(currentOrder);
// If the budget is exceeded, display an error and stop the process
if (isBudgetExceeded)
{
throw new PXException("The project budget has been exceeded. You cannot proceed.");
}
}
// Call the base method to proceed with saving the order
baseMethod();
}
private bool CheckProjectBudgetExceeded(POOrder currentOrder)
{
// Flag to track whether the budget is exceeded
bool isExceeded = false;
foreach (POLine line in Base.Transactions.Select())
{
// Skip lines that are closed or cancelled
if (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 amount
if (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.
Thanks so much will give it a crack!
Hello @rajeshmishra90 ,
Have you tried extending the BudgetControlGraph of the POOrderEntry and override RowSelected event to set the error on field?
public class POOrderEntryExt : BudgetControlGraph<POOrderEntry>
Here is the sample code may help you.
public class POOrderEntryExtExt : PXGraphExtension<POOrderEntryExt, POOrderEntry>
{
public static bool IsActive() => POOrderEntryExt.IsActive();
protected virtual void _(Events.RowSelected<POOrder> e, PXRowSelected baseEvent)
{
baseEvent?.Invoke(e.Cache, e.Args);
// Validate and return if no Budget Control is required
// TODO: Add code to validate
foreach (PMBudgetControlLine budgetControlLine in Base1.BudgetControlLines.Cache.Inserted)
{
if (budgetControlLine.RemainingAmount < 0)
{
e.Cache.RaiseExceptionHandling<POOrder.curyOrderTotal>(e.Row, e.Row.CuryOrderTotal,
new PXSetPropertyException(e.Row, PX.Objects.PM.Messages.BudgetControlDocumentWarning, PXErrorLevel.RowError));
return;
}
}
}
}
Note: I have not tested the above code.
@rajeshmishra90 , Hope the above code work for you.