2024-07-02|閱讀時間 ‧ 約 28 分鐘

ERP後端 | Django如何快速實作靈活的動態簽核表單(1)

raw-image

流程與節點

公司裡面每一張需要簽核的表單可能會有不一樣的簽核流程(work flow)。而流程中每個節點(work flow node)的簽核對象有可能是特定的使用者或是符合某個部門、某個職位的使用者皆可簽核。

請假表單: 代理人 -> 直屬主管 -> 人資部門

採購表單: 直屬主管 -> 採購部門主管 -> 會計部門

考慮到簽核時需要的各種資料依據,我們在data model的設計上讓各個流程節點設定簽核類型,再根據簽核類型逐一自由設定預定的簽核人員或是簽核部門、簽核組織等等。

流程與節點(db schema)

class WorkFlow(Model):
name = CharField()

class WorkFlowNode(Model):
work_flow = ForeignKey()
category = CharField()
organization = ForeignKey()
department = ForeignKey()
position = ForeignKey()
user = ForeignKey()
name = CharField()
order = PositiveIntegerField()

簽核表單與簽核節點

當一張請假表單被創建時,我們需要找出對應的簽核流程設定,同時為他創建簽核表單(sign form)與多個簽核節點(sign node),每一個簽核節點都會關聯回流程節點,才能在簽核時正確判端下一層要送給誰簽、使用者能不能簽核這張表單並同時紀錄簽核結果以及備註資訊。

簽核表單與簽核節點(db schema)

class SignForm(Model):
objects = Manager()
status = FSMField()
user = ForeignKey()
next_sign_node = ForeignKey()
last_sign_node = ForeignKey()

class SignNode(Model):
sign_form = ForeignKey()
work_flow_node = ForeignKey()
agent = ForeignKey()
signer = ForeignKey()
result = FSMField()
date = DateTimeField()
note = TextField()
level = PositiveIntegerField()

如何動態產生簽核表單

假設我們建了兩個簽核流程(work flow): 請假表單簽核流程、採購表單簽核流程,並各自設定一至多個流程節點(work flow node)。

那當我們建立請假表單(leave form)、採購表單(purchase order)後,如何識別對應的簽核流程來建立簽核表單(sign form)與簽核節點(sign node)? 只好請出我們強大的繼承。

class WorkFlowBaseModel(Model):
sign_form = OneToOneField()
class Meta:
abstract = True

@property
def work_flow_name(self):
raise NotImplementedError("Subclasses must implement this method")

@transaction.atomic
def save(self, *args, **kwargs):
is_new = not self.pk
super(WorkFlowBaseModel, self).save(*args, **kwargs)

if is_new and not self.sign_form:
self.init_work_flow()

def init_work_flow(self):
work_flow_name = self.work_flow_name
work_flow, created = WorkFlow.objects.get_or_create(name=work_flow_name)
work_flow_nodes = work_flow.work_flow_nodes.all()

//建立sign form and sign nodes

先建立一個抽象WorkFlowBaseModel,並且規定所有繼承的子類都必須實作work_flow_name

再來讓請假表單、採購表單繼承並且實作各自的work_flow_name

class LeaveForm(WorkFlowBaseModel):
@property
def work_flow_name(self):
return WorkFlowName.leave

class PurchaseOrder(WorkFlowBaseModel):
@property
def work_flow_name(self):
return WorkFlowName.purchase

再回頭看一下WorkFlowBaseModel定義的save、init_work_flow,會發現已經能夠自動根據子類的work_flow_name找出對應的work_flow、work_flow_nodes囉。

最後只要建立sign form以及sign nodes,並將sign form關聯回請假表單、採購表單,完整的簽核表單就建立完成了。

下一篇我們再來介紹怎麼集中由簽核表單(sign form)處理簽核相關的操作。
分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.