公文轉寄流程自訂的資料建模

來源:互聯網
上載者:User
資料
  開發比較複雜的企業多使用者管理資訊系統(MIS),不可能不涉及到系統內多個使用者之間的資料檔案的流轉、審批等功能的開發。由於企業的需求總是隨著時間推移不斷髮生變化,加之各個企業內部所設定的辦公流程不盡相同,一套通用性比較好的管理資訊系統應該能讓系統管理員自己定義公文轉寄的流程。

  儘管筆者沒有機會在已參與開發了的MIS中實現出檔案轉寄流程自訂的功能,但是,早在2002年初就曾深入思考過這方面的設計。當時由於某些原因不能公開自己的設計思路,現在市面上已經有不少MIS產品提供這樣的功能,筆者又已離職,所以是時候把我的設計思路整理出來,和大家分享。

  首先,讓我們分析需求,制定目標。

  1)一般情況下,企業內的公文轉寄、審批是按部門或職位來轉送,即對崗不對人。例如:某個流程的某個環節需要財務總監審批,日後財務總監換人,該流程應該不受影響。而且,流程中某個環節可能出現某個部門中的任何一人都能審批,或者需要該部門的所有人員共同審批。
  2)流程中轉送,審批的公文一般分為檔案和表單2種格式。檔案格式的公文應該支援批處理,即一次可以轉寄多個檔案,審批時可以只退回其中某一個不合格的檔案,其他的檔案可以轉送到下一個環節繼續處理。表單格式的公文應該能讓使用者自己定義表單格式,確定表單中的表項。同理,表單也應該支援批處理。
  3)流程中處理公文的動作應該能讓使用者自己定義。這樣一旦日後增加了新的處理動作,也不用修改MIS系統的底層資料建模。當然,要實現新的處理動作,還是需要在商務邏輯層編寫相應的代碼,不過和修改底層資料建模比起來,工作量要少得多。
  4)每個流程的環節數不一定相同,應該能讓使用者設定環節數,指定公文流轉中每個環節的發送部門和接受部門,處理模式,最長等待時間。
  5)當待處理的公文發出後,系統應該在等待時間中定期向該流程中下個環節的使用者(們)發出通知,提醒該使用者(們)及時處理,直至公文已被處理。如果超出最長等待時間,公文還未被使用者(們)處理,此次流程處理失敗。企業管理層可能會要求記錄相關資訊,以便在日後商務程序重組(BPR)時參考。
  6)某些企業由於特殊原因,在某個流程中要求實現跨環節處理。例如,該流程有6步,執行到第二個環節時要求處理後可以跳過中間三個環節,直接轉到最後一個環節等候處理。其實,這種情況下,並不一定要在技術層面上實現其靈活性,這種特例畢竟是少數。使用者只需定義一個新流程,把上面流程的第1,2,6步複製加入進來,2個流程之間用流程名來區分即可。一個優秀的系統架構設計師應該充分利用現有的工具,不要什麼都自行架設開發。

  上面的需求對靈活性要求較高,抽象化程度較深,所以在表現層和商務邏輯層的開發量較大,初期投資較多,不過開發完畢後估計不需對底層資料庫修改,即可滿足日後不斷變化的公文流轉需求。如果不需要這麼高的靈活性,可以按實際項目簡化某些假設條件。下面按照上面的需求進行用例(use case)分析和資料建模。

  1)由於流程環節的發送方和接受方是對崗不對人,我們應該先描畫出整個企業的機構設定,確定每個部門的權利職責。其中大的部門內可能有若干子部門,每個子部門內又有不同職位,負責處理相應的事務。所以,可先建立一個樹形關係的資料表來儲存企業結構,然後,採用許可權表和使用者組相結合的方式來儲存每個部門每個職位的職能。這塊的設計思路見我之前發布的“淺談資料庫設計技巧(上)、(下)”,我在下面直接給出大致的資料表結構:

部門表(Department_table)
名稱    類型    約束條件                       說明
Dp_id      int        無重複                     類別標識,主鍵
Dp_name   varchar(50) 不允許為空白                   類型名稱,不允許重複
Dp_father   int         不允許為空白                   該類別的父系類別標識,如果是頂節點的話設定為某個唯一值
Dp_layer    varchar(6)  限定3層,初始值為000000       類別的先序遍曆,主要為減少檢索資料庫的次數

功能表(Function_table)
名稱    類型    約束條件   說明
f_id        int        無重複     功能標識,主鍵
f_name      varchar(20) 不允許為空白   功能名稱,不允許重複
f_desc      varchar(50) 允許為空白     功能描述

使用者組表(User_group)
名稱    類型     約束條件   說明
group_id    int          無重複        使用者組標識,主鍵
group_name  varchar(20)  不允許為空白    使用者組名稱
group_power varchar(100) 不允許為空白    使用者組許可權表,內容為功能表f_id的集合

使用者表(User_table)
名稱    類型    約束條件   說明
user_id     int         無重複        使用者標識,主鍵
user_name   varchar(20) 無重複        使用者名稱
user_pwd    varchar(20) 不允許為空白    使用者密碼
user_type   int         不允許為空白    所屬使用者組標識,和User_group.group_id關聯

  說明:其中,按部門的不同職位設定不同許可權的使用者組,如某個使用者組為“市場部業務員”,該使用者組的使用者可在流程“報銷申請”中發送報銷申請。

  2)儘管流程中的公文分為檔案和表單2種格式,但是每個檔案/表單都應該有其唯一標識,名稱等屬性。所以,我們把公文抽象化,把這2種格式的公文的共有屬性提取出來建立一張公文表。

公文表(Document_table)
名稱    類型    約束條件   說明
doc_id      int         無重複        公文標識,主鍵
doc_name    varchar(50) 不允許為空白    公文名稱
doc_type    char(1)     不允許為空白    公文類型

  doc_type欄位用來辨別公文格式,目前只有2種格式,可設“1”表示檔案格式,“2”表示表單格式。估計未來新增公文格式不會太多,所以該欄位只需一位字元。檔案格式的公文一般是在檔案內固定好格式,我們可用一個二進位的欄位直接儲存整個檔案的內容。檔案格式的公文需要建一個表來儲存相關資訊,其大致資料表如下:

檔案表(File_table)
名稱    類型    約束條件   說明
file_id    int         無重複       檔案標識,主鍵
file_name  varchar(50) 不允許為空白   檔案名稱
file_value binary      不允許為空白   檔案內容
……

  表單格式的公文要讓使用者自己定義表單格式,確定表單中的表項。有兩種方法來實現:
  ①每當使用者建立一個新格式的表單時,就建立立一個表,把使用者輸入的表單表項當作該表的欄位。這種方式的優點是表單查詢速度較快方便,商務邏輯層的開發量較小。缺點是不太靈活,如果企業所使用的不同格式的表單較多(>20種),整個資料庫的結構顯得比較混亂,而且大部分表單中都有相同的欄位,這樣也增加了資料冗餘。這種方式的資料建模如下:

表單總表(Sheet_table)
名稱    類型    約束條件   說明
sheet_id    int         無重複        表單標識,主鍵
sheet_name  varchar(50) 不允許為空白    表單名稱
table_name  varchar(20) 不允許為空白    表單子表名,如Sub_table1/Sub_table2

表單子表1(Sub_table1)
名稱   類型   約束條件   說明
sub_id    int       無重複        表單子表標識,主鍵
option1   varchar   不允許為空白    表單表項1
option2   varchar   不允許為空白    表單表項2
option3   varchar   不允許為空白    表單表項3
……

表單子表2(Sub_table2)
名稱   類型   約束條件   說明
sub_id    int       無重複        表單子表標識,主鍵
option1   varchar   不允許為空白    表單表項1
option2   varchar   不允許為空白    表單表項2
option3   varchar   不允許為空白    表單表項3
……

……

  ②對錶單再進行一個抽象,把表單看成由若干個表單表項所組合成的一個集合。這種方式的優點是相當靈活,使用者建立新格式的表單時只用從已有表單表項中勾選出需要的表項即可,而且整個資料庫結構清晰,沒有資料冗餘。缺點是開發比較複雜,工作量和上面相比高出不少,而且表單查詢速度較慢。下面是這種方式的資料建模:

表單總表(Sheet_table)
名稱    類型    約束條件   說明
sheet_id    int         無重複        表單標識,主鍵
sheet_name  varchar(50) 不允許為空白    表單名稱

表單表項表(Option_table)
名稱    類型    約束條件   說明
op_id     int         無重複        表單表項標識,主鍵
op_name   varchar(50) 不允許為空白    表單表項名稱
op_length int         不允許為空白    表單表項長度
op_unit   varchar(10) 允許為空白      表單表項單位

表單資訊表(Sheetinfo_table)
名稱    類型    約束條件   說明
info_id    int        無重複      表單資訊標識,主鍵
sheet_id   int         不允許為空白   所屬表單標識,和Sheet_table.sheet_id關聯
op_id     int         不允許為空白   表單表項標識,和Option_table.op_id關聯
info_value varchar()   不允許為空白   表單資訊值

  3)我們可以把公文轉寄的流程抽象化,看作一個實體超類。建表如下:

流程表(Flow_table)
名稱     類型     約束條件   說明
flow_id      int          無重複        流程標識,主鍵
flow_name    varchar(50)  不允許為空白    流程名稱
flow_stepnum int          不允許為空白    流程步數
flow_desc    varchar(200) 允許為空白      流程描述

  流程中的每一步都可以抽象化成從發送方至接受方的用例,其資料建模大致如下:

處理動作表(Action_table)
名稱  類型     約束條件   說明
a_id    int          無重複        動作標識,主鍵
a_name  varchar(20)  不允許為空白    動作名稱
a_call  varchar(50)  不允許為空白    動作所調用的模組
a_desc  varchar(200) 允許為空白      動作描述

  說明:如果採用面向過程的開發方式,如純指令碼語言,可以把每一個處理動作寫成一個函數,調用a_call欄位記錄的函數,即可完成相應處理動作。如果採用物件導向的開發方式,可以用COM組件來封裝處理動作,則a_call用來記錄相應的COM組件的介面方法。如果是在.NET Framework環境下,可以採用Web服務的方式。當然,發送方、接受方以及公文標識是作為輸入參數的。

流程環節表(Step_table)
名稱    類型     約束條件   說明
step_id    int        無重複        環節標識,主鍵
belong     int        不允許為空白    所屬流程標識,和Flow_table.flow_id關聯
setp_order int        不允許為空白    所屬流程的步驟次序
sender     int        不允許為空白    發送方標識,和User_group.group_id關聯
receiver   int        不允許為空白    接受方標識,和User_group.group_id關聯
a_id       int        不允許為空白    處理動作標識,和Action_table.a_id關聯
a_type     int        不允許為空白    接受方所需的處理人數
max_wait   int        不允許為空白    最長等待時間
wait_unit  varchar(5) 不允許為空白    等待時間的單位

  說明:a_type用來確定接受方所需的處理人數,“0”表示需同職位的所有人一起處理,“1”表示只需該職位的任意一名員工處理,“2”表示需該職位的任意兩名員工一起處理,依次遞推……一起處理的方式和處理動作有關,例如是投票方式,少數服從多數,還是某人有一票否決權等等。可能針對某些處理動作還得細化,進行相關的資料建模,這裡我就不細分下去了。

  4)下面分析公文轉寄的流程環節記錄。此時相當於執行個體化一個流程環節的對象,發送方和接受方應具體聯絡到管理資訊系統的某個(些)使用者,而不是某個使用者組。每經過一環節,我們除了要儲存這方面的資訊,還必須儲存該環節所轉寄的公文,以及處理狀況等資訊。而且,該環節所轉寄公文數量大於等於一,所以可以參考我之前發布的“淺談資料庫設計技巧(下)”中的“簡潔的批量m:n設計”,建表大致如下:

流程環節記錄表(Step_log)
名稱   類型       約束條件   說明
log_id    int          無重複        環節記錄標識,主鍵
step_id   int          不允許為空白    環節標識,和Step_table.step_id關聯
sender    varchar(100) 不允許為空白    發送使用者標識,相關使用者組的User_table.user_id的集合
receiver  varchar(100) 不允許為空白    接受使用者標識,相關使用者組的User_table.user_id的集合
doc_id    int          不允許為空白    轉寄公文標識,和Document_table.doc_id關聯
batch_no  int          不允許為空白    批量轉寄公文編號,同一流程環節轉寄的batch_no相同
state     char(1)      不允許為空白    處理狀態
sub_date  datetime     不允許為空白    提交時間
res_date  datetime     允許為空白      處理回複時間
comment   varchar(255) 允許為空白   處理回複注釋

  說明:
  ①同一流程環節轉寄的batch_no和該批第一條入庫的log_id相同。舉例:假設當前最大log_id是64,接著某使用者一次轉寄了3件公文,則批量插入的3條流程環節記錄的batch_no都是65。之後另外一個使用者通過某個流程環節轉寄了一件公文,再插入流程環節記錄的batch_id是68。
  ②state欄位用來描述其流程環節所處的狀態,是正待處理,已被處理通過,已被處理駁回,還是超出最長等待時間被系統自動收回等等。通過這個欄位我們對接受使用者發出處理通知,還可以可以很容易的查詢出所有超出最長等待時間被系統自動收回的流程,以便企業管理層在日後商務程序重組(BPR)時參考。
  ③如果某份公文在某個流程中的某個環節被處理駁回,可以看作該公文在此次流程中被駁回至起始點,最初發送使用者可根據處理回複注釋修改公文後重新發送。


  總結:
  企業公文流程自訂應該是把企業內已經固定了的公文轉寄、審批次程序電子化,實現高效的無紙化辦公,對於非正式的口頭討論、商議、集會等商務活動並不適合。當企業累積了一定數量的電子化公文轉寄的記錄後,可以在商業諮詢專家和技術開發人員的協助下對其進行資料採礦,分析出其中的低效、無用環節,進行最佳化重組,最終提高整個企業的競爭力。作為技術開發人員,我們應該根據企業實際運作情況、資金投入規模,選擇當前時期最適合的技術解決方案,切不可為了展示自己的技術實力,而把開發複雜化,企業開發並不是追求技術最先進,而且最適合。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.