feat: 完善enm task相关功能

This commit is contained in:
caoqianming 2023-06-15 16:57:29 +08:00
parent 4f37b4c023
commit d2392a3c74
6 changed files with 158 additions and 73 deletions

View File

@ -1,4 +1,4 @@
# Generated by Django 3.2.12 on 2023-06-14 07:27 # Generated by Django 3.2.12 on 2023-06-15 08:27
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
@ -34,6 +34,28 @@ class Migration(migrations.Migration):
'verbose_name': '测点集', 'verbose_name': '测点集',
}, },
), ),
migrations.CreateModel(
name='Mpoint',
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='删除标记')),
('name', models.CharField(max_length=50, verbose_name='测点名称')),
('code', models.CharField(max_length=50, unique=True, verbose_name='测点编号')),
('unit', models.CharField(max_length=50, verbose_name='单位')),
('cate', models.CharField(default='elec', max_length=50, verbose_name='分类')),
('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mpoint_belong_dept', to='system.dept', verbose_name='所属部门')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mpoint_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')),
('ep_belong', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mp_ep_belong', to='em.equipment', verbose_name='属于哪个设备')),
('ep_monitored', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mp_ep_monitored', to='em.equipment', verbose_name='监测哪个设备')),
('mgroup', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='enm.mgroup', verbose_name='所在集合')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mpoint_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
],
options={
'abstract': False,
},
),
migrations.CreateModel( migrations.CreateModel(
name='SfLog', name='SfLog',
fields=[ fields=[
@ -157,22 +179,19 @@ class Migration(migrations.Migration):
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name='Mpoint', name='MpointStat',
fields=[ fields=[
('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')), ('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='创建时间')), ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')),
('update_time', models.DateTimeField(auto_now=True, 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='删除标记')), ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')),
('name', models.CharField(max_length=50, verbose_name='测点名称')), ('type', models.CharField(default='hour', help_text='year/month/day/hour', max_length=50, verbose_name='统计维度')),
('code', models.CharField(max_length=50, unique=True, verbose_name='测点编号')), ('year', models.PositiveSmallIntegerField(verbose_name='')),
('unit', models.CharField(max_length=50, verbose_name='单位')), ('month', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='')),
('cate', models.CharField(default='elec', max_length=50, verbose_name='分类')), ('day', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='')),
('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mpoint_belong_dept', to='system.dept', verbose_name='所属部门')), ('hour', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='')),
('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mpoint_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), ('val', models.FloatField(default=0, verbose_name='统计值')),
('ep_belong', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mp_ep_belong', to='em.equipment', verbose_name='属于哪个设备')), ('mpoint', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='enm.mpoint', verbose_name='关联测点')),
('ep_monitored', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mp_ep_monitored', to='em.equipment', verbose_name='监测哪个设备')),
('mgroup', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='enm.mgroup', verbose_name='所在集合')),
('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='mpoint_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
], ],
options={ options={
'abstract': False, 'abstract': False,
@ -195,25 +214,6 @@ class Migration(migrations.Migration):
'abstract': False, 'abstract': False,
}, },
), ),
migrations.CreateModel(
name='HourStat',
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='删除标记')),
('year', models.PositiveSmallIntegerField(verbose_name='')),
('month', models.PositiveSmallIntegerField(verbose_name='')),
('day', models.PositiveSmallIntegerField(verbose_name='')),
('hour', models.PositiveSmallIntegerField(verbose_name='')),
('val', models.FloatField(default=0, verbose_name='统计值')),
('is_calculated', models.BooleanField(default=False, verbose_name='是否计算过')),
('mpoint', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='enm.mpoint', verbose_name='关联测点')),
],
options={
'abstract': False,
},
),
migrations.CreateModel( migrations.CreateModel(
name='Goal', name='Goal',
fields=[ fields=[

View File

@ -94,16 +94,17 @@ class StSfLog(BaseModel):
class Meta: class Meta:
ordering = ['sflog__start_time'] ordering = ['sflog__start_time']
class HourStat(BaseModel):
"""小时统计表 class MpointStat(BaseModel):
"""测点统计表
""" """
type = models.CharField('统计维度', max_length=50, default='hour', help_text='year/month/day/hour')
year = models.PositiveSmallIntegerField('') year = models.PositiveSmallIntegerField('')
month = models.PositiveSmallIntegerField('') month = models.PositiveSmallIntegerField('', null=True, blank=True)
day = models.PositiveSmallIntegerField('') day = models.PositiveSmallIntegerField('', null=True, blank=True)
hour = models.PositiveSmallIntegerField('') hour = models.PositiveSmallIntegerField('', null=True, blank=True)
mpoint = models.ForeignKey(Mpoint, verbose_name='关联测点', on_delete=models.CASCADE) mpoint = models.ForeignKey(Mpoint, verbose_name='关联测点', on_delete=models.CASCADE)
val = models.FloatField('统计值', default=0) val = models.FloatField('统计值', default=0)
is_calculated = models.BooleanField('是否计算过', default=False)
class Goal(CommonADModel): class Goal(CommonADModel):

View File

@ -1,5 +1,5 @@
from apps.utils.serializers import CustomModelSerializer from apps.utils.serializers import CustomModelSerializer
from apps.enm.models import Mpoint, Mgroup, MpLog, Team, SfLog, StLog from apps.enm.models import Mpoint, Mgroup, MpLog, Team, SfLog, StLog, StSfLog
from apps.system.models import Dept from apps.system.models import Dept
from apps.system.serializers import DeptSimpleSerializer from apps.system.serializers import DeptSimpleSerializer
from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
@ -64,3 +64,12 @@ class SfLogSerializer(CustomModelSerializer):
new_data = {key: data[key] for key in u_fields if key in data} new_data = {key: data[key] for key in u_fields if key in data}
return super().to_internal_value(new_data) return super().to_internal_value(new_data)
return super().to_internal_value(data) return super().to_internal_value(data)
class StSfLogSerializer(CustomModelSerializer):
stlog_ = StLogSerializer(source='stlog', read_only=True)
sflog_ = SfLogSerializer(source='sflog', read_only=True)
class Meta:
model = StSfLog
fields = '__all__'
read_only_fields = EXCLUDE_FIELDS + ['stlog', 'sflog', 'is_current_down']

View File

@ -5,8 +5,14 @@ from celery import shared_task
from apps.utils.sql import DbConnection from apps.utils.sql import DbConnection
from server.settings import get_sysconfig from server.settings import get_sysconfig
from django.core.cache import cache from django.core.cache import cache
from apps.enm.models import MpLog, Mpoint, HourStat from apps.enm.models import MpLog, Mpoint, MpointStat
import datetime import datetime
from django.db.models import Sum
def get_current_and_previous_time():
now = datetime.datetime.now()
pre = now - datetime.timedelta(hours=1)
return now, pre
def get_current_and_previous_hour(): def get_current_and_previous_hour():
now = datetime.datetime.now() now = datetime.datetime.now()
@ -47,35 +53,54 @@ def get_tag_val():
mr_one.save() mr_one.save()
@shared_task(base=CustomTask) @shared_task(base=CustomTask)
def cal_hourstat(): def cal_mpointstat_hour(mpointId: str, year: int, month: int, day: int, hour: int):
""" """
计算小时统计量,默认计算本小时和上小时 计算某一测点, 某一时间点某一小时的统计值
""" """
for mpoint in Mpoint.objects.all(): mpoint = Mpoint.objects.get(id=mpointId)
c_t_r, p_t_r = get_current_and_previous_hour() if mpoint.cate == 'elec': # 是否是电能
if mpoint.cate == 'elec': # 是否是电能 params = {'mpoint': mpoint, 'type': 'hour'}
# 计算本小时,可能不需要 params['year'], params['month'], params['day'], params['hour'] = year, month, day, hour
start_time = c_t_r[0] mrs = MpLog.objects.filter(
params = {'mpoint': mpoint} mpoint=mpoint,
params['year'], params['month'], params['day'], params['hour'] = start_time.year, start_time.month, start_time.day, start_time.hour tag_update__year=params['year'],
mrs = MpLog.objects.filter(mpoint=mpoint, tag_update__gte=c_t_r[0], tag_update__lte=c_t_r[1]).order_by('tag_update') tag_update__month=params['month'],
val = 0 tag_update__day=params['day'],
if mrs.exists(): tag_update__hour= params['hour']).order_by('tag_update')
val = mrs.last() - mrs.first() val = 0
hs, _ = HourStat.objects.get_or_create(**params, defaults=params) if mrs.exists():
hs.val = val val = mrs.last() - mrs.first()
hs.save() ms, _ = MpointStat.objects.get_or_create(**params, defaults=params)
ms.val = val
ms.save()
# 更新更高级别的值
sum_dict_day = MpointStat.objects.filter(type='hour', mpoint=mpoint, year=year, month=month, day=day).aggregate(sum=Sum('val'))
params_day = {'type':'day', 'mpoint': mpoint, 'year': year, 'month': month, 'day': day}
ms_day, _ = MpointStat.objects.get_or_create(**params_day, defaults=params_day)
ms_day.val = sum_dict_day['sum']
ms_day.save()
# 计算上小时 sum_dict_month = MpointStat.objects.filter(type='hour', mpoint=mpoint, year=year, month=month).aggregate(sum=Sum('val'))
start_time2 = p_t_r[0] params_month = {'type':'month', 'mpoint': mpoint, 'year': year, 'month': month}
params = {'mpoint': mpoint} ms_month, _ = MpointStat.objects.get_or_create(**params_month, defaults=params_month)
params['year'], params['month'], params['day'], params['hour'] = start_time2.year, start_time2.month, start_time2.day, start_time2.hour ms_month.val = sum_dict_month['sum']
hs, _ = HourStat.objects.get_or_create(**params, defaults=params) ms_month.save()
if not hs.is_calculated:
mrs = MpLog.objects.filter(mpoint=mpoint, tag_update__gte=p_t_r[0], tag_update__lte=p_t_r[1]).order_by('tag_update') sum_dict_year = MpointStat.objects.filter(type='hour', mpoint=mpoint, year=year).aggregate(sum=Sum('val'))
val = 0 params_year = {'type':'year', 'mpoint': mpoint, 'year': year}
if mrs.exists(): ms_year, _ = MpointStat.objects.get_or_create(**params_year, defaults=params_year)
val = mrs.last() - mrs.first() ms_year.val = sum_dict_year['sum']
hs.val = val ms_year.save()
hs.is_calculated = True
hs.save() @shared_task(base=CustomTask)
def cal_mpointstats(is_now=1):
"""
计算所有测点的统计值默认当前小时
"""
now, pre = get_current_and_previous_time()
if is_now:
for mpoint in Mpoint.objects.all():
cal_mpointstat_hour.delay(mpoint.id, now.year, now.moth, now.day, now.hour)
else:
for mpoint in Mpoint.objects.all():
cal_mpointstat_hour.delay(mpoint.id, pre.year, pre.month, pre.day, pre.hour)

View File

@ -1,6 +1,6 @@
from django.urls import path, include from django.urls import path, include
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from apps.enm.views import MpointViewSet, MgroupViewSet, TeamViewSet, MpLogViewSet, SfLogViewSet, StLogViewSet from apps.enm.views import MpointViewSet, MgroupViewSet, TeamViewSet, MpLogViewSet, SfLogViewSet, StLogViewSet, StSfLogViewSet
API_BASE_URL = 'api/enm/' API_BASE_URL = 'api/enm/'
HTML_BASE_URL = 'enm/' HTML_BASE_URL = 'enm/'
@ -12,6 +12,7 @@ router.register('team', TeamViewSet, basename='team')
router.register('mplog', MpLogViewSet, basename='mplog') router.register('mplog', MpLogViewSet, basename='mplog')
router.register('sflog', SfLogViewSet, basename='sflog') router.register('sflog', SfLogViewSet, basename='sflog')
router.register('stlog', StLogViewSet, basename='stlog') router.register('stlog', StLogViewSet, basename='stlog')
router.register('stsflog', StSfLogViewSet, basename='stsflog')
urlpatterns = [ urlpatterns = [
path(API_BASE_URL, include(router.urls)), path(API_BASE_URL, include(router.urls)),
] ]

View File

@ -1,13 +1,18 @@
from django.shortcuts import render from django.shortcuts import render
from apps.enm.models import Mpoint, Mgroup, Team, MpLog, SfLog, StLog, StSfLog from apps.enm.models import Mpoint, Mgroup, Team, MpLog, SfLog, StLog, StSfLog
from apps.utils.viewsets import CustomModelViewSet, GenericViewSet from apps.utils.viewsets import CustomModelViewSet, GenericViewSet
from rest_framework.mixins import ListModelMixin from rest_framework.mixins import ListModelMixin, UpdateModelMixin
from apps.enm.serializers import MpointSerializer, TeamSerializer, MgroupSerializer, MpLogSerializer, SfLogSerializer, StLogSerializer from apps.enm.serializers import MpointSerializer, TeamSerializer, MgroupSerializer, MpLogSerializer, SfLogSerializer, StLogSerializer, StSfLogSerializer
from rest_framework.exceptions import ParseError from rest_framework.exceptions import ParseError
from django.db import transaction from django.db import transaction
from django.db.models import Q from django.db.models import Q
class MgroupViewSet(CustomModelViewSet): class MgroupViewSet(CustomModelViewSet):
"""
list:测点集
测点集
"""
queryset = Mgroup.objects.all() queryset = Mgroup.objects.all()
serializer_class = MgroupSerializer serializer_class = MgroupSerializer
select_related_fields = ['create_by', 'belong_dept'] select_related_fields = ['create_by', 'belong_dept']
@ -16,6 +21,11 @@ class MgroupViewSet(CustomModelViewSet):
class TeamViewSet(CustomModelViewSet): class TeamViewSet(CustomModelViewSet):
"""
list:班组
班组
"""
queryset = Team.objects.all() queryset = Team.objects.all()
serializer_class = TeamSerializer serializer_class = TeamSerializer
select_related_fields = ['belong_dept', 'leader'] select_related_fields = ['belong_dept', 'leader']
@ -24,6 +34,11 @@ class TeamViewSet(CustomModelViewSet):
class MpointViewSet(CustomModelViewSet): class MpointViewSet(CustomModelViewSet):
"""
list:测点
测点
"""
queryset = Mpoint.objects.all() queryset = Mpoint.objects.all()
serializer_class = MpointSerializer serializer_class = MpointSerializer
select_related_fields = ['create_by', 'belong_dept', 'ep_monitored', 'ep_belong', 'mgroup'] select_related_fields = ['create_by', 'belong_dept', 'ep_monitored', 'ep_belong', 'mgroup']
@ -32,6 +47,11 @@ class MpointViewSet(CustomModelViewSet):
class MpLogViewSet(ListModelMixin, GenericViewSet): class MpLogViewSet(ListModelMixin, GenericViewSet):
"""
list:测点原始记录
测点原始记录
"""
queryset = MpLog.objects.all() queryset = MpLog.objects.all()
serializer_class = MpLogSerializer serializer_class = MpLogSerializer
select_related_fields = ['mpoint'] select_related_fields = ['mpoint']
@ -39,6 +59,11 @@ class MpLogViewSet(ListModelMixin, GenericViewSet):
class StLogViewSet(ListModelMixin, GenericViewSet): class StLogViewSet(ListModelMixin, GenericViewSet):
"""
list:停机记录
停机记录
"""
queryset = StLog.objects.all() queryset = StLog.objects.all()
serializer_class = StLogSerializer serializer_class = StLogSerializer
select_related_fields = ['mgroup'] select_related_fields = ['mgroup']
@ -47,6 +72,11 @@ class StLogViewSet(ListModelMixin, GenericViewSet):
class SfLogViewSet(CustomModelViewSet): class SfLogViewSet(CustomModelViewSet):
"""
list:值班记录
值班记录
"""
queryset = SfLog.objects.all() queryset = SfLog.objects.all()
serializer_class = SfLogSerializer serializer_class = SfLogSerializer
select_related_fields = ['mgroup', 'shift', 'team', 'leader'] select_related_fields = ['mgroup', 'shift', 'team', 'leader']
@ -67,3 +97,22 @@ class SfLogViewSet(CustomModelViewSet):
if stsflog: if stsflog:
stsflog.is_current_down = True stsflog.is_current_down = True
stsflog.save() stsflog.save()
class StSfLogViewSet(ListModelMixin, UpdateModelMixin, GenericViewSet):
"""
list:值班停机关系
值班停机关系
"""
queryset = StSfLog.objects.all()
serializer_class = StSfLogSerializer
select_related_fields = ['stlog', 'sflog']
filterset_fields = ['stlog', 'sflog']
search_fields = ['reason']
def filter_queryset(self, queryset):
params = self.request.query_params
if 'stlog' not in params or 'sflog' not in params:
raise ParseError('请指定所属停机或值班记录')
return super().filter_queryset(queryset)