forked from erp-dev/erp
feat: new modul (stateflow)
This commit is contained in:
@@ -1,3 +1,159 @@
|
||||
from django.db import models
|
||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from flower.common import ModelBase
|
||||
from typing import List
|
||||
|
||||
# Create your models here.
|
||||
|
||||
class State(ModelBase):
|
||||
"""State model representing a state in a stateflow diagram."""
|
||||
name = models.CharField(max_length=100, verbose_name='状态名称')
|
||||
# previous = models.ForeignKey('self', null=True, blank=True, on_delete=models.SET_NULL, verbose_name='上一级状态')
|
||||
description = models.CharField(max_length=200, blank=True, verbose_name='状态描述')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def add_additional_params(self, params: dict):
|
||||
"""Add additional parameters to the state's data field."""
|
||||
if not self.data:
|
||||
self.data = {}
|
||||
self.data.update(params)
|
||||
self.save()
|
||||
|
||||
def get_additional_params(self) -> dict:
|
||||
"""Retrieve additional parameters from the state's data field."""
|
||||
return self.data if self.data else {}
|
||||
|
||||
class Meta:
|
||||
verbose_name = '流程节点'
|
||||
verbose_name_plural = '流程节点'
|
||||
|
||||
|
||||
class StateParameter(ModelBase):
|
||||
"""StateParameter model representing parameters associated with a state."""
|
||||
state = models.ForeignKey(State, on_delete=models.PROTECT, related_name='parameters', verbose_name='关联参数')
|
||||
key = models.CharField(max_length=100, verbose_name='参数键')
|
||||
value = models.CharField(max_length=200, verbose_name='参数值')
|
||||
description = models.CharField(max_length=200, blank=True, verbose_name='参数描述')
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.state.name} - {self.key}"
|
||||
|
||||
class Meta:
|
||||
verbose_name = '工艺参数'
|
||||
verbose_name_plural = '工艺参数'
|
||||
|
||||
|
||||
class Process(ModelBase):
|
||||
"""Process model representing a stateflow process template."""
|
||||
name = models.CharField(max_length=100, verbose_name='流程名称')
|
||||
state_nodes = models.ManyToManyField(
|
||||
State,
|
||||
through='ProcessNode',
|
||||
related_name='processes',
|
||||
verbose_name='节点列表',
|
||||
)
|
||||
description = models.TextField(blank=True, verbose_name='流程描述')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def replace_nodes(self, nodes: List[State]):
|
||||
"""Replace all nodes with new ordered list."""
|
||||
# 清空现有节点后按照传入顺序重建
|
||||
self.process_nodes.all().delete()
|
||||
for order, node in enumerate(nodes):
|
||||
ProcessNode.objects.create(process=self, state=node, order=order)
|
||||
|
||||
def get_nodes(self) -> List[State]:
|
||||
"""Retrieve the list of state nodes as State instances."""
|
||||
process_nodes = self.process_nodes.select_related('state').order_by('order', 'id')
|
||||
return [item.state for item in process_nodes]
|
||||
|
||||
class Meta:
|
||||
verbose_name = '印染流程'
|
||||
verbose_name_plural = '印染流程'
|
||||
|
||||
|
||||
class ProcessNode(ModelBase):
|
||||
"""Intermediate model describing ordered relation between Process and State."""
|
||||
process = models.ForeignKey(Process, on_delete=models.CASCADE, related_name='process_nodes', verbose_name='流程')
|
||||
state = models.ForeignKey(State, on_delete=models.PROTECT, related_name='state_process_nodes', verbose_name='节点')
|
||||
order = models.PositiveIntegerField(default=0, verbose_name='顺序')
|
||||
|
||||
class Meta:
|
||||
verbose_name = '流程节点关联'
|
||||
verbose_name_plural = '流程节点关联'
|
||||
ordering = ['order', 'id']
|
||||
unique_together = ('process', 'order')
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.process.name} -> {self.state.name} ({self.order})"
|
||||
|
||||
|
||||
class BusinessObject(ModelBase):
|
||||
"""业务对象 - 代表流程的一个实例,通过日志跟踪进度"""
|
||||
name = models.CharField(max_length=100, verbose_name='业务对象名称')
|
||||
process = models.ForeignKey(Process, on_delete=models.PROTECT, related_name='business_objects', verbose_name='关联流程')
|
||||
description = models.TextField(blank=True, verbose_name='描述')
|
||||
|
||||
# GenericForeignKey - 关联到任意模型(可选)
|
||||
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, null=True, blank=True, verbose_name='关联对象类型')
|
||||
object_id = models.PositiveIntegerField(null=True, blank=True, verbose_name='关联对象ID')
|
||||
content_object = GenericForeignKey('content_type', 'object_id')
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} ({self.process.name})"
|
||||
|
||||
def get_current_state(self) -> 'State':
|
||||
"""获取当前状态(通过services推导)"""
|
||||
from . import services
|
||||
return services.get_business_object_current_state(self)
|
||||
|
||||
def get_completed_node_ids(self) -> List[int]:
|
||||
"""获取已完成的节点ID列表"""
|
||||
from . import services
|
||||
return services.get_completed_node_ids(self)
|
||||
|
||||
def get_current_parameters(self) -> List['StateParameter']:
|
||||
"""获取当前状态的参数"""
|
||||
from . import services
|
||||
return services.get_current_state_parameters(self)
|
||||
|
||||
def get_progress_percentage(self) -> float:
|
||||
"""计算进度百分比"""
|
||||
from . import services
|
||||
return services.get_progress_percentage(self)
|
||||
|
||||
def get_state_status(self, state: 'State') -> str:
|
||||
"""获取指定状态的状态"""
|
||||
from . import services
|
||||
return services.get_business_object_state_status(self, state)
|
||||
|
||||
def get_timeline(self) -> List[dict]:
|
||||
"""获取状态时间线"""
|
||||
from . import services
|
||||
return services.get_business_object_state_timeline(self)
|
||||
|
||||
class Meta:
|
||||
db_table = 'business_object'
|
||||
verbose_name = '业务对象'
|
||||
verbose_name_plural = '业务对象'
|
||||
|
||||
|
||||
class StateFlowRecord(ModelBase):
|
||||
"""状态流转记录"""
|
||||
business_object = models.ForeignKey(BusinessObject, on_delete=models.CASCADE, related_name='state_logs', verbose_name='业务对象')
|
||||
state = models.ForeignKey(State, on_delete=models.CASCADE, verbose_name='状态')
|
||||
completed_at = models.DateTimeField(auto_now_add=True, verbose_name='完成时间')
|
||||
completed_by = models.ForeignKey('auth.User', on_delete=models.SET_NULL, null=True, verbose_name='操作人')
|
||||
cancelled_at = models.DateTimeField(null=True, blank=True, verbose_name='撤销时间')
|
||||
is_cancelled = models.BooleanField(default=False, verbose_name='是否已撤销')
|
||||
|
||||
class Meta:
|
||||
db_table = 'state_flow_record'
|
||||
verbose_name = '状态流转记录'
|
||||
verbose_name_plural = '状态流转记录'
|
||||
unique_together = [['business_object', 'state']]
|
||||
ordering = ['completed_at']
|
||||
|
||||
Reference in New Issue
Block a user