我想在保存发票(AR301000)之前分配发票编号(RefNbr) - 如果为空白。我已经覆盖了RowPersisting事件,如下所示:
C:\Users\User\StudioProjects\Project\src\META-INF\MANIFEST.MF
INSTEAD OF C:\Users\User\StudioProjects\Project\src\main\java\META-INF\MANIFEST.MF
如果我提出了一张新发票,没有任何行并保存。它按预期正确分配了参考Nbr。
问题是我是否用行提出新发票。它抱怨RefNbr是空白的。
我错过了什么?我该如何解决 ?感谢。
答案 0 :(得分:2)
当父记录的源字段和从属记录的外键字段都不为空时,Acumatica的 PXDBDefaultAttribute 仅更新相关记录的字段。
当依赖记录插入缓存时, PXDBDefaultAttribute 会将源字段值从父记录复制到它从依赖记录中修饰的字段。当框架将新的父记录保存到数据库中时,它首先为父记录引发 RowPersisting 事件。 PXDBDefaultAttribute 订阅父记录类型的 RowPersisting 事件以保存原始源字段值:
此外, PXDBDefaultAttribute 订阅依赖记录类型的 RowPersisting 事件,以使用实际源字段值更新外键字段,该字段值刚刚记录在数据库。要更新外键字段 PXDBDefaultAttribute ,必须首先使用先前在父记录类型的 RowPersisting 事件处理程序中获取的原始源字段值来查找父记录。如果外键字段值显示为空,则 PXDBDefaultAttribute 无法为其找到父记录,并且只是将依赖字段留空。这最终导致错误“ RefNbr不能为空 ”。
尽管如此,我相信如果将AR发票参考编号保留为空,直到将其保存到数据库,将无法实现所需的结果。作为替代方案,我建议将AR发票参考编号默认为某个常量,例如 <输入> ,同时将其替换为 ARInvoice_RowPersisting 处理程序中的实际数字:
using PX.Data;
using System;
namespace PX.Objects.AR
{
public class ARInvoiceNumberingCstAttribute : ARInvoiceType.NumberingAttribute
{
public const string EnterRefNbr = "<ENTER>";
protected override string GetNewNumber()
{
string newNumber = base.GetNewNumber();
if (string.IsNullOrEmpty(newNumber))
{
newNumber = EnterRefNbr;
}
return newNumber;
}
public override void RowPersisting(PXCache sender, PXRowPersistingEventArgs e)
{
if (GetNewNumber() == EnterRefNbr) return;
base.RowPersisting(sender, e);
}
}
public class ARInvoiceEntry_Extension : PXGraphExtension<ARInvoiceEntry>
{
[PXRemoveBaseAttribute(typeof(ARInvoiceType.NumberingAttribute))]
[PXMergeAttributes(Method = MergeMethod.Append)]
[ARInvoiceNumberingCst]
protected void ARInvoice_RefNbr_CacheAttached(PXCache sender)
{ }
protected void ARInvoice_RowPersisting(PXCache cache, PXRowPersistingEventArgs e,
PXRowPersisting InvokeBaseHandler)
{
if (InvokeBaseHandler != null)
InvokeBaseHandler(cache, e);
var row = (ARInvoice)e.Row;
if (row != null)
{
//BB-<timestamp> as inv# for testing only
if (row.RefNbr == ARInvoiceNumberingCstAttribute.EnterRefNbr)
row.RefNbr = "BB-" + DateTime.Now.ToString("hhmmsstt");
}
}
}
}