Customize Navigation (Next/Prev) buttons on Compound Key Management screens - acumatica

The Item Warehouse Details are composed of a compound key of Inventory ID + Site ID. The navigation buttons on the Manage > Item Warehouse Details screen move between the latter part of the key, the Warehouse.
Would it be possible to customize them to navigate between Inventory IDs instead? What events / methods would allow for that?

In order to customize navigation buttons in Acumatica, you should redeclare some or all navigation buttons in an appropriate BLC extension. Below is an example showing how to implement navigation on the Item Warehouse Details screen only by Inventory ID:
using PX.Data;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace PX.Objects.IN
{
public class INItemSiteMaintExt : PXGraphExtension<INItemSiteMaint>
{
public PXFirstCst<INItemSite> First;
public PXPreviousCst<INItemSite> Previous;
public PXNextCst<INItemSite> Next;
public PXLastCst<INItemSite> Last;
public class PXFirstCst<TNode> : PXFirst<TNode>
where TNode : class, IBqlTable, new()
{
public PXFirstCst(PXGraph graph, string name)
: base(graph, name)
{
}
public PXFirstCst(PXGraph graph, Delegate handler)
: base(graph, handler)
{
}
[PXUIField(DisplayName = ActionsMessages.First, MapEnableRights = PXCacheRights.Select)]
[PXFirstButton]
protected override IEnumerable Handler(PXAdapter adapter)
{
var graph = _Graph as INItemSiteMaint;
if (graph == null) return base.Handler(adapter);
InjectCustomWhereClause(ref adapter, graph, typeof(Where<True, Equal<True>>));
return base.Handler(adapter);
}
}
public class PXPreviousCst<TNode> : PXPrevious<TNode>
where TNode : class, IBqlTable, new()
{
public PXPreviousCst(PXGraph graph, string name)
: base(graph, name)
{
}
public PXPreviousCst(PXGraph graph, Delegate handler)
: base(graph, handler)
{
}
[PXUIField(DisplayName = ActionsMessages.Previous, MapEnableRights = PXCacheRights.Select)]
[PXPreviousButton]
protected override IEnumerable Handler(PXAdapter adapter)
{
var graph = _Graph as INItemSiteMaint;
if (graph == null) return base.Handler(adapter);
InjectCustomWhereClause(ref adapter, graph,
typeof(Where<InventoryItem.inventoryCD, Less<Required<InventoryItem.inventoryCD>>>));
return base.Handler(adapter);
}
protected override void Insert(PXAdapter adapter)
{
adapter.Searches = null;
base.Insert(adapter);
}
}
public class PXNextCst<TNode> : PXNext<TNode>
where TNode : class, IBqlTable, new()
{
public PXNextCst(PXGraph graph, string name)
: base(graph, name)
{
}
public PXNextCst(PXGraph graph, Delegate handler)
: base(graph, handler)
{
}
[PXUIField(DisplayName = ActionsMessages.Next, MapEnableRights = PXCacheRights.Select)]
[PXNextButton]
protected override IEnumerable Handler(PXAdapter adapter)
{
var graph = _Graph as INItemSiteMaint;
if (graph == null) return base.Handler(adapter);
InjectCustomWhereClause(ref adapter, graph,
typeof(Where<InventoryItem.inventoryCD, Greater<Required<InventoryItem.inventoryCD>>>));
return base.Handler(adapter);
}
protected override void Insert(PXAdapter adapter)
{
adapter.Searches = null;
base.Insert(adapter);
}
}
public class PXLastCst<TNode> : PXLast<TNode>
where TNode : class, IBqlTable, new()
{
public PXLastCst(PXGraph graph, string name)
: base(graph, name)
{
}
public PXLastCst(PXGraph graph, Delegate handler)
: base(graph, handler)
{
}
[PXUIField(DisplayName = ActionsMessages.Last, MapEnableRights = PXCacheRights.Select)]
[PXLastButton]
protected override IEnumerable Handler(PXAdapter adapter)
{
var graph = _Graph as INItemSiteMaint;
if (graph == null) return base.Handler(adapter);
InjectCustomWhereClause(ref adapter, graph, typeof(Where<True, Equal<True>>));
return base.Handler(adapter);
}
}
private static void InjectCustomWhereClause(ref PXAdapter adapter, INItemSiteMaint graph,
Type conditionToInjectCommand)
{
var bqlCommand = adapter.View.BqlSelect;
var newCommand = new List<Type>(BqlCommand.Decompose(bqlCommand.GetType()));
var newCommandCopy = new List<Type>(newCommand);
var conditionToReplaceCommand = typeof(Where<INItemSite.inventoryID, Equal<Optional<INItemSite.inventoryID>>>);
var conditionToReplace = new List<Type>(BqlCommand.Decompose(conditionToReplaceCommand).Skip(1));
var conditionToInject = new List<Type>(BqlCommand.Decompose(conditionToInjectCommand).Skip(1));
bool whereClause = false;
for (int i = 0; i < newCommand.Count - 1; i++)
{
whereClause = whereClause || typeof(IBqlWhere).IsAssignableFrom(newCommand[i]);
if (!whereClause) continue;
if (newCommand[i] == conditionToReplace.First())
{
bool found = true;
for (int index = 0; index < conditionToReplace.Count; index++)
{
if (newCommand[i + index] != conditionToReplace[index])
{
found = false;
break;
}
}
if (found)
{
newCommandCopy.RemoveRange(i, conditionToReplace.Count);
newCommandCopy.InsertRange(i, conditionToInject);
break;
}
}
}
var cmd = BqlCommand.CreateInstance(BqlCommand.Compose(newCommandCopy.ToArray()));
var newAdapter = new PXAdapter(new PXView(graph, false, cmd));
PXAdapter.Copy(adapter, newAdapter);
var inventoryState = graph.itemsiterecord.Cache.
GetValueExt<INItemSite.inventoryID>(graph.itemsiterecord.Current) as PXSegmentedState;
if (inventoryState != null && inventoryState.Value != null)
newAdapter.Parameters = new object[] { inventoryState.Value };
else
newAdapter.Parameters = new object[] { string.Empty };
newAdapter.SortColumns = null;
newAdapter.Descendings = null;
adapter = newAdapter;
}
}
}

Related

Acumatica The item ProjectTaskID is not found

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using PX.Common;
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.EP;
using PX.Objects.AP;
using PX.Objects.AR;
using PX.Objects.SO;
using PX.TM;
using SOOrder = PX.Objects.SO.SOOrder;
using SOLine = PX.Objects.SO.SOLine;
using PX.CS.Contracts.Interfaces;
using PX.Data.DependencyInjection;
using PX.Data.ReferentialIntegrity.Attributes;
using PX.Objects.PM;
using CRLocation = PX.Objects.CR.Standalone.Location;
using PX.Objects.AP.MigrationMode;
using PX.Objects.Common;
using PX.Objects.Common.Discount;
using PX.Objects;
using PX.Objects.PO;
using PX.Objects.CT;
using PX.Data.EP;
namespace PX.Objects.PO
{
public class POOrderEntry_Extension : PXGraphExtension<POOrderEntry>
{
#region Event Handlers
[Serializable]
public class ProjectFilter : IBqlTable
{
#region ContractID
public abstract class contractID : PX.Data.IBqlField { }
//[PXDefault(typeof(PMProject.contractID))]
[PXUIField(DisplayName = "Project ID")]
[Project(DescriptionField = typeof(PMProject.contractCD))]
public int? ContractID { get; set; }
#endregion
#region ProjectTaskID
public abstract class projectTaskID : PX.Data.BQL.BqlInt.Field<projectTaskID> { }
protected Int32? _ProjectTaskID;
[ProjectTask(typeof(PMProject.contractID), AlwaysEnabled = true, DirtyRead = true, IsKey = true)]
public virtual Int32? ProjectTaskID
{
get
{
return this._ProjectTaskID;
}
set
{
this._ProjectTaskID = value;
}
}
#endregion
}
//PXSelect<PMCostBudget, Where<PMCostBudget.projectID, Equal<Current<PMProject.contractID>>, And<PMCostBudget.type, Equal<GL.AccountType.expense>,
// And<Where<Current<CostBudgetFilter.projectTaskID>, IsNull, Or<Current<CostBudgetFilter.projectTaskID>, Equal<PMCostBudget.projectTaskID>>>>>>,
// OrderBy<Asc<PMCostBudget.projectID, Asc<PMCostBudget.projectTaskID, Asc<PMCostBudget.inventoryID, Asc<PMCostBudget.costCodeID, Asc<PMCostBudget.accountGroupID>>>>>>>(this);
//PXDelegateResult delResult = new PXDelegateRes
public PXFilter<ProjectFilter> projectfilter;
[PXFilterable]
[PXCopyPasteHiddenView]
public PXSelect<PMCostBudget,
Where<PMCostBudget.projectID, Equal<Current<ProjectFilter.contractID>>,
//And<PMCostBudget.projectTaskID, Equal<Current<ProjectFilter.projectTaskID>>,
//And<PMProject.locationID, Equal<Current<POOrder.vendorLocationID>>,
And<PMCostBudget.type, Equal<GL.AccountType.expense>>>> getCostBudget;
// public PXOrderedSelect<POOrder, POLine, Where<POLine.orderType, Equal<Current<POOrder.orderType>>, And<POLine.orderNbr, Equal<Optional<POOrder.orderNbr>>>>, OrderBy<Asc<POLine.orderType, Asc<POLine.orderNbr, Asc<POLine.sortOrder, Asc<POLine.lineNbr>>>>>> Transactions;
// PX.Objects.PM.PMProject project = PXSelect<PM.PMProject, Where<PM.PMProject.contractID, Equal<Required<PM.PMProject.contractID>>>>.Select(this, location.Current.VDefProjectID);
//if (project != null)
public PXAction<POOrder> AddProjectCostBudget;
[PXButton(CommitChanges = true)]
[PXUIField(DisplayName = "Add Project Cost Budget")]
public virtual IEnumerable addProjectCostBudget(PXAdapter adapter)
{
if (getCostBudget.AskExt() == WebDialogResult.OK)
{
return addSelCostBudget(adapter);
}
return adapter.Get();
}
public PXAction<POOrder> AddSelCostBudget;
[PXUIField(DisplayName = "Add", Visible = false)]
[PXButton(CommitChanges = true)]
public virtual IEnumerable addSelCostBudget(PXAdapter adapter)
{
//Base.Transactions.Cache.ForceExceptionHandling = true;
foreach (PMCostBudget cost in getCostBudget.Cache.Cached)
{
//var costExt = cost.GetExtension<PMBudgetExt>();
if (cost.Selected == true)
{
POLine newline = Base.Transactions.Insert();
newline.ProjectID = cost.ProjectID;
newline.TaskID = cost.ProjectTaskID;
newline.CostCodeID = cost.CostCodeID;
newline.InventoryID = cost.InventoryID;
newline.UOM = cost.UOM;
Base.Transactions.Cache.Update(newline);
Base.Transactions.Update(newline);
}
}
//getCostBudget.Cache.Clear();
return adapter.Get();
}
//public override void Initialize()
//{
// base.Initialize();
// AddProjectCostBudget.SetEnabled(false);
//}
//protected virtual void PMCostBudget_ProjectTaskID_FieldVerifying(PXCache sender, PXFieldVerifyingEventArgs e)
//{
// PMCostBudget row = e.Row as PMCostBudget;
// if (row == null) return;
// if (!(e.NewValue is Int32)) return;
// if (e.NewValue != null)
// {
// PXResultset<INLocation> projectLocations = PXSelectReadonly<INLocation,
// Where<INLocation.projectID, Equal<Required<INLocation.projectID>>,
// And2<Where<INLocation.taskID, IsNull>, Or<INLocation.taskID, Equal<Required<INLocation.taskID>>>>>>.Select(Base, row.ProjectID, e.NewValue);
// string taskCD = null;
// PMTask task = PXSelect<PMTask, Where<PMTask.taskID,
// Equal<Required<PMTask.taskID>>>>.Select(Base, row.TaskID);
// if (task != null)
// {
// taskCD = task.TaskCD;
// }
// else
// {
// sender.RaiseExceptionHandling<PMCostBudget.projectTaskID>(row, taskCD, new PXSetPropertyException(Messages.ProjectTaskIsNotAssociatedWithAnyInLocation, PXErrorLevel.Warning));
// }
// }
//}
//protected virtual void PMCostBudget_ProjectTaskID_FieldDefaulting(PXCache sender, PXFieldDefaultingEventArgs e)
//{
// PMCostBudget cost = e.Row as PMCostBudget;
// if (cost == null) return;
// PMTask task = PXSelect<PMTask,
// Where<PMTask.projectID, Equal<Current<ProjectFilter.contractID>>,
// And<PMTask.isDefault, Equal<True>>>>.Select(Base, cost.ProjectID, cost.ProjectTaskID);
// if (task == null) return;
// sender.SetValue<PMCostBudget.projectTaskID>(cost, task.TaskID);
//}
#endregion
}
}
I had created a pop-up panel to insert Project Cost budget into POLines in Purchase Order screen. every time I want to select and insert, It gives this error
Error: An error occurred during processing of the field Project Task: Error: 'Project Task' cannot be found in the system.
The code snippet of my view:[
[Serializable]
public class ProjectFilter : IBqlTable
{
#region ContractID
public abstract class contractID : PX.Data.IBqlField { }
//[PXDefault(typeof(PMProject.contractID))]
[PXUIField(DisplayName = "Project ID")]
[Project(DescriptionField = typeof(PMProject.contractCD))]
public int? ContractID { get; set; }
#endregion
#region ProjectTaskID
public abstract class projectTaskID : PX.Data.BQL.BqlInt.Field<projectTaskID> { }
protected Int32? _ProjectTaskID;
[ProjectTask(typeof(PMProject.contractID), AlwaysEnabled = true, DirtyRead = true, IsKey = true)]
public virtual Int32? ProjectTaskID
{
get
{
return this._ProjectTaskID;
}
set
{
this._ProjectTaskID = value;
}
}
#endregion
}
public PXFilter<ProjectFilter> projectfilter;
[PXFilterable]
[PXCopyPasteHiddenView]
public PXSelect<PMCostBudget,
Where<PMCostBudget.projectID, Equal<Current<ProjectFilter.contractID>>,
And<PMCostBudget.projectTaskID, Equal<Current<ProjectFilter.projectTaskID>>,
And<PMCostBudget.type, Equal<GL.AccountType.expense>>>>> getCostBudget;
]1 this is the error image
The ProjectTask attribute expects a reference to the currently selected project; you need to use ProjectFilter.projectID instead of PMProject.projectID

Update customer children from parent account

Page: AR303000 Version:18.203.0006
Good day
I need to update the Child accounts details(Terms, Status, and Email) when the parent account changes. The problem is I do not know how to save the children Customer's contact email field from Customer_RowPersisting.
The customer child accounts do save a, but the Contact details do not.
namespace PX.Objects.AR
{
public class CustomerMaint_Extension : PXGraphExtension<CustomerMaint>
{
#region Event Handlers
protected void Customer_RowPersisting(PXCache cache, PXRowPersistingEventArgs e)
{
Customer row = (Customer)e.Row;
if (row.ParentBAccountID == null)
{
PXResultset<Customer> Children = PXSelectJoin<Customer,
LeftJoin<BAccount, On<Customer.bAccountID, Equal<BAccount.bAccountID>>>,
Where<BAccount.parentBAccountID, Equal<Required<Customer.bAccountID>>>>.Select(Base, row.BAccountID);
if (Children == null) { return; }
Contact ParContact = PXSelect<Contact, Where<Contact.contactID, Equal<Required<Contact.contactID>>>>.Select(Base, row.DefBillContactID);
foreach (Customer item in Children)
{
//Customer
item.TermsID = row.TermsID;
item.Status = row.Status;
cache.Update(item);
//Contact Details
Contact Cur = PXSelect<Contact, Where<Contact.contactID, Equal<Required<Contact.contactID>>>>.Select(Base, item.DefBillContactID);
Cur.EMail = ParContact.EMail;
cache.Update(Cur);
}
//Do not know if this is right
cache.Persist(PXDBOperation.Normal);
}
}
#endregion
}
}
You can override the Persist() method! You should add a reference for the PX.CS.Contracts.dll dll.
public class CustomerMaintExt : PXGraphExtension<CustomerMaint>
{
#region Overrides
public delegate void PersistDelegate();
[PXOverride]
public void Persist(PersistDelegate baseMethod)
{
using (var scope = new PXTransactionScope())
{
Customer row = this.Base.BAccount.Current;
if (row?.ParentBAccountID == null)
{
CustomerMaint businessAccount = PXGraph.CreateInstance<CustomerMaint>();
PXResultset<Customer> Children = PXSelect<Customer, Where<Customer.parentBAccountID, Equal<Required<Customer.bAccountID>>>>.Select(Base, row.BAccountID);
foreach (Customer item in Children)
{
businessAccount.Clear();
businessAccount.BAccount.Current = PXSelectorAttribute.Select<Customer.bAccountID>(this.Base.BAccount.Cache, item.BAccountID) as Customer;
item.TermsID = row.TermsID;
item.Status = row.Status;
Contact defContact = PXSelect<Contact, Where<Contact.bAccountID, Equal<Required<BAccount.bAccountID>>, And<Contact.contactID, Equal<Required<BAccount.defContactID>>>>>.Select(businessAccount, item.BAccountID, item.DefContactID);
defContact.EMail = this.Base.DefContact.Current.EMail;
businessAccount.DefContact.Update(defContact);
businessAccount.BAccount.Update(item);
businessAccount.Save.PressButton();
}
}
baseMethod();
scope.Complete();
}
}
#endregion
}

Navigating to next page on grid does not refresh the data

I have a grid that displays rows based on the form's filters. When navigated to the next page the data remains the same. I have exported the data into excel which gets all the rows. Only the first page and last page navigation change the rows. Please help on what am I missing in the ASPX
Graph containing view delegate and DAC
public class InventorySales : PXGraph<InventorySales>
{
[Serializable]
public class Filter : IBqlTable
{
public abstract class wareHouse : IBqlField { }
[PXDefault()]
[PXUIField(DisplayName = "Warehouse")]
[PX.Objects.IN.POSiteAvail(typeof(POReceiptLine.inventoryID), typeof(POReceiptLine.subItemID))]
public virtual int? WareHouse { get; set; }
#region InventoryID
public abstract class inventoryCD : PX.Data.IBqlField
{
}
protected Int32? _InventoryCD;
[PXInt()]
[PXUIField(DisplayName = "SKU", Visibility = PXUIVisibility.SelectorVisible)]
[PXSelector(typeof(Search<
InventoryItem.inventoryID,
Where<InventoryItem.itemStatus, Equal<InventoryItemStatus.active>>>),
new Type[] { typeof(InventoryItem.inventoryID), typeof(InventoryItem.inventoryCD),
typeof(InventoryItem.itemStatus),
typeof(InventoryItem.descr)},
SubstituteKey = typeof(InventoryItem.inventoryCD),
DescriptionField = typeof(InventoryItem.descr))]
public virtual Int32? InventoryCD
{
get
{
return this._InventoryCD;
}
set
{
this._InventoryCD = value;
}
}
#endregion
#region BeginDate
public abstract class beginDate : IBqlField
{
}
protected DateTime? _BeginDate;
[PXDBDate]
[PXDefault(typeof(AccessInfo.businessDate))]
[PXUIField(DisplayName = "Start Date")]
public virtual DateTime? BeginDate
{
get
{
return _BeginDate;
}
set
{
_BeginDate = value;
}
}
#endregion
#region EndDate
public abstract class endDate : IBqlField { }
[PXDBDate]
[PXDefault(typeof(AccessInfo.businessDate))]
[PXUIField(DisplayName = "End Date")]
public virtual DateTime? EndDate { get; set; }
#endregion
#region Sales
public abstract class sales : PX.Data.IBqlField
{
}
protected Int32? _Sales;
[PXInt()]
[PXUnboundDefault("30")]
[PXUIField(DisplayName = "Sales")]
[InvSales.List]
public virtual Int32? Sales
{
get
{
return this._Sales;
}
set
{
this._Sales = value;
}
}
#endregion
}
public PXCancel<Filter> Cancel;
public PXFilter<Filter> MasterView;
public PXSelectJoin<
POReceiptLine,
InnerJoin<POReceipt,
On<POReceiptLine.receiptType, Equal<POReceipt.receiptType>,
And<POReceiptLine.receiptNbr, Equal<POReceipt.receiptNbr>>>,
InnerJoin<INSiteStatus,
On<INSiteStatus.inventoryID, Equal<POReceiptLine.inventoryID>,
And<INSiteStatus.siteID, Equal<POReceiptLine.siteID>>>>>,
Where2<
Where2<
Where<POReceiptLine.siteID, Equal<Current<Filter.wareHouse>>,
And<POReceipt.receiptType, Equal<POReceiptType.poreceipt>>>,
And<Where<POReceiptLine.inventoryID, Equal<Current<Filter.inventoryCD>>,
Or<Current<Filter.inventoryCD>, IsNull>>>>,
And<Where<POReceiptLine.receiptDate, GreaterEqual<Current<Filter.beginDate>>,
And<POReceiptLine.receiptDate, LessEqual<Current<Filter.endDate>>>>>>>
DetailsView;
public PXSelectJoin<
SOLine,
InnerJoin<SOOrder,
On<SOLine.orderType, Equal<SOOrder.orderType>,
And<SOOrder.orderNbr, Equal<SOLine.orderNbr>>>>,
Where<SOOrder.status, NotEqual<SOStatus>,
And<SOOrder.orderDate, GreaterEqual<Sub<Current<AccessInfo.businessDate>,Current<Filter.sales>>>,
And<SOOrder.orderDate, LessEqual<Current<AccessInfo.businessDate>>>>>> ss;
List<PXResult<SOLine>> list = new List<PXResult<SOLine>>();
public IEnumerable detailsView()
{
list = PXSelectJoin<
SOLine,
InnerJoin<SOOrder,
On<SOLine.orderType, Equal<SOOrder.orderType>,
And<SOOrder.orderNbr, Equal<SOLine.orderNbr>>>>,
Where<SOOrder.status, NotEqual<SOStatus>,
And<SOOrder.orderDate, GreaterEqual<Sub<Current<AccessInfo.businessDate>, Current<Filter.sales>>>,
And<SOOrder.orderDate, LessEqual<Current<AccessInfo.businessDate>>>>>>.Select(this).ToList();
Int32 startrow = PXView.StartRow;
List<POReceiptLine> poReceiptLineList = new List<POReceiptLine>();
PXView.StartRow = 0;
foreach (PXResult<POReceiptLine, POReceipt, INSiteStatus> result in PXSelectJoin<
POReceiptLine,
InnerJoin<POReceipt,
On<POReceiptLine.receiptType, Equal<POReceipt.receiptType>,
And<POReceiptLine.receiptNbr, Equal<POReceipt.receiptNbr>>>,
InnerJoin<INSiteStatus,
On<INSiteStatus.inventoryID, Equal<POReceiptLine.inventoryID>,
And<INSiteStatus.siteID, Equal<POReceiptLine.siteID>>>>>,
Where2<
Where2<
Where<POReceiptLine.siteID, Equal<Current<Filter.wareHouse>>,
And<POReceipt.receiptType, Equal<POReceiptType.poreceipt>>>,
And<Where<POReceiptLine.inventoryID, Equal<Current<Filter.inventoryCD>>,
Or<Current<Filter.inventoryCD>, IsNull>>>>,
And<Where<POReceiptLine.receiptDate, GreaterEqual<Current<Filter.beginDate>>,
And<POReceiptLine.receiptDate, LessEqual<Current<Filter.endDate>>>>>>>
.Select(this))
{
decimal? sum = 0.00M;
POReceiptLine objsalesprice = (POReceiptLine)result;
INSiteStatus objInSiteStatus = (INSiteStatus)result;
if (objsalesprice != null)
{
POReceiptLineExt obj = objsalesprice.GetExtension<POReceiptLineExt>();
foreach (PXResult<SOLine> res in list)
{
SOLine so = (SOLine)res;
if (so.InventoryID == objsalesprice.InventoryID)
sum = sum + so.CuryLineAmt;
}
obj.UsrSales = sum;
obj.UsrQtyAvail = objInSiteStatus.QtyAvail;
if (!poReceiptLineList.Any(x => x.InventoryID == objsalesprice.InventoryID))
{
poReceiptLineList.Add(objsalesprice);
}
else if (poReceiptLineList.Any(x => x.InventoryID == objsalesprice.InventoryID && x.ReceiptDate.Value.Date < objsalesprice.ReceiptDate.Value.Date))
{
var itemToRemove = poReceiptLineList.Single(r => (r.InventoryID == objsalesprice.InventoryID));
poReceiptLineList.Remove(itemToRemove);
poReceiptLineList.Add(objsalesprice);
}
else if (poReceiptLineList.Any(x => x.InventoryID == objsalesprice.InventoryID
&& x.ReceiptDate.Value.Date == objsalesprice.ReceiptDate.Value.Date && x.CreatedDateTime < objsalesprice.CreatedDateTime))
{
var itemToRemove = poReceiptLineList.Single(r => (r.InventoryID == objsalesprice.InventoryID));
poReceiptLineList.Remove(itemToRemove);
poReceiptLineList.Add(objsalesprice);
}
}
}
return poReceiptLineList;
}
}
You will have to re-work the 'detailsView' delegate method so that it uses the PXView pattern to handle paging.
Detailed instructions on using PXView with Paging in delegate can be found here: https://asiablog.acumatica.com/2016/06/using-pxview-in-dataview-delegate.html
Here's the relevant code excerpt from that page:
public PXSelect<DAC> DataView;
public IEnumerable dataView()
{
PXView select = new PXView(this, true, DataView.View.BqlSelect);
Int32 totalrow = 0;
Int32 startrow = PXView.StartRow;
List<object> result = select.Select(PXView.Currents, PXView.Parameters,
PXView.Searches, PXView.SortColumns, PXView.Descendings,
PXView.Filters, ref startrow, PXView.MaximumRows, ref totalrow);
PXView.StartRow = 0;
foreach (PXResult<DAC> row in result)
{
// Do any dynamic calculations
yield return row;
}
}
Alternatively you can remove paging on the grid by setting the AllowPaging="false" property of the Grid element if you don't need paging.

Acumatica Grid Events

I have a non persisted field in my Sales Order grid. I want the use to enter a value which will be used to update the unit price. i have tried catching all of the events for the grid/field but non of them trigger when the user enters a value. I do not need the update to happen on every character, just when the user hits tab to exist the field or enter.
Graph Extension:
using PX.Data;
using PX.Objects.CS;
using PX.Objects.IN;
namespace PX.Objects.SO
{
public class SOOrderEntry_Extension:PXGraphExtension<SOOrderEntry>
{
protected void SOLine_UsrMargin_FieldSelecting(PXCache cache, PXFieldSelectingEventArgs e)
{
var salesOrderEntry = (SOLine)e.Row;
if (salesOrderEntry == null)
return;
UpdateCustomFields(cache, salesOrderEntry);
}
protected void SOLine_UsrMargin_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
{
var salesOrderEntry = (SOLine)e.Row;
if (salesOrderEntry == null)
return;
UpdateCustomFields(cache, salesOrderEntry);
}
protected void SOLine_UsrMargin_FieldUpdating(PXCache cache, PXFieldUpdatingEventArgs e)
{
var salesOrderEntry = (SOLine)e.Row;
if (salesOrderEntry == null)
return;
UpdateCustomFields(cache, salesOrderEntry);
}
public class string_PROMODET : Constant<string>
{
public string_PROMODET() : base("PROMODET") { }
}
public class string_SALESPROMO : Constant<string>
{
public string_SALESPROMO() : base("SALESPROMO") { }
}
protected void SOLine_RowUpdated(PXCache cache, PXRowUpdatedEventArgs e)
{
var salesOrderEntry = (SOLine)e.Row;
if (salesOrderEntry == null)
return;
UpdateCustomFields(cache, salesOrderEntry);
}
protected void SOLine_RowUpdating(PXCache cache, PXRowUpdatingEventArgs e)
{
var salesOrderEntry = (SOLine)e.Row;
if (salesOrderEntry == null)
return;
UpdateCustomFields(cache, salesOrderEntry);
}
protected void SOLine_RowInserted(PXCache cache, PXRowInsertedEventArgs e)
{
var salesOrderEntry = (SOLine)e.Row;
if (salesOrderEntry == null)
return;
UpdateCustomFields(cache, salesOrderEntry);
}
protected void SOLine_RowInserting(PXCache cache, PXRowInsertingEventArgs e)
{
var salesOrderEntry = (SOLine)e.Row;
if (salesOrderEntry == null)
return;
UpdateCustomFields(cache, salesOrderEntry);
}
protected void SOLine_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
var salesOrderEntry = (SOLine)e.Row;
if (salesOrderEntry == null)
return;
UpdateCustomFields(cache, salesOrderEntry);
}
protected void SOLine_RowSelecting(PXCache cache, PXRowSelectingEventArgs e)
{
var salesOrderEntry = (SOLine)e.Row;
if (salesOrderEntry == null)
return;
UpdateCustomFields(cache, salesOrderEntry);
}
private static void UpdateCustomFields(PXCache cache, SOLine salesOrderEntry)
{
SOLineExt soLineExt = PXCache<SOLine>.GetExtension<SOLineExt>(salesOrderEntry);
PXUIFieldAttribute.SetEnabled<SOLineExt.usrSalesPromotion>(cache, salesOrderEntry, false);
PXUIFieldAttribute.SetEnabled<SOLineExt.usrSalesPromotionDetails>(cache, salesOrderEntry, false);
using (new PXConnectionScope())
{
InventoryItem ii = PXSelect<InventoryItem, Where<InventoryItem.inventoryID, Equal<Required<SOLine.inventoryID>>>>
.Select(new PXGraph(), salesOrderEntry.InventoryID);
if (ii != null)
{
CSAnswers promotionDetail = PXSelect<CSAnswers,
Where2<
Where<CSAnswers.refNoteID, Equal<Required<InventoryItem.noteID>>>,
And<Where<CSAnswers.attributeID, Equal<string_PROMODET>,
Or<CSAnswers.attributeID, Equal<string_PROMODET>>>>>>
.Select(new PXGraph(), ii.NoteID);
CSAnswers promotion = PXSelect<CSAnswers,
Where2<
Where<CSAnswers.refNoteID, Equal<Required<InventoryItem.noteID>>>,
And<Where<CSAnswers.attributeID, Equal<string_SALESPROMO>,
Or<CSAnswers.attributeID, Equal<string_SALESPROMO>>>>>>
.Select(new PXGraph(), ii.NoteID);
INItemStats itemStats = PXSelect<INItemStats, Where<INItemStats.inventoryID, Equal<Required<SOLine.inventoryID>>>>
.Select(new PXGraph(), salesOrderEntry.InventoryID);
if (itemStats != null)
{
cache.SetValue<SOLineExt.usrLastCost>(salesOrderEntry, itemStats.LastCost);
cache.SetValue<SOLineExt.usrMargin>(salesOrderEntry, ((salesOrderEntry.CuryUnitPrice / itemStats.LastCost) - 1) * 100);
}
if (promotion != null)
{
cache.SetValue<SOLineExt.usrSalesPromotion>(salesOrderEntry, promotion.Value == "1" ? true : false);
cache.SetValue<SOLineExt.usrSalesPromotionDetails>(salesOrderEntry, promotion.Value == "1" ? promotionDetail.Value : "");
}
}
}
}
}
}
Cache Extension:
using PX.Data;
using System;
namespace PX.Objects.SO
{
public class SOLineExt : PXCacheExtension<PX.Objects.SO.SOLine>
{
#region UsrLastCost
[PXDecimal]
[PXUIField(DisplayName="Last Cost", Enabled = false, Visible = true, IsReadOnly = true)]
public virtual Decimal? UsrLastCost { get; set; }
public abstract class usrLastCost : IBqlField { }
#endregion
#region UsrSalesPromotion
[PXBool]
[PXUIField(DisplayName="Sales Promotion", Enabled = false, IsReadOnly = true)]
public virtual bool? UsrSalesPromotion { get; set; }
public abstract class usrSalesPromotion : IBqlField { }
#endregion
#region UsrSalesPromotionDetails
[PXString(64)]
[PXUIField(DisplayName="Sales Promotion Details", Enabled = false, IsReadOnly = true)]
public virtual string UsrSalesPromotionDetails { get; set; }
public abstract class usrSalesPromotionDetails : IBqlField { }
#endregion
#region UsrMargin
[PXDecimal]
[PXUIField(DisplayName="Margin")]
public virtual Decimal? UsrMargin { get; set; }
public abstract class usrMargin : IBqlField { }
#endregion
}
}

Current Cache gives Null

I am trying to get the Current Cache which gives me null. In the below code, the value of cc is null. Can anyone let me know what wrong am I doing here?
public class SpCaseNewEntryExtension : PXGraphExtension<SPCaseNewEntry>
{
protected PXGraph _Graph = null;
public class CRCaseClassIDSelectorAttribute : PXCustomSelectorAttribute
{
public override void CacheAttached(PXCache sender)
{
_Graph = sender.Graph;
base.CacheAttached(sender);
}
public CRCaseClassIDSelectorAttribute()
: base(typeof(CRCase.caseClassID))
{
this.DescriptionField = typeof(CRCaseClass.description);
}
protected virtual IEnumerable GetRecords()
{
CRCase cc = ((CRCase)_Graph.Caches[typeof(CRCase)].Current);
foreach (PXResult<CRCaseClass> pc in PXSelectJoinGroupBy<CRCaseClass, 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>>,
Aggregate<GroupBy<CRCaseClass.caseClassID>>>.Select(this._Graph))
{
yield return pc;
}
}

Resources