feat: 批次处理做兼容性处理
This commit is contained in:
parent
77f7a454a1
commit
286a5306e3
|
@ -151,7 +151,7 @@ QC_TRACE_CHOICES = (
|
||||||
class Qct(CommonAModel):
|
class Qct(CommonAModel):
|
||||||
name = models.CharField(max_length=50, verbose_name="名称")
|
name = models.CharField(max_length=50, verbose_name="名称")
|
||||||
number = models.CharField(max_length=20, verbose_name="编号")
|
number = models.CharField(max_length=20, verbose_name="编号")
|
||||||
tags = models.JSONField('检测类型', default=list, blank=True)
|
tags = models.JSONField('检测类型', default=list, blank=True) # process 和 inm
|
||||||
testitems = models.ManyToManyField(TestItem, verbose_name="检测项", blank=True, through='qm.qcttestitem')
|
testitems = models.ManyToManyField(TestItem, verbose_name="检测项", blank=True, through='qm.qcttestitem')
|
||||||
defects = models.ManyToManyField(Defect, verbose_name="缺陷项", blank=True, through='qm.qctdefect')
|
defects = models.ManyToManyField(Defect, verbose_name="缺陷项", blank=True, through='qm.qctdefect')
|
||||||
materials = models.ManyToManyField(Material, verbose_name="物料", blank=True, through='qm.qctmat')
|
materials = models.ManyToManyField(Material, verbose_name="物料", blank=True, through='qm.qctmat')
|
||||||
|
|
|
@ -382,6 +382,26 @@ class Mlogbw(BaseModel):
|
||||||
on_delete=models.PROTECT, null=True, blank=True, related_name="mlogbw_ftest")
|
on_delete=models.PROTECT, null=True, blank=True, related_name="mlogbw_ftest")
|
||||||
note = models.TextField('备注', null=True, blank=True)
|
note = models.TextField('备注', null=True, blank=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def cal_count_notok(mlogb: Mlog):
|
||||||
|
count = Mlogbw.objects.filter(mlogb=mlogb).count()
|
||||||
|
if mlogb.material_in:
|
||||||
|
mlogb.count_use = count
|
||||||
|
elif mlogb.material_out:
|
||||||
|
mlogb.count_real = count
|
||||||
|
count_notok = 0
|
||||||
|
tqs = Mlogbw.objects.filter(mlogb=mlogb, ftest__is_ok=False).values("defect_main").annotate(xcount=Count('id'))
|
||||||
|
md_ids = []
|
||||||
|
for t in tqs:
|
||||||
|
md, _ = MlogbDefect.objects.get_or_create(mlogb=mlogb, defect=t["defect_main"])
|
||||||
|
md.count = t["xcount"]
|
||||||
|
md.save()
|
||||||
|
md_ids.append(md.id)
|
||||||
|
count_notok += t["xcount"]
|
||||||
|
MlogbDefect.objects.filter(mlogb=mlogb).exclude(id__in=md_ids).delete()
|
||||||
|
mlogb.count_notok = count_notok
|
||||||
|
mlogb.count_ok = count - mlogb.count_notok
|
||||||
|
mlogb.save()
|
||||||
|
|
||||||
class Handover(CommonADModel):
|
class Handover(CommonADModel):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -724,7 +724,7 @@ class MlogbOutUpdateSerializer(CustomModelSerializer):
|
||||||
return ins
|
return ins
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
material_out:Material = validated_data["material_out"]
|
material_out:Material = instance.material_out
|
||||||
mlogbdefect = validated_data.pop("mlogbdefect", [])
|
mlogbdefect = validated_data.pop("mlogbdefect", [])
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
ins:Mlogb = super().update(instance, validated_data)
|
ins:Mlogb = super().update(instance, validated_data)
|
||||||
|
|
|
@ -11,7 +11,7 @@ from apps.system.models import User
|
||||||
from apps.pm.models import Mtask
|
from apps.pm.models import Mtask
|
||||||
from apps.mtm.models import Mgroup, Shift, Material, Route, RoutePack, Team, Srule
|
from apps.mtm.models import Mgroup, Shift, Material, Route, RoutePack, Team, Srule
|
||||||
|
|
||||||
from .models import SfLog, WMaterial, Mlog, Mlogb, Mlogbw, Handover, Handoverb, Handoverbw
|
from .models import SfLog, WMaterial, Mlog, Mlogb, Mlogbw, Handover, Handoverb, Handoverbw, MlogbDefect
|
||||||
from apps.mtm.services_2 import cal_material_count
|
from apps.mtm.services_2 import cal_material_count
|
||||||
from apps.wf.models import Ticket
|
from apps.wf.models import Ticket
|
||||||
from apps.utils.thread import MyThread
|
from apps.utils.thread import MyThread
|
||||||
|
@ -233,29 +233,35 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
|
||||||
process = mgroup.process
|
process = mgroup.process
|
||||||
into_wm_mgroup = process.into_wm_mgroup
|
into_wm_mgroup = process.into_wm_mgroup
|
||||||
need_store_notok = process.store_notok
|
need_store_notok = process.store_notok
|
||||||
m_outs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False)
|
mlogb_out_qs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False)
|
||||||
stored_notok = need_store_notok
|
stored_notok = need_store_notok
|
||||||
stored_mgroup = need_store_notok
|
stored_mgroup = need_store_notok
|
||||||
if m_outs.exists():
|
if mlogb_out_qs.exists():
|
||||||
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()]
|
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 mlogb_out_qs.all()]
|
||||||
if need_store_notok:
|
if need_store_notok:
|
||||||
for item in m_outs:
|
for item in mlogb_out_qs:
|
||||||
if item.material_out.tracking == Material.MA_TRACKING_SINGLE:
|
if item.qct is not None:
|
||||||
# 获取所有主要的不合格项
|
if MlogbDefect.objects.filter(mlogb=item).exists():
|
||||||
bw_qs = Mlogbw.objects.filter(mlogb=item)
|
pass
|
||||||
defectIds= Ftest.objects.filter(mlogbw_ftest__in=bw_qs).exclude(defect_main=None).values_list("defect_main__id", flat=True).distinct()
|
else:
|
||||||
defects_map = {d.id: d for d in Defect.objects.filter(id__in=defectIds)}
|
Mlogbw.cal_count_notok(item)
|
||||||
# 过滤并统计相关数据
|
for itemx in MlogbDefect.objects.filter(mlogb=item):
|
||||||
filtered_bw_qs = bw_qs.filter(
|
m_outs_list.append((item.material_out, item.batch, itemx.count, 0, itemx.defect, item))
|
||||||
ftest__defect_main__id__in=defects_map.keys()
|
# # 获取所有主要的不合格项/先暂时保留
|
||||||
).values('ftest__defect_main__id').annotate(xcount=Count('id'))
|
# 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()
|
||||||
for defect_data in filtered_bw_qs:
|
# defects_map = {d.id: d for d in Defect.objects.filter(id__in=defectIds)}
|
||||||
defect_id = defect_data['ftest__defect_main__id']
|
# # 过滤并统计相关数据
|
||||||
xcount = defect_data['xcount']
|
# filtered_bw_qs = bw_qs.filter(
|
||||||
if xcount > 0:
|
# ftest__defect_main__id__in=defects_map.keys()
|
||||||
defect = defects_map[defect_id]
|
# ).values('ftest__defect_main__id').annotate(xcount=Count('id'))
|
||||||
m_outs_list.append((item.material_out, item.batch, xcount, 0, defect, item))
|
# # 整理结果
|
||||||
|
# for defect_data in filtered_bw_qs:
|
||||||
|
# defect_id = defect_data['ftest__defect_main__id']
|
||||||
|
# xcount = defect_data['xcount']
|
||||||
|
# if xcount > 0:
|
||||||
|
# defect = defects_map[defect_id]
|
||||||
|
# m_outs_list.append((item.material_out, item.batch, xcount, 0, defect, item))
|
||||||
else:
|
else:
|
||||||
for f in Mlogb._meta.fields:
|
for f in Mlogb._meta.fields:
|
||||||
if 'count_n_' in f.name and getattr(item, f.name) > 0:
|
if 'count_n_' in f.name and getattr(item, f.name) > 0:
|
||||||
|
@ -358,29 +364,36 @@ def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
|
||||||
if material_out or is_fix: # 产物退回
|
if material_out or is_fix: # 产物退回
|
||||||
# 有多个产物的情况
|
# 有多个产物的情况
|
||||||
# 需要考虑不合格品退回的情况
|
# 需要考虑不合格品退回的情况
|
||||||
m_outs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False)
|
mlogb_out_qs = Mlogb.objects.filter(mlog=mlog, material_out__isnull=False)
|
||||||
if m_outs.exists():
|
if mlogb_out_qs.exists():
|
||||||
m_outs_list = [
|
m_outs_list = [
|
||||||
(mo.material_out, mo.batch if mo.batch else mlog.batch, mo.count_ok, mlog.count_real_eweight, None, mo)
|
(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()]
|
for mo in mlogb_out_qs.all()]
|
||||||
if stored_notok:
|
if stored_notok:
|
||||||
for item in m_outs:
|
for item in mlogb_out_qs:
|
||||||
if item.material_out.tracking == Material.MA_TRACKING_SINGLE:
|
if item.qct is not None:
|
||||||
# 获取所有主要的不合格项
|
if MlogbDefect.objects.filter(mlogb=item).exists():
|
||||||
bw_qs = Mlogbw.objects.filter(mlogb=item)
|
pass
|
||||||
defectIds= Ftest.objects.filter(mlogbw_ftest__in=bw_qs).exclude(defect_main=None).values_list("defect_main__id", flat=True).distinct()
|
else:
|
||||||
defects_map = {d.id: d for d in Defect.objects.filter(id__in=defectIds)}
|
Mlogbw.cal_count_notok(item)
|
||||||
# 过滤并统计相关数据
|
for itemx in MlogbDefect.objects.filter(mlogb=item):
|
||||||
filtered_bw_qs = bw_qs.filter(
|
m_outs_list.append((item.material_out, item.batch, itemx.count, 0, itemx.defect, item))
|
||||||
ftest__defect_main__id__in=defects_map.keys()
|
# if item.material_out.tracking == Material.MA_TRACKING_SINGLE:
|
||||||
).values('ftest__defect_main__id').annotate(xcount=Count('id'))
|
# # 获取所有主要的不合格项
|
||||||
# 整理结果
|
# bw_qs = Mlogbw.objects.filter(mlogb=item)
|
||||||
for defect_data in filtered_bw_qs:
|
# defectIds= Ftest.objects.filter(mlogbw_ftest__in=bw_qs).exclude(defect_main=None).values_list("defect_main__id", flat=True).distinct()
|
||||||
defect_id = defect_data['ftest__defect_main__id']
|
# defects_map = {d.id: d for d in Defect.objects.filter(id__in=defectIds)}
|
||||||
xcount = defect_data['xcount']
|
# # 过滤并统计相关数据
|
||||||
if xcount > 0:
|
# filtered_bw_qs = bw_qs.filter(
|
||||||
defect = defects_map[defect_id]
|
# ftest__defect_main__id__in=defects_map.keys()
|
||||||
m_outs_list.append((item.material_out, item.batch, xcount, 0, defect, item))
|
# ).values('ftest__defect_main__id').annotate(xcount=Count('id'))
|
||||||
|
# # 整理结果
|
||||||
|
# for defect_data in filtered_bw_qs:
|
||||||
|
# defect_id = defect_data['ftest__defect_main__id']
|
||||||
|
# xcount = defect_data['xcount']
|
||||||
|
# if xcount > 0:
|
||||||
|
# defect = defects_map[defect_id]
|
||||||
|
# m_outs_list.append((item.material_out, item.batch, xcount, 0, defect, item))
|
||||||
else:
|
else:
|
||||||
for f in Mlogb._meta.fields:
|
for f in Mlogb._meta.fields:
|
||||||
if 'count_n_' in f.name and getattr(item, f.name) > 0:
|
if 'count_n_' in f.name and getattr(item, f.name) > 0:
|
||||||
|
|
|
@ -592,13 +592,17 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
|
||||||
d_count_real = mlogbin.count_use
|
d_count_real = mlogbin.count_use
|
||||||
d_count_ok = mlogbin.count_use
|
d_count_ok = mlogbin.count_use
|
||||||
# 找寻质检表
|
# 找寻质检表
|
||||||
if material_out.tracking == Material.MA_TRACKING_SINGLE:
|
if is_fix and mgroup.process.type == Process.PRO_PROD:
|
||||||
if is_fix and mgroup.process.type == Process.PRO_PROD:
|
# 如果是生产返修,则忽略质检
|
||||||
# 如果是生产返修,则忽略质检
|
pass
|
||||||
pass
|
elif mlogbout.qct:
|
||||||
else:
|
try:
|
||||||
qctmat = QctMat.objects.filter(material=material_out, qct__is_deleted=False).order_by("-create_time").first()
|
qctmat = QctMat.objects.get(material=material_out, qct__is_deleted=False, qct__tags__contains="process").order_by("-create_time")
|
||||||
mlogbout.qct = qctmat.qct if qctmat else None
|
except QctMat.DoesNotExist:
|
||||||
|
qctmat = None
|
||||||
|
except QctMat.MultipleObjectsReturned:
|
||||||
|
raise ParseError("存在多个质检表,请手动选择")
|
||||||
|
mlogbout.qct = qctmat.qct if qctmat else None
|
||||||
mlogbout.count_real = d_count_real
|
mlogbout.count_real = d_count_real
|
||||||
mlogbout.count_ok = d_count_ok
|
mlogbout.count_ok = d_count_ok
|
||||||
mlogbout.save()
|
mlogbout.save()
|
||||||
|
@ -672,27 +676,6 @@ class MlogbwViewSet(CustomModelViewSet):
|
||||||
raise ParseError('请指定所属消耗/产出明细')
|
raise ParseError('请指定所属消耗/产出明细')
|
||||||
return super().filter_queryset(queryset)
|
return super().filter_queryset(queryset)
|
||||||
|
|
||||||
def cal_mlogb_count(self, mlogb):
|
|
||||||
count = Mlogbw.objects.filter(mlogb=mlogb).count()
|
|
||||||
# 此处先不管检验问题
|
|
||||||
if mlogb.material_in:
|
|
||||||
mlogb.count_use = count
|
|
||||||
elif mlogb.material_out:
|
|
||||||
mlogb.count_real = count
|
|
||||||
count_notok = 0
|
|
||||||
tqs = Mlogbw.objects.filter(mlogb=mlogb, ftest__is_ok=False).values("defect_main").annotate(xcount=Count('id'))
|
|
||||||
md_ids = []
|
|
||||||
for t in tqs:
|
|
||||||
md, _ = MlogbDefect.objects.get_or_create(mlogb=mlogb, defect=t["defect_main"])
|
|
||||||
md.count = t["xcount"]
|
|
||||||
md.save()
|
|
||||||
md_ids.append(md.id)
|
|
||||||
count_notok += t["xcount"]
|
|
||||||
MlogbDefect.objects.filter(mlogb=mlogb).exclude(id__in=md_ids).delete()
|
|
||||||
mlogb.count_notok = count_notok
|
|
||||||
mlogb.count_ok = count - mlogb.count_notok
|
|
||||||
mlogb.save()
|
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def perform_create(self, serializer):
|
def perform_create(self, serializer):
|
||||||
ins:Mlogbw = serializer.save()
|
ins:Mlogbw = serializer.save()
|
||||||
|
@ -715,7 +698,7 @@ class MlogbwViewSet(CustomModelViewSet):
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def perform_update(self, serializer):
|
def perform_update(self, serializer):
|
||||||
mlogbw = serializer.save()
|
mlogbw = serializer.save()
|
||||||
self.cal_mlogb_count(mlogbw.mlogb)
|
Mlogbw.cal_count_notok(mlogbw.mlogb)
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def perform_destroy(self, instance:Mlogbw):
|
def perform_destroy(self, instance:Mlogbw):
|
||||||
|
@ -736,4 +719,4 @@ class MlogbwViewSet(CustomModelViewSet):
|
||||||
mbws = Mlogbw.objects.filter(Q(wpr=instance.wpr)|Q(number__contains=instance.number), mlogb=mlogb_to)
|
mbws = Mlogbw.objects.filter(Q(wpr=instance.wpr)|Q(number__contains=instance.number), mlogb=mlogb_to)
|
||||||
Ftest.objects.filter(id__in=mbws.values_list('ftest__id', flat=True)).delete()
|
Ftest.objects.filter(id__in=mbws.values_list('ftest__id', flat=True)).delete()
|
||||||
mbws.delete()
|
mbws.delete()
|
||||||
self.cal_mlogb_count(mlogb_to)
|
Mlogbw.cal_count_notok(mlogb)
|
||||||
|
|
Loading…
Reference in New Issue