云星空赋能制造企业流程设计与落地2-2-2:工作流自动化任务(下) #常见任务、执行计划、与二开插件结合#原创
金蝶云社区-henryleezs
henryleezs
16人赞赏了该文章 80次浏览 未经作者许可,禁止转载编辑于2024年12月20日 12:33:00
summary-icon摘要由AI智能服务提供

本文介绍了工作流自动化任务中的二开插件案例,包括自动单据提交和自动单据下推。前者通过注册服务插件实现单据的自动提交,后者则在审核操作中注册插件实现单据的下推。此外,还介绍了通过执行计划定时引出列表数据并发送邮件的操作。

#2-2-3 工作流自动化任务(下) begin# 



1、常见任务-二开插件

案例①

自动单据提交:

入口单据非工作流时,即不能在工作流设计器中拖动【自动单据提交】动作,对下游目标单据进行提交操作。

这时可以进入BOSIDE,在单据的保存操作中以注册服务插件的方式实现单据的工作流的自动提交。

收料通知单自动下推来料检验单为例,来料检验单有工作流,只需要自动提交,审核交给IQC

步骤一:建立收料通知单与来料检验单的单据转换规则,并启用。

步骤二:使用有权限的管理员账号访问单据类型列表,找到收料通知单,反审核。在参数设置上勾选【审核自动生成检验单】(如图1-1);

image.png

                                                  图1-1

步骤三:使用有权限的管理员账号进入BOSIDE,打开质量管理模块->检验单,选择编辑->批量编辑字段属性菜单,进入批量编辑字段属性界面;在表单属性->操作列表->编辑保存操作(如图1-2)

image.png

                                                                                             图1-2

步骤四:打开注册python插件界面,注册插件(如图1-3)

image.png

                                                                                           图1-3

python自动提交示例代码:

import clr
clr.AddReference('System')
clr.AddReference('System.Data')
clr.AddReference('Kingdee.BOS')
clr.AddReference('Kingdee.BOS.Core')
clr.AddReference('Kingdee.BOS.WebApi.FormService')
clr.AddReference('Kingdee.BOS.ServiceFacade.KDServiceFx')
clr.AddReference('Newtonsoft.Json')
from Kingdee.BOS import *
from Kingdee.BOS.Core.DynamicForm import *
from Kingdee.BOS.Core.DynamicService import *
from System import *
from System.Data import *
from System.Collections.Generic import *
from Kingdee.BOS.WebApi.FormService import *
from Kingdee.BOS.ServiceFacade.KDServiceFx import *
from Newtonsoft.Json.Linq import *

def EndOperationTransaction(e):
    for billObj in e.DataEntitys:
        billNo = str(billObj["BillNo"])
        apiResult = SubmitBill(billNo)

def SubmitBill(billNo):
    jsonData = """{"Numbers":["BILLNOS"]}"""
    json = jsonData.Replace("BILLNOS",billNo)
    apiResult = WebApiServiceCall.Submit(this.Context, "QM_InspectBill", json)
    return apiResult



❀❀❀小贴士1:如果是注册C#插件,点【注册】按钮,注册写好插件之后需要放到服务器上并做IIS重启。这也是python插件的优势,注册好插件之后可以直接使用。❀❀❀

❀❀❀小贴士2:如果单据类型参数设置中本身没有【审核自动生成检验单】类似的选项,那么可以通过在上游单据的审核操作中调用【自动下推】的服务进行,如图1-4❀❀❀

❀❀❀小贴士3:以上插件的形式针对的是全局用户,如果只是对当前登录的用户生效,可以在单据列表->选项,勾选【保存后自动提交】,也可以实现单据保存后自动提交启动工作流❀❀❀


image.png

                                                                                           图1-4


案例②

自动单据下推

例如上游单据没有工作流,即无法在流程设计中心节点配置【单据转换】操作,这时可通过在上游单据的审核操作中注册插件,实现插件下推下游目标单据的自动化操作。

同样以收料通知单下推来料检验单为例:

步骤一:建立收料通知单与来料检验单的单据转换规则,并启用。

步骤二:使用有权限的管理员账号进入BOSIDE,打开质量供应链模块->采购管理->收料通知单,选择编辑->批量编辑字段属性菜单,进入批量编辑字段属性界面;在表单属性->操作列表->编辑审核操作(如图1-5)。

image.png

                                                                                      如图1-5

                                                     

步骤三:打开注册插件界面,注册插件,勾选启用(如图1-6)。

image.png

                                                                                    图1-6


C#自动提交示例代码参考:插件中实现自动下推并保存


步骤四:重启IIS.



2、执行计划-二开插件


案例①

定时引出列表数据:

通过新建执行计划,引用二开服务插件,定时引出列表数据,并通过邮件的方式,将引出文件发送到指定邮箱。

采购订单列表,定时引出列表数据,并发送邮件到指定的邮箱为例

步骤一:登录星空系统客户端,设置好邮件服务器地址(如图2-1),设置好登录用户的个人邮箱地址(如图2-2);

image.png

                                                                图2-1


image.png

                                                             图2-2

步骤二:打开采购订单列表设置好引出专用过滤方案,如图2-3:

image.png

                                                              图2-3


步骤三:编写执行计划服务插件,C#实例代码如下:

namespace Jac.XkDemo.BOS.App.PlugIn
{
    /// <summary>
    /// 【执行计划】引出列表数据并发送邮件
    /// </summary>
    public class ExportListDataAndSendEmailScheduleService : IScheduleService
    {
        /// <summary>
        /// 执行计划入口函数
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="schedule"></param>
        public void Run(Context ctx, Schedule schedule)
        {
            try
            {
                // 设置组织(SELECT * FROM T_ORG_ORGANIZATIONS)
                ctx.CurrentOrganizationInfo = new OrganizationInfo
                {
                    ID = 1,
                    Name = "蓝海机械总公司"
                };
                // 设置用户(SELECT * FROM T_SEC_USER)
                ctx.UserId = 100008;
                ctx.UserName = "demo";
                // 设置单据
                var formId = "PUR_PurchaseOrder";// 业务对象标识
                // 设置过滤方案(SELECT * FROM T_BAS_FILTERSCHEME WHERE FFORMID='PUR_PurchaseOrder' AND FUSERID=100008)
                var schemeId = "62df6021e6f83e";// 过滤方案内码
                // 创建列表视图
                var view = new ListViewBuilder().CreateListPrintView(ctx, formId, schemeId);
                // 生成引出数据
                var listExportService = new ListExportService(view);
                var filePath = listExportService.ExportData();
                // 发送邮件
                listExportService.SendMail(filePath);
            }
            catch (Exception ex)
            {
                Logger.Error("JAC", "引出列表数据时发生异常:" + ex.Message, ex);
                throw;
            }
        }
    }
}

项目引入组件参考如下:

image.png


步骤四:拷贝插件组件到应用站点的WebSite\Bin目录下,重启IIS。

步骤五:打开执行计划列表,创建新的执行计划,引用服务插件,设置任务执行间隔时间、开始时间、结束时间(如图2-4):

image.png

                                                                  图2-4




案例②

批量提交单据:

通过新建执行计划,引用二开服务插件,定时批量提交数据。

采购订单列表,定时将一周内的未提交的采购订单进行提交,每10分钟执行一次为例

步骤一:编写执行计划服务插件,项目引入组件和C#实例代码如下:

using Kingdee.BOS;
using Kingdee.BOS.App.Core;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Contracts;
using Kingdee.BOS.Core;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Log;
using Newtonsoft.Json;
using System;
using System.Linq;

namespace Jac.XkDemo.BOS.App.PlugIn
{
    /// <summary>
    /// 【执行计划】批量提交单据
    /// </summary>
    public class BatchSubmitBillScheduleService : IScheduleService
    {
        /// <summary>
        /// 执行计划入口函数
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="schedule"></param>
        public void Run(Context ctx, Schedule schedule)
        {
            try
            {
                Logger.Info("JAC-SubmitBill", "批量提交单据开始。");
                Logger.Info("JAC-SubmitBill", "获取操作用户(提交人)信息。");
                var userName = "demo";
                var sql = string.Format("SELECT FUSERID FROM T_SEC_USER WHERE FNAME='{0}'", userName);
                var userId = DBUtils.ExecuteScalar(ctx, sql, 0);
                if (userId == 0)
                {
                    Logger.Error("JAC-SubmitBill", "用户不存在:" + userName, null);
                    return;
                }
                Logger.Info("JAC-SubmitBill", "上下文切换操作用户(提交人)。");
                ctx.UserId = userId;
                ctx.UserName = userName;
                Logger.Info("JAC-SubmitBill", "批量抓取一周内的待提交的采购订单。");
                sql = "/*dialect*/SELECT FID,FBillNo FROM dbo.T_PUR_POORDER WHERE FCREATEDATE>=CONVERT(VARCHAR(10),GETDATE()-7,120) AND FDOCUMENTSTATUS IN ('A','D')";
                var objs = DBUtils.ExecuteDynamicObject(ctx, sql);
                if (objs == null || objs.Count == 0)
                {
                    Logger.Info("JAC-SubmitBill", "批量抓取一周内的待提交的采购订单的数量为0,任务终止。");
                    return;
                }
                Logger.Info("JAC-SubmitBill", "待提交的采购订单:" + string.Join(",", objs.Select(o => string.Format("{0}({1})", o[1], o[0]))));
                var businessInfo = ((FormMetadata)new MetaDataService().Load(ctx, "PUR_PurchaseOrder")).BusinessInfo;
                var pkids = objs.Select(o => o[0]).ToArray();
                var result = new SubmitService().Submit(ctx, businessInfo, pkids, "Submit", null);
                if (result.IsSuccess)
                {
                    var log = "提交成功的单据:" + string.Join(",", result.SuccessDataEnity.Select(o => string.Format("{0}({1})", o["BillNo"], o[0])));
                    if (result.OperateResult != null && result.OperateResult.Count > 0)
                    {
                        log += "\r\n操作结果:" + string.Join(",", result.OperateResult.Select(o => o.Message));
                    }
                    Logger.Info("JAC-SubmitBill", "采购订单批量提交成功:\r\n" + log);
                }
                else
                {
                    var successPkIds = result.SuccessDataEnity == null ? new long[] { } : result.SuccessDataEnity.Select(o => Convert.ToInt64(o[0])).ToArray();
                    var successBills = result.SuccessDataEnity == null ? new string[] { } : result.SuccessDataEnity.Select(o => string.Format("{0}({1})", o["BillNo"], o[0])).ToArray();
                    var failureBills = objs.Where(o => !successPkIds.Contains(Convert.ToInt64(o[0]))).Select(o => string.Format("{0}({1})", o[1], o[0])).ToArray();
                    var log = "提交成功的单据:" + string.Join(",", successBills);
                    log += "\r\n提交失败的单据:" + string.Join(",", failureBills);
                    log += "\r\n失败原因:" + JsonConvert.SerializeObject(result.OperateResult.GetFailResult()) + "\r\n" + JsonConvert.SerializeObject(result.ValidationErrors);
                    if (result.OperateResult != null && result.OperateResult.Count > 0)
                    {
                        log += "\r\n操作结果:" + string.Join(",", result.OperateResult.Select(o => o.Message));
                    }
                    Logger.Info("JAC-SubmitBill", "采购订单批量提交失败:\r\n" + log);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("JAC-SubmitBill", "批量提交单据任务执行失败。", ex);
            }
            finally
            {
                Logger.Info("JAC-SubmitBill", "批量提交单据结束。");
            }
        }
    }
}

步骤二:拷贝插件组件到应用站点的WebSite\Bin目录下,重启IIS。

步骤三:登录业务站点,打开执行计划列表,新增执行计划(如下图2-5):

image.png

                                                             图2-5

步骤四:测试验证,查看执行日志(如图2-6):

image.png

                                                       图2-6



❀❀❀小贴士:二开插件代码注意普通提交和工作流提交的区别,示例代码参考:二开案例.表单插件.普通提交和工作流提交❀❀❀



#2-2-3 工作流自动化任务(下) end# 


相关文章:

工作流自动化任务(上)https://vip.kingdee.com/link/s/luKsl

工作流自动化任务(中)https://vip.kingdee.com/link/s/luqDc


返回文章大纲➹

期待本系列文章能帮助您,将最佳的实践转化为卓越的流程设计,驱动业务实现高效运营。


图标赞 16
16人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
1人打赏
还没有人打赏,快来当第一个打赏的人吧!