2012年7月2日 星期一

Agentflow 開發-會簽應用篇


會簽應用類型
在企業流程的運作中,最常見的類型有兩種,一是循序,另一種是平行簽核,以名片申請流程為例,這類型流程多為一關做完後再往下一關去,
Agentflow流程管理平台中。在會簽的應用上可以採用四種方式來處理(以我們的經驗來分類)。

1. 會簽模組
利用Agentflow流程開發工具時,在流程設計時可以加入會簽模組的節點,代表在公司的流程中,有特定的關卡是一定要平行給特定人員來處理。設計者可以在這個關卡中事先設定要給那些人。這樣的設計適用於一開始就固定給特定的群組對象。

2. 動態會簽
Agentflow的動態會簽功能是相當實用的機制,在公司運作的流程中,常常會有在原本的流程關卡中,需要彈性地由負責人再詢問其他同仁或部門人員的狀況發生。這時候就可以透過Agentflow的動態會簽機制,由負責人每次設定動態加會簽給其他人。詳細的設定請自行參閱流程設計師手冊囉!

3. 動態會簽加值
如果在流程的過程中,我們已經知道某個關卡就是要會簽多人來簽核表示意見,但是這個關卡的人員是由申請人在填寫這次表單時候指定的(當然,不一定要是申請人,只要是在會簽關卡之前的關卡),而非固定的給某些人員。例如:在內部聯絡單中,申請人一開始就可以填寫後面關卡(主管審核關卡後的會簽關卡),他認為需要會簽給那些單位人員,等到主管審核通過後,就直接分送給這些人員簽核。
申請人(指派會簽各單位的人員)-->主管審核-->會簽各單位-->通知申請人。
若我們能夠由前面的人先決定會面關卡的動態會簽人員,而不用由主管審核關卡的主管來設定動態加會簽對象,不就可以達到這樣的效果嗎?這5種應用加值的方式,待會會以案例的方式分享給大家做個參考。

4. 子流程應用於會簽
另外一種會簽的應用方式,是透過子流程來達成。可以事先做好一個會簽流程,關卡數可以僅有一關就結束。當申請人在表單上填寫會簽對象後,流程的下一步就是產生子流程,將表單上的會簽人員當成子流程關卡的處理者,讓他們平行會簽(其實也就是執行子流程關卡),送出子流程後就回到母流程。這樣子的應用需考慮母流程與子流程的資料交換,但是它的彈性應該是最大的。因為是由子流程來處理會簽,它就是一隻完整的流程,可以有不同的表單畫面以及流程完整的Action可以變化。但是也由於它是完整的流程,因此在會簽的同時(使用子流程表單畫面時),是沒有原本表單在下方的(母流程)。當然,我們也可以設計與原本一樣的畫面,再將資料拋轉過來。

這種應用的方式,依我們過去開發Agentflow的經驗,我們認為有它的優點也有它的缺點,下次有空談到子流程應用時,再來跟大家聊聊。




 會簽通知應用範例
我們以業務流程中會用到的內部訂單流程為例來說明。





這個流程的需求是,業務助理除了送交單位主管審核外,還要將內部訂單送給執行單位主管來審查,執行單位主管有三種需求。一個是同時可能送多個人來處理,二是當多人來處理時,只要有一個主管不同意,整個流程就退回,最後則是執行單位主管是每一次業務助理填寫表單時決定,並非是固定的對象。



在表單中設定會簽對象
我們讓使用者在表單中可以設定要會簽的對象,點選icon後跳出一小視窗,讓使用者選擇簽核的對象。


選人的視窗
我們用e-form另外設計一個選人的視窗,用表格元件設計已選的列表,選定完成後將選好列表的資料帶回原本的表單畫面。這種做法,就像一般開視窗選資料,再將資料帶回的效果。

Form.openRoleTreeCustom(true,"" , "member", "orgAction()","", "forms[0].Sign_MemName","forms[0].Sign_MemID","1");

隱藏元件(會簽對象)
一般我們在表單中顯示的資訊,多為使用者看得懂的資訊,例如會簽對象的姓名,但是對於Agentflow系統而言,會簽對象的MemID才是唯一最正確的資訊,所以通常我們會將所需的對象資訊放在一個隱藏的表格,記錄在表單中,這樣一來可以記錄系統所需的資訊外,二來在日後的除錯或追蹤上也會有所依據。

如何利用動態會簽機制
我們前面已經設定了要會簽的對象,接下來就是讓流程關卡可以拿著這些會簽對象,產生動態會簽並且判斷會簽的結果。在這裡我們用了兩個自動執行的節點。
執行會簽
addAddASAudit();

//設定會簽人員 from table
function addAddASAudit(){
var aInstance = MyTask.getArtInstance();
var dataMap = aInstance.getAppDataMap();
var vac = dataMap.get("Sign_Table");
//有設會簽人員才設會簽
if(vac.size()>0  ){
     MyTask.setExecuteAddAS(true);
     MyTask.setAddASType(MyTask.ADD_PARALLEL_ANNOUNCE);
     for(var i = 0;i< vac.size();i++){
         var memid = vac.get(i).get("ITEM2");
         member = Server.getMember(memid);
     MyTask.addAddASAudit(member.getID(),member.getMainRoleID(),member.getMemberDR(member.getMainRoleID()).getDepartmentID());
     }
    
}else{
             Server.flowTo(MyTask,"執行單位主管會簽完成");
}
}
判斷簽核結果與彙整簽核意見

mergeAddAsInfo();
var aInstance = MyTask.getArtInstance();
var dataMap = aInstance.getAppDataMap();
if("true" == dataMap.get("Add_Sign_Reject")){
     Server.flowTo(MyTask,"主管退回");
}else{
     Server.flowTo(MyTask,"執行單位主管同意");
}

//   取出彙整的會簽內容
function mergeAddAsInfo() {
var aInstance = MyTask.getArtInstance();
var dataMap = aInstance.getAppDataMap();
//將會簽結果放入審核意見裡面
var taskmemberlist  = MyTask.getAddASAuditList() ;
var totalResult     = MyTask.getAddASResultString();                //取得加會簽結果的字串
var detailResult    = Server.parseAddASResultString(totalResult);   //將加會簽結果的字串解析成個別的物件形式
var flg_rejcet = false;
var tag = "========================================================";
       var msgarray = SplitString(totalResult,tag);
       var resultarray = SplitResultString(totalResult,tag);
  for(var i = 0; i< detailResult.size(); i++){
     var aCSResultData = detailResult.get(i);
     insertTableByAddAs(aCSResultData,resultarray[i],msgarray[i],"Process_Table");
     if("不同意" == resultarray[i]){
         flg_rejcet = true;
     }
}
if(flg_rejcet){
     //會簽中只要有一人駁回就是要駁回
     dataMap.put("Add_Sign_Reject","true");
}
}

// 把簽核結果加至簽核紀錄表格中
function insertTableByAddAs(aCSResultData,addasResult,msg,tableName) {
var aInstance = MyTask.getArtInstance();
// 整理會簽資料
var addasDep    = aCSResultData.getDep();
var addasRole   = aCSResultData.getRole();
var tmpName     = aCSResultData.getName();
var addasTime   = aCSResultData.getTime("yyyy/MM/dd HH:mm");
var addasName   = tmpName.substring(0,tmpName.indexOf("(")); //只能拿到姓名,沒有工號可用
//var addasMsg    = aCSResultData.getMsg(); //簽核意見
var addasMsg    = msg; //簽核意見

// 將會簽結果放入審核意見裡面
var appDataMap = aInstance.getAppDataMap();
var records = appDataMap.get(tableName);
var row = new Packages.java.util.HashMap();
row.put("ITEM7", records.size() + 1 + "");
row.put("ITEM5", addasTime);
row.put("ITEM8", "會簽單位");
row.put("ITEM6", addasDep);
row.put("ITEM9", addasRole);
row.put("ITEM4", addasName);
var l_member = Server.getMemberByCName(addasName);
var l_id = l_member.getMyID();             
row.put("ITEM2", l_id); //工號
row.put("ITEM3", addasResult);
row.put("ITEM1", addasMsg);
row.put("ITEM10", MyTask.getID());  //TaskID
records.add(records.size(), row);
appDataMap.put(tableName, records);
aInstance.setAppDataMap(appDataMap);
}    






2012年5月8日 星期二

Agentflow 開發請假系統篇-代理人


一般導入Agentflow的公司大多會開發請假系統。雖然它會讓人覺得沒有甚麼效益,但是它卻是公司用最多且不可或缺的電子表單機制。筆者幫客戶開發了許多差勤相關的系統,以我們的經驗大概可以分成三類。
1.    假卡型
這類型的公司多半沒有處理請假的人事系統,人事系統多半是應用來計算薪資,而沒有結合請假處理機制。請假的方式多由請假人向人事單位拿自己的假卡,看看自己目前所剩的假期,再透過紙本的方式向老闆請假,請完假後再註記於假卡中,交還給人事單位。
人事單位每年年初會註記每個人假卡上可被允許的假。每個月依照假卡的請假資料,來計算同仁在該月的薪資。

解決方案:遇到這類型的客戶,我們會讓人事單位與同仁將原本在紙上的作業,完全改換為系統畫面。透過具有假卡功能的差勤資料庫,來記錄每個人的請假紀錄,並且利用系統自動計算請假時數與調整每年度個人允許的假期天數,當然少不了的是請假流程與表單。


對於同仁:可以線上填寫自己的請假單,並且查詢自己剩餘的假期,當然很重要的就是送交代理人與主管審核的機制,還有目前自己的請假單送到哪了。
對於人事單位:可以在每月計算出每個人被審核通過的假數,每年年初可以調整每個同仁各類假期的天數。把原本年初假卡填寫與每月計算請假天數的工作交給電腦來做。人事單位主要與請假單有關的工作,就是到月底前要盡快地催促請假單要審核完成,避免要算薪水時,還有請假單還未通過。
2.    半自動型
這類型的公司多半已有計算假期的人事系統,但是請假單是採用人工的方式,因此透過Agentflow來把紙本的請假單改為線上系統。但由於人事系統是封閉型式,無法將同仁的請假資訊取出查詢或是當請假單完成後更新至人事系統。因此請假單電子化的機制幫助了流程的自動化與效率,但是對於人事單位在假數的計算上,幫助較少。

3.    全自動型
這類型的公司與半自動型很像,只是它的人事系統是可以被整合的,因此從請假單的填寫到差勤的計算都是一氣呵成,人事單位在請假上需要花費時間的部分,應該是每月底趕著同仁把未結的請假單趕快跑完,讓人事可以來計算薪資。
除了請假的全自動化外,有的客戶還會結合刷卡機制、加班單、出差單等,讓差勤資料的計算更完整也更人性化。當然,整合的方式得因地制宜,端看客戶現行環境來調整才是。

代理人應用
不管公司是哪一種類型,請假單都會與「代理人」機制有關,透過Agentflow的代理人機制,可以讓以前紙本的假代理機制,變成真代理。請假單中會提供代理人的欄位,等到請假單審核通過後,Agentflow系統可以在指定的請假區間終將代理人機制啟動,這樣原本送到請假人手中的工作,都會轉送給代理人處理,等到請假結束,代理人還未介入處理的工作就又會還給請假人了。
不過,這些機制必須是在請假單這個流程上設計才會有效果。在流程審核通過後,要記得將請假單上的代理人以及請假日期,透過API的方式通知Agentflow流程引擎,這樣Agentflow才會記得當請假開始時,將請假人的代理人設定給表單中的代理人,並且啟動代理。
你可以在流程結束的後置動作,撰寫指定區間代理的程式碼。程式碼片段如下
     setDeputy(App_MemID, Agent_ID, startDate, startHour, startMin, endDate, endHour, endMin);
     }
function setDeputy(mID,deputyID,startDate,startHour,startMin,endDate,endHour,endMin){
var mr = Server.getMemberByID(mID);
mr.setDeputyID(deputyID);
mr.setExeucteDeputyDuration(true);
mr.setStartExecuteDeputyTime(startDate+" "+startHour+":"+startMin);
mr.setEndExecuteDeputyTime(endDate+" "+endHour+":"+endMin);
Server.updateMemberRecord(mr);
}
這樣就可以依照請假單中填寫的資訊,自動啟動代理人機制了。當然,我們也可以採用手動啟動代理人,就不用寫這段程式碼了(不過,這樣就有點遜了呢!)。

另外在請假單中,要如何選擇代理人呢?最簡單的方式就是讓使用者可要選擇公司組織的任一個人來當成代理人。這時候,我們可以利用AgentflowRole Tree功能,跳出全公司的組織來選擇。程式碼如下
Form.openRoleTreeCustom(false, "","member","","","forms[0].Agent_Name","forms[0].Agent_ID","1");


若不喜歡組織樹的話,也可以用下拉式選單來供選擇。



這時候,可能有人會問「咦!這樣不就可以亂選代理人來代理了?」,關於這個問題,我想選定代理人後,請假單通常會送給代理人來確認是否同意,因此若選了一個不會同意的代理人,那不是讓自己的請假單一直在路上跑?通常是不會發生這種事情,我常常說「若你真的敢選總經理當你的代理人,那可能你很快就不在公司了!」,雖然這是個玩笑話,但是系統限制得越多,會越不彈性,有時候系統無法取代人,人的管理制度與文化才是最有效的。
有些公司希望代理人至少需要是自己部門的,這樣比較能夠處理請假人的工作。這時候,我們可以依然使用AgentflowRole Tree功能來讓使用者選擇代理人,但是我們將RoleTree的範圍縮小,只允許抓取請假人同部門的人員。程式碼如下
var cMember = Client.getCurrentMember();
var roleID = cMember.getMainRoleID();
var memDR = cMember.getMemberDR(roleID);
var depid = memDR.getDepartmentID();
var myid = Form.getValue("App_Dep_ID");
Form.openRoleTreeCustom(false,depid,"member","","","forms[0].Agent_Name","forms[0].Agent_ID","1");

當然,有時候我們希望每個人可被允許的代理人是固定的,可能是同部門,也有可能是跨部門。這時候,就建議自己設計個代理人的資料庫來設定每個人所被允許的代理人列表。在請假單的代理人下拉式選單中就只提供代理人列表中的資料供選擇。


另外設計的代理人設定資料庫


以上就請假單的代理人應用做個說明,希望能拋磚引玉,給各位同好做個參考。在代理人的部分,除了請假單上代理人的應用外,有時候,同仁會臨時請假,根本就沒送請假單。這時候,又希望能夠把他的工作轉給代理人,避免工作沒人處理。這時候就只能請IT人員透過管理工具(Administrator)來幫請假人啟動代理機制了(甚麼?你不會用?那記得去上Agentflow的課程吧!)。

可是誰要給誰代理,IT人員又不太清楚:< 嗯,這時候你可以考慮對於我們上面所提供的代理人列表機制再加工一番,加上啟動代理的機制就可以啦!如果能夠再加上讓各部門的助理可以自行設定自己部門內成員的代理人列表與啟動代理,這樣就更完美了(使用者有問題的時候,就不用打電話給IT,請IT來設定啦!)。聰明如你,一定知道怎麼做吧?我下次再跟各位分享囉!

2012年3月28日 星期三

Blog 開張囉...


自己投入在資訊業界已經有十幾年了,這一路多半是在與使用者打交道。
一直想要將自己在工作上的一些經驗寫下來,尤其是在企業流程管理(BPM)
上的開發經驗。

客戶的需求各式各樣,有的是很清楚自己要的,有的是希望
別人告訴他該怎麼做,有的則是走一步算一步,有也好沒有也罷。所以,做
系統最難的地方是在於"聽懂"客戶的需求是甚麼,再下一步則是"說服"客戶
自己能夠做到甚麼。當然"說服"的過程,就有很多溝通技巧需要使用,
不過,我想最重要的是將心比心,這樣可以讓整件事情平順一點。

企業流程管理(BPM),有的人把它叫做電子表單,有的人叫做簽核系統,
有的人叫它Workflow,不管怎麼稱呼。重點是它是不是能夠滿足企業現
在與可預測的未來(未來太遠了,買一個系統用個20年,這也太厲害了吧)
的需求。

之後,我會把一些我自己做資訊系統,尤其是BPM的觀念與技巧與大家分享,
希望對於朋友們有所幫助,另外,也是幫自己留個紀錄呢。