This commit is contained in:
zty 2025-09-05 11:10:16 +08:00
commit ca18fece21
19 changed files with 190 additions and 63 deletions

View File

@ -153,7 +153,9 @@ class MIOItemCreateSerializer(CustomModelSerializer):
validated_data["batch"] = wm.batch
material: Material = validated_data['material']
batch = validated_data['batch']
batch = validated_data.get("batch", None)
if not batch:
batch = ""
if material.is_hidden:
raise ParseError('隐式物料不可出入库')
if mio.type in [MIO.MIO_TYPE_RETURN_IN, MIO.MIO_TYPE_BORROW_OUT]:

View File

@ -398,7 +398,7 @@ class InmService:
if change_count < 0:
raise ParseError("存在负数!")
state = WMaterial.WM_OK
if defect:
if defect and defect.okcate in [Defect.DEFECT_NOTOK]:
state = WMaterial.WM_NOTOK
mb, _ = MaterialBatch.objects.get_or_create(
material=material,

View File

@ -138,13 +138,17 @@ def daoru_mioitems(path:str, mio:MIO):
mioitems = []
ind = 2
while sheet[f"b{ind}"].value:
while sheet[f"a{ind}"].value:
batch = sheet[f"b{ind}"].value
material_number = sheet[f"a{ind}"].value
try:
material = Material.objects.get(number=material_number)
except Exception as e:
raise ParseError(f"未找到物料:{material_number} {e}")
if batch:
pass
else:
batch = ""
count = sheet[f"c{ind}"].value
warehouse_name = sheet[f"d{ind}"].value
try:

View File

@ -206,12 +206,13 @@ class MIOViewSet(CustomModelViewSet):
if ins.state != MIO.MIO_CREATE:
raise ParseError('记录状态异常')
with transaction.atomic():
ins.submit_time = timezone.now()
ins.state = MIO.MIO_SUBMITED
ins.submit_user = request.user
ins.update_by = request.user
ins.save()
InmService.update_inm(ins)
now = timezone.now()
updated_count = MIO.objects.filter(id=ins.id, submit_time__isnull=True).update(
submit_time=now, update_time=now, state=MIO.MIO_SUBMITED, submit_user=request.user, update_by=request.user)
if updated_count == 1:
InmService.update_inm(ins)
else:
raise ParseError('记录正在处理中,请稍后再试')
InmService.update_material_count(ins)
return Response(MIOListSerializer(instance=ins).data)
@ -228,11 +229,12 @@ class MIOViewSet(CustomModelViewSet):
if ins.submit_user != user:
raise ParseError('非提交人不可撤回')
with transaction.atomic():
ins.submit_time = None
ins.state = MIO.MIO_CREATE
ins.update_by = user
ins.save()
InmService.update_inm(ins, is_reverse=True)
updated_count = MIO.objects.filter(id=ins.id, submit_time__isnull=False).update(
submit_time=None, update_time=timezone.now(), state=MIO.MIO_CREATE, submit_user=None, update_by=request.user)
if updated_count == 1:
InmService.update_inm(ins, is_reverse=True)
else:
raise ParseError('记录正在处理中,请稍后再试')
InmService.update_material_count(ins)
return Response()

View File

@ -58,5 +58,6 @@ class RouteFilter(filters.FilterSet):
"mgroup": ["exact", "in", "isnull"],
"mgroup__name": ["exact", "contains"],
"mgroup__belong_dept": ["exact"],
"mgroup__belong_dept__name": ["exact", "contains"]
"mgroup__belong_dept__name": ["exact", "contains"],
"from_route": ["exact", "isnull"],
}

View File

@ -0,0 +1,24 @@
# Generated by Django 3.2.12 on 2025-09-02 03:22
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('mtm', '0061_material_img'),
]
operations = [
migrations.AddField(
model_name='route',
name='from_route',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='route_f', to='mtm.route', verbose_name='来源路线'),
),
migrations.AlterField(
model_name='route',
name='parent',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='route_parent', to='mtm.route', verbose_name='上级路线'),
),
]

View File

@ -415,8 +415,9 @@ class Route(CommonADModel):
batch_bind = models.BooleanField('是否绑定批次', default=True)
materials = models.ManyToManyField(Material, verbose_name='关联辅助物料', related_name="route_materials",
through="mtm.routemat", blank=True)
parent = models.ForeignKey('self', verbose_name='上级路线', on_delete=models.CASCADE, null=True, blank=True)
parent = models.ForeignKey('self', verbose_name='上级路线', on_delete=models.CASCADE, null=True, blank=True, related_name="route_parent")
params_json = models.JSONField('工艺参数', default=dict, blank=True)
from_route = models.ForeignKey('self', verbose_name='来源路线', on_delete=models.SET_NULL, null=True, blank=True, related_name="route_f")
def __str__(self):
x = ""

View File

@ -247,7 +247,7 @@ class RouteSerializer(CustomModelSerializer):
# if material and process and Route.objects.filter(material=material, process=process).exists():
# raise ValidationError('已选择该工序!!')
with transaction.atomic():
instance = super().create(validated_data)
instance:Route = super().create(validated_data)
material_out = instance.material_out
if material_out:
if material_out.process is None:
@ -263,12 +263,16 @@ class RouteSerializer(CustomModelSerializer):
if instance.material:
instance.material_out = RouteSerializer.gen_material_out(instance, material_out_tracking, user=self.request.user)
instance.save()
rx = Route.objects.filter(material_in=instance.material_in, material_out=instance.material_out, process=process).exclude(id=instance.id).first()
rx = Route.objects.filter(
material_in=instance.material_in, material_out=instance.material_out,
process=process).exclude(id=instance.id).order_by("create_time").first()
if rx:
msg = ""
if rx.routepack:
msg = rx.routepack.name
raise ParseError(f"该工艺步骤已存在-{msg}")
instance.from_route = rx
instance.save()
# msg = ""
# if rx.routepack:
# msg = rx.routepack.name
# raise ParseError(f"该工艺步骤已存在-{msg}")
return instance
def update(self, instance, validated_data):
@ -294,12 +298,16 @@ class RouteSerializer(CustomModelSerializer):
if instance.material:
instance.material_out = RouteSerializer.gen_material_out(instance, material_out_tracking, user=self.request.user)
instance.save()
rx = Route.objects.filter(material_in=instance.material_in, material_out=instance.material_out, process=process).exclude(id=instance.id).first()
rx = Route.objects.filter(
material_in=instance.material_in, material_out=instance.material_out,
process=process).exclude(id=instance.id).order_by("create_time").first()
if rx:
msg = ""
if rx.routepack:
msg = rx.routepack.name
raise ParseError(f"该工艺步骤已存在-{msg}")
instance.from_route = rx
instance.save()
# msg = ""
# if rx.routepack:
# msg = rx.routepack.name
# raise ParseError(f"该工艺步骤已存在-{msg}")
return instance
def to_representation(self, instance):
@ -330,6 +338,12 @@ class RouteMatSerializer(CustomModelSerializer):
model = RouteMat
fields = "__all__"
read_only_fields = EXCLUDE_FIELDS_BASE
def validate(self, attrs):
route:Route = attrs["route"]
if route.from_route is not None:
raise ParseError("该工艺步骤引用其他步骤,无法修改")
return attrs
class MaterialExportSerializer(CustomModelSerializer):

View File

@ -155,12 +155,12 @@ def bind_routepack(ticket: Ticket, transition, new_ticket_data: dict):
raise ParseError('缺少步骤')
r_qs = Route.objects.filter(routepack=routepack).order_by('sort', 'process__sort', 'create_time')
first_route = r_qs.first()
last_route = r_qs.last()
if first_route.batch_bind:
first_route.batch_bind = False
first_route.save(update_fields=['batch_bind'])
if last_route.material_out != routepack.material:
raise ParseError('最后一步产出与工艺包不一致')
# last_route = r_qs.last()
# if last_route.material_out != routepack.material:
# raise ParseError('最后一步产出与工艺包不一致')
ticket_data = ticket.ticket_data
ticket_data.update({
't_model': 'routepack',

View File

@ -368,12 +368,23 @@ class RouteViewSet(CustomModelViewSet):
select_related_fields = ['material',
'process', 'material_in', 'material_out', 'mgroup', 'routepack']
def update(self, request, *args, **kwargs):
obj:Route = self.get_object()
routepack = obj.routepack
@transaction.atomic
def perform_update(self, serializer):
ins:Route = self.get_object()
if ins.from_route is not None:
raise ParseError('该工艺步骤引用其他步骤, 无法编辑')
old_m_in, old_m_out, process = ins.material_in, ins.material_out, ins.process
routepack = ins.routepack
if routepack and routepack.state != RoutePack.RP_S_CREATE:
raise ParseError('该状态下不可编辑')
return super().update(request, *args, **kwargs)
raise ParseError('该工艺路线非创建中不可编辑')
ins_n:Route = serializer.save()
if Route.objects.filter(from_route__id=ins.id).exists() and (ins_n.material_in != old_m_in or ins_n.material_out != old_m_out or ins_n.process != process):
raise ParseError("该工艺步骤被其他步骤引用, 无法修改关键信息")
def perform_destroy(self, instance:Route):
if Route.objects.filter(from_route=instance).exists():
raise ParseError('该工艺步骤被其他步骤引用,无法删除')
return super().perform_destroy(instance)
class SruleViewSet(CustomModelViewSet):

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2025-09-05 01:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('qm', '0052_auto_20250718_1558'),
]
operations = [
migrations.AlterField(
model_name='ftest',
name='is_ok',
field=models.BooleanField(default=True, verbose_name='是否合格'),
),
]

View File

@ -337,7 +337,7 @@ class Ftest(CommonBDModel):
User, verbose_name='操作人', on_delete=models.CASCADE, related_name='ftest_test_user')
check_user = models.ForeignKey(
User, verbose_name='专检人', on_delete=models.CASCADE, related_name='ftest_check_user', null=True, blank=True)
is_ok = models.BooleanField('是否合格', default=False)
is_ok = models.BooleanField('是否合格', default=True)
note = models.TextField('备注', default='', blank=True)
ftest_work = models.ForeignKey(
FtestWork, verbose_name='关联检验工作', on_delete=models.CASCADE, null=True, blank=True)

View File

@ -322,7 +322,7 @@ class FtestWorkViewSet(CustomModelViewSet):
ins:FtestWork = self.get_object()
if ins.ticket:
raise ParseError('该检验工作存在审批!')
if ins.wm is None or ins.mb is None:
if ins.wm is None and ins.mb is None:
raise ParseError('该检验工作未关联库存')
if ins.submit_time is None:
ftestwork_submit(ins, request.user)

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2025-09-04 08:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wpm', '0122_auto_20250827_1522'),
]
operations = [
migrations.AddField(
model_name='mlogbdefect',
name='count_has',
field=models.DecimalField(decimal_places=1, default=0, max_digits=11, verbose_name='含有该缺陷的数量'),
),
]

View File

@ -477,6 +477,7 @@ class MlogbDefect(BaseModel):
mlogb = models.ForeignKey(Mlogb, verbose_name='生产记录', on_delete=models.CASCADE)
defect = models.ForeignKey("qm.Defect", verbose_name='缺陷', on_delete=models.CASCADE, null=True, blank=True)
count = models.DecimalField('数量', default=0, max_digits=11, decimal_places=1)
count_has = models.DecimalField('含有该缺陷的数量', default=0, max_digits=11, decimal_places=1)
@classmethod
def get_defect_qs(cls, ftype="all"):
@ -512,7 +513,7 @@ class Mlogbw(BaseModel):
@classmethod
def cal_count_notok(cls, mlogb: Mlogb):
from apps.qm.models import Defect
from apps.qm.models import Defect, FtestDefect
# 锁定mlogb以防止并发修改
# mlogb:Mlogb = Mlogb.objects.select_for_update().get(pk=mlogb.pk)
count = Mlogbw.objects.filter(mlogb=mlogb).count()
@ -523,9 +524,13 @@ class Mlogbw(BaseModel):
mlogb.count_real = count
count_notok = 0
count_notok_full = 0
tqs = Mlogbw.objects.filter(mlogb=mlogb, ftest__is_ok=False)
tqs_a = Mlogbw.objects.filter(mlogb=mlogb, ftest__is_ok=False).values("ftest__defect_main").annotate(xcount=Count('id'))
defects = {defect.id: defect for defect in Defect.objects.filter(id__in=tqs.values_list("ftest__defect_main", flat=True))}
# 个追踪的合格b类不分批
tqs = Mlogbw.objects.filter(mlogb=mlogb, ftest__defect_main__isnull=False)
tqs_a = Mlogbw.objects.filter(mlogb=mlogb, ftest__defect_main__isnull=False).values("ftest__defect_main").annotate(xcount=Count('id'))
defect_ids = tqs.values_list("ftest__defect_main", flat=True)
tqs_has_a = FtestDefect.objects.filter(ftest__mlogbw_ftest__mlogb=mlogb, has=True).values("defect").annotate(xcount=Count('id'))
defect_ids = defect_ids.union(tqs_has_a.values_list("defect", flat=True))
defects = {defect.id: defect for defect in Defect.objects.filter(id__in=defect_ids)}
md_ids = []
for t in tqs_a:
md, _ = MlogbDefect.objects.get_or_create(mlogb=mlogb, defect=defects[t["ftest__defect_main"]])
@ -535,6 +540,13 @@ class Mlogbw(BaseModel):
count_notok += t["xcount"]
if defects[t["ftest__defect_main"]].okcate != 10:
count_notok_full += t["xcount"]
for t2 in tqs_has_a:
md, _ = MlogbDefect.objects.get_or_create(mlogb=mlogb, defect=defects[t2["defect"]], defaults={"count": 0})
md.count_has = t2["xcount"]
md.save()
md_ids.append(md.id)
MlogbDefect.objects.filter(mlogb=mlogb).exclude(id__in=md_ids).delete()
mlogb.count_notok = count_notok
mlogb.count_ok = count - mlogb.count_notok

View File

@ -1,6 +1,6 @@
from apps.wpm.models import BatchSt
import logging
from apps.wpm.models import Mlogb, MlogbDefect
from apps.wpm.models import Mlogb, Mlogbw, MlogbDefect
from apps.mtm.models import Mgroup
import decimal
from django.db.models import Sum
@ -41,10 +41,14 @@ def main(batch: str, mgroup_obj:Mgroup=None):
for item in mlogb1_qs:
# 找到对应的输入
mlogb_from:Mlogb = item.mlogb_from
mlogbw_from:Mlogbw = item.mlogbw_from
if mlogb_from:
mlogb_q_ids.append(mlogb_from.id)
data[f"{mgroup_name}_count_use"] += mlogb_from.count_use
data[f"{mgroup_name}_count_pn_jgqbl"] += mlogb_from.count_pn_jgqbl
if mlogbw_from:
data[f"{mgroup_name}_count_use"] += 1
data[f"{mgroup_name}_count_pn_jgqbl"] += 0
if item.mlog.handle_user:
data[f"{mgroup_name}_操作人"].append(item.mlog.handle_user)
if item.mlog.handle_date:

View File

@ -29,6 +29,7 @@ def main(batch: str, mgroup_obj):
if mlogb1_qs.exists():
data[f"{mgroup_name}_日期"] = []
data[f"{mgroup_name}_操作人"] = []
data[f"{mgroup_name}_班次"] = []
data[f"{mgroup_name}_count_use"] = 0
data[f"{mgroup_name}_count_real"] = 0
data[f"{mgroup_name}_count_ok"] = 0
@ -47,6 +48,8 @@ def main(batch: str, mgroup_obj):
data[f"{mgroup_name}_操作人"].append(item.mlog.handle_user)
if item.mlog.handle_date:
data[f"{mgroup_name}_日期"].append(item.mlog.handle_date)
if item.mlog.shift:
data[f"{mgroup_name}_班次"].append(item.mlog.shift.name)
data[f"{mgroup_name}_count_real"] += item.count_real
data[f"{mgroup_name}_count_ok"] += item.count_ok
data[f"{mgroup_name}_count_ok_full"] += item.count_ok_full if item.count_ok_full else 0
@ -80,6 +83,8 @@ def main(batch: str, mgroup_obj):
data[f"{mgroup_name}_日期"] = ";".join([item.strftime("%Y-%m-%d") for item in data[f"{mgroup_name}_日期"]])
data[f"{mgroup_name}_操作人"] = list(set(data[f"{mgroup_name}_操作人"]))
data[f"{mgroup_name}_操作人"] = ";".join([item.name for item in data[f"{mgroup_name}_操作人"]])
data[f"{mgroup_name}_班次"] = list(set(data[f"{mgroup_name}_班次"]))
data[f"{mgroup_name}_班次"] = ";".join([item for item in data[f"{mgroup_name}_班次"]])
mlogb2_qs = Mlogb.objects.filter(mlog__submit_time__isnull=False,

View File

@ -216,12 +216,17 @@ class MlogbDefectSerializer(CustomModelSerializer):
defect_okcate = serializers.CharField(source="defect.okcate", read_only=True)
class Meta:
model = MlogbDefect
fields = ["id", "defect_name", "count", "mlogb", "defect", "defect_okcate"]
fields = ["id", "defect_name", "count", "mlogb", "defect", "defect_okcate", "count_has"]
read_only_fields = EXCLUDE_FIELDS_BASE + ["mlogb"]
extra_kwargs = {
'count_has': {'required': False},
}
def validate(self, attrs):
if attrs["count"] < 0:
raise serializers.ValidationError("存在负数!")
if "count_has" not in attrs or attrs["count_has"] < attrs["count"]:
attrs["count_has"] = attrs["count"]
return attrs
class MlogbSerializer(CustomModelSerializer):
@ -635,10 +640,12 @@ class MlogSerializer(CustomModelSerializer):
mgroup:Mgroup = attrs['mgroup']
work_start_time:datetime = attrs['work_start_time']
handle_date, attrs["shift"] = mgroup.get_shift(work_start_time)
if mtask.start_date == mtask.end_date:
if mtask and mtask.start_date == mtask.end_date:
attrs['handle_date'] = mtask.end_date
if attrs['handle_date'] != handle_date:
raise ParseError('任务日期与生产日期不一致')
else:
attrs['handle_date'] = handle_date
handle_user = attrs.get('handle_user', None)
if handle_user is None and hasattr(self, "request"):
@ -684,8 +691,6 @@ class MlogInitSerializer(CustomModelSerializer):
supplier = attrs.get('supplier', None)
if not supplier:
raise ParseError('外协必须选择外协单位')
if attrs.get('work_start_time', None) and 'handle_date' not in attrs:
attrs['handle_date'] = localdate(attrs['work_end_time'])
# 如果已经确定产出则自动获取qct
if attrs.get("material_out", None):
attrs["qct"] = Qct.get(attrs["material_out"], "process", "out")
@ -696,12 +701,14 @@ class MlogInitSerializer(CustomModelSerializer):
class MlogChangeSerializer(CustomModelSerializer):
class Meta:
model = Mlog
fields = ['id', 'work_end_time', 'handle_user', 'note', 'oinfo_json', 'test_file', 'test_user', 'test_time', 'equipment', "team"]
fields = ['id', 'work_start_time', 'work_end_time', 'handle_user', 'note', 'oinfo_json', 'test_file', 'test_user', 'test_time', 'equipment', "team"]
# def validate(self, attrs):
# if attrs.get('work_end_time', None):
# attrs['handle_date'] = localdate(attrs['work_end_time'])
# return attrs
def update(self, instance, validated_data):
work_start_time = validated_data.get('work_start_time', None)
if work_start_time:
mgroup:Mgroup = instance.mgroup
validated_data["handle_date"], validated_data["shift"] = mgroup.get_shift(work_start_time)
return super().update(instance, validated_data)
class CountJsonSerializer(serializers.Serializer):
@ -824,10 +831,9 @@ class MlogbInUpdateSerializer(CustomModelSerializer):
MlogbDefect.objects.bulk_create(mlogb_defect_objects)
ins.cal_count_pn_jgqbl(cal_mlog=False)
# 只有普通工序的才可联动
material_out:Material = ins.mlog.material_out
route:Route = mlog.route
if material_out.tracking == Material.MA_TRACKING_BATCH:
if route and route.process and route.process.mtype == Process.PRO_NORMAL:
route:Route = ins.route if ins.route else ins.mlog.route
if route and route.process and route.process.mtype == Process.PRO_NORMAL:
if route.material_out.tracking == Material.MA_TRACKING_BATCH:
mlogbout_qs = Mlogb.objects.filter(mlog=ins.mlog, mlogb_from=ins)
if mlogbout_qs.count() == 1:
mlogbout = mlogbout_qs.first()
@ -910,7 +916,7 @@ class MlogbwCreateUpdateSerializer(CustomModelSerializer):
class MlogbwStartTestSerializer(serializers.Serializer):
mlogbw_ids = serializers.ListField(child=serializers.CharField(), label="mlogbwId列表")
test_equip = serializers.CharField(label="测试设备", allow_null=True, required=False)
test_equip = serializers.CharField(label="测试设备", allow_null=True, required=False, allow_blank=True)
test_user = serializers.CharField(label="测试人员")
defects = serializers.ListField(child=serializers.CharField(), required=False, allow_null=True, label="缺陷项列表")
testitems = serializers.ListField(child=serializers.CharField(), required=False, allow_null=True, label="测试项列表")
@ -950,7 +956,7 @@ class MlogbwStartTestSerializer(serializers.Serializer):
if mlogbw.ftest:
existing_ftests[mlogbw.ftest_id] = mlogbw.ftest
else:
ftest = Ftest(mlogbw=mlogbw, test_date=test_date, qct=qct)
ftest = Ftest(test_date=test_date, qct=qct, test_user=test_user, type="process", id=idWorker.get_id(), is_ok=True)
new_ftests.append(ftest)
mlogbws_to_update.append(mlogbw)
@ -988,7 +994,7 @@ class MlogbwStartTestSerializer(serializers.Serializer):
else:
# 新记录,需要创建
defects_to_create.append(
FtestDefect(ftest=ftest, defect=defect, test_user=test_user)
FtestDefect(ftest=ftest, defect=defect, test_user=test_user, id=idWorker.get_id())
)
# 批量创建新记录
@ -1027,7 +1033,8 @@ class MlogbwStartTestSerializer(serializers.Serializer):
ftest=ftest,
testitem=testitem,
test_user=test_user,
test_equip=test_equip
test_equip=test_equip,
id=idWorker.get_id()
)
)

View File

@ -152,6 +152,8 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
"""
生产日志提交后需要执行的操作
"""
if mlog.work_start_time > timezone.now():
raise ParseError('操作开始时间不能晚于当前时间')
if mlog.work_start_time and mlog.work_end_time and mlog.work_end_time < mlog.work_start_time:
raise ParseError('操作结束时间不能早于操作开始时间')
if mlog.count_real == 0:
@ -203,7 +205,7 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
for item in m_ins:
mbd_qs = MlogbDefect.get_defect_qs_from_mlogb(item)
for itemx in mbd_qs:
if itemx.defect:
if itemx.defect and itemx.count > 0:
m_ins_bl_list.append((item.material_in, item.batch, itemx.count, itemx.defect, item))
else:
m_ins_list = [(material_in, mlog.batch, mlog.count_use, None, mlog)]
@ -282,7 +284,8 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
# if item.material_out.tracking == Material.MA_TRACKING_SINGLE:
# Mlogbw.cal_count_notok(item)
for itemx in mbd_qs:
m_outs_list.append((item.material_out, item.batch, itemx.count, 0, itemx.defect, item))
if itemx.count > 0:
m_outs_list.append((item.material_out, item.batch, itemx.count, 0, itemx.defect, item))
# # 获取所有主要的不合格项/先暂时保留
# bw_qs = Mlogbw.objects.filter(mlogb=item)
# defectIds= Ftest.objects.filter(mlogbw_ftest__in=bw_qs).exclude(defect_main=None).values_list("defect_main__id", flat=True).distinct()
@ -435,7 +438,8 @@ def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
# if item.material_out.tracking == Material.MA_TRACKING_SINGLE:
# Mlogbw.cal_count_notok(item)
for itemx in mbd_qs:
m_outs_list.append((item.material_out, item.batch, itemx.count, 0, itemx.defect, item))
if itemx.count > 0:
m_outs_list.append((item.material_out, item.batch, itemx.count, 0, itemx.defect, item))
# if item.material_out.tracking == Material.MA_TRACKING_SINGLE:
# # 获取所有主要的不合格项
# bw_qs = Mlogbw.objects.filter(mlogb=item)
@ -530,7 +534,7 @@ def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
for item in m_ins:
mbd_qs = MlogbDefect.get_defect_qs_from_mlogb(item)
for itemx in mbd_qs:
if itemx.defect:
if itemx.defect and itemx.count > 0:
m_ins_bl_list.append((item.material_in, item.batch, itemx.count, itemx.defect, item))
else:
m_ins_list = [(material_in, mlog.batch, mlog.count_use, mlog.wm_in, mlog)]