深入理解OpenERP的工作流(Workflow)

一、工作流定義:
<?xml version="1.0"?>
  <terp><data>
    <record model="workflow" id=workflow_id>
    <field name="name">workflow.name</field>
    <field name="osv">resource.model</field>
    <field name="on_create">True | False</field>
  </record>
</data></terp>

model:固定取值"workflow"
id:任意值,唯一標識本工作流
name: 工作流的名稱,任意定義
osv: 本工作流關聯的對象類型,是OpenERP模塊中定義的某對象名,如採購單對象(purchase.order)。是本工作流處理的數據對象。
on_create:每當系統新產生一個osv 中定義的對象的實例時候,是否對應的產生一個和該對象實例關聯的工作流實例。默認是True.

工作流和工作流實例:工作流定義了對某一類型的對象,如採購訂單(PO)的處理流程。例如,PO單的一般處理流程也許是:1)新建PO,State = draft;2)審批PO,審批的同時,a)系統自動產生收貨單,工倉庫收貨;b)系統自動產生憑據(Invoice),供財務確認付款;c)系統自動產生PDF的採購訂單,並自動EMail給該PO單對應的供應商。但對於特定的某個PO對象,需要一個工作流實例,以記錄本PO對象處在流程的哪個階段,如PO1尚在draft狀態,PO2已經審批通過。
PO單的審批,以及對應的a)、b)、c)的動作,都可以在OE的工作流中定義解決,而不需要全編碼在PO對象上。即工作流實現了流程處理相關的代碼和被處理對象的代碼相分離,降低了不同處理代碼的耦合性,增加了系統功能的柔軟性。

二、活動(Activity)定義
<record model="workflow.activity" id="activity_id">
  <field name="wkf_id" ref="workflow_id"/>
  <field name="name">activity.name</field>
  <field name="kind">dummy | function | subflow | stopall</field>
  <field name="subflow_id">subflow_id</field>
  <field name="action">(...)</field>
  <field name="action_id">(...)</field>
  <field name="split_mode">XOR | OR | AND</field>
  <field name="join_mode">XOR | AND</field>
  <field name="signal_send">(...)</field>
  <field name="flow_start">True | False</field>
  <field name="flow_stop">True | False</field>
</record>

model:固定取值workflow.activity
wkf_id:本Activity所屬的工作流id
name: 本Activity名稱,任意值
kind:本Activity類型,有Dummy, Function, Subflow, Stop All 四種。kind說明,如果流程到達本節點,系統應執行的動作類別。
  Dummy 表示不執行任何動作,即action中定義的代碼不會被執行。
  Function 表示執行action中定義的python代碼,且,執行action_id中定義的server action。常見情況是,action中定義一個write方法,修改流程關聯的對象的狀態。對於Function類型的節點,action中定義的代碼或者返回False,或者返回一個客戶端動作id(A client action should be returned)。
  Subflow類型表示觸發“subflow_id”中指定的工作流。仔細的讀者或許要問,工作流的執行總是和某個被處理的對象關聯,是的,如果定義了action,subflow 關聯的對象id 由action中定義的代碼返回。如果沒有定義action,系統默認subflow關聯的對象和本節點所屬的工作流處理的對象id一致。stopall類型表示,流程到此節點則結束,但結束前,系統仍會執行action中的代碼。

signal_send:執行完本節點的動作(action及action_id定義的動作)後,應向別的工作流發往的signal,格式是:subflow.signal。subflow_id和signal_send必須配合使用,subflow_id表示,觸發子工作流subflow_id,在該子工作流中,通常必須定義signal_send,signal_send定義父流程中的某個signal,表示,子流程處理結束後觸發父流程中的信號subflow.signal。注意,用於父子流程通信的工作流signal必須是形如subflow.* 。例如,在HR模塊的workflow "wkf_expenses"中,需要開發票時候,它觸發流程account模塊中的工作流“account.wkf”(<field name="subflow_id" ref="account.wkf"/>)。account.wkf處理完成後,發出信號subflow.paid 通知wkf_expenses流程(<field name="signal_send">subflow.paid</field>)。wkf_expenses中定義了信號subflow.paid(<field name="signal">subflow.paid</field>)。

split_mode:有三個選項,XOR,OR,AND,默認是XOR。XOR 表示,由本節點始發的出遷移中,沿着第一個滿足遷移條件的遷移跳轉。OR 表示由本節點始發的出遷移中,只要滿足遷移條件即沿該遷移跳轉。AND 表示由本節點始發的出遷移中,只有所有遷移皆滿足遷移條件才跳轉,而且是同時沿所有遷移跳轉。XOR 只有一個跳轉,OR 有零或多個跳轉,AND 有零或全部跳轉。
join_mode:有兩個選項,XOR,AND,默認是XOR。XOR 表示,以本節點爲終點的入遷移中,只要有一個跳至本節點,即執行本節點的action。AND 表示,以本節點爲終點的入遷移中,只有所有遷移都已經跳至本節點,才執行本節點的action。
flow_start:表示流程的開始節點。
flow_stop:表示流程的結束節點。

三、遷移(Transition)的定義
遷移的完整 XML 定義格式如下。
<record model="workflow.transition" id="transition_id">
  <field name="act_from" ref="activity_id_1"/>
  <field name="act_to" ref="activity_id_2"/>
  <field name="signal">(...)</field>
  <field name="condition">(...)</field>
  <field name="trigger_model">(...)</field>
  <field name="trigger_expr_id">(...)</field>
</record>

act_from:本遷移的起始節點,引用之前定義的Activity。
act_to:本遷移的結束節點,引用之前定義的Activity。
signal:觸發本遷移的信號,表示,如果系統收到signal定義的信號,則觸發本遷移。觸發信號有三種方式,1)最常見的是用戶點擊視圖中的“name = 本處定義的signal”的button,此時相當於向系統發送遷移信號量。系統會根據視圖中的對象id,找到對象關聯的workflow,再找到與button name相同的signal,觸發之。2)調用workflow_service的方法:trg_validate(self, uid, res_type, res_id, signal, cr),此方法表示,觸發對象類型res_type關聯的workflow的signal信號,工作流實例關聯的對象實例是 res_id。3)子流程的signal_send 發出的信號,此種情況前文已說過。

condition:遷移的條件,是一段Python代碼,通常是一個函數調用。當系統收到signal中定義的信號時候,檢查此處的條件,條件爲真則實際觸發遷移。
trigger_model和trigger_expr_id:此二字段表示啓動一個新工作流實例。trigger_model定義對象類型,trigger_expr_id 定義一段Python代碼,返回trigger_model類型的對象id。此二字段表示,如果act_from 中的action 執行完畢,且condition 條件OK,則系統中插入一個trigger_model類型,trigger_expr_id返回的對象id關聯的工作流實例。然後,可以調用workflow_service的方法trg_trigger(self, uid, res_type, res_id, cr)實際執行該工作流。實際使用例子請參考Sale模塊的工作流定義 wkf_sale:
            <field name="trigger_model">procurement.order</field>

            <field name="trigger_expr_id">procurement_lines_get()</field>



遷移(Transition)的定義漏了權限組group_id,修正如下。表示只有該權限組可以觸發本遷移。
遷移的完整 XML 定義格式如下。
<record model="workflow.transition" id="transition_id">
  <field name="act_from" ref="activity_id_1"/>
  <field name="act_to" ref="activity_id_2"/>
  <field name="group_id" ref="groupid"/>
  <field name="signal">(...)</field>
  <field name="condition">(...)</field>
  <field name="trigger_model">(...)</field>
  <field name="trigger_expr_id">(...)</field>
</record>


上文關於Trigger model和Trigger expr_id的解釋不夠清楚,更清楚的解釋參看鏈接:http://www.openerp.com/forum/post82154.html#p82154
原文部分摘抄如下:

I'll explain here what these two fields do: trigger_model and trigger_expr_id, for people looking for help :
- These fields let you ask for an "evaluation" of the condition when a specific object changed.

For example, suppose you want to set a Sale Order into the state "Done" once it has been shipped. The first the time the condition will be evaluated, it will be False. But later (some days after), we will confirm the shipping order. But our workflow condition is not checked again. Unless you define trigger_model and trigger_expr_id.

- Trigger model: The object type which will trigger an evaluation of your condition.
- Trigger expr_id: A list of model ids which will trigger the condition.

For example, to take the example of our Sale Order, we don't want to check the condition each time a shipping order is confirmed, but only when the shipping order associated to our sale order is confirmed !

Note: You can put a call to a function into trigger_expr_id, like <field name="trigger_expr_id">get_shipping_ids()</field>, or you can directly put a python value (like in my example in the previous post).

WARNING: Currently (OpenERP 6.0) you can only use trigger_model and trigger_expr_id a few objects: account.move.line, procurement.order and stock.move !

發佈了26 篇原創文章 · 獲贊 13 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章