首页 > 解决方案 > 当文档上的 Hold 字段未选中时,如何正确验证 Transaction 中的字段?

问题描述

我有一个自定义屏幕的文档/事务(FormGrid)结构。当标题中的 Hold 框未选中时,我需要验证 Transaction 级别中的值。从根本上说,我的挑战似乎来自事件处理程序的操作顺序。(FieldVerifying -> FieldUpdating -> Field Updated -> RowUpdating -> RowUpdated)结合处理的视图顺序(似乎是其他视图之前的主要视图)。

现在让我完全困惑的是,如果我将字段留在表单的事务(网格)部分,CommitChanges 会触发,一切正常。但是,如果我将我的字段 (OrderQty) 设置为 0,然后立即取消选中标题中的 Hold 而没有首先“离开” OrderQty 字段,则在处理 Hold 复选框之前不会提交 OrderQty 值。这意味着我无法验证 OrderQty 是否大于 0。从字面上看,我无法在缓存或任何形式的视图中看到我的 OrderQty 值,因为在网格中的 OrderQty 之前处理标题中的保留框。

我已经尝试过简单的方法来进行测试,这是一个更复杂的尝试获取数据的片段。Caches[].Updated 在处理 hold 复选框后保存新值,而不是之前。AddWithoutDuplicates 是一种简单地确保列表中没有记录的方法(允许查看更新的缓存值而不是尚未提交的旧值)

        List<SSRQLine> list = new List<SSRQLine>();

        foreach (SSRQLine line in Caches[typeof(SSRQLine)].Updated)
        {
            AddWithoutDuplicates(list, line);
        }

        foreach (SSRQLine line in Caches[typeof(SSRQLine)].Inserted)
        {
            AddWithoutDuplicates(list, line);
        }

        foreach (SSRQLine line in Lines.Select())
        {
            AddWithoutDuplicates(list, line);
        }

        foreach (SSRQLine line in list)
        ...

有没有办法在输入过程中可靠地验证来自保持复选框的网格数据?或者我必须稍后在 RowPersisting 事件中处理验证?或者关于如何从 Hold_FieldVerifying 验证网格中的用户条目的任何其他建议?

标签: acumatica

解决方案


父 DAC 是 SSRQRequisition,子 DAC 是 SSRQLine。

由于目标是监视取消保持的请求,因此最初的工作被附加到标头 DAC 的保持字段。问题是它需要在子 DAC 未处理其字段事件的一对多关系中验证子 DAC 值。要警告用户但不阻止保存请求,请创建以下事件处理程序:

#region SSRQLine_OrderQty_FieldVerifying
protected virtual void _(Events.FieldVerifying<SSRQLine.orderQty> e)
{
    SSRQLine row = (SSRQLine) e.Row;
    if((decimal?)e.NewValue == 0)
    {
        e.Cache.RaiseExceptionHandling<SSRQLine.orderQty>(e.Row, row.OrderQty, new PXSetPropertyException(Messages.InvalidQuantity, PXErrorLevel.Warning));
    }
}
#endregion

要重新验证整个请求,然后允许用户在取消保留请求后保存它,请在标头 DAC 的 RowPersisting 事件处理程序中执行验证。请注意,如果正在删除请求,则不应执行验证,因此还要测试操作。此外,仅当用户取消暂停请求时才需要进行测试,因此在重新暂停时无需验证。

#region SSRQRequisition_RowPersisting
protected void _(Events.RowPersisting<SSRQRequisition> e)
{
    SSRQRequisition row = e.Row;
    if (e.Operation != PXDBOperation.Delete && row?.Hold == false)
    {
        ValidateConsignment();
    }
}
#endregion

创建 ValidateConsignment 方法是为了简化代码的读取,但由 SSRQRquisition RowPersisting 事件调用。通过这次将异常处理提升为 ERROR 并抛出异常,用户会收到警告,警告现在是阻止保存记录而不被暂停的原因。

#region ValidateConsignment
protected virtual void ValidateConsignment()
{

    int lineCounter = 0;

    SSRQRequisition req = Requisitions.Current;

    List<SSRQLine> list = new List<SSRQLine>();

    foreach (SSRQLine line in Caches[typeof(SSRQLine)].Updated)
    {
        AddWithoutDuplicates(list, line);
    }

    foreach (SSRQLine line in Caches[typeof(SSRQLine)].Inserted)
    {
        AddWithoutDuplicates(list, line);
    }

    foreach (SSRQLine line in Lines.Select())
    {
        AddWithoutDuplicates(list, line);
    }

    foreach (SSRQLine line in list)
    {
        lineCounter++;

        if (line.SiteID == null)
        {
            throw new PXSetPropertyException(Messages.NoWhse, PXErrorLevel.Error);
        }

        if (line.OrderQty == null || line.OrderQty == 0)
        {
            this.Lines.Cache.RaiseExceptionHandling<SSRQLine.orderQty>(line, line.OrderQty, new PXSetPropertyException(Messages.InvalidQuantity, PXErrorLevel.Error));
            throw new PXSetPropertyException(Messages.InvalidQuantity, PXErrorLevel.Error);
        }

    }
    if (lineCounter == 0)
    {
        this.Lines.Cache.RaiseExceptionHandling<SSRQRequisition.hold>(req, req.Hold, new PXSetPropertyException(Messages.NoLines, PXErrorLevel.Error));
        throw new PXSetPropertyException(Messages.NoLines, PXErrorLevel.Error);
    }

}
#endregion

ValidateConsignment 方法当前循环通过缓存的 Inserted 和 Updated 副本,但我可能能够删除这些副本,因为在将更新应用于缓存之前不再对其进行测试。由于现在是从 RowPersisting 方法调用的,因此应该已经应用了用于在缓存中插入和更新记录的所有字段和行事件处理程序。但是,在删除它们之前,我会进一步测试。初步测试确认提供的代码实现了目标。为了提供所需的最终用户体验,只需将代码分布在 3 个不同的事件中,而不是将其全部塞进原本用于启动检查的 Hold 复选框的事件中。行为最终与最初的预期略有不同,


推荐阅读