From ba41228d695cd3289b896d262ebc634372f7f2fe Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 2 Jan 2025 14:01:09 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=94=9F=E4=BA=A7=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=8D=95=E4=B8=AA=E7=89=A9=E6=96=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/inm/serializers.py | 21 ++++++------ .../wpm/migrations/0078_auto_20250102_0958.py | 2 -- apps/wpm/models.py | 19 +++++++---- apps/wpm/serializers.py | 9 +++++- apps/wpm/services.py | 32 ++++++++++++++----- apps/wpmw/models.py | 10 ++++-- 6 files changed, 63 insertions(+), 30 deletions(-) diff --git a/apps/inm/serializers.py b/apps/inm/serializers.py index 4672b17b..9835a7de 100644 --- a/apps/inm/serializers.py +++ b/apps/inm/serializers.py @@ -98,7 +98,6 @@ class MIOItemwCreateSerializer(CustomModelSerializer): fields = ["number", "note"] class MIOItemwSerializer(CustomModelSerializer): - test_user_name = serializers.CharField(source='test_user.name', read_only=True) class Meta: model = MIOItemw fields = "__all__" @@ -119,12 +118,12 @@ class MIOItemwTestSerializer(CustomModelSerializer): class MIOItemCreateSerializer(CustomModelSerializer): assemb = MIOItemACreateSerializer( label='组合件信息', many=True, write_only=True, required=False) - wprs = MIOItemwCreateSerializer(many=True, required=False) + mioitemw_ = MIOItemwCreateSerializer(many=True, required=False) class Meta: model = MIOItem fields = ['mio', 'warehouse', 'material', - 'batch', 'count', 'assemb', 'is_testok', 'wprs'] + 'batch', 'count', 'assemb', 'is_testok', 'mioitemw_'] def create(self, validated_data): mio = validated_data['mio'] @@ -143,7 +142,7 @@ class MIOItemCreateSerializer(CustomModelSerializer): count = validated_data["count"] batch = validated_data["batch"] assemb = validated_data.pop('assemb', []) - wprs = validated_data.pop('wprs', []) + mioitemw_ = validated_data.pop('mioitemw_', []) instance = super().create(validated_data) assemb_dict = {} for i in assemb: @@ -158,13 +157,13 @@ class MIOItemCreateSerializer(CustomModelSerializer): else: raise ParseError('缺少组合件') if material.tracking == Material.MA_TRACKING_SINGLE: - if count == 1 and len(wprs) == 0: + if count == 1 and len(mioitemw_) == 0: MIOItemw.objects.create(mioitem=instance, number=batch) - elif count == 1 and len(wprs) >= 1: - MIOItemw.objects.create(mioitem=instance, number=wprs[0]['number'], note=wprs[0]['note']) - elif count > 1 and len(wprs) == count: - for w in wprs: - MIOItemw.objects.create(mioitem=instance, number=w['number'], note=w['note']) + elif count == 1 and len(mioitemw_) >= 1: + MIOItemw.objects.create(mioitem=instance, number=mioitemw_[0]['number'], note=mioitemw_[0]['note']) + elif count > 1 and len(mioitemw_) == count: + for item in mioitemw_: + MIOItemw.objects.create(mioitem=instance, number=item['number'], note=item['note']) else: raise ParseError('单个明细信息不匹配') return instance @@ -191,7 +190,7 @@ class MIOItemSerializer(CustomModelSerializer): source='material', read_only=True) inout_date = serializers.DateField(source='mio.inout_date', read_only=True) test_user_name = serializers.CharField(source='test_user.name', read_only=True) - wprs = MIOItemwSerializer(source='w_mioitem', read_only=True, many=True) + mioitemw_ = MIOItemwSerializer(source='w_mioitem', read_only=True, many=True) class Meta: model = MIOItem diff --git a/apps/wpm/migrations/0078_auto_20250102_0958.py b/apps/wpm/migrations/0078_auto_20250102_0958.py index 2a611df5..caa1d3d3 100644 --- a/apps/wpm/migrations/0078_auto_20250102_0958.py +++ b/apps/wpm/migrations/0078_auto_20250102_0958.py @@ -26,8 +26,6 @@ class Migration(migrations.Migration): ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), ('number', models.TextField(verbose_name='单个编号')), - ('test_json', models.JSONField(blank=True, default=dict, verbose_name='检验情况')), - ('defect_json', models.JSONField(blank=True, default=list, verbose_name='缺陷情况')), ('note', models.TextField(blank=True, null=True, verbose_name='备注')), ('mlogb', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wpm.mlogb', verbose_name='生产记录')), ], diff --git a/apps/wpm/models.py b/apps/wpm/models.py index 2c34b955..b57c471d 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -12,11 +12,6 @@ from django.utils.translation import gettext_lazy as _ # Create your models here. -# class Good(BaseModel): -# """ -# 产品状态 -# """ -# pass class BatchSt(BaseModel): """ 批次统计表 @@ -102,6 +97,7 @@ class WmStateOption(models.IntegerChoices): REPAIR = 30, _("返修") TEST = 40, _("检验") SCRAP = 50, _("报废") + class WMaterial(CommonBDModel): """ belong_dept是所在车间 @@ -119,10 +115,10 @@ class WMaterial(CommonBDModel): batch = models.TextField('批次号') count = models.PositiveIntegerField('当前数量', default=0) count_eweight = models.FloatField('单数重量', default=0) + defect = models.ForeignKey('qm.defect', verbose_name='缺陷', on_delete=models.SET_NULL, null=True, blank=True) notok_sign = models.CharField('不合格标记', max_length=10, null=True, blank=True) material_origin = models.ForeignKey(Material, verbose_name='原始物料', on_delete=models.SET_NULL, null=True, blank=True, related_name='wm_mo') count_xtest = models.PositiveIntegerField('已检数量', null=True, blank=True) - batch_ofrom = models.TextField('原料批次号', null=True, blank=True) material_ofrom = models.ForeignKey(Material, verbose_name='原料物料', on_delete=models.SET_NULL, null=True, blank=True, related_name='wm_mofrom') @@ -339,6 +335,12 @@ class Mlogb(BaseModel): count_n_qt = models.PositiveIntegerField('其他', default=0) count_notok_json = models.JSONField('不合格情况', default=list, blank=True) +class Mlogbw(BaseModel): + number = models.TextField('单个编号') + mlogb = models.ForeignKey(Mlogb, verbose_name='生产记录', on_delete=models.CASCADE) + note = models.TextField('备注', null=True, blank=True) + + class Handover(CommonADModel): """ 交接记录 @@ -388,6 +390,11 @@ class Handoverb(BaseModel): null=True, blank=True, related_name='handoverb_wm') count = models.PositiveIntegerField('送料数', default=0) +class Handoverbw(BaseModel): + handoverb = models.ForeignKey(Handoverb, verbose_name='关联交接记录', on_delete=models.CASCADE) + number = models.TextField('单个编号') + note = models.TextField('备注', null=True, blank=True) + class AttLog(CommonADModel): """ 到岗记录 diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index d4e6c15b..1ec3f7e5 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -5,7 +5,8 @@ from rest_framework.exceptions import ValidationError, ParseError from datetime import datetime from .models import (SfLog, StLog, SfLogExp, WMaterial, Mlog, - Handover, Handoverb, Mlogb, AttLog, OtherLog, Fmlog, BatchSt) + Handover, Handoverb, Mlogb, AttLog, + OtherLog, Fmlog, BatchSt, Mlogbw) from apps.system.models import Dept, User from apps.system.serializers import UserSimpleSerializer from apps.pm.models import Mtask, Mtaskb @@ -566,6 +567,12 @@ class MlogbInUpdateSerializer(CustomModelSerializer): model = Mlogb fields = ['id', 'count_use', 'count_break', 'count_pn_jgqbl', 'note'] +class MlogbwCreateUpdateSerializer(CustomModelSerializer): + class Meta: + model = Mlogbw + fields = ["number", "note"] + + class MlogbOutUpdateSerializer(CustomModelSerializer): class Meta: model = Mlogb diff --git a/apps/wpm/services.py b/apps/wpm/services.py index e2facb3a..a2da6f0a 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -11,13 +11,15 @@ from apps.system.models import User from apps.pm.models import Mtask from apps.mtm.models import Mgroup, Shift, Material, Route, RoutePack, Team, Srule -from .models import SfLog, WMaterial, Mlog, Mlogb, Handover, Handoverb +from .models import SfLog, WMaterial, Mlog, Mlogb, Mlogbw, Handover, Handoverb from apps.mtm.services import cal_material_count from apps.wf.models import Ticket from apps.utils.thread import MyThread import logging from apps.wpm.services_2 import get_alldata_with_batch_and_store from datetime import timedelta +from apps.wpmw.models import Wpr, WprDefect + myLogger = logging.getLogger('log') def generate_new_batch(old_batch: str, mlog: Mlog): @@ -151,8 +153,8 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): mgroup = mlog.mgroup belong_dept = mgroup.belong_dept - material_out = mlog.material_out - material_in = mlog.material_in + material_out: Material = mlog.material_out + material_in: Material = mlog.material_in supplier = mlog.supplier # 外协 m_ins_list = [] if material_in: # 需要进行车间库存管理 @@ -161,17 +163,17 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): m_ins = Mlogb.objects.filter(mlog=mlog, material_in__isnull=False) if m_ins.exists(): for mi in m_ins.all(): - m_ins_list.append((mi.material_in, mi.batch, mi.count_use, mi.wm_in)) + m_ins_list.append((mi.material_in, mi.batch, mi.count_use, mi)) if mi.count_pn_jgqbl > 0: m_ins_bl_list.append((mi.material_in, mi.batch, mi.count_pn_jgqbl, mi)) else: - m_ins_list = [(material_in, mlog.batch, mlog.count_use, mlog.wm_in)] + m_ins_list = [(material_in, mlog.batch, mlog.count_use, mlog)] for mi in m_ins_list: - mi_ma, mi_batch, mi_count, mi_wm_in = mi + mi_ma, mi_batch, mi_count, mlog_or_b = mi # 需要判断领用数是否合理 # 优先使用工段库存 - if mi_wm_in: - wm_qs = WMaterial.objects.filter(id=mi_wm_in.id) + if isinstance(mlog_or_b, Mlogb) and mlog_or_b.wm_in: + wm_qs = WMaterial.objects.filter(id=mlog_or_b.wm_in.id) else: wm_qs = WMaterial.objects.filter(batch=mi_batch, material=mi_ma, mgroup=mgroup, state=WMaterial.WM_OK) if not wm_qs.exists(): @@ -194,6 +196,12 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): wm.count = wm.count - mi_count wm.update_by = user wm.save() + if material_in.tracking == Material.MA_TRACKING_SINGLE: + mlogbws = Mlogbw.objects.filter(mlogb=mlog_or_b) + if mlogbws.count() != mi.count: + raise ParseError("日志与明细数量不一致,操作失败") + Wpr.clear([item.number for item in mlogbws]) + # 针对加工前不良的暂时额外处理 for item in m_ins_bl_list: material, batch, count_pn_jgqbl, mi_ = item @@ -207,6 +215,8 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): wm.material_ofrom = mi_.material_ofrom wm.update_by = user wm.save() + if material_in.tracking == Material.MA_TRACKING_SINGLE: + raise ParseError("加工前不良的物料暂不支持单件") if material_out: # 需要入车间库存 @@ -255,6 +265,12 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): wm.batch_ofrom = mlog_or_b.batch_ofrom wm.material_ofrom = mlog_or_b.material_ofrom wm.save() + if material_out.tracking == Material.MA_TRACKING_SINGLE: + mlgbws = Mlogbw.objects.filter(mlogb=mlog_or_b) + if mlgbws.count() != mo_count: + raise ParseError("日志与明细数量不一致,操作失败") + for item in mlgbws: + Wpr.change_or_new(item.number, material_out, mb=None, wm=wm) mlog.submit_time = now mlog.submit_user = user diff --git a/apps/wpmw/models.py b/apps/wpmw/models.py index 64bb9d05..2f7c8139 100644 --- a/apps/wpmw/models.py +++ b/apps/wpmw/models.py @@ -20,17 +20,23 @@ class Wpr(BaseModel): @classmethod - def change_or_new(cls, number, material, mb=None, wm=None, state=10): + def change_or_new(cls, number, material, can_new=False, mb=None, wm=None, state=10): ins = cls.objects.filter(number=number).first() if ins: ins.material = material - else: + elif can_new: ins = cls(number=number, material=material) + else: + raise ParseError("物料不存在") ins.state = state ins.mb = mb ins.wm = wm ins.save() + @classmethod + def clear(cls, number_list): + cls.objects.filter(number__in=number_list).update(mb=None, wm=None) + class WprDefect(BaseModel): wpr = models.ForeignKey(Wpr, verbose_name="关联产物", on_delete=models.CASCADE)