diff --git a/apps/qm/migrations/0003_auto_20230627_1348.py b/apps/qm/migrations/0003_auto_20230627_1348.py new file mode 100644 index 00000000..6aeb6e6a --- /dev/null +++ b/apps/qm/migrations/0003_auto_20230627_1348.py @@ -0,0 +1,45 @@ +# Generated by Django 3.2.12 on 2023-06-27 05:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('qm', '0002_auto_20230626_1559'), + ] + + operations = [ + migrations.RemoveField( + model_name='quastat', + name='day', + ), + migrations.RemoveField( + model_name='quastat', + name='month', + ), + migrations.RemoveField( + model_name='quastat', + name='year', + ), + migrations.AddField( + model_name='quastat', + name='day_s', + field=models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='班日'), + ), + migrations.AddField( + model_name='quastat', + name='month_s', + field=models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='班月'), + ), + migrations.AddField( + model_name='quastat', + name='year_s', + field=models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='班年'), + ), + migrations.AlterField( + model_name='quastat', + name='type', + field=models.CharField(default='day', help_text='year_s/month_s/day_s/sflog', max_length=50, verbose_name='统计维度'), + ), + ] diff --git a/apps/qm/models.py b/apps/qm/models.py index 3766e4e9..66acf677 100644 --- a/apps/qm/models.py +++ b/apps/qm/models.py @@ -15,10 +15,10 @@ class QuaStat(CommonBDModel): """ 质量数据统计表 需要有belong_dept """ - type = models.CharField('统计维度', max_length=50, default='day', help_text='year/month/day/sflog') - year = models.PositiveSmallIntegerField('年', null=True, blank=True) - month = models.PositiveSmallIntegerField('月', null=True, blank=True) - day = models.PositiveSmallIntegerField('日', null=True, blank=True) + type = models.CharField('统计维度', max_length=50, default='day', help_text='year_s/month_s/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) sflog = models.ForeignKey(SfLog, verbose_name='关联值班记录', on_delete=models.CASCADE, null=True, blank=True) testitem = models.ForeignKey(TestItem, verbose_name='质检项目', on_delete=models.CASCADE) diff --git a/apps/qm/serializers.py b/apps/qm/serializers.py index bc06ea14..2ac5a6fb 100644 --- a/apps/qm/serializers.py +++ b/apps/qm/serializers.py @@ -12,29 +12,20 @@ class TestItemSerializer(CustomModelSerializer): read_only_fields = EXCLUDE_FIELDS class QuaStatSerializer(CustomModelSerializer): - year = serializers.IntegerField(label='年', required=True) - month = serializers.IntegerField(label='月', required=True) - day = serializers.IntegerField(label='天', required=True) - belong_dept = serializers.PrimaryKeyRelatedField(label="所属部门", queryset=Dept.objects.all(), required=True) + sflog = serializers.PrimaryKeyRelatedField(label="值班记录", queryset=SfLog.objects.all(), required=True) belong_dept_name = serializers.CharField(source='belong_dept.name', read_only=True) material_name = serializers.CharField(source='material.name', read_only=True) testitem_name = serializers.CharField(source='testitem.name', read_only=True) class Meta: model = QuaStat fields = '__all__' - read_only_fields = EXCLUDE_FIELDS + ['type', 'rate_pass'] + read_only_fields = EXCLUDE_FIELDS + ['type', 'rate_pass', 'year_s', 'month_s', 'day_s', 'belong_dept'] extra_kwargs = {'val_avg': {'required': True}, 'num_test':{'required': True}, 'num_ok': {'required': True}} - - -class QuaStatSfLogSerializer(CustomModelSerializer): - sflog = serializers.PrimaryKeyRelatedField(label="值班记录", queryset=SfLog.objects.all(), required=True) - class Meta: - model = QuaStat - fields = '__all__' - read_only_fields = EXCLUDE_FIELDS + ['type', 'year', 'month', 'day', 'belong_dept'] def validate(self, attrs): - sflog = attrs['sflog'] attrs['type'] = 'sflog' - attrs['belong_dept'] = sflog.mgroup.belong_dept + attrs['belong_dept'] = attrs['sflog'].belong_dept + end_time = attrs['sflog'].end_time + attrs['year_s'], attrs['month_s'], attrs['day_s'] = end_time.year, end_time.month, end_time.day + attrs['rate_pass'] = attrs['num_ok']/attrs['num_test'] return attrs \ No newline at end of file diff --git a/apps/qm/tasks.py b/apps/qm/tasks.py index 32769582..eee3932d 100644 --- a/apps/qm/tasks.py +++ b/apps/qm/tasks.py @@ -15,16 +15,41 @@ def cal_quastat(quastatId: str): # GROUP BY field1 # """ ins = QuaStat.objects.get(id=quastatId) - # 月统计 + # 日统计 params = { 'testitem': ins.testitem, 'material': ins.material, 'belong_dept': ins.belong_dept, - 'year': ins.year, - 'month': ins.month + 'year_s': ins.year_s, + 'month_s': ins.month_s, + 'day_s': ins.day_s } + results_day = QuaStat.objects.filter(**params).values('belong_dept', 'material', + 'testitem', 'year_s', 'month_s', 'day_s').annotate( + avg_val_total=Sum(F('avg_val')*F('num_test')), + num_test_1=Sum('num_test'), + num_ok_1=Sum('num_ok')).annotate( + 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()) + ) + for r1 in results_day: + stat_params = { + 'avg_val': r1['avg_val_1'], + 'num_test': r1['num_test_1'], + 'num_ok': r1['num_ok_1'], + 'rate_pass': r1['rate_pass_1'] + } + qua, is_created = QuaStat.objects.get_or_create( + **params, **{'type': 'day_s'}, defaults={**params, **{'type': 'day_s'}, **stat_params} + ) + if not is_created: + for k in stat_params: + setattr(qua, k, stat_params[k]) + qua.save() + # 月统计 + params.pop('day_s') results_month = QuaStat.objects.filter(**params).values('belong_dept', 'material', - 'testitem', 'year', 'month').annotate( + 'testitem', 'year_s', 'month_s').annotate( avg_val_total=Sum(F('avg_val')*F('num_test')), num_test_1=Sum('num_test'), num_ok_1=Sum('num_ok')).annotate( @@ -39,7 +64,7 @@ def cal_quastat(quastatId: str): 'rate_pass': r1['rate_pass_1'] } qua, is_created = QuaStat.objects.get_or_create( - **params, **{'type': 'month'}, defaults={**params, **{'type': 'month'}, **stat_params} + **params, **{'type': 'month_s'}, defaults={**params, **{'type': 'month_s'}, **stat_params} ) if not is_created: for k in stat_params: @@ -47,10 +72,10 @@ def cal_quastat(quastatId: str): qua.save() # 年统计 - params.pop('month') + params.pop('month_s') results_year = QuaStat.objects.filter(**params).values('belong_dept', 'material', - 'testitem', 'year').annotate( + 'testitem', 'year_s').annotate( avg_val_total=Sum(F('avg_val')*F('num_test')), num_test_1=Sum('num_test'), num_ok_1=Sum('num_ok')).annotate( @@ -65,7 +90,7 @@ def cal_quastat(quastatId: str): 'rate_pass': r1['rate_pass_1'] } qua, is_created = QuaStat.objects.get_or_create( - **params, **{'type': 'year'}, defaults={**params, **{'type': 'year'}, **stat_params} + **params, **{'type': 'year_s'}, defaults={**params, **{'type': 'year_s'}, **stat_params} ) if not is_created: for k in stat_params: diff --git a/apps/qm/urls.py b/apps/qm/urls.py index 77a96895..b986fab8 100644 --- a/apps/qm/urls.py +++ b/apps/qm/urls.py @@ -1,14 +1,13 @@ from django.urls import path, include from rest_framework.routers import DefaultRouter -from apps.qm.views import QuaStatViewSet, TestItemViewSet, QuaStatSfLogViewSet +from apps.qm.views import QuaStatViewSet, TestItemViewSet API_BASE_URL = 'api/qm/' HTML_BASE_URL = 'qm/' router = DefaultRouter() router.register('quastat', QuaStatViewSet, basename='quastat') -router.register('quastat_sflog', QuaStatSfLogViewSet, basename='quastat_sflog') router.register('testitem', TestItemViewSet, basename='testitem') urlpatterns = [ path(API_BASE_URL, include(router.urls)), diff --git a/apps/qm/views.py b/apps/qm/views.py index e8595feb..bfb44763 100644 --- a/apps/qm/views.py +++ b/apps/qm/views.py @@ -2,7 +2,7 @@ from django.shortcuts import render from rest_framework.mixins import ListModelMixin, CreateModelMixin from rest_framework.decorators import action from apps.qm.models import QuaStat, TestItem -from apps.qm.serializers import QuaStatSerializer, TestItemSerializer, QuaStatSfLogSerializer +from apps.qm.serializers import QuaStatSerializer, TestItemSerializer from apps.qm.tasks import cal_quastat from rest_framework.response import Response @@ -30,23 +30,10 @@ class QuaStatViewSet(ListModelMixin, CreateModelMixin, CustomGenericViewSet): perms_map = {'get': '*', 'post': 'quastat.create'} queryset = QuaStat.objects.all() serializer_class = QuaStatSerializer - filterset_fields = ['type', 'year', 'month', 'day', 'material', 'testitem', 'belong_dept', 'sflog'] + filterset_fields = ['type', 'year_s', 'month_s', 'day_s', 'material', 'testitem', 'belong_dept', 'sflog', 'sflog__mgroup'] select_related_fields = ['belong_dept', 'material', 'testitem'] - + def perform_create(self, serializer): ins = serializer.save() - ins.rate_pass = ins.num_ok/ ins.num_test - ins.save() - # 计算月和年的统计 - cal_quastat.delay(ins.id) - - -class QuaStatSfLogViewSet(CreateModelMixin, CustomGenericViewSet): - """ - 值班-质量分析 - - 值班-质量分析 - """ - perms_map = {'get': '*', 'post': 'quastat.create'} - queryset = QuaStat.objects.all() - serializer_class = QuaStatSfLogSerializer \ No newline at end of file + # 计算其他方面的统计 + cal_quastat.delay(ins.id) \ No newline at end of file