feat: enm添加xscript

This commit is contained in:
caoqianming 2024-08-27 17:28:30 +08:00
parent 066ddb59c9
commit 2be34d3caa
6 changed files with 158 additions and 6 deletions

View File

@ -0,0 +1,34 @@
# Generated by Django 3.2.12 on 2024-08-27 04:20
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('system', '0005_alter_permission_type'),
('django_celery_beat', '0016_alter_crontabschedule_timezone'),
('enm', '0042_enstat2_out_cement_cost_unit'),
]
operations = [
migrations.CreateModel(
name='Xscript',
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.TextField(blank=True, null=True, verbose_name='脚本内容')),
('base_data', models.JSONField(blank=True, default=dict, null=True, verbose_name='基础数据')),
('myschedule', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='system.myschedule', verbose_name='周期')),
('periodictask', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='xscript_periodictask', to='django_celery_beat.periodictask', verbose_name='关联定时任务')),
],
options={
'abstract': False,
},
),
]

View File

@ -2,7 +2,14 @@ from django.db import models
from apps.utils.models import BaseModel, CommonBModel, CommonADModel, CommonBDModel
from apps.wpm.models import SfLog
from apps.mtm.models import Material, Mgroup, Team
from django_celery_beat.models import PeriodicTask
class Xscript(BaseModel):
name = models.CharField("脚本名称", max_length=50)
code = models.TextField("脚本内容", null=True, blank=True)
base_data = models.JSONField("基础数据", default=dict, null=True, blank=True)
myschedule = models.ForeignKey('system.myschedule', verbose_name='周期', on_delete=models.SET_NULL, null=True, blank=True)
periodictask = models.ForeignKey(PeriodicTask, verbose_name='关联定时任务', on_delete=models.CASCADE, related_name='xscript_periodictask', null=True, blank=True)
class Mpoint(CommonBModel):
"""测点"""

View File

@ -1,10 +1,14 @@
from apps.utils.serializers import CustomModelSerializer
from apps.enm.models import Mpoint, MpointStat, EnStat, EnStat2, MpLogx
from apps.utils.constants import EXCLUDE_FIELDS
from apps.enm.models import Mpoint, MpointStat, EnStat, EnStat2, MpLogx, Xscript
from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
from rest_framework import serializers
from apps.mtm.models import Mgroup
from rest_framework.exceptions import ParseError
from django.core.cache import cache
from django.db import transaction
from django_celery_beat.models import PeriodicTask
import json
from apps.utils.tools import CodeAnalyzer
class MpointSerializer(CustomModelSerializer):
@ -185,3 +189,64 @@ class MpointStatCorrectSerializer(CustomModelSerializer):
class EnStatAnaSerializer(serializers.Serializer):
start_date = serializers.DateField(label="开始日期")
end_date = serializers.DateField(label="结束日期")
class XscriptSerializer(CustomModelSerializer):
myschedule_name = serializers.CharField(source="myschedule.name", read_only=True)
enabled = serializers.BooleanField(source='periodictask.enabled', read_only=True)
last_run_at = serializers.DateTimeField(source='periodictask.last_run_at', read_only=True)
total_run_count = serializers.IntegerField(source='periodictask.total_run_count', read_only=True)
class Meta:
model = Xscript
fields = "__all__"
read_only_fields = EXCLUDE_FIELDS_BASE + ['periodictask']
def validate(self, attrs):
code = attrs['code']
analyzer = CodeAnalyzer()
analyzer.analyze(code)
if analyzer.errors:
raise ParseError(f'脚本错误:{analyzer.errors[0]}')
return super().validate(attrs)
@transaction.atomic
def create(self, validated_data):
ins: Xscript = super().create(validated_data)
pobj = PeriodicTask()
pobj.name = f'{ins.name}_{str(ins.id)[-8:]}'
pobj.task = 'apps.enm.tasks.insert_mplogx_from_xscript'
sch = ins.myschedule
if sch.crontab:
pobj.crontab = sch.crontab
elif sch.interval:
pobj.interval = sch.interval
else:
raise ParseError('不支持的定时策略')
pobj.kwargs = json.dumps({'xscript_id': ins.id})
pobj.enabled = False
pobj.save()
ins.periodictask = pobj
ins.save()
return ins
@transaction.atomic
def update(self, instance, validated_data):
ins = super().update(instance, validated_data)
pobj = instance.periodictask
pobj.name = f'{ins.name}_{str(ins.id)[-8:]}'
sch = ins.myschedule
if sch.crontab:
pobj.crontab = sch.crontab
elif sch.interval:
pobj.interval = sch.interval
else:
raise ParseError('不支持的定时策略')
pobj.save()
return ins
class XscriptDetailSerializer(XscriptSerializer):
last_run_data = serializers.SerializerMethodField()
def get_last_run_data(self, obj):
return {}

View File

@ -2,7 +2,7 @@
from __future__ import absolute_import, unicode_literals
from apps.utils.tasks import CustomTask
from celery import shared_task
from apps.enm.models import MpLogx, Mpoint, MpointStat, EnStat, EnStat2
from apps.enm.models import MpLogx, Mpoint, MpointStat, EnStat, EnStat2, Xscript
from apps.wpm.models import SfLog
import datetime
from django.db.models import Sum, Avg
@ -37,6 +37,19 @@ def get_current_and_previous_time():
pre = now - datetime.timedelta(hours=1)
return now, pre
@shared_task(base=CustomTask)
def insert_mplogx_from_xscript(xscript_id):
xscript = Xscript.objects.get(id=xscript_id)
eval_code = """
from apps.utils.sql import DbConnection
from apps.enm.tasks import db_insert_mplogx_batch
import datetime
from django.utils import timezone
{code}
""".format(code=xscript.code)
exec(eval_code)
def db_insert_mplogx_batch(rows):
for row in rows:

View File

@ -1,6 +1,7 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from apps.enm.views import (MpointViewSet, MpLogxViewSet, MpointStatViewSet, EnStatViewSet, EnStat2ViewSet)
from apps.enm.views import (MpointViewSet, MpLogxViewSet, MpointStatViewSet,
EnStatViewSet, EnStat2ViewSet, XscriptViewSet)
API_BASE_URL = 'api/enm/'
HTML_BASE_URL = 'enm/'
@ -11,6 +12,7 @@ router.register('mplogx', MpLogxViewSet, basename='mplogx')
router.register('mpointstat', MpointStatViewSet, basename='mpointstat')
router.register('enstat', EnStatViewSet, basename='enstat')
router.register('enstat2', EnStat2ViewSet, basename='enstat2')
router.register('xscript', XscriptViewSet, basename='xscript')
urlpatterns = [
path(API_BASE_URL, include(router.urls)),
]

View File

@ -1,8 +1,10 @@
from django.conf import settings
from apps.enm.models import Mpoint, MpointStat, EnStat, EnStat2, MpLogx
from apps.enm.models import Mpoint, MpointStat, EnStat, EnStat2, MpLogx, Xscript
from apps.utils.viewsets import CustomModelViewSet, CustomGenericViewSet
from apps.utils.mixins import BulkCreateModelMixin, BulkDestroyModelMixin, CustomListModelMixin
from apps.enm.serializers import (MpointSerializer, MpLogxSerializer, MpointStatSerializer, EnStatSerializer, EnStat2Serializer, ReCalSerializer, MpointStatCorrectSerializer, EnStatAnaSerializer)
from apps.enm.serializers import (MpointSerializer, MpLogxSerializer, MpointStatSerializer,
EnStatSerializer, EnStat2Serializer, ReCalSerializer,
MpointStatCorrectSerializer, EnStatAnaSerializer, XscriptSerializer)
from apps.enm.filters import MpointStatFilter, EnStatFilter, EnStat2Filter
from apps.enm.tasks import cal_mpointstat_manual
from rest_framework.response import Response
@ -66,6 +68,35 @@ class MpointViewSet(CustomModelViewSet):
return Response()
class XscriptViewSet(CustomModelViewSet):
"""
list:执行脚本
执行脚本
"""
queryset = Xscript.objects.all()
serializer_class = XscriptSerializer
select_related_fields = ["myschedule", "periodictask"]
search_fields = ['name']
@action(methods=['put'], detail=True, perms_map={'put': 'xscript.update'})
def toggle(self, request, pk=None):
"""修改启用禁用状态
修改启用禁用状态
"""
obj = self.get_object()
periodictask = obj.periodictask
periodictask.enabled = False if periodictask.enabled else True
periodictask.save()
return Response()
@transaction.atomic
def perform_destroy(self, instance):
periodictask = instance.periodictask
instance.delete()
periodictask.delete()
# class MpLogViewSet(ListModelMixin, CustomGenericViewSet):
# """
# list:测点原始记录