diff --git a/hb_server/apps/inm/models.py b/hb_server/apps/inm/models.py index b48ae3d..20decf8 100644 --- a/hb_server/apps/inm/models.py +++ b/hb_server/apps/inm/models.py @@ -61,9 +61,9 @@ class FIFO(CommonAModel): operator = models.ForeignKey(User, verbose_name='操作人', on_delete=models.CASCADE) subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.DO_NOTHING, null=True, blank=True) -class FIFODetail(CommonAModel): - """ - 领料详细记录 - """ - +# class FIFODetail(CommonAModel): +# """ +# 领料详细记录 +# """ + diff --git a/hb_server/apps/wf/migrations/0015_auto_20211021_1049.py b/hb_server/apps/wf/migrations/0015_auto_20211021_1049.py new file mode 100644 index 0000000..115ffc4 --- /dev/null +++ b/hb_server/apps/wf/migrations/0015_auto_20211021_1049.py @@ -0,0 +1,40 @@ +# Generated by Django 3.2.6 on 2021-10-21 02:49 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0003_auto_20210812_0909'), + ('wf', '0014_wfscript'), + ] + + operations = [ + migrations.AddField( + model_name='state', + name='filter_policy', + field=models.IntegerField(choices=[(0, '无'), (1, '和工单同属一及上级部门'), (2, '和创建人同属一及上级部门'), (3, '和上步处理人同属一及上级部门')], default=0, verbose_name='参与人过滤策略'), + ), + migrations.AddField( + model_name='ticket', + name='belong_dept', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ticket_belong_dept', to='system.organization', verbose_name='所属部门'), + ), + migrations.AlterField( + model_name='state', + name='participant_type', + field=models.IntegerField(blank=True, choices=[(0, '无处理人'), (1, '个人'), (2, '多人'), (3, '部门'), (4, '角色'), (5, '变量'), (6, '脚本'), (7, '工单的字段'), (8, '父工单的字段'), (9, '代码获取')], default=1, help_text='0.无处理人,1.个人,2.多人,3.部门,4.角色,5.变量(支持工单创建人,创建人的leader),6.脚本,7.工单的字段内容(如表单中的"测试负责人",需要为用户名或者逗号隔开的多个用户名),8.父工单的字段内容。 初始状态请选择类型5,参与人填create_by', verbose_name='参与者类型'), + ), + migrations.AlterField( + model_name='ticket', + name='participant_type', + field=models.IntegerField(choices=[(0, '无处理人'), (1, '个人'), (2, '多人'), (3, '部门'), (4, '角色'), (5, '变量'), (6, '脚本'), (7, '工单的字段'), (8, '父工单的字段'), (9, '代码获取')], default=0, help_text='0.无处理人,1.个人,2.多人', verbose_name='当前处理人类型'), + ), + migrations.AlterField( + model_name='ticketflow', + name='participant_type', + field=models.IntegerField(choices=[(0, '无处理人'), (1, '个人'), (2, '多人'), (3, '部门'), (4, '角色'), (5, '变量'), (6, '脚本'), (7, '工单的字段'), (8, '父工单的字段'), (9, '代码获取')], default=0, help_text='0.无处理人,1.个人,2.多人', verbose_name='处理人类型'), + ), + ] diff --git a/hb_server/apps/wf/models.py b/hb_server/apps/wf/models.py index 877165c..6592d49 100644 --- a/hb_server/apps/wf/models.py +++ b/hb_server/apps/wf/models.py @@ -1,3 +1,4 @@ +from random import choice from django.db import models from django.db.models.base import Model import django.utils.timezone as timezone @@ -66,6 +67,13 @@ class State(CommonAModel): STATE_FIELD_READONLY= 1 # 字段只读 STATE_FIELD_REQUIRED = 2 # 字段必填 STATE_FIELD_OPTIONAL = 3 # 字段可选 + + state_filter_choices=( + (0, '无'), + (1, '和工单同属一及上级部门'), + (2, '和创建人同属一及上级部门'), + (3, '和上步处理人同属一及上级部门'), + ) name = models.CharField('名称', max_length=50) workflow = models.ForeignKey(Workflow, on_delete=models.CASCADE, verbose_name='所属工作流') is_hidden = models.BooleanField('是否隐藏', default=False, help_text='设置为True时,获取工单步骤api中不显示此状态(当前处于此状态时除外)') @@ -76,6 +84,7 @@ class State(CommonAModel): participant = models.JSONField('参与者', default=list, blank=True, help_text='可以为空(无处理人的情况,如结束状态)、userid、userid列表\部门id\角色id\变量(create_by,create_by_tl)\脚本记录的id等,包含子工作流的需要设置处理人为loonrobot') state_fields = models.JSONField('表单字段', default=dict, help_text='json格式字典存储,包括读写属性1:只读,2:必填,3:可选. 示例:{"create_time":1,"title":2, "sn":1}, 内置特殊字段participant_info.participant_name:当前处理人信息(部门名称、角色名称),state.state_name:当前状态的状态名,workflow.workflow_name:工作流名称') # json格式存储,包括读写属性1:只读,2:必填,3:可选,4:不显示, 字典的字典 distribute_type = models.IntegerField('分配方式', default=1, choices=state_distribute_choices, help_text='1.主动接单(如果当前处理人实际为多人的时候,需要先接单才能处理) 2.直接处理(即使当前处理人实际为多人,也可以直接处理) 3.随机分配(如果实际为多人,则系统会随机分配给其中一个人) 4.全部处理(要求所有参与人都要处理一遍,才能进入下一步)') + filter_policy = models.IntegerField('参与人过滤策略', default=0, choices=state_filter_choices) class Transition(CommonAModel): """ @@ -157,7 +166,7 @@ class CustomField(CommonAModel): help_text='radio,checkbox,select,multiselect类型可供选择的选项,格式为json如:{"1":"中国", "2":"美国"},注意数字也需要引号') label = models.JSONField('标签', blank=True, default=dict, help_text='自定义标签,json格式,调用方可根据标签自行处理特殊场景逻辑,loonflow只保存文本内容') -class Ticket(CommonAModel): +class Ticket(CommonBModel): """ 工单 """ @@ -211,7 +220,6 @@ class TicketFlow(BaseModel): ticket_data = models.JSONField('工单数据', default=dict, blank=True, help_text='可以用于记录当前表单数据,json格式') intervene_type = models.IntegerField('干预类型', default=0, help_text='流转类型', choices=Transition.intervene_type_choices) - class WfScript(CommonAModel): """ 执行脚本 diff --git a/hb_server/apps/wf/services.py b/hb_server/apps/wf/services.py index c27dab8..9acdcce 100644 --- a/hb_server/apps/wf/services.py +++ b/hb_server/apps/wf/services.py @@ -124,7 +124,7 @@ class WfService(object): return destination_state @classmethod - def get_ticket_state_participant_info(cls, state:State, ticket:Ticket, ticket_data:dict={}): + def get_ticket_state_participant_info(cls, state:State, ticket:Ticket, ticket_data:dict={}, request={}): """ 获取工单目标状态实际的处理人, 处理人类型 """ @@ -151,11 +151,21 @@ class WfService(object): destination_participant = list(User.objects.filter(dept=destination_participant).values_list('id', flat=True)) elif destination_participant_type == State.PARTICIPANT_TYPE_ROLE:#单角色 - destination_participant = list(User.objects.filter(roles=destination_participant).values_list('id', flat=True)) - + user_queryset = User.objects.filter(roles=destination_participant) + # 如果选择了角色, 需要走过滤策略 + if ticket.filter_policy == 1: + user_queryset = user_queryset.filter(dept=ticket.belong_dept) + elif ticket.filter_policy == 2: + user_queryset = user_queryset.filter(dept=ticket.create_by.dept) + elif ticket.filter_policy == 3: + user_queryset = user_queryset.filter(dept=request.user.dept) + destination_participant = list(user_queryset.values_list('id', flat=True)) if type(destination_participant) == list: destination_participant_type = State.PARTICIPANT_TYPE_MULTI destination_participant = list(set(destination_participant)) + if len(destination_participant) == 1: # 如果只有一个人 + destination_participant_type = State.PARTICIPANT_TYPE_PERSONAL + destination_participant = destination_participant[0] else: destination_participant_type = State.PARTICIPANT_TYPE_PERSONAL if destination_participant_type == State.PARTICIPANT_TYPE_MULTI: diff --git a/hb_server/apps/wf/views.py b/hb_server/apps/wf/views.py index 67e3a12..1025505 100644 --- a/hb_server/apps/wf/views.py +++ b/hb_server/apps/wf/views.py @@ -134,7 +134,7 @@ class TicketViewSet(OptimizationMixin, CreateUpdateCustomMixin, CreateModelMixin if value == State.STATE_FIELD_REQUIRED: if key not in ticket_data or not ticket_data[key]: raise APIException('字段{}必填'.format(key)) - ticket = serializer.save(state=start_state, create_by=request.user, act_state=Ticket.TICKET_ACT_STATE_DRAFT) # 先创建出来 + ticket = serializer.save(state=start_state, create_by=request.user, act_state=Ticket.TICKET_ACT_STATE_DRAFT, belong_dept=request.user.dept) # 先创建出来 next_state = WfService.get_next_state_by_transition_and_ticket_info(ticket=ticket, transition=transition) participant_info = WfService.get_ticket_state_participant_info(state=next_state, ticket=ticket, ticket_data=ticket.ticket_data) destination_participant_type = participant_info.get('destination_participant_type', 0) @@ -202,7 +202,7 @@ class TicketViewSet(OptimizationMixin, CreateUpdateCustomMixin, CreateModelMixin if value == State.STATE_FIELD_REQUIRED: if key not in ticket_data or not ticket_data[key]: raise APIException('字段{}必填'.format(key)) - destination_state = WfService.get_next_state_by_transition_and_ticket_info(ticket, transition, ticket_data) + destination_state = WfService.get_next_state_by_transition_and_ticket_info(ticket, transition, ticket_data, request) multi_all_person = ticket.multi_all_person if multi_all_person: multi_all_person[request.user.id] =dict(transition=transition.id)