I am customizing APInvoiceEntry graph, when it is modified in the Bills and Adjustments Screen (ID=AP301000).
The field curyOrigDiscAmt is set when items are added in the POItem portion of the graph. There is logic that calculates the discount based on payment type (eg Cash Prepayment) and what is set on the vendor class.
This is the default behavior. However, after that runs, I have logic I want to run that adjusts this figure.
I thought I could simply put my logic in a "field changing" method. But none of the actions I can find are activated when the change to curyOrigDiscAmt happens.
So far, I have tried:
protected virtual void _(Events.FieldVerifying<APInvoice, APInvoice.curyOrigDiscAmt> e)
protected virtual void _(Events.FieldUpdated<APInvoice, APInvoice.curyOrigDiscAmt> e)
protected void APInvoice_CuryOrigDiscAmt_FieldUpdating(PXCache cache, PXFieldUpdatingEventArgs e)
protected virtual void _(Events.RowSelecting<APInvoice> e)
None of them fire when the field is changed. I need to reflected in the UI for the user to see, so it doesn't do any good to change it when the record is saved. I need it to happen right after the base code runs that does the calculation.
Where is that? How do I find it?
[EDIT -- Follow-up to Hugues Beauséjour's answer below]
Is there a way to just raise the events without having to change the CalcDisc() method at all? All I need are the events to be called.
In other words something sort of like:
protected override void CalcDisc(PXCache sender, PXFieldUpdatedEventArgs e)
{
base.CalcDisc(sender, e);
base.RaiseEvents(EVENTLIST_TO_RAISE);
}
I would rather not change the code at all if I could help it to keep it more bulletproof to future changes...
The value is computed in the Terms
attribute decorating APInvoice.TermsID
field:
#region TermsID
public abstract class termsID : PX.Data.BQL.BqlString.Field<termsID> { }
/// <summary>
/// The <see cref="PX.Objects.CS.Terms">credit terms</see> associated with the document (unavailable for prepayments and debit adjustments).\
/// Defaults to the <see cref="Vendor.TermsID">credit terms of the vendor</see>.
/// </summary>
[PXDBString(10, IsUnicode = true)]
[PXDefault(typeof(Search<Vendor.termsID,
Where<Vendor.bAccountID, Equal<Current<APInvoice.vendorID>>,
And<Current<APInvoice.docType>, NotEqual<APDocType.debitAdj>>>>),
PersistingCheck = PXPersistingCheck.Nothing)]
[PXUIField(DisplayName = "Terms", Visibility = PXUIVisibility.Visible)]
[APTermsSelector]
[Terms(typeof(APInvoice.docDate), typeof(APInvoice.dueDate), typeof(APInvoice.discDate),
typeof(APInvoice.curyOrigDocAmt), typeof(APInvoice.curyOrigDiscAmt))]
public virtual string TermsID
{
get;
set;
}
#endregion
It is the last parameter of the TermsAttribute
class constructor: CuryDiscBal
public TermsAttribute(Type DocDate, Type DueDate, Type DiscDate, Type CuryDocBal, Type CuryDiscBal)
{
_DocDate = DocDate;
_DueDate = DueDate;
_DiscDate = DiscDate;
_CuryDiscBal = CuryDiscBal;
_CuryDocBal = CuryDocBal;
}
The final value is computed in the CalcDisc
method of Terms
attribute. It is assigned with SetValue
method which does not raise events:
protected virtual void CalcDisc(PXCache sender, PXFieldUpdatedEventArgs e)
{
if (_CuryDocBal != null && _CuryDiscBal != null &&
sender.GetValue(e.Row, _FieldName) != null &&
sender.GetValue(e.Row, _CuryDocBal.Name) != null && !sender.Graph.IsCopyPasteContext)
{
string TermsID = (string)sender.GetValue(e.Row, _FieldName);
decimal CuryDocBal = (decimal)sender.GetValue(e.Row, _CuryDocBal.Name);
decimal CuryDiscBal = 0m;
Terms terms = SelectTerms(sender.Graph, TermsID);
if (terms != null && terms.InstallmentType == TermsInstallmentType.Single && CuryDocBal > 0m)
{
CuryDiscBal = PXDBCurrencyAttribute.Round(sender, e.Row, CuryDocBal * (decimal)terms.DiscPercent / 100, CMPrecision.TRANCURY);
}
sender.SetValue(e.Row, _CuryDiscBal.Name, CuryDiscBal);
PXUIFieldAttribute.SetEnabled(sender, e.Row, _CuryDiscBal.Name, (terms.InstallmentType == TermsInstallmentType.Single));
}
}
To override it you could substitute the Terms attribute with a custom attribute based on the original TermsAttribute
class. Then you override field APInvoice.TermsID
and decorate it with the custom attribute to replace the original Terms. Changing the SetValue
assignment to use SetValueExt
should raise the field updating/updated events.