Customizing Selector when another another Selector value changes - acumatica

I need to Customize CaseClassID Selector on Cases Screen. It should refresh with different values when Contract field is selected on the CaseScreen under the Additional Info tab. Right now the CaseClass is displaying values from CRCase table.But, now if the contract changes the fieldupdatedEvent should be triggered and CaseClassID selector should have values accordingly. Please suggest me how to customize the CaseClassID selector inside FieldUpdated Event Handler
protected virtual void CRCase_ContractID_FieldUpdated(PXCache sender,
PXFieldUpdatedEventArgs e)
{
CRCase cc = (CRCase)e.Row;
if (cc == null) return;
CRCase_CaseClassID_CacheAttached(sender);
}
[PXMergeAttributes(Method = MergeMethod.Replace)]
[PXDBString(10, IsUnicode = true, InputMask = ">aaaaaaaaaa")]
[PXDefault(typeof(Search<CRSetup.defaultCaseClassID>))]
[PXUIField(DisplayName = "Class ID")]
[PXSelector(typeof(Search2<CRCaseClass.caseClassID,
InnerJoin<CaseContract, On<CaseContract.caseClassID,
Equal<CRCaseClass.caseClassID>>,
InnerJoin<Contract, On<CaseContract.contractID,
Equal<Contract.templateID>>,
InnerJoin<CRCase, On<Contract.contractID,
Equal<Current<CRCase.contractID>>>>>>,
Where<CaseContract.active, Equal<True>>>),
DescriptionField = typeof(CRCaseClass.description),
CacheGlobal = true)]
[PXMassUpdatableField]
public virtual String CaseClassID { get; set; }
public virtual void CRCase_CaseClassID_CacheAttached(PXCache sender){
}

Override CaseClassID selector and add your custom logic in its type parameter.
You can create a custom unbound field to filter the selector according to your business logic. When you want to change selector filter, just change the custom field.
#region CaseClassID
public abstract class caseClassID : IBqlField { }
[PXDBString(10, IsUnicode = true, InputMask = ">aaaaaaaaaa")]
[PXDefault(typeof(Search<CRSetup.defaultCaseClassID>))]
[PXUIField(DisplayName = "Class ID")]
// Use your custom field (filterCaseClassID) in the selector type parameter
[PXSelector(typeof(Search<CRCaseClass.caseClassID,
Where<CRCaseClass.caseClassID, Equal<filterCaseClassID>>>),
DescriptionField = typeof(CRCaseClass.description),
CacheGlobal = true)]
[PXMassUpdatableField]
public virtual String CaseClassID { get; set; }
#endregion
#region FilterCaseClassID
public abstract class filterCaseClassID : IBqlField { }
[PXDBString(10, IsUnicode = true, InputMask = ">aaaaaaaaaa")]
// Change the value of your custom field to set the selector filter
public virtual String FilterCaseClassID { get; set; }
#endregion
EDIT overriding DAC field in graph extension and filtering Selector by using a field from another DAC:
using PX.Data;
using PX.Objects.CR.MassProcess;
using System;
namespace PX.Objects.CR
{
[Serializable]
public class CaseContract : IBqlTable
{
public abstract class caseClassID : IBqlField { }
[PXString(10, IsUnicode = true)]
[PXUIField(DisplayName = "Case Class ID")]
[PXSelector(typeof(CRCaseClass.caseClassID),
DescriptionField = typeof(CRCaseClass.description))]
public virtual String CaseClassID
{
get; set;
}
}
public class CRCaseMaint_Extension : PXGraphExtension<CRCaseMaint>
{
[PXMergeAttributes(Method = MergeMethod.Replace)]
[PXDBString(10, IsUnicode = true, InputMask = ">aaaaaaaaaa")]
[PXDefault(typeof(Search<CRSetup.defaultCaseClassID>))]
[PXUIField(DisplayName = "Class ID")]
[PXSelector(typeof(Search<CRCaseClass.caseClassID,
Where<Current<CaseContract.caseClassID>, IsNull,
Or<CRCaseClass.caseClassID, Equal<Current<CaseContract.caseClassID>>>>>),
DescriptionField = typeof(CRCaseClass.description),
CacheGlobal = true)]
[PXMassUpdatableField]
public virtual void CRCase_CaseClassID_CacheAttached(PXCache sender)
{
}
}
}

Related

Adding custom fields to Bills and Adjustment screen causes "nullable object must have a value"

I have a customization to the Bills and Adjustments screen (AP301000), where I'm simply adding 4 user fields to the Document Details tab's grid. I've done this many, many times in the past and I've never seen this error. I have absolutely NO idea what would cause it.
Here's the DAC extension:
[PXCacheName("AP Tran Extension")]
public class APTranExt : PXCacheExtension<APTran>
{
#region UsrACAllocModule
[PXDBString(30, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Allocation Module")]
public virtual string UsrACAllocModule { get; set; }
public abstract class usrACAllocModule : PX.Data.BQL.BqlString.Field<usrACAllocModule> { }
#endregion
#region UsrACAllocBatch
[PXDBString(30, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Allocation Batch")]
public virtual string UsrACAllocBatch { get; set; }
public abstract class usrACAllocBatch : PX.Data.BQL.BqlString.Field<usrACAllocBatch> { }
#endregion
#region UsrACAllocLineNbr
[PXDBInt()]
[PXUIField(DisplayName = "Allocation LineNbr")]
public virtual int? UsrACAllocLineNbr { get; set; }
public abstract class usrACAllocLineNbr : PX.Data.BQL.BqlInt.Field<usrACAllocLineNbr> { }
#endregion
#region UsrACAllocationID
[PXDBString(30, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Allocation ID")]
public virtual string UsrACAllocationID { get; set; }
public abstract class usrACAllocationID : PX.Data.BQL.BqlString.Field<usrACAllocationID> { }
#endregion
}
The database fields exist as follows:
Here is how the fields are added:
And here is the error:
We ran across the same issue. It is a bug in Acumatica. It is resolved in build 20.104.

Enabling "AllowAddNew" and/or "AllowEdit" on selector for custom DAC

I have created a custom DAC, Graph, and Screen to manage tracking of new entity for client, called "Management Company." New screen is simple Grid with CRUD controls. Selector on Customer screen allows me to choose from list of "Management Company" entries. I also added new field to Contact DAC and DB table to track which "Management Company" is assigned to a given contact. This field is where the selector is configured.
I am trying to enable the "AllowAddNew" and/or "AllowEdit" properties of this selector. When I set to "True," the buttons show up but they don't do anything.
I can create and save new entries to this DB table via the new screen and I can retrieve them with the Selector just fine. I just can't create new from selector.
I have tried looking this up and I'm not finding much information.
How can I achieve this?
Sample of DAC:
namespace PX.Objects.CR
{
[Serializable]
public class UsrCustomerManagementCompany : IBqlTable
{
#region MancompID
[PXDBString(16, IsUnicode = true, InputMask = ">LLLLLLLLLLLLLLLL", IsKey = true)]
[PXUIField(DisplayName = "Company ID")]
[PXDefault]
public virtual string MancompID { get; set; }
public abstract class mancompID : IBqlField { }
#endregion
#region MancompName
[PXDBString(60, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Company Name")]
[PXDefault]
public virtual string MancompName { get; set; }
public abstract class mancompName : IBqlField { }
#endregion
#region MancompDescr
[PXDBString(4000, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Description")]
public virtual string MancompDescr { get; set; }
public abstract class mancompDescr : IBqlField { }
#endregion
}
}
Graph:
using System;
using PX.Data;
using PX.Objects.CR;
namespace ClientCode
{
public class ManagementCompanyMaint : PXGraph<ManagementCompanyMaint, UsrCustomerManagementCompany>
{
public PXSelect<UsrCustomerManagementCompany> ManagementCompanies;
}
}
Contact DAC Extension and Selector:
namespace PX.Objects.CR
{
public class ContactExt : PXCacheExtension<PX.Objects.CR.Contact>
{
#region UsrManagementCompany
[PXDBString]
[PXUIField(DisplayName = "Management Company")]
[PXSelector(
typeof(Search<UsrCustomerManagementCompany.mancompID>),
new Type[]
{
typeof(UsrCustomerManagementCompany.mancompID),
typeof(UsrCustomerManagementCompany.mancompName)
},
SubstituteKey = typeof(UsrCustomerManagementCompany.mancompName)
)]
public virtual string UsrManagementCompany { get; set; }
public abstract class usrManagementCompany : IBqlField { }
#endregion
}
}
I think all you are missing is the PXPrimaryGraph attribute on your DAC to indicate for that record type what is the main graph to refer to.
In your case try adding...
[PXPrimaryGraph(typeof(ClientCode.ManagementCompanyMaint))]
[Serializable]
public class UsrCustomerManagementCompany : IBqlTable
{
//...
}
Here are some related questions that might also help:
How to create a hyperlink user field
how to use AllowEdit in Acumatica

InventoryItem BasePrice causing "cast not valid"

I am trying to create a processing page to extract data from several tables which will be used to update the EDI service item list. I keep getting an error that states the specified cast for BasePrice is not valid.
This is simply an internal DAC in the BLC. There is no physical table in the database. If I exclude my BasePrice field everything works fine. If I include it, the insert gets the error. See the code below.
public class EDInventoryProcess : PXGraph<EDInventoryProcess>
{
public PXCancel<EDInventoryFilter> Cancel;
public PXFilter<EDInventoryFilter> Filter;
[PXFilterable]
public PXFilteredProcessingOrderBy<EDInventory, EDInventoryFilter,
OrderBy<Asc<EDInventory.partnerID, Asc<EDInventory.inventoryCD>>>> EDItem;
protected virtual IEnumerable eDItem()
{
EDItem.Cache.Clear();
var cmd = new PXSelectJoin<InventoryItem,
InnerJoin<INItemXRef, On<InventoryItem.inventoryID, Equal<INItemXRef.inventoryID>>,
InnerJoin<EDPartnerInfo, On<INItemXRef.bAccountID, Equal<EDPartnerInfo.customerID>>>>,
Where<INItemXRef.alternateType, Equal<INAlternateType.cPN>,
And<InventoryItem.itemStatus, Equal<InventoryItemStatus.active>>>>(this);
cmd.View.Clear();
var ret = cmd.Select();
if (ret != null)
{
EDInventoryFilter filt = (EDInventoryFilter)Filter.Cache.Current;
EDInventory edInv = new EDInventory();
foreach (PXResult<InventoryItem, INItemXRef, EDPartnerInfo> record in ret)
{
edInv = new EDInventory();
InventoryItem item = (InventoryItem)record;
INItemXRef xref = (INItemXRef)record;
EDPartnerInfo partner = (EDPartnerInfo)record;
edInv.PartnerID = partner.PartnerID;
edInv.InventoryID = item.InventoryID;
edInv.InventoryCD = item.InventoryCD;
edInv.ItemDescr = item.Descr;
edInv.ItemStatus = item.ItemStatus;
edInv.BaseUnit = item.BaseUnit;
edInv.SalesUnit = item.SalesUnit;
edInv.PurchaseUnit = item.PurchaseUnit;
edInv.BasePrice = Convert.ToDecimal(item.BasePrice);
//This is the lint that generates the error.
edInv = EDItem.Insert(edInv);
EDItem.Cache.SetStatus(edInv, PXEntryStatus.Held);
yield return edInv;
}
}
EDItem.Cache.IsDirty = false;
}
Here is the DAC definition:
[Serializable]
public partial class EDInventoryFilter : IBqlTable
{
#region TradingPartner
public abstract class tradingPartner : PX.Data.IBqlField
{
}
protected string _TradingPartner;
[PXString(15)]
[PXUIField(DisplayName = "Trading Partner")]
[PXStringList(new string[] { }, new string[] { })]
public virtual String TradingPartner { get; set; }
#endregion
#region Action
public abstract class action : PX.Data.IBqlField { }
protected string _Action;
[PXString(15)]
[PXUIField(DisplayName = "Action")]
[PXStringList(new string[] { "P" }, new string[] { "Push to EDI" })]
public virtual String Action { get; set; }
#endregion
}
[Serializable]
public partial class EDInventory : IBqlTable
{
#region PartnerID
public abstract class partnerID : IBqlField { }
[PXString(30, IsUnicode = true, IsKey = true)]
[PXDefault("")]
[PXUIField(DisplayName = "Partner")]
public virtual string PartnerID { get; set; }
#endregion
#region InventoryID
public abstract class inventoryID : PX.Data.IBqlField { }
protected Int32? _InventoryID;
[PXInt]
[PXUIField(DisplayName = "Inventory ID", Visibility = PXUIVisibility.Visible, Visible = false)]
public virtual Int32? InventoryID { get; set; }
#endregion
#region InventoryCD
public abstract class inventoryCD : PX.Data.IBqlField { }
protected String _InventoryCD;
[PXDefault()]
[InventoryRaw(IsKey = true, DisplayName = "Inventory ID")]
public virtual String InventoryCD { get; set; }
#endregion
#region ItemDescr
public abstract class itemDescr : PX.Data.IBqlField { }
protected String _ItemDescr;
[PXString(255, IsUnicode = true)]
[PXUIField(DisplayName = "Item Description")]
public virtual String ItemDescr { get; set; }
#endregion
#region ItemStatus
public abstract class itemStatus : PX.Data.IBqlField { }
protected String _ItemStatus;
[PXString(2, IsFixed = true)]
[PXDefault("AC")]
[PXUIField(DisplayName = "Item Status", Visibility = PXUIVisibility.SelectorVisible)]
public virtual String ItemStatus { get; set; }
#endregion
#region BaseUnit
public abstract class baseUnit : PX.Data.IBqlField { }
protected String _BaseUnit;
[PXString]
[PXDefault("")]
[PXUIField(DisplayName = "Base Unit", Visibility = PXUIVisibility.SelectorVisible)]
public virtual String BaseUnit { get; set; }
#endregion
#region SalesUnit
public abstract class salesUnit : PX.Data.IBqlField { }
protected String _SalesUnit;
[PXString]
[PXDefault("")]
[PXUIField(DisplayName = "Sales Unit", Visibility = PXUIVisibility.SelectorVisible)]
public virtual String SalesUnit { get; set; }
#endregion
#region PurchaseUnit
public abstract class purchaseUnit : PX.Data.IBqlField { }
protected String _PurchaseUnit;
[PXString]
[PXDefault("")]
[PXUIField(DisplayName = "Purchase Unit", Visibility = PXUIVisibility.SelectorVisible)]
public virtual String PurchaseUnit { get; set; }
#endregion
#region BasePrice
public abstract class basePrice : PX.Data.IBqlField { }
protected Decimal? _BasePrice;
[PXPriceCost()]
[PXDefault(0.0)]
[PXUIField(DisplayName = "Default Price", Visibility = PXUIVisibility.SelectorVisible)]
public virtual Decimal? BasePrice { get; set; }
#endregion
}
I just discovered what might be the answer. I was listing the default value as
[PXDefault(0.0)]
but I found another reference for decimal default as
[PXDefault(TypeCode.Decimal, "0.0")]
which seems to work. I no longer get the error and my processing screen displays as expected. I had assumed the default value drew its type from the object.
Yes for Decimal fields set [PXDefault(TypeCode.Decimal, "0.0")] attribute to avoid casting issues.

I am trying to bring selector(Formula CD) for filter data in formula master screen,

FormulaID is the identity field and it's new developed screen, but I am not able to get the selector. I have tried all the ways that I know to achieve that:
Maintaining parent and child relationships
Dataview with BQL Query
Below are the definitions of the FormulaID and FormulaCD from DAC:
#region FormulaID
public abstract class formulaID : PX.Data.IBqlField
{
}
protected int? _FormulaID;
[PXDBIdentity(IsKey =true)]
[PXUIField(Enabled = false)]
public virtual int? FormulaID
{
get
{
return this._FormulaID;
}
set
{
this._FormulaID = value;
}
#endregion
#region FormulaCD
public abstract class formulaCD : PX.Data.IBqlField
{
}
protected string _FormulaCD;
[PXDBString(30,IsUnicode = true)]
[PXUIField(DisplayName = "Formula ID", Visibility = PXUIVisibility.SelectorVisible)]
[PXSelector(typeof(Search<TSFormula.formulaCD>),
typeof(TSFormula.descr),SubstituteKey = typeof(TSFormula.formulaCD), ValidateValue = false)]
public virtual string FormulaCD
{
get
{
return this._FormulaCD;
}
set
{
this._FormulaCD = value;
}
}
#endregion
In my example below, the PXDBIdentity integer field is not enabled and not visible. The String field is marked isKey=true with the PXSelector described. The ASPX page markup offers the px:PXSelector tag for the String field as shown:
<px:PXSelector ID="edContractNumber" runat="server" DataField="ContractNumber"
AutoRefresh="True" DataSourceID="ds" NullText="<NEW>">
<GridProperties FastFilterFields="ShortName">
<Columns>
<px:PXGridColumn DataField="ContractNumber" Width="90px"></px:PXGridColumn>
<px:PXGridColumn DataField="ShortName" Width="120px"></px:PXGridColumn>
</Columns>
</GridProperties>
</px:PXSelector>
Here are the DAC fields:
#region ContractID
public abstract class contractID : PX.Data.IBqlField
{
}
[PXDBIdentity()]
[PXDefault(0)]
[PXUIField(Visible = false, Enabled = false)]
public virtual int? ContractID
{
get;
set;
}
#endregion
#region ContractNumber
public abstract class contractNumber : PX.Data.IBqlField
{
}
[PXDBString(IsKey = true)]
[PXDefault()]
[PXSelector(typeof(Search3<MyDAC.contractNumber,
OrderBy<Desc<MyDAC.contractID>>>),
new Type[] {
typeof(MyDAC.shortName),
typeof(MyDAC.contractNumber)},
DirtyRead = true)]
[PXUIField(DisplayName = "Contract Number", Required = true)]
public virtual string ContractNumber { get; set; }
#endregion

PXSelect returns a POReceipt with a wrong VendorID

This is inside an extension of a BLC (extending PXGraphExtension):
[PXOverride]
protected virtual IEnumerable resultRecords()
{
foreach (PXResult<InventoryTranHistEnqResult, INTran> item in list)
{
PXResult<POReceipt> receiptResult = PXSelect<POReceipt, Where<POReceipt.receiptNbr, Equal<Required<POReceipt.receiptNbr>>>>.Select(Base, "999");
POReceipt receipt = (POReceipt)receiptResult;
PXTrace.WriteInformation(receipt.ReceiptNbr); // CORRECT
PXTrace.WriteInformation(receipt.VendorID); // INCORRECT
}
}
The Vendor ID of the receipt seems to be wrong, but the other details from the record seem to be correct? Here is the DAC for POReceipt. Do I need to do something to make the right Vendor ID get selected?
public partial class POReceipt : PX.Data.IBqlTable, PX.Data.EP.IAssign {
#region Selected
#region ReceiptType
#region ReceiptNbr
#region SiteID
public abstract class siteID : IBqlField { }
[IN.Site(DisplayName = "Warehouse")]
public int? SiteID
{
get;
set;
}
#endregion
#region VendorID
public abstract class vendorID : PX.Data.IBqlField
{
}
protected Int32? _VendorID;
[Vendor(typeof(Search<BAccountR.bAccountID,
Where<BAccountR.type,
Equal<BAccountType.companyType>,
Or<Vendor.type,
NotEqual<BAccountType.employeeType>>>>), Visibility = PXUIVisibility.SelectorVisible, CacheGlobal = true, Filterable = true)]
[PXRestrictor(typeof(Where<Vendor.status, IsNull,
Or<Vendor.status,
Equal<BAccount.status.active>,
Or<Vendor.status,
Equal<BAccount.status.oneTime>>>>), AP.Messages.VendorIsInStatus, typeof(Vendor.status))]
[PXDefault()]
[PXFormula(typeof(Switch<Case<Where<POReceipt.receiptType, Equal<POReceiptType.transferreceipt>>, Selector<POReceipt.siteID, Selector<INSite.branchID, Branch.branchCD>>>, POReceipt.vendorID>))]
public virtual Int32? VendorID
{
get
{
return this._VendorID;
}
set
{
this._VendorID = value;
}
}
#endregion

Resources