feat: 支持不合格品处理/添加不合格品存储字段
This commit is contained in:
parent
83ec822f9d
commit
c058fe9338
|
@ -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(),
|
||||
),
|
||||
]
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue