Copying the value from a custom field to TaxRegistrationID field in RowPersisting event - acumatica

I'm trying to copy the value from a custom field called "customerExt.UsrRfc" to TaxRegistrationID field but it doesn't work in Customers screen, I'm using Customer_RowPersisting event handler.
This is the customerExt.UsrRfc field:
This is the TaxRegistrationID field:
This is the RowPersisting event:
protected void Customer_RowPersisting(PXCache cache, PXRowPersistingEventArgs e)
{
Customer row = (Customer)e.Row;
if (row == null)
{
return;
}
var customerExt = row.GetExtension<BAccountExt>();
row.TaxRegistrationID = customerExt.UsrRfc;
}
I tried to copy the value to another field like "Account Ref #" and it works fine.
Can you help me with this?

The TaxRegistrationID field in the screenshot is from Location DAC instead of Customer:
You need to change the solution to update the field in the correct view.

Related

How can I save value of user-defined in the database without clicking the save button

I have created a user-defined field (Last Activity Date) on the Opportunities (CR304000) screen which is populated from the last Start Date of the activity on the Activities tab of the Opportunities screen (CR304000) on RowSelected as shown on screenshot one. When an activity is added for an opportunity, the user is not required to click the save button on the form of the opportunity, therefore the user-defined field I have added does not save the value to the database. I would like the value of the user-defined field to be saved to the database whenever an activity is added to the opportunity and the value of the user-defined field changes without having to click the save button on the opportunity form as I need to use it on a generic Inquiry.
Screenshot 1
Code Snippet:
protected void CROpportunity_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
var row = (PX.Objects.CR.CROpportunity)e.Row;
if (row == null)
{
return;
}
CRActivity cRActivity = PXSelect<CRActivity, Where<CRActivity.refNoteID, Equal<Required<PX.Objects.CR.CROpportunity.noteID>>>, OrderBy<Desc<CRActivity.startDate>>>.Select(Base, row.NoteID);
if (cRActivity == null)
{
return;
}
CROpportunityExt cROpportunityExt = row.GetExtension<CROpportunityExt>();
cROpportunityExt.UsrLastActivity = cRActivity.StartDate;
Base.Opportunity.SetValueExt<CROpportunityExt.usrLastActivity>(Base.Opportunity.Current, cROpportunityExt.UsrLastActivity);
Base.Save.SetPressed(true);
}
In my opinion, push the value to the opportunity instead from the CRActivityMaint graph in the CRActivity RowPersisted event instead of pulling it from the activity in CROpportunity RowSelected. It is not good practice to change values of DAC rows in the RowSelected event.
Your code would be as follows
In CRActivityMaintExt
In RowPersisted
if (!(e.Row?.EntityDescription?.ToLower().Contains("opportunity") ?? false)) return;
CROpportunity opportunity = SelectFrom<CROpportunity>.Where<CROpportunity.noteID.IsEqual<#P.asGuid>>.View.Readonly.Select(Base, e.Row.RefNoteID);
if (opportunity is null) return;
var oppExt = opportunity.GetExtension<YourExtension>();
oppExt.YourValue = e.Row.SomeValue;
Base.Caches<CROpportunity>().PersistUpdated(opportunity);

How do I use the user set value of a DAC extension to enable/disable a UI field of the Base DAC?

I added a bool field to APVendorPrice that needs to be enabled only when a SiteID is entered in the APVendorPriceMaint graph. Likewise, if it is set true, it needs to disable the SiteID field. By creating a graph extension for APVendorPriceMaint, I can tap into the APVendorPrice_RowSelected event to enable/disable my custom field easily. However, when I set my new field to Commit Changes = true, the user entry value of my DAC extension field is lost to me.
How do I get the user entered value on my DAC extension field?
protected virtual void APVendorPrice_RowSelected(PXCache sender, PXRowSelectedEventArgs e, PXRowSelected baseEvent)
{
APVendorPrice row = (APVendorPrice)e.Row;
APVendorPriceExt vendorPriceExt = sender.GetExtension<APVendorPriceExt>(row);
baseEvent(sender, e);
PXUIFieldAttribute.SetEnabled<APVendorPrice.siteID>(sender, row, vendorPriceExt?.UsrMyField != true);
PXUIFieldAttribute.SetEnabled<APVendorPriceExt.UsrMyField>(sender, row, row?.SiteID != null);
}
The GetExtension always returns the saved value rather than seeing that the user toggled the value.
How do I see the user entered value for UsrMyField so that I can enable/disable access to SiteID?

I need to conditionally set a field to be required

I'm customizing the Sales Order screen as follows:
I've added a custom boolean field added to the Order Types screen called 'Require Customer Order Number'.
I've added code to the BLC of the Sales Order screen where I want to conditionally make the CustomerOrderNumber field required, based on whether the 'Require Customer Order Number' field is checked or not.
I'm using the SOOrder_RowSelected event as follows:
protected virtual void SOOrder_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
var soorder = (SOOrder)e.Row;
if (soorder == null) return;
string ordtype = soorder.OrderType;
var soot = (SOOrderType)PXSelect<SOOrderType,
Where<SOOrderType.orderType, Equal<Required<SOOrderType.orderType>>>>.Select(Base, ordtype);
if (soot != null)
{
var sootext = PXCache<SOOrderType>.GetExtension<SOOrderTypeExt>(soot);
if (sootext != null)
{
PXUIFieldAttribute.SetRequired<SOOrder.customerOrderNbr>(sender, sootext.UsrRequireCustOrdNbr == null ? false : (bool)sootext.UsrRequireCustOrdNbr);
}
}
}
This DOES put an asterisk on the CustomerOrderNumber field - but it doesn't spawn an error upon save if that field is empty.
Another issue is my PXSelect to get the record out of SOOrderType ALWAYS returns a null for the check box user field, even if it has a 'True' value in the database (which is why I put the ternary operator on the call). Even if I hard-code a 'true' value in the PXUIFieldAttribute.SetRequired call, it still doesn't spawn the error to prevent a save. The asterisk is there, but it doesn't work.
If I use a Cache_Attached event to add [PXDefault] it works perfectly - but this doesn't help me - I need it conditionally set.
Any ideas?
Required is used only for displaying the asterisk. PXDefault attribute is the one that makes the field mandatory based on PersistingCheck property value.
The issue is that PXUIFieldAttributes like PersistingCheck can only be set once at the time of graph creation. You can set it dynamically in the constructor/Initialize method but if you change the property after that it has no effects.
When I need a field to be mandatory based on a dynamic condition I remove the PXDefault attribute and validate the field manually in event handlers like RowPersisting:
public void PMTimeActivity_RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
{
PMTimeActivity timeActivity = e.Row as PMTimeActivity;
if (timeActivity != null && PMTimeActivity.timeSpent == null)
{
PXUIFieldAttribute.SetError<PMTimeActivity.timeSpent>(sender, timeActivity, "'Time Spent' cannot be empty."));
}
}

Unbound fields on DAC extension - where to populate?

I have extended the CRMarketingListMember DAC in order to include a number of unbound fields. I'm adding these new unbound fields to the List Members grid on CR204000 and need to execute some code in order to put values into these fields when the List Members grid is displayed. The problem is that my unbound fields are always blank in the grid. I've tried extending the CRMarketingListMaint graph and putting the code that populates the unbound fields into the CRMarketingList_RowSelected() event but that, of course, doesn't work.
Thanks for the help!
RowSelecting is the proper event in which to populate unbound fields, if doing additional BQL selects make sure to wrap the logic in a new PXConnectionScope.
Example Below :
public virtual void ARInvoice_RowSelecting(PXCache sender, PXRowSelectingEventArgs e)
{
ARInvoice row = e.Row as ARInvoice;
if (row != null)
{
using (new PXConnectionScope())
{
ARRegisterExtension rowExt = PXCache<ARRegister>.GetExtension<ARRegisterExtension>(row);
var result = PXSelect<.....>
rowExt.UsrISExternalTax = result.IsExternalTax;
}
}
}

How to assign Invoice RefNbr before saving the invoice

I have set my invoice to Manual Numbering
And I want to assign the invoice number(RefNbr) - if blank, before saving the invoice (AR301000). I've overridden the RowPersisting event as follow:
public class ARInvoiceEntry_Extension:PXGraphExtension<ARInvoiceEntry>
{
protected void ARInvoice_RowPersisting(PXCache cache, PXRowPersistingEventArgs e, PXRowPersisting InvokeBaseHandler)
{
var row = (ARInvoice)e.Row;
if (row != null)
{
//BB-<timestamp> as inv# for testing only
if (string.IsNullOrEmpty(row.RefNbr))
row.RefNbr = "BB-" + DateTime.Now.ToString("hhmmsstt");
}
if(InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
}
}
If I raised a new invoice w/out any lines and saved it. It correctly assigned the Reference Nbr as expected.
Problem is if I raised a new invoice WITH lines. Its complaining that the RefNbr is blank.
What am I missing ? How do I fix this ? Thanks.
Acumatica's PXDBDefaultAttribute only updates field of the dependent records when both the source field of the parent record and the foreign key field of the dependent record are not empty.
When a dependent record is inserted into the cache, PXDBDefaultAttribute will copy the source field value from the parent record to the field it decorates from the dependent record. While the framework is saving new parent record into the database, it first raises RowPersisting event for the parent record. PXDBDefaultAttribute subscribes to the RowPersisting event of the parent record type to save the original source field value:
to locate the parent record after it was saved to the database
or to use it as a restore point for the dependent field in case of an aborted transaction
Also, PXDBDefaultAttribute subscribes to the RowPersisting event of the dependent record type to update the foreign key field with the actual source field value, that has just been recorded in the database. To update the foreign key field PXDBDefaultAttribute must first locate the parent record using the original source field value obtained earlier in the RowPersisting event handler of the parent record type. In case the foreign key field value appears to be empty, there is no chance for PXDBDefaultAttribute to locate the parent record for it and it simply leaves the dependent field empty. This is what eventually is causing the error "RefNbr cannot be empty".
With all that being said, I believe it won't be possible to achieve the desired results if leaving AR Invoice Reference Number empty until it gets saved to the database. As an alternative, let me suggest to default AR Invoice Reference Number to some constant, like < ENTER >, and at the same time replace it with the actual number within the ARInvoice_RowPersisting handler:
using PX.Data;
using System;
namespace PX.Objects.AR
{
public class ARInvoiceNumberingCstAttribute : ARInvoiceType.NumberingAttribute
{
public const string EnterRefNbr = "<ENTER>";
protected override string GetNewNumber()
{
string newNumber = base.GetNewNumber();
if (string.IsNullOrEmpty(newNumber))
{
newNumber = EnterRefNbr;
}
return newNumber;
}
public override void RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
{
if (GetNewNumber() == EnterRefNbr) return;
base.RowPersisting(sender, e);
}
}
public class ARInvoiceEntry_Extension : PXGraphExtension<ARInvoiceEntry>
{
[PXRemoveBaseAttribute(typeof(ARInvoiceType.NumberingAttribute))]
[PXMergeAttributes(Method = MergeMethod.Append)]
[ARInvoiceNumberingCst]
protected void ARInvoice_RefNbr_CacheAttached(PXCache sender)
{ }
protected void ARInvoice_RowPersisting(PXCache cache, PXRowPersistingEventArgs e,
PXRowPersisting InvokeBaseHandler)
{
if (InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (ARInvoice)e.Row;
if (row != null)
{
//BB-<timestamp> as inv# for testing only
if (row.RefNbr == ARInvoiceNumberingCstAttribute.EnterRefNbr)
row.RefNbr = "BB-" + DateTime.Now.ToString("hhmmsstt");
}
}
}
}

Resources