This commit is contained in:
zty 2025-01-09 13:36:58 +08:00
commit 4a3934b4fd
8 changed files with 47 additions and 115 deletions

View File

@ -235,6 +235,20 @@ class FtestWork(CommonBDModel):
ftestwork_count_fields.append(f.name)
return ftestwork_count_fields
# def cal_count(self):
# self.count_notok = FtestworkDefect.objects.filter(
# mlogb=self, defect__okcate=30).aggregate(total=Sum("count"))["total"] or 0
# self.count_ok = self.count_real - self.count_notok
# if self.count_ok < 0:
# raise ParseError('合格数量不能小于0')
# self.save(update_fields=['count_ok', 'count_notok'])
# class FtestworkDefect(BaseModel):
# ftestwork = models.ForeignKey(FtestWork, verbose_name='关联检验工作', on_delete=models.CASCADE,
# related_name='ftestwork_defect')
# defect = models.ForeignKey(Defect, verbose_name='缺陷', on_delete=models.CASCADE)
# count = models.PositiveIntegerField('数量', default=0)
class Ftest(CommonBDModel):
"""
检验记录

View File

@ -4,7 +4,7 @@ from apps.qm.models import (QuaStat, TestItem, Ftest, FtestItem, FtestWork, Ptes
from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
from apps.utils.serializers import CustomModelSerializer
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.exceptions import ValidationError, ParseError
from apps.wpm.models import SfLog, WMaterial
from django.db import transaction
from apps.inm.serializers import MaterialBatchDetailSerializer
@ -270,7 +270,7 @@ class FtestProcessSerializer(CustomModelSerializer):
class Meta:
model = Ftest
fields = ["id", "test_date",
"test_user", "note", "ftestitems", "ftestdefects", "qct", "test_user_name", "wpr"]
"test_user", "note", "ftestitems", "ftestdefects", "qct", "test_user_name"]
extra_kwargs = {"qct": {"required": True}}
def validate(self, attrs):
@ -300,19 +300,21 @@ class FtestProcessSerializer(CustomModelSerializer):
with transaction.atomic():
instance = super().update(instance, validated_data)
for item in ftestitems:
if "id" in item and item["id"]:
FtestItem.objects.filter(id=item["id"]).update(
test_user = item["test_user"],
test_val_json = item["test_val_json"])
else:
FtestItem.objects.create(ftest=instance, **item)
try:
ins = FtestItem.objects.get(testitem = item["testitem"], ftest=instance)
except FtestItem.DoesNotExist:
raise ParseError("新的检测项!")
for k, v in item.items():
setattr(ins, k, v)
ins.save()
is_ok = True
for item2 in ftestdefects:
if "id" in item2 and item2["id"]:
ins: FtestDefect = FtestDefect.objects.get(id=item2["id"])
else:
ins = FtestDefect.objects.create(ftest=instance, **item2)
ins.has = item2["has"]
try:
ins = FtestDefect.objects.get(ftest=instance, defect=item2["defect"])
except FtestDefect.DoesNotExist:
raise ParseError("新的缺陷项!")
for k, v in item2.items():
setattr(ins, k, v)
ins.save()
if ins.has and ins.defect.okcate in [Defect.DEFECT_NOTOK]:
is_ok = False

View File

@ -1,36 +0,0 @@
# Generated by Django 3.2.12 on 2025-01-08 07:01
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('qm', '0034_auto_20250108_1016'),
('wpm', '0083_mlogbw_ftest'),
]
operations = [
migrations.CreateModel(
name='MlogbDefect',
fields=[
('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')),
('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')),
('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('count', models.PositiveIntegerField(default=0, verbose_name='数量')),
('defect', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='qm.defect', verbose_name='缺陷')),
('mlogb', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wpm.mlogb', verbose_name='关联记录')),
],
options={
'abstract': False,
},
),
migrations.AddField(
model_name='mlogb',
name='defects',
field=models.ManyToManyField(blank=True, through='wpm.MlogbDefect', to='qm.Defect', verbose_name='不合格缺陷'),
),
]

View File

@ -344,33 +344,19 @@ class Mlogb(BaseModel):
count_n_zt = models.PositiveIntegerField('炸头', default=0)
count_n_qt = models.PositiveIntegerField('其他', default=0)
count_notok_json = models.JSONField('不合格情况', default=list, blank=True)
defects = models.ManyToManyField("qm.defect", verbose_name='不合格缺陷',
through="wpm.mlogbdefect", blank=True)
def get_tracking(self):
if self.material_in:
return "in", self.material_in.tracking
elif self.material_out:
return "out", self.material_out.tracking
def cal_count(self):
self.count_notok = MlogbDefect.objects.filter(
mlogb=self, defect__okcate=30).aggregate(total=Sum("count"))["total"] or 0
self.count_ok = self.count_real - self.count_notok
if self.count_ok < 0:
raise ParseError('合格数量不能小于0')
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 = models.PositiveIntegerField('数量', default=0)
class Mlogbw(BaseModel):
number = models.TextField('单个编号')
mlogb = models.ForeignKey(Mlogb, verbose_name='生产记录', on_delete=models.CASCADE)
wpr = models.ForeignKey("wpmw.wpr", verbose_name='关联产品', on_delete=models.SET_NULL
, related_name='wpr_mlogbw', null=True, blank=True)
ftest = models.OneToOneField("qm.ftest", verbose_name='关联检验', on_delete=models.PROTECT, null=True, blank=True)
ftest = models.OneToOneField("qm.ftest", verbose_name='关联检验',
on_delete=models.PROTECT, null=True, blank=True, related_name="mlogbw_ftest")
note = models.TextField('备注', null=True, blank=True)

View File

@ -6,7 +6,7 @@ from datetime import datetime
from .models import (SfLog, StLog, SfLogExp, WMaterial, Mlog,
Handover, Handoverb, Mlogb, AttLog,
OtherLog, Fmlog, BatchSt, Mlogbw, Handoverbw, MlogbDefect)
OtherLog, Fmlog, BatchSt, Mlogbw, Handoverbw)
from apps.system.models import Dept, User
from apps.system.serializers import UserSimpleSerializer
from apps.pm.models import Mtask, Mtaskb
@ -591,14 +591,15 @@ class MlogbwCreateUpdateSerializer(CustomModelSerializer):
return attrs
def save_ftest(self, mlogbw, ftest_data):
if "id" not in ftest_data or not ftest_data["id"]:
ftest = mlogbw.ftest
if not ftest:
ftest_sr = FtestProcessSerializer(data=ftest_data)
ftest = ftest_sr.create(ftest_data)
mlogbw.ftest = ftest
mlogbw.save()
else:
ftest_sr = FtestProcessSerializer()
ftest_sr.update(instance=Ftest.objects.get(id=ftest_data["id"]), validated_data=ftest_data)
ftest_sr.update(instance=ftest, validated_data=ftest_data)
return mlogbw
@transaction.atomic
@ -908,16 +909,3 @@ class BatchStSerializer(CustomModelSerializer):
model = BatchSt
fields = "__all__"
class MlogbDefectSerializer(CustomModelSerializer):
defect_name = serializers.CharField(source='defect.name', read_only=True)
class Meta:
model = MlogbDefect
fields = "__all__"
read_only_fields = EXCLUDE_FIELDS_BASE
def create(self, validated_data):
defect = validated_data["defect"]
mlogb = validated_data["mlogb"]
if MlogbDefect.objects.filter(mlogb=mlogb, defect=defect).exists():
raise ParseError('该缺陷已填写')
return super().create(validated_data)

View File

@ -201,6 +201,8 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]):
if mlogbws.count() != mi_count:
raise ParseError("日志与明细数量不一致,操作失败")
for item in mlogbws:
if item.test:
raise ParseError("不支持消耗物料的检验")
Wpr.change_or_new(wpr=item.wpr, old_wm=wm)
# 针对加工前不良的暂时额外处理

View File

@ -5,7 +5,7 @@ from apps.wpm.views import (SfLogViewSet, StLogViewSet, SfLogExpViewSet,
WMaterialViewSet, MlogViewSet, HandoverViewSet,
AttlogViewSet, OtherLogViewSet, MlogbViewSet, MlogbInViewSet,
MlogbOutViewSet, FmlogViewSet, BatchStViewSet,
MlogbwViewSet, MlogbDefectViewSet)
MlogbwViewSet)
from apps.wpm.datax import AnaViewSet
@ -28,7 +28,6 @@ router.register('otherlog', OtherLogViewSet, basename='otherlog')
router.register('ana', AnaViewSet, basename='ana')
router.register('batchst', BatchStViewSet, basename='batchst')
router.register('mlogbw', MlogbwViewSet, basename='mlogbw')
router.register("mlogbdefect", MlogbDefectViewSet, basename='mlogbdefect')
urlpatterns = [
path(API_BASE_URL, include(router.urls)),
]

View File

@ -16,7 +16,7 @@ from apps.utils.mixins import CustomListModelMixin, BulkCreateModelMixin, BulkDe
from .filters import StLogFilter, SfLogFilter, WMaterialFilter, MlogFilter, HandoverFilter, MlogbFilter, BatchStFilter
from .models import (SfLog, SfLogExp, StLog, WMaterial, Mlog, Handover, Mlogb,
Mlogbw, AttLog, OtherLog, Fmlog, BatchSt, MlogbDefect)
Mlogbw, AttLog, OtherLog, Fmlog, BatchSt)
from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer,
MlogRevertSerializer,
MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer, HandoverSerializer,
@ -25,7 +25,7 @@ from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer,
AttLogSerializer, OtherLogSerializer, MlogInitSerializer, MlogChangeSerializer,
MlogbDetailSerializer, MlogbInSerializer, MlogbInUpdateSerializer,
MlogbOutUpdateSerializer, FmlogSerializer, FmlogUpdateSerializer, BatchStSerializer,
MlogbwCreateUpdateSerializer, MlogbDefectSerializer)
MlogbwCreateUpdateSerializer)
from .services import mlog_submit, handover_submit, mlog_revert
from apps.wpm.services import mlog_submit_validate, generate_new_batch
from apps.wf.models import State
@ -507,7 +507,7 @@ class MlogbInViewSet(CreateModelMixin, UpdateModelMixin, DestroyModelMixin, Cust
# 找寻质检表
qctmat0 = QctMat.objects.filter(material=mlogbin.material_in).order_by("-create_time").first()
if qctmat0:
mlogbin.qct = qctmat0
mlogbin.qct = qctmat0.qct
mlogbin.save()
mlog:Mlog = mlogbin.mlog
route:Route = mlog.route
@ -618,8 +618,8 @@ class MlogbwViewSet(CustomModelViewSet):
mlogb.count_use = count
elif mlogb.material_out:
mlogb.count_real = count
mlogb.count_ok = count
mlogb.count_notok = 0
mlogb.count_notok = Mlogbw.objects.filter(mlogb=mlogb, ftest__is_ok=False).count()
mlogb.count_ok = count - mlogb.count_notok
mlogb.save()
@transaction.atomic
@ -639,13 +639,15 @@ class MlogbwViewSet(CustomModelViewSet):
@transaction.atomic
def perform_update(self, serializer):
mlogbw = serializer.save()
self.cal_mlogb_count(mlogbw.mlogb)
@transaction.atomic
def perform_destroy(self, instance:Mlogbw):
mlogb = instance.mlogb
if instance.ftest:
instance.ftest.delete()
ftest = instance.ftest
instance.delete()
if ftest:
ftest.delete()
self.cal_mlogb_count(mlogb)
# 如果是输入且输出追踪到个,需同步删除
material_in: Material = mlogb.material_in
@ -658,28 +660,3 @@ class MlogbwViewSet(CustomModelViewSet):
mbw.ftest.delete()
mbw.delete()
self.cal_mlogb_count(mlogb_to)
class MlogbDefectViewSet(CustomListModelMixin, BulkCreateModelMixin,
BulkDestroyModelMixin, CustomGenericViewSet):
perms_map = {"get": "*", "post": "mlog.update", "delete": "mlog.update"}
queryset = MlogbDefect.objects.all()
serializer_class = MlogbDefectSerializer
filterset_fields = ["mlogb", "defect"]
ordering = ["create_time"]
def filter_queryset(self, queryset):
if not self.detail and not self.request.query_params.get('mlogb', None):
raise ParseError('请指定所属日志明细')
return super().filter_queryset(queryset)
@transaction.atomic
def perform_create(self, serializer):
ins:MlogbDefect = serializer.save()
ins.mlogb.cal_count()
@transaction.atomic
def perform_destroy(self, instance):
mlogb = instance.mlogb
instance.delete()
mlogb.cal_count()