From a1ecad9ffecbe2b927c5588ddc4b97de5f3604b4 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 12 Nov 2021 13:16:29 +0800 Subject: [PATCH 01/12] =?UTF-8?q?=E9=A2=86=E6=96=99=E5=85=A5=E5=BA=93item?= =?UTF-8?q?=E5=85=B3=E8=81=94=E5=AD=90=E8=AE=A1=E5=88=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../inm/migrations/0016_auto_20211112_1124.py | 51 +++++++++++++++++++ hb_server/apps/inm/models.py | 17 ++++--- hb_server/apps/inm/serializers.py | 1 + .../mtm/migrations/0030_step_need_test.py | 18 +++++++ hb_server/apps/mtm/models.py | 1 + hb_server/apps/pm/signals.py | 2 + hb_server/apps/wpm/serializers.py | 4 +- hb_server/apps/wpm/views.py | 27 ++++++++-- 8 files changed, 109 insertions(+), 12 deletions(-) create mode 100644 hb_server/apps/inm/migrations/0016_auto_20211112_1124.py create mode 100644 hb_server/apps/mtm/migrations/0030_step_need_test.py diff --git a/hb_server/apps/inm/migrations/0016_auto_20211112_1124.py b/hb_server/apps/inm/migrations/0016_auto_20211112_1124.py new file mode 100644 index 0000000..f246b61 --- /dev/null +++ b/hb_server/apps/inm/migrations/0016_auto_20211112_1124.py @@ -0,0 +1,51 @@ +# Generated by Django 3.2.6 on 2021-11-12 03:24 + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('wpm', '0012_auto_20211111_1056'), + ('mtm', '0030_step_need_test'), + ('pm', '0012_alter_subproductionprogress_type'), + ('inm', '0015_auto_20211111_0940'), + ] + + operations = [ + migrations.RemoveField( + model_name='fifo', + name='subproduction_plan', + ), + migrations.RemoveField( + model_name='iproduct', + name='fifos', + ), + migrations.RemoveField( + model_name='iproduct', + name='state', + ), + migrations.AddField( + model_name='fifoitem', + name='subproduction_plan', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='pm.subproductionplan', verbose_name='关联子生产计划'), + ), + migrations.CreateModel( + name='FIFOItemProduct', + 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(max_length=50, verbose_name='物品编号')), + ('fifoitem', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inm.fifoitem', verbose_name='关联出入库具体产品')), + ('material', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='mtm.material', verbose_name='物料类型')), + ('wproduct', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.CASCADE, to='wpm.wproduct', verbose_name='关联的动态产品')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/hb_server/apps/inm/models.py b/hb_server/apps/inm/models.py index c82db9c..c3902bf 100644 --- a/hb_server/apps/inm/models.py +++ b/hb_server/apps/inm/models.py @@ -67,7 +67,6 @@ class FIFO(CommonAModel): type = models.IntegerField('出入库类型', default=1) is_audited = models.BooleanField('是否审核', default=False) auditor = models.ForeignKey(User, verbose_name='审核人', on_delete=models.CASCADE, null=True, blank=True) - subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.DO_NOTHING, null=True, blank=True) inout_date = models.DateField('出入库日期') remark = models.CharField('备注', max_length=1000, default='') @@ -83,23 +82,25 @@ class FIFOItem(BaseModel): count = models.IntegerField('数量', default=0, validators=[MinValueValidator(0)]) batch = models.CharField('批次号', max_length=100, default='') fifo = models.ForeignKey(FIFO, verbose_name='关联出入库', on_delete=models.CASCADE) + subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='关联子生产计划', on_delete=models.DO_NOTHING, null=True, blank=True) +class FIFOItemProduct(BaseModel): + """ + 出入库产品 + """ + fifoitem = models.ForeignKey(FIFOItem, verbose_name='关联出入库具体产品', on_delete=models.CASCADE) + wproduct = models.ForeignKey('wpm.wproduct', on_delete=models.CASCADE, verbose_name='关联的动态产品', db_constraint=False, null=True, blank=True) + number = models.CharField('物品编号', max_length=50) + material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE) class IProduct(BaseModel): """ 具体产品条目 """ - inm_product_state_choices = ( - (1, '可用'), - (2, '锁定'), - (3, '已消耗') - ) - state = models.IntegerField('物品状态', default=1) number = models.CharField('物品编号', unique=True, null=True, blank=True, max_length=50) material = models.ForeignKey(Material, verbose_name='物料类型', on_delete=models.CASCADE) warehouse = models.ForeignKey(WareHouse, on_delete=models.CASCADE, verbose_name='所在仓库') batch = models.CharField('所属批次号', max_length=100, default='') wproduct = models.ForeignKey('wpm.wproduct', on_delete=models.CASCADE, verbose_name='关联的动态产品', db_constraint=False, null=True, blank=True) - fifos = models.JSONField('关联出入库记录', default=list, blank=True) diff --git a/hb_server/apps/inm/serializers.py b/hb_server/apps/inm/serializers.py index 5bca091..e137622 100644 --- a/hb_server/apps/inm/serializers.py +++ b/hb_server/apps/inm/serializers.py @@ -130,6 +130,7 @@ class InmTestRecordItemCreateSerializer(serializers.ModelSerializer): class InmTestRecordCreateSerializer(serializers.ModelSerializer): record_data = InmTestRecordItemCreateSerializer(many=True) fifo_item = serializers.PrimaryKeyRelatedField(queryset=FIFOItem.objects.all(), required=True) + is_testok = serializers.BooleanField() class Meta: model = TestRecord fields = ['form', 'record_data', 'is_testok', 'fifo_item'] \ No newline at end of file diff --git a/hb_server/apps/mtm/migrations/0030_step_need_test.py b/hb_server/apps/mtm/migrations/0030_step_need_test.py new file mode 100644 index 0000000..c38b446 --- /dev/null +++ b/hb_server/apps/mtm/migrations/0030_step_need_test.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.6 on 2021-11-12 03:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0029_step_type'), + ] + + operations = [ + migrations.AddField( + model_name='step', + name='need_test', + field=models.BooleanField(default=False, verbose_name='是否需要过程检验'), + ), + ] diff --git a/hb_server/apps/mtm/models.py b/hb_server/apps/mtm/models.py index 99a19e3..53d24c3 100644 --- a/hb_server/apps/mtm/models.py +++ b/hb_server/apps/mtm/models.py @@ -81,6 +81,7 @@ class Step(CommonAModel): name = models.CharField('工序步骤名称', max_length=100) number = models.CharField('步骤编号', max_length=100, null=True, blank=True) instruction_content = models.TextField('相应操作指导', null=True, blank=True) + need_test = models.BooleanField('是否需要过程检验', default=False) sort = models.IntegerField('排序号', default=1) equipments = models.ManyToManyField(Equipment, verbose_name='使用设备', related_name='step_equips') diff --git a/hb_server/apps/pm/signals.py b/hb_server/apps/pm/signals.py index 69aa69c..9d6cd6c 100644 --- a/hb_server/apps/pm/signals.py +++ b/hb_server/apps/pm/signals.py @@ -13,6 +13,8 @@ def update_subplan_main(sender, instance, created, **kwargs): subplan.main_product = instance.material subplan.main_count = instance.count subplan.main_count_real = instance.count_real + if subplan.main_count == instance.count_real: + subplan.state = 4 subplan.save() diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index d9862b6..9edbbd0 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -25,7 +25,7 @@ class PickSerializer(serializers.Serializer): def create(self, validated_data): picks = validated_data.pop('picks') - sp = validated_data['subproduction_plan'] + sp = validated_data.pop('subproduction_plan') if sp.state not in [1,2]: raise exceptions.ValidationError('该子计划状态错误') if sp.is_picked: @@ -48,6 +48,7 @@ class PickSerializer(serializers.Serializer): i['fifo'] = fifo i['count'] = i.pop('pick_count') i['is_testok'] = True # 默认检测合格 + i['subproduction_plan'] = sp FIFOItem.objects.create(**i) # 更新车间物料 wm, _ = WMaterial.objects.get_or_create(material=i['material'], batch=i['batch'], \ @@ -183,6 +184,7 @@ class WpmTestRecordItemCreateSerializer(serializers.ModelSerializer): class WpmTestRecordCreateSerializer(serializers.ModelSerializer): record_data = WpmTestRecordItemCreateSerializer(many=True) wproduct = serializers.PrimaryKeyRelatedField(queryset=WProduct.objects.all(), required=True) + is_testok = serializers.BooleanField() class Meta: model = TestRecord fields = ['form', 'record_data', 'is_testok', 'wproduct'] diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index c49e9ba..6a9b61b 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -53,6 +53,7 @@ class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet): serializer.save() return Response() + class WProductViewSet(ListModelMixin, GenericViewSet): """ 半成品 @@ -65,6 +66,13 @@ class WProductViewSet(ListModelMixin, GenericViewSet): ordering_fields = ['id'] ordering = ['id'] + @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WpmTestRecordCreateSerializer) + @transaction.atomic + def putin(): + """ + 半成品入库 + """ + @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WpmTestRecordCreateSerializer) @transaction.atomic def test(self, request, pk=None): @@ -77,7 +85,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet): record_data = vdata.pop('record_data') wproduct = vdata['wproduct'] if wproduct.act_state != WProduct.WPR_ACT_STATE_TOTEST: - raise exceptions.APIException('该半成品无需检测') + raise exceptions.APIException('该半成品不可检测') if 'is_testok' not in vdata: raise exceptions.APIException('未填写检测结论') @@ -96,8 +104,21 @@ class WProductViewSet(ListModelMixin, GenericViewSet): tris.append(TestRecordItem(**m)) TestRecordItem.objects.bulk_create(tris) - # 如果检测合格 - + # 如果检测合格, 变更动态产品进行状态 + + if obj.is_testok: + vdata['wproduct'].act_state = WProduct.WPR_ACT_STATE_OK + vdata['wproduct'].save() + # 更新子计划状态 + # 获取该子计划主产品数, 更新进度 + main_count = WProduct.objects.filter(subproduction_plan=wproduct.subproduction_plan, act_stae=WProduct.WPR_ACT_STATE_OK).count() + instance = SubProductionProgress.objects.get(subproduction_plan=wproduct.subproduction_plan, + is_main=True, type=SubprodctionMaterial.SUB_MA_TYPE_OUT) + instance.count_real = main_count + instance.save() + else:# 如果不合格 + pass + return Response() class OperationViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): From d28bbc4439525fba205bf74794280659487aa30e Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 12 Nov 2021 16:43:26 +0800 Subject: [PATCH 02/12] =?UTF-8?q?=E9=A2=86=E6=96=99bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/serializers.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 9edbbd0..3725c71 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -39,10 +39,7 @@ class PickSerializer(serializers.Serializer): # raise exceptions.ValidationError('物料不存在') # 创建出库记录 with transaction.atomic(): - validated_data['create_by'] = self.context['request'].user - validated_data['type'] = FIFO.FIFO_TYPE_DO_OUT - validated_data['inout_date'] = timezone.now() - fifo = FIFO.objects.create(**validated_data) + fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_OUT, inout_date=timezone.now(), create_by=self.context['request'].user) for i in picks: # 更新出库详情 i['fifo'] = fifo From a78a10c3fa2f6cc070c442eb564858f410f83c43 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 15 Nov 2021 09:16:16 +0800 Subject: [PATCH 03/12] =?UTF-8?q?=E9=A2=86=E6=96=99=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=EF=BC=8C=E6=93=8D=E4=BD=9C=E8=A1=A8=E5=8D=95=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/mtm/models.py | 10 ++++----- hb_server/apps/pm/views.py | 2 +- hb_server/apps/system/models.py | 25 +++++++++++++++++++++ hb_server/apps/wpm/serializers.py | 17 +++++++------- hb_server/apps/wpm/views.py | 37 +++++++++++++++++++------------ 5 files changed, 63 insertions(+), 28 deletions(-) diff --git a/hb_server/apps/mtm/models.py b/hb_server/apps/mtm/models.py index 53d24c3..614024d 100644 --- a/hb_server/apps/mtm/models.py +++ b/hb_server/apps/mtm/models.py @@ -2,7 +2,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.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 from apps.system.models import Organization @@ -178,7 +178,7 @@ class SubProduction(CommonAModel): verbose_name = '产品生产工序' verbose_name_plural = verbose_name -class SubprodctionMaterial(CommonAModel): +class SubprodctionMaterial(CommonADModel): """ 输入/输出物料/工具工装 """ @@ -198,20 +198,20 @@ class SubprodctionMaterial(CommonAModel): sort = models.IntegerField('排序号', default=1) -class UsedStep(CommonAModel): +class UsedStep(CommonADModel): """ 涉及的生产子工序 """ step = models.ForeignKey(Step, verbose_name='子工序', on_delete=models.CASCADE, related_name='usedstep') remark = models.TextField('生产备注', null=True, blank=True) - subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE) + subproduction = models.ForeignKey(SubProduction, verbose_name='关联生产分解', on_delete=models.CASCADE, related_name='usedstep_subproduction') class Meta: verbose_name = '产品生产子工序' verbose_name_plural = verbose_name -class TechDoc(CommonAModel): +class TechDoc(CommonADModel): """ 技术文件 """ diff --git a/hb_server/apps/pm/views.py b/hb_server/apps/pm/views.py index 0a42efd..45b573b 100644 --- a/hb_server/apps/pm/views.py +++ b/hb_server/apps/pm/views.py @@ -159,7 +159,7 @@ class SubProductionPlanViewSet(CreateUpdateModelAMixin, ListModelMixin, UpdateMo serializer = SubProductionProgressSerializer(instance=instance, many=True) return Response(serializer.data) - @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=PickNeedSerializer) + @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=serializers.Serializer) def pick_need(self, request, pk=None): """ 领料需求清单/库存数 diff --git a/hb_server/apps/system/models.py b/hb_server/apps/system/models.py index 7515bce..c773fcf 100644 --- a/hb_server/apps/system/models.py +++ b/hb_server/apps/system/models.py @@ -177,6 +177,18 @@ class CommonAModel(SoftModel): class Meta: abstract = True +class CommonADModel(BaseModel): + """ + 业务用基本表A,包含create_by, update_by字段, 硬删除 + """ + create_by = models.ForeignKey( + User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='创建人', related_name= '%(class)s_create_by') + update_by = models.ForeignKey( + User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='最后编辑人', related_name= '%(class)s_update_by') + + class Meta: + abstract = True + class CommonBModel(SoftModel): """ 业务用基本表B,包含create_by, update_by, belong_dept字段 @@ -191,6 +203,19 @@ class CommonBModel(SoftModel): class Meta: abstract = True +class CommonBDModel(BaseModel): + """ + 业务用基本表B,包含create_by, update_by, belong_dept字段, 硬删除 + """ + create_by = models.ForeignKey( + User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='创建人', related_name = '%(class)s_create_by') + update_by = models.ForeignKey( + User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='最后编辑人', related_name = '%(class)s_update_by') + belong_dept = models.ForeignKey( + Organization, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='所属部门', related_name= '%(class)s_belong_dept') + + class Meta: + abstract = True class File(CommonAModel): """ diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 3725c71..5197848 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -113,17 +113,17 @@ class OperationListSerializer(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") + # 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) def validate(self, data): - subproduction_plan = data['subproduction_plan'] + # subproduction_plan = data['subproduction_plan'] step = data['step'] - stepIds=[i['id'] for i in subproduction_plan.steps] - if step.id not in stepIds: - raise exceptions.ValidationError('请选择正确的子工序操作') + # stepIds=[i['id'] for i in subproduction_plan.steps] + # if step.id not in stepIds: + # raise exceptions.ValidationError('请选择正确的子工序操作') if 'wproducts' in data and data['wproducts']: if step.type == Step.STEP_TYPE_DIV: @@ -131,8 +131,8 @@ class OperationInitSerializer(serializers.Serializer): for i in data['wproducts']: if i.is_executed: raise exceptions.ValidationError('不可进行操作') - if i.subproduction_plan != subproduction_plan: - raise exceptions.ValidationError('半成品所属子计划不一致') + # if i.subproduction_plan != subproduction_plan: + # raise exceptions.ValidationError('半成品所属子计划不一致') if i.p_state != step: raise exceptions.ValidationError('半成品所属子工序不一致') else: @@ -146,6 +146,7 @@ class DoInputSerializer(serializers.Serializer): count_input = serializers.IntegerField(min_value=0, label='消耗数量') class DoOutputSerializer(serializers.Serializer): + subproduction_plan = serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID", required=False) material = serializers.PrimaryKeyRelatedField(queryset=Material.objects.all(), label='物料ID') count_output = serializers.IntegerField(min_value=0, label='产出数量') @@ -164,7 +165,7 @@ class OperationRecordSerializer(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") + # 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) input = DoInputSerializer(many=True, required=False) diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 6a9b61b..b387741 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -151,26 +151,33 @@ class DoFormInit(CreateAPIView, GenericAPIView): ret = {} ret_0 = {} ret_0['step'] = data['step'] - ret_0['subproduction_plan'] = data['subproduction_plan'] + splans =[] + ret_0['input'] = [] + # ret_0['subproduction_plan'] = data['subproduction_plan'] if 'wproducts' in data and data['wproducts']: ret_0['wproducts'] = data['wproducts'] + splans = WProduct.objects.filter(id__in=data['wproducts']).values('subproduction_plan', flat=True) + # 调出所属子计划现有物料 + ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter(subproduction_plan__in=splans), many=True) else: ret_0['wproducts'] = [] - # 调出该子计划现有物料 - ret_0['input'] = list(WMaterial.objects.filter(subproduction_plan=vdata['subproduction_plan'])\ - .values('id', 'material', 'material__name', 'count', 'material__number', 'batch')) + + for i in ret_0['input']: i['count_input'] = 0 # 需要输出的物料 if ret_0['wproducts']: # 排除主要产物, 因为已经放到半成品里了, 由半成品进行处理, 夹层可能需要特殊处理 o_objs = SubProductionProgress.objects.filter( - subproduction_plan=vdata['subproduction_plan'], type=SubprodctionMaterial.SUB_MA_TYPE_OUT).exclude(is_main=True) + subproduction_plan__in=splans, type=SubprodctionMaterial.SUB_MA_TYPE_OUT).exclude(is_main=True) else: + # 此时显示所有子计划的情况 + splans = SubProductionPlan.objects.filter(is_deleted=False, + subproduction__usedstep_subproduction__step=vdata['step'], state=3) o_objs = SubProductionProgress.objects.filter( - subproduction_plan=vdata['subproduction_plan'], type=SubprodctionMaterial.SUB_MA_TYPE_OUT) - ret_0['output'] = list(o_objs.values('material', 'material__name', 'material__number')) + subproduction_plan__in=splans, type=SubprodctionMaterial.SUB_MA_TYPE_OUT) + ret_0['output'] = list(o_objs.values('subproduction_plan', 'material', 'material__name', 'material__number')) for i in ret_0['output']: i['count_output']=0 ret['forms'] = [] @@ -227,16 +234,16 @@ class DoFormSubmit(CreateAPIView, GenericAPIView): if 'output' in data and data['output']: for i in vdata['output']: # 已经序列化好的数据 ma = i['material'] - if vdata['subproduction_plan'].main_product == ma: # 如果是该计划主产物 + if i['subproduction_plan'].main_product == ma: # 如果是该计划主产物 # 如果是切割 # 获取下一步子工序 if vdata['step'].type == Step.STEP_TYPE_DIV: - stepIds = [i['id'] for i in vdata['subproduction_plan'].steps] + stepIds = [i['id'] for i in i['subproduction_plan'].steps] pindex = stepIds.index(vdata['step'].id) wpr = dict(m_state=ma, p_state=Step.objects.get(pk=stepIds[pindex+1]), act_state=WProduct.WPR_ACT_STATE_DOING, is_executed=False, remark='', - subproduction_plan=vdata['subproduction_plan'], - production_plan=vdata['subproduction_plan'].production_plan) + subproduction_plan=i['subproduction_plan'], + production_plan=i['subproduction_plan'].production_plan) for x in range(i['count_output']): WProduct.objects.create(**wpr) else: @@ -244,18 +251,20 @@ class DoFormSubmit(CreateAPIView, GenericAPIView): OperationMaterial.objects.create(type=2, operation=action_obj, material= ma, count=i['count_output']) # 更新车间物料表 - ins, _ = WMaterial.objects.get_or_create(subproduction_plan=vdata['subproduction_plan'], + ins, _ = WMaterial.objects.get_or_create(subproduction_plan=i['subproduction_plan'], material=ma) ins.count = ins.count + i['count_output'] ins.save() # 更新子计划进度表 - sp = SubProductionProgress.objects.get(subproduction_plan=vdata['subproduction_plan'], + sp = SubProductionProgress.objects.get(subproduction_plan=i['subproduction_plan'], material=ma) sp.count_real = sp.count_real + i['count_input'] sp.save() # 更新动态产品表 - if 'wproducts' in data and data['wproducts']: + if 'wproducts' in vdata and data['wproducts']: + for i in data['wproducts']: + pass wproducts = WProduct.objects.filter(pk__in=data['wproducts']) # 获取下一步子工序 stepIds = [i['id'] for i in vdata['subproduction_plan'].steps] From b09b3996ac3a96f1c56a70ddd6e9094453d5aa59 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 15 Nov 2021 11:23:01 +0800 Subject: [PATCH 04/12] =?UTF-8?q?=E5=AD=90=E5=B7=A5=E5=BA=8F=E6=93=8D?= =?UTF-8?q?=E4=BD=9C?= 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/services.py | 15 ++++++ hb_server/apps/wpm/views.py | 89 ++++++++++++++++--------------- 3 files changed, 62 insertions(+), 46 deletions(-) create mode 100644 hb_server/apps/wpm/services.py diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 5197848..b35fa0b 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -113,7 +113,7 @@ class OperationListSerializer(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) + 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) @@ -165,7 +165,7 @@ class OperationRecordSerializer(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) + 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) input = DoInputSerializer(many=True, required=False) diff --git a/hb_server/apps/wpm/services.py b/hb_server/apps/wpm/services.py new file mode 100644 index 0000000..de6e5c8 --- /dev/null +++ b/hb_server/apps/wpm/services.py @@ -0,0 +1,15 @@ +from apps.pm.models import SubProductionPlan +from apps.mtm.models import Step +class WpmServies(object): + + @classmethod + def get_next_step(cls, subproduction_plan:SubProductionPlan, nowstep:Step): + """ + 获取下一步骤 + """ + stepIds = [i['id'] for i in subproduction_plan.steps] + pindex = stepIds.index(nowstep.id) + if pindex + 1 < len(stepIds): + return Step.objects.get(pk=stepIds[pindex+1]), True + else: + return nowstep, False \ No newline at end of file diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index b387741..91c7524 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -19,6 +19,8 @@ from apps.wpm.serializers import OperationDetailSerializer, OperationListSeriali from rest_framework.response import Response from django.db import transaction from rest_framework import exceptions + +from apps.wpm.services import WpmServies # Create your views here. class WPlanViewSet(ListModelMixin, GenericViewSet): """ @@ -158,9 +160,15 @@ class DoFormInit(CreateAPIView, GenericAPIView): ret_0['wproducts'] = data['wproducts'] splans = WProduct.objects.filter(id__in=data['wproducts']).values('subproduction_plan', flat=True) # 调出所属子计划现有物料 - ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter(subproduction_plan__in=splans), many=True) + ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter(subproduction_plan__in=splans), many=True).data else: + if 'subproduction_plan' in vdata: + splans = [vdata['subproduction_plan']] + else: + splans = SubProductionPlan.objects.filter(is_deleted=False, + subproduction__usedstep_subproduction__step=vdata['step'], state=3) ret_0['wproducts'] = [] + ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter(subproduction_plan__in=splans), many=True).data for i in ret_0['input']: @@ -172,9 +180,7 @@ class DoFormInit(CreateAPIView, GenericAPIView): subproduction_plan__in=splans, type=SubprodctionMaterial.SUB_MA_TYPE_OUT).exclude(is_main=True) else: - # 此时显示所有子计划的情况 - splans = SubProductionPlan.objects.filter(is_deleted=False, - subproduction__usedstep_subproduction__step=vdata['step'], state=3) + # 此时显示所有子计划需要输出的物料 o_objs = SubProductionProgress.objects.filter( subproduction_plan__in=splans, type=SubprodctionMaterial.SUB_MA_TYPE_OUT) ret_0['output'] = list(o_objs.values('subproduction_plan', 'material', 'material__name', 'material__number')) @@ -238,9 +244,8 @@ class DoFormSubmit(CreateAPIView, GenericAPIView): # 如果是切割 # 获取下一步子工序 if vdata['step'].type == Step.STEP_TYPE_DIV: - stepIds = [i['id'] for i in i['subproduction_plan'].steps] - pindex = stepIds.index(vdata['step'].id) - wpr = dict(m_state=ma, p_state=Step.objects.get(pk=stepIds[pindex+1]), + newstep, _ = WpmServies.get_next_step(i['subproduction_plan'], vdata['step']) + wpr = dict(m_state=ma, p_state=newstep, act_state=WProduct.WPR_ACT_STATE_DOING, is_executed=False, remark='', subproduction_plan=i['subproduction_plan'], production_plan=i['subproduction_plan'].production_plan) @@ -262,44 +267,40 @@ class DoFormSubmit(CreateAPIView, GenericAPIView): sp.save() # 更新动态产品表 - if 'wproducts' in vdata and data['wproducts']: - for i in data['wproducts']: - pass - wproducts = WProduct.objects.filter(pk__in=data['wproducts']) - # 获取下一步子工序 - stepIds = [i['id'] for i in vdata['subproduction_plan'].steps] - pindex = stepIds.index(vdata['step'].id) - if pindex + 1 < len(stepIds): # 如果不是最后一步 - newstep = Step.objects.get(pk=stepIds[pindex+1]) - wproducts.update(p_state=newstep, is_executed=False, pre_pstate=vdata['step']) - - # 特殊情况如果是夹层结合 - if vdata['step'].type == Step.STEP_TYPE_COMB: + if 'wproducts' in vdata and vdata['wproducts']: + if vdata['step'].type == Step.STEP_TYPE_COMB: + wproducts = vdata['wproducts'] + if 'suproduction_plan' in vdata: wproducts.update(is_hidden=True) # 隐藏 - - WProduct.objects.create( - m_state=vdata['subproduction_plan'].main_product, p_state = newstep, - act_state=WProduct.WPR_ACT_STATE_DOING, is_executed=False, remark='', - subproduction_plan=vdata['subproduction_plan'], - production_plan=vdata['subproduction_plan'].production_plan, - parent = data['wproducts'] - ) - - else: # 如果是最后一步, 此时需要转序并更新状态为待检测, 此时物料状态需变成当前子计划的主产物状态 - newstep = vdata['step'] - wproducts.update(p_state=newstep, is_executed=True, - act_state=WProduct.WPR_ACT_STATE_TOTEST, pre_pstate=newstep, m_state=vdata['subproduction_plan'].main_product) - - # 特殊情况如果是夹层结合 - if vdata['step'].type == Step.STEP_TYPE_COMB: - wproducts.update(is_hidden=True) # 隐藏 - - WProduct.objects.create( - m_state=vdata['subproduction_plan'].main_product, p_state = newstep, - act_state=WProduct.WPR_ACT_STATE_TOTEST, is_executed=True, remark='', - subproduction_plan=vdata['subproduction_plan'], - production_plan=vdata['subproduction_plan'].production_plan - ) + newstep, hasNext = WpmServies.get_next_step(i['subproduction_plan'], vdata['step']) + wproduct = WProduct() + wproduct.m_state = vdata['subproduction_plan'].main_product + wproduct.p_state = newstep + wproduct.subproduction_plan=vdata['subproduction_plan'] + wproduct.production_plan=vdata['subproduction_plan'].production_plan + wproduct.parent = data['wproducts'] + if hasNext: + wproduct.act_state=WProduct.WPR_ACT_STATE_DOING + wproduct.is_executed=False + else: + wproduct.act_state=WProduct.WPR_ACT_STATE_TOTEST + wproduct.is_executed=True + wproduct.save() + else: + raise exceptions.APIException('请指定子计划') + else: + for wproduct in vdata['wproducts']: + # 获取下一步子工序 + newstep, hasNext = WpmServies.get_next_step(i['subproduction_plan'], vdata['step']) + wproduct.p_state = newstep + wproduct.pre_pstate=vdata['step'] + if hasNext: + wproduct.is_executed= False + else: + wproduct.is_executed= True + wproduct.act_state=WProduct.WPR_ACT_STATE_TOTEST + wproduct.m_state=wproduct.subproduction_plan.main_product + wproduct.save() # 保存自定义表单结果 for i in vdata['forms']: From 6aa30e9c6ad2e08e75f7aebf3b8d8c759861d739 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 15 Nov 2021 11:32:47 +0800 Subject: [PATCH 05/12] =?UTF-8?q?=E5=AD=90=E5=B7=A5=E5=BA=8F=E6=93=8D?= =?UTF-8?q?=E4=BD=9Cbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/serializers.py | 5 +++++ hb_server/apps/wpm/views.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index b35fa0b..d8194e1 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -186,6 +186,11 @@ class WpmTestRecordCreateSerializer(serializers.ModelSerializer): class Meta: model = TestRecord fields = ['form', 'record_data', 'is_testok', 'wproduct'] + +class WproductPutin(serializers.Serializer): + """ + 半成品入库序列化 + """ \ No newline at end of file diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 91c7524..414669c 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -158,7 +158,7 @@ class DoFormInit(CreateAPIView, GenericAPIView): # ret_0['subproduction_plan'] = data['subproduction_plan'] if 'wproducts' in data and data['wproducts']: ret_0['wproducts'] = data['wproducts'] - splans = WProduct.objects.filter(id__in=data['wproducts']).values('subproduction_plan', flat=True) + splans = WProduct.objects.filter(id__in=data['wproducts']).values_list('subproduction_plan', flat=True) # 调出所属子计划现有物料 ret_0['input'] = WMaterialListSerializer(instance=WMaterial.objects.filter(subproduction_plan__in=splans), many=True).data else: From 5379b84438edab7efbf78e8642c6dc996e788614 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 15 Nov 2021 13:52:12 +0800 Subject: [PATCH 06/12] =?UTF-8?q?=E5=8D=8A=E6=88=90=E5=93=81=E5=85=A5?= =?UTF-8?q?=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/inm/signals.py | 2 +- hb_server/apps/wpm/serializers.py | 7 +++- hb_server/apps/wpm/views.py | 59 ++++++++++++++++++++++++++----- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/hb_server/apps/inm/signals.py b/hb_server/apps/inm/signals.py index 83c28f5..d62ba49 100644 --- a/hb_server/apps/inm/signals.py +++ b/hb_server/apps/inm/signals.py @@ -8,7 +8,7 @@ def update_inm(instance:FIFO, type:int=1): """ 更新库存(正反) """ - if instance.type in [FIFO.FIFO_TYPE_PUR_IN]: # 采购入库 + if instance.type in [FIFO.FIFO_TYPE_PUR_IN, FIFO.FIFO_TYPE_DO_IN]: # 采购入库, 生产入库 # 更新相关表 for i in FIFOItem.objects.filter(fifo=instance): material = i.material diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index d8194e1..7f3555c 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -187,10 +187,15 @@ class WpmTestRecordCreateSerializer(serializers.ModelSerializer): model = TestRecord fields = ['form', 'record_data', 'is_testok', 'wproduct'] -class WproductPutin(serializers.Serializer): +class WproductPutInSerializer(serializers.Serializer): """ 半成品入库序列化 """ + +class WplanPutInSerializer(serializers.Serializer): + warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID") + remark = serializers.CharField(label="入库备注", required =False) + \ No newline at end of file diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 414669c..fec4feb 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -5,6 +5,8 @@ from rest_framework.utils import serializer_helpers from rest_framework.utils.field_mapping import get_relation_kwargs from rest_framework.views import APIView from rest_framework.viewsets import GenericViewSet, ModelViewSet +from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct +from apps.inm.signals import update_inm from apps.mtm.models import Material, RecordForm, Step, SubprodctionMaterial from apps.mtm.serializers import RecordFormDetailSerializer from apps.pm.models import SubProductionPlan, SubProductionProgress @@ -15,12 +17,13 @@ from apps.system.mixins import CreateUpdateModelAMixin, OptimizationMixin from rest_framework.decorators import action from apps.wpm.models import WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem -from apps.wpm.serializers import OperationDetailSerializer, OperationListSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WpmTestRecordCreateSerializer +from apps.wpm.serializers import OperationDetailSerializer, OperationListSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer from rest_framework.response import Response from django.db import transaction -from rest_framework import exceptions +from rest_framework import exceptions, serializers from apps.wpm.services import WpmServies +from django.utils import timezone # Create your views here. class WPlanViewSet(ListModelMixin, GenericViewSet): """ @@ -34,6 +37,51 @@ class WPlanViewSet(ListModelMixin, GenericViewSet): ordering_fields = ['process__number'] ordering = ['process__number'] + @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WplanPutInSerializer) + @transaction.atomic + def putin(self, request, pk=None): + """ + 半成品入库 + """ + serializer= WplanPutInSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + vdata = serializer.data + subplan = self.get_object() + material = subplan.main_product + batch = subplan.production_plan.number + wproducts = WProduct.objects.filter(subproduction_plan=subplan, + act_state=WProduct.WPR_ACT_STATE_OK, m_state=material, is_deleted=False) + if wproducts.exists(): + # 创建入库记录 + fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_IN, + is_audited=True, auditor=request.user, inout_date=timezone.now(), create_by=request.user) + # 创建入库明细 + fifoitem = FIFOItem() + fifoitem.is_tested = True + fifoitem.is_testok = True + fifoitem.warehouse = vdata['warehouse'] + fifoitem.material = material + fifoitem.count = wproducts.count() + fifoitem.batch = batch + fifoitem.fifo = fifo + fifoitem.subproduction_plan = subplan + fifoitem.save() + # 创建入库明细半成品 + ips = [] + for i in wproducts: + ip = {} + ip['fifoitem'] = fifoitem + ip['wproduct'] = i + ip['number'] = i.number + ip['material'] = material + ips.append(FIFOItemProduct(**ip)) + FIFOItemProduct.objects.bulk_create(ips) + # 更新库存隐藏半成品 + update_inm(fifo) + wproducts.update(is_hidden=True) + return Response() + + class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet): """ 车间物料表 @@ -68,13 +116,6 @@ class WProductViewSet(ListModelMixin, GenericViewSet): ordering_fields = ['id'] ordering = ['id'] - @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WpmTestRecordCreateSerializer) - @transaction.atomic - def putin(): - """ - 半成品入库 - """ - @action(methods=['post'], detail=False, perms_map={'post':'*'}, serializer_class=WpmTestRecordCreateSerializer) @transaction.atomic def test(self, request, pk=None): From 25211e9e5aad081a96da79e29cd81a0b06bac9d4 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Mon, 15 Nov 2021 14:06:18 +0800 Subject: [PATCH 07/12] =?UTF-8?q?=E5=BE=85=E6=A3=80=E6=B5=8B=E5=8D=8A?= =?UTF-8?q?=E6=88=90=E5=93=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/inm/signals.py | 4 +++- hb_server/apps/wpm/views.py | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/hb_server/apps/inm/signals.py b/hb_server/apps/inm/signals.py index d62ba49..7259090 100644 --- a/hb_server/apps/inm/signals.py +++ b/hb_server/apps/inm/signals.py @@ -1,7 +1,7 @@ from django.db.models.signals import post_save from django.dispatch import receiver -from apps.inm.models import Inventory, MaterialBatch, FIFO, FIFOItem +from apps.inm.models import FIFOItemProduct, Inventory, MaterialBatch, FIFO, FIFOItem def update_inm(instance:FIFO, type:int=1): @@ -23,6 +23,8 @@ def update_inm(instance:FIFO, type:int=1): o2.save() material.count = material.count + i.count material.save() + # 如果有详细半成品 + pass elif instance.type in [FIFO.FIFO_TYPE_DO_OUT]: # 生产领料 # 更新相关表 for i in FIFOItem.objects.filter(fifo=instance): diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index fec4feb..88fa039 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -53,8 +53,9 @@ class WPlanViewSet(ListModelMixin, GenericViewSet): act_state=WProduct.WPR_ACT_STATE_OK, m_state=material, is_deleted=False) if wproducts.exists(): # 创建入库记录 + 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) + is_audited=True, auditor=request.user, inout_date=timezone.now(), create_by=request.user, remark=remark) # 创建入库明细 fifoitem = FIFOItem() fifoitem.is_tested = True @@ -111,7 +112,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet): perms_map={'*':'*'} queryset = WProduct.objects.select_related('p_state', 'm_state').filter(is_hidden=False) serializer_class = WProductListSerializer - filterset_fields = ['p_state', 'subproduction_plan', 'm_state', 'production_plan', 'p_state__process'] + filterset_fields = ['p_state', 'subproduction_plan', 'm_state', 'production_plan', 'p_state__process', 'act_state'] search_fields = ['number'] ordering_fields = ['id'] ordering = ['id'] From 5904ab147597af8be0e19ce56c248a04b0bb4617 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 16 Nov 2021 08:42:45 +0800 Subject: [PATCH 08/12] =?UTF-8?q?=E7=94=9F=E4=BA=A7=E5=85=A5=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/inm/serializers.py | 13 +++++++--- hb_server/apps/inm/signals.py | 2 -- .../mtm/migrations/0031_auto_20211116_0841.py | 24 ++++++++++++++++++ hb_server/apps/mtm/models.py | 2 +- .../0009_alter_testrecorditem_is_testok.py | 18 +++++++++++++ hb_server/apps/qm/models.py | 2 +- hb_server/apps/wf/services.py | 2 +- .../wpm/migrations/0013_auto_20211116_0841.py | 25 +++++++++++++++++++ hb_server/apps/wpm/models.py | 6 ++++- hb_server/apps/wpm/views.py | 20 ++++++++++++--- 10 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 hb_server/apps/mtm/migrations/0031_auto_20211116_0841.py create mode 100644 hb_server/apps/qm/migrations/0009_alter_testrecorditem_is_testok.py create mode 100644 hb_server/apps/wpm/migrations/0013_auto_20211116_0841.py diff --git a/hb_server/apps/inm/serializers.py b/hb_server/apps/inm/serializers.py index e137622..f398159 100644 --- a/hb_server/apps/inm/serializers.py +++ b/hb_server/apps/inm/serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers -from apps.inm.models import FIFO, FIFOItem, IProduct, MaterialBatch, WareHouse,Inventory +from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct, MaterialBatch, WareHouse,Inventory from apps.qm.models import TestRecord, TestRecordItem from apps.system.serializers import UserSimpleSerializer @@ -105,14 +105,19 @@ class FIFOInPurSerializer(serializers.ModelSerializer): raise serializers.ValidationError('数目对不上') else: i['fifo'] = obj - fifod = FIFOItem.objects.create(**i) + fifoitem = FIFOItem.objects.create(**i) + p_list0 = [] + for x in p_details: + x['material'] = i['material'] + x['fifoitem'] = fifoitem + p_list0.append(FIFOItemProduct(**x)) + FIFOItemProduct.objects.bulk_create(p_list0) + p_list = [] for x in p_details: - x['state'] = 1 x['material'] = i['material'] x['warehouse'] = validated_data['warehouse'] x['batch'] = i['batch'] - x['fifos'] = [fifod.id] p_list.append(IProduct(**x)) IProduct.objects.bulk_create(p_list) else: diff --git a/hb_server/apps/inm/signals.py b/hb_server/apps/inm/signals.py index 7259090..66870a4 100644 --- a/hb_server/apps/inm/signals.py +++ b/hb_server/apps/inm/signals.py @@ -23,8 +23,6 @@ def update_inm(instance:FIFO, type:int=1): o2.save() material.count = material.count + i.count material.save() - # 如果有详细半成品 - pass elif instance.type in [FIFO.FIFO_TYPE_DO_OUT]: # 生产领料 # 更新相关表 for i in FIFOItem.objects.filter(fifo=instance): diff --git a/hb_server/apps/mtm/migrations/0031_auto_20211116_0841.py b/hb_server/apps/mtm/migrations/0031_auto_20211116_0841.py new file mode 100644 index 0000000..91e81b6 --- /dev/null +++ b/hb_server/apps/mtm/migrations/0031_auto_20211116_0841.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2.6 on 2021-11-16 00:41 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0030_step_need_test'), + ] + + operations = [ + migrations.AlterField( + model_name='recordform', + name='name', + field=models.CharField(max_length=100, verbose_name='表格名称'), + ), + migrations.AlterField( + model_name='usedstep', + name='subproduction', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='usedstep_subproduction', to='mtm.subproduction', verbose_name='关联生产分解'), + ), + ] diff --git a/hb_server/apps/mtm/models.py b/hb_server/apps/mtm/models.py index 614024d..ef0426c 100644 --- a/hb_server/apps/mtm/models.py +++ b/hb_server/apps/mtm/models.py @@ -102,7 +102,7 @@ class RecordForm(CommonAModel): (RF_TYPE_DO, '生产记录'), (RF_TYPE_TEST, '检验记录') ) - name = models.CharField('表格名称', max_length=100, unique=True) + name = models.CharField('表格名称', max_length=100) type = models.IntegerField('表格类型', choices=type_choices, default=1) step = models.ForeignKey(Step, verbose_name='关联子工序', on_delete=models.CASCADE, null=True, blank=True) material = models.ForeignKey(Material, verbose_name='关联物料', on_delete=models.CASCADE, null=True, blank=True) diff --git a/hb_server/apps/qm/migrations/0009_alter_testrecorditem_is_testok.py b/hb_server/apps/qm/migrations/0009_alter_testrecorditem_is_testok.py new file mode 100644 index 0000000..6d9507f --- /dev/null +++ b/hb_server/apps/qm/migrations/0009_alter_testrecorditem_is_testok.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.6 on 2021-11-16 00:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('qm', '0008_auto_20211111_1405'), + ] + + operations = [ + migrations.AlterField( + model_name='testrecorditem', + name='is_testok', + field=models.BooleanField(blank=True, null=True, verbose_name='是否合格'), + ), + ] diff --git a/hb_server/apps/qm/models.py b/hb_server/apps/qm/models.py index 35d77d8..0cc9d5d 100644 --- a/hb_server/apps/qm/models.py +++ b/hb_server/apps/qm/models.py @@ -66,5 +66,5 @@ class TestRecordItem(BaseModel): field_value = models.JSONField('录入值', default=dict, blank=True) need_judge = models.BooleanField('是否需要判定', default=False) sort = models.IntegerField('排序号', default=1) - is_testok = models.BooleanField('是否合格', default=True) + is_testok = models.BooleanField('是否合格', null=True, blank=True) test_record = models.ForeignKey(TestRecord, verbose_name='关联的检测记录', on_delete=models.CASCADE, related_name='item_test_record') \ No newline at end of file diff --git a/hb_server/apps/wf/services.py b/hb_server/apps/wf/services.py index bc39a3e..badfc5e 100644 --- a/hb_server/apps/wf/services.py +++ b/hb_server/apps/wf/services.py @@ -121,7 +121,7 @@ class WfService(object): for i in transition.condition_expression: expression = i['expression'].format(**ticket_all_value) import datetime, time # 用于支持条件表达式中对时间的操作 - if eval(expression, {"__builtins__":None}, {'datetime':datetime, 'time':time}): + if eval(expression, {'__builtins__':None}, {'datetime':datetime, 'time':time}): destination_state = State.objects.get(pk=i['target_state']) return destination_state diff --git a/hb_server/apps/wpm/migrations/0013_auto_20211116_0841.py b/hb_server/apps/wpm/migrations/0013_auto_20211116_0841.py new file mode 100644 index 0000000..b5264ba --- /dev/null +++ b/hb_server/apps/wpm/migrations/0013_auto_20211116_0841.py @@ -0,0 +1,25 @@ +# Generated by Django 3.2.6 on 2021-11-16 00:41 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('inm', '0016_auto_20211112_1124'), + ('wpm', '0012_auto_20211111_1056'), + ] + + operations = [ + migrations.AddField( + model_name='wproduct', + name='warehouse', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='inm.warehouse', verbose_name='所在仓库'), + ), + migrations.AlterField( + model_name='wproduct', + name='act_state', + field=models.IntegerField(choices=[(1, '生产中'), (2, '待检测'), (3, '已合格'), (4, '库存中')], default=0, verbose_name='进行状态'), + ), + ] diff --git a/hb_server/apps/wpm/models.py b/hb_server/apps/wpm/models.py index 0d8d4b8..83dfcf1 100644 --- a/hb_server/apps/wpm/models.py +++ b/hb_server/apps/wpm/models.py @@ -2,6 +2,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.pm.models import ProductionPlan, SubProductionPlan from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File from utils.model import SoftModel, BaseModel @@ -24,10 +25,12 @@ class WProduct(CommonAModel): WPR_ACT_STATE_DOING = 1 WPR_ACT_STATE_TOTEST = 2 WPR_ACT_STATE_OK = 3 + WPR_ACT_STATE_INM = 4 act_state_choices=( (WPR_ACT_STATE_DOING, '生产中'), (WPR_ACT_STATE_TOTEST, '待检测'), - (WPR_ACT_STATE_OK, '已合格') + (WPR_ACT_STATE_OK, '已合格'), + (WPR_ACT_STATE_INM, '库存中'), ) number = models.CharField('物品编号', unique=True, null=True, blank=True, max_length=50) m_state = models.ForeignKey(Material, verbose_name='所属物料状态', on_delete=models.CASCADE) @@ -40,6 +43,7 @@ class WProduct(CommonAModel): remark = models.CharField('备注', max_length=200, null=True, blank=True) subproduction_plan = models.ForeignKey(SubProductionPlan, verbose_name='当前子生产计划', on_delete=models.CASCADE) 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) class Operation(CommonAModel): diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 88fa039..eebdae6 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -5,7 +5,7 @@ from rest_framework.utils import serializer_helpers from rest_framework.utils.field_mapping import get_relation_kwargs from rest_framework.views import APIView from rest_framework.viewsets import GenericViewSet, ModelViewSet -from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct +from apps.inm.models import FIFO, FIFOItem, FIFOItemProduct, IProduct from apps.inm.signals import update_inm from apps.mtm.models import Material, RecordForm, Step, SubprodctionMaterial from apps.mtm.serializers import RecordFormDetailSerializer @@ -77,9 +77,21 @@ class WPlanViewSet(ListModelMixin, GenericViewSet): ip['material'] = material ips.append(FIFOItemProduct(**ip)) FIFOItemProduct.objects.bulk_create(ips) - # 更新库存隐藏半成品 + # 创建IProduct + ips2 = [] + for i in wproducts: + ip = {} + ip['warehouse'] = vdata['warehouse'] + ip['batch'] = batch + ip['wproduct'] = i + ip['number'] = i.number + ip['material'] = material + ips2.append(IProduct(**ip)) + IProduct.objects.bulk_create(ips2) + # 更新库存并修改半成品进行状态 update_inm(fifo) - wproducts.update(is_hidden=True) + wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=vdata['warehouse']) + return Response() @@ -143,7 +155,7 @@ class WProductViewSet(ListModelMixin, GenericViewSet): 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 True + 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) From fe5108f616c6611740caf1aba82c75a6ee4987ae Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 16 Nov 2021 09:10:51 +0800 Subject: [PATCH 09/12] =?UTF-8?q?=E9=A2=86=E6=96=99bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/serializers.py | 9 +++-- hb_server/apps/wpm/views.py | 58 ++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 7f3555c..593eb8e 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -17,7 +17,7 @@ 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="领料数量") + pick_count = serializers.IntegerField(label="领料数量", required=False) class PickSerializer(serializers.Serializer): subproduction_plan=serializers.PrimaryKeyRelatedField(queryset=SubProductionPlan.objects.all(), label="子计划ID") @@ -43,7 +43,7 @@ class PickSerializer(serializers.Serializer): for i in picks: # 更新出库详情 i['fifo'] = fifo - i['count'] = i.pop('pick_count') + i['count'] = i.pop('pick_count', 0) i['is_testok'] = True # 默认检测合格 i['subproduction_plan'] = sp FIFOItem.objects.create(**i) @@ -195,7 +195,10 @@ class WproductPutInSerializer(serializers.Serializer): class WplanPutInSerializer(serializers.Serializer): warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID") remark = serializers.CharField(label="入库备注", required =False) - + +class WproductPutInSerializer(serializers.Serializer): + warehouse = serializers.PrimaryKeyRelatedField(queryset=WareHouse.objects.all(), label="仓库ID") + remark = serializers.CharField(label="入库备注", required =False) \ No newline at end of file diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index eebdae6..6f6ce82 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 WMaterial, WProduct, Operation, OperationMaterial, OperationRecord, OperationRecordItem -from apps.wpm.serializers import OperationDetailSerializer, OperationListSerializer, PickSerializer, OperationInitSerializer, OperationSubmitSerializer, WMaterialListSerializer, WProductListSerializer, WplanPutInSerializer, WpmTestRecordCreateSerializer +from apps.wpm.serializers import OperationDetailSerializer, OperationListSerializer, 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 @@ -116,6 +116,62 @@ class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet): serializer.save() return Response() + @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WproductPutInSerializer) + @transaction.atomic + def putin(self, request, pk=None): + """ + 半成品入库 + """ + serializer= WproductPutInSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + vdata = serializer.data + subplan = self.get_object() + material = subplan.main_product + batch = subplan.production_plan.number + wproducts = WProduct.objects.filter(subproduction_plan=subplan, + act_state=WProduct.WPR_ACT_STATE_OK, m_state=material, is_deleted=False) + if wproducts.exists(): + # 创建入库记录 + 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) + # 创建入库明细 + fifoitem = FIFOItem() + fifoitem.is_tested = True + fifoitem.is_testok = True + fifoitem.warehouse = vdata['warehouse'] + fifoitem.material = material + fifoitem.count = wproducts.count() + fifoitem.batch = batch + fifoitem.fifo = fifo + fifoitem.subproduction_plan = subplan + fifoitem.save() + # 创建入库明细半成品 + ips = [] + for i in wproducts: + ip = {} + ip['fifoitem'] = fifoitem + ip['wproduct'] = i + ip['number'] = i.number + ip['material'] = material + ips.append(FIFOItemProduct(**ip)) + FIFOItemProduct.objects.bulk_create(ips) + # 创建IProduct + ips2 = [] + for i in wproducts: + ip = {} + ip['warehouse'] = vdata['warehouse'] + ip['batch'] = batch + ip['wproduct'] = i + ip['number'] = i.number + ip['material'] = material + ips2.append(IProduct(**ip)) + IProduct.objects.bulk_create(ips2) + # 更新库存并修改半成品进行状态 + update_inm(fifo) + wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=vdata['warehouse']) + + return Response() class WProductViewSet(ListModelMixin, GenericViewSet): """ From f1102656c7836d8d4f1b0995750d1c92b064e775 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 16 Nov 2021 09:17:13 +0800 Subject: [PATCH 10/12] =?UTF-8?q?=E9=A2=86=E6=96=99bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/serializers.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 593eb8e..2d50877 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -42,11 +42,12 @@ class PickSerializer(serializers.Serializer): fifo = FIFO.objects.create(type=FIFO.FIFO_TYPE_DO_OUT, inout_date=timezone.now(), create_by=self.context['request'].user) for i in picks: # 更新出库详情 - i['fifo'] = fifo i['count'] = i.pop('pick_count', 0) - i['is_testok'] = True # 默认检测合格 - i['subproduction_plan'] = sp - FIFOItem.objects.create(**i) + if i['count']>0: + i['fifo'] = fifo + i['is_testok'] = True # 默认检测合格 + i['subproduction_plan'] = sp + FIFOItem.objects.create(**i) # 更新车间物料 wm, _ = WMaterial.objects.get_or_create(material=i['material'], batch=i['batch'], \ subproduction_plan=sp,defaults={ From 73a475c4ea016486ce3f2321faed973f63f1beb3 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 16 Nov 2021 09:51:32 +0800 Subject: [PATCH 11/12] =?UTF-8?q?=E9=A2=86=E6=96=99bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hb_server/apps/wpm/serializers.py | 28 ++++----- hb_server/apps/wpm/views.py | 96 +++++++++++++++---------------- 2 files changed, 62 insertions(+), 62 deletions(-) diff --git a/hb_server/apps/wpm/serializers.py b/hb_server/apps/wpm/serializers.py index 2d50877..b9c4474 100644 --- a/hb_server/apps/wpm/serializers.py +++ b/hb_server/apps/wpm/serializers.py @@ -48,20 +48,20 @@ class PickSerializer(serializers.Serializer): i['is_testok'] = True # 默认检测合格 i['subproduction_plan'] = sp FIFOItem.objects.create(**i) - # 更新车间物料 - wm, _ = WMaterial.objects.get_or_create(material=i['material'], batch=i['batch'], \ - subproduction_plan=sp,defaults={ - 'material':i['material'], - 'batch':i['batch'], - 'subproduction_plan':sp, - 'count':0 - }) - wm.count = wm.count + i['count'] - wm.save() - # 更新子计划物料情况 - spp = SubProductionProgress.objects.get(material=i['material'], subproduction_plan=sp, type=1) - spp.count_pick = spp.count_pick + i['count'] - spp.save() + # 更新车间物料 + wm, _ = WMaterial.objects.get_or_create(material=i['material'], batch=i['batch'], \ + subproduction_plan=sp,defaults={ + 'material':i['material'], + 'batch':i['batch'], + 'subproduction_plan':sp, + 'count':0 + }) + wm.count = wm.count + i['count'] + wm.save() + # 更新子计划物料情况 + spp = SubProductionProgress.objects.get(material=i['material'], subproduction_plan=sp, type=1) + spp.count_pick = spp.count_pick + i['count'] + spp.save() sp.is_picked=True sp.state = 3 #生产中 sp.state_date_real = timezone.now() #实际开工日期 diff --git a/hb_server/apps/wpm/views.py b/hb_server/apps/wpm/views.py index 6f6ce82..b97cc6c 100644 --- a/hb_server/apps/wpm/views.py +++ b/hb_server/apps/wpm/views.py @@ -34,8 +34,8 @@ class WPlanViewSet(ListModelMixin, GenericViewSet): search_fields = [] serializer_class = SubProductionPlanListSerializer filterset_fields = ['production_plan', 'process', 'state', 'main_product', 'workshop'] - ordering_fields = ['process__number'] - ordering = ['process__number'] + ordering_fields = [] + ordering = ['-id'] @action(methods=['post'], detail=True, perms_map={'post':'*'}, serializer_class=WplanPutInSerializer) @transaction.atomic @@ -125,52 +125,52 @@ class WMaterialViewSet(CreateUpdateModelAMixin, ListModelMixin, GenericViewSet): serializer= WproductPutInSerializer(data=request.data) serializer.is_valid(raise_exception=True) vdata = serializer.data - subplan = self.get_object() - material = subplan.main_product - batch = subplan.production_plan.number - wproducts = WProduct.objects.filter(subproduction_plan=subplan, - act_state=WProduct.WPR_ACT_STATE_OK, m_state=material, is_deleted=False) - if wproducts.exists(): - # 创建入库记录 - 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) - # 创建入库明细 - fifoitem = FIFOItem() - fifoitem.is_tested = True - fifoitem.is_testok = True - fifoitem.warehouse = vdata['warehouse'] - fifoitem.material = material - fifoitem.count = wproducts.count() - fifoitem.batch = batch - fifoitem.fifo = fifo - fifoitem.subproduction_plan = subplan - fifoitem.save() - # 创建入库明细半成品 - ips = [] - for i in wproducts: - ip = {} - ip['fifoitem'] = fifoitem - ip['wproduct'] = i - ip['number'] = i.number - ip['material'] = material - ips.append(FIFOItemProduct(**ip)) - FIFOItemProduct.objects.bulk_create(ips) - # 创建IProduct - ips2 = [] - for i in wproducts: - ip = {} - ip['warehouse'] = vdata['warehouse'] - ip['batch'] = batch - ip['wproduct'] = i - ip['number'] = i.number - ip['material'] = material - ips2.append(IProduct(**ip)) - IProduct.objects.bulk_create(ips2) - # 更新库存并修改半成品进行状态 - update_inm(fifo) - wproducts.update(act_sate=WProduct.WPR_ACT_STATE_INM, warehouse=vdata['warehouse']) - + wproduct = self.get_object() + if wproduct.act_state != WProduct.WPR_ACT_STATE_OK: + raise exceptions.APIException('半成品不可入库') + material = wproduct.m_state + batch = wproduct.production_plan.number + # 创建入库记录 + 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) + # 创建入库明细 + fifoitem = FIFOItem() + fifoitem.is_tested = True + fifoitem.is_testok = True + fifoitem.warehouse = vdata['warehouse'] + fifoitem.material = material + fifoitem.count = 1 # 单个半成品入库 + fifoitem.batch = batch + fifoitem.fifo = fifo + fifoitem.subproduction_plan = wproduct.subproduction_plan + fifoitem.save() + # 创建入库明细半成品 + ips = [] + for i in [wproduct]: + ip = {} + ip['fifoitem'] = fifoitem + ip['wproduct'] = i + ip['number'] = i.number + ip['material'] = material + ips.append(FIFOItemProduct(**ip)) + FIFOItemProduct.objects.bulk_create(ips) + # 创建IProduct + ips2 = [] + for i in [wproduct]: + ip = {} + ip['warehouse'] = vdata['warehouse'] + ip['batch'] = batch + ip['wproduct'] = i + ip['number'] = i.number + ip['material'] = material + ips2.append(IProduct(**ip)) + IProduct.objects.bulk_create(ips2) + # 更新库存并修改半成品进行状态 + update_inm(fifo) + wproduct.act_state=WProduct.WPR_ACT_STATE_INM + wproduct.warehouse=vdata['warehouse'] + wproduct.save() return Response() class WProductViewSet(ListModelMixin, GenericViewSet): From ec64f67041772df9a5cbca37bdf02229bb27f179 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Tue, 16 Nov 2021 10:26:03 +0800 Subject: [PATCH 12/12] =?UTF-8?q?=E5=88=A4=E5=AE=9A=E8=A1=A8=E8=BE=BE?= =?UTF-8?q?=E5=BC=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...32_alter_recordformfield_rule_expression.py | 18 ++++++++++++++++++ hb_server/apps/mtm/models.py | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 hb_server/apps/mtm/migrations/0032_alter_recordformfield_rule_expression.py diff --git a/hb_server/apps/mtm/migrations/0032_alter_recordformfield_rule_expression.py b/hb_server/apps/mtm/migrations/0032_alter_recordformfield_rule_expression.py new file mode 100644 index 0000000..1f55b4a --- /dev/null +++ b/hb_server/apps/mtm/migrations/0032_alter_recordformfield_rule_expression.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.6 on 2021-11-16 02:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0031_auto_20211116_0841'), + ] + + operations = [ + migrations.AlterField( + model_name='recordformfield', + name='rule_expression', + field=models.TextField(default='', verbose_name='判定表达式'), + ), + ] diff --git a/hb_server/apps/mtm/models.py b/hb_server/apps/mtm/models.py index ef0426c..c3fb34f 100644 --- a/hb_server/apps/mtm/models.py +++ b/hb_server/apps/mtm/models.py @@ -154,7 +154,7 @@ class RecordFormField(CommonAModel): high_rule = models.IntegerField('上限规则', choices=high_rule_choices, null=True, blank=True) low_limit = models.FloatField('下限值', null=True, blank=True) low_rule = models.IntegerField('下限规则', choices=low_rule_choices, null=True, blank=True) - rule_expression = models.JSONField('判定表达式', default=list, help_text='判定表达式, 格式为[{"expression":"{value} > 3 and {value}<10"}] 其中{}用于填充的字段key,运算时会换算成实际的值,符合条件返回true,表达式只支持简单的运算或datetime/time运算.以首次匹配成功的条件为准,所以多个条件不要有冲突' ) + rule_expression = models.TextField('判定表达式', default='') class Meta: verbose_name = '记录表格字段'