From c058fe93385375b80c2a9f8f8cee540de1a6131c Mon Sep 17 00:00:00 2001 From: caoqianming Date: Wed, 17 Jul 2024 16:58:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E4=B8=8D=E5=90=88?= =?UTF-8?q?=E6=A0=BC=E5=93=81=E5=A4=84=E7=90=86/=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=B8=8D=E5=90=88=E6=A0=BC=E5=93=81=E5=AD=98=E5=82=A8=E5=AD=97?= =?UTF-8?q?=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wpm/migrations/0055_auto_20240717_1653.py | 44 ++++++++++++ apps/wpm/models.py | 11 +-- apps/wpm/serializers.py | 8 ++- apps/wpm/services.py | 71 +++++++++---------- apps/wpm/views.py | 4 +- 5 files changed, 93 insertions(+), 45 deletions(-) create mode 100644 apps/wpm/migrations/0055_auto_20240717_1653.py diff --git a/apps/wpm/migrations/0055_auto_20240717_1653.py b/apps/wpm/migrations/0055_auto_20240717_1653.py new file mode 100644 index 00000000..c3bd9334 --- /dev/null +++ b/apps/wpm/migrations/0055_auto_20240717_1653.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.12 on 2024-07-17 08:53 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('mtm', '0034_route_batch_bind'), + ('wpm', '0054_mlog_fill_way'), + ] + + operations = [ + migrations.AddField( + model_name='mlog', + name='wm_in', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mlog_wm_in', to='wpm.wmaterial', verbose_name='投入物料所在库存'), + ), + migrations.AddField( + model_name='mlogb', + name='wm_in', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='wpm.wmaterial', verbose_name='投入物料所在库存'), + ), + migrations.AddField( + model_name='wmaterial', + name='material_origin', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wm_mo', to='mtm.material', verbose_name='原始物料'), + ), + migrations.AddField( + model_name='wmaterial', + name='notok_sign', + field=models.CharField(blank=True, max_length=10, null=True, verbose_name='不合格标记'), + ), + migrations.AlterField( + model_name='wmaterial', + name='material', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='wm_m', to='mtm.material', verbose_name='物料'), + ), + migrations.AlterUniqueTogether( + name='wmaterial', + unique_together=set(), + ), + ] diff --git a/apps/wpm/models.py b/apps/wpm/models.py index 5508da03..2678f434 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -89,14 +89,14 @@ class WMaterial(CommonBDModel): belong_dept是所在车间 """ material = models.ForeignKey( - Material, verbose_name='物料', on_delete=models.CASCADE) + Material, verbose_name='物料', on_delete=models.CASCADE, related_name='wm_m') mgroup = models.ForeignKey(Mgroup, verbose_name='所在工段', on_delete=models.CASCADE, null=True, blank=True) batch = models.CharField('批次号', max_length=50) count = models.PositiveIntegerField('当前数量', default=0) count_eweight = models.FloatField('单数重量', default=0) + 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') - class Meta: - unique_together = ('material', 'batch', 'belong_dept', 'mgroup') class Mlog(CommonADModel): """ @@ -115,6 +115,7 @@ class Mlog(CommonADModel): Mtask, verbose_name='关联任务', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_mtask') mgroup = models.ForeignKey( Mgroup, verbose_name='工段', on_delete=models.CASCADE, null=True, blank=True) + wm_in = models.ForeignKey(WMaterial, verbose_name='投入物料所在库存', on_delete=models.SET_NULL, null=True, blank=True, related_name='mlog_wm_in') material_in = models.ForeignKey( Material, verbose_name='消耗物', on_delete=models.CASCADE, null=True, blank=True, related_name='mlog_material_in') material_out = models.ForeignKey( @@ -133,10 +134,10 @@ class Mlog(CommonADModel): count_use = models.PositiveIntegerField('领用数', default=0) count_real = models.PositiveIntegerField('实际生产数', default=0) count_real_eweight = models.FloatField('单数重量', default=0) + count_break = models.PositiveIntegerField('加工碎料数', default=0) count_ok = models.PositiveIntegerField('合格数', default=0) count_notok = models.PositiveIntegerField('不合格数', default=0) - count_break = models.PositiveIntegerField('加工碎料数', default=0) count_break_t = models.PositiveIntegerField('检验碎料数', default=0) count_n_zw = models.PositiveIntegerField('炸纹', default=0) @@ -210,12 +211,14 @@ class Mlogb(BaseModel): batch = models.CharField('批次号', max_length=50, null=True, blank=True) mtask = models.ForeignKey(Mtask, verbose_name='关联任务', on_delete=models.CASCADE, related_name='mlogb_mtask', null=True, blank=True) + wm_in = models.ForeignKey(WMaterial, verbose_name='投入物料所在库存', on_delete=models.SET_NULL, null=True, blank=True) material_in = models.ForeignKey( Material, verbose_name='投入物料', on_delete=models.CASCADE, related_name='mlogb_material_in', null=True, blank=True) material_out = models.ForeignKey( Material, verbose_name='产物', on_delete=models.CASCADE, related_name='mlogb_material_out', null=True, blank=True) count_use = models.PositiveIntegerField('领用数量', default=0) count_break = models.PositiveIntegerField('加工破碎数', default=0) + count_break_t = models.PositiveIntegerField('检验碎料数', default=0) count_real = models.PositiveIntegerField('实际生产数', default=0) count_ok = models.PositiveIntegerField('合格数量', default=0) diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index 484afa4d..ef1fb11d 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -361,19 +361,21 @@ class MlogChangeSerializer(CustomModelSerializer): class MlogbInSerializer(CustomModelSerializer): class Meta: model = Mlogb - fields = ['id', 'mlog', 'mtask', 'batch', 'count_use'] - extra_kwargs = {'count_use': {'required': True}, 'mtask': {'required': True}, 'batch': {'required': True, 'allow_blank': False}} + fields = ['id', 'mlog', 'mtask', 'wm_in', 'count_use'] + extra_kwargs = {'count_use': {'required': True}, 'mtask': {'required': True}, 'wm_in': {'required': True}} def validate(self, attrs): mlog: Mlog = attrs['mlog'] mtask: Mtask = attrs['mtask'] + wm_in: WMaterial = attrs['wm_in'] if mlog.route != mtask.route: raise ValidationError('工序不匹配') route = mlog.route + attrs['material_in'] = wm_in.material_in + attrs['batch'] = wm_in.batch if route.batch_bind: if not Mlogb.objects.filter(mtask__utask=mtask.utask, mlog__submit_time__isnull=False, material_out__isnull=False, batch=attrs['batch']).exists(): raise ValidationError('批次号不匹配') - attrs['material_in'] = mlog.material_in return attrs def create(self, validated_data): diff --git a/apps/wpm/services.py b/apps/wpm/services.py index 332deff7..cbb4eb00 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -146,9 +146,9 @@ def do_in(mio: MIO): for al in action_list: xmaterial, xbatch, xcount = al # 优先从车间库存里拿 - wm_qs = WMaterial.objects.filter(batch=xbatch, material=xmaterial, belong_dept=belong_dept, mgroup=None) + wm_qs = WMaterial.objects.filter(batch=xbatch, material=xmaterial, belong_dept=belong_dept, mgroup=None, notok_sign=None) if not wm_qs.exists(): - wm_qs = WMaterial.objects.filter(batch=xbatch, material=xmaterial, belong_dept=belong_dept, mgroup__isnull=False) + wm_qs = WMaterial.objects.filter(batch=xbatch, material=xmaterial, belong_dept=belong_dept, mgroup__isnull=False, notok_sign=None) count_x = wm_qs.count() if count_x == 1: @@ -161,12 +161,10 @@ def do_in(mio: MIO): f'{str(xmaterial)}-{xbatch}-存在多个相同批次!') new_count = wm.count - xcount - if new_count > 0: + if new_count >= 0: wm.count = new_count wm.update_by = do_user wm.save() - elif new_count == 0: - wm.delete() else: raise ParseError(f'{str(xmaterial)}-{xbatch}车间物料不足') @@ -189,16 +187,19 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): if material_in: # 需要进行车间库存管理 m_ins = Mlogb.objects.filter(mlog=mlog, material_in__isnull=False) if m_ins.exists(): - m_ins_list = [(mi.material_in, mi.batch, mi.count_use) for mi in m_ins.all()] + m_ins_list = [(mi.material_in, mi.batch, mi.count_use, mi.wm_in) for mi in m_ins.all()] else: - m_ins_list = [(material_in, mlog.batch, mlog.count_use)] + m_ins_list = [(material_in, mlog.batch, mlog.count_use, mlog.wm_in)] for mi in m_ins_list: - mi_ma, mi_batch, mi_count = mi + mi_ma, mi_batch, mi_count, mi_wm_in = mi # 需要判断领用数是否合理 # 优先使用工段库存 - wm_qs = WMaterial.objects.filter(batch=mi_batch, material=mi_ma, mgroup=mgroup) - if not wm_qs.exists(): - wm_qs = WMaterial.objects.filter(batch=mi_batch, material=mi_ma, belong_dept=belong_dept, mgroup=None) + if mi_wm_in: + wm_qs = WMaterial.objects.filter(id=mi_wm_in.id) + else: + wm_qs = WMaterial.objects.filter(batch=mi_batch, material=mi_ma, mgroup=mgroup, notok_sign=None) + if not wm_qs.exists(): + wm_qs = WMaterial.objects.filter(batch=mi_batch, material=mi_ma, belong_dept=belong_dept, mgroup=None, notok_sign=None) count_x = wm_qs.count() if count_x == 1: @@ -215,11 +216,8 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): f'{str(mi_ma)}-{mi_batch}-该批次车间库存不足!') else: wm.count = wm.count - mi_count - if wm.count == 0: - wm.delete() - else: - wm.update_by = user - wm.save() + wm.update_by = user + wm.save() if material_out: # 需要入车间库存 into_wm_mgroup = material_out.process.into_wm_mgroup if material_out.process else False m_outs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False) @@ -230,7 +228,7 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): for mo in m_outs_list: mo_ma, mo_batch, mo_count, mo_count_eweight = mo - lookup = {'batch': mo_batch, 'material': mo_ma, 'mgroup': None} + lookup = {'batch': mo_batch, 'material': mo_ma, 'mgroup': None, 'notok_sign': None} if into_wm_mgroup: lookup['mgroup'] = mgroup else: @@ -263,21 +261,28 @@ def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): into_wm_mgroup = material_in.process.into_wm_mgroup if material_in.process else False m_ins = Mlogb.objects.filter(mlog=mlog, material_in__isnull=False) if m_ins.exists(): - m_ins_list = [(mi.material_in, mi.batch, mi.count_use) for mi in m_ins.all()] + m_ins_list = [(mi.material_in, mi.batch, mi.count_use, mi.wm_in) for mi in m_ins.all()] else: - m_ins_list = [(material_in, mlog.batch, mlog.count_use)] + m_ins_list = [(material_in, mlog.batch, mlog.count_use, mlog.wm_in)] for mi in m_ins_list: - mi_ma, mi_batch, mi_count = mi - lookup = {'batch': mi_batch, 'material': mi_ma, 'mgroup': None} - if into_wm_mgroup: - lookup['mgroup'] = mgroup + mi_ma, mi_batch, mi_count, mi_wm_in = mi + if mi_wm_in: + mi_wm_in.count = mi_wm_in.count + mi_count + mi_wm_in.update_by = user + mi_wm_in.save() else: - lookup['belong_dept'] = belong_dept + lookup = {'batch': mi_batch, 'material': mi_ma, 'mgroup': None, 'notok_sign': None} + if mi_wm_in: + lookup['id'] + if into_wm_mgroup: + lookup['mgroup'] = mgroup + else: + lookup['belong_dept'] = belong_dept - wm, _ = WMaterial.objects.get_or_create(**lookup, defaults=lookup) - wm.count = wm.count + mi_count - wm.update_by = user - wm.save() + wm, _ = WMaterial.objects.get_or_create(**lookup, defaults=lookup) + wm.count = wm.count + mi_count + wm.update_by = user + wm.save() if material_out: # 产物退回 # 有多个产物的情况 into_wm_mgroup = material_out.process.into_wm_mgroup if material_out.process else False @@ -289,7 +294,7 @@ def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): for mo in m_outs_list: mo_ma, mo_batch, mo_count, _ = mo - lookup = {'batch': mo_batch, 'material': mo_ma, 'mgroup': None} + lookup = {'batch': mo_batch, 'material': mo_ma, 'mgroup': None, 'notok_sign': None} if into_wm_mgroup: lookup['mgroup'] = mgroup else: @@ -307,9 +312,7 @@ def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): wm.count = wm.count - mo_count if wm.count < 0: raise ParseError('车间库存不足, 产物无法回退') - elif wm.count == 0: - wm.delete() - else: + elif wm.count >= 0: wm.update_by = user wm.save() mlog.submit_time = None @@ -465,8 +468,6 @@ def handover_submit(handover: Handover, user: User, now: Union[datetime.datetime count_x = wm_from.count - handover.count if count_x < 0: raise ParseError('车间库存不足!') - elif count_x == 0: - wm_from_need_delete = True else: wm_from.count = count_x wm_from.save() @@ -485,5 +486,3 @@ def handover_submit(handover: Handover, user: User, now: Union[datetime.datetime handover.submit_user = user handover.submit_time = now handover.save() - if wm_from_need_delete: - wm_from.delete() diff --git a/apps/wpm/views.py b/apps/wpm/views.py index 7998298b..8ab2ef18 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -110,7 +110,7 @@ class WMaterialViewSet(ListModelMixin, CustomGenericViewSet): 车间库存 """ perms_map = {'get': '*'} - queryset = WMaterial.objects.all() + queryset = WMaterial.objects.filter(count__gt=0) serializer_class = WMaterialSerializer select_related_fields = ['material', 'belong_dept', 'material__process'] search_fields = ['material__name', @@ -441,7 +441,7 @@ class MlogbViewSet(ListModelMixin, CustomGenericViewSet): class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, CustomGenericViewSet): - perms_map = {'post': 'mlog.update', 'delete': 'mlog.update'} + perms_map = {'post': 'mlog.update', 'delete': 'mlog.update', 'put': 'mlog.update'} queryset = Mlogb.objects.filter(material_in__isnull=False) serializer_class = MlogbInSerializer update_serializer_class = MlogbInUpdateSerializer