我需要使用分配和批准地图。什么是在EP205000页面构建的地图使用模板?我在Acumatica的文件coderepository.xml中进行了研究,并在那里找到了EPApprovalAutomation类。我想使用它,但它需要使用类的参数来实现IAssignedMap接口。它给出了另一个问题,因为IAssignedMap接口是内部的,这给另一个谜题,如何使用IAssignedMap接口?有什么替代方案?
答案 0 :(得分:8)
这个答案可能会有点晚,但我相信它对其他人有用,所以我会分享它。
数据库的新表格和字段
XXSetupApproval
为模块中的批准设置添加新的设置表(进一步XXSetupApproval)。您可以在下面看到所有必填字段,但如果要拆分不同类型实体的批准,则可能需要添加任何其他参数。
CREATE TABLE XXSetupApproval
(
CompanyID int NOT NULL,
ApprovalID int NOT NULL identity,
AssignmentMapID int NOT NULL,
AssignmentNotificationID int NULL,
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,
IsActive bit NOT NULL
)
GO
ALTER TABLE XXSetupApproval
ADD CONSTRAINT XXSetupApproval_PK PRIMARY KEY CLUSTERED (CompanyID, ApprovalID)
GO
XXRegister
修改您需要实施审批机制的实体表(XX进一步注册)。您的实体应包括三个必填字段,您可以在下面看到。 OwnerID uniqueidentifier为NULL, WorkGroupID int NULL, 批准位NOT NULL XXSetup 修改模块中主要设置的表格(进一步XXSetup)。您的设置应包括一个必填字段,您可以在下面看到。根据您的实体名称命名此标志,因为它将指示是否启用批准机制(XXRequestApproval进一步)。 XXRequestApproval位NULL
数据库的新更新脚本</ strong>
根据您的条件更新XXRegister表并为所有现有记录设置Approved标志等于1。使用您自己的表达式而不是三个点。
EXEC sp_executesql N'UPDATE XXRegister SET Approved = 1 WHERE ...'
代码的新表格和字段
AssignmentMapTypeXX
将您的实体添加到AssignmentMapType类(进一步AssignmentMapTypeXX)。此类型应仅用于选择所需类型的赋值映射。
public static class AssignmentMapType
{
...
public class AssignmentMapTypeXX : Constant<string>
{
public AssignmentMapTypeXX() : base(typeof(XXRegister).FullName) { }
}
...
}
XXSetup
根据数据库中的新字段向XXSetup DAC添加新属性和类。如果需要,请使用任何其他属性。
#region XXRequestApproval
public abstract class xXRequestApproval : PX.Data.IBqlField { }
[EPRequireApproval]
[PXDefault(false, PersistingCheck = PXPersistingCheck.Null)]
[PXUIField(DisplayName = "Require Approval")]
public virtual bool? XXRequestApproval { get; set; }
#endregion
XXSetupApproval
Add new DAC to the code according with XXSetupApproval table in the database. XXSetupApproval DAC should realize IAssignedMap interface (AssignmentMapID, AssignmentNotificationID, IsActive fields). Use any other attributes if needed.
[Serializable]
public partial class XXSetupApproval : IBqlTable, IAssignedMap
{
#region ApprovalID
public abstract class approvalID : IBqlField { }
[PXDBIdentity(IsKey = true)]
public virtual int? ApprovalID { get; set; }
#endregion
#region AssignmentMapID
public abstract class assignmentMapID : IBqlField { }
[PXDefault]
[PXDBInt]
[PXSelector(typeof(Search<EPAssignmentMap.assignmentMapID, Where<EPAssignmentMap.entityType, Equal<AssignmentMapType.AssignmentMapTypeXX>>>),
DescriptionField = typeof(EPAssignmentMap.name))]
[PXUIField(DisplayName = "Approval Map")]
public virtual int? AssignmentMapID { get; set; }
#endregion
#region AssignmentNotificationID
public abstract class assignmentNotificationID : IBqlField { }
[PXDBInt]
[PXSelector(typeof(PX.SM.Notification.notificationID), SubstituteKey = typeof(PX.SM.Notification.name))]
[PXUIField(DisplayName = "Pending Approval Notification")]
public virtual int? AssignmentNotificationID { get; set; }
#endregion
#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
#region IsActive
public abstract class isActive : IBqlField { }
[PXDBBool()]
[PXDefault(typeof(Search<XXSetup.xXRequestApproval>), PersistingCheck = PXPersistingCheck.Nothing)]
public virtual bool? IsActive { get; set; }
#endregion
}
XXRegister
将PXEmailSource属性添加到XXRegister DAC,“分配和批准地图”树选择器需要它。
[PXEMailSource]
public partial class XXRegister : IBqlTable, EP.IAssign ...
根据数据库中的新字段向XXRegister DAC添加新属性和类。 XXRegister DAC应该实现IAssign接口(OwnerID,WorkgroupID字段)。如果需要,使用任何其他属性。使用您自己的表达式而不是三个点。
#region OwnerID
public abstract class ownerID : IBqlField { }
[PXDBGuid()]
[PXDefault(typeof(...), PersistingCheck = PXPersistingCheck.Nothing)]
[PX.TM.PXOwnerSelector()]
[PXUIField(DisplayName = "Owner")]
public virtual Guid? OwnerID { get; set; }
#endregion
#region WorkgroupID
public abstract class workgroupID : IBqlField { }
[PXDBInt]
[PXDefault(typeof(...), PersistingCheck = PXPersistingCheck.Nothing)]
[PX.TM.PXCompanyTreeSelector]
[PXUIField(DisplayName = "Workgroup", Enabled = false)]
public virtual int? WorkgroupID { get; set; }
#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
<强>以下状态强>
为实体添加新的审批状态,并在列表中使用它们。如果“P”和“R”已在使用中,请使用其他字母。
public const string PendingApproval = "P";
public const string Rejected = "R";
public class ListAttribute : PXStringListAttribute
{
public ListAttribute() : base(
new string[] { ..., PendingApproval, Rejected, ... },
new string[] { ..., EP.Messages.PendingApproval, EP.Messages.Rejected, ... }) { ; }
}
实体图表的新代码
在图形中实施EPApprovalAutomation帮助程序,该图形正在与您的实体一起操作。使用您自己的参数而不是三个点。
public EPApprovalAutomation<...> Approval;
添加XXSetupApproval DAC的视图。使用您自己的表达式而不是三个点。
public PXSelect<XXSetupApproval, Where<...>> SetupApproval;
主要设置图表的新代码
为XXSetupApproval DAC添加视图。
public PXSelect<APSetupApproval> SetupApproval;
根据XXRequestApproval字段的新值更新每个XXSetupApproval行。
protected virtual void XXSetup_XXRequestApproval_FieldVerifying(PXCache sender, PXFieldVerifyingEventArgs e)
{
PXCache cache = this.Caches[typeof(XXSetupApproval)];
foreach (XXSetupApproval setup in PXSelect<XXSetupApproval>.Select(this))
{
setup.IsActive = (bool?)e.NewValue;
cache.Update(setup);
}
}
网页的新表格和字段
XXSetup.aspx
将具有批准设置的新标签添加到设置的主网页(XXSetup.aspx进一步)。如果需要,请使用任何其他参数。
<px:PXTabItem Text="Approval">
<Template>
<px:PXPanel ID="panelApproval" runat="server" >
<px:PXLayoutRule runat="server" LabelsWidth="S" ControlSize="XM" />
<px:PXCheckBox ID="chkXXRequestApproval" runat="server" AlignLeft="True" Checked="True" DataField="XXRequestApproval" CommitChanges="True" />
</px:PXPanel>
<px:PXGrid ID="gridApproval" runat="server" DataSourceID="ds" SkinID="Details" Width="100%" >
<AutoSize Enabled="True" />
<Levels>
<px:PXGridLevel DataMember="SetupApproval" >
<RowTemplate>
<px:PXLayoutRule runat="server" StartColumn="True" LabelsWidth="M" ControlSize="XM" />
<px:PXSelector ID="edAssignmentMapID" runat="server" DataField="AssignmentMapID" AllowEdit="True" CommitChanges="True" />
<px:PXSelector ID="edAssignmentNotificationID" runat="server" DataField="AssignmentNotificationID" AllowEdit="True" />
</RowTemplate>
<Columns>
<px:PXGridColumn DataField="AssignmentMapID" Width="250px" RenderEditorText="True" TextField="AssignmentMapID_EPAssignmentMap_Name" />
<px:PXGridColumn DataField="AssignmentNotificationID" Width="250px" RenderEditorText="True" />
</Columns>
</px:PXGridLevel>
</Levels>
</px:PXGrid>
</Template>
</px:PXTabItem>
XXRegister.aspx
将新字段“已批准”添加到实体的主网页(进一步XXRegister.aspx)。如果需要,请使用任何其他参数。
<px:PXCheckBox ID="chkApproved" runat="server" DataField="Approved" CommitChanges="True" Enabled="False" />
将包含批准信息的新标签添加到XXRegister.aspx网页。如果需要,请使用任何其他参数。
<px:PXTabItem Text="Approval Details" BindingContext="form" RepaintOnDemand="false">
<Template>
<px:PXGrid ID="gridApproval" runat="server" DataSourceID="ds" Width="100%" SkinID="DetailsInTab" NoteIndicator="True" Style="left: 0px; top: 0px;">
<AutoSize Enabled="True" />
<Mode AllowAddNew="False" AllowDelete="False" AllowUpdate="False" />
<Levels>
<px:PXGridLevel DataMember="Approval">
<Columns>
<px:PXGridColumn DataField="ApproverEmployee__AcctCD" Width="160px" />
<px:PXGridColumn DataField="ApproverEmployee__AcctName" Width="160px" />
<px:PXGridColumn DataField="ApprovedByEmployee__AcctCD" Width="100px" />
<px:PXGridColumn DataField="ApprovedByEmployee__AcctName" Width="160px" />
<px:PXGridColumn DataField="ApproveDate" Width="90px" />
<px:PXGridColumn DataField="Status" AllowNull="False" AllowUpdate="False" RenderEditorText="True"/>
<px:PXGridColumn DataField="WorkgroupID" Width="150px" />
</Columns>
</px:PXGridLevel>
</Levels>
</px:PXGrid>
</Template>
</px:PXTabItem>
自动化定义的新自动化步骤
这是批准实施过程中最困难的部分,因为应该在实体的当前行为范围内创建一些新的自动化步骤。例如,该实体具有相应的下一个状态和自动化步骤:“保持” - &gt; “打开”。我们应该在这两个步骤之间实施审批机制。然后应创建三个新的自动化步骤:“保持打开”(如果我们不需要批准文档),“待批准”(如果我们需要批准文档),“待批准”(从步骤开始)应批准或拒绝该实体)。新的生命周期将如下所示:“保持” - &gt; “保持开放”或“等待批准” - &gt; “开放”或“待批准”。因此,“保持 - 打开”和“暂停待批准”自动化步骤只是确定“保持”后应使用哪个自动化步骤的开关。
<Step StepID="Hold-Open" Description="Hold-Open" GraphName="…" ViewName="Document" TimeStampName="tstamp">
<Filter FieldName="Status" Condition="Equals" Value="H" Operator="And" />
<Filter FieldName="Hold" Condition="Equals" Value="False" Value2="False" Operator="And" />
<Filter FieldName="Approved" Condition="Equals" Value="True" Value2="False" Operator="And" />
<Action ActionName="*" IsDefault="1">
<Fill FieldName="Status" Value="N" />
</Action>
</Step>
<Step StepID="Hold-Pending Approval" Description="Hold-Pending Approval" GraphName="…" ViewName="Document" TimeStampName="tstamp">
<Filter OpenBrackets="1" FieldName="Status" Condition="Equals" Value="H" Operator="Or" />
<Filter FieldName="Status" Condition="Equals" Value="N" CloseBrackets="1" Operator="And" />
<Filter FieldName="Hold" Condition="Equals" Value="False" Value2="False" Operator="And" />
<Filter FieldName="Approved" Condition="Equals" Value="False" Value2="False" Operator="And" />
<Action ActionName="*" IsDefault="1">
<Fill FieldName="Status" Value="P" />
</Action>
</Step>
感谢Acumatica开发团队的Evgeny Kralko的工作。
答案 1 :(得分:2)
添加此作为答案,因为它太大而无法发表评论。我的回答建立在加布里埃尔的回答之上......
我能够获得Gabriel发布的以下附加内容的步骤:(例如,参考图表SOOrderEntry)
如果要填写批准人在批准表单上看到的EPApproval字段(如说明),您可以在图表中附加包含批准设置的缓存,如下所示:
[PXDBString(60,IsUnicode = true)] [PXDefault(typeof(MyDac.description),PersistingCheck = PXPersistingCheck.Nothing)] protected virtual void EPApproval_Descr_CacheAttached(PXCache sender) { }
如果你想要&#34;输入&#34;审批屏幕上的值是用户友好的而不是对象命名空间(PX.Objects.MyStuff.MyDac)然后在主DAC上使用PXCacheName属性,如下所示:
[PXEMailSource] [序列化] [PXCacheName(&#34;我的DAC&#34;)] [PXPrimaryGraph(typeof运算(MyGraph))] public class MyDac:PX.Data.IBqlTable,PX.Data.EP.IAssign {...}
我的自定义图表上的自定义审批流程正在全面展开。非常感谢Gabriel和Evgeny的文章。我使用的Acumatica版本是5.30.2233。一个限制是没有办法打包自动化步骤,因此从自定义包中分发它是不灵活的。
答案 2 :(得分:0)
如果您检查RQRequestEntry,则在“保留”中还有一个附加代码
if (order.Hold != true && order.Approved != true)
{
order.CheckBudget = false;
if (order.BudgetValidation == true)
foreach (RQBudget budget in this.Budget.Select())
{
if (budget.RequestAmt > budget.BudgetAmt)
{
order.CheckBudget = true; break;
}
}
if(order.CheckBudget == true)
{
RQRequestClass cls = this.reqclass.SelectWindowed(0,1,order.ReqClassID);
if (cls != null && cls.BudgetValidation == RQRequestClassBudget.Error)
throw new PXRowPersistedException(typeof(RQRequest).Name, order, Messages.CheckBudgetWarning);
}
if (Setup.Current.RequestAssignmentMapID != null)
{
var processor = new EPAssignmentProcessor<RQRequest>();
processor.Assign(order, Setup.Current.RequestAssignmentMapID);
order.WorkgroupID = order.ApprovalWorkgroupID;
order.OwnerID = order.ApprovalOwnerID;
}
}
yield return (RQRequest)Document.Search<RQRequest.orderNbr>(order.OrderNbr);
我一直在试图找出第三级批准步骤,但说明中不包括这一部分。我什至尝试调试acumatica的代码,而且那里似乎没有错误。为了其他开发者的利益,这就是您所需要的
您需要将这部分代码分配给下一个批准者:
if (Setup.Current.RequestAssignmentMapID != null)
{
var processor = new EPAssignmentProcessor<RQRequest>();
processor.Assign(order, Setup.Current.RequestAssignmentMapID);
order.WorkgroupID = order.ApprovalWorkgroupID;
order.OwnerID = order.ApprovalOwnerID;
}