feat: mlogb添加字段以追踪原料批次

This commit is contained in:
caoqianming 2024-11-13 15:56:40 +08:00
parent c1d140a082
commit 7d9582fe34
5 changed files with 92 additions and 16 deletions

View File

@ -0,0 +1,25 @@
# Generated by Django 3.2.12 on 2024-11-13 07:55
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('mtm', '0042_auto_20241010_1140'),
('wpm', '0070_auto_20241112_1447'),
]
operations = [
migrations.AddField(
model_name='mlogb',
name='batch_ofrom',
field=models.TextField(blank=True, null=True, verbose_name='原料批次号'),
),
migrations.AddField(
model_name='mlogb',
name='material_ofrom',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mlogb_mofrom', to='mtm.material', verbose_name='原料物料'),
),
]

View File

@ -283,11 +283,16 @@ class Mlogb(BaseModel):
batch = models.TextField('批次号', null=True, blank=True) batch = models.TextField('批次号', null=True, blank=True)
mtask = models.ForeignKey(Mtask, verbose_name='关联任务', mtask = models.ForeignKey(Mtask, verbose_name='关联任务',
on_delete=models.CASCADE, related_name='mlogb_mtask', null=True, blank=True) 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) wm_in = models.ForeignKey(WMaterial, verbose_name='投入物料所在库存', on_delete=models.SET_NULL, null=True, blank=True)
material_in = models.ForeignKey( material_in = models.ForeignKey(
Material, verbose_name='投入物料', on_delete=models.CASCADE, related_name='mlogb_material_in', null=True, blank=True) Material, verbose_name='投入物料', on_delete=models.CASCADE, related_name='mlogb_material_in', null=True, blank=True)
material_out = models.ForeignKey( material_out = models.ForeignKey(
Material, verbose_name='产物', on_delete=models.CASCADE, related_name='mlogb_material_out', null=True, blank=True) Material, verbose_name='产物', on_delete=models.CASCADE, related_name='mlogb_material_out', 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='mlogb_mofrom')
count_use = models.PositiveIntegerField('领用数量', default=0) count_use = models.PositiveIntegerField('领用数量', default=0)
count_break = models.PositiveIntegerField('加工破碎数', default=0) count_break = models.PositiveIntegerField('加工破碎数', default=0)

View File

@ -294,14 +294,18 @@ class MlogSerializer(CustomModelSerializer):
instance: Mlog = super().create(validated_data) instance: Mlog = super().create(validated_data)
# 自动生成mlogb # 自动生成mlogb
batch_in = instance.batch batch_in = instance.batch
if instance.wm_in: wm_in = instance.wm_in
batch_in = instance.wm_in.batch if wm_in:
batch_in = wm_in.batch
add_dict = { add_dict = {
'mlog': instance, 'batch': batch_in, 'wm_in': instance.wm_in, 'mlog': instance, 'batch': batch_in, 'wm_in': wm_in,
'mtask': instance.mtask, 'material_in': instance.material_in, 'mtask': instance.mtask, 'material_in': instance.material_in,
'count_use': instance.count_use, 'count_break': instance.count_break, 'count_use': instance.count_use, 'count_break': instance.count_break,
'count_pn_jgqbl': instance.count_pn_jgqbl 'count_pn_jgqbl': instance.count_pn_jgqbl
} }
if wm_in:
add_dict['batch_ofrom'] = wm_in.batch_ofrom
add_dict['material_ofrom'] = wm_in.material_ofrom
Mlogb.objects.create(**add_dict) Mlogb.objects.create(**add_dict)
# mlogb只用于组合件输出物填写 # mlogb只用于组合件输出物填写
@ -331,7 +335,11 @@ class MlogSerializer(CustomModelSerializer):
for f in Mlogb._meta.fields: for f in Mlogb._meta.fields:
if 'count_n_' in f.name: if 'count_n_' in f.name:
add_dict_2[f.name] = getattr(instance, f.name) add_dict_2[f.name] = getattr(instance, f.name)
Mlogb.objects.create(**add_dict_2) ddict = {}
if wm_in:
wm_in = instance.wm_in
ddict = {"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom}
Mlogb.objects.create(**add_dict_2, defaults=ddict)
return instance return instance
def update(self, instance, validated_data): def update(self, instance, validated_data):
@ -345,11 +353,12 @@ class MlogSerializer(CustomModelSerializer):
with transaction.atomic(): with transaction.atomic():
mlogb = validated_data.pop('mlogb', []) mlogb = validated_data.pop('mlogb', [])
instance: Mlog = super().update(instance, validated_data) instance: Mlog = super().update(instance, validated_data)
wm_in = instance.wm_in
if instance.fill_way == Mlog.MLOG_12: if instance.fill_way == Mlog.MLOG_12:
# 自动生成mlogb # 自动生成mlogb
batch_in = instance.batch batch_in = instance.batch
if instance.wm_in: if wm_in:
batch_in = instance.wm_in.batch batch_in = wm_in.batch
minx, _ = Mlogb.objects.get_or_create( minx, _ = Mlogb.objects.get_or_create(
mlog=instance, mlog=instance,
batch=batch_in, batch=batch_in,
@ -357,6 +366,9 @@ class MlogSerializer(CustomModelSerializer):
mtask=instance.mtask, mtask=instance.mtask,
material_in=instance.material_in material_in=instance.material_in
) )
if wm_in:
minx.batch_ofrom = wm_in.batch_ofrom
minx.material_ofrom = wm_in.material_ofrom
minx.count_use = instance.count_use minx.count_use = instance.count_use
minx.count_break = instance.count_break minx.count_break = instance.count_break
minx.count_pn_jgqbl = instance.count_pn_jgqbl minx.count_pn_jgqbl = instance.count_pn_jgqbl
@ -380,6 +392,9 @@ class MlogSerializer(CustomModelSerializer):
mox.count_ok = instance.count_ok mox.count_ok = instance.count_ok
mox.count_notok = instance.count_notok mox.count_notok = instance.count_notok
mox.count_break_t = instance.count_break_t mox.count_break_t = instance.count_break_t
if wm_in:
mox.batch_ofrom = wm_in.batch
mox.material_ofrom = wm_in.material_ofrom
for f in Mlogb._meta.fields: for f in Mlogb._meta.fields:
if 'count_n_' in f.name: if 'count_n_' in f.name:
setattr(mox, f.name, getattr(instance, f.name)) setattr(mox, f.name, getattr(instance, f.name))
@ -511,6 +526,8 @@ class MlogbInSerializer(CustomModelSerializer):
route = mlog.route route = mlog.route
attrs['material_in'] = wm_in.material attrs['material_in'] = wm_in.material
attrs['batch'] = wm_in.batch attrs['batch'] = wm_in.batch
attrs["batch_ofrom"] = wm_in.batch_ofrom
attrs["material_ofrom"] = wm_in.material_ofrom
if route.batch_bind: if route.batch_bind:
if not WMaterial.mat_in_qs(mtask).filter(id=wm_in.id).exists(): if not WMaterial.mat_in_qs(mtask).filter(id=wm_in.id).exists():
raise ValidationError('该车间库存非本任务使用') raise ValidationError('该车间库存非本任务使用')

View File

@ -8,7 +8,7 @@ from typing import Union
from rest_framework.exceptions import ParseError from rest_framework.exceptions import ParseError
from apps.system.models import User from apps.system.models import User
from apps.inm.models import MIO, MIOItem, MIOItemA from apps.inm.models import MIO, MIOItem, MIOItemA, MaterialBatch
from apps.pm.models import Mtask from apps.pm.models import Mtask
from apps.mtm.models import Mgroup, Shift, Material, Route, RoutePack from apps.mtm.models import Mgroup, Shift, Material, Route, RoutePack
@ -186,7 +186,12 @@ def do_in(mio: MIO):
for al in action_list: for al in action_list:
xmaterial, xbatch, xcount = al xmaterial, xbatch, xcount = al
# 优先从车间库存里拿 # 优先从车间库存里拿
wm_qs = WMaterial.objects.filter(batch=xbatch, material=xmaterial, belong_dept=belong_dept, mgroup=mgroup, state=WMaterial.WM_OK) wm_qs = WMaterial.objects.filter(
batch=xbatch,
material=xmaterial,
belong_dept=belong_dept,
mgroup=mgroup,
state=WMaterial.WM_OK)
# if not wm_qs.exists(): # if not wm_qs.exists():
# wm_qs = WMaterial.objects.filter(batch=xbatch, material=xmaterial, belong_dept=belong_dept, mgroup__isnull=False, notok_sign=None, material_origin=None, count_xtest=None) # wm_qs = WMaterial.objects.filter(batch=xbatch, material=xmaterial, belong_dept=belong_dept, mgroup__isnull=False, notok_sign=None, material_origin=None, count_xtest=None)
@ -227,6 +232,7 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
material_out = mlog.material_out material_out = mlog.material_out
material_in = mlog.material_in material_in = mlog.material_in
supplier = mlog.supplier # 外协 supplier = mlog.supplier # 外协
m_ins_list = []
if material_in: # 需要进行车间库存管理 if material_in: # 需要进行车间库存管理
m_ins = Mlogb.objects.filter(mlog=mlog, material_in__isnull=False) m_ins = Mlogb.objects.filter(mlog=mlog, material_in__isnull=False)
if m_ins.exists(): if m_ins.exists():
@ -287,7 +293,7 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
stored_notok = False stored_notok = False
stored_mgroup = False stored_mgroup = False
if m_outs.exists(): if m_outs.exists():
m_outs_list = [(mo.material_out, mo.batch if mo.batch else mlog.batch, mo.count_ok, mlog.count_real_eweight, None) for mo in m_outs.all()] m_outs_list = [(mo.material_out, mo.batch if mo.batch else mlog.batch, mo.count_ok, mlog.count_real_eweight, None, mo) for mo in m_outs.all()]
if need_store_notok: if need_store_notok:
for item in m_outs: for item in m_outs:
for f in Mlogb._meta.fields: for f in Mlogb._meta.fields:
@ -296,11 +302,11 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
m_outs_list.append( (item.material_out, item.batch if item.batch else mlog.batch, getattr(item, f.name), mlog.count_real_eweight, notok_sign)) m_outs_list.append( (item.material_out, item.batch if item.batch else mlog.batch, getattr(item, f.name), mlog.count_real_eweight, notok_sign))
stored_notok = True stored_notok = True
else: else:
m_outs_list = [(material_out, mlog.batch, mlog.count_ok, mlog.count_real_eweight, None)] m_outs_list = [(material_out, mlog.batch, mlog.count_ok, mlog.count_real_eweight, None, mlog)]
# 一次填写的暂时不处理不合格品 # 一次填写的暂时不处理不合格品
for mo in m_outs_list: for mo in m_outs_list:
mo_ma, mo_batch, mo_count, mo_count_eweight, notok_sign = mo mo_ma, mo_batch, mo_count, mo_count_eweight, notok_sign, mlog_or_b = mo
wm_state = WMaterial.WM_OK if notok_sign is None else WMaterial.WM_NOTOK wm_state = WMaterial.WM_OK if notok_sign is None else WMaterial.WM_NOTOK
lookup = {'batch': mo_batch, 'material': mo_ma, 'mgroup': None, 'notok_sign': notok_sign, 'state': wm_state} lookup = {'batch': mo_batch, 'material': mo_ma, 'mgroup': None, 'notok_sign': notok_sign, 'state': wm_state}
if into_wm_mgroup: if into_wm_mgroup:
@ -309,12 +315,20 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
else: else:
lookup['belong_dept'] = belong_dept lookup['belong_dept'] = belong_dept
if mo_count > 0: if mo_count > 0:
wm, _ = WMaterial.objects.get_or_create(**lookup, defaults={**lookup, "belong_dept": belong_dept}) wm, is_create2 = WMaterial.objects.get_or_create(**lookup, defaults={**lookup, "belong_dept": belong_dept})
wm.count = wm.count + mo_count wm.count = wm.count + mo_count
wm.count_eweight = mo_count_eweight wm.count_eweight = mo_count_eweight
wm.update_by = user wm.update_by = user
if supplier is not None: if supplier is not None:
wm.supplier = supplier wm.supplier = supplier
if is_create2:
if isinstance(mlog_or_b, Mlog) and mlog_or_b.wm_in:
wm.batch_ofrom = mlog_or_b.wm_in.batch_ofrom
wm.material_ofrom = mlog_or_b.wm_in.material_ofrom
elif isinstance(mlog_or_b, Mlogb):
wm.batch_ofrom = mlog_or_b.batch_ofrom
wm.material_ofrom = mlog_or_b.material_ofrom
wm.batch_ofrom = mlog_or_b
wm.save() wm.save()
mlog.submit_time = now mlog.submit_time = now
@ -600,7 +614,11 @@ def handover_submit(handover: Handover, user: User, now: Union[datetime.datetime
material=material, material=material,
mgroup=recive_mgroup, mgroup=recive_mgroup,
belong_dept=recive_dept, belong_dept=recive_dept,
state=WMaterial.WM_OK state=WMaterial.WM_OK,
defaults={
"batch_ofrom": wm_from.batch_ofrom,
"material_ofrom": wm_from.material_ofrom
}
) )
elif handover.type == Handover.H_REPAIR: elif handover.type == Handover.H_REPAIR:
if handover.recive_mgroup: if handover.recive_mgroup:
@ -611,7 +629,11 @@ def handover_submit(handover: Handover, user: User, now: Union[datetime.datetime
belong_dept=recive_dept, belong_dept=recive_dept,
notok_sign=wm_from.notok_sign, notok_sign=wm_from.notok_sign,
material_origin=material, material_origin=material,
state=WMaterial.WM_REPAIR state=WMaterial.WM_REPAIR,
defaults={
"batch_ofrom": wm_from.batch_ofrom,
"material_ofrom": wm_from.material_ofrom
}
) )
else: else:
raise ParseError("返工交接必须指定接收工段") raise ParseError("返工交接必须指定接收工段")
@ -624,6 +646,8 @@ def handover_submit(handover: Handover, user: User, now: Union[datetime.datetime
belong_dept=recive_dept, belong_dept=recive_dept,
defaults={ defaults={
"count_xtest": 0, "count_xtest": 0,
"batch_ofrom": wm_from.batch_ofrom,
"material_ofrom": wm_from.material_ofrom
}, },
) )
elif handover.type == Handover.H_SCRAP: elif handover.type == Handover.H_SCRAP:
@ -634,7 +658,11 @@ def handover_submit(handover: Handover, user: User, now: Union[datetime.datetime
mgroup=recive_mgroup, mgroup=recive_mgroup,
belong_dept=recive_dept, belong_dept=recive_dept,
notok_sign=wm_from.notok_sign, notok_sign=wm_from.notok_sign,
state=WMaterial.WM_SCRAP state=WMaterial.WM_SCRAP,
defaults={
"batch_ofrom": wm_from.batch_ofrom,
"material_ofrom": wm_from.material_ofrom
}
) )
else: else:
raise ParseError("不支持非工段报废") raise ParseError("不支持非工段报废")

View File

@ -488,7 +488,8 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
"material_out": ins.mlog.material_out "material_out": ins.mlog.material_out
} }
m_dict['batch'] = generate_new_batch(ins.batch, mlog) m_dict['batch'] = generate_new_batch(ins.batch, mlog)
Mlogb.objects.get_or_create(**m_dict, defaults=m_dict) wm_in: WMaterial = ins.wm_in
Mlogb.objects.get_or_create(**m_dict, defaults={"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom})
class MlogbOutViewSet(UpdateModelMixin, CustomGenericViewSet): class MlogbOutViewSet(UpdateModelMixin, CustomGenericViewSet):