Views: 45
我們目標是寫一支DLL,在申請者送出後讀取表單資料,然後將資料存到資料表Z_TRIGGER_TEST。
Trigger用途
在BPM模組中,我們如果需要這幾樣功能,透過Trigger比較容易,這功能其實是所謂的hook,但在UOF2稱為TRIGGER
- 申請者送出表單時取到電子表單的內容並寫到特定的資料表
 - 申請者送出將表單內容送去外部系統
 - 在流程中將欄位填入特定資料,例如將評比分數轉換為ABC
 
前置準備
- 先把UOF2安裝好,我安裝到
C:\Web\UOFTEST\,這篇教學使用的是v28版,官方2025公班導入時提供的版本 - 創好一個帳號(不建議用admin),然後可以設定為系統管理員
 - Visual Studio 2022,我使用的是社群版本
 
Getting Start
創立專案
VISUAL STUDIO 2022 > 新增 類別庫專案(.Net Framwork) 英文版是Class Library(.NET Framwork)
這邊要注意要選有(.NET Framwork的),然後.Net Framework版本要選4.8
創好之後刪除Class1.cs
加入必要的參考元件

選擇 瀏覽Browse > Browse..瀏覽,接著找到網站的bin資料夾,我的是C:\WEB\UOFTEST\bin,然後直接貼底下列出的黨名
(印象中這是公班導入時老師建議的常用DLL)
Quartz.dll排程有關的Ede.Uof.EIP.Organization.dll組織有關的Ede.Uof.EIP.Organization.Util.dll組織有關的Ede.Uof.EIP.Plant.dll設備借用有關的Ede.Uof.EIP.ResourceLibrary.dllEde.Uof.EIP.Schedule.CalendarSync.dll行事曆有關的Ede.Uof.EIP.Schedule.Common.dll行事曆有關的Ede.Uof.EIP.Schedule.Corporation.dll行事曆有關的Ede.Uof.EIP.Schedule.dll行事曆有關的Ede.Uof.EIP.Schedule.Report.dll行事曆有關的Ede.Uof.EIP.SystemInfo.dllEde.Uof.Utility.Data.dllEde.Uof.Utility.dll大部分重要的函數都在這邊Ede.Uof.Utility.Log.dllEde.Uof.Utility.Message.dll寄信有關Ede.Uof.Utility.Page.Common.dll頁面元件有關Ede.Uof.Utility.Page.dllEde.Uof.Utility.Task.dll排程有關Ede.Uof.WKF.Design.dll電子表單有關Ede.Uof.WKF.dll電子表單有關Newtonsoft.Json.dll物件轉JSON有關
加完後按下OK
加入後可以在參考(Reference看到)
表單簽核事件
一等一UOF2的表單總共有幾個事件
- 起單
 - 簽核
 - 結案
 - 取回
 - 作廢
 - 變更狀態(表單管理員)
 
比較常用的是前三個狀態
設計一個TRIGGER測試表單
表單名稱:測試TRIGGER
表單設定
通常我不勾「預設儲存副本」,跟不勾「下一站若為相同簽核者則跳過」
設計表單
我們一開始欄位不用多,只需幾個代表性欄位
- 表單編號(
DOC_NBR) - 申請者(
APPLICICATE) - 申請者部門(
APPLICICATE_DEPT) - 單行文字(
SINGLE_TEXT) - 申請日期(
APPLY_DATE) 
加入流程
設計完成後加入流程,這邊測試上就加入兩個申請者就好。
發佈表單
TRIGGER命名
- 單一
Trigger:如果沒有要把起單、簽核、結案等表單不同階段分開為不同triiger,這邊直接用Trigger就好。 - 多個
Trigger:起單、簽核、結案等表單不同階段分開為不同Trigger- 起單:
TriggerStart - 簽核:
TriggerSign - 結案:
TriggerFinish - 作廢:
TriggerCancel - 退回:
TriggerReturn 
 - 起單:
 
常用的是這五種
開始寫TRIGGER
我們目標是讀取表單資料,然後將資料存到資料表Z_TRIGGER_TEST。
新增 Trigger.cs
對專案按下Add之後選Class後,輸入Trigger.cs
這邊要做幾件事
- 可見度改為
public - 繼承兩個介面
ICallbackTriggerPlugin - 加入
using Ede.Uof.WKF.ExternalUtility;,這個通常會自動加入,如果沒加入的話自己加一下,如果Visual Studio顯示找不到的話,應該是沒將對應的dll加入參考,請補一下。 
實做Trigger介面
這邊Visual Studio有自動實做的功能,先將滑鼠移到1紅線處,接著點出來的2小圖,然後選3 implement interface
實做後我們要先把 throw都刪除,然後在GetFormResult()加入一個Return "" ;
改完之後如圖。
之後我們目標在GetFormResult(),其他兩個方法不用理會
取得表單XML內容
表單送出後會存入XML,要取得的話有兩個方法
- 從資料庫的
TB_WKF_TASK資料表用表單編號查詢 - 從
applyTask取得表單的內容 
從資料庫取得
表單的最後狀態在UOF2系統中是儲存在資料表TB_WKF_TASK ,可以透過SQL查詢取得,不過我寫Trigger不太用這個方式。
SELECT TOP (1) [CURRENT_DOC] FROM [dbo].[TB_WKF_TASK] WHERE [DOC_NBR] = '表單編號'
從applyTask取得
寫法關鍵在於 透過applyTask.CurrentDocXML可以拿到XML的內容,然後通常我會存到硬碟中,整個寫起來作法如下。
using Ede.Uof.Utility.Data;
using Ede.Uof.WKF.ExternalUtility;
using System;
using System.Xml;
namespace UOF_DEV
{
    public class Trigger : ICallbackTriggerPlugin
    {
        public void Finally()
        {
            
        }
        public string GetFormResult(ApplyTask applyTask)
        {
            //取得表單編號
            string DOC_NBR = applyTask.FormNumber;
            //將目前表單內容讀到 doc物件當中
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(applyTask.CurrentDocXML);
            //儲存表單xml內容到硬碟中
            doc.Save($"C:\\UOF_DEBUG\\{DOC_NBR}{DateTime.Now:yyyy-MM-dd-hh-mm-ss}.xml");
            //故意失敗,用於重複測試使用
            throw new Exception("For TEST");
            return "";
        }
        public void OnError(Exception errorException)
        {
            
        }
    }
}
Trigger的部分我們先寫到這,先來讓系統可以自動呼叫Trigger,這邊我多加了一個故意讓方法失敗的Exception,這是個開發上的小技巧,有了這個就能透過重送功能直接測試Trigger。
建立UOF_DEBUG資料夾
我將XML將資料儲存到C:\UOF_DEBUG資料夾中,這個資料夾要先手動建立+賦予帳號iis apppool\應用程式集區名稱寫入權限
設定編譯路徑
我通常設定編譯後直接送至bin資料夾。
對專案按下右鍵,選擇屬性Properties
這邊直接從檔案總管複製路徑,貼到Output path就好,完成後儲存與關閉。
測試編譯
測試編譯UOF_DEV,對專案按下滑鼠右鍵,選擇Build(建置)
編譯後應該可以在bin資料夾中看到跟專案同名的dll檔案
外部組件註冊-註冊DLL
- 分類:我有先建立一個TEST的分類,這邊就看需求去規劃你的分類
 - 外部組件名稱:這個不是檔名,通常是取表單名稱+事件名稱,例如
表單AA-起單、表單AA-簽核中、表單AA-結案等,這邊用於之後表單事件的選擇辨認DLL用途。 - DLL:名稱,這邊要帶入DLL檔名,但不需要副檔名
.dll - 組件路徑:namespace+class名稱,通常是專案名稱+類別名稱,所以在這邊我填入
UOF_DEV.Trigger 
這邊KEY好之後按下「確定」,存檔離開。
設定表單事件要呼叫的Trigger
同樣轉到表單設計
選擇表單 > 維護表單
接著在這幾個項目選擇剛剛的組件,選好了之後按下確定。
測試送單
換個帳號(不要用admin)
電子簽核 >>表單申請
選擇表單>>填寫表單
將一般帳號加入系統管理員
通常在本機開發時測試表單我都會用一般帳號測試,但會將這個一般帳號設定為系統管理員,不熟一等一科技EIP的朋友也別擔心,步驟如下
先用admin帳號登入,預設密碼為123456
系統管理>管理員設定
選系統管理員 > 選取人員 之後選擇你的帳號就能新增
觀看DLL呼叫情形
這個功能需要系統管理員才看的到
電子簽核 >> 呼叫DLL狀態查詢
接著點表單 > 查詢,如果正常的話可以看見一個傳送失敗 or (傳送成功),如果都沒看到的話要到表單設計>維護表單>進階設定看DLL那邊設定有沒有選。
接著滑鼠點表單編號,可以看到傳送狀態
點進去後應該可以看見程式末端拋出來的Exception For TEST,這代表之前到這個步驟你應該都做成功了。
拆解XML
XML我們已經透過trigger另存成一個檔案,可以在檔案總管找到它,我的是存在C:\UOF_DEBUG\,這邊的小技巧是可以讓檔案照時間排序。
接著使用notepad++開啟檔案內容
這邊你可以發現資料大致上是這樣
fildId =欄位名稱feildValue= 欄位內容realValue= 另一種欄位內容 ,人員組織多半這樣放
寫Model
我習慣靠 Dapper 這類 ORM 替代 ADO.NET (傳統的 .NET 資料庫讀寫套件),寫得比較快而且比較不會出錯。
我們先把對應的 Model 寫出來,用途是我們寫一個物件,物件的屬性就是對應資料庫欄位,這樣靠 Dapper 寫資料庫 CRUD 時候就能自動幫我們進行對應,減少要寫的程式碼。
整理一下欄位(這個案例中都是string)
DOC_NBR表單編號APPLICICATE申請者APPLICICATE_DEPT申請者部門APPLY_DATE申請日期,這個用DateTime類型SINGLE_TEXT單行文字
另外還有兩個狀態欄位建議加上去(都是string)
TASK_STATUS表單工作狀態:1處理中,2結案,3異常,4退回TASK_RESULT表單申請結果:0核准,1否決,2作廢,NULL簽核中
資料表在這邊我取名為 Z_TEST_TRIGGER ,因此新增一個類別檔案 Z_TEST_TRIGGER.cs
 Z_TEST_TRIGGER.cs內容如下:
using System;
namespace UOF_DEV
{
    /// <summary>
    /// 測試用的表單 對應資料表 Z_TEST_TRIGGER
    /// </summary>
    public class Z_TEST_TRIGGER
    {
        /// <summary>
        /// 表單編號
        /// </summary>
        public string DOC_NBR { get; set; }
        /// <summary>
        /// 申請人
        /// </summary>
        public string APPLICICATE { get; set; }
        /// <summary>
        /// 申請者部門
        /// </summary>
        public string APPLICICATE_DEPT { get; set; }
        /// <summary>
        /// 申請日期
        /// </summary>
        public DateTime APPLY_DATE { get; set; }
        /// <summary>
        /// 單行文字測試
        /// </summary>
        public string SINGLE_TEXT { get; set; }
        /// <summary>
        /// 表單工作狀態: 1處理中, 2結案, 3異常, 4退回
        /// </summary>
        public string TASK_STATUS { get; set; }
        /// <summary>
        /// 表單申請結果: 0核准, 1否決, 2作廢, NULL簽核中
        /// </summary>
        public string TASK_RESULT { get; set; }
    }
}
接著在資料庫新增資料表,這邊我使用SSMS的介面操作
這邊依照需求寫資料,注意記得將DOC_NBR設定為PK(主鍵)
一些處理的函數
(這邊其實靠ChatGPT就好)
我在這裡提供幾個方便的函數,可以學我將這些寫成Trigger共用DLL,但先這樣用
GetFieldValue取得XML中FieldValue的值TryParseDateTime字串轉DateTimeGetFormTaskStatus將表單狀態轉為數字GetFormTaskResult將申請結果轉為數字
/// <summary>
/// 取出XML字串的值
/// </summary>
/// <param name="doc"></param>
// <param name="fieldId"></param>
/// <returns></returns>
private string GetFieldValue(XmlDocument doc, string fieldId)
{
  return doc.SelectSingleNode($"//FieldItem[@fieldId='{fieldId}']")?.Attributes["fieldValue"]?.Value;
}
/// <summary>
/// 字串轉DateTime
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private DateTime? TryParseDateTime(string value)
{
    if (DateTime.TryParse(value, out DateTime result))
        return result;
    return null;
}
/// <summary>
///表單狀態
/// </summary>
/// <param name="applyTask">
/// </param>
/// <returns>
/// 1 = 處理中
/// 2 = 結案
/// 3 = 異常
/// 4 = 退回
/// </returns>
public static string GetFormTaskStatus(ApplyTask applyTask)
{
    try
    {
        // 結案
        // 如果 TaskStatus 不是 Active,返回 "2結案"
        if (applyTask.Task.TaskStatus != ActiveStatus.Active)
        {
            return "2";
        }
        //退回申請者
        // 檢查 SignResult 為 ReturnToAppliant 退回申請者 且 TaskStatus 為 Active,返回 "4退回"
        if (applyTask.SignResult == SignResult.ReturnToAppliant &&
            applyTask.Task.TaskStatus == ActiveStatus.Active)
        {
            return "4";
        }
        // 退回某人
        // 檢查 SignResult 為 Return 且 TaskStatus 為 Active,返回 "1處理中"
        if (applyTask.SignResult == SignResult.Return && applyTask.Task.TaskStatus == ActiveStatus.Active)
        {
            return "1";
        }
        // 檢查 SignResult 為 GetBack 且 TaskStatus 為 Active,返回 "4退回"
        if (applyTask.SignResult == SignResult.GetBack && applyTask.Task.TaskStatus == ActiveStatus.Active)
        {
            return "4";
        }
        // 檢查 SignResult 為 Approve 且 TaskStatus 為 ReturnToApplicant,返回 "1處理中"
        if (applyTask.SignResult == SignResult.Approve &&
            applyTask.Task.TaskStatus == ActiveStatus.ReturnToApplicant)
        {
            return "1";
        }
        // 檢查 SignResult 為 Disapprove 且 TaskStatus 為 Active,返回 "2結案"
        if (applyTask.SignResult == SignResult.Disapprove && applyTask.Task.TaskStatus == ActiveStatus.Active)
        {
            return "2";
        }
        // 如果沒有匹配條件,返回 "1處理中"
        return "1";
    }
    catch
    {
        // 如果發生異常,返回 "3異常"
        return "3";
    }
}
/// <summary>
/// 取得表單的申請結果
/// </summary>
/// <param name="applyTask">The apply task.</param>
/// <returns>0核准, 1否決, 2作廢,3退回, NULL 簽核中</returns>
public static string GetFormTaskResult(ApplyTask applyTask)
{
    return applyTask.FormResult == ApplyResult.UnKnow ? null : ((int)applyTask.FormResult).ToString();
}
將XML轉為MODEL
var model = new Z_TEST_TRIGGER
{
    DOC_NBR = GetFieldValue(doc, "DOC_NBR"),
    APPLICICATE = GetFieldValue(doc, "APPLICICATE"),
    APPLICICATE_DEPT = GetFieldValue(doc, "APPLICICATE_DEPT"),
    APPLY_DATE = TryParseDateTime(GetFieldValue(doc, "APPLY_DATE")) ?? DateTime.Now,
    SINGLE_TEXT = GetFieldValue(doc, "SINGLE_TEXT"),
    TASK_STATUS = GetFormTaskStatus(applyTask),
    TASK_RESULT = GetFormTaskResult(applyTask)
};
安裝dapper
對專案案右鍵 然後選Manage NuGet Packages (管理Nuget套件)

Browse 瀏覽 > 搜尋 dapper > install
Apply (套用)
⚠️ System.Runtime.CompilerServices.Unsafe 4.5.3 這邊有個坑
⚠️⚠️⚠️安裝時候會裝上舊版的System.Runtime.CompilerServices.Unsafe 4.5.3 編譯時候會蓋掉eip自帶的,導致eip變成錯誤500
裝完之後要再去Nuget的Update將System.Runtime.CompilerService.Unsafe 4.5.3 升級到 System.Runtime.CompilerService.Unsafe 5.0之後的版本,eip才能正常運作
簡單的做法就是直接全部更新就好
這樣就安裝起來了,佈署的時候要記得將 dapper.dll 一起拷貝上去,其他dapper需要的dll在eip上都新版的,所以可以不用複製
寫新增與更新
取得EIP的連線字串
_connectionString = new DatabaseHelper().Command.Connection.ConnectionString; 
using Ede.Uof.Utility.Data;
using Ede.Uof.WKF.Engine;
using Ede.Uof.WKF.ExternalUtility;
using System;
using System.Data.SqlClient;
using System.Xml;
using Dapper;
namespace UOF_DEV
{
    public class Trigger : ICallbackTriggerPlugin
    {
        /// <summary>
        /// 連線字串
        /// </summary>
        private string _connectionString;
        /// <summary>
        /// 建構子
        /// </summary>
        public Trigger()
        {
            //EIP內建抓取得連線字串
            _connectionString = new DatabaseHelper().Command.Connection.ConnectionString; 
        }
       /*其他程式碼 ....*/
     }
}
這邊偷懶一下,我只寫刪除+新增
/// <summary>
/// 新增或更新資料到 Z_TEST_TRIGGER 資料表
/// </summary>
/// <param name="model"></param>
public void Insert(Z_TEST_TRIGGER model)
{
    string sql = @"
        DELETE FROM Z_TEST_TRIGGER WHERE DOC_NBR = @DOC_NBR;
        INSERT INTO Z_TEST_TRIGGER (DOC_NBR, APPLICICATE, APPLICICATE_DEPT, APPLY_DATE, SINGLE_TEXT, TASK_STATUS, TASK_RESULT)
                    VALUES (@DOC_NBR, @APPLICICATE, @APPLICICATE_DEPT, @APPLY_DATE, @SINGLE_TEXT, @TASK_STATUS, @TASK_RESULT)";
    //將資料寫入資料庫
    using (var conn = new SqlConnection(_connectionString))
    {
        conn.Open();
        var transaction = conn.BeginTransaction();
        try
        {
            conn.Execute(sql, model , transaction);
            transaction.Commit();
        }
        catch (Exception)
        {
            transaction.Rollback();
            throw;
        }
        
    }
}
完整的Trigger程式如下
using Ede.Uof.Utility.Data;
using Ede.Uof.WKF.Engine;
using Ede.Uof.WKF.ExternalUtility;
using System;
using System.Data.SqlClient;
using System.Xml;
using Dapper;
namespace UOF_DEV
{
    public class Trigger : ICallbackTriggerPlugin
    {
        /// <summary>
        /// 連線字串
        /// </summary>
        private string _connectionString;
        /// <summary>
        /// 建構子
        /// </summary>
        public Trigger()
        {
            //EIP內建抓取得連線字串
            _connectionString = new DatabaseHelper().Command.Connection.ConnectionString; 
        }
        public void Finally()
        {
            
        }
        public string GetFormResult(ApplyTask applyTask)
        {
            //取得表單編號
            string DOC_NBR = applyTask.FormNumber;
            //將目前表單內容讀到 doc物件當中
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(applyTask.CurrentDocXML);
            //建立儲存表單的目錄
            System.IO.Directory.CreateDirectory("C:\\UOF_DEBUG\\");
            //儲存表單xml內容到硬碟中
            doc.Save($"C:\\UOF_DEBUG\\{DOC_NBR}{DateTime.Now:yyyy-MM-dd-hh-mm-ss}.xml");
            /*XML SAMPLE
             <Form formVersionId="09a27207-17b7-4ff5-be49-3b8d2d1552a7">
                 <FormFieldValue>
                   <FieldItem fieldId="DOC_NBR" fieldValue="BPM250800001" realValue="" enableSearch="True" />
                   <FieldItem fieldId="APPLICICATE" fieldValue="WISH(wish)" realValue="<UserSet><Element type='user'> <userId>084ecfd9-b65a-4b99-b649-d4abcf03112c</userId></Element></UserSet>
" enableSearch="True" />
                   <FieldItem fieldId="APPLICICATE_DEPT" fieldValue="RD-T1" realValue="2c3feec0-c47e-b3d2-9b62-053be7cac613,RD-T1,False" enableSearch="True" />
                   <FieldItem fieldId="APPLY_DATE" fieldValue="2025/08/05" realValue="" enableSearch="True" fillerName="WISH" fillerUserGuid="084ecfd9-b65a-4b99-b649-d4abcf03112c" fillerAccount="wish" fillSiteId="" />
                   <FieldItem fieldId="SINGLE_TEXT" fieldValue="123456" realValue="" enableSearch="True" fillerName="WISH" fillerUserGuid="084ecfd9-b65a-4b99-b649-d4abcf03112c" fillerAccount="wish" fillSiteId="" />
                 </FormFieldValue>
               </Form>
             */
            var model = new Z_TEST_TRIGGER
            {
                DOC_NBR = GetFieldValue(doc, "DOC_NBR"),
                APPLICICATE = GetFieldValue(doc, "APPLICICATE"),
                APPLICICATE_DEPT = GetFieldValue(doc, "APPLICICATE_DEPT"),
                APPLY_DATE = TryParseDateTime(GetFieldValue(doc, "APPLY_DATE")) ?? DateTime.Now,
                SINGLE_TEXT = GetFieldValue(doc, "SINGLE_TEXT"),
                TASK_STATUS = GetFormTaskStatus(applyTask),
                TASK_RESULT = GetFormTaskResult(applyTask)
            };
            Insert(model);
            //故意失敗,用於重複測試使用
            throw new Exception("For TEST");
            return "";
        }
        /// <summary>
        /// 新增或更新資料到 Z_TEST_TRIGGER 資料表
        /// </summary>
        /// <param name="model"></param>
        public void Insert(Z_TEST_TRIGGER model)
        {
            string sql = @"
                DELETE FROM Z_TEST_TRIGGER WHERE DOC_NBR = @DOC_NBR;
                INSERT INTO Z_TEST_TRIGGER (DOC_NBR, APPLICICATE, APPLICICATE_DEPT, APPLY_DATE, SINGLE_TEXT, TASK_STATUS, TASK_RESULT)
                            VALUES (@DOC_NBR, @APPLICICATE, @APPLICICATE_DEPT, @APPLY_DATE, @SINGLE_TEXT, @TASK_STATUS, @TASK_RESULT)";
            //將資料寫入資料庫
            using (var conn = new SqlConnection(_connectionString))
            {
                conn.Open();
                var transaction = conn.BeginTransaction();
                try
                {
                    conn.Execute(sql, model , transaction);
                    transaction.Commit();
                }
                catch (Exception)
                {
                    transaction.Rollback();
                    throw;
                }
                
            }
        }
        public void OnError(Exception errorException)
        {
            
        }
        /// <summary>
        /// 取得BPM表單中 FieldValue 的內容
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="fieldId"></param>
        /// <returns></returns>
        private string GetFieldValue(XmlDocument doc, string fieldId)
        {
            return doc.SelectSingleNode($"//FieldItem[@fieldId='{fieldId}']")?.Attributes["fieldValue"]?.Value;
        }
        /// <summary>
        /// 取得BPM表單中 RealValue 的內容
        /// </summary>
        /// <param name="doc">表單XML</param>
        /// <param name="fieldId">欄位名稱</param>
        /// <returns></returns>
        private string GerRealValue(XmlDocument doc, string fieldId)
        {
            return doc.SelectSingleNode($"//FieldItem[@fieldId='{fieldId}']")?.Attributes["realValue"]?.Value;
        }
        /// <summary>
        /// 字串轉DateTime
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private DateTime? TryParseDateTime(string value)
        {
            if (DateTime.TryParse(value, out DateTime result))
                return result;
            return null;
        }
        /// <summary>
        ///表單狀態
        /// </summary>
        /// <param name="applyTask">
        /// </param>
        /// <returns>
        /// 1 = 處理中
        /// 2 = 結案
        /// 3 = 異常
        /// 4 = 退回
        /// </returns>
        public static string GetFormTaskStatus(ApplyTask applyTask)
        {
            try
            {
                // 結案
                // 如果 TaskStatus 不是 Active,返回 "2結案"
                if (applyTask.Task.TaskStatus != ActiveStatus.Active)
                {
                    return "2";
                }
                //退回申請者
                // 檢查 SignResult 為 ReturnToAppliant 退回申請者 且 TaskStatus 為 Active,返回 "4退回"
                if (applyTask.SignResult == SignResult.ReturnToAppliant &&
                    applyTask.Task.TaskStatus == ActiveStatus.Active)
                {
                    return "4";
                }
                // 退回某人
                // 檢查 SignResult 為 Return 且 TaskStatus 為 Active,返回 "1處理中"
                if (applyTask.SignResult == SignResult.Return && applyTask.Task.TaskStatus == ActiveStatus.Active)
                {
                    return "1";
                }
                // 檢查 SignResult 為 GetBack 且 TaskStatus 為 Active,返回 "4退回"
                if (applyTask.SignResult == SignResult.GetBack && applyTask.Task.TaskStatus == ActiveStatus.Active)
                {
                    return "4";
                }
                // 檢查 SignResult 為 Approve 且 TaskStatus 為 ReturnToApplicant,返回 "1處理中"
                if (applyTask.SignResult == SignResult.Approve &&
                    applyTask.Task.TaskStatus == ActiveStatus.ReturnToApplicant)
                {
                    return "1";
                }
                // 檢查 SignResult 為 Disapprove 且 TaskStatus 為 Active,返回 "2結案"
                if (applyTask.SignResult == SignResult.Disapprove && applyTask.Task.TaskStatus == ActiveStatus.Active)
                {
                    return "2";
                }
                // 如果沒有匹配條件,返回 "1處理中"
                return "1";
            }
            catch
            {
                // 如果發生異常,返回 "3異常"
                return "3";
            }
        }
        /// <summary>
        /// 取得表單的申請結果
        /// </summary>
        /// <param name="applyTask">The apply task.</param>
        /// <returns>0核准, 1否決, 2作廢,3退回, NULL 簽核中</returns>
        public static string GetFormTaskResult(ApplyTask applyTask)
        {
            return applyTask.FormResult == ApplyResult.UnKnow ? null : ((int)applyTask.FormResult).ToString();
        }
    }
}
好了就可以編譯+進行重送表單到Trigger
重送表單到Trigger測試
因為之前有拋出Exception,所以可以一直重新執行,這個上線前記得拿掉。
編譯新版的後,重新回到EIP內的電子簽核>>管理>>呼叫DLL狀態查詢
選擇表單>>勾選>>重新執行>>點表單編號進去看結果
從資料庫驗證結果
寫程式的一個很重要的點 ,一定要驗證
上測試環境前的準備
- 多測試幾次,使用不同帳號跟職位進行測試
 - 將儲存xml等臨時性的程式碼刪除或註解
 - 進行重構:補齊註解+重新命名變數讓程式更好維護
 
官方文件參考
這部分如果想參考可以看 U-OfficeForce26.0系統開發手冊(電子簽核).docx.pdf ,看肆、表單事件處理,不過我覺得寫的很少,多數技巧是我自己摸出來的。

				
0 Comments