I have segmented INLocation.LocationCD and need to restrict the PXSelector to include or exclude a particular segment based on the screen where the location is being entered. I have been able to access the DAC extension field in the displayed columns of the PXSelector, but the field is evaluated as null during the Search<> parameter of PXSelector.
I have tried:
- referencing INLocationExt.myField directly,
- making an inherited DAC to define the custom field directly,
- and creating a PXProjection in hopes that the additional layer would cause the unbound field to be retrieved to populate the PXSelector in case the field was not being loaded in time for the Search<>.
Key points:
- This is an unbound field in the DAC extension
- It returns an value based evaluating the last segment of the INLocation.LocationCD
- Generic Inquiries properly display this value
- I have been unable to make PXSelector return any values when I reference the unbound field unless I simply check And
The field defined in my DAC extension:
[PXString(1)]
[PXUIField(DisplayName = "Condition")]
[ConditionType.List]
public String UsrSSCondition
{
get
{
if (LocationCD == null || LocationCD.Length == 0) return ConditionType.Undefined;
switch (LocationCD.Substring(LocationCD.Length - 1, 1))
{
case "N":
return ConditionType.New;
case "R":
return ConditionType.Repair;
case "C":
return ConditionType.Core;
case "U":
return ConditionType.Used;
default:
return ConditionType.Undefined;
}
}
}
public abstract class usrSSCondition : PX.Data.BQL.BqlString.Field<usrSSCondition> { }
The PXSelector:
[PXSelector(typeof(Search<INLocation.locationID, Where<INLocation.receiptsValid, Equal<True>,
And<INLocationExt.usrSSCondition, NotEqual<ConditionType.core>>>>),
typeof(INLocation.locationCD),
typeof(INLocation.active),
typeof(INLocation.primaryItemID),
typeof(INLocation.primaryItemClassID),
typeof(INLocationExt.usrSSCondition),
typeof(INLocation.receiptsValid),
SubstituteKey = typeof(INLocation.locationCD))]
The PXProjection:
[Serializable]
[PXCacheName("SSCS INLocation")]
[PXProjection(typeof(Select<INLocation>))]
public partial class SSINLocation : IBqlTable
{
#region LocationID
[PXDBInt(IsKey = true, BqlField = typeof(INLocation.locationID))]
public int? LocationID { get; set; }
public abstract class locationID : PX.Data.BQL.BqlInt.Field<locationID> { }
#endregion
#region LocationCD
[PXDBString(BqlField = typeof(INLocation.locationCD))]
public String LocationCD { get; set; }
public abstract class locationCD : PX.Data.BQL.BqlString.Field<locationCD> { }
#endregion
#region UsrSSCondition
[PXDBString(BqlField = typeof(INLocationExt.usrSSCondition))]
public String UsrSSCondition { get; set; }
public abstract class usrSSCondition : PX.Data.BQL.BqlString.Field<usrSSCondition> { }
#endregion
#region ReceiptsValid
[PXDBBool(BqlField = typeof(INLocation.receiptsValid))]
public bool? ReceiptsValid { get; set; }
public abstract class receiptsValid : PX.Data.BQL.BqlBool.Field<receiptsValid> { }
#endregion
#region Active
[PXDBBool(BqlField = typeof(INLocation.active))]
public bool? Active { get; set; }
public abstract class active : PX.Data.BQL.BqlBool.Field<active> { }
#endregion
#region PrimaryItemID
[PXDBInt(BqlField = typeof(INLocation.primaryItemID))]
public int? PrimaryItemID { get; set; }
public abstract class primaryItemID : PX.Data.BQL.BqlInt.Field<primaryItemID> { }
#endregion
#region PrimaryItemClassID
[PXDBInt(BqlField = typeof(INLocation.primaryItemClassID))]
public int? PrimaryItemClassID { get; set; }
public abstract class primaryItemClassID : PX.Data.BQL.BqlInt.Field<primaryItemClassID> { }
#endregion
}
I have tried simple versions and various combinations of those to no avail. How do I leverage my "condition" in the Search<> clause of the PXSelector?
Edit 1: Picture of PXSelector returning values as a column - does not work as a PXRestrictor or as a where clause in Select<>.
Edit 2: More info
I have simplified the DAC extension to use PXFormula and pick out the last character of the LocationCD retrieved by PXFormula to set the value.
We need to use the last segment of the LocationCD to manage the condition of the part in a bin. This would allow us to separate cost as well as manage MRO Spares for maintenance as New, Used, Repaired, and Requiring Repair while also allowing the ability to specify other conditions later (like NCM if received damaged, etc.) if needed. While some materials can be used globally, materials of certain conditions need to be available under certain use cases. My intended strategy is to apply the rules to the last segment of the Location CD to allow the PXSelector to control user entry, either as a DAC extension on INLocation or as a Cache_Attached in the relevant graphs, if necessary.
I created a DAC extension on INLocation for usrSSCondition as a PXString. My latest attempt was to use a PXFormula to pull the LocationCD value and then custom code on the set{} to pick out the last segment and set the code for the relevant condition. (This technique was actually new to me, and a response in the stackoverflow post guided me to the idea.)
When using in a PXSelector as a displayed column, I can see the value. However, the Select<> does not allow me to tap into that segment or custom PXString field used to display that condition. I was hoping that some "behind the scenes magic" would evaluate my PXString field to limit the results, but it seems that the field is returned as null during the Select and then processed in a later step of DAC processing. When I think about what a Select is doing, it would make sense that data not stored in the database cannot be used to filter the results. PXRestrictor does not impact it either.
1) Is there a way to get my DAC to process the PXString value before the PXSelector applies the where clause? 2) Is this something I need to take to an attribute for post-processing? (If so, any suggestions on where to look for a simple example?)
Updated DAC:
#region usrSSCondition
private String _condition;
[PXString]
[PXUIField(DisplayName = "Condition")]
[PXFormula(typeof(INLocation.locationCD))]
[ConditionType.List]
public String UsrSSCondition
{
get { return _condition; }
set
{
string Loc = value;
if (Loc == null || Loc.Length == 0)
{
_condition = ConditionType.Undefined;
}
else
{
_condition = (Loc.Substring(Loc.Length - 1, 1)) switch
{
"N" => ConditionType.New,
"R" => ConditionType.Repair,
"C" => ConditionType.Core,
"U" => ConditionType.Used,
_ => ConditionType.Undefined,
};
}
}
}