diff --git a/apps/wpm/migrations/0084_auto_20250108_1501.py b/apps/wpm/migrations/0084_auto_20250108_1501.py new file mode 100644 index 00000000..b5b43404 --- /dev/null +++ b/apps/wpm/migrations/0084_auto_20250108_1501.py @@ -0,0 +1,36 @@ +# 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='不合格缺陷'), + ), + ] diff --git a/apps/wpm/models.py b/apps/wpm/models.py index fee7cbf1..88e53bec 100644 --- a/apps/wpm/models.py +++ b/apps/wpm/models.py @@ -9,6 +9,7 @@ from apps.system.models import Dept from apps.pum.models import Supplier from django.db.models import Sum, Subquery from django.utils.translation import gettext_lazy as _ +from rest_framework.exceptions import ParseError # Create your models here. @@ -343,11 +344,21 @@ 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) -# 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) + 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('单个编号') diff --git a/apps/wpm/serializers.py b/apps/wpm/serializers.py index b6b40e06..c3a0a953 100644 --- a/apps/wpm/serializers.py +++ b/apps/wpm/serializers.py @@ -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) + OtherLog, Fmlog, BatchSt, Mlogbw, Handoverbw, MlogbDefect) from apps.system.models import Dept, User from apps.system.serializers import UserSimpleSerializer from apps.pm.models import Mtask, Mtaskb @@ -880,3 +880,10 @@ class BatchStSerializer(CustomModelSerializer): class Meta: 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 diff --git a/apps/wpm/urls.py b/apps/wpm/urls.py index 3497ade0..d64e046d 100644 --- a/apps/wpm/urls.py +++ b/apps/wpm/urls.py @@ -4,7 +4,8 @@ from rest_framework.routers import DefaultRouter from apps.wpm.views import (SfLogViewSet, StLogViewSet, SfLogExpViewSet, WMaterialViewSet, MlogViewSet, HandoverViewSet, AttlogViewSet, OtherLogViewSet, MlogbViewSet, MlogbInViewSet, - MlogbOutViewSet, FmlogViewSet, BatchStViewSet, MlogbwViewSet) + MlogbOutViewSet, FmlogViewSet, BatchStViewSet, + MlogbwViewSet, MlogbDefectViewSet) from apps.wpm.datax import AnaViewSet @@ -27,6 +28,7 @@ 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)), ] diff --git a/apps/wpm/views.py b/apps/wpm/views.py index 92d77984..981f1320 100644 --- a/apps/wpm/views.py +++ b/apps/wpm/views.py @@ -12,18 +12,20 @@ from apps.system.models import User from apps.mtm.models import Material, Process, Route from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet -from apps.utils.mixins import CustomListModelMixin +from apps.utils.mixins import CustomListModelMixin, BulkCreateModelMixin, BulkDestroyModelMixin 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) -from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer, MlogRevertSerializer, - MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer, HandoverSerializer, HandoverUpdateSerializer, - GenHandoverSerializer, GenHandoverWmSerializer, MlogAnaSerializer, + Mlogbw, AttLog, OtherLog, Fmlog, BatchSt, MlogbDefect) +from .serializers import (SflogExpSerializer, SfLogSerializer, StLogSerializer, WMaterialSerializer, + MlogRevertSerializer, + MlogSerializer, MlogRelatedSerializer, DeptBatchSerializer, HandoverSerializer, + HandoverUpdateSerializer, + GenHandoverSerializer, GenHandoverWmSerializer, MlogAnaSerializer, AttLogSerializer, OtherLogSerializer, MlogInitSerializer, MlogChangeSerializer, - MlogbDetailSerializer, MlogbInSerializer, MlogbInUpdateSerializer, + MlogbDetailSerializer, MlogbInSerializer, MlogbInUpdateSerializer, MlogbOutUpdateSerializer, FmlogSerializer, FmlogUpdateSerializer, BatchStSerializer, - MlogbwCreateUpdateSerializer) + MlogbwCreateUpdateSerializer, MlogbDefectSerializer) 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 @@ -637,3 +639,26 @@ class MlogbwViewSet(CustomModelViewSet): 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() \ No newline at end of file