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)
|
FtestDefect.objects.create(ftest=ftest, defect=defect)
|
||||||
return ftest
|
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):
|
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:一二级')
|
fill_way = models.PositiveSmallIntegerField("填写方式", default=10, help_text='10:仅二级;20:二三级;30:一二级')
|
||||||
mtype = models.PositiveSmallIntegerField('生产类型', default=10, help_text='10:自生产;20:外协生产', choices=((10, '自生产'), (20, '外协生产')))
|
mtype = models.PositiveSmallIntegerField('生产类型', default=10, help_text='10:自生产;20:外协生产', choices=((10, '自生产'), (20, '外协生产')))
|
||||||
is_fix = models.BooleanField('是否用于返修', default=False)
|
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)
|
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_start_time = models.DateTimeField('生产开始时间', null=True, blank=True)
|
||||||
work_end_time = models.DateTimeField('生产结束时间', null=True, blank=True)
|
work_end_time = models.DateTimeField('生产结束时间', null=True, blank=True)
|
||||||
|
@ -289,6 +290,16 @@ class Mlog(CommonADModel):
|
||||||
return ['create_by', 'update_by',
|
return ['create_by', 'update_by',
|
||||||
'create_time', 'update_time', 'id']
|
'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
|
@classmethod
|
||||||
def count_fields(cls):
|
def count_fields(cls):
|
||||||
mlog_count_fields = []
|
mlog_count_fields = []
|
||||||
|
@ -363,10 +374,16 @@ class Mlogb(BaseModel):
|
||||||
def mlogbdefect(self):
|
def mlogbdefect(self):
|
||||||
return MlogbDefect.objects.filter(mlogb=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):
|
class MlogbDefect(BaseModel):
|
||||||
mlogb = models.ForeignKey(Mlogb, verbose_name='生产记录', on_delete=models.CASCADE)
|
mlogb = models.ForeignKey(Mlogb, verbose_name='生产记录', on_delete=models.CASCADE)
|
||||||
defect = models.ForeignKey("qm.Defect", 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)
|
floor = models.IntegerField("层数", null=True, blank=True)
|
||||||
count = models.PositiveIntegerField('数量', default=0)
|
count = models.PositiveIntegerField('数量', default=0)
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ from django.db import transaction
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.utils.timezone import localdate
|
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.wf.serializers import TicketSimpleSerializer
|
||||||
from apps.wpmw.models import Wpr
|
from apps.wpmw.models import Wpr
|
||||||
from apps.qm.serializers import FtestProcessSerializer
|
from apps.qm.serializers import FtestProcessSerializer
|
||||||
|
@ -202,12 +202,19 @@ class WMaterialSerializer(CustomModelSerializer):
|
||||||
ret['count_cando'] = ret['count'] - ret['count_working']
|
ret['count_cando'] = ret['count'] - ret['count_working']
|
||||||
return ret
|
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):
|
class MlogbSerializer(CustomModelSerializer):
|
||||||
material_out_ = MaterialSimpleSerializer(
|
material_out_ = MaterialSimpleSerializer(
|
||||||
source='material_out', read_only=True)
|
source='material_out', read_only=True)
|
||||||
material_out_name = serializers.StringRelatedField(
|
material_out_name = serializers.StringRelatedField(
|
||||||
source='material_out', read_only=True)
|
source='material_out', read_only=True)
|
||||||
|
mlogbdefect = MlogbDefectSerializer(many=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Mlogb
|
model = Mlogb
|
||||||
|
@ -261,13 +268,6 @@ class MlogListSerializer(CustomModelSerializer):
|
||||||
model = Mlog
|
model = Mlog
|
||||||
fields = '__all__'
|
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):
|
class MlogbDetailSerializer(CustomModelSerializer):
|
||||||
material_out_name = serializers.StringRelatedField(
|
material_out_name = serializers.StringRelatedField(
|
||||||
|
@ -324,6 +324,7 @@ class MlogSerializer(CustomModelSerializer):
|
||||||
ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
|
ticket_ = TicketSimpleSerializer(source='ticket', read_only=True)
|
||||||
test_user_name = serializers.CharField(source='test_user.name', read_only=True)
|
test_user_name = serializers.CharField(source='test_user.name', read_only=True)
|
||||||
|
|
||||||
|
mlogdefect = MlogbDefectSerializer(many=True)
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Mlog
|
model = Mlog
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
|
@ -338,6 +339,7 @@ class MlogSerializer(CustomModelSerializer):
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
material_out = validated_data['material_out']
|
material_out = validated_data['material_out']
|
||||||
mtask:Mtask = validated_data.get('mtask', None)
|
mtask:Mtask = validated_data.get('mtask', None)
|
||||||
|
mlogdefect = validated_data.pop('mlogdefect', [])
|
||||||
if mtask and mtask.state != Mtask.MTASK_ASSGINED:
|
if mtask and mtask.state != Mtask.MTASK_ASSGINED:
|
||||||
raise ParseError('该任务非下达中不可选择')
|
raise ParseError('该任务非下达中不可选择')
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
@ -393,13 +395,25 @@ class MlogSerializer(CustomModelSerializer):
|
||||||
'count_ok': instance.count_ok, 'count_notok': instance.count_notok,
|
'count_ok': instance.count_ok, 'count_notok': instance.count_notok,
|
||||||
'count_break_t': instance.count_break_t
|
'count_break_t': instance.count_break_t
|
||||||
}
|
}
|
||||||
|
need_mdfect = False
|
||||||
|
if instance.qct or mlogdefect:
|
||||||
|
need_mdfect = True
|
||||||
|
else:
|
||||||
for f in Mlogb._meta.fields:
|
for f in Mlogb._meta.fields:
|
||||||
if 'count_n_' in f.name:
|
if 'count_n_' in f.name:
|
||||||
add_dict_2[f.name] = getattr(instance, f.name)
|
add_dict_2[f.name] = getattr(instance, f.name)
|
||||||
ddict = {}
|
ddict = {}
|
||||||
if wm_in:
|
if wm_in:
|
||||||
ddict = {"batch_ofrom": wm_in.batch_ofrom, "material_ofrom": wm_in.material_ofrom}
|
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
|
return instance
|
||||||
|
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
|
@ -407,6 +421,7 @@ class MlogSerializer(CustomModelSerializer):
|
||||||
raise ParseError('不支持的填写类型')
|
raise ParseError('不支持的填写类型')
|
||||||
validated_data.pop('mtask', None)
|
validated_data.pop('mtask', None)
|
||||||
validated_data.pop('mgroup', None)
|
validated_data.pop('mgroup', None)
|
||||||
|
mlogdefect = validated_data.pop('mlogdefect', [])
|
||||||
if instance.mtask:
|
if instance.mtask:
|
||||||
validated_data.pop('handle_date', None)
|
validated_data.pop('handle_date', None)
|
||||||
# validated_data.pop('handle_user', None)
|
# validated_data.pop('handle_user', None)
|
||||||
|
@ -463,11 +478,24 @@ class MlogSerializer(CustomModelSerializer):
|
||||||
if wm_in:
|
if wm_in:
|
||||||
mox.batch_ofrom = wm_in.batch
|
mox.batch_ofrom = wm_in.batch
|
||||||
mox.material_ofrom = wm_in.material_ofrom
|
mox.material_ofrom = wm_in.material_ofrom
|
||||||
|
need_mdefect=False
|
||||||
|
if instance.qct or mlogdefect:
|
||||||
|
need_mdefect = True
|
||||||
|
else:
|
||||||
for f in Mlogb._meta.fields:
|
for f in Mlogb._meta.fields:
|
||||||
if 'count_n_' in f.name:
|
if 'count_n_' in f.name:
|
||||||
setattr(mox, f.name, getattr(instance, f.name))
|
setattr(mox, f.name, getattr(instance, f.name))
|
||||||
mox.save()
|
mox.save()
|
||||||
Mlogb.objects.filter(mlog=instance, material_out__isnull=False).exclude(id=mox.id).delete()
|
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
|
return instance
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
|
@ -576,6 +604,8 @@ class MlogInitSerializer(CustomModelSerializer):
|
||||||
raise ParseError('外协必须选择外协单位')
|
raise ParseError('外协必须选择外协单位')
|
||||||
if attrs.get('work_end_time', None):
|
if attrs.get('work_end_time', None):
|
||||||
attrs['handle_date'] = localdate(attrs['work_end_time'])
|
attrs['handle_date'] = localdate(attrs['work_end_time'])
|
||||||
|
if attrs["material_out"]:
|
||||||
|
attrs["qct"] = Qct.get(attrs["material_out"], "process")
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
class MlogChangeSerializer(CustomModelSerializer):
|
class MlogChangeSerializer(CustomModelSerializer):
|
||||||
|
@ -726,27 +756,20 @@ class MlogbOutUpdateSerializer(CustomModelSerializer):
|
||||||
# else:
|
# else:
|
||||||
# raise ParseError("mlogbdefect仅支持批次件")
|
# raise ParseError("mlogbdefect仅支持批次件")
|
||||||
# return ins
|
# return ins
|
||||||
|
@transaction.atomic
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
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)
|
||||||
if (instance.qct or mlogbdefect) and instance.material_out.tracking == Material.MA_TRACKING_BATCH:
|
if (ins.qct or mlogbdefect) and ins.material_out.tracking == Material.MA_TRACKING_BATCH:
|
||||||
count_notok = 0
|
MlogbDefect.objects.filter(mlogb=ins).delete()
|
||||||
md_ids = []
|
mlogb_defect_objects = [
|
||||||
for item in mlogbdefect:
|
MlogbDefect(**{**item, "mlogb": ins})
|
||||||
defect:Defect = item["defect"]
|
for item in mlogbdefect if item["count"] > 0
|
||||||
if item["count"] > 0:
|
]
|
||||||
insb, _ = MlogbDefect.objects.get_or_create(mlogb=ins, defect=defect, floor=item.get('floor', None))
|
if mlogb_defect_objects:
|
||||||
insb.count = item["count"]
|
MlogbDefect.objects.bulk_create(mlogb_defect_objects)
|
||||||
insb.save(update_fields=["count"])
|
ins.cal_count_notok()
|
||||||
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()
|
|
||||||
return ins
|
return ins
|
||||||
|
|
||||||
def validate(self, attrs):
|
def validate(self, attrs):
|
||||||
|
|
|
@ -596,7 +596,7 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
|
||||||
# 如果是生产返修,则忽略质检
|
# 如果是生产返修,则忽略质检
|
||||||
pass
|
pass
|
||||||
elif mlogbout.qct is None:
|
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_real = d_count_real
|
||||||
mlogbout.count_ok = d_count_ok
|
mlogbout.count_ok = d_count_ok
|
||||||
mlogbout.save()
|
mlogbout.save()
|
||||||
|
@ -628,11 +628,11 @@ class MlogbOutViewSet(UpdateModelMixin, CustomGenericViewSet):
|
||||||
serializer_class = MlogbOutUpdateSerializer
|
serializer_class = MlogbOutUpdateSerializer
|
||||||
|
|
||||||
|
|
||||||
class FmlogViewSet(CustomModelViewSet):
|
class FmlogViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyModelMixin, CustomGenericViewSet):
|
||||||
perms_map = {'get': '*', 'post': 'mlog.create', 'put': 'mlog.update', 'delete': 'mlog.delete'}
|
perms_map = {'get': '*', 'post': 'mlog.create', 'put': 'mlog.update', 'delete': 'mlog.delete'}
|
||||||
queryset = Fmlog.objects.all()
|
queryset = Fmlog.objects.all()
|
||||||
serializer_class = FmlogSerializer
|
serializer_class = FmlogSerializer
|
||||||
update_serializer_class = FmlogUpdateSerializer
|
# update_serializer_class = FmlogUpdateSerializer
|
||||||
filterset_fields = ['mtask', 'mgroup', 'mtask__route']
|
filterset_fields = ['mtask', 'mgroup', 'mtask__route']
|
||||||
select_related_fields = ['mtask', 'mgroup', 'mtask__route', 'mtask__route__routepack']
|
select_related_fields = ['mtask', 'mgroup', 'mtask__route', 'mtask__route__routepack']
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue