首页 > 解决方案 > 如何在 PXSelector 的 Search<> 参数中包含 DAC 扩展未绑定字段?

问题描述

我已经对 INLocation.LocationCD 进行了分段,并且需要限制 PXSelector 以根据输入位置的屏幕包含或排除特定段。我已经能够访问 PXSelector 显示列中的 DAC 扩展字段,但在 PXSelector 的 Search<> 参数期间该字段被评估为空。

我努力了:

关键点:

我的 DAC 扩展中定义的字段:

[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> { }

PX 选择器:

[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))]

PX投影:

[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

}

我试过简单的版本和各种组合都无济于事。如何在 PXSelector 的 Search<> 子句中利用我的“条件”?

编辑 1: PXSelector 作为列返回值的图片 - 不能用作 PXRestrictor 或 Select<> 中的 where 子句。

健康)状况

编辑 2:更多信息

我已简化 DAC 扩展以使用 PXFormula 并选择 PXFormula 检索到的 LocationCD 的最后一个字符来设置值。

我们需要使用 LocationCD 的最后一段来管理 bin 中零件的状况。这将使我们能够将成本分开并管理 MRO 备件以进行维护,如新的、使用的、已修复的和需要维修的,同时还允许稍后指定其他条件(如收到损坏的 NCM 等)(如果需要)。虽然某些材料可以在全球范围内使用,但某些条件下的材料需要在某些用例下可用。我的预期策略是将规则应用于位置 CD 的最后一段,以允许 PXSelector 控制用户输入,如果需要,可以作为 INLocation 上的 DAC 扩展或作为相关图表中的 Cache_Attached。

我在 INLocation 上为 usrSSCondition 创建了一个 DAC 扩展作为 PXString。我最近的尝试是使用 PXFormula 来提取 LocationCD 值,然后在 set{} 上使用自定义代码来挑选最后一段并为相关条件设置代码。(这种技术对我来说实际上是新的,stackoverflow 帖子中的回应引导我想到了这个想法。)

在 PXSelector 中用作显示列时,我可以看到该值。但是, Select<> 不允许我进入用于显示该条件的那个段或自定义 PXString 字段。我希望一些“幕后魔术”会评估我的 PXString 字段以限制结果,但似乎该字段在 Select 期间返回为 null,然后在 DAC 处理的后续步骤中进行处理。当我考虑 Select 正在做什么时,没有存储在数据库中的数据不能用于过滤结果是有道理的。PXRestrictor 也不影响它。

1) 有没有办法让我的 DAC 在 PXSelector 应用 where 子句之前处理 PXString 值?2)这是我需要对属性进行后处理的东西吗?(如果是这样,关于在哪里寻找一个简单的例子有什么建议吗?)

更新的 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,
            };
        }
    }
}

标签: acumatica

解决方案


永远不要在 getter 中使用代码,它不会在 BQL 表达式中正常工作!

如果你想检查Loc.Substring(Loc.Length - 1, 1)BQL 中的某个地方,只需编写你自己的 BQL 函数

public class ConditionTypeBySegment<Source> : BqlFunction, IBqlOperand, IBqlCreator
    where Source : IBqlOperand
{
    private IBqlCreator _source;

    public void Verify(PXCache cache, object item, List<object> pars, ref bool? result, ref object value)
    {
        if (!getValue<Source>(ref _source, cache, item, pars, ref result, out value) || value == null)
            return;

        if (value is string strValue)
        {
            switch (strValue.Substring(strValue.Length - 1, 1))
            {
                case "N":
                    value = ConditionType.New;
                    break;
                case "R":
                    value = ConditionType.Repair;
                    break;
                case "C":
                    value = ConditionType.Core;
                    break;
                case "U":
                    value = ConditionType.Used;
                    break;
                default:
                    value = ConditionType.Undefined;
                    break;
            }

            return;
        }

        value = ConditionType.Undefined;
    }

    public bool AppendExpression(ref SQLExpression exp, PXGraph graph, BqlCommandInfo info, BqlCommand.Selection selection)
    {
        ...
        return true;
    }
}

或使用现有功能的组合。例如:

[PXSelector(typeof(Search<INLocation.locationID,
    Where<INLocation.receiptsValid, Equal<True>,
        And<Substring<FABookBalance.deprToPeriod, Sub<StrLen<FABookBalance.deprToPeriod>, int1>, int1>, NotEqual<ConditionTypes.tCore>>>>),
    typeof(INLocation.locationCD),
    typeof(INLocation.active),
    typeof(INLocation.primaryItemID),
    typeof(INLocation.primaryItemClassID),
    typeof(INLocationExt.usrSSCondition),
    typeof(INLocation.receiptsValid),
    SubstituteKey = typeof(INLocation.locationCD))]

public static class ConditionTypes
{
    public class tNew : PX.Data.BQL.BqlString.Constant<tNew> { public tNew() : base("N") { } }
    public class tRepair : PX.Data.BQL.BqlString.Constant<tRepair> { public tRepair() : base("R") { } }
    public class tCore : PX.Data.BQL.BqlString.Constant<tCore> { public tCore() : base("C") { } }
    public class tUsed : PX.Data.BQL.BqlString.Constant<tUsed> { public tUsed() : base("U") { } }
}

推荐阅读