From ff47f66463b323c99f1117caa07b196986951748 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 27 Aug 2021 16:20:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=A5=E8=89=BA=E6=B5=81=E7=A8=8B=E5=AD=98js?= =?UTF-8?q?on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_client/.env.production | 2 +- .../migrations/0002_stepoperationitem_sort.py | 18 +++++ .../mtm/migrations/0003_auto_20210827_1604.py | 22 ++++++ hb_server/apps/mtm/models.py | 2 +- hb_server/apps/mtm/serializers.py | 28 +++++-- hb_server/apps/mtm/views.py | 23 +++--- .../wf/migrations/0007_auto_20210827_1103.py | 76 +++++++++++++++++++ .../wf/migrations/0008_auto_20210827_1104.py | 26 +++++++ hb_server/apps/wf/models.py | 16 ++-- hb_server/apps/wf/serializers.py | 4 + hb_server/apps/wf/services.py | 14 ++-- hb_server/apps/wf/views.py | 43 ++++++++--- 12 files changed, 232 insertions(+), 42 deletions(-) create mode 100644 hb_server/apps/mtm/migrations/0002_stepoperationitem_sort.py create mode 100644 hb_server/apps/mtm/migrations/0003_auto_20210827_1604.py create mode 100644 hb_server/apps/wf/migrations/0007_auto_20210827_1103.py create mode 100644 hb_server/apps/wf/migrations/0008_auto_20210827_1104.py diff --git a/hb_client/.env.production b/hb_client/.env.production index 8994f69..484e806 100644 --- a/hb_client/.env.production +++ b/hb_client/.env.production @@ -2,5 +2,5 @@ ENV = 'production' # base api -VUE_APP_BASE_API = '' +VUE_APP_BASE_API = 'http://47.95.0.242:2222/api' diff --git a/hb_server/apps/mtm/migrations/0002_stepoperationitem_sort.py b/hb_server/apps/mtm/migrations/0002_stepoperationitem_sort.py new file mode 100644 index 0000000..73e98f2 --- /dev/null +++ b/hb_server/apps/mtm/migrations/0002_stepoperationitem_sort.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.6 on 2021-08-27 02:43 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='stepoperationitem', + name='sort', + field=models.IntegerField(default=1, verbose_name='排序号'), + ), + ] diff --git a/hb_server/apps/mtm/migrations/0003_auto_20210827_1604.py b/hb_server/apps/mtm/migrations/0003_auto_20210827_1604.py new file mode 100644 index 0000000..470e16b --- /dev/null +++ b/hb_server/apps/mtm/migrations/0003_auto_20210827_1604.py @@ -0,0 +1,22 @@ +# Generated by Django 3.2.6 on 2021-08-27 08:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0002_stepoperationitem_sort'), + ] + + operations = [ + migrations.RemoveField( + model_name='material', + name='process', + ), + migrations.AddField( + model_name='material', + name='processes', + field=models.JSONField(blank=True, default=list, verbose_name='工艺流程'), + ), + ] diff --git a/hb_server/apps/mtm/models.py b/hb_server/apps/mtm/models.py index df7a7ec..7012f3f 100644 --- a/hb_server/apps/mtm/models.py +++ b/hb_server/apps/mtm/models.py @@ -19,7 +19,7 @@ class Material(CommonAModel): number = models.CharField('编号', max_length=100, unique=True) type = models.CharField('物料类型', choices= type_choices, max_length=20, default=1) sort_str = models.CharField('排序字符', max_length=100, null=True, blank=True) - process = models.ManyToManyField('mtm.process', through='mtm.ProductProcess', related_name='product_process') + processes = models.JSONField('工艺流程', default=list, blank=True) class Meta: verbose_name = '物料表' diff --git a/hb_server/apps/mtm/serializers.py b/hb_server/apps/mtm/serializers.py index 60fe1c8..a2b531a 100644 --- a/hb_server/apps/mtm/serializers.py +++ b/hb_server/apps/mtm/serializers.py @@ -1,43 +1,55 @@ -from rest_framework.serializers import ModelSerializer +from rest_framework import serializers from .models import Material, Process, ProductProcess, Step from apps.system.serializers import FileSimpleSerializer -class MaterialSerializer(ModelSerializer): +class MaterialSerializer(serializers.ModelSerializer): + processes = serializers.ListField(child=serializers.IntegerField(min_value=1)) class Meta: model = Material fields = '__all__' -class MaterialSimpleSerializer(ModelSerializer): +class MaterialDetailSerializer(serializers.ModelSerializer): + processes_ = serializers.SerializerMethodField() + class Meta: + model = Material + fields = '__all__' + + def get_processes_(self, obj): + objs = Process.objects.filter(id__in=obj.processes) + return ProcessSimpleSerializer(instance=objs, many=True).data + + +class MaterialSimpleSerializer(serializers.ModelSerializer): class Meta: model = Material fields = ['id', 'name', 'number'] -class ProcessSerializer(ModelSerializer): +class ProcessSerializer(serializers.ModelSerializer): instruction_ = FileSimpleSerializer(source='instruction', read_only=True) class Meta: model = Process fields = '__all__' -class ProcessSimpleSerializer(ModelSerializer): +class ProcessSimpleSerializer(serializers.ModelSerializer): class Meta: model = Process fields = ['id', 'name', 'number'] -class StepSerializer(ModelSerializer): +class StepSerializer(serializers.ModelSerializer): class Meta: model = Step fields = '__all__' -class ProductProcessListSerializer(ModelSerializer): +class ProductProcessListSerializer(serializers.ModelSerializer): process_ = ProcessSimpleSerializer(source='process', read_only=True) product_ = MaterialSimpleSerializer(source='product', read_only=True) class Meta: model = ProductProcess fields = '__all__' -class ProductProcessUpdateSerializer(ModelSerializer): +class ProductProcessUpdateSerializer(serializers.ModelSerializer): class Meta: model = ProductProcess fields = ['sort'] \ No newline at end of file diff --git a/hb_server/apps/mtm/views.py b/hb_server/apps/mtm/views.py index f1510cb..fc7c922 100644 --- a/hb_server/apps/mtm/views.py +++ b/hb_server/apps/mtm/views.py @@ -3,7 +3,7 @@ from rest_framework.viewsets import ModelViewSet, GenericViewSet from rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin from apps.mtm.models import Material, Process, ProductProcess, Step -from apps.mtm.serializers import MaterialSerializer, ProductProcessListSerializer, ProductProcessUpdateSerializer, ProcessSerializer, StepSerializer +from apps.mtm.serializers import MaterialDetailSerializer, MaterialSerializer, MaterialSimpleSerializer, ProductProcessListSerializer, ProductProcessUpdateSerializer, ProcessSerializer, StepSerializer from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin from rest_framework.decorators import action from rest_framework.response import Response @@ -24,14 +24,19 @@ class MaterialViewSet(PageOrNot, CreateUpdateModelAMixin, ModelViewSet): ordering_fields = ['number', 'sort_str'] ordering = ['number'] - @action(methods=['get'], detail=True, perms_map={'get':'*'}, pagination_class=None, serializer_class=StepSerializer) - def steps(self, request, pk=None): - """ - 工序下的子工序 - """ - process = self.get_object() - serializer = self.serializer_class(instance=Step.objects.filter(process=process, is_deleted=False), many=True) - return Response(serializer.data) + def get_serializer_class(self, *args, **kwargs): + if self.action == 'retrieve': + return MaterialDetailSerializer + return MaterialSerializer + + # @action(methods=['get'], detail=True, perms_map={'get':'*'}, pagination_class=None, serializer_class=MaterialSimpleSerializer) + # def processes(self, request, pk=None): + # """ + # 产品生产工艺流程 + # """ + # material = self.get_object() + # serializer = self.serializer_class(instance=Process.objects.filter(id__in=material.processes), many=True) + # return Response(serializer.data) class ProcessViewSet(PageOrNot, CreateUpdateModelAMixin, ModelViewSet): diff --git a/hb_server/apps/wf/migrations/0007_auto_20210827_1103.py b/hb_server/apps/wf/migrations/0007_auto_20210827_1103.py new file mode 100644 index 0000000..a10b7ae --- /dev/null +++ b/hb_server/apps/wf/migrations/0007_auto_20210827_1103.py @@ -0,0 +1,76 @@ +# Generated by Django 3.2.6 on 2021-08-27 03:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wf', '0006_auto_20210825_1542'), + ] + + operations = [ + migrations.RemoveField( + model_name='ticket', + name='add_node_man', + ), + migrations.RemoveField( + model_name='ticketflow', + name='participant', + ), + migrations.AddField( + model_name='state', + name='distribute_type', + field=models.IntegerField(choices=[(1, '主动接单'), (2, '直接处理'), (3, '随机分配'), (4, '全部处理')], default=1, help_text='1.主动接单(如果当前处理人实际为多人的时候,需要先接单才能处理) 2.直接处理(即使当前处理人实际为多人,也可以直接处理) 3.随机分配(如果实际为多人,则系统会随机分配给其中一个人) 4.全部处理(要求所有参与人都要处理一遍,才能进入下一步)', verbose_name='分配方式'), + ), + migrations.AddField( + model_name='state', + name='participant', + field=models.JSONField(blank=True, default=list, help_text='可以为空(无处理人的情况,如结束状态)、userid、userid列表\\部门id\\角色id\\变量(create_by,create_by_tl)\\脚本记录的id等,包含子工作流的需要设置处理人为loonrobot', verbose_name='参与者'), + ), + migrations.AddField( + model_name='ticket', + name='act_state', + field=models.IntegerField(choices=[(0, '草稿中'), (1, '进行中'), (2, '被退回'), (3, '被撤回'), (4, '已完成'), (5, '已关闭')], default=1, help_text='当前工单的进行状态', verbose_name='进行状态'), + ), + migrations.AddField( + model_name='ticket', + name='multi_all_person', + field=models.JSONField(blank=True, default=dict, help_text='需要当前状态处理人全部处理时实际的处理结果,json格式', verbose_name='全部处理的结果'), + ), + migrations.AddField( + model_name='ticket', + name='participant', + field=models.JSONField(blank=True, default=list, help_text='可以为空(无处理人的情况,如结束状态)、userid、userid列表', verbose_name='当前处理人'), + ), + migrations.AddField( + model_name='ticket', + name='participant_type', + field=models.IntegerField(choices=[(0, '无处理人'), (1, '个人'), (2, '多人'), (3, '部门'), (4, '角色'), (5, '变量'), (6, '脚本'), (7, '工单的字段'), (8, '父工单的字段')], default=0, help_text='0.无处理人,1.个人,2.多人', verbose_name='当前处理人类型'), + ), + migrations.AddField( + model_name='workflow', + name='sn_prefix', + field=models.CharField(default='hb', max_length=50, 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, '父工单的字段')], default=1, help_text='0.无处理人,1.个人,2.多人,3.部门,4.角色,5.变量(支持工单创建人,创建人的leader),6.脚本,7.工单的字段内容(如表单中的"测试负责人",需要为用户名或者逗号隔开的多个用户名),8.父工单的字段内容。 初始状态请选择类型5,参与人填create_by', verbose_name='参与者类型'), + ), + migrations.AlterField( + model_name='state', + name='type', + field=models.IntegerField(choices=[(0, '普通'), (1, '开始'), (2, '结束')], default=0, help_text='0.普通类型 1.初始状态(用于新建工单时,获取对应的字段必填及transition信息) 2.结束状态(此状态下的工单不得再处理,即没有对应的transition)', verbose_name='状态类型'), + ), + migrations.AlterField( + model_name='workflow', + name='display_form_str', + field=models.JSONField(blank=True, default=list, help_text='默认"[]",用于用户只有对应工单查看权限时显示哪些字段,field_key的list的json,如["days","sn"],内置特殊字段participant_info.participant_name:当前处理人信息(部门名称、角色名称),state.state_name:当前状态的状态名,workflow.workflow_name:工作流名称', verbose_name='展现表单字段'), + ), + migrations.AlterField( + model_name='workflow', + name='limit_expression', + field=models.JSONField(blank=True, default=dict, help_text='限制周期({"period":24} 24小时), 限制次数({"count":1}在限制周期内只允许提交1次), 限制级别({"level":1} 针对(1单个用户 2全局)限制周期限制次数,默认特定用户);允许特定人员提交({"allow_persons":"zhangsan,lisi"}只允许张三提交工单,{"allow_depts":"1,2"}只允许部门id为1和2的用户提交工单,{"allow_roles":"1,2"}只允许角色id为1和2的用户提交工单)', verbose_name='限制表达式'), + ), + ] diff --git a/hb_server/apps/wf/migrations/0008_auto_20210827_1104.py b/hb_server/apps/wf/migrations/0008_auto_20210827_1104.py new file mode 100644 index 0000000..fe1e449 --- /dev/null +++ b/hb_server/apps/wf/migrations/0008_auto_20210827_1104.py @@ -0,0 +1,26 @@ +# Generated by Django 3.2.6 on 2021-08-27 03:04 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('wf', '0007_auto_20210827_1103'), + ] + + operations = [ + migrations.AddField( + model_name='ticket', + name='add_node_man', + field=models.ForeignKey(blank=True, help_text='加签操作的人,工单当前处理人处理完成后会回到该处理人,当处于加签状态下才有效', null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='加签人'), + ), + migrations.AddField( + model_name='ticketflow', + name='participant', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='处理人'), + ), + ] diff --git a/hb_server/apps/wf/models.py b/hb_server/apps/wf/models.py index bf60399..7c5e313 100644 --- a/hb_server/apps/wf/models.py +++ b/hb_server/apps/wf/models.py @@ -12,11 +12,11 @@ class Workflow(CommonAModel): 工作流 """ name = models.CharField('名称', max_length=50) - sn_prefix = models.CharField('流水号前缀', max_length=50) + sn_prefix = models.CharField('流水号前缀', max_length=50, default='hb') description = models.CharField('描述', max_length=200) view_permission_check = models.BooleanField('查看权限校验', default=True, help_text='开启后,只允许工单的关联人(创建人、曾经的处理人)有权限查看工单') - limit_expression = models.JSONField('限制表达式', max_length=1000, default=dict, blank=True, help_text='限制周期({"period":24} 24小时), 限制次数({"count":1}在限制周期内只允许提交1次), 限制级别({"level":1} 针对(1单个用户 2全局)限制周期限制次数,默认特定用户);允许特定人员提交({"allow_persons":"zhangsan,lisi"}只允许张三提交工单,{"allow_depts":"1,2"}只允许部门id为1和2的用户提交工单,{"allow_roles":"1,2"}只允许角色id为1和2的用户提交工单)') - display_form_str = models.JSONField('展现表单字段', max_length=10000, default=list, blank=True, help_text='默认"[]",用于用户只有对应工单查看权限时显示哪些字段,field_key的list的json,如["days","sn"],内置特殊字段participant_info.participant_name:当前处理人信息(部门名称、角色名称),state.state_name:当前状态的状态名,workflow.workflow_name:工作流名称') + limit_expression = models.JSONField('限制表达式', default=dict, blank=True, help_text='限制周期({"period":24} 24小时), 限制次数({"count":1}在限制周期内只允许提交1次), 限制级别({"level":1} 针对(1单个用户 2全局)限制周期限制次数,默认特定用户);允许特定人员提交({"allow_persons":"zhangsan,lisi"}只允许张三提交工单,{"allow_depts":"1,2"}只允许部门id为1和2的用户提交工单,{"allow_roles":"1,2"}只允许角色id为1和2的用户提交工单)') + display_form_str = models.JSONField('展现表单字段', default=list, blank=True, help_text='默认"[]",用于用户只有对应工单查看权限时显示哪些字段,field_key的list的json,如["days","sn"],内置特殊字段participant_info.participant_name:当前处理人信息(部门名称、角色名称),state.state_name:当前状态的状态名,workflow.workflow_name:工作流名称') title_template = models.CharField('标题模板', max_length=50, default='你有一个待办工单:{title}', null=True, blank=True, help_text='工单字段的值可以作为参数写到模板中,格式如:你有一个待办工单:{title}') content_template = models.CharField('内容模板', max_length=1000, default='标题:{title}, 创建时间:{create_time}', null=True, blank=True, help_text='工单字段的值可以作为参数写到模板中,格式如:标题:{title}, 创建时间:{create_time}') @@ -60,6 +60,10 @@ class State(CommonAModel): (STATE_DISTRIBUTE_TYPE_RANDOM, '随机分配'), (STATE_DISTRIBUTE_TYPE_ALL, '全部处理'), ) + + STATE_FIELD_READONLY= 1 # 字段只读 + STATE_FIELD_REQUIRED = 2 # 字段必填 + STATE_FIELD_OPTIONAL = 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中不显示此状态(当前处于此状态时除外)') @@ -69,7 +73,7 @@ class State(CommonAModel): participant_type = models.IntegerField('参与者类型', choices=type2_choices, default=1, blank=True, help_text='0.无处理人,1.个人,2.多人,3.部门,4.角色,5.变量(支持工单创建人,创建人的leader),6.脚本,7.工单的字段内容(如表单中的"测试负责人",需要为用户名或者逗号隔开的多个用户名),8.父工单的字段内容。 初始状态请选择类型5,参与人填create_by') 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:可选. 示例:{"created_at":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, help_text='1.主动接单(如果当前处理人实际为多人的时候,需要先接单才能处理) 2.直接处理(即使当前处理人实际为多人,也可以直接处理) 3.随机分配(如果实际为多人,则系统会随机分配给其中一个人) 4.全部处理(要求所有参与人都要处理一遍,才能进入下一步)') + distribute_type = models.IntegerField('分配方式', default=1, choices=state_distribute_choices, help_text='1.主动接单(如果当前处理人实际为多人的时候,需要先接单才能处理) 2.直接处理(即使当前处理人实际为多人,也可以直接处理) 3.随机分配(如果实际为多人,则系统会随机分配给其中一个人) 4.全部处理(要求所有参与人都要处理一遍,才能进入下一步)') class Transition(CommonAModel): """ @@ -150,7 +154,7 @@ class Ticket(CommonAModel): parent_state = models.ForeignKey(State, null=True, blank=True, on_delete=models.CASCADE, verbose_name='父工单状态', related_name='ticket_parent_state') ticket_data = models.JSONField('工单数据', default=dict, help_text='工单所有字段内容') in_add_node = models.BooleanField('加签状态中', default=False, help_text='是否处于加签状态下') - add_node_man = models.CharField('加签人', max_length=50, default='', blank=True, help_text='加签操作的人,工单当前处理人处理完成后会回到该处理人,当处于加签状态下才有效') + add_node_man = models.ForeignKey(User, verbose_name='加签人', on_delete=models.SET_NULL, null=True, blank=True, help_text='加签操作的人,工单当前处理人处理完成后会回到该处理人,当处于加签状态下才有效') participant_type = models.IntegerField('当前处理人类型', default=0, help_text='0.无处理人,1.个人,2.多人', choices=State.type2_choices) participant = models.JSONField('当前处理人', default=list, blank=True, help_text='可以为空(无处理人的情况,如结束状态)、userid、userid列表') @@ -164,6 +168,6 @@ class TicketFlow(BaseModel): ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE, verbose_name='关联工单') transition = models.ForeignKey(Transition, verbose_name='流转id', help_text='与worklow.Transition关联, 为0时表示认为干预的操作', on_delete=models.CASCADE) suggestion = models.CharField('处理意见', max_length=10000, default='', blank=True) - participant = models.CharField('处理人', max_length=50, default='', blank=True) + participant = models.ForeignKey(User, verbose_name='处理人', on_delete=models.SET_NULL, null=True, blank=True) state = models.ForeignKey(State, verbose_name='当前状态', default=0, blank=True, on_delete=models.CASCADE) ticket_data = models.JSONField('工单数据', default=dict, blank=True, help_text='可以用于记录当前表单数据,json格式') \ No newline at end of file diff --git a/hb_server/apps/wf/serializers.py b/hb_server/apps/wf/serializers.py index dc7ed0a..d4ca696 100644 --- a/hb_server/apps/wf/serializers.py +++ b/hb_server/apps/wf/serializers.py @@ -48,6 +48,10 @@ class TicketCreateSerializer(serializers.ModelSerializer): class Meta: model=Ticket fields=['title','workflow','ticket_data', 'transition'] + + def create(self, validated_data): + validated_data.pop('transition') + return super().create(validated_data) class TicketSerializer(serializers.ModelSerializer): workflow_ = WorkflowSimpleSerializer(source='workflow', read_only=True) diff --git a/hb_server/apps/wf/services.py b/hb_server/apps/wf/services.py index 8e4cc0f..1fd04dc 100644 --- a/hb_server/apps/wf/services.py +++ b/hb_server/apps/wf/services.py @@ -114,26 +114,26 @@ class WfService(object): 回到初始状态 """ return dict(destination_participant_type=State.PARTICIPANT_TYPE_PERSONAL, - destination_participant=ticket.create_by, - multi_all_person=dict()) + destination_participant=ticket.create_by.id, + multi_all_person={}) elif state.type == State.STATE_TYPE_END: """ 到达结束状态 """ return dict(destination_participant_type=State.PARTICIPANT_TYPE_PERSONAL, - destination_participant='', - multi_all_person=dict()) + destination_participant=None, + multi_all_person={}) multi_all_person_dict = {} destination_participant_type, destination_participant = State.participant_type, State.participant if destination_participant_type == State.PARTICIPANT_TYPE_FIELD: - destination_participant = ticket_data.get(destination_participant, '') if destination_participant in ticket_data else Ticket.ticket_data.get(destination_participant, '') + destination_participant = ticket_data.get(destination_participant, None) if destination_participant in ticket_data else Ticket.ticket_data.get(destination_participant, None) if destination_participant_type == State.PARTICIPANT_TYPE_DEPT:#单部门 - destination_participant = User.objects.filter(dept=destination_participant).values_list('id') + destination_participant = list(User.objects.filter(dept=destination_participant).values_list('id', flat=True)) if destination_participant_type == State.PARTICIPANT_TYPE_ROLE:#单角色 - destination_participant = User.objects.filter(roles=destination_participant).values_list('id') + destination_participant = list(User.objects.filter(roles=destination_participant).values_list('id', flat=True)) if type(destination_participant) == list: destination_participant_type = State.PARTICIPANT_TYPE_MULTI diff --git a/hb_server/apps/wf/views.py b/hb_server/apps/wf/views.py index 1702059..d629edc 100644 --- a/hb_server/apps/wf/views.py +++ b/hb_server/apps/wf/views.py @@ -5,7 +5,7 @@ from apps.wf.serializers import CustomFieldSerializer, StateSerializer, TicketCr from django.shortcuts import render from rest_framework.viewsets import GenericViewSet, ModelViewSet from rest_framework.decorators import action, api_view -from apps.wf.models import CustomField, Ticket, Workflow, State, Transition +from apps.wf.models import CustomField, Ticket, Workflow, State, Transition, TicketFlow from apps.system.mixins import CreateUpdateCustomMixin, CreateUpdateModelAMixin, OptimizationMixin from apps.wf.services import WfService from rest_framework.exceptions import APIException @@ -104,27 +104,50 @@ class TicketViewSet(OptimizationMixin, CreateUpdateCustomMixin, CreateModelMixin """ 新建工单 """ - serializer = self.get_serializer(data=request.data) + rdata = request.data + serializer = self.get_serializer(data=rdata) serializer.is_valid(raise_exception=True) - start_state = WfService.get_workflow_start_state(serializer.data['workflow']) - transition = Transition.objects.get(pk=serializer.data['transition']) - ticket_data = serializer.data['ticket_data'] + start_state = WfService.get_workflow_start_state(rdata['workflow']) + transition = Transition.objects.get(pk=rdata['transition']) + ticket_data = rdata['ticket_data'] if transition.field_require_check: for key, value in start_state.state_fields.items(): #校验必填项 - if value == 2: + if value == State.STATE_FIELD_REQUIRED: if key not in ticket_data or not ticket_data[key]: raise APIException('字段{}必填'.format(key)) - ticket = serializer.save() + ticket = serializer.save(state=start_state) # 先创建出来 next_state = WfService.get_next_state_id_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) destination_participant = participant_info.get('destination_participant', '') - multi_all_person = participant_info.get('multi_all_person', '{}') # 多人需要全部处理情况 - sn = WfService.get_ticket_sn(ticket.workflow) + multi_all_person = participant_info.get('multi_all_person', {}) # 多人需要全部处理情况 + sn = WfService.get_ticket_sn(ticket.workflow) # 流水号 if next_state.type == State.STATE_TYPE_END: act_state = Ticket.TICKET_ACT_STATE_FINISH elif next_state.type == State.STATE_TYPE_START: - pass + act_state = Ticket.TICKET_ACT_STATE_DRAFT + else: + act_state = Ticket.TICKET_ACT_STATE_ONGOING + title = rdata.get('title', '') + title_template = ticket.workflow.title_template + if title_template: + all_ticket_data = {**rdata, **rdata['ticket_data']} + title = title_template.format(**all_ticket_data) + # 更新工单 + ticket.sn=sn + ticket.title=title + ticket.state=next_state + ticket.participant=destination_participant + ticket.participant_type=destination_participant_type + ticket.act_state=act_state + ticket.multi_all_person=multi_all_person + ticket.save() + # 新增流转记录 + TicketFlow.objects.create(ticket=ticket, state=start_state, ticket_data=ticket_data, + suggestion=rdata.get('suggestion',''), participant_type=State.PARTICIPANT_TYPE_PERSONAL, + particant=ticket.create_by) + return Response(serializer.data) + @action(methods=['get'], detail=True, perms_map={'get':'*'}) def flowsteps(self, request, pk=None):