From 0a83b8c2c2e2b12ec4863eb787f870ff2f595b92 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 17 Jan 2022 14:39:37 +0800 Subject: [PATCH 01/19] =?UTF-8?q?=E9=A6=96=E9=A1=B5=E4=BA=A4=E4=BB=98?= =?UTF-8?q?=E4=BA=A7=E5=93=81=E6=95=B0=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/inm/filters.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hb_server/apps/inm/filters.py b/hb_server/apps/inm/filters.py index db876ec..bc97441 100644 --- a/hb_server/apps/inm/filters.py +++ b/hb_server/apps/inm/filters.py @@ -21,7 +21,8 @@ class MbFilterSet(filters.FilterSet): class IProductFilterSet(filters.FilterSet): order = filters.NumberFilter(field_name="wproduct__subproduction_plan__production_plan__order") - + update_time_start = filters.DateFilter(field_name="update_time", lookup_expr='gte') + update_time_end = filters.DateFilter(field_name="update_time", lookup_expr='lte') class Meta: model = IProduct - fields = ['material', 'warehouse', 'batch', 'order', 'material__type'] + fields = ['material', 'warehouse', 'batch', 'order', 'material__type', 'is_saled', 'update_time_start', 'update_time_end'] From b8824e94ac96308ece108a366f23ff5fd64806af Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 18 Jan 2022 08:42:26 +0800 Subject: [PATCH 02/19] =?UTF-8?q?=E5=88=9B=E5=BB=BA=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=97=B6=E5=90=8C=E6=AD=A5=E8=AE=BE=E5=A4=87=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0010_alter_equipment_state.py | 18 +++++++++++++++++ hb_server/apps/em/models.py | 15 +++++++++----- hb_server/apps/hrm/models.py | 8 ++++---- .../0023_alter_productionplan_order.py | 20 +++++++++++++++++++ .../migrations/0049_operationequip_state.py | 18 +++++++++++++++++ hb_server/apps/wpm/models.py | 1 + hb_server/apps/wpm/views.py | 1 + 7 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 hb_server/apps/em/migrations/0010_alter_equipment_state.py create mode 100644 hb_server/apps/pm/migrations/0023_alter_productionplan_order.py create mode 100644 hb_server/apps/wpm/migrations/0049_operationequip_state.py diff --git a/hb_server/apps/em/migrations/0010_alter_equipment_state.py b/hb_server/apps/em/migrations/0010_alter_equipment_state.py new file mode 100644 index 0000000..4f8de3c --- /dev/null +++ b/hb_server/apps/em/migrations/0010_alter_equipment_state.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.9 on 2022-01-18 00:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('em', '0009_auto_20210916_1108'), + ] + + operations = [ + migrations.AlterField( + model_name='equipment', + name='state', + field=models.PositiveIntegerField(choices=[(0, '完好'), (1, '限用'), (2, '在修'), (3, '禁用')], default=0, verbose_name='设备状态'), + ), + ] diff --git a/hb_server/apps/em/models.py b/hb_server/apps/em/models.py index f2cb67c..6838b99 100644 --- a/hb_server/apps/em/models.py +++ b/hb_server/apps/em/models.py @@ -14,11 +14,16 @@ class Equipment(CommonBModel): """ 设备台账信息 """ + EQUIP_STATE_OK = 0 + EQUIP_STATE_LIMIT = 1 + EQUIP_STATE_FIX = 2 + EQUIP_STATE_DISABLE = 3 state_choices = ( - (0, '完好'), - (1, '限用'), - (2, '在修'), - (3, '禁用') + (EQUIP_STATE_OK, '完好'), + (EQUIP_STATE_LIMIT, '限用'), + (EQUIP_STATE_FIX, '在修'), + (EQUIP_STATE_DISABLE, '禁用') + ) statedm_choices = ( (0, '合格'), @@ -54,7 +59,7 @@ class Equipment(CommonBModel): factory = models.CharField('生产厂', max_length=50, null=True, blank=True) production_date = models.DateField('生产日期', null=True, blank=True) buy_date = models.DateField('购置日期', null=True, blank=True) - state = models.CharField('设备状态', max_length=11, choices=state_choices, default=0) + state = models.PositiveIntegerField('设备状态', choices=state_choices, default=0) parameter = models.TextField('技术参数', null=True, blank=True) place = models.CharField('存放位置', max_length=50, null=True, blank=True) count = models.IntegerField('数量', default=0) diff --git a/hb_server/apps/hrm/models.py b/hb_server/apps/hrm/models.py index dc85cf5..5f95387 100644 --- a/hb_server/apps/hrm/models.py +++ b/hb_server/apps/hrm/models.py @@ -36,8 +36,8 @@ class Employee(CommonAModel): def __str__(self): return self.name -class Attendance(CommonADModel): - """ - 出勤记录 - """ +# class Attendance(CommonADModel): +# """ +# 出勤记录 +# """ \ No newline at end of file diff --git a/hb_server/apps/pm/migrations/0023_alter_productionplan_order.py b/hb_server/apps/pm/migrations/0023_alter_productionplan_order.py new file mode 100644 index 0000000..4fd00c6 --- /dev/null +++ b/hb_server/apps/pm/migrations/0023_alter_productionplan_order.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.9 on 2022-01-18 00:39 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('sam', '0010_auto_20211208_1408'), + ('pm', '0022_auto_20211229_1429'), + ] + + operations = [ + migrations.AlterField( + model_name='productionplan', + name='order', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='plan_order', to='sam.order', verbose_name='关联订单'), + ), + ] diff --git a/hb_server/apps/wpm/migrations/0049_operationequip_state.py b/hb_server/apps/wpm/migrations/0049_operationequip_state.py new file mode 100644 index 0000000..5541350 --- /dev/null +++ b/hb_server/apps/wpm/migrations/0049_operationequip_state.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.9 on 2022-01-18 00:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wpm', '0048_operationwproduct_place'), + ] + + operations = [ + migrations.AddField( + model_name='operationequip', + name='state', + field=models.PositiveSmallIntegerField(choices=[(0, '完好'), (1, '限用'), (2, '在修'), (3, '禁用')], default=0, verbose_name='当前设备状态'), + ), + ] diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py index dd870b4..b259eac 100644 --- a/hb_server/apps/wpm/models.py +++ b/hb_server/apps/wpm/models.py @@ -336,4 +336,5 @@ class OperationEquip(BaseModel): Operation, verbose_name='关联操作', on_delete=models.CASCADE, related_name='oe_operation') equip = models.ForeignKey(Equipment, verbose_name='生产设备', on_delete=models.CASCADE, related_name='oe_equip') + state = models.PositiveSmallIntegerField('当前设备状态', choices=Equipment.state_choices, default=Equipment.EQUIP_STATE_OK) remark = models.TextField('备注', null=True, blank=True) diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 28d8a12..475b0d1 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -559,6 +559,7 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd ope = OperationEquip() ope.operation = op ope.equip = i + ope.state = i.state ope.save() # 查询所需的工具工装 for i in SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL, From 8dcabaf8dc72dc413ed9b40ab76af075dcd0d737 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 19 Jan 2022 14:37:13 +0800 Subject: [PATCH 03/19] =?UTF-8?q?wproduct=20notok=E7=AD=9B=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + hb_server/apps/wpm/filters.py | 3 +++ hb_server/apps/wpm/views.py | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index fa116e5..2f02e50 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ deploy.sh package-lock.json .idea/ .vscode/ +.idea/ server/static/ \ No newline at end of file diff --git a/hb_server/apps/wpm/filters.py b/hb_server/apps/wpm/filters.py index c8392d3..d85c1cd 100644 --- a/hb_server/apps/wpm/filters.py +++ b/hb_server/apps/wpm/filters.py @@ -41,6 +41,9 @@ class WProductFilterSet(filters.FilterSet): def filter_tag(self, queryset, name, value): if value == 'no_scrap': queryset = queryset.exclude(act_state=WProduct.WPR_ACT_STATE_SCRAP) + elif value == 'notok': + queryset = queryset.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP])\ + .exclude(step__process__id = 1) # 不算冷加工的报废 return queryset diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 475b0d1..caababf 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -16,7 +16,7 @@ from rest_framework.decorators import action from apps.wf.models import Workflow from apps.wpm.filters import CuttingFilterSet, OperationRecordFilterSet, WMaterialFilterSet, WProductFilterSet from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, \ - OperationMaterial, OperationRecord, OperationRecordItem, WprouctTicket + OperationMaterial, OperationRecord, OperationRecordItem, WproductFlow, WprouctTicket from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerializer, OperationEquipUpdateSerializer, \ OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, \ From aa10f7cee12918fb74d95274206f601c7315277d Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 19 Jan 2022 14:41:00 +0800 Subject: [PATCH 04/19] wpm filter notok --- hb_server/apps/wpm/filters.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hb_server/apps/wpm/filters.py b/hb_server/apps/wpm/filters.py index d85c1cd..54454f8 100644 --- a/hb_server/apps/wpm/filters.py +++ b/hb_server/apps/wpm/filters.py @@ -44,6 +44,9 @@ class WProductFilterSet(filters.FilterSet): elif value == 'notok': queryset = queryset.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP])\ .exclude(step__process__id = 1) # 不算冷加工的报废 + elif value == 'ok': + queryset = queryset.filter(act_state__in=[WProduct.WPR_ACT_STATE_INM, + WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_SELLED]) return queryset From f29a5ee5e4f7873ebf296372985833fd8adb0b47 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 19 Jan 2022 15:04:03 +0800 Subject: [PATCH 05/19] =?UTF-8?q?=E9=A6=96=E9=A1=B5=E5=90=88=E6=A0=BC?= =?UTF-8?q?=E7=8E=87=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/srm/serializers.py | 6 +++- hb_server/apps/srm/urls.py | 3 +- hb_server/apps/srm/views.py | 47 +++++++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/hb_server/apps/srm/serializers.py b/hb_server/apps/srm/serializers.py index edea221..10e2b94 100644 --- a/hb_server/apps/srm/serializers.py +++ b/hb_server/apps/srm/serializers.py @@ -19,4 +19,8 @@ class PlanGanttSerializer(serializers.ModelSerializer): def get_children(self, obj): subplans = SubProductionPlan.objects.filter(production_plan=obj).order_by('process__number') - return SubplanGanttSerializer(instance=subplans, many=True).data \ No newline at end of file + return SubplanGanttSerializer(instance=subplans, many=True).data + +class ProcessYieldSerializer(serializers.Serializer): + datetime_start = serializers.DateField(label='开始时间', required=False, allow_null=True) + datetime_end = serializers.DateField(label='结束时间', required=False, allow_null=True) \ No newline at end of file diff --git a/hb_server/apps/srm/urls.py b/hb_server/apps/srm/urls.py index cbaf2ed..0d8a992 100644 --- a/hb_server/apps/srm/urls.py +++ b/hb_server/apps/srm/urls.py @@ -3,11 +3,12 @@ from rest_framework import urlpatterns from django.urls import path, include from rest_framework.routers import DefaultRouter -from apps.srm.views import GanttPlan +from apps.srm.views import GanttPlan, ProcessYieldView router = DefaultRouter() urlpatterns = [ path('gantt/plan/', GanttPlan.as_view()), + path('process/yield/', ProcessYieldView.as_view()), path('', include(router.urls)), ] diff --git a/hb_server/apps/srm/views.py b/hb_server/apps/srm/views.py index 4551f30..175c847 100644 --- a/hb_server/apps/srm/views.py +++ b/hb_server/apps/srm/views.py @@ -1,9 +1,14 @@ + from django.shortcuts import render from rest_framework import serializers -from rest_framework.generics import ListAPIView +from rest_framework.generics import ListAPIView, CreateAPIView +from rest_framework.views import APIView from rest_framework.response import Response +from apps.mtm.models import Process, Step from apps.pm.models import ProductionPlan, SubProductionPlan -from apps.srm.serializers import PlanGanttSerializer +from apps.srm.serializers import PlanGanttSerializer, ProcessYieldSerializer +from apps.wpm.models import WProduct, WproductFlow +from django.db.models import Count # Create your views here. class GanttPlan(ListAPIView): @@ -15,4 +20,42 @@ class GanttPlan(ListAPIView): queryset = ProductionPlan.objects.filter(is_deleted=False, is_planed=True).prefetch_related('subplan_plan', 'subplan_plan__process') ordering = ['-id'] +class ProcessYieldView(CreateAPIView): + """ + 工序成品率统计 + """ + perms_map = {'get':'*'} + serializer_class = ProcessYieldSerializer + + + def create(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + vdata = serializer.validated_data + wpfs = WproductFlow.objects.filter(is_lastlog=True) + if vdata.get('datetime_start', None): + wpfs = wpfs.filter(update_time__gte = vdata.get('datetime_start')) + if vdata.get('datetime_end', None): + wpfs = wpfs.filter(update_time__lte = vdata.get('datetime_end')) + # 根据产品日志记录进行聚合 + count_ok_g = list(wpfs.filter(act_state__in=[WProduct.WPR_ACT_STATE_INM, + WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_SELLED]).values('step__process__id').annotate(count_ok=Count('id'))) + count_notok_g = list(wpfs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP]).values('step__process__id', + ).annotate(count_notok=Count('id'))) + ret = [] + process_l = list(Process.objects.filter(is_deleted=False).order_by('number').values('id', 'name')) + for i in process_l: + ret_item = {'id':i['id'], 'name':i['name'], 'count_ok':0, 'count_notok':0, 'rate':0} + for m in count_ok_g: + if m['step__process__id'] == ret_item['id']: + ret_item['count_ok'] = m['count_ok'] + for n in count_notok_g: + if n['step__process__id'] == ret_item['id']: + ret_item['count_notok'] = n['count_notok'] + rate = (ret_item['count_ok']/(ret_item['count_ok']+ret_item['count_notok'])) \ + if ret_item['count_ok']+ret_item['count_notok']>0 else 0 + ret_item['rate'] = rate + ret.append(ret_item) + return Response(ret) + From 5c2751baa9a01af9e3527efff0d9d4c4efef4591 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 19 Jan 2022 15:06:51 +0800 Subject: [PATCH 06/19] =?UTF-8?q?=E9=A6=96=E9=A1=B5=E5=90=88=E6=A0=BC?= =?UTF-8?q?=E7=8E=87=E8=AE=A1=E7=AE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/srm/views.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hb_server/apps/srm/views.py b/hb_server/apps/srm/views.py index 175c847..57a6a75 100644 --- a/hb_server/apps/srm/views.py +++ b/hb_server/apps/srm/views.py @@ -45,7 +45,7 @@ class ProcessYieldView(CreateAPIView): ret = [] process_l = list(Process.objects.filter(is_deleted=False).order_by('number').values('id', 'name')) for i in process_l: - ret_item = {'id':i['id'], 'name':i['name'], 'count_ok':0, 'count_notok':0, 'rate':0} + ret_item = {'id':i['id'], 'name':i['name'], 'count_ok':0, 'count_notok':0, 'rate':1} for m in count_ok_g: if m['step__process__id'] == ret_item['id']: ret_item['count_ok'] = m['count_ok'] @@ -53,7 +53,7 @@ class ProcessYieldView(CreateAPIView): if n['step__process__id'] == ret_item['id']: ret_item['count_notok'] = n['count_notok'] rate = (ret_item['count_ok']/(ret_item['count_ok']+ret_item['count_notok'])) \ - if ret_item['count_ok']+ret_item['count_notok']>0 else 0 + if ret_item['count_ok']+ret_item['count_notok']>0 else 1 ret_item['rate'] = rate ret.append(ret_item) return Response(ret) From 65f0d9f1ee7296f7e0fc281477526738f177fc13 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 19 Jan 2022 15:17:19 +0800 Subject: [PATCH 07/19] =?UTF-8?q?=E4=BA=A7=E5=93=81=E5=88=86=E8=A7=A3?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0need=5Fcombtest=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../0044_subproduction_need_combtest.py | 18 ++++++++++++++++++ hb_server/apps/mtm/models.py | 1 + hb_server/apps/mtm/serializers.py | 5 +++++ hb_server/apps/mtm/views.py | 6 +++++- 4 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 hb_server/apps/mtm/migrations/0044_subproduction_need_combtest.py diff --git a/hb_server/apps/mtm/migrations/0044_subproduction_need_combtest.py b/hb_server/apps/mtm/migrations/0044_subproduction_need_combtest.py new file mode 100644 index 0000000..c570518 --- /dev/null +++ b/hb_server/apps/mtm/migrations/0044_subproduction_need_combtest.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.9 on 2022-01-19 07:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0043_auto_20220106_0942'), + ] + + operations = [ + migrations.AddField( + model_name='subproduction', + name='need_combtest', + field=models.BooleanField(default=False, verbose_name='需要质检'), + ), + ] diff --git a/hb_server/apps/mtm/models.py b/hb_server/apps/mtm/models.py index b7b99c2..4afb8b5 100644 --- a/hb_server/apps/mtm/models.py +++ b/hb_server/apps/mtm/models.py @@ -210,6 +210,7 @@ class SubProduction(CommonAModel): name = models.CharField('命名', max_length=50, null=True, blank=True) product = models.ForeignKey(Material, verbose_name='产品', on_delete=models.CASCADE) process = models.ForeignKey(Process, verbose_name='隶属大工序', on_delete=models.CASCADE, related_name='subproduction_process') + need_combtest = models.BooleanField('需要质检', default=False) sort = models.IntegerField('排序号', default=1) class Meta: diff --git a/hb_server/apps/mtm/serializers.py b/hb_server/apps/mtm/serializers.py index 8e5eb53..99cdfb6 100644 --- a/hb_server/apps/mtm/serializers.py +++ b/hb_server/apps/mtm/serializers.py @@ -72,6 +72,11 @@ class SubProductionSerializer(serializers.ModelSerializer): model = SubProduction fields = '__all__' +class SubProductionCreateUpdateSerializer(serializers.ModelSerializer): + class Meta: + model = SubProduction + fields = ['name', 'product', 'process', 'need_combtest', 'sort'] + class OtherMaterialSerializer(serializers.ModelSerializer): class Meta: model = SubprodctionMaterial diff --git a/hb_server/apps/mtm/views.py b/hb_server/apps/mtm/views.py index 04f3caa..1bb9e47 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, Process, RecordForm, RecordFormField, Step, SubprodctionMaterial, TechDoc, UsedStep, SubProduction -from apps.mtm.serializers import InputMaterialSerializer, InputMaterialUpdateSerializer, MaterialDetailSerializer, MaterialSerializer, MaterialSimpleSerializer, OtherMaterialSerializer, OutputMaterialSerializer, OutputMaterialUpdateSerializer, ProcessSerializer, RecordFormCreateSerializer, RecordFormDetailSerializer, RecordFormFieldCreateSerializer, RecordFormFieldSerializer, RecordFormFieldUpdateSerializer, RecordFormSerializer, RecordFormUpdateSerializer, StepDetailSerializer, StepSerializer, SubProductionSerializer, SubprodctionMaterialListSerializer, TechDocCreateSerializer, TechDocListSerializer, TechDocUpdateSerializer, UsedStepCreateSerializer, UsedStepListSerializer, UsedStepUpdateSerializer +from apps.mtm.serializers import InputMaterialSerializer, InputMaterialUpdateSerializer, MaterialDetailSerializer, MaterialSerializer, MaterialSimpleSerializer, OtherMaterialSerializer, OutputMaterialSerializer, OutputMaterialUpdateSerializer, 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 @@ -80,6 +80,10 @@ class SubProductionViewSet(CreateUpdateModelAMixin, ModelViewSet): search_fields = ['name'] serializer_class = SubProductionSerializer ordering = ['sort'] + def get_serializer_class(self): + if self.action in ['create', 'update']: + return SubProductionCreateUpdateSerializer + return super().get_serializer_class() class InputMaterialViewSet(CreateUpdateModelAMixin, ModelViewSet): """ From db270f79149fc2444b1ee1b2217d804400b03807 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Jan 2022 08:42:40 +0800 Subject: [PATCH 08/19] =?UTF-8?q?update=5Fwproduct=5Fby=5Ftest=20=E6=A0=B9?= =?UTF-8?q?=E6=8D=AE=E9=85=8D=E7=BD=AE=E6=98=AF=E5=90=A6=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E8=B4=A8=E6=A3=80=E5=86=B3=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/services.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hb_server/apps/wpm/services.py b/hb_server/apps/wpm/services.py index 3734106..76a585d 100644 --- a/hb_server/apps/wpm/services.py +++ b/hb_server/apps/wpm/services.py @@ -54,7 +54,8 @@ class WpmServies(object): elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and wproduct.material.type == Material.MA_TYPE_GOOD: # 成品检验 wproduct.act_state = WProduct.WPR_ACT_STATE_TOFINALTEST - elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and wproduct.step.type == Step.STEP_TYPE_COMB: # 夹层检验 + elif wproduct.act_state == WProduct.WPR_ACT_STATE_TOTEST and \ + wproduct.subproduction_plan.subproduction.need_combtest : # 配置中需要质检 wproduct.act_state = WProduct.WPR_ACT_STATE_TOCOMBTEST else: wproduct.act_state = WProduct.WPR_ACT_STATE_OK From d01ca7df0f0ef326d1001427e935596746b3c9b9 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Jan 2022 09:13:59 +0800 Subject: [PATCH 09/19] =?UTF-8?q?=E5=86=B7=E5=8A=A0=E5=B7=A5=E4=BA=A7?= =?UTF-8?q?=E5=93=81=E5=90=88=E6=A0=BC=E7=8E=87=E4=B8=BA1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/srm/views.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hb_server/apps/srm/views.py b/hb_server/apps/srm/views.py index 57a6a75..b5a7158 100644 --- a/hb_server/apps/srm/views.py +++ b/hb_server/apps/srm/views.py @@ -50,7 +50,9 @@ class ProcessYieldView(CreateAPIView): if m['step__process__id'] == ret_item['id']: ret_item['count_ok'] = m['count_ok'] for n in count_notok_g: - if n['step__process__id'] == ret_item['id']: + if n['step__process__id'] == 1: # 如果是冷加工 + ret['count_notok'] = ret_item['count_ok'] + elif n['step__process__id'] == ret_item['id']: ret_item['count_notok'] = n['count_notok'] rate = (ret_item['count_ok']/(ret_item['count_ok']+ret_item['count_notok'])) \ if ret_item['count_ok']+ret_item['count_notok']>0 else 1 From 8e8f231f72286d97c8ace09672e8e28542ec0f6a Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Jan 2022 09:58:32 +0800 Subject: [PATCH 10/19] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../em/migrations/0011_auto_20220120_0956.py | 63 +++++++++++++++++++ hb_server/apps/em/models.py | 42 +++++-------- hb_server/apps/em/serializers.py | 4 +- hb_server/apps/em/urls.py | 4 +- hb_server/apps/em/views.py | 7 ++- 5 files changed, 88 insertions(+), 32 deletions(-) create mode 100644 hb_server/apps/em/migrations/0011_auto_20220120_0956.py diff --git a/hb_server/apps/em/migrations/0011_auto_20220120_0956.py b/hb_server/apps/em/migrations/0011_auto_20220120_0956.py new file mode 100644 index 0000000..845ec26 --- /dev/null +++ b/hb_server/apps/em/migrations/0011_auto_20220120_0956.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.9 on 2022-01-20 01:56 + +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), + ('em', '0010_alter_equipment_state'), + ] + + operations = [ + migrations.CreateModel( + name='ECheckRecord', + 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='删除标记')), + ('check_date', models.DateField(blank=True, null=True, verbose_name='校准检查日期')), + ('description', models.CharField(blank=True, max_length=200, null=True, verbose_name='描述')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='echeckrecord_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.RemoveField( + model_name='equipment', + name='belong_dept', + ), + migrations.RemoveField( + model_name='equipment', + name='statedm', + ), + migrations.AddField( + model_name='equipment', + name='next_check_date', + field=models.DateField(blank=True, null=True, verbose_name='下次校准检查日期'), + ), + migrations.AlterField( + model_name='equipment', + name='state', + field=models.PositiveIntegerField(choices=[(10, '完好'), (20, '限用'), (30, '在修'), (40, '禁用')], default=0, verbose_name='设备状态'), + ), + migrations.DeleteModel( + name='Equipmentrecord', + ), + migrations.AddField( + model_name='echeckrecord', + name='equipment', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='em.equipment', verbose_name='校准检定设备'), + ), + migrations.AddField( + model_name='echeckrecord', + name='update_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='echeckrecord_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人'), + ), + ] diff --git a/hb_server/apps/em/models.py b/hb_server/apps/em/models.py index 6838b99..6b330e2 100644 --- a/hb_server/apps/em/models.py +++ b/hb_server/apps/em/models.py @@ -4,20 +4,19 @@ from django.db.models.base import Model import django.utils.timezone as timezone from django.db.models.query import QuerySet from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File -#from apps.mtm.models import Process from utils.model import SoftModel, BaseModel from simple_history.models import HistoricalRecords -class Equipment(CommonBModel): +class Equipment(CommonAModel): """ 设备台账信息 """ - EQUIP_STATE_OK = 0 - EQUIP_STATE_LIMIT = 1 - EQUIP_STATE_FIX = 2 - EQUIP_STATE_DISABLE = 3 + EQUIP_STATE_OK = 10 + EQUIP_STATE_LIMIT = 20 + EQUIP_STATE_FIX = 30 + EQUIP_STATE_DISABLE = 40 state_choices = ( (EQUIP_STATE_OK, '完好'), (EQUIP_STATE_LIMIT, '限用'), @@ -25,15 +24,6 @@ class Equipment(CommonBModel): (EQUIP_STATE_DISABLE, '禁用') ) - statedm_choices = ( - (0, '合格'), - (1, '准用'), - (2, '限用'), - (3, '禁用'), - (4, '停用'), - (5, '封存') - ) - type_choices = ( (1, '生产设备'), (2, '检验工具') @@ -65,14 +55,14 @@ class Equipment(CommonBModel): count = models.IntegerField('数量', default=0) keeper = models.ForeignKey(User, verbose_name='保管人', on_delete=models.CASCADE, null=True, blank=True) description = models.CharField('描述', max_length=200, blank=True, null=True) - #process = models.ForeignKey(Process, verbose_name='工序', on_delete=models.CASCADE, null=True, blank=True) - mgmtype = models.IntegerField('管理类别', choices=mgmtype_choices, default=1)#监视,测量设备 - way = models.IntegerField('校准或检定方式', choices=way_choices, default=1)#监视,测量设备 - standard = models.CharField('溯源标准或依据', max_length=200, blank=True, null=True)#监视,测量设备 - cycle = models.IntegerField('校准或检定周期', default=0)#监视,测量设备 - usetype = models.IntegerField('使用类别', choices=usetype_choices, default=1)#监视,测量设备 - statedm = models.IntegerField('设备状态', choices=statedm_choices, default=0)#监视,测量设备 + # 以下是监视测量设备单独字段 + mgmtype = models.IntegerField('管理类别', choices=mgmtype_choices, default=1) + way = models.IntegerField('校准或检定方式', choices=way_choices, default=1) + standard = models.CharField('溯源标准或依据', max_length=200, blank=True, null=True) + cycle = models.IntegerField('校准或检定周期', default=0) + usetype = models.IntegerField('使用类别', choices=usetype_choices, default=1) + next_check_date = models.DateField('下次校准检查日期',blank=True, null=True) class Meta: verbose_name = '设备信息' verbose_name_plural = verbose_name @@ -80,8 +70,10 @@ class Equipment(CommonBModel): def __str__(self): return self.number + '-' + self.name -class Equipmentrecord(CommonBModel): +class ECheckRecord(CommonAModel): + """ + 校准鉴定记录 + """ equipment = models.ForeignKey(Equipment, verbose_name='校准检定设备', on_delete=models.CASCADE, null=True, blank=True) - recentlydate = models.DateField('最近一次校准/检定日期',blank=True, null=True) - nextdate = models.DateField('下次应校准或检定日期',blank=True, null=True) + check_date = models.DateField('校准检查日期',blank=True, null=True) description = models.CharField('描述', max_length=200, blank=True, null=True) \ No newline at end of file diff --git a/hb_server/apps/em/serializers.py b/hb_server/apps/em/serializers.py index be34bfc..ce3908e 100644 --- a/hb_server/apps/em/serializers.py +++ b/hb_server/apps/em/serializers.py @@ -2,7 +2,7 @@ from apps.mtm.models import Step from rest_framework import serializers from rest_framework.serializers import ModelSerializer -from .models import Equipment,Equipmentrecord +from .models import Equipment, ECheckRecord from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSerializer @@ -34,7 +34,7 @@ class EquipmentSimpleSerializer(ModelSerializer): class EquipmentrecordSerializer(ModelSerializer): equipment_ = EquipmentSerializer(source='equipment', read_only=True) class Meta: - model = Equipmentrecord + model = ECheckRecord fields = '__all__' @staticmethod diff --git a/hb_server/apps/em/urls.py b/hb_server/apps/em/urls.py index e2f7e91..2fc4bb8 100644 --- a/hb_server/apps/em/urls.py +++ b/hb_server/apps/em/urls.py @@ -1,12 +1,12 @@ from django.db.models import base from rest_framework import urlpatterns -from apps.em.views import DaqView, EquipmentViewSet,EquipmentrecordViewSet +from apps.em.views import DaqView, EquipmentViewSet, EChcekRecordViewSet from django.urls import path, include from rest_framework.routers import DefaultRouter router = DefaultRouter() router.register('equipment', EquipmentViewSet, basename='equipment') -router.register('equipmentrecord', EquipmentrecordViewSet, basename='equipmentrecord') +router.register('echeck_record', EChcekRecordViewSet, basename='echeck_record') urlpatterns = [ path('daq/', DaqView.as_view()), path('', include(router.urls)), diff --git a/hb_server/apps/em/views.py b/hb_server/apps/em/views.py index 00ae4b9..7e526bf 100644 --- a/hb_server/apps/em/views.py +++ b/hb_server/apps/em/views.py @@ -5,7 +5,7 @@ from rest_framework.viewsets import ModelViewSet from rest_framework import serializers, status from rest_framework.response import Response -from apps.em.models import Equipment,Equipmentrecord +from apps.em.models import Equipment, ECheckRecord from apps.em.serializers import DaqCreateSerializer, EquipmentSerializer,EquipmentrecordSerializer from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin @@ -26,13 +26,13 @@ class EquipmentViewSet(CreateUpdateModelAMixin, OptimizationMixin, ModelViewSet) # Create your views here. -class EquipmentrecordViewSet(CreateUpdateModelAMixin, OptimizationMixin, ModelViewSet): +class EChcekRecordViewSet(CreateUpdateModelAMixin, OptimizationMixin, ModelViewSet): """ 设备校准-增删改查 """ perms_map = {'get': '*', 'post': 'equipmentrecord_create', 'put': 'equipmentrecord_update', 'delete': 'equipmentrecord_delete'} - queryset = Equipmentrecord.objects.all() + queryset = ECheckRecord.objects.all() serializer_class = EquipmentrecordSerializer filterset_fields = ['equipment'] ordering_fields = ['create_time'] @@ -49,6 +49,7 @@ class EquipmentrecordViewSet(CreateUpdateModelAMixin, OptimizationMixin, ModelVi serializer.is_valid(raise_exception=True) serializer.save() return Response(status=status.HTTP_200_OK) + def update(self, request, *args, **kwargs): data = request.data if data.get('equipment', None): From cf19c022fae5830f7ea032369de4a7d8ad9f1d18 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Jan 2022 10:47:31 +0800 Subject: [PATCH 11/19] =?UTF-8?q?em=20=E6=9B=B4=E6=96=B0=E6=A3=80=E6=B5=8B?= =?UTF-8?q?=E6=97=A5=E6=9C=9F=20=E6=9C=AA=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/em/models.py | 20 +++++++--- hb_server/apps/em/serializers.py | 26 +++++++++--- hb_server/apps/em/services.py | 7 ++++ hb_server/apps/em/views.py | 68 +++++++++++++++++--------------- hb_server/apps/pm/views.py | 4 +- 5 files changed, 80 insertions(+), 45 deletions(-) create mode 100644 hb_server/apps/em/services.py diff --git a/hb_server/apps/em/models.py b/hb_server/apps/em/models.py index 6b330e2..194474f 100644 --- a/hb_server/apps/em/models.py +++ b/hb_server/apps/em/models.py @@ -3,7 +3,7 @@ from django.contrib.auth.models import AbstractUser from django.db.models.base import Model import django.utils.timezone as timezone from django.db.models.query import QuerySet -from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File +from apps.system.models import CommonADModel, CommonAModel, CommonBModel, Organization, User, Dict, File from utils.model import SoftModel, BaseModel from simple_history.models import HistoricalRecords @@ -24,6 +24,13 @@ class Equipment(CommonAModel): (EQUIP_STATE_DISABLE, '禁用') ) + state2_choices = ( + (EQUIP_STATE_OK, '合格'), + (EQUIP_STATE_DISABLE, '禁用') + + ) + EQUIP_TYPE_PRO = 1 + EQUIP_TYPE_TEST = 2 type_choices = ( (1, '生产设备'), (2, '检验工具') @@ -59,10 +66,11 @@ class Equipment(CommonAModel): mgmtype = models.IntegerField('管理类别', choices=mgmtype_choices, default=1) way = models.IntegerField('校准或检定方式', choices=way_choices, default=1) standard = models.CharField('溯源标准或依据', max_length=200, blank=True, null=True) - cycle = models.IntegerField('校准或检定周期', default=0) + cycle = models.IntegerField('校准或检定周期(月)', null=True, blank=True) usetype = models.IntegerField('使用类别', choices=usetype_choices, default=1) - next_check_date = models.DateField('下次校准检查日期',blank=True, null=True) + check_date = models.DateField('最近校准检查日期', blank=True, null=True) + next_check_date = models.DateField('预计下次校准检查日期',blank=True, null=True) class Meta: verbose_name = '设备信息' verbose_name_plural = verbose_name @@ -70,10 +78,10 @@ class Equipment(CommonAModel): def __str__(self): return self.number + '-' + self.name -class ECheckRecord(CommonAModel): +class ECheckRecord(CommonADModel): """ 校准鉴定记录 """ - equipment = models.ForeignKey(Equipment, verbose_name='校准检定设备', on_delete=models.CASCADE, null=True, blank=True) - check_date = models.DateField('校准检查日期',blank=True, null=True) + equipment = models.ForeignKey(Equipment, verbose_name='校准检定设备', on_delete=models.CASCADE) + check_date = models.DateField('校准检查日期') description = models.CharField('描述', max_length=200, blank=True, null=True) \ No newline at end of file diff --git a/hb_server/apps/em/serializers.py b/hb_server/apps/em/serializers.py index ce3908e..89900d3 100644 --- a/hb_server/apps/em/serializers.py +++ b/hb_server/apps/em/serializers.py @@ -1,12 +1,12 @@ from apps.mtm.models import Step from rest_framework import serializers from rest_framework.serializers import ModelSerializer - +from rest_framework import exceptions from .models import Equipment, ECheckRecord from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSerializer -class EquipmentSerializer(ModelSerializer): +class EquipmentListSerializer(ModelSerializer): belong_dept_ = OrganizationSimpleSerializer(source='belong_dept', read_only=True) keeper_ = UserSimpleSerializer(source='keeper', read_only=True) step_ = serializers.SerializerMethodField() @@ -24,15 +24,26 @@ class EquipmentSerializer(ModelSerializer): return Step.objects.filter(equipments=obj).values('id', 'name', 'number') +class EquipmentCreateUpdateSerializer(ModelSerializer): + class Meta: + model = Equipment + exclude = ['create_by', 'update_by', 'create_time', 'update_time'] + + def validate(self, attrs): + if attrs['type'] == Equipment.EQUIP_TYPE_TEST: + if attrs['state'] not in [Equipment.EQUIP_STATE_OK, Equipment.EQUIP_STATE_DISABLE]: + raise exceptions.APIException('设备状态错误') + return super().validate(attrs) + class EquipmentSimpleSerializer(ModelSerializer): class Meta: model = Equipment - fields = ['id', 'number', 'name', 'state'] + fields = ['id', 'number', 'name', 'state', 'model'] -class EquipmentrecordSerializer(ModelSerializer): - equipment_ = EquipmentSerializer(source='equipment', read_only=True) +class ECheckRecordListSerializer(ModelSerializer): + equipment_ = EquipmentSimpleSerializer(source='equipment', read_only=True) class Meta: model = ECheckRecord fields = '__all__' @@ -43,6 +54,11 @@ class EquipmentrecordSerializer(ModelSerializer): queryset = queryset.select_related('equipment') return queryset +class EChcekRecordCreateSerializer(ModelSerializer): + class Meta: + model = ECheckRecord + fields = ['equipment', 'check_date', 'description'] + class DaqCreateSerializer(serializers.Serializer): number = serializers.CharField() file = serializers.FileField() \ No newline at end of file diff --git a/hb_server/apps/em/services.py b/hb_server/apps/em/services.py new file mode 100644 index 0000000..0f05e39 --- /dev/null +++ b/hb_server/apps/em/services.py @@ -0,0 +1,7 @@ +from apps.em.models import Equipment +class EmService: + + @classmethod + def update_check_date(cls, equip:Equipment): + # 根据校准检定记录变更下次日期 + pass \ No newline at end of file diff --git a/hb_server/apps/em/views.py b/hb_server/apps/em/views.py index 7e526bf..0d19abe 100644 --- a/hb_server/apps/em/views.py +++ b/hb_server/apps/em/views.py @@ -1,14 +1,20 @@ +from datetime import timedelta from django.shortcuts import render +from numpy import delete from rest_framework.exceptions import APIException from rest_framework.views import APIView -from rest_framework.viewsets import ModelViewSet - +from rest_framework.viewsets import ModelViewSet, GenericViewSet +from rest_framework.mixins import CreateModelMixin, RetrieveModelMixin, ListModelMixin, DestroyModelMixin from rest_framework import serializers, status from rest_framework.response import Response from apps.em.models import Equipment, ECheckRecord -from apps.em.serializers import DaqCreateSerializer, EquipmentSerializer,EquipmentrecordSerializer +from apps.em.serializers import DaqCreateSerializer, EChcekRecordCreateSerializer, ECheckRecordListSerializer, \ + EquipmentCreateUpdateSerializer, EquipmentListSerializer +from apps.em.services import EmService from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin - +from dateutil.relativedelta import relativedelta +from django.utils import timezone +from django.db import transaction # Create your views here. class EquipmentViewSet(CreateUpdateModelAMixin, OptimizationMixin, ModelViewSet): @@ -18,49 +24,47 @@ class EquipmentViewSet(CreateUpdateModelAMixin, OptimizationMixin, ModelViewSet) perms_map = {'get': '*', 'post': 'equipment_create', 'put': 'equipment_update', 'delete': 'equipment_delete'} queryset = Equipment.objects.all() - serializer_class = EquipmentSerializer + serializer_class = EquipmentListSerializer search_fields = ['number', 'name','description'] - filterset_fields = ['belong_dept', 'keeper', 'type'] + filterset_fields = ['keeper', 'type'] ordering_fields = ['create_time'] ordering = ['-create_time'] + def get_serializer_class(self): + if self.action in ['create', 'update']: + return EquipmentCreateUpdateSerializer + return super().get_serializer_class() # Create your views here. -class EChcekRecordViewSet(CreateUpdateModelAMixin, OptimizationMixin, ModelViewSet): +class EChcekRecordViewSet(CreateUpdateModelAMixin, OptimizationMixin, + CreateModelMixin, RetrieveModelMixin, ListModelMixin, DestroyModelMixin, GenericViewSet): """ 设备校准-增删改查 """ - perms_map = {'get': '*', 'post': 'equipmentrecord_create', - 'put': 'equipmentrecord_update', 'delete': 'equipmentrecord_delete'} + perms_map = {'get': '*', 'post': 'echeckrecord_create', 'delete': 'echeckrecord_delete'} queryset = ECheckRecord.objects.all() - serializer_class = EquipmentrecordSerializer + serializer_class = ECheckRecordListSerializer filterset_fields = ['equipment'] - ordering_fields = ['create_time'] - ordering = ['-create_time'] + ordering = ['-id'] + def get_serializer_class(self): + if self.action in ['create']: + return EChcekRecordCreateSerializer + return super().get_serializer_class() + + @transaction.atomic def create(self, request, *args, **kwargs): - - data = request.data - if data.get('equipment', None): - equipment = Equipment.objects.get(pk=data['equipment']) - equipment.statedm = data['state'] - equipment.save() serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) - serializer.save() - return Response(status=status.HTTP_200_OK) - - def update(self, request, *args, **kwargs): - data = request.data - if data.get('equipment', None): - equipment = Equipment.objects.get(pk=data['equipment']) - equipment.statedm = data['state'] - equipment.save() - id = self.get_object() - serializer = self.get_serializer(id, data=data) - serializer.is_valid(raise_exception=True) - serializer.save() - return Response(status=status.HTTP_200_OK) + instance = serializer.save(create_by=request.user) + EmService.update_check_date(equip=instance) + return Response() + + def destroy(self, request, *args, **kwargs): + instance = self.get_object() + EmService.update_check_date(equip=instance) + instance.delete() + return super().destroy(request, *args, **kwargs) import uuid import os diff --git a/hb_server/apps/pm/views.py b/hb_server/apps/pm/views.py index 3fe8799..3761ead 100644 --- a/hb_server/apps/pm/views.py +++ b/hb_server/apps/pm/views.py @@ -4,7 +4,7 @@ from django.db import transaction from rest_framework import serializers from rest_framework.views import APIView from apps.em.models import Equipment -from apps.em.serializers import EquipmentSerializer +from apps.em.serializers import EquipmentSimpleSerializer from apps.inm.models import MaterialBatch from apps.inm.serializers import MaterialBatchSerializer from apps.mtm.models import Step, SubProduction, SubprodctionMaterial, UsedStep @@ -248,5 +248,5 @@ class ResourceViewSet(GenericViewSet): subproductions = SubProduction.objects.filter(product__id__in=rdata_l, is_deleted=False) steps = Step.objects.filter(usedstep__is_deleted=False, usedstep__subproduction__in=subproductions) equips = Equipment.objects.filter(step_equips__in=steps, is_deleted=False).distinct() - serializer = EquipmentSerializer(instance=equips, many=True) + serializer = EquipmentSimpleSerializer(instance=equips, many=True) return Response(serializer.data) From e4c7f4856cbf603ee6a78bc4297645c23739cc92 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Jan 2022 10:49:05 +0800 Subject: [PATCH 12/19] =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../em/migrations/0012_auto_20220120_1048.py | 43 +++++++++++++++++++ .../0050_alter_operationequip_state.py | 18 ++++++++ 2 files changed, 61 insertions(+) create mode 100644 hb_server/apps/em/migrations/0012_auto_20220120_1048.py create mode 100644 hb_server/apps/wpm/migrations/0050_alter_operationequip_state.py diff --git a/hb_server/apps/em/migrations/0012_auto_20220120_1048.py b/hb_server/apps/em/migrations/0012_auto_20220120_1048.py new file mode 100644 index 0000000..a0aff45 --- /dev/null +++ b/hb_server/apps/em/migrations/0012_auto_20220120_1048.py @@ -0,0 +1,43 @@ +# Generated by Django 3.2.9 on 2022-01-20 02:48 + +import datetime +from django.db import migrations, models +import django.db.models.deletion +from django.utils.timezone import utc + + +class Migration(migrations.Migration): + + dependencies = [ + ('em', '0011_auto_20220120_0956'), + ] + + operations = [ + migrations.AddField( + model_name='equipment', + name='check_date', + field=models.DateField(blank=True, null=True, verbose_name='最近校准检查日期'), + ), + migrations.AlterField( + model_name='echeckrecord', + name='check_date', + field=models.DateField(default=datetime.datetime(2022, 1, 20, 2, 48, 20, 706844, tzinfo=utc), verbose_name='校准检查日期'), + preserve_default=False, + ), + migrations.AlterField( + model_name='echeckrecord', + name='equipment', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='em.equipment', verbose_name='校准检定设备'), + preserve_default=False, + ), + migrations.AlterField( + model_name='equipment', + name='cycle', + field=models.IntegerField(blank=True, null=True, verbose_name='校准或检定周期(月)'), + ), + migrations.AlterField( + model_name='equipment', + name='next_check_date', + field=models.DateField(blank=True, null=True, verbose_name='预计下次校准检查日期'), + ), + ] diff --git a/hb_server/apps/wpm/migrations/0050_alter_operationequip_state.py b/hb_server/apps/wpm/migrations/0050_alter_operationequip_state.py new file mode 100644 index 0000000..a04569a --- /dev/null +++ b/hb_server/apps/wpm/migrations/0050_alter_operationequip_state.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.9 on 2022-01-20 02:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('wpm', '0049_operationequip_state'), + ] + + operations = [ + migrations.AlterField( + model_name='operationequip', + name='state', + field=models.PositiveSmallIntegerField(choices=[(10, '完好'), (20, '限用'), (30, '在修'), (40, '禁用')], default=10, verbose_name='当前设备状态'), + ), + ] From accfedb1d75ee8e645fbd5ded38d659ad1514657 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Jan 2022 10:57:32 +0800 Subject: [PATCH 13/19] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=A0=A1=E5=87=86?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E5=8F=98=E6=9B=B4=E4=B8=8B=E6=AC=A1=E6=A0=A1?= =?UTF-8?q?=E5=87=86=E6=97=A5=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/em/serializers.py | 2 +- hb_server/apps/em/services.py | 15 +++++++++++++-- hb_server/apps/em/views.py | 9 +++++---- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/hb_server/apps/em/serializers.py b/hb_server/apps/em/serializers.py index 89900d3..e60b2a4 100644 --- a/hb_server/apps/em/serializers.py +++ b/hb_server/apps/em/serializers.py @@ -27,7 +27,7 @@ class EquipmentListSerializer(ModelSerializer): class EquipmentCreateUpdateSerializer(ModelSerializer): class Meta: model = Equipment - exclude = ['create_by', 'update_by', 'create_time', 'update_time'] + exclude = ['create_by', 'update_by', 'create_time', 'update_time', 'check_date', 'next_check_date'] def validate(self, attrs): if attrs['type'] == Equipment.EQUIP_TYPE_TEST: diff --git a/hb_server/apps/em/services.py b/hb_server/apps/em/services.py index 0f05e39..15f5b08 100644 --- a/hb_server/apps/em/services.py +++ b/hb_server/apps/em/services.py @@ -1,7 +1,18 @@ -from apps.em.models import Equipment +from tabnanny import check +from apps.em.models import ECheckRecord, Equipment +from dateutil.relativedelta import relativedelta +from django.utils import timezone class EmService: @classmethod def update_check_date(cls, equip:Equipment): # 根据校准检定记录变更下次日期 - pass \ No newline at end of file + check = ECheckRecord.objects.filter(equipment=equip).order_by('id').last() + if check: + if equip.cycle: + equip.check_date = check.check_date + if equip.next_check_date: + equip.next_check_date = equip.next_check_date + relativedelta(months=equip.cycle) + else: + equip.next_check_date = timezone.now() + relativedelta(months=equip.cycle) + equip.save() \ No newline at end of file diff --git a/hb_server/apps/em/views.py b/hb_server/apps/em/views.py index 0d19abe..aec05f7 100644 --- a/hb_server/apps/em/views.py +++ b/hb_server/apps/em/views.py @@ -12,7 +12,7 @@ from apps.em.serializers import DaqCreateSerializer, EChcekRecordCreateSerialize EquipmentCreateUpdateSerializer, EquipmentListSerializer from apps.em.services import EmService from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin -from dateutil.relativedelta import relativedelta + from django.utils import timezone from django.db import transaction @@ -57,14 +57,15 @@ class EChcekRecordViewSet(CreateUpdateModelAMixin, OptimizationMixin, serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) instance = serializer.save(create_by=request.user) - EmService.update_check_date(equip=instance) + EmService.update_check_date(equip=instance.equipment) return Response() + @transaction.atomic def destroy(self, request, *args, **kwargs): instance = self.get_object() - EmService.update_check_date(equip=instance) instance.delete() - return super().destroy(request, *args, **kwargs) + EmService.update_check_date(equip=instance.equipment) + return Response() import uuid import os From ddc54a8c762d081fa04c71ad58e0a21c065a0b8f Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Jan 2022 11:01:18 +0800 Subject: [PATCH 14/19] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E8=AF=B7=E6=B1=82bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/em/serializers.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hb_server/apps/em/serializers.py b/hb_server/apps/em/serializers.py index e60b2a4..c22238d 100644 --- a/hb_server/apps/em/serializers.py +++ b/hb_server/apps/em/serializers.py @@ -7,7 +7,6 @@ from apps.system.serializers import OrganizationSimpleSerializer, UserSimpleSeri class EquipmentListSerializer(ModelSerializer): - belong_dept_ = OrganizationSimpleSerializer(source='belong_dept', read_only=True) keeper_ = UserSimpleSerializer(source='keeper', read_only=True) step_ = serializers.SerializerMethodField() class Meta: @@ -17,7 +16,7 @@ class EquipmentListSerializer(ModelSerializer): @staticmethod def setup_eager_loading(queryset): """ Perform necessary eager loading of data. """ - queryset = queryset.select_related('belong_dept','keeper') + queryset = queryset.select_related('keeper') return queryset def get_step_(self, obj): From b9a9aa2091d1360aba286d38d02d8323f622e411 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Jan 2022 13:21:59 +0800 Subject: [PATCH 15/19] update check date bug --- hb_server/apps/em/services.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/hb_server/apps/em/services.py b/hb_server/apps/em/services.py index 15f5b08..0c1eba4 100644 --- a/hb_server/apps/em/services.py +++ b/hb_server/apps/em/services.py @@ -8,11 +8,13 @@ class EmService: def update_check_date(cls, equip:Equipment): # 根据校准检定记录变更下次日期 check = ECheckRecord.objects.filter(equipment=equip).order_by('id').last() + equip.check_date = check.check_date if check: if equip.cycle: - equip.check_date = check.check_date - if equip.next_check_date: - equip.next_check_date = equip.next_check_date + relativedelta(months=equip.cycle) - else: - equip.next_check_date = timezone.now() + relativedelta(months=equip.cycle) - equip.save() \ No newline at end of file + equip.next_check_date = equip.check_date + relativedelta(months=equip.cycle) + else: + equip.next_check_date = None + else: + equip.check_date = None + equip.next_check_date = None + equip.save() \ No newline at end of file From 0c5601f53afc0fa658a113c3eda55e9a66cb9a64 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Jan 2022 13:23:04 +0800 Subject: [PATCH 16/19] update check date bug --- hb_server/apps/em/services.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hb_server/apps/em/services.py b/hb_server/apps/em/services.py index 0c1eba4..5e1781c 100644 --- a/hb_server/apps/em/services.py +++ b/hb_server/apps/em/services.py @@ -8,8 +8,8 @@ class EmService: def update_check_date(cls, equip:Equipment): # 根据校准检定记录变更下次日期 check = ECheckRecord.objects.filter(equipment=equip).order_by('id').last() - equip.check_date = check.check_date if check: + equip.check_date = check.check_date if equip.cycle: equip.next_check_date = equip.check_date + relativedelta(months=equip.cycle) else: From 7f4da0221ca8d4b10bae85e8cdaee09bbc6ba0fa Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Jan 2022 13:50:30 +0800 Subject: [PATCH 17/19] =?UTF-8?q?=E5=86=B7=E5=8A=A0=E5=B7=A5=E7=9A=84?= =?UTF-8?q?=E5=90=88=E6=A0=BC=E7=8E=87=E5=8D=95=E7=8B=AC=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/develop/urls.py | 5 +++-- hb_server/apps/develop/views.py | 13 ++++++++++++- hb_server/apps/srm/views.py | 12 ++++++++---- hb_server/apps/wpm/services.py | 6 +++++- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/hb_server/apps/develop/urls.py b/hb_server/apps/develop/urls.py index b284243..79f8f04 100644 --- a/hb_server/apps/develop/urls.py +++ b/hb_server/apps/develop/urls.py @@ -2,13 +2,14 @@ from django.db.models import base from rest_framework import urlpatterns from django.urls import path, include from rest_framework.routers import DefaultRouter -from apps.develop.views import CleanDataView, UpdateCuttingView, UpdateFIFOItem, UpdateLastTestResult +from apps.develop.views import CleanDataView, UpdateCuttingView, UpdateFIFOItem, UpdateLastTestResult, UpdateSpg urlpatterns = [ path('cleandata/', CleanDataView.as_view()), path('update_cutting/', UpdateCuttingView.as_view()), path('update_last_result/', UpdateLastTestResult.as_view()), path('update_last_result/', UpdateLastTestResult.as_view()), - path('update_fifoitem/', UpdateFIFOItem.as_view()) + path('update_fifoitem/', UpdateFIFOItem.as_view()), + path('update_spg/', UpdateSpg.as_view()) ] diff --git a/hb_server/apps/develop/views.py b/hb_server/apps/develop/views.py index f02f55f..f6a52fc 100644 --- a/hb_server/apps/develop/views.py +++ b/hb_server/apps/develop/views.py @@ -6,7 +6,7 @@ from rest_framework.permissions import IsAdminUser from rest_framework.response import Response from apps.inm.models import FIFO, FIFOItem, Inventory, MaterialBatch from apps.mtm.models import Material -from apps.pm.models import ProductionPlan +from apps.pm.models import ProductionPlan, SubProductionPlan from apps.sam.models import Order from apps.wf.models import Ticket from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow @@ -80,3 +80,14 @@ class UpdateFIFOItem(APIView): i.is_testok = None i.save() return Response() + +class UpdateSpg(APIView): + permission_classes = [IsAdminUser] + @transaction.atomic + def post(self, request, format=None): + """ + 冷加工重新计算合格率 + """ + for i in SubProductionPlan.objects.filter(subproduction__process__id=1): + WpmServies.update_subproduction_progress_main(sp=i) + return Response() diff --git a/hb_server/apps/srm/views.py b/hb_server/apps/srm/views.py index b5a7158..ec7a398 100644 --- a/hb_server/apps/srm/views.py +++ b/hb_server/apps/srm/views.py @@ -40,7 +40,13 @@ class ProcessYieldView(CreateAPIView): # 根据产品日志记录进行聚合 count_ok_g = list(wpfs.filter(act_state__in=[WProduct.WPR_ACT_STATE_INM, WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_SELLED]).values('step__process__id').annotate(count_ok=Count('id'))) - count_notok_g = list(wpfs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP]).values('step__process__id', + count_notok_g = list( + ( + wpfs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP]).exclude(step__process__id=1) + | wpfs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP], + step__process__id=1).exclude(number=None) + )\ + .values('step__process__id', ).annotate(count_notok=Count('id'))) ret = [] process_l = list(Process.objects.filter(is_deleted=False).order_by('number').values('id', 'name')) @@ -50,9 +56,7 @@ class ProcessYieldView(CreateAPIView): if m['step__process__id'] == ret_item['id']: ret_item['count_ok'] = m['count_ok'] for n in count_notok_g: - if n['step__process__id'] == 1: # 如果是冷加工 - ret['count_notok'] = ret_item['count_ok'] - elif n['step__process__id'] == ret_item['id']: + if n['step__process__id'] == ret_item['id']: ret_item['count_notok'] = n['count_notok'] rate = (ret_item['count_ok']/(ret_item['count_ok']+ret_item['count_notok'])) \ if ret_item['count_ok']+ret_item['count_notok']>0 else 1 diff --git a/hb_server/apps/wpm/services.py b/hb_server/apps/wpm/services.py index 76a585d..d880f7f 100644 --- a/hb_server/apps/wpm/services.py +++ b/hb_server/apps/wpm/services.py @@ -114,7 +114,11 @@ class WpmServies(object): objs = WproductFlow.objects.filter(subproduction_plan=sp, is_lastlog=True) count_ok = objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_INM, WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_SELLED]).count() - count_notok = objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP]).count() + count_notok = ( + objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP]).exclude(step__process__id=1) + | objs.filter(act_state__in=[WProduct.WPR_ACT_STATE_NOTOK, WProduct.WPR_ACT_STATE_SCRAP], + step__process__id=1).exclude(number=None) + ).count() count_real = objs.exclude(act_state__in=[WProduct.WPR_ACT_STATE_TORETEST, WProduct.WPR_ACT_STATE_DOWAIT, WProduct.WPR_ACT_STATE_DOING]).count() ins = SubProductionProgress.objects.filter(subproduction_plan=sp, From b8346d90b94ed52111608162f7e541ce363487cf Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Jan 2022 15:41:47 +0800 Subject: [PATCH 18/19] =?UTF-8?q?wproduct=20=E6=8C=87=E6=B4=BE=E8=AE=A2?= =?UTF-8?q?=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wpm/migrations/0051_auto_20220120_1541.py | 25 +++++++++++++++++ hb_server/apps/wpm/models.py | 5 ++-- hb_server/apps/wpm/serializers.py | 7 ++++- hb_server/apps/wpm/views.py | 28 +++++++++++++++++-- hb_server/utils/response.py | 25 +++++++++-------- 5 files changed, 74 insertions(+), 16 deletions(-) create mode 100644 hb_server/apps/wpm/migrations/0051_auto_20220120_1541.py diff --git a/hb_server/apps/wpm/migrations/0051_auto_20220120_1541.py b/hb_server/apps/wpm/migrations/0051_auto_20220120_1541.py new file mode 100644 index 0000000..9a0c6fb --- /dev/null +++ b/hb_server/apps/wpm/migrations/0051_auto_20220120_1541.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.9 on 2022-01-20 07:41 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('sam', '0010_auto_20211208_1408'), + ('wpm', '0050_alter_operationequip_state'), + ] + + operations = [ + migrations.AddField( + model_name='wproduct', + name='to_order', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sam.order', verbose_name='指派的订单'), + ), + migrations.AddField( + model_name='wproductflow', + name='to_order', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='sam.order', verbose_name='指派的订单'), + ), + ] diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py index b259eac..c52a061 100644 --- a/hb_server/apps/wpm/models.py +++ b/hb_server/apps/wpm/models.py @@ -118,7 +118,8 @@ class WProduct(CommonAModel): on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_test') ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单', on_delete=models.SET_NULL, null=True, blank=True, related_name='wp_ticket') - + + to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE) is_mtested = models.BooleanField('是否军检', default=False) is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True) remark_mtest = models.TextField('军检备注', null=True, blank=True) @@ -192,7 +193,7 @@ class WproductFlow(CommonAModel): on_delete=models.SET_NULL, null=True, blank=True) ticket = models.ForeignKey('wf.ticket', verbose_name='当前工单', on_delete=models.SET_NULL, null=True, blank=True) - + to_order = models.ForeignKey('sam.order', verbose_name='指派的订单', null=True, blank=True, on_delete = models.CASCADE) is_mtested = models.BooleanField('是否军检', default=False) is_mtestok = models.BooleanField('是否军检合格', null=True, blank=True) remark_mtest = models.TextField('军检备注', null=True, blank=True) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 8956eb3..3e245ef 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -19,6 +19,7 @@ from apps.system.models import User from apps.system.serializers import UserSimpleSerializer from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, Pick, WMaterial, WProduct, OperationRecord, OperationRecordItem, WprouctTicket from django.db import transaction +from apps.sam.models import Order class PickHalfSerializer(serializers.Serializer): id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID') @@ -560,4 +561,8 @@ class CuttingListSerializer(serializers.ModelSerializer): class WproductMtestSerializer(serializers.ModelSerializer): class Meta: model = WProduct - fields = ['remark_mtest', 'is_mtestok'] \ No newline at end of file + fields = ['remark_mtest', 'is_mtestok'] + +class WproductToOrderSerializer(serializers.Serializer): + wproducts = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), many=True) + order = serializers.PrimaryKeyRelatedField(queryset=Order.objects.all()) \ No newline at end of file diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index caababf..5847c89 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -27,7 +27,7 @@ from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerial PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, \ WProductCardSerializer, WProductDetailSerializer, WProductListSerializer, \ WpmTestFormInitSerializer, WproductMtestSerializer, WproductPutInSerializer, \ - WproductPutInsSerializer, WproductTicketListSerializer + WproductPutInsSerializer, WproductTicketListSerializer, WproductToOrderSerializer from rest_framework.response import Response from django.db import transaction @@ -441,7 +441,31 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): ret.append([str(index + 1), item['step_name'], item['actions']]) return Response(ret) - + @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=WproductToOrderSerializer) + @transaction.atomic + def to_order(self, request, pk=None): + """ + 指派发货订单 + """ + serializer = WproductToOrderSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + vdata = serializer.validated_data + wps = WProduct.objects.filter(id__in = [i.id for i in vdata.get('wproducts')]) + wp = wps.first() + order = vdata['order'] + if wp.material != order.product: + raise exceptions.ValidationError('所选订单与产品不符') + for i in wps: + if i.material != wp.material and i.material.type != Material.MA_TYPE_GOOD and i.act_state \ + not in [WProduct.WPR_ACT_STATE_OK, WProduct.WPR_ACT_STATE_INM]: + raise exceptions.ValidationError('所选产品错误') + for i in wps: + i.to_order = order + i.update_by = request.user + i.save() + WpmServies.add_wproduct_flow_log(i,change_str='to_order') + return Response() + class WproductTicketViewSet(ListModelMixin, GenericViewSet): """ 玻璃审批工单 diff --git a/hb_server/utils/response.py b/hb_server/utils/response.py index f4379f4..0411547 100644 --- a/hb_server/utils/response.py +++ b/hb_server/utils/response.py @@ -47,17 +47,20 @@ class FitJSONRenderer(JSONRenderer): """ response_body = BaseResponse() response = renderer_context.get("response") - response_body.code = response.status_code - if response_body.code >= 400: # 响应异常 - response_body.data = data # data里是详细异常信息 - prefix = "" - if isinstance(data, dict): - prefix = list(data.keys())[0] - data = data[prefix] - if isinstance(data, list): - data = data[0] - response_body.msg = prefix + ":" + str(data) # 取一部分放入msg,方便前端alert + status_code = response.status_code # Http状态异常码 + if status_code >= 400: # 如果http响应异常 + if isinstance(data, dict) and 'code' in data: # 如果自定义了异常码 + response_body = data + else: + response_body.data = data # data里是详细异常信息 + prefix = "" + if isinstance(data, dict): + prefix = list(data.keys())[0] + data = data[prefix] + elif isinstance(data, list): + data = data[0] + response_body.msg = prefix + ":" + str(data) # 取一部分放入msg,方便前端alert else: response_body.data = data - renderer_context.get("response").status_code = 200 # 统一成200响应,用code区分 + renderer_context.get("response").status_code = 200 # 统一成200响应, 可用body里code区分业务异常 return super(FitJSONRenderer, self).render(response_body.dict, accepted_media_type, renderer_context) From 28882ae074339ad55059c32294080a204e5848b8 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 20 Jan 2022 15:44:27 +0800 Subject: [PATCH 19/19] =?UTF-8?q?wproductserializer=20=E5=A2=9E=E5=8A=A0to?= =?UTF-8?q?=5Forder=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/serializers.py | 1 + hb_server/apps/wpm/views.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 3e245ef..3181088 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -156,6 +156,7 @@ class WProductListSerializer(serializers.ModelSerializer): subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True) warehouse_ = WareHouseSimpleSerializer(source='warehouse', read_only=True) children = serializers.SerializerMethodField() + to_order_ = OrderSimpleSerializer(source='to_order', read_only=True) class Meta: model = WProduct fields = '__all__' diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 5847c89..47c49dc 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -148,7 +148,7 @@ class WProductViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): """ perms_map = {'*': '*'} queryset = WProduct.objects.select_related('step', 'material', - 'subproduction_plan', 'warehouse').prefetch_related('wproduct_child') + 'subproduction_plan', 'warehouse', 'order').prefetch_related('wproduct_child') serializer_class = WProductListSerializer filterset_class = WProductFilterSet search_fields = ['number']