From eba134a2c370335f453cbd969361fdb0edafcaae Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 22 Nov 2021 11:03:08 +0800 Subject: [PATCH] =?UTF-8?q?=E8=BD=A6=E9=97=B4=E6=93=8D=E4=BD=9C=E6=B6=88?= =?UTF-8?q?=E8=80=97=E4=BA=A7=E5=87=BA=E5=B7=A5=E5=85=B7=E5=B7=A5=E8=A3=85?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/models.py | 20 +++++----- hb_server/apps/wpm/serializers.py | 39 ++++++++++++++++++- hb_server/apps/wpm/services.py | 23 +++++++++++- hb_server/apps/wpm/urls.py | 5 ++- hb_server/apps/wpm/views.py | 62 ++++++++++++++++++++++++++++++- 5 files changed, 135 insertions(+), 14 deletions(-) diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py index 517593e..e0d7b62 100644 --- a/hb_server/apps/wpm/models.py +++ b/hb_server/apps/wpm/models.py @@ -3,11 +3,11 @@ from django.db.models.base import Model import django.utils.timezone as timezone from django.db.models.query import QuerySet from apps.inm.models import WareHouse -from apps.pm.models import ProductionPlan, SubProductionPlan +from apps.pm.models import ProductionPlan, SubProductionPlan, SubProductionProgress from apps.system.models import CommonADModel, CommonAModel, CommonBModel, Organization, User, Dict, File from utils.model import SoftModel, BaseModel from simple_history.models import HistoricalRecords -from apps.mtm.models import Material, Process, RecordFormField, Step, RecordForm +from apps.mtm.models import Material, Process, RecordFormField, Step, RecordForm, SubprodctionMaterial from django.core.validators import MinValueValidator from apps.em.models import Equipment class WMaterial(BaseModel): @@ -42,7 +42,7 @@ class WProduct(CommonAModel): is_hidden = models.BooleanField('是否隐藏', default=False) parent = models.JSONField('父', default=list, blank=True) remark = models.CharField('备注', max_length=200, null=True, blank=True) - subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE) + subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE, related_name='wproduct_subplan') production_plan = models.ForeignKey(ProductionPlan, verbose_name='关联主生产计划', on_delete=models.CASCADE) warehouse = models.ForeignKey(WareHouse, verbose_name='所在仓库', on_delete=models.SET_NULL, null=True, blank=True) operation = models.ForeignKey('wpm.operation', verbose_name='关联操作', @@ -73,16 +73,18 @@ class OperationMaterial(BaseModel): """ 生产操作物料消耗产出表 """ - type_choices=( - (1, '消耗'), - (2, '产出') - ) - type = models.IntegerField('类型', default=0, choices=type_choices) + type = models.IntegerField('类型', default=0, choices=SubprodctionMaterial.type_choices) operation = models.ForeignKey(Operation, verbose_name='关联的生产操作', on_delete=models.CASCADE) - wmaterial = models.ForeignKey(WMaterial, verbose_name='关联的车间物料', on_delete=models.CASCADE, null=True, blank=True) + material = models.ForeignKey(Material, verbose_name='可能产出的产品', on_delete=models.CASCADE, null=True, blank=True) count = models.IntegerField('消耗或产出数量', validators=[MinValueValidator(0)]) + wmaterial = models.ForeignKey(WMaterial, verbose_name='关联的车间物料', on_delete=models.CASCADE, null=True, blank=True) + subproduction_progress = models.ForeignKey(SubProductionProgress, verbose_name='关联的生产进度', on_delete=models.CASCADE, null=True, blank=True) + + 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) + class OperationRecord(BaseModel): """ 记录表格 diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index cbcdf3d..78b0ecc 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -12,7 +12,7 @@ from django.utils.translation import gettext_lazy as _ from apps.pm.serializers import SubproductionPlanSimpleSerializer from apps.qm.models import TestRecord, TestRecordItem from apps.system.serializers import UserSimpleSerializer -from apps.wpm.models import Operation, OperationEquip, OperationWproduct, WMaterial, WProduct, OperationRecord, OperationRecordItem +from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, WMaterial, WProduct, OperationRecord, OperationRecordItem from django.db import transaction class PickHalfSerializer(serializers.Serializer): @@ -313,6 +313,43 @@ class OperationRecordListSerializer(serializers.ModelSerializer): class Meta: model = OperationRecord fields = '__all__' + +class OperationMaterialListSerializer(serializers.ModelSerializer): + material_ = MaterialSimpleSerializer(source='material', read_only=True) + subproduction_plan_ = SubproductionPlanSimpleSerializer(source='subproduction_plan', read_only=True) + class Meta: + model = OperationMaterial + fields = '__all__' + +class OperationMaterialCreate1Serailizer(serializers.ModelSerializer): + wmaterial = serializers.PrimaryKeyRelatedField(required=True, queryset=WMaterial.objects.all()) + class Meta: + model = OperationMaterial + fields = ['operation', 'wmaterial', 'count'] + def create(self, validated_data): + wmaterial = validated_data['wmaterial'] + validated_data['material'] = wmaterial.material + validated_data['subproduction_plan'] = wmaterial.subproduction_plan + validated_data['batch'] = wmaterial.batch + return super().create(validated_data) + +class OperationMaterialCreate2Serailizer(serializers.ModelSerializer): + subproduction_progress = serializers.PrimaryKeyRelatedField(required=True, queryset=SubProductionProgress.objects.all()) + class Meta: + model = OperationMaterial + fields = ['operation', 'subproduction_progress', 'count'] + + def create(self, validated_data): + subproduction_progress = validated_data['subproduction_progress'] + validated_data['material'] = subproduction_progress.material + validated_data['subproduction_plan'] = subproduction_progress.subproduction_plan + return super().create(validated_data) + +class OperationMaterialCreate3Serializer(serializers.ModelSerializer): + material = serializers.PrimaryKeyRelatedField(required=True, queryset=Material.objects.all()) + class Meta: + model = OperationMaterial + fields = ['operation', 'material'] \ No newline at end of file diff --git a/hb_server/apps/wpm/services.py b/hb_server/apps/wpm/services.py index de6e5c8..591914f 100644 --- a/hb_server/apps/wpm/services.py +++ b/hb_server/apps/wpm/services.py @@ -1,5 +1,7 @@ +from typing import List from apps.pm.models import SubProductionPlan -from apps.mtm.models import Step +from apps.mtm.models import Step, SubprodctionMaterial +from apps.wpm.models import WProduct class WpmServies(object): @classmethod @@ -12,4 +14,21 @@ class WpmServies(object): if pindex + 1 < len(stepIds): return Step.objects.get(pk=stepIds[pindex+1]), True else: - return nowstep, False \ No newline at end of file + return nowstep, False + + @classmethod + def get_subplans_queryset_from_wproducts(cls, wproducts:List): + """ + 通过半成品列表获取所属子计划 + """ + splans = SubProductionPlan.objects.filter(is_deleted=False, wproduct__subplan__in=wproducts) + return splans + + @classmethod + def get_subplans_queyset_from_step(cls, step:Step): + """ + 通过当前操作获取所有正在进行的子计划 + """ + splans = SubProductionPlan.objects.filter(is_deleted=False, + subproduction__usedstep_subproduction__step=step, state=SubProductionPlan.SUBPLAN_STATE_WORKING) + return splans \ No newline at end of file diff --git a/hb_server/apps/wpm/urls.py b/hb_server/apps/wpm/urls.py index 96d2986..57db6b9 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, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet +from apps.wpm.views import DoFormInit, DoFormSubmit, OperationEquipViewSet, OperationMaterialInputViewSet, OperationMaterialOutputViewSet, OperationMaterialToolViewSet, OperationRecordViewSet, OperationViewSet, OperationWproductViewSet, WMaterialViewSet, WPlanViewSet, WProductViewSet router = DefaultRouter() router.register('wmaterial', WMaterialViewSet, basename='wmaterial') @@ -12,6 +12,9 @@ router.register('operation', OperationViewSet, basename='operation') router.register('operation_wproduct', OperationWproductViewSet, basename='operation_wproduct') router.register('operation_equip', OperationEquipViewSet, basename='operation_equip') router.register('operation_record', OperationRecordViewSet, basename='operation_record') +router.register('operation_input', OperationMaterialInputViewSet, basename='operation_input') +router.register('operation_output', OperationMaterialOutputViewSet, basename='operation_output') +router.register('operation_tool', OperationMaterialToolViewSet, basename='operation_tool') router.register('subplan', WPlanViewSet, basename='wplan') urlpatterns = [ path('do/init/', DoFormInit.as_view()), diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 1cb79c0..4bcf0b0 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -17,7 +17,7 @@ from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin from rest_framework.decorators import action from apps.wpm.models import OperationEquip, OperationWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem -from apps.wpm.serializers import OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer +from apps.wpm.serializers import OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer from rest_framework.response import Response from django.db import transaction from rest_framework import exceptions, serializers @@ -294,9 +294,11 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd op.is_submited = False op.create_by = request.user op.save() + splans = [] # 创建操作所用半成品关联记录 if 'wproducts' in vdata: owps = [] + splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts']) for wpd in vdata['wproducts']: owp = {} owp['operation'] = op @@ -307,6 +309,8 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd owp['production_plan'] = wpd.production_plan owps.append(OperationWproduct(**owp)) OperationWproduct.objects.bulk_create(owps) + else: + splans = WpmServies.get_subplans_queryset_from_wproducts(vdata['wproducts']) # 查询需要填写的自定义表格 forms = RecordForm.objects.filter(step=step, type=RecordForm.RF_TYPE_DO) for i in forms: @@ -321,6 +325,14 @@ class OperationViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Upd ope.operation = op ope.equip = i ope.save() + # 查询所需的工具工装 + for i in SubprodctionMaterial.objects.filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL, + subproduction__subplan_subprod__in = splans): + opm = OperationMaterial() + opm.operation = op + opm.material = i.material + opm.type = SubprodctionMaterial.SUB_MA_TYPE_TOOL + opm.save() return Response() @@ -414,6 +426,54 @@ class OperationRecordViewSet(ListModelMixin, DestroyModelMixin, GenericViewSet): return Response() +class OperationMaterialInputViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet): + """ + 消耗物料 + """ + perms_map={'*':'*'} + queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_IN) + serializer_class = OperationMaterialListSerializer + filterset_fields = ['operation', 'subproduction_plan'] + ordering_fields = ['id'] + ordering = ['-id'] + + def get_serializer_class(self): + if self.action == 'create': + return OperationMaterialCreate1Serailizer + return super().get_serializer_class() + +class OperationMaterialOutputViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet): + """ + 产出物料 + """ + perms_map={'*':'*'} + queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_OUT) + serializer_class = OperationMaterialListSerializer + filterset_fields = ['operation', 'subproduction_plan'] + ordering_fields = ['id'] + ordering = ['-id'] + + def get_serializer_class(self): + if self.action == 'create': + return OperationMaterialCreate2Serailizer + return super().get_serializer_class() + +class OperationMaterialToolViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, GenericViewSet): + """ + 工具工装 + """ + perms_map={'*':'*'} + queryset = OperationMaterial.objects.select_related('operation', 'subproduction_plan').filter(type=SubprodctionMaterial.SUB_MA_TYPE_TOOL) + serializer_class = OperationMaterialListSerializer + filterset_fields = ['operation', 'subproduction_plan'] + ordering_fields = ['id'] + ordering = ['-id'] + + def get_serializer_class(self): + if self.action == 'create': + return OperationMaterialCreate3Serializer + return super().get_serializer_class() + class DoFormInit(CreateAPIView, GenericAPIView): perms_map={'*':'*'} serializer_class=OperationInitSerializer