From f34d77e8ef03e429da4c0c7276c94be23e4dc432 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 18 Feb 2022 16:16:32 +0800 Subject: [PATCH 1/7] packitem bug --- hb_server/apps/mtm/views.py | 4 +- .../pm/migrations/0025_auto_20220218_1616.py | 45 +++++++++++++++++++ hb_server/apps/pm/models.py | 26 ++++++----- 3 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 hb_server/apps/pm/migrations/0025_auto_20220218_1616.py diff --git a/hb_server/apps/mtm/views.py b/hb_server/apps/mtm/views.py index 5a3f3e0..4a02aa5 100644 --- a/hb_server/apps/mtm/views.py +++ b/hb_server/apps/mtm/views.py @@ -4,7 +4,7 @@ from rest_framework.mixins import CreateModelMixin, ListModelMixin, UpdateModelM from apps.mtm.filters import MaterialFilterSet, TechDocFilterset from apps.mtm.models import Material, PackItem, Process, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc, UsedStep, SubProduction -from apps.mtm.serializers import InputMaterialSerializer, InputMaterialUpdateSerializer, MaterialDetailSerializer, MaterialSerializer, MaterialSimpleSerializer, OtherMaterialSerializer, OutputMaterialSerializer, OutputMaterialUpdateSerializer, PackItemCreateSerializer, PackItemUpdateSerializer, ProcessSerializer, RecordFormCreateSerializer, RecordFormDetailSerializer, RecordFormFieldCreateSerializer, RecordFormFieldSerializer, RecordFormFieldUpdateSerializer, RecordFormSerializer, RecordFormUpdateSerializer, StepDetailSerializer, StepSerializer, SubProductionCreateUpdateSerializer, SubProductionSerializer, SubprodctionMaterialListSerializer, TechDocCreateSerializer, TechDocListSerializer, TechDocUpdateSerializer, UsedStepCreateSerializer, UsedStepListSerializer, UsedStepUpdateSerializer +from apps.mtm.serializers import InputMaterialSerializer, InputMaterialUpdateSerializer, MaterialDetailSerializer, MaterialSerializer, MaterialSimpleSerializer, OtherMaterialSerializer, OutputMaterialSerializer, OutputMaterialUpdateSerializer, PackItemCreateSerializer, PackItemSerializer, PackItemUpdateSerializer, ProcessSerializer, RecordFormCreateSerializer, RecordFormDetailSerializer, RecordFormFieldCreateSerializer, RecordFormFieldSerializer, RecordFormFieldUpdateSerializer, RecordFormSerializer, RecordFormUpdateSerializer, StepDetailSerializer, StepSerializer, SubProductionCreateUpdateSerializer, SubProductionSerializer, SubprodctionMaterialListSerializer, TechDocCreateSerializer, TechDocListSerializer, TechDocUpdateSerializer, UsedStepCreateSerializer, UsedStepListSerializer, UsedStepUpdateSerializer from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin from rest_framework.decorators import action from rest_framework.response import Response @@ -38,7 +38,7 @@ class PackItemViewSet(CreateUpdateModelAMixin, ModelViewSet): perms_map = {'get': '*', 'post': 'packitem_create', 'put': 'packitem_update', 'delete': 'packitem_delete'} queryset = PackItem.objects.all() - serializer_class = MaterialSerializer + serializer_class = PackItemSerializer search_fields = ['name', 'number'] filterset_fields = ['material'] ordering = ['sort'] diff --git a/hb_server/apps/pm/migrations/0025_auto_20220218_1616.py b/hb_server/apps/pm/migrations/0025_auto_20220218_1616.py new file mode 100644 index 0000000..84dfbed --- /dev/null +++ b/hb_server/apps/pm/migrations/0025_auto_20220218_1616.py @@ -0,0 +1,45 @@ +# Generated by Django 3.2.9 on 2022-02-18 08:16 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('mtm', '0047_packitem'), + ('pm', '0024_auto_20220217_1524'), + ] + + operations = [ + migrations.AddField( + model_name='subproductionplan', + name='first_tester', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='首件检查员'), + ), + migrations.AddField( + model_name='subproductionplan', + name='is_first_testok', + field=models.BooleanField(default=True, verbose_name='首件是否合格'), + ), + migrations.CreateModel( + name='FirstItem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('field_value', models.JSONField(blank=True, null=True, verbose_name='录入值')), + ('is_hidden', models.BooleanField(default=False, verbose_name='是否隐藏')), + ('is_testok', models.BooleanField(blank=True, null=True, verbose_name='是否合格')), + ('form_field', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.recordformfield', verbose_name='关联自定义表格字段')), + ('subproduction_plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='item_test_record', to='pm.subproductionplan', verbose_name='关联的子计划')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/hb_server/apps/pm/models.py b/hb_server/apps/pm/models.py index d15141a..f872e60 100644 --- a/hb_server/apps/pm/models.py +++ b/hb_server/apps/pm/models.py @@ -1,5 +1,5 @@ -from io import open_code -from apps.system.models import CommonAModel, Organization + +from apps.system.models import CommonAModel, Organization, User from django.db import models from django.contrib.auth.models import AbstractUser from django.db.models.base import Model @@ -92,19 +92,23 @@ class SubProductionPlan(CommonAModel): is_picked = models.BooleanField('是否已领料', default=False) # wproducts = models.JSONField('半成品表', default=list, blank=True) + is_first_testok = models.BooleanField('首件是否合格', default=True) + first_tester = models.ForeignKey(User, on_delete=models.CASCADE, + verbose_name="首件检查员", null=True, blank=True) + class Meta: verbose_name = '子生产计划' verbose_name_plural = verbose_name -# class FirstItem(BaseModel): -# """ -# 首件确认表记录条目 -# """ -# form_field = models.ForeignKey(RecordFormField, verbose_name='关联自定义表格字段', on_delete=models.CASCADE) -# field_value = models.JSONField('录入值', null=True, blank=True) -# is_hidden = models.BooleanField('是否隐藏', default=False) -# is_testok = models.BooleanField('是否合格', null=True, blank=True) -# subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联的子计划', on_delete=models.CASCADE, related_name='item_test_record') +class FirstItem(BaseModel): + """ + 首件确认表记录条目 + """ + form_field = models.ForeignKey(RecordFormField, verbose_name='关联自定义表格字段', on_delete=models.CASCADE) + field_value = models.JSONField('录入值', null=True, blank=True) + is_hidden = models.BooleanField('是否隐藏', default=False) + is_testok = models.BooleanField('是否合格', null=True, blank=True) + subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联的子计划', on_delete=models.CASCADE, related_name='item_test_record') class SubProductionProgress(BaseModel): """ From ff386204b52acec76ec9411845d8cbdbe3a66144 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 18 Feb 2022 16:57:09 +0800 Subject: [PATCH 2/7] =?UTF-8?q?=E8=8E=B7=E5=8F=96=E9=A6=96=E4=BB=B6?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E8=A1=A8first=5Ftest=5Finit=20part1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pm/migrations/0026_auto_20220218_1636.py | 65 +++++++++++++++++++ hb_server/apps/pm/models.py | 17 +++-- hb_server/apps/pm/serializers.py | 29 ++++++++- hb_server/apps/pm/views.py | 19 +++++- .../migrations/0005_user_last_check_time.py | 18 +++++ 5 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 hb_server/apps/pm/migrations/0026_auto_20220218_1636.py create mode 100644 hb_server/apps/system/migrations/0005_user_last_check_time.py diff --git a/hb_server/apps/pm/migrations/0026_auto_20220218_1636.py b/hb_server/apps/pm/migrations/0026_auto_20220218_1636.py new file mode 100644 index 0000000..bde5e8c --- /dev/null +++ b/hb_server/apps/pm/migrations/0026_auto_20220218_1636.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.9 on 2022-02-18 08:36 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0047_packitem'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('pm', '0025_auto_20220218_1616'), + ] + + operations = [ + migrations.RemoveField( + model_name='subproductionplan', + name='first_tester', + ), + migrations.RemoveField( + model_name='subproductionplan', + name='is_first_testok', + ), + migrations.AddField( + model_name='subproductionplan', + name='first_sign_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='首件签字时间'), + ), + migrations.AddField( + model_name='subproductionplan', + name='form', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mtm.recordform', verbose_name='首件检查表'), + ), + migrations.AddField( + model_name='subproductionplan', + name='is_testok', + field=models.BooleanField(blank=True, null=True, verbose_name='首件是否合格'), + ), + migrations.AddField( + model_name='subproductionplan', + name='leader_1', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='first_leader_1', to=settings.AUTH_USER_MODEL, verbose_name='工序负责人'), + ), + migrations.AddField( + model_name='subproductionplan', + name='leader_2', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='first_leader_2', to=settings.AUTH_USER_MODEL, verbose_name='技术负责人'), + ), + migrations.AddField( + model_name='subproductionplan', + name='leader_3', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='first_leader_3', to=settings.AUTH_USER_MODEL, verbose_name='总检'), + ), + migrations.AddField( + model_name='subproductionplan', + name='remark', + field=models.CharField(blank=True, max_length=100, null=True, verbose_name='备注'), + ), + migrations.AddField( + model_name='subproductionplan', + name='tester', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='first_tester', to=settings.AUTH_USER_MODEL, verbose_name='首件检查员'), + ), + ] diff --git a/hb_server/apps/pm/models.py b/hb_server/apps/pm/models.py index f872e60..3b4607d 100644 --- a/hb_server/apps/pm/models.py +++ b/hb_server/apps/pm/models.py @@ -7,7 +7,7 @@ import django.utils.timezone as timezone from django.db.models.query import QuerySet from utils.model import SoftModel, BaseModel -from apps.mtm.models import Material, Process, RecordFormField, SubProduction, SubprodctionMaterial +from apps.mtm.models import Material, Process, RecordForm, RecordFormField, SubProduction, SubprodctionMaterial from apps.sam.models import Order class ProductionPlan(CommonAModel): @@ -92,9 +92,18 @@ class SubProductionPlan(CommonAModel): is_picked = models.BooleanField('是否已领料', default=False) # wproducts = models.JSONField('半成品表', default=list, blank=True) - is_first_testok = models.BooleanField('首件是否合格', default=True) - first_tester = models.ForeignKey(User, on_delete=models.CASCADE, - verbose_name="首件检查员", null=True, blank=True) + is_testok = models.BooleanField('首件是否合格', null=True, blank=True) + form = models.ForeignKey(RecordForm, verbose_name='首件检查表', on_delete=models.CASCADE, null=True, blank=True) + tester = models.ForeignKey(User, on_delete=models.CASCADE, + verbose_name="首件检查员", null=True, blank=True, related_name='first_tester') + leader_1 = models.ForeignKey(User, on_delete=models.CASCADE, + verbose_name="工序负责人", null=True, blank=True, related_name='first_leader_1') + leader_2 = models.ForeignKey(User, on_delete=models.CASCADE, + verbose_name="技术负责人", null=True, blank=True, related_name='first_leader_2') + leader_3 = models.ForeignKey(User, on_delete=models.CASCADE, + verbose_name="总检", null=True, blank=True, related_name='first_leader_3') + first_sign_time = models.DateTimeField('首件签字时间', null=True, blank=True) + remark = models.CharField('备注', max_length=100, null=True, blank=True) class Meta: verbose_name = '子生产计划' diff --git a/hb_server/apps/pm/serializers.py b/hb_server/apps/pm/serializers.py index a537ae9..d098511 100644 --- a/hb_server/apps/pm/serializers.py +++ b/hb_server/apps/pm/serializers.py @@ -1,8 +1,9 @@ +from apps.mtm.models import RecordForm from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress from rest_framework import serializers from apps.sam.serializers import OrderSerializer, OrderSimpleSerializer -from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer, SubProductionSimpleSerializer -from apps.system.serializers import OrganizationSimpleSerializer +from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer, RecordFormSimpleSerializer, SubProductionSimpleSerializer +from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSerializer from utils.mixins import DynamicFieldsSerializerMixin @@ -74,4 +75,26 @@ class SubProductionProgressSerializer(serializers.ModelSerializer): subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True) class Meta: model = SubProductionProgress - fields = '__all__' \ No newline at end of file + fields = '__all__' + + +class FirstTestInitSerializer(serializers.Serializer): + form = serializers.PrimaryKeyRelatedField(queryset=RecordForm.objects.all(), required=True) + +class FirstTestDetailSerializer(serializers.ModelSerializer): + tester_ = UserSimpleSerializer(source='tester', read_only=True) + leader_1_ = UserSimpleSerializer(source='leader_1', read_only=True) + leader_2_ = UserSimpleSerializer(source='leader_2', read_only=True) + leader_3_ = UserSimpleSerializer(source='leader_3', read_only=True) + form_ = RecordFormSimpleSerializer(source='form', read_only=True) + # record_data = TestRecordItemSerializer(source='item_test_record', read_only=True, many=True) + record_data = serializers.SerializerMethodField() + + class Meta: + model = SubProductionPlan + fields = ['id', 'form', 'form_', 'is_testok', 'remark', 'first_sign_time' + 'tester', 'tester_', 'leader_1', 'leader_1_', 'leader_2', + 'leader_2_', 'leader_3', 'leader_3_'] + + def get_record_data(self, obj): + return None \ No newline at end of file diff --git a/hb_server/apps/pm/views.py b/hb_server/apps/pm/views.py index 5df4d6f..e7bcfd2 100644 --- a/hb_server/apps/pm/views.py +++ b/hb_server/apps/pm/views.py @@ -10,7 +10,7 @@ from apps.inm.serializers import MaterialBatchSerializer from apps.mtm.models import Material, Step, SubProduction, SubprodctionMaterial from apps.pm.filters import PlanFilterSet, SubproductionProgressFilterSet from apps.system.mixins import CreateUpdateModelAMixin -from apps.pm.serializers import GenSubPlanSerializer, PickNeedSerializer, PlanDestorySerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, ResourceConvertListSerializer, ResourceConvertSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer +from apps.pm.serializers import FirstTestInitSerializer, GenSubPlanSerializer, PickNeedSerializer, PlanDestorySerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, ResourceConvertListSerializer, ResourceConvertSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin from apps.pm.models import ProductionPlan, SubProductionProgress, SubProductionPlan from rest_framework.viewsets import GenericViewSet, ModelViewSet @@ -229,6 +229,23 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo have = MaterialBatchSerializer(instance=objs, many=True).data return Response({'need':need, 'have':have}) + @action(methods=['put'], detail=True, perms_map={'post':'first_test'}, serializer_class=FirstTestInitSerializer) + @transaction.atomic + def first_test_init(self, request, pk=None): + """ + 获取首件检查表 + """ + obj = self.get_object() + if obj.is_testok is None: + rdata = request.data + serializer = self.get_serializer(data=rdata) + serializer.is_valid(raise_exception=True) + form = serializer.validated_data.get('form') + + raise APIException('已经过首件确认') + + + class SubProductionProgressViewSet(ListModelMixin, GenericViewSet): """ 生产进度 diff --git a/hb_server/apps/system/migrations/0005_user_last_check_time.py b/hb_server/apps/system/migrations/0005_user_last_check_time.py new file mode 100644 index 0000000..284e91b --- /dev/null +++ b/hb_server/apps/system/migrations/0005_user_last_check_time.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.9 on 2022-01-25 08:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0004_user_is_atwork'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='last_check_time', + field=models.DateTimeField(blank=True, null=True, verbose_name='打卡时间'), + ), + ] From 7a1df98575462d51bed80a740602df8b1b372f55 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 18 Feb 2022 17:02:11 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0005_user_last_check_time.py | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 hb_server/apps/system/migrations/0005_user_last_check_time.py diff --git a/hb_server/apps/system/migrations/0005_user_last_check_time.py b/hb_server/apps/system/migrations/0005_user_last_check_time.py deleted file mode 100644 index 284e91b..0000000 --- a/hb_server/apps/system/migrations/0005_user_last_check_time.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.9 on 2022-01-25 08:51 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('system', '0004_user_is_atwork'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='last_check_time', - field=models.DateTimeField(blank=True, null=True, verbose_name='打卡时间'), - ), - ] From aaee37fee2d23a57bfbca19dbd989b95a6728829 Mon Sep 17 00:00:00 2001 From: shijing Date: Mon, 21 Feb 2022 09:29:02 +0800 Subject: [PATCH 4/7] statisticsStyleChange --- .../views/statistics/materialStatistics.vue | 343 +++++++++++++----- .../views/statistics/progressStatistics.vue | 14 +- 2 files changed, 260 insertions(+), 97 deletions(-) diff --git a/hb_client/src/views/statistics/materialStatistics.vue b/hb_client/src/views/statistics/materialStatistics.vue index 80a9fc9..678a592 100644 --- a/hb_client/src/views/statistics/materialStatistics.vue +++ b/hb_client/src/views/statistics/materialStatistics.vue @@ -9,14 +9,21 @@
废料原因统计
-
+ +
@@ -54,9 +61,9 @@
采购物料表
@@ -67,9 +74,9 @@
采购供应商表
@@ -109,9 +116,9 @@
废料来源
@@ -157,17 +164,21 @@ }, data() { return { + chartId0: 'chart0', chartId1: 'chart1', chartId2: 'chart2', chartId3: 'chart3', barChart: null, barChart1: null, pieOptions: {}, - barOptions: {}, + barOptions1: {}, + barOptions21: {}, + barOptions22: {}, + barOptions3: {}, activeName: '废料统计', chartsName: "chartsName", + domHeight:'300px', cdata: { - xData: ["气泡", "划痕"], seriesData: [ {value: 10, name: "气泡"}, {value: 5, name: "破点"}, @@ -175,11 +186,29 @@ {value: 6, name: "其他"}, ] }, - chartData: { + chartData1: { xAxisData: ["气泡", "破点", "划伤", "其他"], - seriesData: [10, 5, 19, 6], + seriesData: [30, 25, 35, 10], }, - xAxisbar: ["供应商1", "供应商2", "供应商3", "供应商4", "供应商5", "供应商6", "供应商7"], + chartData21: { + xAxisData: ["物料1", "物料2", "物料3", "物料4", "物料5", "物料6", "物料7"], + seriesData: [800, 950, 960, 906, 600, 800, 900], + }, + chartData22: { + xAxisData: ["供应商1", "供应商2", "供应商3", "供应商4", "供应商5", "供应商6", "供应商7"], + seriesData: [5, 20, 15, 25,10, 10,15], + }, + chartData3: { + xAxisData: ["供应商1", "供应商2", "供应商3", "供应商4", "供应商5", "供应商6", "供应商7"], + seriesData:[2, 2, 4, 5,1, 0,1], + }, + xAxisData1: ["气泡", "破点", "划伤", "其他"], + xAxisbar21: ["物料1", "物料2", "物料3", "物料4", "物料5", "物料6", "物料7"], + xAxisbar22: ["供应商1", "供应商2", "供应商3", "供应商4", "供应商5", "供应商6", "供应商7"], + xAxisbar3: ["供应商1", "供应商2", "供应商3", "供应商4", "供应商5", "供应商6", "供应商7"], + barData1: [30, 25, 35, 10], + barData21: [800, 950, 960, 906, 600, 800, 900], + barData22: [5, 20, 15, 25,10, 10,15], barData: [80, 95, 96, 96, 96, 98, 99], list: [ {id: 1, name: 'HIehd91', card: '3331', sco: 'REF-31', num: 2, reason: "气泡"}, @@ -233,87 +262,22 @@ immediate: true, deep: true }, + created(){ + let hei = document.getElementsByClassName('app-main')[0].clientHeight; + this.domHeight =( hei- 20)/2+'px'; + }, methods: { - drawChart() { - let that = this; - this.barChart = this.$echarts.init(document.getElementById('barChart')); - this.barChart.setOption({ - grid: { - top: '10%', - left: '3%', - right: '5%', - bottom: '1%', - containLabel: true - }, - tooltip: { - trigger: 'item', - formatter: function (params) { - let color = params.color;//图例颜色 - let htmlStr = '
'; - htmlStr += params.seriesName + '
'; - htmlStr += ''; - htmlStr += params.name + ':' + params.value + '件'; - htmlStr += '
'; - return htmlStr; - } - }, - xAxis: { - axisTick: { - show: false - }, - splitLine: { - show: false, //去掉X轴分割线 - }, - data: that.chartData.xAxisData, - }, - yAxis: { - axisLine: { - show: true,//y轴线 - }, - axisTick: { - show: false//Y轴刻度线 - }, - axisLabel: { - color: '#333333'//Y轴文本颜色 - }, - splitLine: { - show: true, //Y轴分割线 - lineStyle: { - color: '#dddddd'//Y轴分割线颜色 - } - }, - }, - series: [{ - name: '废料统计', - type: 'bar', - barWidth: 20, - data: that.chartData.seriesData, - label: { - show: true, //开启显示 - position: 'top', //在上方显示 - formatter: '{c}',//显示百分号 - textStyle: { //数值样式 - color: 'black',//字体颜色 - fontSize: 10//字体大小 - } - }, - itemStyle: { - color: '#409EFF' - }, - }] - }); - }, - handleClick(tab) { + handleClick() { // console.log(tab); // debugger; }, }, mounted() { - this.drawChart(); - this.barOptions = { + let that = this; + this.barOptions1 = { grid: { top: '10%', - left: '3%', + left: '5%', right: '5%', bottom: '1%', containLabel: true @@ -323,9 +287,9 @@ formatter: function (params) { let color = params.color;//图例颜色 let htmlStr = '
'; - htmlStr += params.name + '
'; + htmlStr += params.seriesName + '
'; htmlStr += ''; - htmlStr += params.seriesName + ':' + params.value + '%'; + htmlStr += params.name + ':' + params.value + '件'; htmlStr += '
'; return htmlStr; } @@ -337,7 +301,7 @@ splitLine: { show: false, //去掉X轴分割线 }, - data: this.xAxisbar, + data: that.chartData1.xAxisData, }, yAxis: { axisLine: { @@ -357,10 +321,10 @@ }, }, series: [{ - name: '成品率', + name: '废料统计', type: 'bar', barWidth: 20, - data: this.barData, + data: that.chartData1.seriesData, label: { show: true, //开启显示 position: 'top', //在上方显示 @@ -374,7 +338,202 @@ color: '#409EFF' }, }] - } + }; + this.barOptions21 = { + grid: { + top: '10%', + left: '5%', + right: '5%', + bottom: '1%', + containLabel: true + }, + tooltip: { + trigger: 'item', + formatter: function (params) { + let color = params.color;//图例颜色 + let htmlStr = '
'; + htmlStr += '物料采购' + '
'; + htmlStr += ''; + htmlStr += params.name + ':' + params.value + '件'; + htmlStr += '
'; + return htmlStr; + } + }, + xAxis: { + axisTick: { + show: false + }, + splitLine: { + show: false, //去掉X轴分割线 + }, + data: this.chartData21.xAxisData, + }, + yAxis: { + axisLine: { + show: true,//y轴线 + }, + axisTick: { + show: false//Y轴刻度线 + }, + axisLabel: { + color: '#333333'//Y轴文本颜色 + }, + splitLine: { + show: true, //Y轴分割线 + lineStyle: { + color: '#dddddd'//Y轴分割线颜色 + } + }, + }, + series: [{ + name: '物料', + type: 'bar', + barWidth: 20, + data: this.chartData21.seriesData, + label: { + show: true, //开启显示 + position: 'top', //在上方显示 + formatter: '{c}',//显示百分号 + textStyle: { //数值样式 + color: 'black',//字体颜色 + fontSize: 10//字体大小 + } + }, + itemStyle: { + color: '#409EFF' + }, + }] + }; + this.barOptions22 = { + grid: { + top: '10%', + left: '5%', + right: '5%', + bottom: '1%', + containLabel: true + }, + tooltip: { + trigger: 'item', + formatter: function (params) { + let color = params.color;//图例颜色 + let htmlStr = '
'; + htmlStr += params.seriesName + '
'; + htmlStr += ''; + htmlStr += params.name + ':' + params.value + '%'; + htmlStr += '
'; + return htmlStr; + } + }, + xAxis: { + axisTick: { + show: false + }, + splitLine: { + show: false, //去掉X轴分割线 + }, + data: this.chartData22.xAxisData, + }, + yAxis: { + axisLine: { + show: true,//y轴线 + }, + axisTick: { + show: false//Y轴刻度线 + }, + axisLabel: { + color: '#333333'//Y轴文本颜色 + }, + splitLine: { + show: true, //Y轴分割线 + lineStyle: { + color: '#dddddd'//Y轴分割线颜色 + } + }, + }, + series: [{ + name: '采购占比', + type: 'bar', + barWidth: 20, + data: this.chartData22.seriesData, + label: { + show: true, //开启显示 + position: 'top', //在上方显示 + formatter: '{c}',//显示百分号 + textStyle: { //数值样式 + color: 'black',//字体颜色 + fontSize: 10//字体大小 + } + }, + itemStyle: { + color: '#409EFF' + }, + }] + }; + this.barOptions3 = { + grid: { + top: '10%', + left: '5%', + right: '5%', + bottom: '1%', + containLabel: true + }, + tooltip: { + trigger: 'item', + formatter: function (params) { + let color = params.color;//图例颜色 + let htmlStr = '
'; + htmlStr += params.seriesName + '
'; + htmlStr += ''; + htmlStr += params.name + ':' + params.value + '件'; + htmlStr += '
'; + return htmlStr; + } + }, + xAxis: { + axisTick: { + show: false + }, + splitLine: { + show: false, //去掉X轴分割线 + }, + data: this.chartData3.xAxisData, + }, + yAxis: { + axisLine: { + show: true,//y轴线 + }, + axisTick: { + show: false//Y轴刻度线 + }, + axisLabel: { + color: '#333333'//Y轴文本颜色 + }, + splitLine: { + show: true, //Y轴分割线 + lineStyle: { + color: '#dddddd'//Y轴分割线颜色 + } + }, + }, + series: [{ + name: '废料来源', + type: 'bar', + barWidth: 20, + data: this.chartData3.seriesData, + label: { + show: true, //开启显示 + position: 'top', //在上方显示 + formatter: '{c}',//显示百分号 + textStyle: { //数值样式 + color: 'black',//字体颜色 + fontSize: 10//字体大小 + } + }, + itemStyle: { + color: '#409EFF' + }, + }] + }; } } diff --git a/hb_client/src/views/statistics/progressStatistics.vue b/hb_client/src/views/statistics/progressStatistics.vue index 0e5ee33..8afeeb4 100644 --- a/hb_client/src/views/statistics/progressStatistics.vue +++ b/hb_client/src/views/statistics/progressStatistics.vue @@ -7,7 +7,7 @@ @@ -18,7 +18,7 @@ :id="chartId1" :options="barOptions" :className="chartsName" - height="45vh" + :height="domHeight" width="100%" > @@ -31,7 +31,7 @@ :id="chartId2" :options="barOptions1" :className="chartsName" - height="45vh" + :height="domHeight" width="100%" > @@ -54,7 +54,6 @@ v-el-height-adaptive-table="{bottomOffset: 42}" > - @@ -64,7 +63,6 @@ - @@ -168,6 +166,7 @@ {value: 1, name: "逾期率"}, ] }, + domHeight:'300px', xAxisbar:["冷加工", "热弯", "钢化", "镀膜", "夹层", "包边", "装框"], barData: [80, 95, 96, 96, 96, 98, 99], xAxisbar1:[ "2021/09", "2021/10", "2021/11", "2021/12", "2022/01", "2022/02"], @@ -217,6 +216,10 @@ immediate: true, deep: true }, + created(){ + let hei = document.getElementsByClassName('app-main')[0].clientHeight; + this.domHeight =( hei- 60)/2+'px'; + }, methods: { getList() { this.orderLoading = true; @@ -378,6 +381,7 @@ }, }] } + } } From 6b73a12840566c9360f2232f4587d0cebbaf0725 Mon Sep 17 00:00:00 2001 From: shijing Date: Mon, 21 Feb 2022 10:23:22 +0800 Subject: [PATCH 5/7] cheeckTableChange --- hb_client/src/components/customForm/index.vue | 124 ++++++++---------- .../src/components/customForm/review.vue | 123 +++++++++-------- .../views/statistics/materialStatistics.vue | 8 -- hb_client/src/views/wpm/need.vue | 22 ++-- 4 files changed, 126 insertions(+), 151 deletions(-) diff --git a/hb_client/src/components/customForm/index.vue b/hb_client/src/components/customForm/index.vue index 961af55..c809024 100644 --- a/hb_client/src/components/customForm/index.vue +++ b/hb_client/src/components/customForm/index.vue @@ -9,7 +9,7 @@ -1||rule.indexOf('&&')>-1){ - let tam = '', arr = []; - if(rule.indexOf('||')>-1){ - arr = rule.split('||'); - }else{ - arr = rule.split('&&'); - } - for (let i = 0;i-1||rule.indexOf('&&')>-1){ + let tam = '', arr = []; + if(rule.indexOf('||')>-1){ + arr = rule.split('||'); + }else{ + arr = rule.split('&&'); + } + for (let i = 0;i-1){ - if( tam.indexOf('true')>-1){ - rea = true; - }else{ - rea = false; - } }else{ - if( tam.indexOf('false')>-1){ - rea = false; - }else{ - rea = true; - } + tam += 'false'; } - if(rea){ - that.formData[index].is_hidden = false; - }else{ - that.formData[index].is_hidden = true; - that.checkForm[field_key] = null; - } - return rea; - }else{ - let temp =rule.match(reg)[0]; - let key = temp.replace(/\{|\}/g, '');//qipao - let a = rule.replace(key, 'yy'); - a = a.replace(key, 'yy'); - let yy = "'"+that.checkForm[key]+"'"; - if(eval(eval(a))){ - that.formData[index].is_hidden = false; - }else{ - that.formData[index].is_hidden = true; - that.checkForm[field_key] = null; - } - return eval(eval(a)); } + let rea = true; + if(rule.indexOf('||')>-1){ + if( tam.indexOf('true')>-1){ + rea = true; + }else{ + rea = false; + } + }else{ + if( tam.indexOf('false')>-1){ + rea = false; + }else{ + rea = true; + } + } + if(rea){ + that.formData[index].is_hidden = false; + }else{ + that.formData[index].is_hidden = true; + that.checkForm[field_key] = null; + } + return rea; }else{ - that.formData[index].is_hidden = true; - that.checkForm[field_key] = null; - return false; + let temp =rule.match(reg)[0]; + let key = temp.replace(/\{|\}/g, '');//qipao + let a = rule.replace(key, 'yy'); + a = a.replace(key, 'yy'); + let yy = "'"+that.checkForm[key]+"'"; + if(eval(eval(a))){ + that.formData[index].is_hidden = false; + }else{ + that.formData[index].is_hidden = true; + that.checkForm[field_key] = null; + } + return eval(eval(a)); } }else{ that.formData[index].is_hidden = false; diff --git a/hb_client/src/components/customForm/review.vue b/hb_client/src/components/customForm/review.vue index 91cc206..7f4d601 100644 --- a/hb_client/src/components/customForm/review.vue +++ b/hb_client/src/components/customForm/review.vue @@ -9,7 +9,7 @@ -1||rule.indexOf('&&')>-1){ - let tam = '', arr = []; - if(rule.indexOf('||')>-1){ - arr = rule.split('||'); - }else{ - arr = rule.split('&&'); - } - for (let i = 0;i-1||rule.indexOf('&&')>-1){ + let tam = '', arr = []; + if(rule.indexOf('||')>-1){ + arr = rule.split('||'); + }else{ + arr = rule.split('&&'); + } + for (let i = 0;i-1){ - if( tam.indexOf('true')>-1){ - rea = true; - }else{ - rea = false; - } }else{ - if( tam.indexOf('false')>-1){ - rea = false; - }else{ - rea = true; - } + tam += 'false'; } - if(rea){ - that.formData[index].is_hidden = false; - }else{ - that.formData[index].is_hidden = true; - that.checkForm[field_key] = null; - } - return rea; - }else{ - let temp =rule.match(reg)[0]; - let key = temp.replace(/\{|\}/g, '');//qipao - let a = rule.replace(key, 'yy'); - a = a.replace(key, 'yy'); - let yy = "'"+that.checkForm[key]+"'"; - if(eval(eval(a))){ - that.formData[index].is_hidden = false; - }else{ - that.formData[index].is_hidden = true; - that.checkForm[field_key] = null; - } - return eval(eval(a)); } + let rea = true; + if(rule.indexOf('||')>-1){ + if( tam.indexOf('true')>-1){ + rea = true; + }else{ + rea = false; + } + }else{ + if( tam.indexOf('false')>-1){ + rea = false; + }else{ + rea = true; + } + } + if(rea){ + that.formData[index].is_hidden = false; + }else{ + that.formData[index].is_hidden = true; + that.checkForm[field_key] = null; + } + return rea; }else{ - that.formData[index].is_hidden = true; - that.checkForm[field_key] = null; - return false; + let temp =rule.match(reg)[0]; + let key = temp.replace(/\{|\}/g, '');//qipao + let a = rule.replace(key, 'yy'); + a = a.replace(key, 'yy'); + let yy = "'"+that.checkForm[key]+"'"; + if(eval(eval(a))){ + that.formData[index].is_hidden = false; + }else{ + that.formData[index].is_hidden = true; + that.checkForm[field_key] = null; + } + return eval(eval(a)); } }else{ that.formData[index].is_hidden = false; diff --git a/hb_client/src/views/statistics/materialStatistics.vue b/hb_client/src/views/statistics/materialStatistics.vue index 678a592..aeadea4 100644 --- a/hb_client/src/views/statistics/materialStatistics.vue +++ b/hb_client/src/views/statistics/materialStatistics.vue @@ -202,14 +202,6 @@ xAxisData: ["供应商1", "供应商2", "供应商3", "供应商4", "供应商5", "供应商6", "供应商7"], seriesData:[2, 2, 4, 5,1, 0,1], }, - xAxisData1: ["气泡", "破点", "划伤", "其他"], - xAxisbar21: ["物料1", "物料2", "物料3", "物料4", "物料5", "物料6", "物料7"], - xAxisbar22: ["供应商1", "供应商2", "供应商3", "供应商4", "供应商5", "供应商6", "供应商7"], - xAxisbar3: ["供应商1", "供应商2", "供应商3", "供应商4", "供应商5", "供应商6", "供应商7"], - barData1: [30, 25, 35, 10], - barData21: [800, 950, 960, 906, 600, 800, 900], - barData22: [5, 20, 15, 25,10, 10,15], - barData: [80, 95, 96, 96, 96, 98, 99], list: [ {id: 1, name: 'HIehd91', card: '3331', sco: 'REF-31', num: 2, reason: "气泡"}, {id: 2, name: 'HIehd92', card: '3332', sco: 'REF-32', num: 1, reason: "划痕"}, diff --git a/hb_client/src/views/wpm/need.vue b/hb_client/src/views/wpm/need.vue index 2af65be..c05e711 100644 --- a/hb_client/src/views/wpm/need.vue +++ b/hb_client/src/views/wpm/need.vue @@ -1008,25 +1008,23 @@ handleInspection(scope, index) { //调该物料对应的检查表 let that = this; - this.innerIndex = index; + that.innerIndex = index; // this.outerVisible = true; - this.wproduct = scope.row.id;//半成品ID - debugger; - console.log(scope.row.material_check); - this.listQueryrecordform.material = scope.row.material_check!==null ? scope.row.material_check :scope.row.material;// - this.listQueryrecordform.type = 2; - this.listQueryrecordform.enabled = true; - this.recordform = null; - getrecordformList(this.listQueryrecordform).then((response) => { + that.wproduct = scope.row.id;//半成品ID + that.listQueryrecordform.material = scope.row.material; + that.listQueryrecordform.type = 20; + that.listQueryrecordform.enabled = true; + that.recordform = null; + getrecordformList(that.listQueryrecordform).then((response) => { if (response.data) { - this.recordformList = response.data; + that.recordformList = response.data; if (response.data.length === 1) { that.recordform = response.data[0].id; that.formName = response.data[0].name; that.submitrecordform(index); } else { //弹出列表选择框 - this.outerVisible = true; + that.outerVisible = true; } } }); @@ -1038,8 +1036,6 @@ return item.id === that.recordform; }); that.formName = arr[0].name; - // this.outerVisible = false; - // that.submitrecordform(that.innerIndex); }, //检验记录 checkRecord(scope, index) { From 65a4ab8934fc41ed29c87523e156d3665fd153b5 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 21 Feb 2022 10:40:58 +0800 Subject: [PATCH 6/7] =?UTF-8?q?=E9=A6=96=E4=BB=B6=E6=A3=80=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pm/migrations/0027_auto_20220221_1027.py | 40 +++++++++++ hb_server/apps/pm/models.py | 18 +---- hb_server/apps/pm/serializers.py | 24 ++----- hb_server/apps/pm/views.py | 68 ++++++++++++++++--- .../migrations/0025_alter_testrecord_type.py | 18 +++++ hb_server/apps/qm/models.py | 4 +- hb_server/apps/qm/views.py | 3 +- hb_server/apps/wf/views.py | 6 +- hb_server/utils/response.py | 4 +- 9 files changed, 137 insertions(+), 48 deletions(-) create mode 100644 hb_server/apps/pm/migrations/0027_auto_20220221_1027.py create mode 100644 hb_server/apps/qm/migrations/0025_alter_testrecord_type.py diff --git a/hb_server/apps/pm/migrations/0027_auto_20220221_1027.py b/hb_server/apps/pm/migrations/0027_auto_20220221_1027.py new file mode 100644 index 0000000..a3891ff --- /dev/null +++ b/hb_server/apps/pm/migrations/0027_auto_20220221_1027.py @@ -0,0 +1,40 @@ +# Generated by Django 3.2.9 on 2022-02-21 02:27 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('qm', '0025_alter_testrecord_type'), + ('pm', '0026_auto_20220218_1636'), + ] + + operations = [ + migrations.RemoveField( + model_name='subproductionplan', + name='form', + ), + migrations.RemoveField( + model_name='subproductionplan', + name='is_testok', + ), + migrations.RemoveField( + model_name='subproductionplan', + name='tester', + ), + migrations.AddField( + model_name='subproductionplan', + name='first_test', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='qm.testrecord'), + ), + migrations.AddField( + model_name='subproductionplan', + name='first_test_state', + field=models.IntegerField(default=10, verbose_name='首件状态'), + ), + migrations.DeleteModel( + name='FirstItem', + ), + ] diff --git a/hb_server/apps/pm/models.py b/hb_server/apps/pm/models.py index 3b4607d..53d5e2f 100644 --- a/hb_server/apps/pm/models.py +++ b/hb_server/apps/pm/models.py @@ -69,6 +69,7 @@ class SubProductionPlan(CommonAModel): (SUBPLAN_STATE_WORKING, '生产中'), (SUBPLAN_STATE_DONE, '已完成'), ) + number = models.CharField('子计划编号', max_length=50, unique=True, null=True, blank=True) production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE, related_name='subplan_plan') subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='subplan_subprod') @@ -91,11 +92,8 @@ class SubProductionPlan(CommonAModel): end_date_real = models.DateField('实际完工日期', null=True, blank=True) is_picked = models.BooleanField('是否已领料', default=False) - # wproducts = models.JSONField('半成品表', default=list, blank=True) - is_testok = models.BooleanField('首件是否合格', null=True, blank=True) - form = models.ForeignKey(RecordForm, verbose_name='首件检查表', on_delete=models.CASCADE, null=True, blank=True) - tester = models.ForeignKey(User, on_delete=models.CASCADE, - verbose_name="首件检查员", null=True, blank=True, related_name='first_tester') + first_test_state = models.IntegerField('首件状态', default=SUBPLAN_STATE_PLANING) + first_test = models.ForeignKey('qm.testrecord', on_delete=models.CASCADE, null=True, blank=True) leader_1 = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="工序负责人", null=True, blank=True, related_name='first_leader_1') leader_2 = models.ForeignKey(User, on_delete=models.CASCADE, @@ -109,16 +107,6 @@ class SubProductionPlan(CommonAModel): verbose_name = '子生产计划' verbose_name_plural = verbose_name -class FirstItem(BaseModel): - """ - 首件确认表记录条目 - """ - form_field = models.ForeignKey(RecordFormField, verbose_name='关联自定义表格字段', on_delete=models.CASCADE) - field_value = models.JSONField('录入值', null=True, blank=True) - is_hidden = models.BooleanField('是否隐藏', default=False) - is_testok = models.BooleanField('是否合格', null=True, blank=True) - subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联的子计划', on_delete=models.CASCADE, related_name='item_test_record') - class SubProductionProgress(BaseModel): """ 子计划生产进度统计表/物料消耗 diff --git a/hb_server/apps/pm/serializers.py b/hb_server/apps/pm/serializers.py index d098511..d32669c 100644 --- a/hb_server/apps/pm/serializers.py +++ b/hb_server/apps/pm/serializers.py @@ -33,12 +33,15 @@ class ResourceConvertListSerializer(serializers.ListSerializer): class ResourceCalListSerializer(serializers.ListSerializer): child = ResourceCalSerializer() -class SubProductionPlanListSerializer(serializers.ModelSerializer): +class SubProductionPlanListSerializer(DynamicFieldsSerializerMixin, serializers.ModelSerializer): workshop_ = OrganizationSimpleSerializer(source='workshop', read_only=True) process_ = ProcessSimpleSerializer(source='process', read_only=True) subproduction_ = SubProductionSimpleSerializer(source='subproduction', read_only=True) product_ = MaterialSimpleSerializer(source='product', read_only=True) plan_product_ = serializers.SerializerMethodField() + leader_1_ = UserSimpleSerializer(source='leader_1', read_only=True) + leader_2_ = UserSimpleSerializer(source='leader_2', read_only=True) + leader_3_ = UserSimpleSerializer(source='leader_3', read_only=True) class Meta: model=SubProductionPlan fields = '__all__' @@ -81,20 +84,7 @@ class SubProductionProgressSerializer(serializers.ModelSerializer): class FirstTestInitSerializer(serializers.Serializer): form = serializers.PrimaryKeyRelatedField(queryset=RecordForm.objects.all(), required=True) -class FirstTestDetailSerializer(serializers.ModelSerializer): - tester_ = UserSimpleSerializer(source='tester', read_only=True) - leader_1_ = UserSimpleSerializer(source='leader_1', read_only=True) - leader_2_ = UserSimpleSerializer(source='leader_2', read_only=True) - leader_3_ = UserSimpleSerializer(source='leader_3', read_only=True) - form_ = RecordFormSimpleSerializer(source='form', read_only=True) - # record_data = TestRecordItemSerializer(source='item_test_record', read_only=True, many=True) - record_data = serializers.SerializerMethodField() - class Meta: - model = SubProductionPlan - fields = ['id', 'form', 'form_', 'is_testok', 'remark', 'first_sign_time' - 'tester', 'tester_', 'leader_1', 'leader_1_', 'leader_2', - 'leader_2_', 'leader_3', 'leader_3_'] - - def get_record_data(self, obj): - return None \ No newline at end of file +class FirstTestAuditSerializer(serializers.Serializer): + leader = serializers.CharField() + base64 = serializers.CharField() \ No newline at end of file diff --git a/hb_server/apps/pm/views.py b/hb_server/apps/pm/views.py index e7bcfd2..e9f541b 100644 --- a/hb_server/apps/pm/views.py +++ b/hb_server/apps/pm/views.py @@ -5,23 +5,27 @@ from rest_framework import serializers from rest_framework.views import APIView from apps.em.models import Equipment from apps.em.serializers import EquipmentSimpleSerializer +from apps.hrm.services import HRMService from apps.inm.models import MaterialBatch from apps.inm.serializers import MaterialBatchSerializer -from apps.mtm.models import Material, Step, SubProduction, SubprodctionMaterial +from apps.mtm.models import Material, RecordFormField, Step, SubProduction, SubprodctionMaterial from apps.pm.filters import PlanFilterSet, SubproductionProgressFilterSet +from apps.qm.models import TestRecord, TestRecordItem from apps.system.mixins import CreateUpdateModelAMixin -from apps.pm.serializers import FirstTestInitSerializer, GenSubPlanSerializer, PickNeedSerializer, PlanDestorySerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, ResourceConvertListSerializer, ResourceConvertSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer +from apps.pm.serializers import FirstTestAuditSerializer, FirstTestInitSerializer, GenSubPlanSerializer, PickNeedSerializer, PlanDestorySerializer, ProductionPlanCreateFromOrderSerializer, ProductionPlanSerializer, ResourceCalListSerializer, ResourceCalSerializer, ResourceConvertListSerializer, ResourceConvertSerializer, SubProductionPlanListSerializer, SubProductionPlanUpdateSerializer, SubProductionProgressSerializer from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin from apps.pm.models import ProductionPlan, SubProductionProgress, SubProductionPlan from rest_framework.viewsets import GenericViewSet, ModelViewSet from django.shortcuts import render from apps.sam.models import Order -from rest_framework.exceptions import APIException, ParseError +from rest_framework.exceptions import APIException, ParseError, ValidationError from rest_framework.response import Response from rest_framework.decorators import action from django.db.models import F from utils.tools import ranstr from django.db import transaction +from rest_framework import status +from django.utils import timezone # Create your views here. def updateOrderPlanedCount(order): @@ -145,7 +149,9 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo 子生产计划-列表/修改 """ perms_map = {'get': '*', 'put':'subplan_update'} - queryset = SubProductionPlan.objects.select_related('process', 'workshop', 'subproduction', 'product', 'production_plan__product') + queryset = SubProductionPlan.objects.select_related('process', + 'workshop', 'subproduction', 'product', + 'production_plan__product', 'leader_1', 'leader_2', 'leader_3') search_fields = [] serializer_class = SubProductionPlanListSerializer filterset_fields = ['production_plan', 'process', 'state', 'product', 'workshop'] @@ -229,20 +235,64 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo have = MaterialBatchSerializer(instance=objs, many=True).data return Response({'need':need, 'have':have}) - @action(methods=['put'], detail=True, perms_map={'post':'first_test'}, serializer_class=FirstTestInitSerializer) + @action(methods=['post'], detail=True, perms_map={'post':'first_test'}, serializer_class=FirstTestInitSerializer) @transaction.atomic def first_test_init(self, request, pk=None): """ - 获取首件检查表 + 首件检查表初始化 """ obj = self.get_object() - if obj.is_testok is None: + if obj.first_test is None: rdata = request.data serializer = self.get_serializer(data=rdata) serializer.is_valid(raise_exception=True) form = serializer.validated_data.get('form') - - raise APIException('已经过首件确认') + savedict = dict( + create_by=request.user, + subproduction_plan=obj, + type = TestRecord.TEST_FIRST, + form=form) + tr = TestRecord.objects.create(**savedict) + for i in RecordFormField.objects.filter(form=form, is_deleted=False): + tri = TestRecordItem() + tri.test_record = tr + tri.form_field = i + tri.is_hidden = i.is_hidden + tri.create_by = request.user + tri.save() + return Response() + raise APIException('首件检查已存在') + + @action(methods=['post'], detail=True, perms_map={'post':'first_test_audit'}, serializer_class=FirstTestAuditSerializer) + @transaction.atomic + def first_audit(self, request, pk=None): + obj = self.get_object() + if obj.leader_1 and obj.leader_2 and obj.leader_3: + raise ValidationError('首件确认已完成') + if obj.first_test is None: + raise ValidationError('未进行首件检查') + if not obj.first_test.is_submited: + raise ValidationError('首件检查未提交') + if not obj.first_test.is_testok: + raise ValidationError('首件检查不合格') + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + vdata = serializer.validated_data + user, msg = HRMService.face_compare_from_base64(vdata.get('base64')) + if user: + le = vdata.get('leader') + if le not in ['leader_1', 'leader_2', 'leader_3']: + return Response('审核人有误', status=status.HTTP_400_BAD_REQUEST) + if vdata.get('leader') == 'leader_1': + obj.leader_1 = user + elif vdata.get('leader') == 'leader_2': + obj.leader_2 = user + else: + obj.leader_3 = user + obj.first_sign_time = timezone.now() + obj.save() + return Response() + return Response(msg, status=status.HTTP_400_BAD_REQUEST) diff --git a/hb_server/apps/qm/migrations/0025_alter_testrecord_type.py b/hb_server/apps/qm/migrations/0025_alter_testrecord_type.py new file mode 100644 index 0000000..5d7404c --- /dev/null +++ b/hb_server/apps/qm/migrations/0025_alter_testrecord_type.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.9 on 2022-02-21 02:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('qm', '0024_rename_is_midtesing_testrecord_is_midtesting'), + ] + + operations = [ + migrations.AlterField( + model_name='testrecord', + name='type', + field=models.PositiveSmallIntegerField(choices=[(20, '工序检验'), (30, '工序复检'), (36, '夹层检验'), (40, '成品检验'), (10, '首件检验')], default=20), + ), + ] diff --git a/hb_server/apps/qm/models.py b/hb_server/apps/qm/models.py index db776de..adb040a 100644 --- a/hb_server/apps/qm/models.py +++ b/hb_server/apps/qm/models.py @@ -47,6 +47,7 @@ class TestRecord(CommonADModel): """ 检验记录 """ + TEST_FIRST = 10 TEST_PROCESS = 20 TEST_PROCESS_RE = 30 TEST_COMB = 36 @@ -55,7 +56,8 @@ class TestRecord(CommonADModel): (TEST_PROCESS, '工序检验'), (TEST_PROCESS_RE, '工序复检'), (TEST_COMB, '夹层检验'), - (TEST_FINAL, '成品检验') + (TEST_FINAL, '成品检验'), + (TEST_FIRST, '首件检验') ) form = models.ForeignKey('mtm.recordform', verbose_name='所用表格', on_delete=models.CASCADE) type = models.PositiveSmallIntegerField(choices=type_choice, default=TEST_PROCESS) diff --git a/hb_server/apps/qm/views.py b/hb_server/apps/qm/views.py index 1151491..d46d6ce 100644 --- a/hb_server/apps/qm/views.py +++ b/hb_server/apps/qm/views.py @@ -93,7 +93,8 @@ class TestRecordViewSet(ListModelMixin, UpdateModelMixin, RetrieveModelMixin, De with transaction.atomic(): obj.is_submited=True obj.save() - WpmService.update_wproduct_by_test(obj, request.user) # 这里已经做了日志记录和进度计算 + if obj.wproduct: + WpmService.update_wproduct_by_test(obj, request.user) # 这里已经做了日志记录和进度计算 return Response() # def create(self, request, *args, **kwargs): diff --git a/hb_server/apps/wf/views.py b/hb_server/apps/wf/views.py index 3040daa..f223264 100644 --- a/hb_server/apps/wf/views.py +++ b/hb_server/apps/wf/views.py @@ -90,7 +90,7 @@ class WorkflowViewSet(CreateUpdateModelAMixin, ModelViewSet): class StateViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet): perms_map = {'get':'*', 'post':'workflow_update', - 'put':'workflow_update', 'delete':'workflow_delete'} + 'put':'workflow_update', 'delete':'workflow_update'} queryset = State.objects.all() serializer_class = StateSerializer search_fields = ['name'] @@ -99,7 +99,7 @@ class StateViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, Destr class TransitionViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet): perms_map = {'get':'*', 'post':'workflow_update', - 'put':'workflow_update', 'delete':'workflow_delete'} + 'put':'workflow_update', 'delete':'workflow_update'} queryset = Transition.objects.all() serializer_class = TransitionSerializer search_fields = ['name'] @@ -108,7 +108,7 @@ class TransitionViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, class CustomFieldViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet): perms_map = {'get':'*', 'post':'workflow_update', - 'put':'workflow_update', 'delete':'workflow_delete'} + 'put':'workflow_update', 'delete':'workflow_update'} queryset = CustomField.objects.all() serializer_class = CustomFieldSerializer search_fields = ['field_name'] diff --git a/hb_server/utils/response.py b/hb_server/utils/response.py index 776757f..2f60656 100644 --- a/hb_server/utils/response.py +++ b/hb_server/utils/response.py @@ -62,8 +62,8 @@ class FitJSONRenderer(JSONRenderer): if isinstance(data, list): data = data[0] - response_body.msg = prefix + ":" + str(data) # 取一部分放入msg,方便前端alert + response_body.msg = prefix + str(data) # 取一部分放入msg,方便前端alert else: response_body.data = data renderer_context.get("response").status_code = 200 # 统一成200响应, 可用body里code区分业务异常 - return super(FitJSONRenderer, self).render(response_body.dict, accepted_media_type, renderer_context) + return super(FitJSONRenderer, self).render(response_body.dict, accepted_media_type, renderer_context) \ No newline at end of file From 678cf5ffa9531912feaef8419d787433f54d979b Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 21 Feb 2022 11:11:25 +0800 Subject: [PATCH 7/7] =?UTF-8?q?splan=20=E5=A2=9E=E5=8A=A0first=5Ftest=5F?= =?UTF-8?q?=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/pm/migrations/0027_auto_20220221_1027.py | 5 ----- hb_server/apps/pm/models.py | 3 +-- hb_server/apps/pm/serializers.py | 2 ++ hb_server/apps/qm/models.py | 2 +- hb_server/apps/qm/serializers.py | 6 +++++- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/hb_server/apps/pm/migrations/0027_auto_20220221_1027.py b/hb_server/apps/pm/migrations/0027_auto_20220221_1027.py index a3891ff..ee1ca1b 100644 --- a/hb_server/apps/pm/migrations/0027_auto_20220221_1027.py +++ b/hb_server/apps/pm/migrations/0027_auto_20220221_1027.py @@ -29,11 +29,6 @@ class Migration(migrations.Migration): name='first_test', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='qm.testrecord'), ), - migrations.AddField( - model_name='subproductionplan', - name='first_test_state', - field=models.IntegerField(default=10, verbose_name='首件状态'), - ), migrations.DeleteModel( name='FirstItem', ), diff --git a/hb_server/apps/pm/models.py b/hb_server/apps/pm/models.py index 53d5e2f..7a06a16 100644 --- a/hb_server/apps/pm/models.py +++ b/hb_server/apps/pm/models.py @@ -91,8 +91,7 @@ class SubProductionPlan(CommonAModel): start_date_real = models.DateField('实际开工日期', null=True, blank=True) end_date_real = models.DateField('实际完工日期', null=True, blank=True) is_picked = models.BooleanField('是否已领料', default=False) - - first_test_state = models.IntegerField('首件状态', default=SUBPLAN_STATE_PLANING) + first_test = models.ForeignKey('qm.testrecord', on_delete=models.CASCADE, null=True, blank=True) leader_1 = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="工序负责人", null=True, blank=True, related_name='first_leader_1') diff --git a/hb_server/apps/pm/serializers.py b/hb_server/apps/pm/serializers.py index d32669c..470ad67 100644 --- a/hb_server/apps/pm/serializers.py +++ b/hb_server/apps/pm/serializers.py @@ -1,6 +1,7 @@ from apps.mtm.models import RecordForm from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress from rest_framework import serializers +from apps.qm.serializers import TestRecordShortSerializer from apps.sam.serializers import OrderSerializer, OrderSimpleSerializer from apps.mtm.serializers import MaterialSimpleSerializer, ProcessSimpleSerializer, RecordFormSimpleSerializer, SubProductionSimpleSerializer from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSerializer @@ -42,6 +43,7 @@ class SubProductionPlanListSerializer(DynamicFieldsSerializerMixin, serializers. leader_1_ = UserSimpleSerializer(source='leader_1', read_only=True) leader_2_ = UserSimpleSerializer(source='leader_2', read_only=True) leader_3_ = UserSimpleSerializer(source='leader_3', read_only=True) + first_test_ = TestRecordShortSerializer(source='first_test', read_only=True) class Meta: model=SubProductionPlan fields = '__all__' diff --git a/hb_server/apps/qm/models.py b/hb_server/apps/qm/models.py index adb040a..65c0cf3 100644 --- a/hb_server/apps/qm/models.py +++ b/hb_server/apps/qm/models.py @@ -61,7 +61,7 @@ class TestRecord(CommonADModel): ) form = models.ForeignKey('mtm.recordform', verbose_name='所用表格', on_delete=models.CASCADE) type = models.PositiveSmallIntegerField(choices=type_choice, default=TEST_PROCESS) - is_testok = models.BooleanField('是否合格', default=True) + is_testok = models.BooleanField('是否合格', null=True, blank=True) number = models.CharField('产品编号', null=True, blank=True, max_length=50) wproduct = models.ForeignKey('wpm.wproduct', verbose_name='关联的动态产品', on_delete=models.CASCADE, null=True, blank=True, related_name='test_wproduct') material = models.ForeignKey('mtm.material', verbose_name='关联的物料状态', on_delete=models.CASCADE, null=True, blank=True) diff --git a/hb_server/apps/qm/serializers.py b/hb_server/apps/qm/serializers.py index d1379c6..28a8829 100644 --- a/hb_server/apps/qm/serializers.py +++ b/hb_server/apps/qm/serializers.py @@ -63,7 +63,11 @@ class TestRecordItemSerializer(serializers.ModelSerializer): class Meta: model = TestRecordItem fields = '__all__' - + +class TestRecordShortSerializer(serializers.ModelSerializer): + class Meta: + model = TestRecord + fields = ['id', 'form', 'is_testok', 'is_submited'] class TestRecordCreateSerializer(serializers.ModelSerializer): record_data = TestRecordItemCreateSerializer(many=True) class Meta: