From 7dd15c57da999c819839600894eb61cb790848f1 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Thu, 6 Nov 2025 23:59:51 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20material=20count=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=AE=8C=E5=85=A8=E7=94=B1=E8=AE=A1=E7=AE=97=E5=8F=AF=E5=BE=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/inm/correct.py | 45 -------------------------------------- apps/inm/services.py | 12 ---------- apps/inm/services_daoru.py | 2 -- apps/inm/views.py | 5 ----- apps/mtm/serializers.py | 12 ++++++++++ apps/mtm/services_2.py | 42 +++++++++++++++++------------------ apps/mtm/views.py | 37 ++++++++++++++++++++----------- apps/wpm/services.py | 36 ------------------------------ 8 files changed, 57 insertions(+), 134 deletions(-) delete mode 100644 apps/inm/correct.py diff --git a/apps/inm/correct.py b/apps/inm/correct.py deleted file mode 100644 index 6725404d..00000000 --- a/apps/inm/correct.py +++ /dev/null @@ -1,45 +0,0 @@ -from .models import MaterialBatch, MIOItem -from apps.mtm.models import Material, Mgroup -from apps.system.models import Dept -from rest_framework.exceptions import ParseError -from django.db.models import F, Sum -from django.db import transaction -from .services import InmService - -def correct_material_batch(): - """矫正物料批次 - """ - mgroups = Mgroup.objects.all() - p_dict = {} - for mgroup in mgroups: - if mgroup.process: - processId = mgroup.process.id - dept: Dept = mgroup.belong_dept - if processId not in p_dict: - p_dict[processId] = dept - else: - raise ParseError('存在多个同工序的工段:{}'.format(mgroup.name)) - mbs = MaterialBatch.objects.filter(material__type__in=[Material.MA_TYPE_GOOD, Material.MA_TYPE_HALFGOOD], - production_dept=None) - for mb in mbs: - if mb.material.process: - processId = mb.material.process.id - mb.production_dept = p_dict[processId] - mb.save() - - -def correct_mb_count_notok(): - """矫正因count_notok未记录导致的错误数据 - """ - mis = MIOItem.objects.filter(mio__state=20, count_notok=0).exclude( - test_date=None, - count_notok=F('count_n_zw') + F('count_n_tw') + F('count_n_qp') + F('count_n_wq') + F('count_n_dl') + F('count_n_pb') + F('count_n_dxt') + F('count_n_js') + F('count_n_qx') + F('count_n_zz') + F('count_n_ysq') + F('count_n_hs') + F('count_n_b') + F('count_n_qt') - ) - for mi in mis: - count_notok = mi.count_n_zw + mi.count_n_tw + mi.count_n_qp + mi.count_n_wq + mi.count_n_dl + mi.count_n_pb + mi.count_n_dxt + mi.count_n_js + mi.count_n_qx + mi.count_n_zz + mi.count_n_ysq + mi.count_n_hs + mi.count_n_b + mi.count_n_qt - # 先处理库存 - try: - MIOItem.objects.filter(id=mi.id).update(count_notok=count_notok) - InmService.update_mb_after_test(mi) - except ParseError as e: - MIOItem.objects.filter(id=mi.id).update(test_date=None) diff --git a/apps/inm/services.py b/apps/inm/services.py index 75e6d3a0..a424c738 100644 --- a/apps/inm/services.py +++ b/apps/inm/services.py @@ -3,7 +3,6 @@ from apps.inm.models import (MIO, MIOItem, MIOItemA, MIOItemw) from rest_framework.exceptions import ParseError from apps.mtm.models import Material -from apps.mtm.services_2 import cal_material_count from apps.wpm.models import WMaterial, BatchSt, BatchLog from apps.wpm.services_2 import ana_batch_thread from apps.wpmw.models import Wpr @@ -268,16 +267,6 @@ def do_in(item: MIOItem): class InmService: - @classmethod - def update_material_count(cls, instance: MIO): - """ - 更新物料数量 - """ - # 统计物料数量 - m_ids = list(MIOItem.objects.filter(mio=instance).values_list('material_id', flat=True)) - m_ids2 = list(MIOItemA.objects.filter(mioitem__mio=instance).values_list('material_id', flat=True)) - cal_material_count(m_ids+m_ids2) - @classmethod def update_inm(cls, instance: MIO, is_reverse: bool = False): """ @@ -484,5 +473,4 @@ class InmService: mioitem.delete() else: raise ParseError("不支持该出入库单明细撤销") - cal_material_count([mioitem.material.id]) \ No newline at end of file diff --git a/apps/inm/services_daoru.py b/apps/inm/services_daoru.py index be19207e..97137496 100644 --- a/apps/inm/services_daoru.py +++ b/apps/inm/services_daoru.py @@ -2,7 +2,6 @@ from rest_framework.exceptions import ParseError from apps.mtm.models import Process, Material from apps.inm.models import WareHouse, MaterialBatch, MIOItem, MIOItemw, MIO from apps.utils.tools import ranstr -from apps.mtm.services_2 import cal_material_count def daoru_mb(path: str): """ @@ -59,7 +58,6 @@ def daoru_mb(path: str): MaterialBatch.objects.get_or_create( material=material, batch=batch, warehouse=warehouse, defaults={"material": material, "batch": batch, "warehouse": warehouse, "count": count, "id": idWorker.get_id()} ) - cal_material_count([material.id]) i = i + 1 def daoru_mioitem_test(path:str, mioitem:MIOItem): diff --git a/apps/inm/views.py b/apps/inm/views.py index d98a946a..56159b1f 100644 --- a/apps/inm/views.py +++ b/apps/inm/views.py @@ -223,7 +223,6 @@ class MIOViewSet(CustomModelViewSet): ins.state = MIO.MIO_SUBMITED ins.save() InmService.update_inm(ins) - InmService.update_material_count(ins) return Response(MIOListSerializer(instance=ins).data) @action(methods=['post'], detail=True, perms_map={'post': 'mio.submit'}, serializer_class=serializers.Serializer) @@ -245,7 +244,6 @@ class MIOViewSet(CustomModelViewSet): ins.submit_time = None ins.save() InmService.update_inm(ins, is_reverse=True) - InmService.update_material_count(ins) return Response() @@ -408,7 +406,6 @@ class MIOItemViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyMode sr.save() # 开始变动库存 InmService.update_mb_item(ins, -1, 'count_notok') - InmService.update_material_count(ins.mio) return Response() @action(methods=['post'], detail=True, perms_map={'post': 'mioitem.test'}, serializer_class=serializers.Serializer) @@ -426,7 +423,6 @@ class MIOItemViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyMode pass ins.test_date = None ins.save() - InmService.update_material_count(ins.mio) return Response() @action(methods=['post'], detail=True, perms_map={'post': 'mioitem.test'}, serializer_class=MIOItemPurInTestSerializer) @@ -444,7 +440,6 @@ class MIOItemViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyMode sr = MIOItemPurInTestSerializer(instance=ins, data=request.data) sr.is_valid(raise_exception=True) sr.save() - InmService.update_material_count(ins.mio) return Response() @action(methods=['post'], detail=False, perms_map={'post': '*'}, serializer_class=MioItemAnaSerializer) diff --git a/apps/mtm/serializers.py b/apps/mtm/serializers.py index 949c70b9..db0877e3 100644 --- a/apps/mtm/serializers.py +++ b/apps/mtm/serializers.py @@ -33,6 +33,18 @@ class MaterialSimpleSerializer(CustomModelSerializer): class MaterialSerializer(CustomModelSerializer): process_name = serializers.CharField(source='process.name', read_only=True) full_name = serializers.SerializerMethodField() + count_mb = serializers.SerializerMethodField() + count_wm = serializers.SerializerMethodField() + count = serializers.SerializerMethodField() + + def get_count_mb(self, obj): + return getattr(obj, 'count_mb', 0) + + def get_count_wm(self, obj): + return getattr(obj, 'count_wm', 0) + + def get_count(self, obj): + return getattr(obj, 'count_mb', 0) + getattr(obj, 'count_wm', 0) class Meta: model = Material diff --git a/apps/mtm/services_2.py b/apps/mtm/services_2.py index f4843a64..7df796d5 100644 --- a/apps/mtm/services_2.py +++ b/apps/mtm/services_2.py @@ -4,24 +4,24 @@ from django.db.models import Sum from apps.inm.models import MaterialBatch from apps.wpm.models import WMaterial -def cal_material_count(materialId_list: List[str]=None): - """ - 计算物料总数量 - """ - if materialId_list is None: - materialId_list = [] - if materialId_list: - objs = Material.objects.filter(id__in=set(materialId_list)) - else: - objs = Material.objects.all() - for material in objs: - mb_count = MaterialBatch.objects.filter(material=material, state=10).aggregate(total=Sum("count"))["total"] or 0 - wm_count = WMaterial.objects.filter(material=material, state=10).aggregate(total=Sum("count"))["total"] or 0 - if mb_count is None: - mb_count = 0 - if wm_count is None: - wm_count = 0 - Material.objects.filter(id=material.id).update( - count_wm=wm_count, - count_mb=mb_count, - count=mb_count + wm_count) \ No newline at end of file +# def cal_material_count(materialId_list: List[str]=None): +# """ +# 计算物料总数量 +# """ +# if materialId_list is None: +# materialId_list = [] +# if materialId_list: +# objs = Material.objects.filter(id__in=set(materialId_list)) +# else: +# objs = Material.objects.all() +# for material in objs: +# mb_count = MaterialBatch.objects.filter(material=material, state=10).aggregate(total=Sum("count"))["total"] or 0 +# wm_count = WMaterial.objects.filter(material=material, state=10).aggregate(total=Sum("count"))["total"] or 0 +# if mb_count is None: +# mb_count = 0 +# if wm_count is None: +# wm_count = 0 +# Material.objects.filter(id=material.id).update( +# count_wm=wm_count, +# count_mb=mb_count, +# count=mb_count + wm_count) \ No newline at end of file diff --git a/apps/mtm/views.py b/apps/mtm/views.py index 2bd530b2..67b240f5 100644 --- a/apps/mtm/views.py +++ b/apps/mtm/views.py @@ -17,12 +17,13 @@ from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet from apps.utils.mixins import BulkCreateModelMixin, BulkDestroyModelMixin, CustomListModelMixin from rest_framework.serializers import Serializer from django.db import transaction -from django.db.models import Q from apps.wf.models import Ticket from django.utils import timezone from rest_framework.permissions import IsAdminUser from apps.utils.export import export_excel from operator import itemgetter +from django.db.models import Sum, Q, Value, F, ExpressionWrapper, DecimalField +from django.db.models.functions import Coalesce # Create your views here. class MaterialViewSet(CustomModelViewSet): @@ -40,6 +41,28 @@ class MaterialViewSet(CustomModelViewSet): 'type', 'process', 'process__sort', 'sort', 'id', 'number'] ordering_fields = ['name', 'model', 'specification', 'type', 'process', 'process__sort', 'sort', 'id', 'number', 'create_time'] + + def get_queryset(self): + qs = super().get_queryset() + if self.action in ["list", "retrieve"]: + return qs.annotate( + count_wm=Coalesce( + Sum('mb_m__count', filter=Q(mb_m__state=10)), + Value(0), + output_field=DecimalField() + ), + count_mb=Coalesce( + Sum('wm_m__count', filter=Q(wm_m__state=10)), + Value(0), + output_field=DecimalField() + ) + ).annotate( + count=ExpressionWrapper( + F('count_wm') + F('count_mb'), + output_field=DecimalField() + ) + ) + def perform_destroy(self, instance): from apps.inm.models import MaterialBatch @@ -60,18 +83,6 @@ class MaterialViewSet(CustomModelViewSet): daoru_material(settings.BASE_DIR + request.data.get('path', '')) return Response() - @action(methods=['post'], detail=True, serializer_class=Serializer, perms_map={'post': 'material.create'}) - @transaction.atomic - def cal_count(self, request, *args, **kwargs): - """统计数量 - - 统计数量 - """ - ins = self.get_object() - from apps.mtm.services_2 import cal_material_count - cal_material_count([ins.id]) - return Response() - @action(methods=['put'], detail=True, serializer_class=Serializer, perms_map={'put': '*'}) @transaction.atomic def set_week_esitimate_consume(self, request, *args, **kwargs): diff --git a/apps/wpm/services.py b/apps/wpm/services.py index d64adab7..f6d1a27c 100644 --- a/apps/wpm/services.py +++ b/apps/wpm/services.py @@ -12,7 +12,6 @@ from apps.pm.models import Mtask from apps.mtm.models import Mgroup, Shift, Material, Route, RoutePack, Team, Srule from .models import SfLog, WMaterial, Mlog, Mlogb, Mlogbw, Handover, Handoverb, Handoverbw, MlogbDefect, BatchLog, BatchSt, MlogUser -from apps.mtm.services_2 import cal_material_count from apps.wf.models import Ticket from apps.wf.services import WfService import logging @@ -23,7 +22,6 @@ from ..qm.models import Defect, Ftest from django.db.models import Count, Q from apps.utils.tasks import ctask_run from apps.mtm.models import Process -from apps.mtm.services_2 import cal_material_count from apps.utils.lock import lock_model_record_d_func myLogger = logging.getLogger('log') @@ -399,9 +397,6 @@ def mlog_submit(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): # 更新任务进度 cal_mtask_progress_from_mlog(mlog) - # 更新物料数量 - cal_material_count_from_mlog(mlog) - # 触发批次统计分析 xbatches = list(Mlogb.objects.filter(mlog=mlog).values_list('batch', flat=True)) ana_batch_thread(xbatchs=xbatches, mgroup=mlog.mgroup) @@ -618,9 +613,6 @@ def mlog_revert(mlog: Mlog, user: User, now: Union[datetime.datetime, None]): # 更新任务进度 cal_mtask_progress_from_mlog(mlog) - # 更新物料数量 - cal_material_count_from_mlog(mlog) - # 清除关系链 BatchLog.clear(mlog=mlog) @@ -650,24 +642,6 @@ def cal_mtask_progress_from_mlog(mlog:Mlog): continue update_mtask(mtask, fill_way=mlog.fill_way) caled_mtask.append(mtask) - -def cal_material_count_from_mlog(mlog: Mlog): - """ - 更新mlog关联的物料数量(可单独执行) - """ - matid_list = [] - if mlog.material_in: - matid_list.append(mlog.material_in.id) - if mlog.material_out: - matid_list.append(mlog.material_out.id) - matid_list2 = Mlogb.objects.filter(mlog=mlog).values_list('material_in__id', 'material_out__id').distinct() - for matid in matid_list2: - if matid[0]: - matid_list.append(matid[0]) - if matid[1]: - matid_list.append(matid[1]) - matid_list = list(set(matid_list)) - cal_material_count(matid_list) def update_mtask(mtask: Mtask, fill_way: int = 10): @@ -953,11 +927,6 @@ def handover_submit(handover:Handover, user: User, now: Union[datetime.datetime, if handover.recive_user is None: handover.recive_user = user handover.save() - - # 如果是改版交接需要触发统计数量 - if handover.type == Handover.H_CHANGE: - mids.append(handover.material_changed.id) - cal_material_count(mids) ana_batch_thread(xbatchs=batches) @@ -1013,11 +982,6 @@ def handover_revert(handover:Handover, handler:User=None): handover.save() # 删除追踪链 BatchLog.clear(handover=handover) - - # 如果是改版交接需要触发统计数量 - if handover.type == Handover.H_CHANGE: - mids.append(handover.material_changed.id) - cal_material_count(mids) ana_batch_thread(xbatchs=xbatchs)