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
Related
We have 2 DAC - Master and Child
Master DAC
#region MasterID
public abstract class masterID:PX.Data.BQL.BqlInt.Field<masterID> { }
protected int? _MasterID;
[PXDBIdentity()]
[PXUIField(Visibility = PXUIVisibility.Invisible)]
[PXReferentialIntegrityCheck]
public virtual int? MasterID
{
get {return this._MasterID;}
set {this._MasterID = value;}
}
#endregion
#region MasterCD
public abstract class masterRoutingCD:PX.Data.BQL.BqlString.Field<masterCD> { }
protected string _MasterRoutingCD;
[BomID(DisplayName = "Master #", IsKey = true, Required = true,
Visibility = PXUIVisibility.SelectorVisible)]
[PXDefault]
[Rev.Key(typeof(Setup.pMMasterNumberSequenceID),
typeof(Master.masterCD),
typeof(Master.revisionNo),
typeof(Master.masterCD),
typeof(Master.revisionNo)
)]
public virtual string MasterCD
{
get {return this._MasterCD;}
set {this._MasterCD = value;}
}
#endregion
#region RevisionNo
public abstract class revisionNo:PX.Data.IBqlField { }
protected string _RevisionNo;
[RevisionIDField(IsKey = true, Visibility = PXUIVisibility.SelectorVisible,
Required = true)]
[PXDefault(typeof(Master.defaultRevisionNo),
PersistingCheck = PXPersistingCheck.Nothing)]
[Rev.ID(typeof(Master.defaultRevisionNo),
typeof(Master.masterCD),
typeof(Master.revisionNo),
typeof(Master.revisionNo),
typeof(Master.description),
typeof(Master.fromDate),
typeof(Master.toDate))]
public virtual string RevisionNo
{
get {return this._RevisionNo;}
set {this._RevisionNo = value;}
}
#endregion
Child DAC
public abstract class childID:PX.Data.BQL.BqlInt.Field<childID> { }
protected int? _ChildID;
[PXDBIdentity()]
//[PXReferentialIntegrityCheck]
public virtual int? ChildID
{
get {return this._ChildID;}
set {this._ChildID = value;}
}
#endregion
#region MasterID
public abstract class masterID:PX.Data.BQL.BqlInt.Field<masterID> { }
protected int? _MasterID;
[PXDBInt()]
[PXDBDefault(typeof(Master.masterID))]
[PXParent(typeof(Select<Master, Where<Master.masterRoutingCD, Equal<Current<masterCD>>,
And<Master.revisionNo, Equal<Current<revisionNo>>>>>))]
public virtual int? MasterID
{
get {return _MasterID;}
set {_MasterID = value;}
}
#endregion MasterID
#region MasterCD
public abstract class masterCD:PX.Data.BQL.BqlString.Field<masterCD> { }
protected string _MasterCD;
[PXDBDefault(typeof(Master.masterCD))]
[PXDBString(IsKey = true, IsUnicode = true)]
public virtual string MasterCD
{
get {return this._MasterCD;}
set {this._MasterCD = value;}
}
#endregion
#region Revision
public abstract class revisionNo:PX.Data.BQL.BqlString.Field<revisionNo> {}
[PXDBString(15, IsKey = true, IsUnicode = true)]
[PXDBDefault(typeof(Master.revisionNo))]
public virtual string RevisionNo { get; set; }
#endregion Revision
public abstract class stepsID:PX.Data.BQL.BqlInt.Field<stepsID> { }
[OperationCDField(IsKey =true, DisplayName = "Steps ID",
Visibility = PXUIVisibility.SelectorVisible)]
[PXDefault(PersistingCheck = PXPersistingCheck.NullOrBlank)]
//[PXUIField(DisplayName = "Process Steps ID")]
public virtual string StepsID { get; set; }
Graph - MasterMaint
public class MasterMaint:PXRevisionableGraph<MasterMaint, Master,
Master.masterCD, Master.revisionNo>
{
public PXSelect<Child, Where<Child.masterCD, Equal<Current<Master.masterCD>>,
And<Child.revisionNo, Equal<Current<Master.revisionNo>>>>> ChildRecords;
#region Override
public override bool CanClipboardCopyPaste()
{
return false;
}
public override bool CanCreateNewRevision(MasterMaint fromGraph, MasterMaint toGraph,
string keyValue, string revisionValue, out string error)
{
// Always returns true as new revisions can be created at any time
error = string.Empty;
return true;
}
public override void CopyRevision(MasterMaint fromGraph, MasterMaint toGraph,
string keyValue, string revisionValue)
{
if(toGraph?.Documents?.Current == null || fromGraph?.Documents?.Current == null)
{
// api calls should create new revs on their own - this causes issues
// when calling from api so we need to turn the copy rev logic off
return;
}
toGraph.Documents.Cache.SetDefaultExt<EWPMMasterRouting.status>
(toGraph.Documents.Current);
if(SkipAutoCreateNewRevision())
{
return;
}
CopyChildRecords(fromGraph.Documents.Current.MasterRoutingCD,
fromGraph.Documents.Current.RevisionNo, toGraph.Documents.Current.MasterID,
keyValue, revisionValue, false);
}
internal virtual void CopyChildRecords(string sourceID, string sourceRevisionNo,
int? newMasterID, string newMasterCD, string newRevisionID, bool copyNotes)
{
foreach(Child fromRow in PXSelect<Child,
Where<Child.masterCD, Equal<Required<Child.masterCD>>,
And<Child.revisionNo, Equal<Required<Child.revisionNo>>>>>
.Select(this, sourceID, sourceRevisionNo))
{
var toRow = PXCache<Child>.CreateCopy(fromRow);
toRow.MasterID = newMasterRoutingID;
toRow.ChildID = null;
toRow.MasterCD = newMasterCD;
toRow.RevisionNo= newRevisionID;
toRow = ChildRecords.Insert(toRow);
}
}
#endregion
}
Issue - When the value is changed in the Revision the record is displayed with new revision number keeping the CD fields as for previous revision and all the child.
That is all correct, But when the record is saved, there is error "Another process has updated the Record, your changes will be lost"
Why there is a Error
In Acuamtica we have NoteID column unique across the system If you try to create a record with duplicating NoteID field value you'll get "Another process has updated the record" exception because it consider that you are updating the same record.
In you case when you copy revision you do not reset the NoteID value for the record so you actually try to insert another record with the same value.
You'll need to add the following line to CopyRevision method
toGraph.Documents.Cache.SetDefaultExt<EWPMMasterRouting.noteID>(toGraph.Documents.Current);
Build 18.203.0006
Page: AP301000
Good day, I have extended the APRegister Class by adding 2 new checkbox fields. I want to iterate through al the APTran transactions and look for suIDs that start with FBL and GAS. If I find them the new tick boxes should tick.
Currently, the fields(tick boxes) do not save to the database. I am not sure how to tell Acumatica the APRegisterExt has updated.
APInvoiceEntry_Extension:
namespace PX.Objects.AP
{
public class APRegisterExt : PXCacheExtension<PX.Objects.AP.APRegister>
{
#region UsrGroupAEmail
[PXDBBool]
[PXUIField(DisplayName="GroupA Email")]
public virtual bool? UsrGroupAEmail { get; set; }
public abstract class usrGroupAEmail : IBqlField { }
#endregion
#region UsrGroupBEmail
[PXDBBool]
[PXUIField(DisplayName="GroupB Email")]
public virtual bool? UsrGroupBEmail { get; set; }
public abstract class usrGroupBEmail : IBqlField { }
#endregion
}
}
APInvoiceEntry_Extension:
namespace PX.Objects.AP
{
public class APInvoiceEntry_Extension : PXGraphExtension<APInvoiceEntry>
{
#region Event Handlers
protected void APInvoice_RowSelected(PXCache cache, PXRowSelectedEventArgs e)
{
APInvoice invoice = e.Row as APInvoice;
if (invoice == null) return;
var apRX = invoice.GetExtension<APRegisterExt>();
PXResultset<APTran> Tlist = PXSelectJoin<APTran,
LeftJoin<POReceiptLine,
On<POReceiptLine.receiptNbr, Equal<APTran.receiptNbr>,
And<POReceiptLine.lineNbr, Equal<APTran.receiptLineNbr>>>>,
Where<
APTran.tranType, Equal<Current<APInvoice.docType>>,
And<APTran.refNbr, Equal<Current<APInvoice.refNbr>>>>,
OrderBy<
Asc<APTran.tranType,
Asc<APTran.refNbr,
Asc<APTran.lineNbr>>>>>.Select(Base);
apRX.UsrGroupBEmail = false;
apRX.UsrGroupAEmail = false;
foreach (APTran item in Tlist)
{
if (item.SubID.Value.ToString().StartsWith("FBL") || item.SubID.Value.ToString().StartsWith("GAS"))
{
apRX.UsrGroupBEmail = true;
cache.SetValue<APRegisterExt.usrGroupBEmail>(e.Row, true);
}
else
{
apRX.UsrGroupAEmail = true;
}
}
}
#endregion
}
}
Can someone please show me the correct way of saving the data to the new tick boxes so that cache updates.
Consider moving the logic to APRegister_RowPersisting.
Importantly, APTran.subID is an Int dataType.
Read instead the Sub table/DAC during a For Loop of
Base.Transactions.Select() to detect SubCD startsWith FBL or GAS.
foreach(APTran item in Base.Transaction.Select())
{
Sub sub = PXSelect<Sub,
Where<Sub.subID, Equal<Required<Sub.subID>>>>
.Select(graph, item.SubID);
if (item.SubCD.StartsWith("FBL") ||
item.SubCD.StartsWith("GAS"))
{
apRX.UsrGroupBEmail = true;
}
else
{
apRX.UsrGroupAEmail = true;
}
}
To be complete, you may also need to reset both flags during APTran_SubID_FieldUpdated regardless of the changed value:
protected void APTran_SubID_FieldUpdated(PXCache sender,
PXFieldUpdatedEventArgs e, PXFieldUpdated del)
{
del?.Invoke(sender,e);
var apRX = Base.Document.Current.GetExtension<APRegisterExt>();
apRX.UsrGroupBEmail = false;
apRX.UsrGroupAEmail = false;
}
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.
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;
}
}
}
We have a custom processing screen that is updating a custom field called UsrDateNotified in the ARTran table where the UsrDateNotified is prior to the RevisionDateReceived in a custom table ItemBaseDocument. We also need to update the UsrDateNotified field in table ItemBaseDocument which is linked to the InventoryID in ARTran. Our current code below validates for updating the ARTran table, but we are struggling with how to also update the related ItemBaseDocument for the selected ARTran records. What is the right approach for this scenario?
using System;
using System.Collections;
using System.Linq;
using PX.Data;
using PX.SM;
using PX.Objects.AR;
using PX.Objects.CR;
using PX.Objects.IN;
namespace DocCenter
{
public class UpdateLastNotified : PXGraph<UpdateLastNotified>
{
public PXFilter<UpdateLastNotifiedFilter> MasterView;
public PXCancel<UpdateLastNotifiedFilter> Cancel;
[PXFilterable]
public PXSelect<ARTran> DetailsView;
public UpdateLastNotified()
{
Cancel.SetCaption("Clear Filter");
this.DetailsView.Cache.AllowInsert = false;
this.DetailsView.Cache.AllowDelete = false;
this.DetailsView.Cache.AllowUpdate = true;
}
protected virtual IEnumerable detailsView()
{
UpdateLastNotifiedFilter filter = MasterView.Current as UpdateLastNotifiedFilter;
PXSelectBase<ARTran> cmd = new PXSelectJoinOrderBy<ARTran,
InnerJoin<InventoryItem, On<ARTran.inventoryID, Equal <InventoryItem.inventoryID>>,
InnerJoin<ItemBaseDocument, On<InventoryItemExt.usrDocumentNumber, Equal<ItemBaseDocument.baseDocumentCode>>,
InnerJoin<Contact, On<ARTranExt.usrContactID, Equal<Contact.contactID>>>>>,
OrderBy<Asc<ARTran.tranDate>>>(this);
cmd.WhereAnd<Where<ContactExt.usrNotificationPriority,
Equal<Current<UpdateLastNotifiedFilter.notificationPriority>>>>();
cmd.WhereAnd<Where<ARTranExt.usrDateNotified,
Less<ItemBaseDocument.revisionDateReceived>>>();
if (filter.BaseDocumentCode != null)
{
cmd.WhereAnd<Where<InventoryItemExt.usrDocumentNumber,
Equal<Current<UpdateLastNotifiedFilter.baseDocumentCode>>>>();
}
return cmd.Select();
}
public PXAction<UpdateLastNotifiedFilter> Process;
[PXProcessButton]
[PXButton(CommitChanges=true)]
[PXUIField(DisplayName = "Process")]
protected virtual IEnumerable process(PXAdapter adapter)
{
PXLongOperation.StartOperation(this, delegate()
{
foreach(ARTran tran in DetailsView.Select())
{
if (tran.Selected==true)
{
ARTranExt tranExt = tran.GetExtension<ARTranExt>();
ARInvoiceEntry tranEntry = new ARInvoiceEntry();
tranExt.UsrDateNotified = MasterView.Current.DateNotified;
tranEntry.Transactions.Update(tran);
tranEntry.Save.PressButton();
}
}
}
);
return adapter.Get();
}
[Serializable]
public class UpdateLastNotifiedFilter : IBqlTable
{
public static class NotificationPriority
{
public const string None = "N";
public const string Alert = "A";
public const string Express = "E";
public const string Shipment = "P";
public const string Subscription = "S";
}
#region NotificationPriority
public abstract class notificationPriority : PX.Data.IBqlField
{
}
[PXDBString(1, IsFixed = true)]
[PXDefault(NotificationPriority.None)]
[PXUIField(DisplayName = "Notification Type")]
[PXStringList(
new string[]
{
NotificationPriority.None,
NotificationPriority.Alert,
NotificationPriority.Express,
NotificationPriority.Shipment,
NotificationPriority.Subscription
},
new string[]
{
"None",
"Alert",
"Express",
"Shipment",
"Subscription"
})]
#endregion
#region BaseDocumentID
public abstract class baseDocumentCode : PX.Data.IBqlField
{
}
[PXString(50)]
[PXUIField(DisplayName="Document Number")]
[PXSelector(typeof(DocCenter.ItemBaseDocument.baseDocumentCode))]
public virtual String BaseDocumentCode
{
get;
set;
}
#endregion
#region DateNotified
public abstract class dateNotified : PX.Data.IBqlField
{
}
[PXDBDate()]
[PXDefault(typeof(AccessInfo.businessDate))]
[PXUIField(DisplayName = "Date Notified")]
public DateTime? DateNotified { get; set; }
#endregion
}
}
}
Your best bet would be to create a view that selects ItemBaseDocument.
PXSelect<ItemBaseDocument> ViewName;
In your for loop of your action button, you will want to create a new ItemBaseDocument object and set it equal to the corresponding ItemBaseDocument row entry. You can then update the date of this object, and when you execute your Save.PressButton() action, that should save the updates to that entry as well.
foreach(ARTran tran in DetailsView.Select())
{
if (tran.Selected==true)
{
ARTranExt tranExt = tran.GetExtension<ARTranExt>();
ARInvoiceEntry tranEntry = new ARInvoiceEntry();
tranExt.UsrDateNotified = MasterView.Current.DateNotified;
tranEntry.Transactions.Update(tran);
tranEntry.Save.PressButton();
//Target Added Code
ItemBaseDocument doc = PXSelect<ItemBaseDocument, Where<ItemBaseDocument.inventoryID,
Equal<Required<ARTran.inventoryID>>>>.Select(tran.InventoryID);
doc.UsrDateNotified = MasterView.Current.DateNotified;
}
}
Disclaimer: There may be a syntax error in the added code above. If there is, please let me know and I will fix it.