One of the most often called customization requests is to default (or update) a Field A, based on what was entered in a Field B. And now its time for me to post a memo article on standard technique for this customization.
Lets define a scope of work:
1. When we issue an invoice to a customer.
2. And then select a Project used by this customer.
3. We have to default a Customer Ref Number field with a Project Purchase Order Number.
4. Which is, in its own case, an Attribute of a Project, and has to be retrieved from there.
5. PO Number is defined in Project Module "Attributes" screen and entered into a "Project" Maintenance screen.
Something like this:
In the video below I comment on customization done. Please find the code for the customization below.
Here is the code:
using System;
using System.Collections;
using System.Collections.Generic;
using PX.Data;
using PX.Objects.GL;
using PX.Objects.CM;
using PX.Objects.CS;
using PX.Objects.CR;
using PX.Objects.TX;
using PX.Objects.IN;
using PX.Objects.BQLConstants;
using PX.Objects.EP;
using PX.TM;
using SOInvoice = PX.Objects.SO.SOInvoice;
using SOInvoiceEntry = PX.Objects.SO.SOInvoiceEntry;
using PX.Objects.SO;
using PX.Objects.DR;
using PX.Objects;
using PX.Objects.AR;
using PX.Objects.PM;
namespace PX.Objects.AR
{
[PXCustomization]
public class Cst_ARInvoiceEntry: ARInvoiceEntry
{
#region Event Handlers
protected override void ARInvoice_ProjectID_FieldUpdated(PXCache sender, PXFieldUpdatedEventArgs e)
{
base.ARInvoice_ProjectID_FieldUpdated(sender, e);
var row = (ARInvoice)e.Row;
var ProjectID = row.ProjectID;
var CustRefNbr = row.InvoiceNbr;
string EntityType = "PR";
string Attribute = "PONUMBER";
//CustRefNbr = CustRefNbr + 1;
PMProject pm = PXSelect<PMProject,
Where<PMProject.baseType, Equal<PMProject.ProjectBaseType>, And<PMProject.nonProject, Equal<False>, And<PMProject.contractID, Equal<Current<ARInvoice.projectID>>, And<PMProject.isTemplate, NotEqual<True>>>>>>.SelectSingleBound(this, new object [] { e.Row });
if (pm != null)
{
//CustRefNbr = pm.ContractCD;
PXResultset<CSAnswers> res = PXSelectJoin<CSAnswers,
InnerJoin<CSAttribute, On<CSAttribute.attributeID, Equal<CSAnswers.attributeID>>>,
Where<CSAnswers.entityType, Equal<Required<CSAnswers.entityType>>,
And<CSAnswers.attributeID, Equal<Required<CSAnswers.attributeID>>,
And<CSAnswers.entityID, Equal<Required<CSAnswers.entityID>>>>>>.Select(this, EntityType, Attribute, pm.ContractID);
CSAnswers ans = res;
if (ans.Value != null)
{
//CustRefNbr = ans.Value;
ARInvoice line = sender.CreateCopy(row) as ARInvoice;
line.InvoiceNbr = ans.Value;
sender.Update(line);
//string msg = CustRefNbr;
//throw new PXSetPropertyException(msg);
//row.InvoiceNbr = CustRefNbr;
}}}
#endregion
}
}
All the best,
Sergey.
Sergey, can you talk about accessing and modifying attribute fields in general? There is a serious lack of that information in Acumatica. For instance accessing and modifying attributes in Stock Items.
ReplyDeleteHi, thanks for asking. Just found a learning video on adding attributes. https://youtu.be/igpoOIUJ1hU But I believe you need something more comprehensive, like where they stored and how to access them?
DeleteHow would you update the Attribute programmatically from a custom field instead of the other way around?
ReplyDeleteThere is no difference between what you call Attribute and Custom Field. As long as these fields are in a DAC, they treated the same way. I recommend you to post development case or take some development training as a reference for the development example as well.
DeleteIn this example you update a custom field from an attribute. How would you update the attribute from a custom field or from another attribute?
ReplyDeleteFor example if I had existing Attribute called PCNumber on Contacts and I wanted to Update the PCNumber Attribute on a Case depending on the Contact selected...
You mean on cases not a single case, as there could be multiple cases attached to a contact? You need to write a code a assume that selects all the cases, and updates them one by one.
Delete