from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.exceptions import ParseError from drf_yasg.utils import swagger_auto_schema from apps.mtm.models import Mgroup from apps.wpm.serializers import BatchMgroupSerializer from apps.wpm.models import WMaterial, Mlogb from django.db.models import Q, Sum, F, ExpressionWrapper from collections import defaultdict from apps.mtm.models import Material class BatchWorkView(APIView): perms_map = {"post": "*"} @swagger_auto_schema( operation_summary='工段批次加工进度', request_body=BatchMgroupSerializer, responses={200: []}, ) def post(self, request): sr = BatchMgroupSerializer(data=request.data) sr.is_valid(raise_exception=True) vdata = sr.validated_data try: mgroup:Mgroup = Mgroup.objects.get(name=vdata['mgroup_name']) except Exception: raise ParseError(f"获取工段信息失败-{vdata['mgroup_name']}") matinIds = mgroup.process.get_canin_mat_ids() # 待加工的批次 wm_qs = WMaterial.objects.filter(mgroup=mgroup, count__gt=0) wm_todo_qs = wm_qs.filter(material__id__in=matinIds).exclude(state=WMaterial.WM_REPAIRED)|wm_qs.filter(state=WMaterial.WM_REPAIR, mgroup=mgroup) wm_v = wm_todo_qs.order_by("batch").values("count", "batch", wmid=F("id")) # 对应的操作子日志投入 mlogb_qs = Mlogb.objects.filter(mlog__mgroup=mgroup, wm_in__in=wm_todo_qs) mlogb_qs_v = mlogb_qs.values("count_use", "mlog__submit_time", wmid=F("wm_in__id")) # 对应的操作子日志产出 mlogb_qs2 = Mlogb.objects.filter(mlogb_from__in=mlogb_qs) mlogb_qs2_v = mlogb_qs2.values("count_real", "count_ok", "mlog__submit_time", wmid=F("mlogb_from__wm_in__id")) # 1. 处理wm_v - 原始物料数据 wm_dict = {item['wmid']: {'count': item['count'], 'batch': item['batch']} for item in wm_v} # 2. 处理mlogb_qs_v - 物料使用数据 use_dict = defaultdict(lambda: {'count_use': 0, 'count_use_submit': 0, 'count_use_unsubmit': 0}) for item in mlogb_qs_v: wmid = item['wmid'] if item['mlog__submit_time']: use_dict[wmid]['count_use_submit'] += item['count_use'] else: use_dict[wmid]['count_use_unsubmit'] += item['count_use'] use_dict[wmid]['count_use'] += item['count_use'] # 3. 处理mlogb_qs2_v - 物料产出数据 output_dict = defaultdict(lambda: {'count_real': 0, 'count_ok': 0}) for item in mlogb_qs2_v: if item['mlog__submit_time']: # 只统计已提交的记录 wmid = item['wmid'] output_dict[wmid]['count_real'] += item['count_real'] output_dict[wmid]['count_ok'] += item['count_ok'] # 合并所有数据 result = [] for wmid, wm_data in wm_dict.items(): use_data = use_dict.get(wmid, {}) output_data = output_dict.get(wmid, {}) count = wm_data['count'] row = { 'wmid': wmid, 'batch': wm_data['batch'], 'count_todo': count - use_data.get('count_use_unsubmit', 0), 'count_working': use_data.get('count_use_unsubmit', 0), 'count_real': output_data.get('count_real', 0), 'count_ok': output_data.get('count_ok', 0), 'count': count } result.append(row) return Response(result)