feat: mlog填写支持defect定义
This commit is contained in:
parent
5245689ec2
commit
9907bf7c43
|
@ -316,6 +316,25 @@ class Ftest(CommonBDModel):
|
|||
FtestDefect.objects.create(ftest=ftest, defect=defect)
|
||||
return ftest
|
||||
|
||||
# @classmethod
|
||||
# def cal_count_notok(cls, ftestwork: FtestWork):
|
||||
# count = Ftest.objects.filter(ftest_work=ftestwork).count()
|
||||
# mlogb.count_real = count
|
||||
# count_notok = 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))}
|
||||
# md_ids = []
|
||||
# for t in tqs_a:
|
||||
# md, _ = MlogbDefect.objects.get_or_create(mlogb=mlogb, defect=defects[t["ftest__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 FtestItem(BaseModel):
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 3.2.12 on 2025-03-03 09:08
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('qm', '0046_alter_testitem_description'),
|
||||
('wpm', '0090_mlogbdefect_floor'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='mlog',
|
||||
name='qct',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='qm.qct', verbose_name='所用质检表'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='mlogbdefect',
|
||||
name='count_test',
|
||||
field=models.IntegerField(blank=True, null=True, verbose_name='抽检数'),
|
||||
),
|
||||
]
|
|
@ -172,6 +172,7 @@ class Mlog(CommonADModel):
|
|||
fill_way = models.PositiveSmallIntegerField("填写方式", default=10, help_text='10:仅二级;20:二三级;30:一二级')
|
||||
mtype = models.PositiveSmallIntegerField('生产类型', default=10, help_text='10:自生产;20:外协生产', choices=((10, '自生产'), (20, '外协生产')))
|
||||
is_fix = models.BooleanField('是否用于返修', default=False)
|
||||
qct = models.ForeignKey("qm.qct", verbose_name='所用质检表', on_delete=models.SET_NULL, null=True, blank=True)
|
||||
supplier = models.ForeignKey(Supplier, verbose_name='外协供应商', on_delete=models.SET_NULL, null=True, blank=True)
|
||||
work_start_time = models.DateTimeField('生产开始时间', null=True, blank=True)
|
||||
work_end_time = models.DateTimeField('生产结束时间', null=True, blank=True)
|
||||
|
@ -288,7 +289,17 @@ class Mlog(CommonADModel):
|
|||
def audit_ignore_fields(self):
|
||||
return ['create_by', 'update_by',
|
||||
'create_time', 'update_time', 'id']
|
||||
|
||||
|
||||
@property
|
||||
def mlogdefect(self):
|
||||
return MlogbDefect.objects.filter(mlogb__mlog=self)
|
||||
|
||||
def cal_count_notok(self):
|
||||
count_notok = MlogbDefect.objects.filter(defect__okcate=30, mlogb__mlog=self).aggregate(total=Sum("count"))["total"] or 0
|
||||
self.count_notok = count_notok
|
||||
self.count_ok = self.count_real - count_notok
|
||||
self.save(update_fields=["count_ok", "count_notok"])
|
||||
|
||||
@classmethod
|
||||
def count_fields(cls):
|
||||
mlog_count_fields = []
|
||||
|
@ -363,10 +374,16 @@ class Mlogb(BaseModel):
|
|||
def mlogbdefect(self):
|
||||
return MlogbDefect.objects.filter(mlogb=self)
|
||||
|
||||
def cal_count_notok(self):
|
||||
count_notok = MlogbDefect.objects.filter(defect__okcate=30, mlogb=self).aggregate(total=Sum("count"))["total"] or 0
|
||||
self.count_notok = count_notok
|
||||
self.count_ok = self.count_real - count_notok
|
||||
self.save(update_fields=["count_ok", "count_notok"])
|
||||
|
||||
class MlogbDefect(BaseModel):
|
||||
mlogb = models.ForeignKey(Mlogb, verbose_name='生产记录', on_delete=models.CASCADE)
|
||||
defect = models.ForeignKey("qm.Defect", verbose_name='缺陷', on_delete=models.CASCADE)
|
||||
count_test = models.IntegerField("抽检数", null=True, blank=True)
|
||||
floor = models.IntegerField("层数", null=True, blank=True)
|
||||
count = models.PositiveIntegerField('数量', default=0)
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ from django.db import transaction
|
|||
from django.utils import timezone
|
||||
from django.core.cache import cache
|
||||
from django.utils.timezone import localdate
|
||||
from apps.qm.models import NotOkOption, Ftest
|
||||
from apps.qm.models import NotOkOption, Qct
|
||||
from apps.wf.serializers import TicketSimpleSerializer
|
||||
from apps.wpmw.models import Wpr
|
||||
from apps.qm.serializers import FtestProcessSerializer
|
||||
|
@ -202,12 +202,19 @@ class WMaterialSerializer(CustomModelSerializer):
|
|||
ret['count_cando'] = ret['count'] - ret['count_working']
|
||||
return ret
|
||||
|
||||
class MlogbDefectSerializer(CustomModelSerializer):
|
||||
defect_name = serializers.CharField(source="defect.name", read_only=True)
|
||||
class Meta:
|
||||
model = MlogbDefect
|
||||
fields = ["id", "defect_name", "count", "mlogb", "defect", "floor", "count_test"]
|
||||
read_only_fields = EXCLUDE_FIELDS_BASE + ["mlogb"]
|
||||
|
||||
class MlogbSerializer(CustomModelSerializer):
|
||||
material_out_ = MaterialSimpleSerializer(
|
||||
source='material_out', read_only=True)
|
||||
material_out_name = serializers.StringRelatedField(
|
||||
source='material_out', read_only=True)
|
||||
mlogbdefect = MlogbDefectSerializer(many=True)
|
||||
|
||||
class Meta:
|
||||
model = Mlogb
|
||||
|
@ -261,13 +268,6 @@ class MlogListSerializer(CustomModelSerializer):
|
|||
model = Mlog
|
||||
fields = '__all__'
|
||||
|
||||
class MlogbDefectSerializer(CustomModelSerializer):
|
||||
defect_name = serializers.CharField(source="defect.name", read_only=True)
|
||||
class Meta:
|
||||
model = MlogbDefect
|
||||
fields = ["id", "defect_name", "count", "mlogb", "defect", "floor"]
|
||||
read_only_fields = EXCLUDE_FIELDS_BASE + ["mlogb"]
|
||||
|
||||
|
||||
class MlogbDetailSerializer(CustomModelSerializer):
|
||||
material_out_name = serializers.StringRelatedField(
|
||||
|
@ -324,6 +324,7 @@ class MlogSerializer(CustomModelSerializer):
|
|||
ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
|
||||
test_user_name = serializers.CharField(source='test_user.name', read_only=True)
|
||||
|
||||
mlogdefect = MlogbDefectSerializer(many=True)
|
||||
class Meta:
|
||||
model = Mlog
|
||||
fields = '__all__'
|
||||
|
@ -338,6 +339,7 @@ class MlogSerializer(CustomModelSerializer):
|
|||
def create(self, validated_data):
|
||||
material_out = validated_data['material_out']
|
||||
mtask:Mtask = validated_data.get('mtask', None)
|
||||
mlogdefect = validated_data.pop('mlogdefect', [])
|
||||
if mtask and mtask.state != Mtask.MTASK_ASSGINED:
|
||||
raise ParseError('该任务非下达中不可选择')
|
||||
with transaction.atomic():
|
||||
|
@ -393,13 +395,25 @@ class MlogSerializer(CustomModelSerializer):
|
|||
'count_ok': instance.count_ok, 'count_notok': instance.count_notok,
|
||||
'count_break_t': instance.count_break_t
|
||||
}
|
||||
for f in Mlogb._meta.fields:
|
||||
if 'count_n_' in f.name:
|
||||
add_dict_2[f.name] = getattr(instance, f.name)
|
||||
need_mdfect = False
|
||||
if instance.qct or mlogdefect:
|
||||
need_mdfect = True
|
||||
else:
|
||||
for f in Mlogb._meta.fields:
|
||||
if 'count_n_' in f.name:
|
||||
add_dict_2[f.name] = getattr(instance, f.name)
|
||||
ddict = {}
|
||||
if wm_in:
|
||||
ddict = {"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom}
|
||||
Mlogb.objects.get_or_create(**add_dict_2, defaults=ddict)
|
||||
mlogb, _ = Mlogb.objects.get_or_create(**add_dict_2, defaults=ddict)
|
||||
if need_mdfect:
|
||||
mlogb_defect_objects = [
|
||||
MlogbDefect(**{**item, "mlogb": mlogb})
|
||||
for item in mlogdefect if item["count"] > 0
|
||||
]
|
||||
if mlogb_defect_objects:
|
||||
MlogbDefect.objects.bulk_create(mlogb_defect_objects)
|
||||
instance.cal_count_notok()
|
||||
return instance
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
|
@ -407,6 +421,7 @@ class MlogSerializer(CustomModelSerializer):
|
|||
raise ParseError('不支持的填写类型')
|
||||
validated_data.pop('mtask', None)
|
||||
validated_data.pop('mgroup', None)
|
||||
mlogdefect = validated_data.pop('mlogdefect', [])
|
||||
if instance.mtask:
|
||||
validated_data.pop('handle_date', None)
|
||||
# validated_data.pop('handle_user', None)
|
||||
|
@ -463,11 +478,24 @@ class MlogSerializer(CustomModelSerializer):
|
|||
if wm_in:
|
||||
mox.batch_ofrom = wm_in.batch
|
||||
mox.material_ofrom = wm_in.material_ofrom
|
||||
for f in Mlogb._meta.fields:
|
||||
if 'count_n_' in f.name:
|
||||
setattr(mox, f.name, getattr(instance, f.name))
|
||||
need_mdefect=False
|
||||
if instance.qct or mlogdefect:
|
||||
need_mdefect = True
|
||||
else:
|
||||
for f in Mlogb._meta.fields:
|
||||
if 'count_n_' in f.name:
|
||||
setattr(mox, f.name, getattr(instance, f.name))
|
||||
mox.save()
|
||||
Mlogb.objects.filter(mlog=instance, material_out__isnull=False).exclude(id=mox.id).delete()
|
||||
if need_mdefect:
|
||||
MlogbDefect.objects.filter(mlogb__mlog=instance).delete()
|
||||
mlogb_defect_objects = [
|
||||
MlogbDefect(**{**item, "mlogb": mlogb})
|
||||
for item in mlogdefect if item["count"] > 0
|
||||
]
|
||||
if mlogb_defect_objects:
|
||||
MlogbDefect.objects.bulk_create(mlogb_defect_objects)
|
||||
instance.cal_count_notok()
|
||||
return instance
|
||||
|
||||
def validate(self, attrs):
|
||||
|
@ -576,6 +604,8 @@ class MlogInitSerializer(CustomModelSerializer):
|
|||
raise ParseError('外协必须选择外协单位')
|
||||
if attrs.get('work_end_time', None):
|
||||
attrs['handle_date'] = localdate(attrs['work_end_time'])
|
||||
if attrs["material_out"]:
|
||||
attrs["qct"] = Qct.get(attrs["material_out"], "process")
|
||||
return attrs
|
||||
|
||||
class MlogChangeSerializer(CustomModelSerializer):
|
||||
|
@ -726,27 +756,20 @@ class MlogbOutUpdateSerializer(CustomModelSerializer):
|
|||
# else:
|
||||
# raise ParseError("mlogbdefect仅支持批次件")
|
||||
# return ins
|
||||
|
||||
@transaction.atomic
|
||||
def update(self, instance, validated_data):
|
||||
mlogbdefect = validated_data.pop("mlogbdefect", [])
|
||||
with transaction.atomic():
|
||||
ins:Mlogb = super().update(instance, validated_data)
|
||||
if (instance.qct or mlogbdefect) and instance.material_out.tracking == Material.MA_TRACKING_BATCH:
|
||||
count_notok = 0
|
||||
md_ids = []
|
||||
for item in mlogbdefect:
|
||||
defect:Defect = item["defect"]
|
||||
if item["count"] > 0:
|
||||
insb, _ = MlogbDefect.objects.get_or_create(mlogb=ins, defect=defect, floor=item.get('floor', None))
|
||||
insb.count = item["count"]
|
||||
insb.save(update_fields=["count"])
|
||||
if defect.okcate == Defect.DEFECT_NOTOK:
|
||||
count_notok += item["count"]
|
||||
md_ids.append(insb.id)
|
||||
MlogbDefect.objects.filter(mlogb=ins).exclude(id__in=md_ids).delete()
|
||||
ins.count_notok = count_notok
|
||||
ins.count_ok = ins.count_real - ins.count_notok
|
||||
ins.save()
|
||||
if (ins.qct or mlogbdefect) and ins.material_out.tracking == Material.MA_TRACKING_BATCH:
|
||||
MlogbDefect.objects.filter(mlogb=ins).delete()
|
||||
mlogb_defect_objects = [
|
||||
MlogbDefect(**{**item, "mlogb": ins})
|
||||
for item in mlogbdefect if item["count"] > 0
|
||||
]
|
||||
if mlogb_defect_objects:
|
||||
MlogbDefect.objects.bulk_create(mlogb_defect_objects)
|
||||
ins.cal_count_notok()
|
||||
return ins
|
||||
|
||||
def validate(self, attrs):
|
||||
|
|
|
@ -596,7 +596,7 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
|
|||
# 如果是生产返修,则忽略质检
|
||||
pass
|
||||
elif mlogbout.qct is None:
|
||||
mlogbout.qct = Qct.get(mlogbout.material_out, "process")
|
||||
mlogbout.qct = Qct.get(mlogbout.material_out, "process") if mlog.qct is None else mlog.qct
|
||||
mlogbout.count_real = d_count_real
|
||||
mlogbout.count_ok = d_count_ok
|
||||
mlogbout.save()
|
||||
|
@ -628,11 +628,11 @@ class MlogbOutViewSet(UpdateModelMixin, CustomGenericViewSet):
|
|||
serializer_class = MlogbOutUpdateSerializer
|
||||
|
||||
|
||||
class FmlogViewSet(CustomModelViewSet):
|
||||
class FmlogViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyModelMixin, CustomGenericViewSet):
|
||||
perms_map = {'get': '*', 'post': 'mlog.create', 'put': 'mlog.update', 'delete': 'mlog.delete'}
|
||||
queryset = Fmlog.objects.all()
|
||||
serializer_class = FmlogSerializer
|
||||
update_serializer_class = FmlogUpdateSerializer
|
||||
# update_serializer_class = FmlogUpdateSerializer
|
||||
filterset_fields = ['mtask', 'mgroup', 'mtask__route']
|
||||
select_related_fields = ['mtask', 'mgroup', 'mtask__route', 'mtask__route__routepack']
|
||||
|
||||
|
|
Loading…
Reference in New Issue