【问题标题】:How to work with Assignment and Approval Maps in Acumatica via Automation Steps?如何通过自动化步骤在 Acumatica 中使用分配和批准图?
【发布时间】:2015-11-30 17:56:48
【问题描述】:

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

【问题讨论】:

    标签: acumatica acumatica-kb


    【解决方案1】:

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

    数据库的新表和字段

    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
    

    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 ...'
    

    代码的新表和字段

    AssignmentMapTypeXX

    将您的实体添加到 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
    

    XXSetupApproval

    根据数据库中的 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>
    

    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>
    

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

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

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

    【讨论】:

    • 您是如何在 AssignmentMapType 中对静态类进行更改的?
    【解决方案2】:

    将其添加为答案,因为它太大而无法评论。我在下面的回答建立在 Gabriel 的回答之上...

    我能够通过以下添加获得 Gabriel 发布的步骤:(有关示例,请参阅图形 SOOrderEntry)

    1. 为您的 屏幕/实体
    2. 需要在 XXSetupApproval 表中获取一条记录,该表链接 到上面创建的 Approval map ID
    3. 因为IAssignedMap是内部的,所以需要自己创建 继承 EPApprovalAutomation 的 XXApprovalAutomation 类 并覆盖 GetAssignedMaps。在您的图表上使用它来代替 EPApprovalAutomation。确保在 XXSetupApproval SetupApproval 视图之后添加此内容,否则您将在页面上收到类似于 “必须在图表中声明类型为 'XXSetupApproval' 的视图才能使用 EPApprovalAutomation” 的错误。
    4. 将 PXActions 添加到您的图表中,用于“Actions”和“Hold”。如果您没有该操作,则在尝试批准时可能会收到以下错误:“自动化 对于屏幕/图形 %GraphName% 存在但未正确配置。 找不到操作 - '操作'"
    5. 为“批准”或“拒绝”菜单项添加另一个自动化步骤 操作下拉菜单。我遵循标准销售订单“SO Pending 批准”自动化步骤作为创建我的自定义图表的基础 审批流程自动化步骤。
    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] [可序列化] [PXCacheName("我的 DAC")] [PXPrimaryGraph(typeof(MyGraph))] 公共类 MyDac : PX.Data.IBqlTable, PX.Data.EP.IAssign {...}

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

    【讨论】:

    • 你是如何添加第一名的?通过 Visual Studio 源代码或 DAC 扩展?
    • 只需将 Acumatica 屏幕用于分配图和批准图。您需要为屏幕添加一个条目。在 18R2 中
    • 是否有关于如何使用自定义代码插件的说明,而我可以将 XML 文件导入 Acumatica 定义,谢谢。
    • 我不知道。我创建了一个类来导入 xml 文件并要求用户仍然激活。我认为在 19R2 中有一种打包方式,但尚未对其进行详细研究。看看您是否可以将其作为问题发布,我可以稍后尝试回答,或者其他人是否已经准备好可以回答的示例
    【解决方案3】:

    如果您检查 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;
                        }
    

    【讨论】:

      猜你喜欢
      • 2017-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-05
      • 2018-06-26
      • 1970-01-01
      相关资源
      最近更新 更多