From e15ad98c9295935044650abddc49a013ede790c5 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 31 Dec 2021 10:26:07 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E5=90=8E=E6=9B=B4=E6=96=B0=E8=BF=9B=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/models.py | 17 +++++++++++++++++ hb_server/apps/wpm/services.py | 10 +++++++++- hb_server/apps/wpm/views.py | 22 ++++++++++++++++------ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py index dd55ceb..1bac267 100644 --- a/hb_server/apps/wpm/models.py +++ b/hb_server/apps/wpm/models.py @@ -197,6 +197,10 @@ class OperationWproduct(BaseModel): material = models.ForeignKey(Material, verbose_name='操作时的物料状态', on_delete=models.CASCADE) subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE, related_name='ow_subplan') + class Meta: + unique_together = ( + ('operation','wproduct') + ) class OperationMaterial(BaseModel): """ @@ -214,6 +218,19 @@ class OperationMaterial(BaseModel): subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联的子计划', on_delete=models.CASCADE, null=True, blank=True) batch = models.CharField('批次号', max_length=100, null=True, blank=True) + #以下为冷加工下料清单所用字段 + count_cut = models.PositiveIntegerField('切裁片数', default=0) + count_real = models.PositiveIntegerField('生产片数', default=0) + count_ok = models.PositiveIntegerField('成品数量', default=0) + count_qipao = models.PositiveIntegerField('气泡甩片', default=0) + count_podian = models.PositiveIntegerField('破点甩片', default=0) + count_hua = models.PositiveIntegerField('划伤甩片', default=0) + count_other = models.PositiveIntegerField('其他甩片', default=0) + class Meta: + unique_together = ( + ('operation','material', 'batch') + ) + class OperationRecord(BaseModel): """ 记录表格 diff --git a/hb_server/apps/wpm/services.py b/hb_server/apps/wpm/services.py index bd68bb7..eb1a226 100644 --- a/hb_server/apps/wpm/services.py +++ b/hb_server/apps/wpm/services.py @@ -7,7 +7,7 @@ from apps.mtm.models import Material, Step, SubprodctionMaterial from apps.qm.models import TestRecord from apps.system.models import User from apps.wf.models import State, TicketFlow, Transition -from apps.wpm.models import WProduct, WproductFlow, WprouctTicket +from apps.wpm.models import Operation, OperationMaterial, WProduct, WproductFlow, WprouctTicket from utils.tools import ranstr class WpmServies(object): @@ -146,3 +146,11 @@ class WpmServies(object): setattr(ins, f.name, getattr(instance, f.name, None)) ins.change_str = change_str ins.save() + + @classmethod + def update_cutting_list(cls, op:Operation): + """ + 更新下料清单 + """ + inputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_IN) + outputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT) diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index c446a47..817ed9f 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -579,9 +579,11 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd spp.save() # 更新动态产品表 if step.type == Step.STEP_TYPE_NOM: - for i in OperationWproduct.objects.filter(operation=op): + ows = OperationWproduct.objects.filter(operation=op) + for i in ows: wp = i.wproduct wsp = i.subproduction_plan + # 获取下一步子工序 newstep, hasNext = WpmServies.get_next_step(wsp, step) wp.step = newstep @@ -591,17 +593,21 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd else: wp.act_state = WProduct.WPR_ACT_STATE_TOTEST wp.material = wsp.product - # 更新子计划生产进度 - # 如果产品有返工标记不做计算 - if wp.ng_sign not in [WProduct.NG_BACK_FIX, WProduct.NG_BACK_WORK]: - WpmServies.update_subproduction_progress_main(sp=wsp) wp.operation = None wp.update_by = request.user wp.save() WpmServies.add_wproduct_flow_log(wp, 'operation_submit') + + for i in ows.values('subproduction_plan').distinct(): + # 更新进度 + WpmServies.update_subproduction_progress_main(sp=wsp) + elif step.type == Step.STEP_TYPE_DIV: # 更新物料产出情况 - for i in OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT): + outputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT) + if not outputs.exists(): + raise exceptions.APIException('请选择物料产出') + for i in outputs: if i.subproduction_progress.is_main: newstep, _ = WpmServies.get_next_step(i.subproduction_plan, step) wpr = dict(material=i.material, step=newstep, @@ -640,6 +646,10 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd raise exceptions.APIException('产出物料未填写或填写错误') op.is_submited = True op.save() + + # 如果是冷加工 + if step.type == Step.STEP_TYPE_DIV: + WpmServies.update_cutting_list(op=op) return Response() From 7861b5419eb13ae9bc92af78918d39256cc9c626 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 31 Dec 2021 10:45:21 +0800 Subject: [PATCH 2/3] =?UTF-8?q?wproductticket=20list=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0order=20product?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/serializers.py | 4 ++++ hb_server/apps/wpm/views.py | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 18503a4..a0adae6 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -12,6 +12,7 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ from apps.pm.serializers import SubproductionPlanSimpleSerializer from apps.qm.models import TestRecord, TestRecordItem +from apps.sam.serializers import OrderSimpleSerializer 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 @@ -437,7 +438,10 @@ class WproductTicketListSerializer(serializers.ModelSerializer): step_ = StepSimpleSerializer(source='step', read_only=True) subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True) resp_process_ = ProcessSimpleSerializer(source='resp_process', read_only=True) + order_ = OrderSimpleSerializer(source='subproduction_plan.production_plan.order', read_only=True) + product_ = MaterialSimpleSerializer(source='subproduction_plan.production_plan.product', read_only=True) class Meta: model = WprouctTicket fields = '__all__' + \ No newline at end of file diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 817ed9f..6e8b151 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -429,7 +429,8 @@ class WproductTicketViewSet(ListModelMixin, GenericViewSet): 玻璃审批工单 """ perms_map={'*':'*'} - queryset = WprouctTicket.objects.select_related('step', 'material', 'subproduction_plan', 'resp_process') + queryset = WprouctTicket.objects.select_related('step', 'material', 'subproduction_plan', + 'resp_process', 'subproduction_plan__production_plan__order', 'subproduction_plan__production_plan') serializer_class = WproductTicketListSerializer filterset_fields = ['step', 'material', 'subproduction_plan', 'resp_process'] ordering_fields = ['id'] From a1c86557f078b4edc3cbfe67ab94475d5f9ecbc1 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 31 Dec 2021 11:31:01 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E4=B8=8B=E6=96=99=E6=B8=85=E5=8D=95?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wpm/migrations/0043_auto_20211231_1130.py | 57 +++++++++++++++++++ hb_server/apps/wpm/serializers.py | 10 +++- hb_server/apps/wpm/services.py | 31 +++++++++- hb_server/apps/wpm/urls.py | 3 +- hb_server/apps/wpm/views.py | 21 ++++++- 5 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 hb_server/apps/wpm/migrations/0043_auto_20211231_1130.py diff --git a/hb_server/apps/wpm/migrations/0043_auto_20211231_1130.py b/hb_server/apps/wpm/migrations/0043_auto_20211231_1130.py new file mode 100644 index 0000000..268568c --- /dev/null +++ b/hb_server/apps/wpm/migrations/0043_auto_20211231_1130.py @@ -0,0 +1,57 @@ +# Generated by Django 3.2.9 on 2021-12-31 03:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0042_alter_recordformfield_field_type'), + ('wpm', '0042_wprouctticket_resp_process'), + ] + + operations = [ + migrations.AddField( + model_name='operationmaterial', + name='count_cut', + field=models.PositiveIntegerField(default=0, verbose_name='切裁片数'), + ), + migrations.AddField( + model_name='operationmaterial', + name='count_hua', + field=models.PositiveIntegerField(default=0, verbose_name='划伤甩片'), + ), + migrations.AddField( + model_name='operationmaterial', + name='count_ok', + field=models.PositiveIntegerField(default=0, verbose_name='成品数量'), + ), + migrations.AddField( + model_name='operationmaterial', + name='count_other', + field=models.PositiveIntegerField(default=0, verbose_name='其他甩片'), + ), + migrations.AddField( + model_name='operationmaterial', + name='count_podian', + field=models.PositiveIntegerField(default=0, verbose_name='破点甩片'), + ), + migrations.AddField( + model_name='operationmaterial', + name='count_qipao', + field=models.PositiveIntegerField(default=0, verbose_name='气泡甩片'), + ), + migrations.AddField( + model_name='operationmaterial', + name='count_real', + field=models.PositiveIntegerField(default=0, verbose_name='生产片数'), + ), + migrations.AlterUniqueTogether( + name='operationmaterial', + unique_together={('operation', 'material', 'batch')}, + ), + migrations.AlterUniqueTogether( + name='operationwproduct', + unique_together={('operation', 'wproduct')}, + ), + ] diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index a0adae6..dcef7f8 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -13,6 +13,7 @@ from django.utils.translation import gettext_lazy as _ from apps.pm.serializers import SubproductionPlanSimpleSerializer from apps.qm.models import TestRecord, TestRecordItem from apps.sam.serializers import OrderSimpleSerializer +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 @@ -444,4 +445,11 @@ class WproductTicketListSerializer(serializers.ModelSerializer): class Meta: model = WprouctTicket fields = '__all__' - \ No newline at end of file + +class CuttingListSerializer(serializers.ModelSerializer): + subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True) + material_ = MaterialSimpleSerializer(source='material', read_only=True) + create_by_ = UserSimpleSerializer(source='create_by', read_only=True) + class Meta: + model = OperationMaterial + fields = '__all__' \ No newline at end of file diff --git a/hb_server/apps/wpm/services.py b/hb_server/apps/wpm/services.py index eb1a226..d565482 100644 --- a/hb_server/apps/wpm/services.py +++ b/hb_server/apps/wpm/services.py @@ -148,9 +148,36 @@ class WpmServies(object): ins.save() @classmethod - def update_cutting_list(cls, op:Operation): + def update_cutting_list_with_operation(cls, op:Operation): """ - 更新下料清单 + 根据车间操作更新下料清单 """ inputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_IN) outputs = OperationMaterial.objects.filter(operation=op, type=SubprodctionMaterial.SUB_MA_TYPE_OUT) + for i in inputs: + sp = i.subproduction_plan + i.count_cut = outputs.filter(subproduction_plan=sp).first().count + i.count_real = sp.count_real + i.count_ok = sp.count_ok + wpfs = WproductFlow.objects.filter(subproduction_plan=sp, is_lastlog=True) + i.count_qipao = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_QIPAO).count() + i.count_podian = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_PODIAN).count() + i.count_hua = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_HUA).count() + i.count_other = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_OTHER).count() + i.is_cutting = True + i.save() + + @classmethod + def update_cutting_list_with_sp(cls, sp:SubProductionPlan): + """ + 根据子计划更新下料清单 + """ + wpfs = WproductFlow.objects.filter(subproduction_plan=sp, is_lastlog=True) + for i in OperationMaterial.objects.filter(subproduction_plan=sp, is_cutting=True): + i.count_real = sp.count_real + i.count_ok = sp.count_ok + i.count_qipao = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_QIPAO).count() + i.count_podian = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_PODIAN).count() + i.count_hua = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_HUA).count() + i.count_other = wpfs.filter(scrap_reason=WProduct.SCRAP_REASON_OTHER).count() + i.save() \ No newline at end of file diff --git a/hb_server/apps/wpm/urls.py b/hb_server/apps/wpm/urls.py index 77d91f7..b617c02 100644 --- a/hb_server/apps/wpm/urls.py +++ b/hb_server/apps/wpm/urls.py @@ -3,7 +3,7 @@ from rest_framework import urlpatterns from django.urls import path, include from rest_framework.routers import DefaultRouter -from apps.wpm.views import DoFormInit, DoFormSubmit, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet, WproductTicketViewSet +from apps.wpm.views import CuttingListViewSet, DoFormInit, DoFormSubmit, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet, WproductTicketViewSet router = DefaultRouter() router.register('wmaterial', WMaterialViewSet, basename='wmaterial') @@ -17,6 +17,7 @@ router.register('operation_input', OperationMaterialInputViewSet, basename='oper router.register('operation_output', OperationMaterialOutputViewSet, basename='operation_output') router.register('operation_tool', OperationMaterialToolViewSet, basename='operation_tool') router.register('subplan', WPlanViewSet, basename='wplan') +router.register('cutting_list', CuttingListViewSet, basename='cutting_list') urlpatterns = [ path('do/init/', DoFormInit.as_view()), path('do/submit/', DoFormSubmit.as_view()), diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 6e8b151..2a47bca 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -22,7 +22,7 @@ from apps.wf.serializers import WorkflowSimpleSerializer from apps.wpm.filters import WMaterialFilterSet, WProductFilterSet from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem, WprouctTicket -from apps.wpm.serializers import OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordDetailSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickHalfsSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestFormInitSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer, WproductPutInsSerializer, WproductTicketListSerializer +from apps.wpm.serializers import CuttingListSerializer, OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1ListSerailizer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2ListSerailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordDetailSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickHalfsSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, ScrapSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestFormInitSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer, WproductPutInsSerializer, WproductTicketListSerializer from rest_framework.response import Response from django.db import transaction from rest_framework import exceptions, serializers @@ -385,6 +385,8 @@ class WProductViewSet(ListModelMixin, GenericViewSet): obj.update_time = timezone.now() obj.save() WpmServies.add_wproduct_flow_log(obj, 'scrap') + if obj.step.process.id == 1: #如果是冷加工 + WpmServies.update_cutting_list_with_sp(obj.subproduction_plan) return Response() # @action(methods=['get'], detail=False, perms_map={'get':'*'}) @@ -649,8 +651,8 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd op.save() # 如果是冷加工 - if step.type == Step.STEP_TYPE_DIV: - WpmServies.update_cutting_list(op=op) + if step.process.id==1: + WpmServies.update_cutting_list_with_operation(op=op) return Response() @@ -785,6 +787,19 @@ class OperationMaterialInputViewSet(ListModelMixin, CreateModelMixin, DestroyMod instance.delete() return Response() +class CuttingListViewSet(ListModelMixin, GenericViewSet): + """ + 下料清单 + """ + perms_map={'*':'*'} + queryset = OperationMaterial.objects.select_related('operation', + 'subproduction_plan', 'material', 'create_by').filter(operation__step__process__id=1) + serializer_class = CuttingListSerializer + filterset_fields = ['operation', 'subproduction_plan', 'material'] + ordering_fields = ['id'] + ordering = ['-id'] + + class OperationMaterialOutputViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet): """ 产出物料