diff --git a/hb_server/apps/wf/models.py b/hb_server/apps/wf/models.py index 0aebb03..94c9c44 100644 --- a/hb_server/apps/wf/models.py +++ b/hb_server/apps/wf/models.py @@ -19,7 +19,7 @@ class Workflow(CommonAModel): view_permission_check = models.BooleanField('查看权限校验', default=True, help_text='开启后,只允许工单的关联人(创建人、曾经的处理人)有权限查看工单') 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}') + 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}') class State(CommonAModel): diff --git a/hb_server/apps/wf/scripts.py b/hb_server/apps/wf/scripts.py index 3ce706f..cbb7560 100644 --- a/hb_server/apps/wf/scripts.py +++ b/hb_server/apps/wf/scripts.py @@ -4,7 +4,9 @@ from apps.wpm.models import WProduct class GetParticipants: - + """ + 获取处理人脚本 + """ all_funcs = [ {'func':'get_create_by', 'name':'获取工单创建人'} ] @@ -20,8 +22,11 @@ class GetParticipants: return participant class HandleScripts: + """ + 任务处理脚本 + """ all_funcs = [ - {'func': 'handle_wproduct', 'name':'处理不合格品'} + {'func': 'handle_something', 'name':'处理一些工作'} ] @@ -42,32 +47,11 @@ class HandleScripts: return ticket @classmethod - def handle_wproduct(cls, ticket:Ticket): - """处理不合格品""" - # 任务处理 + def handle_something(cls, ticket:Ticket): + """处理一些工作""" + # 任务处理代码区 - ticket_data = ticket.ticket_data - wt = ticket.wt_ticket - wp = wt.wproduct - if 'shenli2' in ticket_data and ticket_data['shenli2']: - wt.decision = ticket_data['shenli2'] - if ticket_data['shenli2'] in ['返工', '返修']: - pass - elif ticket_data['shenli2'] in ['让步接收']: - wp.act_state = WProduct.WPR_ACT_STATE_OK - elif 'shenli1' in ticket_data and ticket_data['shenli1']: - wp.decision = ticket_data['shenli1'] - if ticket_data['shenli1'] in ['返工', '返修']: - pass - elif ticket_data['shenli1'] in ['让步接收']: - wp.act_state = WProduct.WPR_ACT_STATE_OK - wt.save() - wp.save() # 调用自动流转 - ticket = cls.to_next(ticket=ticket, by_task=True, script_str= 'handle_wproduct') - if ticket.act_state == Ticket.TICKET_ACT_STATE_FINISH: - # 如果工单完成 - wp.ticket = None - wp.save() + ticket = cls.to_next(ticket=ticket, by_task=True, script_str= 'handle_something') diff --git a/hb_server/apps/wf/serializers.py b/hb_server/apps/wf/serializers.py index e7987ec..de756fe 100644 --- a/hb_server/apps/wf/serializers.py +++ b/hb_server/apps/wf/serializers.py @@ -51,6 +51,7 @@ class TicketSimpleSerializer(serializers.ModelSerializer): class TicketCreateSerializer(serializers.ModelSerializer): transition = serializers.PrimaryKeyRelatedField(queryset=Transition.objects.all(), write_only=True) + title = serializers.CharField(allow_blank=True, required=False) class Meta: model=Ticket fields=['title','workflow', 'ticket_data', 'transition'] diff --git a/hb_server/apps/wf/services.py b/hb_server/apps/wf/services.py index beb9724..5d486c1 100644 --- a/hb_server/apps/wf/services.py +++ b/hb_server/apps/wf/services.py @@ -273,7 +273,7 @@ class WfService(object): # 校验表单必填项目 if transition.field_require_check or not created: for key, value in ticket.state.state_fields.items(): - if value == State.STATE_FIELD_REQUIRED: + if int(value) == State.STATE_FIELD_REQUIRED: if key not in new_ticket_data or not new_ticket_data[key]: raise APIException('字段{}必填'.format(key)) diff --git a/hb_server/apps/wf/views.py b/hb_server/apps/wf/views.py index 7aba7c6..2f9b092 100644 --- a/hb_server/apps/wf/views.py +++ b/hb_server/apps/wf/views.py @@ -132,10 +132,10 @@ class TicketViewSet(OptimizationMixin, CreateUpdateCustomMixin, CreateModelMixin return TicketDetailSerializer return super().get_serializer_class() - def get_queryset(self): - if self.action=='list' and (not self.request.query_params.get('category', None)): + def filter_queryset(self, queryset): + if not self.request.query_params.get('category', None): raise APIException('请指定查询分类') - return super().get_queryset() + return super().filter_queryset(queryset) @transaction.atomic def create(self, request, *args, **kwargs): @@ -154,11 +154,11 @@ class TicketViewSet(OptimizationMixin, CreateUpdateCustomMixin, CreateModelMixin # 校验必填项 if transition.field_require_check: for key, value in start_state.state_fields.items(): - if value == State.STATE_FIELD_REQUIRED: + if int(value) == State.STATE_FIELD_REQUIRED: if key not in ticket_data and not ticket_data[key]: raise APIException('字段{}必填'.format(key)) save_ticket_data[key] = ticket_data[key] - elif value == State.STATE_FIELD_OPTIONAL: + elif int(value) == State.STATE_FIELD_OPTIONAL: save_ticket_data[key] = ticket_data[key] ticket = serializer.save(state=start_state, diff --git a/hb_server/apps/wpm/migrations/0037_wproduct_scrap_reason.py b/hb_server/apps/wpm/migrations/0037_wproduct_scrap_reason.py new file mode 100644 index 0000000..a87bc0c --- /dev/null +++ b/hb_server/apps/wpm/migrations/0037_wproduct_scrap_reason.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.9 on 2021-12-21 08:19 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wpm', '0036_auto_20211221_0923'), + ] + + operations = [ + migrations.AddField( + model_name='wproduct', + name='scrap_reason', + field=models.IntegerField(blank=True, choices=[(10, '气泡'), (20, '破点'), (30, '划伤'), (40, '其他')], null=True, verbose_name='报废原因'), + ), + ] diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py index 2b4b897..f34ceaf 100644 --- a/hb_server/apps/wpm/models.py +++ b/hb_server/apps/wpm/models.py @@ -94,6 +94,8 @@ class WprouctTicket(CommonAModel): material = models.ForeignKey(Material, verbose_name='所在物料状态', on_delete=models.CASCADE) step = models.ForeignKey(Step, verbose_name='所在步骤', on_delete=models.CASCADE) subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='所在子生产计划', on_delete=models.CASCADE) + test_record = models.ForeignKey('qm.testrecord', verbose_name='关联检验记录', on_delete=models.CASCADE, null=True, blank=True) + ticket = models.ForeignKey('wf.ticket', verbose_name='关联工单', on_delete=models.CASCADE, related_name='wt_ticket') decision = models.CharField('最终决定', null=True, blank=True, max_length=100) diff --git a/hb_server/apps/wpm/signals.py b/hb_server/apps/wpm/signals.py new file mode 100644 index 0000000..70e5693 --- /dev/null +++ b/hb_server/apps/wpm/signals.py @@ -0,0 +1,59 @@ +from django.db.models.signals import post_save +from apps.qm.models import TestRecord +from apps.wf.models import Ticket +from django.dispatch import receiver + +from apps.wpm.models import WProduct, WprouctTicket + + +@receiver(post_save, sender=Ticket) +def handleTicket(sender, instance, created, **kwargs): + if instance.workflow.name == '不合格品审理单': + if created: + ticket_data = instance.ticket_data + """ + 创建关联信息表 + """ + obj = WprouctTicket() + wproduct = WProduct.objects.get(id=ticket_data['wproduct']) + obj.wproduct = wproduct + obj.number = wproduct.number + obj.material = wproduct.material + obj.step = wproduct.step + obj.subproduction_plan = wproduct.subproduction_plan + obj.ticket = instance + obj.test_record = TestRecord.objects.filter(wproduct=wproduct, is_deleted=False, is_testok=False).order_by('-id').first() + obj.save() + + # 工单绑定半成品 + wproduct.ticket = instance + wproduct.save() + + # 检验员 + if not ticket_data.get('tester', None): + ticket_data['tester'] = obj.test_record.create_by.id + instance.ticket_data = ticket_data + instance.save() + + elif instance.act_state == Ticket.TICKET_ACT_STATE_FINISH: + """ + 执行操作决定 + """ + ticket_data = instance.ticket_data + wt = instance.wt_ticket + wp = wt.wproduct + if 'decision_1' in ticket_data and ticket_data['decision_1']: + wt.decision = ticket_data['decision_1'] + if ticket_data['decision_1'] in ['返工', '返修']: + pass + elif ticket_data['decision_1'] in ['让步接收']: + wp.act_state = WProduct.WPR_ACT_STATE_OK + elif 'decision_2' in ticket_data and ticket_data['decision_2']: + wp.decision = ticket_data['decision_2'] + if ticket_data['decision_2'] in ['返工', '返修']: + pass + elif ticket_data['decision_2'] in ['让步接收']: + wp.act_state = WProduct.WPR_ACT_STATE_OK + wt.save() + wp.save() + \ No newline at end of file diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index ae855e7..527efdb 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -374,11 +374,11 @@ class WProductViewSet(ListModelMixin, GenericViewSet): workflow = Workflow.objects.filter(name='不合格品审理单', is_deletd=False).first() if workflow: exist_data = { - 'sys_wproduct':obj.id, - 'sys_name':obj.material.name, - 'sys_specification':obj.material.specification, - 'sys_finder':request.user.id, - 'sys_process':obj.step.process.id, + 'wproduct':obj.id, + 'wproduct_name':obj.material.name, + 'wproduct_specification':obj.material.specification, + 'finder':request.user.id, + 'find_process':obj.step.process.id, } ret = {'workflow':workflow.id} ret['exist_data'] = exist_data