個人微型工做流引擎-功能解析及API設計

1、前言

     上一篇我給你們介紹了個人工做流的模型和基本的設計,這篇我想詳細說明下我這款工做流的功能及使用示例。這款工做流主要是面向開發者設計的,爲了先讓你們有個全局的認識,局部功能的設計實現就不細說了,後續有時間我會繼續寫文章向你們介紹。web

2、功能詳解及使用示例代碼

     一、配置流程引擎,通常在程序啓動過程當中調用(Global.asax.cs中)數據庫

//初始化流程引擎
BpmConfiguration
    .Instance()
    .Config(@"C:\Configration\BpmConfig.xml")
    .Start();

若是不指定配置文件,則默認從app.config或web.config中讀取流程配置app

//初始化流程引擎
BpmConfiguration
    .Instance()
    .Start();

固然還支持同時啓動多個流程引擎,以提供SAAS程序的支持。測試

//A租戶引擎配置
BpmConfiguration
    .Instance("TenantA")
    .Config(@"C:\BpmConfigA.xml") 
    .Start();

//B租戶引擎配置
BpmConfiguration
    .Instance("TenantB")
    .Config(@"C:\BpmConfigB.xml")
    .Start();

XML中的配置包括:數據庫鏈接、日誌配置文件、任務計劃啓動延時、任務計劃執行週期、用戶關係結構的映射、流程中變量類型的拓展等。 

    二、取得工做流上下文,即工做流的入口,全部的功能都集中在這個入口上。 spa

var bpm = new BpmContext()
    .UseTransaction(true)
    .SetActor("蕭秦");

當前對於不一樣的引擎實例,其上下文是不一樣的設計

var bpm = new BpmContext("TenantA");
var bpm = new BpmContext("TenantB");

不傳構造參數時,返回的是默認實例。
 
    三、事務支持,是否開啓事務、提交、回滾。 日誌

bpm.UseTransaction(true);
bpm.Commit();
bpm.Rollback();


    四、流程定義 code

//新增流程定義
bpm.NewProcessDefinition("請假流程")
    .SetXmlFile(@"C:\Definition\demo1.xml")
    .SetCategory("分類1")
    .SetEffectDate(DateTime.Now)
    .SetExpireDate(DateTime.Now.AddDays(180))
    .SetMemo("memo1")
    .Create()   //建立流程定義
    .Parse()    //解析xml

流程建立時,版本號是自動生成的,默認從1.0開始,當流程名稱相同時,就會生成不一樣版本。
在xml中可定義不一樣的任務節點:開始節點、自動節點、人工節點、決策節點、發散節點、聚合節點、子流程節點、會籤節點、等待節點、結束節點。
及鏈接任務節點的路由、人員分配狀況、變量定義、事件動做等信息,可參照我上篇文章中的xml定義xml

//加載流程定義
var processDefinition = bpm.LoadProcessDefiniton("1");
processDefinition.Deploy();     //發佈流程定義
processDefinition.Revoke();     //召回流程定義
processDefinition.Delete();     //刪除流程定義


    五、流程實例 對象

//發起流程實例
var process = bpm.NewProcessIntance("請假流程","蕭秦");
process.SetVariable("project_id", 1399); //保存流程變量
process.Start();   //啓動 
process.Suspend(); //掛起
process.Resume();  //恢復
process.Cancel();  //撤銷
process.End();     //結束

這裏NewProcessInstance這個方法實例上有三個參數,第一個是流程定義ID,第二個是啓動的業務ID,第三個是子流程的返回棧點ID,非子流程能夠忽略。

//啓動流程
var startTask = process.Start();
startTask.SetRecord("SO20150903001");       //保存表單數據(關聯)
startTask.SetAttach("01", "02");            //保存附件信息(關聯),可多個
startTask.SetVariable("var1", "value1");    //保存任務變量
startTask.Signal();                         //轉交下一步

task.SetRecord用於保存當前表單數據id,數據自己保存在業務表中
task.SetAttach用於保存當前節點的附件id,附件信息則保存在附件管理表中
task.Signal流程流轉的關鍵方法,根據流程定義觸發token令牌離開動做

//審批任務
var task = bpm.LoadTaskInstance("00");
task.SetOpinion(SignResult.Passed, "我贊成");  //設置審批意見
task.SetReceiver("顏經理");                    //設置下一步的審批人
task.Signal();                                //轉交下一步

這裏提供了SetReceiver的方法設置下一步的審批人,正常狀況下流程定義中已經定義好了,是不須要再進行設置的,可是考慮在實際應用中可能會有把任務給指定領導審批的狀況,在通達OA中也是能夠設置下一步審批人,故添加了此方法,須要時能夠調用,注意應用此方法會覆蓋定義中對工做項owner屬性的設置。

//任務委派
var task1 = bpm.LoadTaskInstance("01");
task1.AssignCandidate("小鄭,小胡");              //添加任務候選人
task1.AssignCandidate("saler", ActorType.Role); //添加任務候選人
task1.AssignTo("李四");                         //把任務分配給李四

個人工做流中,對於工做任務只能有一個全部者(owner),一個實際操做者(actor),但能夠擁有多個候選人(candidate)。
候選人是當前工做可分配的一範圍限制或人員列表,owner是任務的擁有者,actor是owner考慮複雜委辦關係後計算出的操做者。
task.AssignCandidate這個方法用於添加任務候選人,第二個參數是對象類型,能夠直接添加一個角色、機構、用戶組等。
task.AssignTo即分配任務,任務的分配狀態包括如下幾個狀態

public enum AssignStatus
{
    //未決
    Pending,

    //認領, 用戶認領任務並接收任務輸入數據
    Claim,

    //委辦, 委派給另外一我的(例如,經理)以代替他或她執行任務
    Depute,

    //到期, 沒有在指定的時間段內處理批准任務
    Expire,

    //續訂, 沒有在給定的時間範圍內處理此任務,則該任務將被續訂,以便在另外一時間段內執行
    Renew
}

若是流程卡到某個節點好久,咱們能夠發催辦消息
若是一個流程節點的確須要好久才能完成,我設計了一個當前工做進度彙報接口

//工做催辦
task.Urge("很急,請經理儘快處理,在線等!");

//彙報當前工做進度
task.Report(0.6, "預計這個星期就能完成");

task.Urge會向任務實際擁有者發送一條催辦通知,並生成催辦歷史。
task.Report會向任務的訂閱者(全部關注當前流程任務的人)發送一條進度報告。

//查詢變量
var var0 = process.GetVariable("project_id");
var var1 = task1.GetVariable("var1");
var var2 = task1.GetVariable<DateTime>("var2");
var var3 = task1.GetVariableObject("var3");

變量分爲三種:
流程變量 會持久化,存在於整個的流程週期內
任務變量 會持久化,存在在當前的任務中
臨時變量 不會持久化到數據庫中,只存在於當前執行上下文中(executionContext)。
設置變量SetVariable 獲取變量GetVariable
支持任意數據類型

    六、中國特點審批方式,主要包括會籤、加簽(前加簽、後加籤、並加簽)、減籤、自由流
會籤:一個任務由多我的參與共同作決策
加簽:這個任務我本身以爲沒有把握,想加入一我的或多我的跟我共同決策(在前加簽順序在當前決策者以前,後加籤順序在當前決策者以後,並加簽不分順序並行處理)
減籤:跟加簽相反,取消某人蔘與決策的資格
自由流:流程定義中沒有,臨時添加的動態路由直接把當前工做發送到指定的節點審批。
轉會籤:由單人決策的普通審批節點轉成多人共同決策的會籤節點,支持遞歸會籤,即會籤子節點能夠繼續轉會籤節點 。
轉審批:由多人共同決策的會籤節點轉成單人決策的普通審批節點

在我在工做流中,會籤設計瞭如下幾個參數:
a 運行模式,並行時如發散節點,進入會籤節點時會同時激活全部參與人的工做任務,串行時則有前後順序,因此纔有了前加簽和後加籤

public enum RunMode
{
    //串行
    Serial,

    //並行
    Parallel
}

b 決策模式,根據子節點的結果如何去決策會籤節點

public enum DecisionMode
{
    //主辦人模式
    Sponsor, 
    
    //投票模式
    Vote, 
    
    //一票經過
    OnePass, 
    
    //一票否決
    OneVeto
}

主辦人模式:須要設置一個主辦人,結果以主辦人的決策爲準,其它人的決策只是提供參考
投票模式:即設置一個經過的比例,由你們投票決定。支持設置每一個人的投票權重。
一票經過:其實能夠看做是投票模式經過率設置大於0%的一種。
一票否決:能夠看做投票模式經過率設置100%的一種。
固然這裏只是我把經常使用的幾種模式列出來了,還能夠本身拓展決策模式,只須要繼承實現我定義的抽象類Decision便可。

c 是否等待,即還有人未表決,但目前已表決的狀況已經能夠肯定會簽結果的狀況下,需不須要等待其它人表決完成後才繼續轉交下一步。

會籤分兩種,一種是流程定義中定義好的會籤,一種是普通審批節點臨時轉成會籤的。實際上中國式審批其實就是要靈活,若是在流程定義中定義好的,其實能夠不用會籤節點,用多個普通節點也能夠去實現。會籤節點的設計主要是爲了轉會籤這個場景:就是當前普通審批節點的審批人以爲本身沒有把握或者不想擔責任,能夠加入上級領導或其它更多的人一塊兒來決策或提供參考意見。

示例:普通審批轉會籤 運行模式設置爲並行,決策模式是權重投票,須要等待全部人都投票,經過線爲65%

//轉會籤
var task2 = bpm.LoadTaskInstance("02"); 
task2.ToCountersign(RunMode.Parallel, DecisionMode.Vote, true, 0.65M);
task2.CountersignAdd(new Countersigner() { actor_id = "張三", vote_weight = 1 });
task2.CountersignAdd(new Countersigner() { actor_id = "李四", vote_weight = 0.5 });
task2.CountersignAdd(new Countersigner() { actor_id = "小五", vote_weight = 2 });

並行模式即爲並加簽,前加簽、後加籤的前提是串行模式,假設task2爲串行、主辦人模式、原審批人爲蕭秦

//前加簽
task2.CountersignAddBefore("蕭秦", new Countersigner() { actor_id = "張三"});

//後加籤
task2.CountersignAddAfter("蕭秦", new Countersigner() { actor_id = "李四", is_sponsor = true});

減籤則相對比較簡單了

//減籤
task2.CountersignRemove("王");

會籤節點轉普通審批,直接讓一我的決策

//轉審批
 task2.ToSinglesign("隔壁老王");

自由流模式,建立臨時路直接跳轉到指定節點進行審批

//自由流
var task3 = bpm.LoadTaskInstance("03");
task3.SetFreeRedirect("總經理審批");
task3.Signal();


    七、回退機制
流程回退到指定節點

//流程實例指定任意節點回退
var process2 = bpm.LoadProcessInstance("02");
process2.Rollback("填寫請假單");

任務實例回退到上一步

//當前工做任務回退到上一個審批節點
var task4 = bpm.LoadTaskInstance("04");
task4.Rollback();


    八、工做委辦
張三把某個任務直接委託給李四辦理,支持遞歸委辦關係,即張三委託給李四,李四再委託給王五,王五在委託給趙六…

bpm.NewDeputeService("張三", "李四")
   .ForTaskInstance("任務實例ID")
   .Depute();

把整個流程實例委託給李四,即此流程實例下全部的張三的任務都會委託給李四

bpm.NewDeputeService("張三", "李四")
   .ForProcessInstance("流程實例ID")
   .Depute();

把某個流程定義中的一個任務節點委託給李四,即全部的這個節點建立的全部任務實例若是是張三的任務都會委託給李四

bpm.NewDeputeService("張三", "李四")
   .ForTaskDefinition("任務定義ID")
   .Depute();

把某個流程定義委託給李四,即這個流程中建立的全部的任務實例,若是是張三的任務,在設置的生效期間中都會委託給李四

bpm.NewDeputeService("張三", "李四")
   .ForProcessDefinition("流程定義ID")
   .SetDateRange(DateTime.Now, DateTime.Now.AddDays(30)) //生效期間
   .SetMemo("這個月出差,這個流程都委託給李四代辦")            //委託說明
   .Depute();

收回委託關係,只要將Revoke替換Depute動做便可

//收回委辦工做
bpm.NewDeputeService("張三", "李四")
   .ForProcessInstance("流程實例ID")
   .Revoke();


    九、關注訂閱
這個功能跟委託類似,訂閱後會收到流程動態或任務動態消息提醒,如:流程已建立、啓動、掛起…,任務已建立、分配給誰、進度彙報、任務完成等等

//關注訂閱
bpm.NewSubscribeService("張三")
   .ForTaskInstance("任務實例ID")
   .Subscribe();

bpm.NewSubscribeService("張三")
   .ForProcessInstance("流程實例ID")
   .Subscribe();

bpm.NewSubscribeService("張三")
   .ForProcessDefinition("流程定義ID")
   .Subscribe();

bpm.NewSubscribeService("張三","李四","王五")
   .ForTaskDefinition("任務定義ID")
   .Subscribe();

取消訂閱,同樣只須要把Subscribe改成Unsubscribe便可

//取消訂閱
bpm.NewSubscribeService("李四")
   .ForProcessDefinition("採購流程")
   .Unsubscribe();


    十、數據查詢
查詢我沒有提供接口,直接開放數據庫查詢比我提供的接口會更加靈活,好比:
a 查詢已發佈的流程定義

select * from bpm_definition_process where state = 'Deploy'

流程定義狀態包括

public enum ProcessDefinitionState
{
    //建立
    Create,

    //解析
    Parse,

    //發佈
    Deploy,

    //回收
    Revoke,

    //刪除
    Delete
}

b 個人流程

select * from bpm_instance_process where state = 'Run' and starter = '蕭秦'

流程狀態包括

public enum ProcessState
{
    //建立
    Create,

    //運行
    Run,

    //掛起
    Pending,

    //終止
    Termination,

    //完成
    Complete,

    //取消
    Cancel
}

c 個人待辦任務

select * from bpm_instance_task where state = 'Run' and actor_id = '蕭秦'

待辦任務包括了別人委託給你的任務,若是隻想看屬於本身的任務則能夠

select * from bpm_instance_task where state = 'Run' and owner_id = '蕭秦'

任務狀態包括

public enum TaskState
{
    //建立, 任務已被建立
    Create,

    //阻塞, 到達線中有阻塞任務還未完成
    Blocking,

    //啓動
    Run,
   
    //完成, 用戶已經完成任務並提供了任務的輸出數據
    Complete,

    //失敗, 用戶已經完成任務, 而且提供了錯誤消息
    Failure,

    //回退
    Rollback
}

d 查詢任務的候選人信息

select * from bpm_instance_assignment where task_instance_id = 'ID'

e 查詢個人消息

select * from bpm_application_notify where state='Unread' and reciever_id = '蕭秦'

其它查詢就再也不舉例了
 

3、總結

     以前我有說過我開發這個的引擎的目的是爲了在作項目時,有一個體積輕巧,引入方便的單dll文件(發佈後大小爲1.1M)的工做流引擎,接口也簡單易於二次開發,支持多數據庫而且功能還算強大。從前年開始的簡易版本設計開發到如今基本成形,測試也是花費了大量的時間,可能還有問題沒有測到,不過如今基本穩定。接下來若是有時間我會慢慢跟你們介紹功能細節的設計和實現,還有什麼功能我考慮不周全的或意見或有哪部分想詳細瞭解的均可以給我留言。聯繫13606021792

相關文章
相關標籤/搜索