feat: 质检数据重新统计并放入enstat表中

This commit is contained in:
caoqianming 2023-07-25 11:16:38 +08:00
parent 6c3cbf0c5e
commit 7fde7148bf
5 changed files with 253 additions and 85 deletions

View File

@ -0,0 +1,33 @@
# Generated by Django 3.2.12 on 2023-07-25 03:12
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('qm', '0007_alter_quastat_type'),
]
operations = [
migrations.RemoveField(
model_name='quastat',
name='day_s',
),
migrations.RemoveField(
model_name='quastat',
name='month_s',
),
migrations.RemoveField(
model_name='quastat',
name='shift',
),
migrations.RemoveField(
model_name='quastat',
name='type',
),
migrations.RemoveField(
model_name='quastat',
name='year_s',
),
]

View File

@ -1,7 +1,7 @@
from django.db import models from django.db import models
from apps.system.models import CommonAModel from apps.system.models import CommonAModel
from apps.utils.models import CommonBDModel from apps.utils.models import CommonBDModel
from apps.mtm.models import Material, Shift from apps.mtm.models import Material, Mgroup, Team
from apps.wpm.models import SfLog from apps.wpm.models import SfLog
class TestItem(CommonAModel): class TestItem(CommonAModel):
@ -17,15 +17,10 @@ class TestItem(CommonAModel):
# Create your models here. # Create your models here.
class QuaStat(CommonBDModel): class QuaStat(CommonBDModel):
""" """
质量数据统计 需要有belong_dept 质量数据
""" """
type = models.CharField('统计维度', max_length=50, default='day', help_text='year_s/month_s/month_sf/day_s/sflog')
year_s = models.PositiveSmallIntegerField('班年', null=True, blank=True)
month_s = models.PositiveSmallIntegerField('班月', null=True, blank=True)
day_s = models.PositiveSmallIntegerField('班日', null=True, blank=True)
material = models.ForeignKey(Material, verbose_name='关联产物', on_delete=models.CASCADE) material = models.ForeignKey(Material, verbose_name='关联产物', on_delete=models.CASCADE)
sflog = models.ForeignKey(SfLog, verbose_name='关联值班记录', on_delete=models.CASCADE, null=True, blank=True) sflog = models.ForeignKey(SfLog, verbose_name='关联值班记录', on_delete=models.CASCADE, null=True, blank=True)
shift = models.ForeignKey(Shift, verbose_name='关联班组', on_delete=models.CASCADE, null=True, blank=True)
testitem = models.ForeignKey(TestItem, verbose_name='质检项目', on_delete=models.CASCADE) testitem = models.ForeignKey(TestItem, verbose_name='质检项目', on_delete=models.CASCADE)
val_avg = models.FloatField('平均值', null=True, blank=True) val_avg = models.FloatField('平均值', null=True, blank=True)
num_test = models.PositiveSmallIntegerField('检测次数', null=True, blank=True) num_test = models.PositiveSmallIntegerField('检测次数', null=True, blank=True)

View File

@ -24,11 +24,6 @@ class QuaStatSerializer(CustomModelSerializer):
extra_kwargs = {'val_avg': {'required': True, 'allow_null': False}, 'num_test':{'required': True, 'allow_null': False}, 'num_ok': {'required': True, 'allow_null': False}} extra_kwargs = {'val_avg': {'required': True, 'allow_null': False}, 'num_test':{'required': True, 'allow_null': False}, 'num_ok': {'required': True, 'allow_null': False}}
def validate(self, attrs): def validate(self, attrs):
attrs['type'] = 'sflog'
attrs['belong_dept'] = attrs['sflog'].belong_dept
end_time = attrs['sflog'].end_time
end_time_local = localtime(end_time)
attrs['year_s'], attrs['month_s'], attrs['day_s'], attrs['shift'] = end_time_local.year, end_time_local.month, end_time_local.day, attrs['sflog'].shift
attrs['rate_pass'] = attrs['num_ok']/attrs['num_test'] attrs['rate_pass'] = attrs['num_ok']/attrs['num_test']
return attrs return attrs

View File

@ -4,68 +4,209 @@ from apps.qm.models import QuaStat
from apps.utils.tasks import CustomTask from apps.utils.tasks import CustomTask
from django.db.models import Sum, F, ExpressionWrapper, FloatField, Q from django.db.models import Sum, F, ExpressionWrapper, FloatField, Q
def cal_quastat_type(qs, params_o: dict, type: str): # def cal_quastat_type(qs, params_o: dict, type: str):
params = params_o.copy() # params = params_o.copy()
v_list = ['belong_dept', 'material', 'testitem', 'year_s', 'month_s', 'day_s', 'shift'] # v_list = ['belong_dept', 'material', 'testitem', 'year_s', 'month_s', 'day_s', 'shift']
if type == 'month_sf': # if type == 'month_sf':
params.pop('day_s') # params.pop('day_s')
v_list = ['belong_dept', 'material', 'testitem', 'year_s', 'month_s', 'shift'] # v_list = ['belong_dept', 'material', 'testitem', 'year_s', 'month_s', 'shift']
elif type == 'month_s': # elif type == 'month_s':
params.pop('shift') # params.pop('shift')
params.pop('day_s') # params.pop('day_s')
v_list = ['belong_dept', 'material', 'testitem', 'year_s', 'month_s'] # v_list = ['belong_dept', 'material', 'testitem', 'year_s', 'month_s']
elif type == 'year_s': # elif type == 'year_s':
params.pop('shift') # params.pop('shift')
params.pop('month_s') # params.pop('month_s')
params.pop('day_s') # params.pop('day_s')
v_list = ['belong_dept', 'material', 'testitem', 'year_s'] # v_list = ['belong_dept', 'material', 'testitem', 'year_s']
qs_ = qs.filter(**params).values(*v_list) # qs_ = qs.filter(**params).values(*v_list)
results = qs_.annotate( # results = qs_.annotate(
avg_val_total=Sum(F('val_avg')*F('num_test')), # avg_val_total=Sum(F('val_avg')*F('num_test')),
num_test_1=Sum('num_test'), # num_test_1=Sum('num_test'),
num_ok_1=Sum('num_ok')).annotate( # num_ok_1=Sum('num_ok')).annotate(
avg_val_1=ExpressionWrapper(F('avg_val_total')/F('num_test_1'), output_field=FloatField()) # avg_val_1=ExpressionWrapper(F('avg_val_total')/F('num_test_1'), output_field=FloatField())
# ,rate_pass_1=ExpressionWrapper(F('num_ok_1')/F('num_test_1'), output_field=FloatField()) 不知道为什么算出来是0 # # ,rate_pass_1=ExpressionWrapper(F('num_ok_1')/F('num_test_1'), output_field=FloatField()) 不知道为什么算出来是0
) # )
query = """ # query = """
SELECT SUM(num_test * val_avg)/SUM(num_test) AS avg_val_1, SUM(num_test) AS num_test_1, SUM(num_ok) AS num_ok_1, SUM(num_ok)/SUM(num_test) as rate_pass_1 # SELECT SUM(num_test * val_avg)/SUM(num_test) AS avg_val_1, SUM(num_test) AS num_test_1, SUM(num_ok) AS num_ok_1, SUM(num_ok)/SUM(num_test) as rate_pass_1
FROM qm_quastat # FROM qm_quastat
where year_s = 2023 and month_s = 7 and day_s = 7 and type = 'sflog' # where year_s = 2023 and month_s = 7 and day_s = 7 and type = 'sflog'
GROUP BY belong_dept_id, material_id, testitem_id # GROUP BY belong_dept_id, material_id, testitem_id
""" # """
params['type'] = type # params['type'] = type
for r1 in results: # for r1 in results:
stat_params = { # stat_params = {
'val_avg': r1['avg_val_1'], # 'val_avg': r1['avg_val_1'],
'num_test': r1['num_test_1'], # 'num_test': r1['num_test_1'],
'num_ok': r1['num_ok_1'], # 'num_ok': r1['num_ok_1'],
'rate_pass': r1['num_ok_1']/r1['num_test_1'] # 'rate_pass': r1['num_ok_1']/r1['num_test_1']
} # }
qua, is_created = QuaStat.objects.get_or_create( # qua, is_created = QuaStat.objects.get_or_create(
**params, defaults={**params, **stat_params} # **params, defaults={**params, **stat_params}
) # )
for k in stat_params: # for k in stat_params:
setattr(qua, k, stat_params[k]) # setattr(qua, k, stat_params[k])
qua.save() # qua.save()
# @shared_task(base=CustomTask)
# def cal_quastat(quastatId: str):
# ins = QuaStat.objects.get(id=quastatId)
# qs = QuaStat.objects.filter(type='sflog').exclude(Q(val_avg__isnull=True)|Q(num_test__isnull=True)|Q(num_ok__isnull=True))
# params = {
# 'testitem': ins.testitem,
# 'material': ins.material,
# 'shift': ins.shift,
# 'belong_dept': ins.belong_dept,
# 'year_s': ins.year_s,
# 'month_s': ins.month_s,
# 'day_s': ins.day_s
# }
# # 日统计
# cal_quastat_type(qs, params_o=params, type='day_s')
# # 班月统计
# cal_quastat_type(qs, params_o=params, type='month_sf')
# # 月统计
# cal_quastat_type(qs, params_o=params, type='month_s')
# # 年统计
# cal_quastat_type(qs, params_o=params, type='year_s')
@shared_task(base=CustomTask) @shared_task(base=CustomTask)
def cal_quastat(quastatId: str): def cal_quastat_sflog(sflogId: str):
ins = QuaStat.objects.get(id=quastatId) from apps.wpm.models import SfLog
qs = QuaStat.objects.filter(type='sflog').exclude(Q(val_avg__isnull=True)|Q(num_test__isnull=True)|Q(num_ok__isnull=True)) from apps.enm.models import EnStat
params = { from apps.utils.sql import query_all_dict
'testitem': ins.testitem, sflog = SfLog.objects.get(id=sflogId)
'material': ins.material, mgroup = sflog.mgroup
'shift': ins.shift, team = sflog.team
'belong_dept': ins.belong_dept, qs = QuaStat.objects.exclude(Q(val_avg__isnull=True)|Q(num_test__isnull=True)|Q(num_ok__isnull=True))
'year_s': ins.year_s,
'month_s': ins.month_s, year_s, month_s, day_s = sflog.get_ymd
'day_s': ins.day_s
} # 班统计
qs1_v = qs.filter(sflog=sflog).annotate(material_name=F('material__name'), testitem_name=F('testitem__name')).values('material', 'material_name', 'testitem', 'testitem_name', 'val_avg', 'num_test', 'num_ok', 'rate_pass')
enstat, _ = EnStat.objects.get_or_create(type="sflog", sflog=sflog,
defaults={'type': 'sflog', 'sflog': sflog, 'mgroup': mgroup, 'year_s': year_s, 'month_s': month_s, 'day_s': day_s, 'total_production': 0, 'elec_consume': 0})
enstat.qua_data = list(qs1_v)
enstat.save()
# 日统计 # 日统计
cal_quastat_type(qs, params_o=params, type='day_s') sql_q2 = f"""SELECT
mtma."id" AS material,
mtma."name" AS material_name,
qmt."id" AS testitem,
qmt."name" AS testitem_name,
CAST(SUM(num_test * val_avg) AS FLOAT)/NULLIF(SUM(num_test), 0) AS val_avg,
SUM(num_test) AS num_test,
SUM(num_ok) AS num_ok,
CAST(SUM(num_ok) AS FLOAT)/NULLIF(SUM(num_test),0) AS rate_pass
FROM qm_quastat qmq
LEFT JOIN wpm_sflog sflog on sflog.id = qmq.sflog_id
LEFT JOIN mtm_mgroup mgroup on mgroup.id = sflog.mgroup_id
LEFT JOIN mtm_material mtma on mtma.id = qmq.material_id
LEFT JOIN qm_testitem qmt on qmt.id = qmq.testitem_id
where EXTRACT(year from sflog.end_time) = {year_s}
and EXTRACT(month from sflog.end_time) = {month_s} and EXTRACT(day from sflog.end_time) = {day_s}
and mgroup.id = '{mgroup.id}'
and qmq.val_avg is not NULL
and qmq.num_test is not NULL
and qmq.num_ok is not NULL
GROUP BY mgroup."id", mtma."id", qmt."id", mgroup.sort, mtma.sort, qmt.sort
ORDER BY mgroup.sort, mtma.sort, qmt.sort
"""
res2 = query_all_dict(sql_q2)
enstat, _ = EnStat.objects.get_or_create(type="day_s", mgroup=mgroup, year_s=year_s, month_s=month_s, day_s=day_s,
defaults={'type': 'day_s', 'mgroup': mgroup, 'year_s': year_s, 'month_s': month_s, 'day_s': day_s, 'total_production': 0, 'elec_consume': 0})
enstat.qua_data = res2
enstat.save()
if team:
# 班月统计 # 班月统计
cal_quastat_type(qs, params_o=params, type='month_sf') sql_q3 = f"""SELECT
# 月统计 mtma."id" AS material,
cal_quastat_type(qs, params_o=params, type='month_s') mtma."name" AS material_name,
# 年统计 qmt."id" AS testitem,
cal_quastat_type(qs, params_o=params, type='year_s') qmt."name" AS testitem_name,
CAST(SUM(num_test * val_avg) AS FLOAT)/NULLIF(SUM(num_test), 0) AS val_avg,
SUM(num_test) AS num_test,
SUM(num_ok) AS num_ok,
CAST(SUM(num_ok) AS FLOAT)/NULLIF(SUM(num_test),0) AS rate_pass
FROM qm_quastat qmq
LEFT JOIN wpm_sflog sflog on sflog.id = qmq.sflog_id
LEFT JOIN mtm_team team on team.id = sflog.team_id
LEFT JOIN mtm_material mtma on mtma.id = qmq.material_id
LEFT JOIN qm_testitem qmt on qmt.id = qmq.testitem_id
where EXTRACT(year from sflog.end_time) = {year_s}
and EXTRACT(month from sflog.end_time) = {month_s}
and team.id = '{team.id}'
and qmq.val_avg is not NULL
and qmq.num_test is not NULL
and qmq.num_ok is not NULL
GROUP BY mgroup."id", mtma."id", qmt."id", mgroup.sort, mtma.sort, qmt.sort
ORDER BY mgroup.sort, mtma.sort, qmt.sort
"""
res3 = query_all_dict(sql_q3)
enstat, _ = EnStat.objects.get_or_create(type="month_sf", mgroup=mgroup, team=team, year_s=year_s, month_s=month_s,
defaults={'type': 'month_sf', 'mgroup': mgroup, 'year_s': year_s, 'month_s': month_s, 'team': team, 'total_production': 0, 'elec_consume': 0})
enstat.qua_data = res3
enstat.save()
# 月统计
sql_q4 = f"""SELECT
mtma."id" AS material,
mtma."name" AS material_name,
qmt."id" AS testitem,
qmt."name" AS testitem_name,
CAST(SUM(num_test * val_avg) AS FLOAT)/NULLIF(SUM(num_test), 0) AS val_avg,
SUM(num_test) AS num_test,
SUM(num_ok) AS num_ok,
CAST(SUM(num_ok) AS FLOAT)/NULLIF(SUM(num_test),0) AS rate_pass
FROM qm_quastat qmq
LEFT JOIN wpm_sflog sflog on sflog.id = qmq.sflog_id
LEFT JOIN mtm_mgroup mgroup on mgroup.id = sflog.mgroup_id
LEFT JOIN mtm_material mtma on mtma.id = qmq.material_id
LEFT JOIN qm_testitem qmt on qmt.id = qmq.testitem_id
where EXTRACT(year from sflog.end_time) = {year_s}
and EXTRACT(month from sflog.end_time) = {month_s}
and mgroup.id = '{mgroup.id}'
and qmq.val_avg is not NULL
and qmq.num_test is not NULL
and qmq.num_ok is not NULL
GROUP BY mgroup."id", mtma."id", qmt."id", mgroup.sort, mtma.sort, qmt.sort
ORDER BY mgroup.sort, mtma.sort, qmt.sort
"""
res4 = query_all_dict(sql_q4)
enstat, _ = EnStat.objects.get_or_create(type="month_s", mgroup=mgroup, year_s=year_s, month_s=month_s,
defaults={'type': 'month_s', 'mgroup': mgroup, 'year_s': year_s, 'month_s': month_s, 'total_production': 0, 'elec_consume': 0})
enstat.qua_data = res4
enstat.save()
# 年统计
sql_q5 = f"""SELECT
mtma."id" AS material,
mtma."name" AS material_name,
qmt."id" AS testitem,
qmt."name" AS testitem_name,
CAST(SUM(num_test * val_avg) AS FLOAT)/NULLIF(SUM(num_test), 0) AS val_avg,
SUM(num_test) AS num_test,
SUM(num_ok) AS num_ok,
CAST(SUM(num_ok) AS FLOAT)/NULLIF(SUM(num_test),0) AS rate_pass
FROM qm_quastat qmq
LEFT JOIN wpm_sflog sflog on sflog.id = qmq.sflog_id
LEFT JOIN mtm_mgroup mgroup on mgroup.id = sflog.mgroup_id
LEFT JOIN mtm_material mtma on mtma.id = qmq.material_id
LEFT JOIN qm_testitem qmt on qmt.id = qmq.testitem_id
where EXTRACT(year from sflog.end_time) = {year_s}
and mgroup.id = '{mgroup.id}'
and qmq.val_avg is not NULL
and qmq.num_test is not NULL
and qmq.num_ok is not NULL
GROUP BY mgroup."id", mtma."id", qmt."id", mgroup.sort, mtma.sort, qmt.sort
ORDER BY mgroup.sort, mtma.sort, qmt.sort
"""
res5 = query_all_dict(sql_q5)
enstat, _ = EnStat.objects.get_or_create(type="year_s", mgroup=mgroup, year_s=year_s,
defaults={'type': 'year_s', 'mgroup': mgroup, 'year_s': year_s, 'total_production': 0, 'elec_consume': 0})
enstat.qua_data = res5
enstat.save()

View File

@ -3,12 +3,13 @@ from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelM
from rest_framework.decorators import action from rest_framework.decorators import action
from apps.qm.models import QuaStat, TestItem from apps.qm.models import QuaStat, TestItem
from apps.qm.serializers import QuaStatSerializer, TestItemSerializer, QuaStatUpdateSerializer from apps.qm.serializers import QuaStatSerializer, TestItemSerializer, QuaStatUpdateSerializer
from apps.qm.tasks import cal_quastat from apps.qm.tasks import cal_quastat_sflog
from rest_framework.response import Response from rest_framework.response import Response
from apps.utils.mixins import BulkCreateModelMixin, BulkUpdateModelMixin from apps.utils.mixins import BulkCreateModelMixin, BulkUpdateModelMixin
import datetime import datetime
from apps.utils.viewsets import CustomGenericViewSet from apps.utils.viewsets import CustomGenericViewSet
from apps.wpm.models import SfLog
# Create your views here. # Create your views here.
class TestItemViewSet(ListModelMixin, CustomGenericViewSet): class TestItemViewSet(ListModelMixin, CustomGenericViewSet):
@ -25,22 +26,25 @@ class TestItemViewSet(ListModelMixin, CustomGenericViewSet):
class QuaStatViewSet(ListModelMixin, BulkUpdateModelMixin, CustomGenericViewSet): class QuaStatViewSet(ListModelMixin, BulkUpdateModelMixin, CustomGenericViewSet):
""" """
list:质量分析报告 list:质量数据统计
质量分析报告 质量数据统计
""" """
perms_map = {'get': '*', 'put': 'quastat.update'} perms_map = {'get': '*', 'put': 'quastat.update'}
queryset = QuaStat.objects.all() queryset = QuaStat.objects.all()
serializer_class = QuaStatSerializer serializer_class = QuaStatSerializer
update_serializer_class = QuaStatUpdateSerializer update_serializer_class = QuaStatUpdateSerializer
filterset_fields = ['type', 'year_s', 'month_s', 'day_s', 'material', 'testitem', 'belong_dept', 'sflog', 'sflog__mgroup'] filterset_fields = ['material', 'testitem', 'belong_dept', 'sflog', 'sflog__mgroup', 'sflog__shift', 'sflog__end_time__year', 'sflog__end_time__month', 'sflog__end_time__day']
select_related_fields = ['belong_dept', 'material', 'testitem'] select_related_fields = ['belong_dept', 'material', 'testitem']
ordering = ['belong_dept__sort', 'material__sort', 'testitem__sort', 'year_s', 'month_s', 'day_s'] ordering = ['belong_dept__sort', 'material__sort', 'testitem__sort']
def perform_update(self, serializer): def after_bulk_update(self, objs):
ins = serializer.save() now = datetime.datetime.now()
cal_quastat.delay(ins.id) sflogIds = []
if ins.sflog: # 更新值班记录的质检时间 for i in objs:
ins.sflog.last_test_time = datetime.datetime.now() sflogIds.append(i['sflog'])
ins.sflog.save() sflogIds = list(set(sflogIds))
SfLog.objects.filter(id__in=sflogIds).update(last_test_time=now) # 更新质检记录时间
for sflogId in sflogIds:
cal_quastat_sflog.delay(sflogId)
return super().after_bulk_update(objs)