Merge branch 'v2' of https://e.coding.net/ctcdevteam/ehs/ehs_server into v2
This commit is contained in:
commit
006f0ace98
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class DpmConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'dpm'
|
||||||
|
verbose_name = '双重预防'
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
from django.db import models
|
||||||
|
from apps.utils.models import CommonBModel, CommonAModel
|
||||||
|
from django_celery_beat.models import PeriodicTask
|
||||||
|
|
||||||
|
# Create your models here.
|
||||||
|
class RiskPoint(CommonBModel):
|
||||||
|
"""
|
||||||
|
风险点表
|
||||||
|
"""
|
||||||
|
R_LEVEL = (
|
||||||
|
(10, '低风险'),
|
||||||
|
(20, '一般风险'),
|
||||||
|
(30, '较大风险'),
|
||||||
|
(40, '重大风险')
|
||||||
|
)
|
||||||
|
R_TYPE = (
|
||||||
|
(10, '作业活动类'),
|
||||||
|
(20, '设备设施类')
|
||||||
|
)
|
||||||
|
R_M_LEVEL = (
|
||||||
|
(10, '岗位级'),
|
||||||
|
(20, '班组级'),
|
||||||
|
(30, '部门级'),
|
||||||
|
(40, '公司级')
|
||||||
|
)
|
||||||
|
name = models.CharField('名称', max_length=40)
|
||||||
|
area = models.ForeignKey('am.area', on_delete=models.CASCADE, verbose_name='所在区域', related_name='riskpoint_area', null=True, blank=True)
|
||||||
|
place = models.CharField('具体地点', max_length=100, null=True, blank=True)
|
||||||
|
level = models.PositiveSmallIntegerField('风险点等级', default=10, choices=R_LEVEL)
|
||||||
|
type = models.PositiveSmallIntegerField('风险点类型', default=10, choices=R_TYPE)
|
||||||
|
manage_level = models.PositiveSmallIntegerField('管控层级', default=10, choices=R_M_LEVEL)
|
||||||
|
dept_res = models.ForeignKey('system.dept', on_delete=models.SET_NULL, verbose_name='责任部门', related_name='riskpoint_dept_res', null=True, blank=True)
|
||||||
|
user_res = models.ForeignKey('system.user', on_delete=models.CASCADE, verbose_name='责任人', related_name='hazard_user_discover', null=True, blank=True)
|
||||||
|
|
||||||
|
class Risk(CommonBModel):
|
||||||
|
"""
|
||||||
|
风险表
|
||||||
|
"""
|
||||||
|
name = models.TextField('项目/步骤')
|
||||||
|
level = models.PositiveSmallIntegerField('风险等级', default=10, choices=RiskPoint.R_LEVEL)
|
||||||
|
standard = models.TextField('检查标准', null=True, blank=True)
|
||||||
|
hazard = models.TextField('危害因素', null=True, blank=True)
|
||||||
|
results = models.ManyToManyField('system.dictionary', verbose_name='可能后果', related_name='risk_results', null=True)
|
||||||
|
sort = models.PositiveSmallIntegerField('排序', default=1)
|
||||||
|
measure_tech = models.TextField('工程技术措施', null=True, blank=True)
|
||||||
|
measure_manage = models.TextField('管理措施', null=True, blank=True)
|
||||||
|
measure_edu = models.TextField('培训教育措施', null=True, blank=True)
|
||||||
|
measure_protect = models.TextField('个体防护措施', null=True, blank=True)
|
||||||
|
measure_emer = models.TextField('应急处置措施', null=True, blank=True)
|
||||||
|
riskl = models.DecimalField(max_digits=6, decimal_places=1, null=True, blank=True)
|
||||||
|
riske = models.DecimalField(max_digits=6, decimal_places=1, null=True, blank=True)
|
||||||
|
riskc = models.DecimalField(max_digits=6, decimal_places=1, null=True, blank=True)
|
||||||
|
riskd = models.DecimalField(max_digits=6, decimal_places=1, null=True, blank=True)
|
||||||
|
riskpoint = models.ForeignKey(RiskPoint, on_delete=models.CASCADE, verbose_name='所属风险点')
|
||||||
|
|
||||||
|
|
||||||
|
class CheckTaskSet(CommonBModel):
|
||||||
|
"""
|
||||||
|
检查任务派发设置
|
||||||
|
"""
|
||||||
|
riskpoint = models.ForeignKey(RiskPoint, verbose_name='关联风险点', related_name='ctask_riskpoint', on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
|
note = models.TextField('派发备注', null=True, blank=True)
|
||||||
|
expire = models.PositiveSmallIntegerField('执行有效期(h)', default=0, help_text='0代表不设限制直到下个任务派发')
|
||||||
|
user_duty = models.ForeignKey('system.user', verbose_name='指派人', on_delete=models.SET_NULL, 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='checktask_periodictask')
|
||||||
|
|
||||||
|
|
||||||
|
class CheckWork(CommonBModel):
|
||||||
|
"""
|
||||||
|
检查工作
|
||||||
|
"""
|
||||||
|
CW_TYPE = (
|
||||||
|
(10, '手动'),
|
||||||
|
(20, '派发')
|
||||||
|
)
|
||||||
|
name = models.CharField('名称', max_length=40)
|
||||||
|
description = models.TextField('工作描述', null=True, blank=True)
|
||||||
|
type = models.PositiveSmallIntegerField('任务类型', default=10, choices=CW_TYPE)
|
||||||
|
category = models.ForeignKey('system.dictionary', on_delete=models.CASCADE, verbose_name='工作分类', null=True, blank=True)
|
||||||
|
time_start = models.DateTimeField('开启时间')
|
||||||
|
time_end = models.DateTimeField('关闭时间')
|
||||||
|
enabled = models.BooleanField('是否可用', default=True)
|
||||||
|
user_duty = models.ForeignKey('system.user', verbose_name='指派人', on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
|
riskpoint = models.ForeignKey(RiskPoint, verbose_name='关联风险点', related_name='cwork_riskpoint', on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
|
note = models.TextField('检查备注', null=True, blank=True)
|
||||||
|
time_check = models.BooleanField('最后检查时间', default=True)
|
||||||
|
checktaskset = models.ForeignKey(CheckTaskSet, verbose_name='关联派发任务', on_delete=models.CASCADE, null=True, blank=True)
|
||||||
|
|
||||||
|
|
||||||
|
class Hazard(CommonBModel):
|
||||||
|
"""
|
||||||
|
事故隐患表
|
||||||
|
"""
|
||||||
|
H_HARM = (
|
||||||
|
(10, '无伤害'),
|
||||||
|
(20, '轻微伤'),
|
||||||
|
(30, '轻伤'),
|
||||||
|
(40, '重伤'),
|
||||||
|
(50, '死亡')
|
||||||
|
)
|
||||||
|
H_LEVEL = (
|
||||||
|
(10, '无隐患'),
|
||||||
|
(20, '一般隐患'),
|
||||||
|
(30, '重大隐患')
|
||||||
|
)
|
||||||
|
H_STATE = (
|
||||||
|
(10, '待提交'),
|
||||||
|
(20, '流程中'),
|
||||||
|
(30, '已结束')
|
||||||
|
)
|
||||||
|
number = models.CharField('编号', max_length=20, null=True, blank=True)
|
||||||
|
checkwork = models.ForeignKey(CheckWork, verbose_name='关联检查工作', null=True, blank=True)
|
||||||
|
state = models.PositiveSmallIntegerField('隐患流程状态', default=10, choices=H_STATE)
|
||||||
|
time_discover = models.DateTimeField('发现时间')
|
||||||
|
dept_res = models.ForeignKey('system.dept', on_delete=models.SET_NULL, verbose_name='责任部门', related_name='hazard_dept_res', null=True, blank=True)
|
||||||
|
user_discover = models.ForeignKey('system.user', on_delete=models.CASCADE, verbose_name='发现人', related_name='hazard_user_discover')
|
||||||
|
area = models.ForeignKey('am.area', on_delete=models.CASCADE, verbose_name='所在区域', null=True, blank=True)
|
||||||
|
place = models.CharField('具体地点', max_length=100, null=True, blank=True)
|
||||||
|
level = models.PositiveSmallIntegerField('隐患等级', default=10, choices=H_LEVEL)
|
||||||
|
harm_access = models.PositiveSmallIntegerField('伤害评估', default=10, choices=H_HARM)
|
||||||
|
category = models.ForeignKey('system.dictionary', on_delete=models.CASCADE, verbose_name='隐患类别', null=True, blank=True)
|
||||||
|
description = models.TextField('隐患描述', null=True, blank=True)
|
||||||
|
reason = models.TextField('原因分析', null=True, blank=True)
|
||||||
|
correct_measure = models.TextField('整改措施', null=True, blank=True)
|
||||||
|
correct_solution = models.ForeignKey('system.file', verbose_name='整改方案', null=True, blank=True)
|
||||||
|
correct_deadline = models.DateTimeField('整改期限', null=True, blank=True)
|
||||||
|
photos = models.ManyToManyField('system.file', verbose_name='现场照片', related_name='hazard_photos', null=True)
|
||||||
|
correct_description = models.TextField('整改描述', null=True, blank=True)
|
||||||
|
photos_done = models.ManyToManyField('system.file', verbose_name='整改后照片', related_name='hazard_photos_done', null=True)
|
||||||
|
dept_correct = models.ForeignKey('system.dept', on_delete=models.CASCADE, verbose_name='整改部门', related_name='hazard_dept_correct', null=True, blank=True)
|
||||||
|
user_correct = models.ForeignKey('system.user', on_delete=models.SET_NULL, verbose_name='整改责任人', related_name='hazard_user_correct', null=True, blank=True)
|
||||||
|
correct_time = models.DateTimeField('整改完成时间', null=True, blank=True)
|
||||||
|
user_access = models.ForeignKey('system.user', on_delete=models.CASCADE, verbose_name='评估人', related_name='hazard_user_access')
|
||||||
|
opinion_access = models.TextField('评估意见', null=True, blank=True)
|
||||||
|
user_check = models.ForeignKey('system.user', on_delete=models.CASCADE, verbose_name='复查人', related_name='hazard_user_check')
|
||||||
|
opinion_check = models.TextField('复查意见', null=True, blank=True)
|
||||||
|
user_audit = models.ForeignKey('system.user', on_delete=models.CASCADE, verbose_name='审核人', related_name='hazard_user_audit')
|
||||||
|
opinion_audit = models.TextField('审核意见', null=True, blank=True)
|
||||||
|
ticket = models.ForeignKey('wf.ticket', on_delete=models.SET_NULL, verbose_name='关联工单', related_name='hazard_ticket', null=True, blank=True)
|
||||||
|
|
||||||
|
|
||||||
|
class CheckItem(CommonAModel):
|
||||||
|
"""
|
||||||
|
检查工作-隐患关联表
|
||||||
|
"""
|
||||||
|
CITEM_RESULT = (
|
||||||
|
(10, '未检查'),
|
||||||
|
(20, '合格'),
|
||||||
|
(30, '不合格')
|
||||||
|
)
|
||||||
|
checkwork = models.ForeignKey(CheckWork, verbose_name='关联检查工作', related_name='citem_checkwork', on_delete=models.CASCADE)
|
||||||
|
risk = models.ForeignKey(Risk, verbose_name='关联风险', related_name='citem_risk', on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
|
hazard = models.ForeignKey(Hazard, verbose_name='关联隐患', related_name='citem_hazard', on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
|
result = models.PositiveSmallIntegerField('检查结果', default=10)
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
import json
|
||||||
|
from apps.dpm.models import CheckTaskSet, CheckWork, RiskPoint, Risk
|
||||||
|
from rest_framework import serializers
|
||||||
|
from apps.utils.serializers import CustomModelSerializer
|
||||||
|
from apps.utils.constants import EXCLUDE_FIELDS
|
||||||
|
from apps.system.models import Dictionary
|
||||||
|
from django_celery_beat.models import PeriodicTask
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class RiskPointCreateUpdateSerializer(CustomModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = RiskPoint
|
||||||
|
exclude = EXCLUDE_FIELDS
|
||||||
|
|
||||||
|
|
||||||
|
class RiskPointSerializer(CustomModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = RiskPoint
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class RiskCreateUpdateSerializer(CustomModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Risk
|
||||||
|
exclude = EXCLUDE_FIELDS + ['riskd']
|
||||||
|
|
||||||
|
def save(self, **kwargs):
|
||||||
|
obj = super().save(**kwargs)
|
||||||
|
if obj.riskl and obj.riske and obj.riskc:
|
||||||
|
obj.riskd = obj.riskl * obj.riske * obj.riskc
|
||||||
|
if obj.riskd >= 320:
|
||||||
|
obj.level = 40
|
||||||
|
elif 320 > obj.riskd >= 160:
|
||||||
|
obj.level = 30
|
||||||
|
elif 160 > obj.riskd >= 70:
|
||||||
|
obj.level = 20
|
||||||
|
else:
|
||||||
|
obj.level = 10
|
||||||
|
obj.save()
|
||||||
|
self.cal_riskpoint_level(obj)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def cal_riskpoint_level(risk):
|
||||||
|
"""
|
||||||
|
计算风险点风险等级
|
||||||
|
"""
|
||||||
|
riskpoint = risk.riskpoint
|
||||||
|
levels = Risk.objects.filter(riskpoint=riskpoint).values_list('level', flat=True)
|
||||||
|
riskpoint.level = max(levels)
|
||||||
|
riskpoint.save()
|
||||||
|
RiskCreateUpdateSerializer.cal_area_level(riskpoint)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def cal_area_level(riskpoint):
|
||||||
|
"""
|
||||||
|
计算区域风险等级
|
||||||
|
"""
|
||||||
|
area = riskpoint.area
|
||||||
|
if area:
|
||||||
|
levels = RiskPoint.objects.filter(area=area).values_list('level', flat=True)
|
||||||
|
area.level = max(levels)
|
||||||
|
area.save()
|
||||||
|
|
||||||
|
|
||||||
|
class RiskSerializer(CustomModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Risk
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class CheckTaskSetCreateUpdateSerializer(CustomModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = CheckTaskSet
|
||||||
|
exclude = EXCLUDE_FIELDS + ['periodictask']
|
||||||
|
|
||||||
|
def save(self, **kwargs):
|
||||||
|
ins = super().save(**kwargs)
|
||||||
|
if ins.periodictask:
|
||||||
|
pobj = ins.periodictask
|
||||||
|
pobj.name = 'checktask_' + time.strftime('%Y%m%d%H%M%S')
|
||||||
|
pobj.task = 'apps.dpm.dispath_checkwork_task'
|
||||||
|
pobj.kwargs = json.dumps({'checktaskset': ins.id})
|
||||||
|
else:
|
||||||
|
pobj = PeriodicTask()
|
||||||
|
sch = ins.myschedule
|
||||||
|
if sch.crontab:
|
||||||
|
pobj.crontab = sch.crontab
|
||||||
|
elif sch.interval:
|
||||||
|
pobj.interval = sch.interval
|
||||||
|
pobj.save()
|
||||||
|
ins.periodictask = pobj
|
||||||
|
ins.save()
|
||||||
|
return ins
|
||||||
|
|
||||||
|
|
||||||
|
class CheckTaskSetSerializer(CustomModelSerializer):
|
||||||
|
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 = CheckTaskSet
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class CheckWork_10_CreateUpdateSerializer(CustomModelSerializer):
|
||||||
|
category = serializers.PrimaryKeyRelatedField(
|
||||||
|
label='检查分类', queryset=Dictionary.objects.filter(type__code='checkwork_category'))
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = CheckWork
|
||||||
|
fields = ['name', 'description', 'category', 'time_start', 'time_end', 'enabled']
|
||||||
|
|
||||||
|
def save(self, **kwargs):
|
||||||
|
kwargs['type'] = 10 # 创建/编辑只有手动类型
|
||||||
|
return super().save(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class CheckWorkSerializer(CustomModelSerializer):
|
||||||
|
category_name = serializers.CharField(source='category.name', read_only=True)
|
||||||
|
user_duty_name = serializers.CharField(source='user_duty.name', read_only=True)
|
||||||
|
riskpoint_name = serializers.CharField(source='riskpoint.name', read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = CheckWork
|
||||||
|
fields = '__all__'
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
from apps.utils.tasks import CustomTask
|
||||||
|
from celery import shared_task
|
||||||
|
from apps.dpm.models import CheckTaskSet, CheckWork
|
||||||
|
from django.utils import timezone
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(base=CustomTask)
|
||||||
|
def dispath_checkwork_task(checktaskset: str):
|
||||||
|
cts = CheckTaskSet.objects.get(id=checktaskset)
|
||||||
|
cw = CheckWork()
|
||||||
|
cw.type = 20
|
||||||
|
cw.checktaskset = cts
|
||||||
|
cw.name = '风险点检查(自动派发)'
|
||||||
|
now = timezone.now()
|
||||||
|
cw.time_start = now
|
||||||
|
if cts.expire:
|
||||||
|
cw.time_end = now + timedelta(hours=cts.expire)
|
||||||
|
cw.user_duty = cts.user_duty
|
||||||
|
cw.riskpoint = cts.riskpoint
|
||||||
|
cw.note = cts.note
|
||||||
|
cw.save()
|
||||||
|
# 发送通知
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(base=CustomTask)
|
||||||
|
def expire_checkwork():
|
||||||
|
now = timezone.now()
|
||||||
|
CheckWork.objects.filter(expire__gte=now).update(enabled=False)
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
from apps.dpm.views import RiskPointViewSet, RiskViewSet
|
||||||
|
from django.urls import path, include
|
||||||
|
from rest_framework.routers import DefaultRouter
|
||||||
|
|
||||||
|
API_BASE_URL = 'api/dpm/'
|
||||||
|
HTML_BASE_URL = 'dpm/'
|
||||||
|
# cache_areas_info()
|
||||||
|
router = DefaultRouter()
|
||||||
|
router.register('riskpoint', RiskPointViewSet, basename='riskpoint')
|
||||||
|
router.register('risk', RiskViewSet, basename='risk')
|
||||||
|
urlpatterns = [
|
||||||
|
path(API_BASE_URL, include(router.urls)),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
from apps.dpm.serializers import RiskPointCreateUpdateSerializer, RiskPointSerializer, RiskCreateUpdateSerializer, RiskSerializer, CheckTaskSetCreateUpdateSerializer, CheckTaskSetSerializer, CheckWork_10_CreateUpdateSerializer, CheckWorkSerializer
|
||||||
|
from apps.utils.viewsets import CustomModelViewSet
|
||||||
|
from apps.dpm.models import CheckTaskSet, CheckWork, RiskPoint, Risk
|
||||||
|
from rest_framework.decorators import action
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
|
||||||
|
# Create your views here.
|
||||||
|
class RiskPointViewSet(CustomModelViewSet):
|
||||||
|
queryset = RiskPoint.objects.all()
|
||||||
|
create_serializer_class = RiskPointCreateUpdateSerializer
|
||||||
|
update_serializer_class = RiskPointCreateUpdateSerializer
|
||||||
|
serializer_class = RiskPointSerializer
|
||||||
|
select_related_fields = ['area', 'dept_res', 'user_res']
|
||||||
|
search_fields = ['name']
|
||||||
|
filterset_fields = ['area', 'type', 'level', 'manage_level']
|
||||||
|
|
||||||
|
|
||||||
|
class RiskViewSet(CustomModelViewSet):
|
||||||
|
queryset = Risk.objects.all()
|
||||||
|
create_serializer_class = RiskCreateUpdateSerializer
|
||||||
|
update_serializer_class = RiskCreateUpdateSerializer
|
||||||
|
serializer_class = RiskSerializer
|
||||||
|
select_related_fields = ['riskpoint']
|
||||||
|
prefetch_related_fields = ['results']
|
||||||
|
search_fields = ['name']
|
||||||
|
filterset_fields = ['results']
|
||||||
|
|
||||||
|
|
||||||
|
class CheckTaskSetViewSet(CustomModelViewSet):
|
||||||
|
queryset = CheckTaskSet.objects.all()
|
||||||
|
create_serializer_class = CheckTaskSetCreateUpdateSerializer
|
||||||
|
update_serializer_class = CheckTaskSetCreateUpdateSerializer
|
||||||
|
serializer_class = CheckTaskSetSerializer
|
||||||
|
select_related_fields = ['periodictask']
|
||||||
|
search_fields = ['note']
|
||||||
|
filterset_fields = ['periodictask__enabled']
|
||||||
|
|
||||||
|
@action(methods=['put'], detail=True, perms_map={'put': 'checktaskset.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()
|
||||||
|
|
||||||
|
def perform_destroy(self, instance):
|
||||||
|
with transaction.atomic():
|
||||||
|
periodictask = instance.periodictask
|
||||||
|
instance.delete()
|
||||||
|
periodictask.enabled = False
|
||||||
|
periodictask.save()
|
||||||
|
|
||||||
|
|
||||||
|
class CheckWorkViewSet(CustomModelViewSet):
|
||||||
|
queryset = CheckWork.objects.all()
|
||||||
|
create_serializer_class = CheckWork_10_CreateUpdateSerializer
|
||||||
|
update_serializer_class = CheckWork_10_CreateUpdateSerializer
|
||||||
|
serializer_class = CheckWorkSerializer
|
||||||
|
search_fields = ['name', 'description']
|
||||||
|
select_related_fields = ['category', 'user_duty', 'riskpoint']
|
||||||
|
filterset_fields = ['type', 'category', 'riskpoint']
|
||||||
|
|
||||||
|
|
||||||
|
class HazardViewSet(CustomModelViewSet):
|
||||||
|
pass
|
||||||
|
|
@ -40,7 +40,7 @@ class AlgoChannel(BaseModel):
|
||||||
|
|
||||||
algo = models.ForeignKey(EventCate, verbose_name='关联算法', on_delete=models.CASCADE)
|
algo = models.ForeignKey(EventCate, verbose_name='关联算法', on_delete=models.CASCADE)
|
||||||
vchannel = models.ForeignKey(TDevice, verbose_name='视频通道', on_delete=models.CASCADE)
|
vchannel = models.ForeignKey(TDevice, verbose_name='视频通道', on_delete=models.CASCADE)
|
||||||
always_on = models.BooleanField("始终开启", default=True)
|
always_on = models.BooleanField("实时开启", default=False)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = ('algo', 'vchannel')
|
unique_together = ('algo', 'vchannel')
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ from django.contrib.auth.models import UserManager
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.contrib.auth.models import AbstractUser
|
from django.contrib.auth.models import AbstractUser
|
||||||
from apps.utils.models import CommonADModel, CommonAModel, CommonBModel, BaseModel, SoftDeletableManagerMixin
|
from apps.utils.models import CommonADModel, CommonAModel, CommonBModel, BaseModel, SoftDeletableManagerMixin
|
||||||
|
from django_celery_beat.models import IntervalSchedule, CrontabSchedule
|
||||||
|
|
||||||
|
|
||||||
class DataFilter(models.IntegerChoices):
|
class DataFilter(models.IntegerChoices):
|
||||||
|
|
@ -237,3 +238,17 @@ class File(CommonAModel):
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
|
class MySchedule(CommonAModel):
|
||||||
|
"""
|
||||||
|
常用周期
|
||||||
|
"""
|
||||||
|
MS_TYPE = (
|
||||||
|
(10, '间隔'),
|
||||||
|
(20, '定时')
|
||||||
|
)
|
||||||
|
name = models.CharField('名称', max_length=200)
|
||||||
|
type = models.PositiveSmallIntegerField('周期类型', default=10)
|
||||||
|
interval = models.ForeignKey(IntervalSchedule, on_delete=models.PROTECT, null=True, blank=True)
|
||||||
|
crontab = models.ForeignKey(CrontabSchedule, on_delete=models.PROTECT, null=True, blank=True)
|
||||||
|
|
@ -9,7 +9,7 @@ from apps.utils.fields import MyFilePathField
|
||||||
from apps.utils.serializers import CustomModelSerializer
|
from apps.utils.serializers import CustomModelSerializer
|
||||||
from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
|
from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
|
||||||
from apps.utils.tools import check_phone_e
|
from apps.utils.tools import check_phone_e
|
||||||
from .models import (Dictionary, DictType, File, Dept, Permission, Post, PostRole,
|
from .models import (Dictionary, DictType, File, Dept, MySchedule, Permission, Post, PostRole,
|
||||||
Role, User, UserPost)
|
Role, User, UserPost)
|
||||||
from rest_framework.exceptions import ParseError, ValidationError
|
from rest_framework.exceptions import ParseError, ValidationError
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
@ -385,7 +385,6 @@ class PostRoleCreateSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
class UserInfoSerializer(CustomModelSerializer):
|
class UserInfoSerializer(CustomModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ['id', 'username', 'name', 'post', 'avatar', 'belong_dept', 'type']
|
fields = ['id', 'username', 'name', 'post', 'avatar', 'belong_dept', 'type']
|
||||||
|
|
@ -395,3 +394,41 @@ class ApkSerializer(serializers.Serializer):
|
||||||
version = serializers.CharField(label='版本号')
|
version = serializers.CharField(label='版本号')
|
||||||
file = serializers.CharField(label='文件地址')
|
file = serializers.CharField(label='文件地址')
|
||||||
|
|
||||||
|
|
||||||
|
class IntervalScheduleSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = IntervalSchedule
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
|
||||||
|
class CrontabScheduleSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = CrontabSchedule
|
||||||
|
exclude = ['timezone']
|
||||||
|
|
||||||
|
|
||||||
|
class MyScheduleCreateSerializer(CustomModelSerializer):
|
||||||
|
interval_ = IntervalScheduleSerializer(allow_null=True, required=False)
|
||||||
|
crontab_ = CrontabScheduleSerializer(allow_null=True, required=False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = MySchedule
|
||||||
|
fields = ['name', 'type', 'interval_', 'crontab_']
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
if attrs['type'] == 10 and attrs.get('interval_', None):
|
||||||
|
pass
|
||||||
|
elif attrs['type'] == 20 and attrs.get('crontab_', None):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise ValidationError('信息有误')
|
||||||
|
return super().validate(attrs)
|
||||||
|
|
||||||
|
|
||||||
|
class MyScheduleSerializer(CustomModelSerializer):
|
||||||
|
interval_ = IntervalScheduleSerializer(source='interval', read_only=True)
|
||||||
|
crontab = CrontabScheduleSerializer(source='crontab', read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = MySchedule
|
||||||
|
fields = '__all__'
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ from apps.utils.permission import ALL_PERMS, get_user_perms_map
|
||||||
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
|
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
|
||||||
from server.celery import app as celery_app
|
from server.celery import app as celery_app
|
||||||
from .models import (Dept, Dictionary, DictType, File, Permission, Post, PostRole, Role, User,
|
from .models import (Dept, Dictionary, DictType, File, Permission, Post, PostRole, Role, User,
|
||||||
UserPost)
|
UserPost, MySchedule)
|
||||||
from .serializers import (ApkSerializer, DeptCreateUpdateSerializer, DeptSerializer, DictCreateUpdateSerializer,
|
from .serializers import (ApkSerializer, DeptCreateUpdateSerializer, DeptSerializer, DictCreateUpdateSerializer,
|
||||||
DictSerializer, DictTypeCreateUpdateSerializer, DictTypeSerializer,
|
DictSerializer, DictTypeCreateUpdateSerializer, DictTypeSerializer,
|
||||||
FileSerializer, PasswordChangeSerializer, PermissionCreateUpdateSerializer,
|
FileSerializer, PasswordChangeSerializer, PermissionCreateUpdateSerializer,
|
||||||
|
|
@ -35,7 +35,7 @@ from .serializers import (ApkSerializer, DeptCreateUpdateSerializer, DeptSeriali
|
||||||
PTaskSerializer, PTaskCreateUpdateSerializer, PTaskResultSerializer,
|
PTaskSerializer, PTaskCreateUpdateSerializer, PTaskResultSerializer,
|
||||||
RoleCreateUpdateSerializer, RoleSerializer, TaskRunSerializer,
|
RoleCreateUpdateSerializer, RoleSerializer, TaskRunSerializer,
|
||||||
UserCreateSerializer, UserListSerializer, UserPostCreateSerializer,
|
UserCreateSerializer, UserListSerializer, UserPostCreateSerializer,
|
||||||
UserPostSerializer, UserUpdateSerializer)
|
UserPostSerializer, UserUpdateSerializer, MyScheduleCreateSerializer, MyScheduleSerializer)
|
||||||
from rest_framework.viewsets import GenericViewSet
|
from rest_framework.viewsets import GenericViewSet
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -664,3 +664,29 @@ class ApkViewSet(MyLoggingMixin, ListModelMixin, CreateModelMixin, GenericViewSe
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
copyfile(settings.BASE_DIR + vdata['file'], settings.BASE_DIR + '/media/zc_ehs.apk')
|
copyfile(settings.BASE_DIR + vdata['file'], settings.BASE_DIR + '/media/zc_ehs.apk')
|
||||||
return Response()
|
return Response()
|
||||||
|
|
||||||
|
|
||||||
|
class MyScheduleViewSet(ListModelMixin, CreateModelMixin, DestroyModelMixin, CustomGenericViewSet):
|
||||||
|
perms_map = {'get': '*', 'post': 'myschedule.create', 'delete': 'myschedule.delete'}
|
||||||
|
serializer_class = MyScheduleSerializer
|
||||||
|
create_serializer_class = MyScheduleCreateSerializer
|
||||||
|
queryset = MySchedule.objects.all()
|
||||||
|
select_related_fields = ['interval', 'crontab']
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def perform_create(self, serializer):
|
||||||
|
vdata = serializer.validated_data
|
||||||
|
vdata['create_by'] = self.request.user #不可少
|
||||||
|
interval_data = vdata.pop('interval_', None)
|
||||||
|
crontab_data = vdata.pop('crontab_', None)
|
||||||
|
if vdata['type'] == 10:
|
||||||
|
interval, _ = IntervalSchedule.objects.get_or_create(**interval_data, defaults=interval_data)
|
||||||
|
obj = MySchedule(**vdata)
|
||||||
|
obj.interval = interval
|
||||||
|
obj.save()
|
||||||
|
elif vdata['type'] == 20:
|
||||||
|
crontab_data['timezone'] = 'Asia/Shanghai'
|
||||||
|
crontab, _ = CrontabSchedule.objects.get_or_create(**crontab_data, defaults=crontab_data)
|
||||||
|
obj = MySchedule(**vdata)
|
||||||
|
obj.crontab = crontab
|
||||||
|
obj.save()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue