我在Acumatica项目中添加了许多自定义屏幕,并且我想在这些屏幕上添加批准,因此我找到并遵循了本指南:
How to work with Assignment and Approval Maps in Acumatica via Automation Steps?
这是我的代码: 我的DAC:
[PXEMailSource]
[PXPrimaryGraph(typeof(ProductMaint))]
[Serializable]
public class PSSAProduct : IBqlTable, IAssign
{
#region ProductID
[PXDBIdentity(IsKey = true)]
[PXUIField(DisplayName = "Product ID")]
public virtual int? ProductID { get; set; }
public abstract class productID : IBqlField { }
#endregion
#region ProductCD
[PXDBString(50, IsUnicode = true)]
[PXUIField(DisplayName = "Product ID")]
public virtual string ProductCD { get; set; }
public abstract class productCD : IBqlField { }
#endregion
#region ProductName
[PXDBString(50, IsUnicode = true, InputMask = "")]
[PXUIField(DisplayName = "Product Name")]
public virtual string ProductName { get; set; }
public abstract class productName : IBqlField { }
#endregion
#region Active
[PXDBBool()]
[PXDefault(true, PersistingCheck = PXPersistingCheck.Nothing)]
[PXUIField(DisplayName = "Active")]
public virtual bool? Active { get; set; }
public abstract class active : IBqlField { }
#endregion
#region OwnerID
public abstract class ownerID : IBqlField { }
[PXDBGuid()]
[PX.TM.PXOwnerSelector()]
[PXUIField(DisplayName = "Owner")]
public virtual Guid? OwnerID { get; set; }
#endregion
#region WorkgroupID
public abstract class workgroupID : IBqlField { }
[PXDBInt()]
[PXSelector(typeof(Search<EPCompanyTree.workGroupID>), SubstituteKey = typeof(EPCompanyTree.description))]
[PX.TM.PXCompanyTreeSelector]
[PXUIField(DisplayName = "Workgroup", Enabled = false)]
public virtual int? WorkgroupID { get; set; }
#endregion
#region Hold
[PXDBBool()]
[PXUIField(DisplayName = "Hold", Visibility = PXUIVisibility.Visible)]
[PXDefault(true)]
//[PXNoUpdate] <- Saw this in the PO code, but had to remove so user could save stat of the Hold checkbox
public virtual bool? Hold { get; set; }
public abstract class hold : IBqlField { }
#endregion
#region Approved
public abstract class approved : IBqlField { }
[PXDBBool]
[PXDefault(false, PersistingCheck = PXPersistingCheck.Nothing)]
[PXUIField(DisplayName = "Approved", Visibility = PXUIVisibility.Visible, Enabled = false)]
public virtual bool? Approved { get; set; }
#endregion
#region Rejected
public abstract class rejected : IBqlField { }
[PXBool]
[PXDefault(false, PersistingCheck = PXPersistingCheck.Nothing)]
public bool? Rejected { get; set; }
#endregion
#region Status
[PXDBString(1)]
[PXDefault(PSSAProduct.Statuses.Hold)]
[PXUIField(DisplayName = "Status", Visibility = PXUIVisibility.SelectorVisible, Enabled = false)]
[Statuses.List]
public virtual string Status { get; set; }
public abstract class status : IBqlField { }
#endregion
}
我的图表:
public class ProductMaint : PXGraph<ProductMaint, PSSAProduct>
{
public PXSelect<PSSAProduct> PSSAProductView;
public PXSelect<PSSASetupApproval> SetupApproval;
public EPApprovalAutomation<PSSAProduct, PSSAProduct.approved, PSSAProduct.rejected, PSSAProduct.hold, PSSASetupApproval> Approval;
}
我的设置程序:
[Serializable]
public class PSSASetup : IBqlTable
{
#region SARequestApproval
[EPRequireApproval]
[PXDefault(false, PersistingCheck = PXPersistingCheck.Null)]
[PXUIField(DisplayName = "SARequest Approval")]
public virtual bool? SARequestApproval { get; set; }
public abstract class sARequestApproval : IBqlField { }
#endregion
}
还有我的设置批准类:
[Serializable]
public class PSSASetupApproval : IBqlTable, IAssignedMap
{
#region ApprovalID
[PXDBIdentity(IsKey = true)]
[PXUIField(DisplayName = "Approval ID")]
public virtual int? ApprovalID { get; set; }
public abstract class approvalID : IBqlField { }
#endregion
#region AssignmentMapID
[PXDefault()]
[PXDBInt()]
[PXSelector(typeof(Search<EPAssignmentMap.assignmentMapID, Where<EPAssignmentMap.entityType, Equal<AssignmentMapType.AssignmentMapTypeProduct>>>),
DescriptionField = typeof(EPAssignmentMap.name))]
[PXUIField(DisplayName = "Assignment Map ID")]
public virtual int? AssignmentMapID { get; set; }
public abstract class assignmentMapID : IBqlField { }
#endregion
#region AssignmentNotificationID
[PXDBInt()]
[PXSelector(typeof(PX.SM.Notification.notificationID), SubstituteKey = typeof(PX.SM.Notification.name))]
[PXUIField(DisplayName = "Pending Approval Notification")]
public virtual int? AssignmentNotificationID { get; set; }
public abstract class assignmentNotificationID : IBqlField { }
#endregion
#region IsActive
[PXDBBool()]
[PXDefault(typeof(Search<PSSASetup.sARequestApproval>), PersistingCheck = PXPersistingCheck.Nothing)]
[PXUIField(DisplayName = "Is Active")]
public virtual bool? IsActive { get; set; }
public abstract class isActive : IBqlField { }
#endregion
}
public static class AssignmentMapType
{
public class AssignmentMapTypeProduct : Constant<string>
{
public AssignmentMapTypeProduct() : base(typeof(PSSAProduct).FullName) { }
}
}
我的问题是,如果我将Acumatica的DAC用作EPApprovalAutomation的SourceAssign,它没有错误。但是,如果我使用DAC,它将在框架的代码中引发“ Value不能为空”。
我仔细检查了两个DAC之间的区别,但我什么都没意识到。
我的Acumatica版本是17R2。
如果您知道,请告诉我我想念的是什么。
谢谢!
答案 0 :(得分:1)
通常,此错误“值不能为空”与在DB中使用NOT NULL字段定义的表有关,或者与PXDefault属性为DAC且试图持久保存到DB的DAC有关。
如果您在链接中使用了示例,并且使用审计字段创建了数据库表:
CreatedByID uniqueidentifier NOT NULL,
CreatedByScreenID char(8) NOT NULL,
CreatedDateTime datetime NOT NULL,
LastModifiedByID uniqueidentifier NOT NULL,
LastModifiedByScreenID char(8) NOT NULL,
LastModifiedDateTime datetime NOT NULL,
Tstamp timestamp NULL,
确保也将它们添加到DAC:
#region tstamp
public abstract class Tstamp : IBqlField { }
[PXDBTimestamp()]
public virtual byte[] tstamp { get; set; }
#endregion
#region CreatedByID
public abstract class createdByID : IBqlField { }
[PXDBCreatedByID()]
public virtual Guid? CreatedByID { get; set; }
#endregion
#region CreatedByScreenID
public abstract class createdByScreenID : IBqlField { }
[PXDBCreatedByScreenID()]
public virtual string CreatedByScreenID { get; set; }
#endregion
#region CreatedDateTime
public abstract class createdDateTime : IBqlField { }
[PXDBCreatedDateTime()]
public virtual DateTime? CreatedDateTime { get; set; }
#endregion
#region LastModifiedByID
public abstract class lastModifiedByID : IBqlField { }
[PXDBLastModifiedByID()]
public virtual Guid? LastModifiedByID { get; set; }
#endregion
#region LastModifiedByScreenID
public abstract class lastModifiedByScreenID : IBqlField { }
[PXDBLastModifiedByScreenID()]
public virtual string LastModifiedByScreenID { get; set; }
#endregion
#region LastModifiedDateTime
public abstract class lastModifiedDateTime : IBqlField { }
[PXDBLastModifiedDateTime()]
public virtual DateTime? LastModifiedDateTime { get; set; }
#endregion
还要在代码中签入PXDefault的以下两种可能的候选者:
在PSSAProduct
DAC的“状态”字段中,使用[PXDefault(PSSAProduct.Statuses.Hold)]
。检查您是否正确定义了PSSAProduct.Statuses。
在PSSASetupApproval
DAC的AssignmentMapID字段中,PXSelector [PXSelector(typeof(Search<EPAssignmentMap.assignmentMapID, Where<EPAssignmentMap.entityType, Equal<AssignmentMapType.AssignmentMapTypeProduct>>>), DescriptionField = typeof(EPAssignmentMap.name))]
找不到任何记录。您可以进行测试以确保其正常工作。
答案 1 :(得分:0)
我设法检查了两个班级之间的区别,然后找到了答案:我错过了NoteID字段
#region NoteID
public abstract class noteID : PX.Data.IBqlField
{
}
protected Guid? _NoteID;
[PXNote(new Type[0], ShowInReferenceSelector = true)]
public virtual Guid? NoteID
{
get
{
return this._NoteID;
}
set
{
this._NoteID = value;
}
}
#endregion