diff --git a/hb_server/apps/wf/migrations/0020_auto_20211223_1006.py b/hb_server/apps/wf/migrations/0020_auto_20211223_1006.py new file mode 100644 index 0000000..81df3fe --- /dev/null +++ b/hb_server/apps/wf/migrations/0020_auto_20211223_1006.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.9 on 2021-12-23 02:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wf', '0019_auto_20211221_0923'), + ] + + operations = [ + migrations.AddField( + model_name='customfield', + name='is_hidden', + field=models.BooleanField(default=False, help_text='可用于携带不需要用户查看的信息', verbose_name='是否隐藏'), + ), + migrations.AlterField( + model_name='customfield', + name='field_choice', + field=models.JSONField(blank=True, default=list, help_text='选项值,格式为list, 例["id":1, "name":"张三"]', verbose_name='选项值'), + ), + migrations.AlterField( + model_name='customfield', + name='field_type', + field=models.CharField(choices=[('string', '字符串'), ('int', '整型'), ('float', '浮点'), ('boolean', '布尔'), ('date', '日期'), ('datetime', '日期时间'), ('radio', '单选'), ('checkbox', '多选'), ('select', '单选下拉'), ('selects', '多选下拉'), ('cascader', '单选级联'), ('cascaders', '多选级联'), ('select_dg', '弹框单选'), ('select_dgs', '弹框多选'), ('textarea', '文本域'), ('file', '附件')], help_text='5.字符串,10.整形,15.浮点型,20.布尔,25.日期,30.日期时间,35.单选框,40.多选框,45.下拉列表,50.多选下拉列表,55.文本域,60.用户名, 70.多选的用户名, 80.附件(只保存路径,多个使用逗号隔开)', max_length=50, verbose_name='类型'), + ), + migrations.AlterField( + model_name='customfield', + name='label', + field=models.CharField(default='', help_text='处理特殊逻辑使用', max_length=1000, verbose_name='标签'), + ), + migrations.AlterField( + model_name='workflow', + name='title_template', + field=models.CharField(blank=True, default='{title}', help_text='工单字段的值可以作为参数写到模板中,格式如:你有一个待办工单:{title}', max_length=50, null=True, verbose_name='标题模板'), + ), + ] diff --git a/hb_server/apps/wf/models.py b/hb_server/apps/wf/models.py index 94c9c44..27c2f4a 100644 --- a/hb_server/apps/wf/models.py +++ b/hb_server/apps/wf/models.py @@ -150,14 +150,16 @@ class CustomField(CommonAModel): ('checkbox', '多选'), ('select', '单选下拉'), ('selects', '多选下拉'), + ('cascader', '单选级联'), + ('cascaders', '多选级联'), + ('select_dg', '弹框单选'), + ('select_dgs', '弹框多选'), ('textarea', '文本域'), - ('selectuser', '单选用户'), - ('selectusers', '多选用户'), - ('file', '附件'), - ('draw', '绘图') + ('file', '附件') ) workflow = models.ForeignKey(Workflow, on_delete=models.CASCADE, verbose_name='所属工作流') - field_type = models.CharField('类型', max_length=50, choices=field_type_choices, help_text='5.字符串,10.整形,15.浮点型,20.布尔,25.日期,30.日期时间,35.单选框,40.多选框,45.下拉列表,50.多选下拉列表,55.文本域,60.用户名, 70.多选的用户名, 80.附件(只保存路径,多个使用逗号隔开)') + field_type = models.CharField('类型', max_length=50, choices=field_type_choices, + help_text='string, int, float, date, datetime, radio, checkbox, select, selects, cascader, cascaders, cascader, cascaders,textarea, file') field_key = models.CharField('字段标识', max_length=50, help_text='字段类型请尽量特殊,避免与系统中关键字冲突') field_name = models.CharField('字段名称', max_length=50) sort = models.IntegerField('排序', default=0, help_text='工单基础字段在表单中排序为:流水号0,标题20,状态id40,状态名41,创建人80,创建时间100,更新时间120.前端展示工单信息的表单可以根据这个id顺序排列') @@ -167,9 +169,13 @@ class CustomField(CommonAModel): field_template = models.TextField('文本域模板', default='', blank=True, help_text='文本域类型字段前端显示时可以将此内容作为字段的placeholder') boolean_field_display = models.JSONField('布尔类型显示名', default=dict, blank=True, help_text='当为布尔类型时候,可以支持自定义显示形式。{"1":"是","0":"否"}或{"1":"需要","0":"不需要"},注意数字也需要引号') - field_choice = models.JSONField('radio、checkbox、select的选项', default=dict, blank=True, - help_text='radio,checkbox,select,multiselect类型可供选择的选项,格式为json如:{"1":"中国", "2":"美国"},注意数字也需要引号') - label = models.JSONField('标签', blank=True, default=dict, help_text='自定义标签,json格式,调用方可根据标签自行处理特殊场景逻辑,loonflow只保存文本内容') + + field_choice = models.JSONField('选项值', default=list, blank=True, + help_text='选项值,格式为list, 例["id":1, "name":"张三"]') + + label = models.CharField('标签', max_length=1000, default='', help_text='处理特殊逻辑使用') + + is_hidden = models.BooleanField('是否隐藏', default=False, help_text='可用于携带不需要用户查看的信息') class Ticket(CommonBModel): """ diff --git a/hb_server/apps/wf/serializers.py b/hb_server/apps/wf/serializers.py index de756fe..0a38ac7 100644 --- a/hb_server/apps/wf/serializers.py +++ b/hb_server/apps/wf/serializers.py @@ -38,8 +38,12 @@ class TransitionSerializer(serializers.ModelSerializer): queryset = queryset.select_related('source_state','destination_state') return queryset +class FieldChoiceSerializer(serializers.Serializer): + id = serializers.Field(label='ID') + name = serializers.CharField(label='名称') class CustomFieldSerializer(serializers.ModelSerializer): + field_choice = FieldChoiceSerializer(label='选项列表', many=True) class Meta: model = CustomField fields = '__all__' @@ -107,8 +111,28 @@ class TicketDetailSerializer(serializers.ModelSerializer): key = i['field_key'] i['field_state'] = state_fields.get(key, 1) i['field_value'] = ticket_data.get(key, None) + i['field_display'] = i['field_value'] # 该字段是用于查看详情直接展示 + if 'sys_user' in i['label']: + if isinstance(i['field_value'], list): + i['field_display'] = ','.join(list(User.objects.filter(id__in=i['field_value']).values_list('name', flat=True))) + else: + i['field_display'] = User.objects.get(id=i['field_value']).name + elif i['field_type'] in ['radio', 'select']: + for m in i['field_choice']: + if m['id'] == i['field_value']: + i['field_display'] = m['name'] + elif i['field_type'] in ['checkbox', 'selects']: + d_list = [] + for m in i['field_choice']: + if m['id'] in i['field_value']: + d_list.append(m['name']) + i['field_display'] = ','.join(d_list) return all_fields_l + def filter_display(self, item, field_value): + if item['id'] == field_value: + return + class TicketFlowSerializer(serializers.ModelSerializer): participant_ = UserSimpleSerializer(source='participant', read_only=True) state_ = StateSimpleSerializer(source='state', read_only=True) diff --git a/hb_server/apps/wf/views.py b/hb_server/apps/wf/views.py index 2f9b092..06c3703 100644 --- a/hb_server/apps/wf/views.py +++ b/hb_server/apps/wf/views.py @@ -133,7 +133,7 @@ class TicketViewSet(OptimizationMixin, CreateUpdateCustomMixin, CreateModelMixin return super().get_serializer_class() def filter_queryset(self, queryset): - if not self.request.query_params.get('category', None): + if not self.detail and not self.request.query_params.get('category', None): raise APIException('请指定查询分类') return super().filter_queryset(queryset) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 01c6315..034c1f8 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -382,6 +382,7 @@ class OperationMaterialCreate2Serailizer(serializers.ModelSerializer): class OperationMaterialCreate2ListSerailizer(serializers.ListSerializer): child=OperationMaterialCreate2Serailizer() + class OperationMaterialCreate3Serializer(serializers.ModelSerializer): material = serializers.PrimaryKeyRelatedField(required=True, queryset=Material.objects.all()) class Meta: diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 34556f6..8d906d2 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -343,7 +343,8 @@ class WProductViewSet(ListModelMixin, GenericViewSet): vdata = serializer.validated_data if obj.act_state == WProduct.WPR_ACT_STATE_NOTOK: pass - elif obj.step.process.id == 1: # 如果是冷加工可直接报废 + elif obj.step.process.id == 1 and \ + obj.act_state in [WProduct.WPR_ACT_STATE_DOWAIT, WProduct.WPR_ACT_STATE_TOTEST]: # 如果是冷加工可直接报废 if vdata.get('scrap_reason', None): obj.scrap_reason = vdata['scrap_reason'] else: @@ -375,6 +376,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet): if workflow: exist_data = { 'wproduct':obj.id, + 'wproduct_number':obj.number, 'wproduct_name':obj.material.name, 'wproduct_specification':obj.material.specification, 'finder':request.user.id,