I'm customizing the Approve Time Card Summaries screen to do the following:
1.) Add a checkbox to the filter section
2.) When this checkbox is checked, don't show the 'Approved' rows in the grid.
I've added a cache extension with a new unbound boolean field, and added the checkbox to the filter / header section of the screen.
What I'm wondering is - Is there an IEnumerable method (can I use 'summary'?) that can check that header filter field and only yield return the rows that pass the filter test? If so, I'm not sure what the syntax would be to do this.
Or - would it be better to rewrite the Summary view select statement in the Graph extension with the added where clause?
Thanks...
I figured out how to do this. In the Graph extension, I rewrote the 'Summary' view and then used the IEnumerable 'summary' delegate to return only the rows where it meets the checkbox criteria I set up. To wit:
public PXSelectJoin<EPSummaryApprove
, LeftJoin<EPEarningType, On<EPEarningType.typeCD, Equal<EPSummaryApprove.earningType>>>
, Where2<Where<EPSummaryApprove.taskApproverID, Equal<Current<EPSummaryFilter.approverID>>, Or<Where<EPSummaryApprove.taskApproverID, IsNull, And<EPSummaryApprove.approverID, Equal<Current<EPSummaryFilter.approverID>>>>>>
, And2<Where<EPSummaryApprove.weekId, GreaterEqual<Current<EPSummaryFilter.fromWeek>>, Or<Current<EPSummaryFilter.fromWeek>, IsNull>>
, And2<Where<EPSummaryApprove.weekId, LessEqual<Current<EPSummaryFilter.tillWeek>>, Or<Current<EPSummaryFilter.tillWeek>, IsNull>>
, And2<Where<EPSummaryApprove.projectID, Equal<Current<EPSummaryFilter.projectID>>, Or<Current<EPSummaryFilter.projectID>, IsNull>>
, And2<Where<EPSummaryApprove.projectTaskID, Equal<Current<EPSummaryFilter.projectTaskID>>, Or<Current<EPSummaryFilter.projectTaskID>, IsNull>>
, And<Where<EPSummaryApprove.employeeID, Equal<Current<EPSummaryFilter.employeeID>>, Or<Current<EPSummaryFilter.employeeID>, IsNull>>
>
>
>
>
>
>
> Summary;
protected IEnumerable summary()
{
var epsf = (EPSummaryFilter)Base.Filter.Cache.Current;
var epse = PXCache<EPSummaryFilter>.GetExtension<EPSummaryFilterExt>(epsf);
foreach(var res in Base.Summary.Select())
{
var sum = (EPSummaryApprove)res;
if (epse != null)
{
if (epse.ExcludeApproved == true)
{
if (sum.IsApprove != true)
{
yield return res;
}
}
else
yield return res;
}
else
yield return res;
}
}
Related
Example:
As per the Below screenshot, i have to combine below two grids into one grid and the first grid(query list) will display as it is and the second grid values should show as drop down for the respective query.
Samplegridsimage
when i tried to use field selecting event, it is loading all vales from second grid but i need only 3 values for fuel type value and for others different drop down.
can anyone suggest how to get only particular values in the drop down.
protected virtual void KNRWTAXQueries_Response_FieldSelecting(PXCache cache, PXFieldSelectingEventArgs e)
{
KNRWTAXQueries doc = e.Row as KNRWTAXQueries;
if (doc == null) return;
List<string> Responsevalues = new List<string>();
List<string> ResponseLables = new List<string>();
if (QueryList.Current != null)
{
if (Base.Transactions.Current != null)
{
foreach (KNRWTAXQueries queries in PXSelect<KNRWTAXQueries, Where<KNRWTAXQueries.nonStockItemID, Equal<Required<APTran.inventoryID>>>>.Select(Base, doc.NonStockItemID))
{
foreach (KNRWTAXResponse response in PXSelect<KNRWTAXResponse, Where<KNRWTAXResponse.tAXQueID, Equal<Required<KNRWTAXResponse.tAXQueID>>>>.
Select(Base, queries.Taxqueid))
{
Responsevalues.Add(response.Response);
ResponseLables.Add(response.Response);
e.ReturnState = PXStringState.CreateInstance(e.ReturnState, 255, true, typeof(KNRWTAXQueries.response).Name, false, 1, string.Empty, Responsevalues.ToArray(),
ResponseLables.ToArray(), true, null);
}
}
}
}
// ((PXStringState)e.ReturnState).MultiSelect = false;
}
You can use RowSelected event of the row to set the list. No need to use FieldSelecting (however you can use field selecting too)
You should use PXStringListAttribute.SetList method to set new list instead of using string state
You should set MatrixMode=true in the aspx grid row so that list is recreated for each row (oterwise the list will be the same for all rows)
<px:PXGridColumn DataField="OrigTranType" Type="DropDownList" MatrixMode="true" />
When using the collapsed interface on the sales order (AKA the arrow tiny button to the right) is it possible to do one of the following:
Change the fields it displays (eg: right now I am showing some labels for the fields below in those columns). It would be truly amazing if when I click that, I could move some of the fields from the first column to the top 2 rows. Thus, I would move the most important data from the first column to the header.
Alternately, can you make the top be 3-4 rows instead of just 2, or is that hard coded in?
Thanks in advance.
Form container Autosize element and MinHeight/MinHeightLimit properties does affect the behavior of the expander but I haven't found a way to achieve the desired functionality with those.
This is the code which generates the form panel Div element:
/// <summary>
/// Create the content division control.
/// </summary>
private WebControl CreateContentDiv()
{
WebControl div = this.TemplateContainer;
this.hasStaticContent = this.AutoSizeWindow;
if (hasStaticContent) foreach (Control c in div.Controls)
{
IAutoSizedControl sc = c as IAutoSizedControl;
if (sc != null && sc.AutoSize.Enabled) { hasStaticContent = false; break; }
var wc = c as WebControl;
var hc = c as System.Web.UI.HtmlControls.HtmlControl;
if (wc != null || hc != null)
{
string pos = (wc != null) ? wc.Style["position"] : hc.Style["position"];
if (pos == "absolute") { hasStaticContent = false; break; }
}
}
if (!hasStaticContent && (!ControlHelper.GetHeight(this).IsEmpty || this.AutoSize.Enabled))
div.Height = Unit.Percentage(100);
// mark division as editable region
if (this.DesignMode)
div.Attributes.Add(DesignerRegion.DesignerRegionAttributeName, "0");
return div;
}
I also found elements that suggests the 2 row value is hardcoded for the purpose of showing the expander control (if content height is taller then 2 row show expander control):
/// <summary>
///
/// </summary>
protected override void OnLoad(EventArgs e)
{
if (this.Page != null && !this.Page.IsCallback)
{
var gen = (PXLayoutGenerator)this.TemplateContainer;
gen.CreateStackByRules();
if (!this.CaptionAsLink && !this.AutoSize.Enabled)
{
if (this.AllowCollapse == null && gen.Rows > 2) this.AllowCollapse = true;
//if (this.AllowCollapse == true && !this.CaptionVisible) this.CreateCollapseImage();
}
}
base.OnLoad(e);
}
With JavaScript it would possible to roll your own logic to control the UI layer.
Setting the TabPanel style height property will achieve the desired rendering and it should be possible to hook the expander events too:
document.getElementById('ctl00_phF_form_t0').style.height = '117px';
To re-order the editor control based on the form collapsed state is a bit more difficult depending on the layout but can be achieved similarly by setting the CSS display property:
var isVisible = false;
document.getElementById(alse'ctl00_phF_form_t0_edCustomerID_text').parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.style.display = isVisible ? 'block' : 'none';
I am trying to update the Inventory Item ImageUrl if it is found to be null with some conditions. I have added a Usr field called UsrStyleImg to the Item Class screen. This field is for a basic image of an item and it is stored in the database. The functionality I want is if the Inventory Item does not have an image in the ImageUrl then it will default to the UsrStyleImg that is connected with the ItemClassID. ItemClassID is also found on the Stock Item Screen. Here is the code I have in the InventoryItemMaint graph:
protected void InventoryItem_ImageUrl_FieldDefaulting(PXCache cache, PXFieldDefaultingEventArgs e)
{
var row = (InventoryItem)e.Row;
if (row == null) return;
var item = (INItemClass)PXSelect<INItemClass, Where<INItemClass.itemClassID, Equal<Current<InventoryItem.itemClassID>>>>.Select(Base, row.ItemClassID);
var image = PXSelect<InventoryItem, Where<InventoryItem.imageUrl, Equal<Current<InventoryItem.imageUrl>>>>.Select(Base, row.ImageUrl);
if (image != null)
return;
else {
e.NewValue = item.GetExtension<INItemClassExt>().UsrStyleImg;
}
}
The code compiles fine but when I test with an Item that has an Item Class attached to it with an image in the INItemClass table called UsrStyleImg it does not populate to the imageUrl found in the Inventory Item table or the Stock Item screen. I have also tried this with FieldSelecting and using the e.ReturnValue with still the same results.
If I need more clarification please let me know.
Try using a RowSelecting Event
protected virtual void InventoryItem_RowSelecting(PXCache sender, PXRowSelectingEventArgs e)
{
InventoryItem row = e.Row as InventoryItem;
//Extra checks to prevent infinite loops
if (row != null && !string.IsNullOrWhiteSpace(row.InventoryCD) && Base.Item.Cache.GetStatus(row) == PXEntryStatus.Notchanged)
{
if (!string.IsNullOrWhiteSpace(row.ItemClassID))
{
//You must always use a PXConnectionScope if Selecting during RowSelecting
using (new PXConnectionScope())
{
//If you're going to pass in a value in .Select, use Required instead of Current.
INItemClass itemClass = PXSelectReadonly<INItemClass, Where<INItemClass.itemClassID, Equal<Required<INItemClass.itemClassID>>>>.Select(Base, row.ItemClassID);
if (itemClass != null && string.IsNullOrWhiteSpace(row.ImageUrl))
{
INItemClassExt itemClassExt = itemClass.GetExtension<INItemClassExt>();
//To prevent unneeded update if it's blank
if (!string.IsNullOrWhiteSpace(itemClassExt.UsrStyleImg))
{
row.ImageUrl = itemClassExt .UsrStyleImg;
//Force set the status in the Cache, otherwise it infinite loops
Base.Item.Cache.SetStatus(row, PXEntryStatus.Updated);
Base.Item.Update(row);
}
}
}
}
}
}
I have added a field to the Prepare Replenishment form that needs to be updated when a user selects a row in the Replenishment Item grid. How do I access the field. I know it is in the INReplenishmentFilterExt but I can't figure out how to get access to the extension.
Edit #1: I am able to get the value of the field but it does not update on the screen when I use cache.SetValue. I am trying to update this filter extension field from inside of the Selected event handler.
protected void INReplenishmentItem_Selected_FieldUpdating(PXCache cache, PXFieldUpdatingEventArgs e)
{
var row = (INReplenishmentItem)e.Row;
if (row == null)
return;
INReplenishmentFilter filter = Base.Filter.Current;
INReplenishmentFilterExt filterExt = PXCache<INReplenishmentFilter>.GetExtension<INReplenishmentFilterExt>(filter);
decimal poAmount = filterExt.UsrPOAmount.HasValue ? filterExt.UsrPOAmount.Value : 0;
decimal lastPrice = pvi.LastPrice.HasValue ? pvi.LastPrice.Value : 0;
decimal newPOAmount = poAmount + lastPrice;
cache.SetValue<INReplenishmentFilterExt.usrPOAmount>(filterExt, newPOAmount);
}
You cannot set the value of the Filter using the Cache of INReplenishmentItem.
I have edited my answer, the code below should work.
//Always use virtual methods for Event Handlers
protected virtual void INReplenishmentItem_Selected_FieldUpdating(PXCache sender, PXFieldUpdatingEventArgs e)
{
//Try not to use vars. Especially when you know the Type of the object
INReplenishmentItem row = e.Row as INReplenishmentItem;
if (row != null)
{
INReplenishmentFilter filter = Base.Filter.Current;
INReplenishmentFilterExt filterExt = PXCache<INReplenishmentFilter>.GetExtension<INReplenishmentFilterExt>(filter);
decimal poAmount = filterExt.UsrPOAmount ?? 0;
decimal lastPrice = pvi.LastPrice ?? 0;//Not sure what pvi is
decimal newPOAmount = poAmount + lastPrice;
//"sender" is the cache that specifically stores the datatype of row
//Therefor you cannot use it to update records of a different datatype
//You also should not pass an Extension into the argument that should be the row object you are trying to update
Base.Filter.Cache.SetValueExt<INReplenishmentFilterExt.usrPOAmount>(filter, newPOAmount);
}
}
I have a custom line number field in opportunity product tab for customer to re-sequence the selected products and the grid is sorted on custom field value.
I am trying to pass the value from opportunity to sales order which also having a similar field.
the following code i have tried and it did not work
PXGraph.InstanceCreated.AddHandler<SOOrderEntry>((graph) =>
{
graph.RowUpdated.AddHandler<SOLine>((cache, args) =>
{
CROpportunityProducts product = (adapter.View.Graph as OpportunityMaint).Products.Current;
CROpportunityProductsExtNV productext = PXCache<CROpportunityProducts>.GetExtension<CROpportunityProductsExtNV>(product);
SOLine soline = (SOLine)args.Row;
SOLineExtNV solineext = PXCache<SOLine>.GetExtension<SOLineExtNV>(soline);
solineext.UsrLineNo = productext.UsrLineNo;
});
});
The following piece of code returns same value for all line numbers
You can implement RowInserting Event handler as below:
graph.RowInserting.AddHandler<SOLine>((cache, args) =>
{
var soLine = (SOLine)args.Row;
CROpportunityProducts opProduct = PXResult<CROpportunityProducts>.Current;
SOLineExtNV soLineExt = PXCache<SOLine>.GetExtension<SOLineExtNV>(soLine);
CROpportunityProductsExtNV opProductExt = PXCache<CROpportunityProducts>.GetExtension<CROpportunityProductsExtNV>(opProduct);
soLineExt.UsrLineNo = opProductExt.UsrLineNo;
});
wish they could split up the call to create the order and the call to insert the lines to make it easier to customize. We have done something similar. Here is a sample from what I tested using a graph extension and overriding the DoCreateSalesOrder call in the opportunitymaint graph. (This assumes the select on products is the same order the transaction on the sales order were inserted. I am sure there could be a better answer, but this is an example I have handy.)
public class CROpportunityMaintExtNV : PXGraphExtension<OpportunityMaint>
{
[PXOverride]
public virtual void DoCreateSalesOrder(Action del)
{
try
{
del();
}
catch (PXRedirectRequiredException redirect)
{
var products = this.Products.Select().ToArray();
int rowCntr = 0;
foreach (SOLine soLine in ((SOOrderEntry)redirect.Graph).Transactions.Select())
{
// Assumes inserted rows in same order as products listed (default should be the key)
//Current product
CROpportunityProducts currentProduct = products[rowCntr];
var productExtension = currentProduct.GetExtension<CROpportunityProductsExtNV>();
((SOOrderEntry) redirect.Graph).Transactions.Cache.SetValueExt<SOLineExtNV.usrLineNo>(soLine, productExtension.UsrLineNo);
rowCntr++;
}
throw redirect;
}
}
}
The problem you had with your code is the Current product was always the same which resulted in the same value.