5

我需要制作使用分配和批准地图。EP205000页面构建的地图使用模板是什么?我对 Acumatica 的 coderepository.xml 文件进行了研究,发现那里有 EPApprovalAutomation 类。我想使用它,但它需要在实现 IAssignedMap 接口的类的参数中使用。这又带来了一个问题,因为IAAssignedMap接口是内部的,这又给了一个谜,IAAssignedMap接口怎么用?什么是替代品?

4

3 回答 3

9

这个答案可能来得有点晚,但我相信它对其他人有用,所以我会分享它。

数据库的新表和字段

XX设置批准

在您的模块中添加新的设置表以进行审批设置(进一步的 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

XX注册

修改需要实施审批机制的实体表(进一步XX注册)。您的实体应包含三个必填字段,您可以在下面看到。

OwnerID uniqueidentifier NULL,
WorkGroupID int NULL,
Approved bit NOT NULL

XX设置

修改模块中的主要设置表(进一步的 XXSetup)。您的设置应包括一个必填字段,您可以在下面看到。根据您的实体名称命名此标志,因为它将指示是否启用了批准机制(XXRequestApproval 进一步)。

XXRequestApproval bit NULL

数据库的新更新脚本

根据您的条件更新 XXRegister 表并为所有现有记录设置 Approved 标志等于 1。使用您自己的表达式而不是三个点。

EXEC sp_executesql N'UPDATE XXRegister SET Approved = 1 WHERE ...'

代码的新表和字段

分配地图类型XX

将您的实体添加到 AssignmentMapType 类(进一步是 AssignmentMapTypeXX)。此类型应仅用于选择所需类型的分配映射。

public static class AssignmentMapType
{
    ...
    public class AssignmentMapTypeXX : Constant<string>
    {
        public AssignmentMapTypeXX() : base(typeof(XXRegister).FullName) { }
    }
    ...
}

XX设置

根据数据库中的新字段,将新属性和类添加到 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

XX设置批准

根据数据库中的 XXSetupApproval 表在代码中添加新的 DAC。XXSetupApproval DAC 应该实现 IAssignedMap 接口(AssignmentMapID、AssignmentNotificationID、IsActive 字段)。如果需要,使用任何其他属性。

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

XX注册

将 PXEmailSource 属性添加到 XXRegister DAC,“Assignment and Approvals Maps”树选择器需要它。

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

XX注册.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>

自动化定义的新自动化步骤

这是审批实施过程中最困难的部分,因为应该在实体的当前行为范围内创建一些新的自动化步骤。例如,实体具有相应的下一个状态和自动化步骤:“保持”->“打开”。我们应该在这两个步骤之间实施审批机制。然后应该创建三个新的自动化步骤:“Hold-Open”(如果我们不需要批准文档)、“Hold-Pending Approval”(如果我们需要批准文档)、“Pending Approval”(从实体应该被批准或拒绝)。新的生命周期将如下所示:“Hold” -> “Hold-Open” OR “Hold-Pending Approval” -> “Open” OR “Pending Approval”。所以“保持打开”和“

<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 所做的工作。

于 2016-05-19T18:13:23.547 回答
3

将此添加为答案,因为它太大而无法发表评论。我在下面的回答建立在加布里埃尔的回答之上......

我能够获得 Gabriel 发布的使用以下添加的步骤:(请参阅图 SOOrderEntry 示例)

  1. 为您的屏幕/实体创建分配和批准地图记录
  2. 需要在您的 XXSetupApproval 表中获取一条记录,该表链接到上面创建的 Approval map ID
  3. 因为 IAssignedMap 是内部的,所以您需要创建自己的 XXApprovalAutomation 类,该类继承 EPApprovalAutomation 并覆盖 GetAssignedMaps。在您的图表上使用它来代替 EPApprovalAutomation。确保在 XXSetupApproval SetupApproval 视图之后添加此内容,否则您将在页面上收到类似于“必须在图表中声明类型为 'XXSetupApproval' 的视图以使用 EPApprovalAutomation”的错误
  4. 将 PXActions 添加到“Actions”和“Hold”图表中。如果您没有该操作,则在尝试批准时可能会收到以下错误:“屏幕/图形 %GraphName% 的自动化存在但未正确配置。找不到操作 - '操作'”
  5. 为“操作”下拉菜单的“批准”或“拒绝”菜单项添加另一个自动化步骤。我按照标准销售订单“SO Pending Approval”自动化步骤作为创建自定义图表审批流程自动化步骤的基础。
  6. 如果您想填写 EPApproval 字段,例如审批者在审批表上看到的描述,您可以在包含审批设置的图表中附加缓存,如下所示:

    [PXDBString(60, IsUnicode = true)] [PXDefault(typeof(MyDac.description), PersistingCheck = PXPersistingCheck.Nothing)] 受保护的虚拟无效 EPApproval_Descr_CacheAttached(PXCache 发件人) { }

  7. 如果您希望批准屏幕上的“类型”值是用户友好的,而不是对象命名空间 (PX.Objects.MyStuff.MyDac),则在主 DAC 上使用 PXCacheName 属性,如下所示:

    [PXEMailSource] [Serializable] [PXCacheName("My DAC")] [PXPrimaryGraph(typeof(MyGraph))] 公共类 MyDac : PX.Data.IBqlTable, PX.Data.EP.IAssign {...}

我的自定义图表上的自定义审批流程功能齐全。很大的帮助/感谢 Gabriel 和 Evgeny 的文章。我使用的 Acumatica 版本是 5.30.2233。一个限制是无法打包自动化步骤,因此从定制包分发它并不灵活。

于 2016-08-05T18:13:29.803 回答
0

如果您检查 RQRequestEntry,“Hold”中有一个附加代码

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;
                    }
于 2019-04-04T05:04:34.550 回答