From e5d45c757757d4b114b64ce28841139bb89409c9 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 2 Dec 2021 09:55:08 +0800 Subject: [PATCH 01/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=A2=86=E6=96=99?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wpm/migrations/0027_pick_pickwproduct.py | 54 +++++++++++++++++++ hb_server/apps/wpm/models.py | 28 +++++++++- hb_server/apps/wpm/serializers.py | 10 +++- hb_server/apps/wpm/views.py | 21 +++++++- 4 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 hb_server/apps/wpm/migrations/0027_pick_pickwproduct.py diff --git a/hb_server/apps/wpm/migrations/0027_pick_pickwproduct.py b/hb_server/apps/wpm/migrations/0027_pick_pickwproduct.py new file mode 100644 index 0000000..b9b4f4e --- /dev/null +++ b/hb_server/apps/wpm/migrations/0027_pick_pickwproduct.py @@ -0,0 +1,54 @@ +# Generated by Django 3.2.9 on 2021-12-02 01:54 + +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), + ('inm', '0019_auto_20211201_1011'), + ('pm', '0015_auto_20211122_1556'), + ('mtm', '0040_material_piece_count'), + ('wpm', '0026_auto_20211201_1608'), + ] + + operations = [ + migrations.CreateModel( + name='Pick', + 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='删除标记')), + ('type', models.PositiveSmallIntegerField(choices=[(10, '仓库领取'), (20, '半成品领取')], default=10)), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pick_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('fifo', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='inm.fifo', verbose_name='关联的出入库记录')), + ('subproduction_plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='关联子生产计划')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pick_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PickWproduct', + 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='删除标记')), + ('number', models.CharField(blank=True, max_length=50, null=True, verbose_name='物品编号')), + ('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='领取时的物料状态')), + ('pick', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wpm.pick', verbose_name='关联领料')), + ('subproduction_plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pm.subproductionplan', verbose_name='领取时所属子生产计划')), + ('wproduct', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pw_wproduct', to='wpm.wproduct', verbose_name='关联半成品')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py index 9bd50d2..b1af088 100644 --- a/hb_server/apps/wpm/models.py +++ b/hb_server/apps/wpm/models.py @@ -3,7 +3,7 @@ from django.db import models 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.inm.models import FIFO, WareHouse 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 @@ -20,7 +20,6 @@ class WMaterial(BaseModel): batch = models.CharField('批次号', max_length=100, null=True, blank=True) count = models.PositiveIntegerField('当前数量', default=0) - class WProduct(CommonAModel): """ 动态半成品/成品表 @@ -55,6 +54,31 @@ class WProduct(CommonAModel): operation = models.ForeignKey('wpm.operation', verbose_name='关联操作', on_delete=models.SET_NULL, null=True, blank=True, related_name='current_operation') + +class Pick(CommonADModel): + """ + 领料记录 + """ + PICK_FROM_WAREHOUSE = 10 + PICK_FROM_WPRODUCT = 20 + type_choice = ( + (PICK_FROM_WAREHOUSE, '仓库领取'), + (PICK_FROM_WPRODUCT, '半成品领取'), + ) + subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.CASCADE) + type = models.PositiveSmallIntegerField(choices=type_choice, default=PICK_FROM_WAREHOUSE) + fifo = models.ForeignKey(FIFO, verbose_name='关联的出入库记录', on_delete=models.CASCADE, null=True, blank=True) + +class PickWproduct(BaseModel): + """ + 领取半成品时详情 + """ + pick = models.ForeignKey(Pick, verbose_name='关联领料', on_delete=models.CASCADE) + wproduct = models.ForeignKey(WProduct, verbose_name='关联半成品', on_delete=models.CASCADE, related_name='pw_wproduct') + number = models.CharField('物品编号', null=True, blank=True, max_length=50) + material = models.ForeignKey(Material, verbose_name='领取时的物料状态', on_delete=models.CASCADE) + subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='领取时所属子生产计划', on_delete=models.CASCADE) + class Operation(CommonADModel): """ 生产操作 diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index ec95ed0..7bca29e 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -13,7 +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.system.serializers import UserSimpleSerializer -from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, WMaterial, WProduct, OperationRecord, OperationRecordItem +from apps.wpm.models import Operation, OperationEquip, OperationMaterial, OperationWproduct, Pick, WMaterial, WProduct, OperationRecord, OperationRecordItem from django.db import transaction class PickHalfSerializer(serializers.Serializer): @@ -32,7 +32,6 @@ class PickDetailSerializer(serializers.Serializer): class PickSerializer(serializers.Serializer): subproduction_plan=serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID") picks = PickDetailSerializer(many=True) # 从库存里拿 - def create(self, validated_data): picks = validated_data.pop('picks') @@ -108,6 +107,13 @@ class PickSerializer(serializers.Serializer): sp.state = SubProductionPlan.SUBPLAN_STATE_WORKING #生产中 sp.state_date_real = timezone.now() #实际开工日期 sp.save() + # 创建领料记录 + pick = Pick() + pick.subproduction_plan = sp + pick.type = Pick.PICK_FROM_WAREHOUSE + pick.fifo = fifo + pick.create_by = self.context['request'].user + pick.save() # 更新库存 fifo.is_audited = True fifo.save() diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 86712f3..5fc6d27 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -16,7 +16,7 @@ from apps.qm.models import TestRecordItem from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin from rest_framework.decorators import action from apps.wpm.filters import WMaterialFilterSet -from apps.wpm.models import OperationEquip, OperationWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem +from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem 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 @@ -59,6 +59,12 @@ class WPlanViewSet(ListModelMixin, GenericViewSet): serializer.is_valid(raise_exception=True) vdata = serializer.data first_step = Step.objects.get(pk=sp.steps[0]['id']) + # 创建领料记录 + pick = Pick() + pick.subproduction_plan = sp + pick.type = Pick.PICK_FROM_WPRODUCT + pick.create_by = request.user + pick.save() for i in vdata: if 'wproducts' in i and len(i['wproducts'])>0: spp = SubProductionProgress.objects.get(pk=i['id']) @@ -66,12 +72,23 @@ class WPlanViewSet(ListModelMixin, GenericViewSet): # if spp.count_pick > spp.count: # raise exceptions.APIException('超过计划数') spp.save() - wps = WProduct.objects.filter(pk__in=[x for x in i['wproducts']]) + wps = WProduct.objects.filter(pk__in=[x for x in i['wproducts']], act_state=WProduct.WPR_ACT_STATE_OK) wps.update(step=first_step, is_executed=False, act_state=WProduct.WPR_ACT_STATE_TORETEST, is_hidden=False, warehouse=None, subproduction_plan=sp, update_by=request.user, update_time=timezone.now()) + for i in wps: + pw = PickWproduct() + pw.pick =pick + pw.wproduct = i + pw.number = i.number + pw.material = i.material + pw.subproduction_plan = i.suproduction_plan + pw.save() + else: + raise exceptions.APIException('未选择任何玻璃') sp.is_picked = True sp.save() + return Response() From 7113f1bed1d64935baef42919da36d32c83447c8 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 2 Dec 2021 14:15:04 +0800 Subject: [PATCH 02/16] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/pm/views.py | 2 +- hb_server/apps/sam/views.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hb_server/apps/pm/views.py b/hb_server/apps/pm/views.py index 9ad869f..4ad9519 100644 --- a/hb_server/apps/pm/views.py +++ b/hb_server/apps/pm/views.py @@ -42,7 +42,7 @@ class ProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, CreateModel queryset = ProductionPlan.objects.select_related('order', 'order__contract', 'product') serializer_class = ProductionPlanSerializer search_fields = ['number'] - filterset_fields = [] + filterset_fields = ['product', 'order'] ordering_fields = ['id'] ordering = ['-id'] diff --git a/hb_server/apps/sam/views.py b/hb_server/apps/sam/views.py index f1f4be7..441e7fa 100644 --- a/hb_server/apps/sam/views.py +++ b/hb_server/apps/sam/views.py @@ -50,7 +50,7 @@ class OrderViewSet(CreateUpdateCustomMixin, ModelViewSet): queryset = Order.objects.select_related('contract', 'customer').all() serializer_class = OrderSerializer search_fields = ['number', 'product'] - filterset_fields = [] + filterset_fields = ['product', 'contract', 'customer'] ordering_fields = ['create_time'] ordering = ['-create_time'] From 5bac47bfb06c52e24c657d01d36491a84d7b4da9 Mon Sep 17 00:00:00 2001 From: shijing Date: Thu, 2 Dec 2021 14:56:24 +0800 Subject: [PATCH 03/16] customForm --- hb_client/src/components/customForm/index.vue | 537 ++++++++++++++ hb_client/src/views/mtm/materialdo.vue | 692 ++++++++++-------- 2 files changed, 936 insertions(+), 293 deletions(-) create mode 100644 hb_client/src/components/customForm/index.vue diff --git a/hb_client/src/components/customForm/index.vue b/hb_client/src/components/customForm/index.vue new file mode 100644 index 0000000..eb9b8df --- /dev/null +++ b/hb_client/src/components/customForm/index.vue @@ -0,0 +1,537 @@ + + + + + diff --git a/hb_client/src/views/mtm/materialdo.vue b/hb_client/src/views/mtm/materialdo.vue index 317fcf4..7c3993e 100644 --- a/hb_client/src/views/mtm/materialdo.vue +++ b/hb_client/src/views/mtm/materialdo.vue @@ -86,109 +86,120 @@ :visible.sync="dialogVisibleForm" :title="tableForm.name" > - - - - - - - + + <!––>
回退
保存
@@ -210,7 +221,12 @@
-
+ --> +
+ + 合格验证 + +
@@ -450,10 +466,13 @@ !--> - + - + + + + - - + + @@ -494,6 +513,7 @@ diff --git a/hb_client/src/views/mtm/materialdo.vue b/hb_client/src/views/mtm/materialdo.vue index 5203d7e..29e3ab3 100644 --- a/hb_client/src/views/mtm/materialdo.vue +++ b/hb_client/src/views/mtm/materialdo.vue @@ -85,6 +85,7 @@ --> -
- - 合格验证 - -
+ + + + +
@@ -821,14 +822,14 @@ that.$set(that.checkForm, key, '') } that.dialogVisibleForm = true; - setTimeout(function () { + /* setTimeout(function () { that.canvasInit(); - }, 500); + }, 500);*/ } }); that.fieldLists(); }, - canvasInit() { + /*canvasInit() { let that = this; preDrawAry = []; that.canvas = document.getElementById('canvas'); @@ -841,7 +842,7 @@ setTimeout(function () { that.draw(); }, 500); - }, + },*/ checkPermission, handleCurrentChange(row) { @@ -883,7 +884,7 @@ } }); }, - draw() { + /*draw() { let canvasImg = document.getElementById("canvasImg"); canvasImg.style.width = '300px'; canvasImg.style.height = '200px'; @@ -1020,13 +1021,13 @@ } }, - /* // 删除批注 + /!* // 删除批注 restuya(){ this.word.style.display="none"; this.Txt.style.display="none"; this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height); window.location.reload(); - },*/ + },*!/ // 撤销 back() { @@ -1128,7 +1129,7 @@ } else { alert("检验合格!") } - }, + },*/ //新增记录表 handleCreate() { this.recordform = Object.assign({}, defaultrecordform); @@ -1274,64 +1275,4 @@ background: #fde2e2; } - canvas { - border: 1px solid #000000; - cursor: crosshair; - } - - .canvasBtnWrap { - display: flex; - flex-direction: column; - width: 80px; - padding-left: 20px; - justify-content: space-between; - } - - .canvasBtn { - width: 70px; - height: 35px; - line-height: 35px; - border: 1px solid #aaaaaa; - text-align: center; - border-radius: 15px; - } - - .hide { - display: none; - } - - #txt { - position: absolute; - top: 1%; - left: 1%; - width: 150px; - height: 30px; - border: 1px solid #e42343; - } - - #word { - position: absolute; - width: 150px; - height: 70px; - padding: 0 2px; - background: none; - color: #e42343; - border: 1px dashed #b9b9b9; - } - - #word::-webkit-input-placeholder { - color: #e42343; - } - - #word::-moz-placeholder { - color: #e42343; - } - - #word::placeholder { - color: #e42343; - } - - #res { - display: inline-block; - } From a3ec039c0087e7ed9443d1495636400a3a3c4ff1 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 3 Dec 2021 10:11:15 +0800 Subject: [PATCH 13/16] =?UTF-8?q?=E5=8D=8A=E6=88=90=E5=93=81=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E5=85=A5=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/serializers.py | 21 +++---- hb_server/apps/wpm/views.py | 94 +++++++++++++++++-------------- 2 files changed, 62 insertions(+), 53 deletions(-) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index f7591de..091ed4f 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -18,16 +18,14 @@ from django.db import transaction class PickHalfSerializer(serializers.Serializer): id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID') - wproducts = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label='半成品ID'), - required=False) # 从半成品表里直接修改状态 + wproducts = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label='半成品ID', many=True, required=False) # 从半成品表里直接修改状态 class PickDetailSerializer(serializers.Serializer): material = serializers.PrimaryKeyRelatedField(queryset=Material.objects.all(), label="物料ID") batch = serializers.CharField(label='物料批次', allow_blank=True) warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID") pick_count = serializers.IntegerField(label="领料数量", required=False) - iproducts = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=IProduct.objects.all(), label='库存半成品ID'), - required=False) + iproducts = serializers.PrimaryKeyRelatedField(queryset=IProduct.objects.all(), label='库存半成品ID',required=False, many=True) class PickSerializer(serializers.Serializer): subproduction_plan=serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID") @@ -172,8 +170,7 @@ class OperationCreateSerializer(serializers.Serializer): """ step = serializers.PrimaryKeyRelatedField(queryset=Step.objects.all(), label="子工序ID") # subproduction_plan = serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID", required=False) - wproducts = serializers.ListField(child= - serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all()), label="半成品ID列表", required=False) + wproducts = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label="半成品ID列表", required=False, many=True) def validate(self, data): # subproduction_plan = data['subproduction_plan'] @@ -209,8 +206,7 @@ class OperationUpdateSerializer(serializers.ModelSerializer): class OperationInitSerializer(serializers.Serializer): step = serializers.PrimaryKeyRelatedField(queryset=Step.objects.all(), label="子工序ID") subproduction_plan = serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID", required=False) - wproducts = serializers.ListField(child= - serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all()), label="半成品ID列表", required=False) + wproducts = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label="半成品ID列表", required=False, many=True) def validate(self, data): # subproduction_plan = data['subproduction_plan'] @@ -273,8 +269,7 @@ class OperationWproductListSerializer(serializers.ModelSerializer): class OperationSubmitSerializer(serializers.Serializer): step = serializers.PrimaryKeyRelatedField(queryset=Step.objects.all(), label="子工序ID") subproduction_plan = serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID", required=False) - wproducts = serializers.ListField(child= - serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all()), label="半成品ID列表", required=False) + wproducts = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label="半成品ID列表", required=False, many=True) input = DoInputSerializer(many=True, required=False) output = DoOutputSerializer(many=True, required=False) forms = OperationRecordSerializer(many=True, required=False) @@ -307,6 +302,12 @@ class WproductPutInSerializer(serializers.Serializer): warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID") remark = serializers.CharField(label="入库备注", required =False) +class WproductPutInsSerializer(serializers.Serializer): + warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID") + wproducts = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label='半成品ID', many=True) + remark = serializers.CharField(label="入库备注", required =False) + + class OperationEquipListSerializer(serializers.Serializer): equip_ = EquipmentSimpleSerializer(source='equip', read_only=True) class Meta: diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 39a7b08..2a9d3ad 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -18,7 +18,7 @@ from rest_framework.decorators import action from apps.wpm.filters import WMaterialFilterSet from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem -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 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, WproductPutInsSerializer from rest_framework.response import Response from django.db import transaction from rest_framework import exceptions, serializers @@ -27,6 +27,7 @@ from apps.wpm.services import WpmServies from django.utils import timezone from utils.tools import ranstr from rest_framework import status +from django.db.models import Count # Create your views here. class WPlanViewSet(ListModelMixin, GenericViewSet): """ @@ -245,49 +246,56 @@ class WProductViewSet(ListModelMixin, GenericViewSet): wproduct.save() return Response() + + @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WproductPutInsSerializer) + @transaction.atomic + def putins(self, request, pk=None): + """ + 半成品批量入库 + """ + serializer= WproductPutInsSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + vdata = serializer.data + wproducts = WProduct.objects.filter(pk__in=[x for x in vdata['wproducts']]) + warehouse = WareHouse.objects.get(id=vdata['warehouse']) + for i in wproducts: + if i.act_state is not WProduct.WPR_ACT_STATE_OK: + raise exceptions.APIException('存在不可入库产品') + # 聚合一下 + wproducts_a = wproducts.values('subproduction_plan', 'material', 'subproduction_plan__number').annotate(total=Count('id')) + # 创建入库记录 + remark = vdata.get('remark', '') + fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN, + is_audited=True, auditor=request.user, inout_date=timezone.now(), create_by=request.user, remark=remark) + # 创建入库明细 + for i in wproducts_a: + fifoitem = FIFOItem() + fifoitem.is_tested = True + fifoitem.is_testok = True + fifoitem.warehouse = warehouse + fifoitem.material = i['material'] + fifoitem.count = i['total'] + fifoitem.batch = i['subproduction_plan__number'] + fifoitem.fifo = fifo + fifoitem.subproduction_plan = i['subproduction_plan'] + fifoitem.save() + + wproducts_items = wproducts.filter(subproduction_plan=i['subproduction_plan'], material=i['material']) + ips = [] + for i in wproducts_items: + # 创建入库明细半成品 + ip = {} + ip['fifoitem'] = fifoitem + ip['wproduct'] = i + ip['number'] = i.number + ip['material'] = i.material + ips.append(FIFOItemProduct(**ip)) + FIFOItemProduct.objects.bulk_create(ips) + # 更新库存并修改半成品进行状态 + update_inm(fifo) + wproducts.update(act_state=WProduct.WPR_ACT_STATE_INM, warehouse=warehouse, update_by=request.user) + return Response() - # @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WpmTestRecordCreateSerializer) - # @transaction.atomic - # def retest(self, request, pk=None): - # """ - # 复检 - # """ - # serializer = WpmTestRecordCreateSerializer(data=request.data) - # serializer.is_valid(raise_exception=True) - # vdata = serializer.validated_data - # record_data = vdata.pop('record_data') - # wproduct = vdata['wproduct'] - # if wproduct.act_state != WProduct.WPR_ACT_STATE_TORETEST: - # raise exceptions.APIException('该产品当前状态不可检验') - # if 'is_testok' not in vdata: - # raise exceptions.APIException('未填写检测结论') - - # obj = serializer.save(create_by = self.request.user, - # material=wproduct.material, number=wproduct.number, subproduction_plan=wproduct.subproduction_plan) - # tris = [] - # for m in record_data: # 保存记录详情 - # form_field = m['form_field'] - # m['field_name'] = form_field.field_name - # m['field_key'] = form_field.field_key - # m['field_type'] = form_field.field_type - # m['field_value'] = m['field_value'] - # m['sort'] = form_field.sort - # m['need_judge'] = form_field.need_judge - # m['is_testok'] = m['is_testok'] if 'is_testok' in m else None - # m['test_record'] = obj - # tris.append(TestRecordItem(**m)) - # TestRecordItem.objects.bulk_create(tris) - - # # 如果检测合格, 变更动态产品进行状态 - - # if obj.is_testok: - # wproduct.act_state = WProduct.WProduct.WPR_ACT_STATE_DOWAIT - # wproduct.save() - # else:# 如果不合格 - # wproduct.act_state = WProduct.WPR_ACT_STATE_NOTOK - # wproduct.save() - # return Response() - @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WproductPutInSerializer) @transaction.atomic def putin(self, request, pk=None): From 52be92e98bd1e120cc8a230eff7383339aa34eff Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 3 Dec 2021 10:12:21 +0800 Subject: [PATCH 14/16] =?UTF-8?q?=E5=8D=8A=E6=88=90=E5=93=81=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E5=85=A5=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 2a9d3ad..de4c8ee 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -247,7 +247,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet): return Response() - @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WproductPutInsSerializer) + @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WproductPutInsSerializer) @transaction.atomic def putins(self, request, pk=None): """ From 03e0f0d1a24aae1750f117e1ab0049e156cf0c3a Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 3 Dec 2021 10:51:07 +0800 Subject: [PATCH 15/16] =?UTF-8?q?=E7=8E=BB=E7=92=83=E6=89=B9=E9=87=8F?= =?UTF-8?q?=E5=85=A5=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/views.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index de4c8ee..b100adf 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -260,7 +260,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet): warehouse = WareHouse.objects.get(id=vdata['warehouse']) for i in wproducts: if i.act_state is not WProduct.WPR_ACT_STATE_OK: - raise exceptions.APIException('存在不可入库产品') + raise exceptions.APIException('存在不可入库半成品') # 聚合一下 wproducts_a = wproducts.values('subproduction_plan', 'material', 'subproduction_plan__number').annotate(total=Count('id')) # 创建入库记录 @@ -269,15 +269,16 @@ class WProductViewSet(ListModelMixin, GenericViewSet): is_audited=True, auditor=request.user, inout_date=timezone.now(), create_by=request.user, remark=remark) # 创建入库明细 for i in wproducts_a: + spi = SubProductionPlan.objects.get(pk=i['subproduction_plan']) fifoitem = FIFOItem() fifoitem.is_tested = True fifoitem.is_testok = True fifoitem.warehouse = warehouse - fifoitem.material = i['material'] + fifoitem.material = Material.objects.get(pk=i['material']) fifoitem.count = i['total'] - fifoitem.batch = i['subproduction_plan__number'] + fifoitem.batch = spi.number fifoitem.fifo = fifo - fifoitem.subproduction_plan = i['subproduction_plan'] + fifoitem.subproduction_plan = spi fifoitem.save() wproducts_items = wproducts.filter(subproduction_plan=i['subproduction_plan'], material=i['material']) From 84ba718a98529dc3cdbc836077416aab4f6be727 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 3 Dec 2021 11:26:13 +0800 Subject: [PATCH 16/16] =?UTF-8?q?=E9=A2=86=E5=8D=8A=E6=88=90=E5=93=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wf/models.py | 12 ++++++++++++ hb_server/apps/wf/serializers.py | 2 +- hb_server/apps/wpm/serializers.py | 10 ++++------ hb_server/apps/wpm/views.py | 8 +++----- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/hb_server/apps/wf/models.py b/hb_server/apps/wf/models.py index 4bc7d75..a9ae071 100644 --- a/hb_server/apps/wf/models.py +++ b/hb_server/apps/wf/models.py @@ -210,6 +210,18 @@ class Ticket(CommonBModel): act_state = models.IntegerField('进行状态', default=1, help_text='当前工单的进行状态', choices=act_state_choices) multi_all_person = models.JSONField('全部处理的结果', default=dict, blank=True, help_text='需要当前状态处理人全部处理时实际的处理结果,json格式') + +class TicketData(): + """ + 工单数据,自定义字段值 + """ + form_field = models.ForeignKey(CustomField, verbose_name='关联字段', on_delete=models.SET_NULL, db_constraint=False, null=True, blank=True) + field_name = models.CharField('字段名', max_length=50) + field_key = models.CharField('字段标识', max_length=50) + field_type = models.CharField('字段类型', choices=CustomField.field_type_choices, max_length=50) + field_value = models.JSONField('录入值', default=dict, blank=True) + sort = models.IntegerField('排序号', default=1) + class TicketFlow(BaseModel): """ 工单流转日志 diff --git a/hb_server/apps/wf/serializers.py b/hb_server/apps/wf/serializers.py index 45369a5..e79f121 100644 --- a/hb_server/apps/wf/serializers.py +++ b/hb_server/apps/wf/serializers.py @@ -52,7 +52,7 @@ class TicketCreateSerializer(serializers.ModelSerializer): transition = serializers.IntegerField(label='流转ID') class Meta: model=Ticket - fields=['title','workflow','ticket_data', 'transition'] + fields=['title','workflow', 'ticket_data', 'transition'] def create(self, validated_data): validated_data.pop('transition') diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 091ed4f..b689a84 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -18,8 +18,11 @@ from django.db import transaction class PickHalfSerializer(serializers.Serializer): id = serializers.PrimaryKeyRelatedField(queryset=SubProductionProgress.objects.all(), label='子计划进度ID') - wproducts = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), label='半成品ID', many=True, required=False) # 从半成品表里直接修改状态 + wproducts = serializers.ListField(child=serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all()) + , label='半成品ID', required=False) # 从半成品表里直接修改状态 +class PickHalfsSerializer(serializers.ListSerializer): + child = PickHalfSerializer() class PickDetailSerializer(serializers.Serializer): material = serializers.PrimaryKeyRelatedField(queryset=Material.objects.all(), label="物料ID") batch = serializers.CharField(label='物料批次', allow_blank=True) @@ -289,11 +292,6 @@ class WpmTestRecordCreateSerializer(serializers.ModelSerializer): model = TestRecord fields = ['form', 'record_data', 'is_testok', 'wproduct'] -class WproductPutInSerializer(serializers.Serializer): - """ - 半成品入库序列化 - """ - class WplanPutInSerializer(serializers.Serializer): warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID") remark = serializers.CharField(label="入库备注", required =False) diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index b100adf..9d3b427 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -18,7 +18,7 @@ from rest_framework.decorators import action from apps.wpm.filters import WMaterialFilterSet from apps.wpm.models import OperationEquip, OperationWproduct, Pick, PickWproduct, WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem -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, WproductPutInsSerializer +from apps.wpm.serializers import OperationEquipListSerializer, OperationEquipUpdateSerializer, OperationMaterialCreate1Serailizer, OperationMaterialCreate2Serailizer, OperationMaterialCreate3Serializer, OperationMaterialListSerializer, OperationRecordListSerializer, OperationRecordSubmitSerializer, OperationUpdateSerializer, OperationWproductListSerializer, OperationCreateSerializer, OperationDetailSerializer, OperationListSerializer, PickHalfSerializer, PickHalfsSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer, WproductPutInSerializer, WproductPutInsSerializer from rest_framework.response import Response from django.db import transaction from rest_framework import exceptions, serializers @@ -41,7 +41,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet): ordering_fields = [] ordering = ['-update_time'] - @action(methods=['post', 'get'], detail=True, perms_map={'post':'*', 'get':'*'}, serializer_class=PickHalfSerializer) + @action(methods=['post', 'get'], detail=True, perms_map={'post':'*', 'get':'*'}, serializer_class=PickHalfsSerializer) @transaction.atomic def pick_half(self, request, pk=None): """ @@ -56,7 +56,7 @@ class WPlanViewSet(ListModelMixin, GenericViewSet): material__type=Material.MA_TYPE_HALFGOOD, subproduction_plan=sp).select_related('material') return Response(SubProductionProgressSerializer(instance=spps, many=True).data) elif request.method=='POST': - serializer= PickHalfSerializer(data=request.data, many=True) + serializer= PickHalfsSerializer(data=request.data) serializer.is_valid(raise_exception=True) vdata = serializer.data first_step = Step.objects.get(pk=sp.steps[0]['id']) @@ -85,8 +85,6 @@ class WPlanViewSet(ListModelMixin, GenericViewSet): pw.material = i.material pw.subproduction_plan = i.suproduction_plan pw.save() - else: - raise exceptions.APIException('未选择任何玻璃') sp.is_picked = True sp.save()