feat: 调整数据结构

This commit is contained in:
caoqianming 2025-03-13 16:33:59 +08:00
parent f43726a884
commit 38dc9199e2
4 changed files with 105 additions and 108 deletions

View File

@ -0,0 +1,41 @@
# Generated by Django 3.2.12 on 2025-03-13 08:33
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('wpm', '0098_auto_20250312_0923'),
]
operations = [
migrations.RemoveField(
model_name='mlogb',
name='mlogb_to',
),
migrations.RemoveField(
model_name='mlogbw',
name='mlogb_to',
),
migrations.RemoveField(
model_name='mlogbw',
name='mlogbw_to',
),
migrations.AddField(
model_name='mlogb',
name='mlogb_from',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mlogb_from_mlogb', to='wpm.mlogb', verbose_name='来源批'),
),
migrations.AddField(
model_name='mlogb',
name='mlogbw_from',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mlogb_from_mlogb', to='wpm.mlogbw', verbose_name='来源个'),
),
migrations.AlterField(
model_name='mlogbw',
name='mlogbw_from',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='w_mlogbw_from', to='wpm.mlogbw', verbose_name='来源个'),
),
]

View File

@ -329,8 +329,10 @@ class Mlogb(BaseModel):
parent = models.ForeignKey("self", verbose_name='父级物料', on_delete=models.CASCADE, null=True, blank=True,
related_name='mlogb_parent')
mlogb_to = models.ForeignKey("self", verbose_name='生成的', on_delete=models.SET_NULL, null=True, blank=True,
related_name='mlogb_to_mlogb')
mlogb_from = models.ForeignKey("self", verbose_name='来源批', on_delete=models.CASCADE, null=True, blank=True,
related_name='mlogb_from_mlogb')
mlogbw_from = models.ForeignKey("wpm.mlogbw", verbose_name='来源个', on_delete=models.CASCADE, null=True, blank=True,
related_name='mlogb_from_mlogb')
material_out = models.ForeignKey(
Material, verbose_name='产物', on_delete=models.CASCADE, related_name='mlogb_material_out',
null=True, blank=True)
@ -435,9 +437,7 @@ class Mlogbw(BaseModel):
"""
number = models.TextField('单个编号')
mlogb = models.ForeignKey(Mlogb, verbose_name='生产记录', on_delete=models.CASCADE, related_name="w_mlogb")
mlogb_to = models.ForeignKey(Mlogb, verbose_name='指向生产记录', on_delete=models.CASCADE, null=True, blank=True, related_name="w_mlogb_to")
mlogbw_to = models.ForeignKey("self", verbose_name='指向单个产品', on_delete=models.SET_NULL, null=True, blank=True, related_name="w_mlogbw_to")
mlogbw_from = models.ForeignKey("self", verbose_name='来自单个产品', on_delete=models.SET_NULL, null=True, blank=True, related_name="w_mlogbw_from")
mlogbw_from = models.ForeignKey("self", verbose_name='来源个', on_delete=models.CASCADE, null=True, blank=True, related_name="w_mlogbw_from")
wpr = models.ForeignKey("wpmw.wpr", verbose_name='关联产品', on_delete=models.SET_NULL
, related_name='wpr_mlogbw', null=True, blank=True)
equip = models.ForeignKey(Equipment, verbose_name='设备', on_delete=models.SET_NULL, null=True, blank=True)

View File

@ -732,8 +732,8 @@ class MlogbwCreateUpdateSerializer(CustomModelSerializer):
ftest = FtestProcessSerializer(required=False)
class Meta:
model = Mlogbw
fields = ["id", "number", "wpr", "note", "mlogb", "ftest", "equip", "work_start_time", "work_end_time", "mlogb_to"]
read_only_fields = ["mlogb_to"]
fields = ["id", "number", "wpr", "note", "mlogb", "ftest", "equip", "work_start_time", "work_end_time", "mlogb_from", "mlogbw_from"]
read_only_fields = ["mlogb_from", "mlogbw_from"]
def validate(self, attrs):
mlogb:Mlogb = attrs["mlogb"]

View File

@ -539,32 +539,6 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
ins: Mlogb = instance
if ins.mlog.submit_time is not None:
raise ParseError('生产日志已提交不可编辑')
# if ins.mlogb_to:
# qs = Mlogb.objects.filter(id=ins.mlogb_to.id)
# ftestIds = list(Ftest.objects.filter(mlogbw_ftest__mlogb__in=qs).values_list('id', flat=True))
# qs.delete()
# if ftestIds:
# Ftest.objects.filter(id__in=ftestIds).delete()
# elif ins.parent is None and ins.mtask:
# query_dict = {"material_out__isnull": False, "mlog": ins.mlog, "mtask": ins.mtask}
# route = ins.mtask.route
# if route.batch_bind:
# query_dict["batch__contains"] = ins.batch
# qs = Mlogb.objects.filter(**query_dict)
qs = Mlogbw.objects.filter(mlogb=ins, ftest__isnull=False)
if ins.mlogb_to:
qs = qs|Mlogbw.objects.filter(mlogb=ins.mlogb_to, ftest__isnull=False)
qs = qs|Mlogbw.objects.filter(mlogb__id__in=list(Mlogbw.objects.filter(mlogb=ins).values_list("mlogb_to__id", flat=True)), ftest__isnull=False)
# 需要删除子集ftest记录
if qs:
ftestIds = list(Ftest.objects.filter(mlogbw_ftest__in=qs).values_list('id', flat=True))
qs.delete()
if ftestIds:
Ftest.objects.filter(id__in=ftestIds).delete()
if ins.mlogb_to:
ins.mlogb_to.delete()
mlogb_to_ids = list(Mlogbw.objects.filter(mlogb=ins).values_list("mlogb_to__id", flat=True))
Mlogb.objects.filter(id__in=mlogb_to_ids).delete()
ins.delete()
@transaction.atomic
@ -610,11 +584,9 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
d_count_real = mlogbin.count_use
d_count_ok = mlogbin.count_use
mlogbout, _ = Mlogb.objects.get_or_create(**m_dict, defaults=
{"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom, "count_real": d_count_real, "count_ok": d_count_ok, "qct": qct})
if mlogbin.mlogb_to is None:
mlogbin.mlogb_to = mlogbout
mlogbin.save(update_fields = ["mlogb_to"])
elif mlogbin.mlogb_to != mlogbout:
{"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom, "count_real": d_count_real, "count_ok": d_count_ok,
"qct": qct, "mlogb_from": mlogbin})
if mlogbout.mlogb_from != mlogbin:
raise ParseError("生成产出出错1")
elif mtype == Process.PRO_DIV:
div_number = route.div_number
@ -622,42 +594,34 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
for mlogbwin in Mlogbw.objects.filter(mlogb=mlogbin).order_by("number"):
m_dict["batch"] = mlogbwin.number
mlogbout, _ = Mlogb.objects.get_or_create(**m_dict, defaults=
{"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom, "count_real": div_number, "count_ok": div_number, "qct": qct})
if mlogbwin.mlogb_to is None:
mlogbwin.mlogb_to = mlogbout
mlogbwin.save(update_fields = ["mlogb_to"])
elif mlogbwin.mlogb_to != mlogbout:
{"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom,
"count_real": div_number, "count_ok": div_number, "qct": qct, "mlogbw_from": mlogbwin})
if mlogbout.mlogbw_from != mlogbwin:
raise ParseError("生成产出出错2")
elif material_out.tracking == Material.MA_TRACKING_BATCH:
d_count_real = mlogbin.count_use * div_number
d_count_ok = d_count_real
mlogbout, _ = Mlogb.objects.get_or_create(**m_dict, defaults=
{"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom, "count_real": d_count_real, "count_ok": d_count_ok, "qct": qct})
if mlogbin.mlogb_to is None:
mlogbin.mlogb_to = mlogbout
mlogbin.save(update_fields = ["mlogb_to"])
elif mlogbin.mlogb_to != mlogbout:
{"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom,
"count_real": d_count_real, "count_ok": d_count_ok, "qct": qct, "mlogb_from": mlogbin})
if mlogbout.mlogb_from != mlogbin:
raise ParseError("生成产出出错2-2")
elif mtype == Process.PRO_MERGE:
xcount = math.floor( mlogbin.count_use / route.div_number)
d_count_real = xcount
d_count_ok = xcount
mlogbout, _ = Mlogb.objects.get_or_create(**m_dict, defaults=
{"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom, "count_real": d_count_real, "count_ok": d_count_ok, "qct": qct})
if mlogbin.mlogb_to is None:
mlogbin.mlogb_to = mlogbout
mlogbin.save(update_fields = ["mlogb_to"])
elif mlogbin.mlogb_to != mlogbout:
{"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom,
"count_real": d_count_real, "count_ok": d_count_ok, "qct": qct, "mlogb_from": mlogbin})
if mlogbout.mlogb_from != mlogbin:
raise ParseError("生成产出出错3")
elif is_fix:
d_count_real = mlogbin.count_use
d_count_ok = mlogbin.count_use
mlogbout, _ = Mlogb.objects.get_or_create(**m_dict, defaults=
{"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom, "count_real": d_count_real, "count_ok": d_count_ok, "qct": qct})
if mlogbin.mlogb_to is None:
mlogbin.mlogb_to = mlogbout
mlogbin.save(update_fields = ["mlogb_to"])
elif mlogbin.mlogb_to != mlogbout:
{"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom,
"count_real": d_count_real, "count_ok": d_count_ok, "qct": qct, "mlogb_from": mlogbin})
if mlogbout.mlogb_from != mlogbin:
raise ParseError("生成产出出错4")
else:
raise ParseError("不支持生成产出物料!")
@ -666,21 +630,15 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
for mlogbwin in Mlogbw.objects.filter(mlogb=mlogbin).order_by("number"):
wpr = mlogbwin.wpr
if mtype == Process.PRO_NORMAL:
bw, _ = Mlogbw.objects.get_or_create(wpr=wpr, mlogb=mlogbout, defaults={"number": wpr.number})
if mlogbwin.mlogbw_to is None:
mlogbwin.mlogbw_to = bw
mlogbwin.save(update_fields = ["mlogbw_to"])
elif mlogbwin.mlogbw_to != bw:
bw, _ = Mlogbw.objects.get_or_create(wpr=wpr, mlogb=mlogbout, defaults={"number": wpr.number, "mlogbw_from": mlogbwin})
if bw.mlogbw_from != mlogbwin:
raise ParseError("生成产出出错5")
elif mtype == Process.PRO_DIV:
for i in range(route.div_number):
Mlogbw.objects.get_or_create(mlogb=mlogbout, number=f'{wpr.number}-{i+1}', defaults={"mlogbw_from": mlogbwin})
elif is_fix:
bw, _ = Mlogbw.objects.get_or_create(wpr=wpr, mlogb=mlogbout, defaults={"number": wpr.number})
if mlogbwin.mlogbw_to is None:
mlogbwin.mlogbw_to = bw
mlogbwin.save(update_fields = ["mlogbw_to"])
elif mlogbwin.mlogbw_to != bw:
bw, _ = Mlogbw.objects.get_or_create(wpr=wpr, mlogb=mlogbout, defaults={"number": wpr.number, "mlogbw_from": mlogbwin})
if bw.mlogbw_from != mlogbwin:
raise ParseError("生成产出出错6")
else:
raise ParseError("不支持的生产类型1")
@ -749,7 +707,7 @@ class MlogbwViewSet(CustomModelViewSet):
# 如果是输入且输出追踪到个,需同步创建
material_in:Material = mlogb.material_in
if material_in is not None:
mlogb_to = mlogb.mlogb_to
mlogb_qs = Mlogb.objects.filter(mlogb_from=ins)
material_out:Material = mlogb.mlog.material_out
mtype = route.process.mtype if route.process else None
if material_in.tracking == Material.MA_TRACKING_SINGLE and mtype == Process.PRO_DIV:
@ -757,38 +715,31 @@ class MlogbwViewSet(CustomModelViewSet):
wm_in = mlogbin.wm_in
mlog = mlogbin.mlog
div_number = route.div_number
if ins.mlogb_to:
mlogbout = ins.mlogb_to
else:
m_dict = {
"mtask": mlogbin.mtask,
"mlog": mlog,
"batch": ins.number,
"material_out": material_out,
"batch_ofrom": wm_in.batch_ofrom,
"material_ofrom": wm_in.material_ofrom,
"count_real": div_number,
"count_ok": div_number, "qct": mlog.qct
}
mlogbout = Mlogb.objects.create(**m_dict)
ins.mlogb_to = mlogbout
ins.save(update_fields=["mlogb_to"])
m_dict = {
"mtask": mlogbin.mtask,
"mlog": mlog,
"batch": ins.number,
"material_out": material_out,
"batch_ofrom": wm_in.batch_ofrom,
"material_ofrom": wm_in.material_ofrom,
"count_real": div_number,
"count_ok": div_number, "qct": mlog.qct
}
mlogbout, _ = Mlogb.objects.get_or_create(mlogbw_from=ins, defaults=m_dict)
if material_out.tracking == Material.MA_TRACKING_SINGLE:
for i in range(div_number):
Mlogbw.objects.get_or_create(mlogb=mlogbout, number=f"{ins.number}-{i+1}", defaults={"mlogbw_from": ins})
Mlogbw.cal_count_notok(mlogbout)
elif mlogb_to and material_out.tracking == Material.MA_TRACKING_SINGLE:
if route.process.mtype == Process.PRO_NORMAL:
bw, _ = Mlogbw.objects.get_or_create(mlogb=mlogb_to, wpr=ins.wpr, defaults={"number": ins.number})
if ins.mlogbw_to is None:
ins.mlogbw_to = bw
ins.save(update_fields=["mlogbw_to"])
elif ins.mlogbw_to != bw:
raise ParseError("生成产出出错7")
elif route.process.mtype == Process.PRO_DIV:
for i in range(route.div_number):
Mlogbw.objects.get_or_create(mlogb=mlogb_to, number=f'{ins.number}-{i+1}', defaults={"mlogbw_from": ins})
Mlogbw.cal_count_notok(mlogb_to)
elif mlogb_qs.exists() and material_out.tracking == Material.MA_TRACKING_SINGLE:
for mlogb in mlogb_qs:
if route.process.mtype == Process.PRO_NORMAL:
bw, _ = Mlogbw.objects.get_or_create(mlogb=mlogb, wpr=ins.wpr, defaults={"number": ins.number, "mlogbw_from": ins})
if bw.mlogbw_from != ins:
raise ParseError("生成产出出错7")
elif route.process.mtype == Process.PRO_DIV:
for i in range(route.div_number):
Mlogbw.objects.get_or_create(mlogb=mlogb, number=f'{ins.number}-{i+1}', defaults={"mlogbw_from": ins})
Mlogbw.cal_count_notok(mlogb)
@transaction.atomic
def perform_update(self, serializer):
@ -801,17 +752,22 @@ class MlogbwViewSet(CustomModelViewSet):
if mlogb.material_out is not None and instance.wpr is not None:
raise ParseError("不能删除该产出明细")
ftest = instance.ftest
instance.delete()
if ftest:
ftest.delete()
Mlogbw.cal_count_notok(mlogb)
# 如果是输入且输出追踪到个,需同步删除
material_in: Material = mlogb.material_in
need_cal_mlogb = False
if material_in is not None:
if instance.mlogb_to:
Mlogb.objects.filter(id=instance.mlogb_to.id).delete()
if instance.mlogbw_to:
instance.mlogbw_to.delete()
Mlogbw.cal_count_notok(instance.mlogbw_to.mlogb)
mlogbw_qs = Mlogbw.objects.filter(mlogbw_from=instance)
mlogbIds = list(mlogbw_qs.values_list("mlogb__id", flat=True))
if mlogbIds:
need_cal_mlogb = True
ftest = instance.ftest
if ftest:
ftest.delete()
instance.delete()
Mlogbw.cal_count_notok(mlogb)
if need_cal_mlogb:
for i in mlogbIds:
Mlogbw.cal_count_notok(Mlogb.objects.get(id=i))