diff --git a/apps/develop/urls.py b/apps/develop/urls.py index ddbc6380..0c1c5685 100755 --- a/apps/develop/urls.py +++ b/apps/develop/urls.py @@ -10,7 +10,7 @@ router.register('correct', CorrectViewSet, basename='correct') urlpatterns = [ path(API_BASE_URL + 'reload_server_git/', ReloadServerGit.as_view()), - path(API_BASE_URL + 'reload_web_git/', ReloadClientGit.as_view()), + # path(API_BASE_URL + 'reload_web_git/', ReloadClientGit.as_view()), path(API_BASE_URL + 'reload_server_only/', ReloadServerOnly.as_view()), path(API_BASE_URL + 'backup_database/', BackupDatabase.as_view()), path(API_BASE_URL + 'backup_media/', BackupMedia.as_view()), diff --git a/apps/dpm/migrations/0001_initial.py b/apps/dpm/migrations/0001_initial.py index 23e0d7db..32a2e4c6 100644 --- a/apps/dpm/migrations/0001_initial.py +++ b/apps/dpm/migrations/0001_initial.py @@ -28,7 +28,6 @@ class Migration(migrations.Migration): ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), ('note', models.TextField(blank=True, null=True, verbose_name='派发备注')), ('expire', models.PositiveSmallIntegerField(default=0, help_text='0代表不设限制直到下个任务派发', verbose_name='执行有效期(h)')), - ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='checktaskset_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='checktaskset_create_by', to=settings.AUTH_USER_MODEL, 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(on_delete=django.db.models.deletion.CASCADE, related_name='checktask_periodictask', to='django_celery_beat.periodictask', verbose_name='关联定时任务')), @@ -51,7 +50,6 @@ class Migration(migrations.Migration): ('time_end', models.DateTimeField(verbose_name='关闭时间')), ('note', models.TextField(blank=True, null=True, verbose_name='检查备注')), ('time_check', models.DateTimeField(blank=True, null=True, verbose_name='开始检查时间')), - ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='checkwork_belong_dept', to='system.dept', verbose_name='所属部门')), ('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='system.dictionary', verbose_name='工作分类')), ('checktaskset', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='dpm.checktaskset', verbose_name='关联派发策略')), ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='checkwork_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), @@ -73,7 +71,6 @@ class Migration(migrations.Migration): ('type', models.PositiveSmallIntegerField(choices=[(10, '作业活动类'), (20, '设备设施类')], default=10, verbose_name='风险点类型')), ('manage_level', models.PositiveSmallIntegerField(choices=[(10, '岗位级'), (20, '班组级'), (30, '部门级'), (40, '公司级')], default=10, verbose_name='管控层级')), ('area', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='riskpoint_area', to='am.area', verbose_name='所在区域')), - ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='riskpoint_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='riskpoint_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), ('dept_res', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='riskpoint_dept_res', to='system.dept', verbose_name='责任部门')), ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='riskpoint_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), @@ -104,7 +101,6 @@ class Migration(migrations.Migration): ('riske', models.DecimalField(blank=True, decimal_places=1, max_digits=6, null=True)), ('riskc', models.DecimalField(blank=True, decimal_places=1, max_digits=6, null=True)), ('riskd', models.DecimalField(blank=True, decimal_places=1, max_digits=6, null=True)), - ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='risk_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='risk_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), ('results', models.ManyToManyField(blank=True, related_name='risk_results', to='system.Dictionary', verbose_name='可能后果')), ('riskpoint', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dpm.riskpoint', verbose_name='所属风险点')), @@ -134,7 +130,6 @@ class Migration(migrations.Migration): ('correct_description', models.TextField(blank=True, null=True, verbose_name='整改描述')), ('correct_time', models.DateTimeField(blank=True, null=True, verbose_name='整改完成时间')), ('area', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='am.area', verbose_name='所在区域')), - ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='hazard_belong_dept', to='system.dept', verbose_name='所属部门')), ('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='system.dictionary', verbose_name='隐患类别')), ('checkwork', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='dpm.checkwork', verbose_name='关联检查工作')), ('correct_solution', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='system.file', verbose_name='整改方案')), @@ -192,10 +187,8 @@ class Migration(migrations.Migration): ('result', models.PositiveSmallIntegerField(default=10, verbose_name='检查结果')), ('note', models.TextField(blank=True, null=True, verbose_name='备注')), ('checkwork', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='citem_checkwork', to='dpm.checkwork', verbose_name='关联检查工作')), - ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='checkitem_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), ('hazard', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='citem_hazard', to='dpm.hazard', verbose_name='关联隐患')), ('risk', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='citem_risk', to='dpm.risk', verbose_name='关联风险')), - ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='checkitem_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), ], options={ 'abstract': False, diff --git a/apps/dpm/migrations/0002_auto_20240612_1042.py b/apps/dpm/migrations/0002_auto_20240612_1042.py new file mode 100644 index 00000000..57d89519 --- /dev/null +++ b/apps/dpm/migrations/0002_auto_20240612_1042.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.12 on 2024-06-12 02:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dpm', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='checkwork', + name='usable', + field=models.BooleanField(default=True, verbose_name='是否可用'), + ), + migrations.AlterField( + model_name='checkwork', + name='time_end', + field=models.DateTimeField(blank=True, null=True, verbose_name='关闭时间'), + ), + ] diff --git a/apps/dpm/models.py b/apps/dpm/models.py index 19e6c6c0..fd4dfe10 100644 --- a/apps/dpm/models.py +++ b/apps/dpm/models.py @@ -1,9 +1,9 @@ from django.db import models -from apps.utils.models import CommonBModel, CommonAModel +from apps.utils.models import BaseModel, CommonAModel, CommonADModel from django_celery_beat.models import PeriodicTask # Create your models here. -class RiskPoint(CommonBModel): +class RiskPoint(CommonAModel): """ 风险点表 """ @@ -32,7 +32,7 @@ class RiskPoint(CommonBModel): 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='riskpoint_user_res', null=True, blank=True) -class Risk(CommonBModel): +class Risk(CommonAModel): """ 风险表 """ @@ -54,7 +54,7 @@ class Risk(CommonBModel): riskpoint = models.ForeignKey(RiskPoint, on_delete=models.CASCADE, verbose_name='所属风险点') -class CheckTaskSet(CommonBModel): +class CheckTaskSet(CommonADModel): """ 检查任务派发设置 """ @@ -66,7 +66,7 @@ class CheckTaskSet(CommonBModel): periodictask = models.ForeignKey(PeriodicTask, verbose_name='关联定时任务', on_delete=models.CASCADE, related_name='checktask_periodictask') -class CheckWork(CommonBModel): +class CheckWork(CommonAModel): """ 检查工作 """ @@ -78,8 +78,9 @@ class CheckWork(CommonBModel): 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) + usable = models.BooleanField('是否可用', default=True) time_start = models.DateTimeField('开启时间') - time_end = models.DateTimeField('关闭时间') + time_end = models.DateTimeField('关闭时间', null=True, blank=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) @@ -87,7 +88,7 @@ class CheckWork(CommonBModel): checktaskset = models.ForeignKey(CheckTaskSet, verbose_name='关联派发策略', on_delete=models.CASCADE, null=True, blank=True) -class Hazard(CommonBModel): +class Hazard(CommonAModel): """ 事故隐患表 """ @@ -139,7 +140,7 @@ class Hazard(CommonBModel): ticket = models.ForeignKey('wf.ticket', on_delete=models.SET_NULL, verbose_name='关联工单', related_name='hazard_ticket', null=True, blank=True) -class CheckItem(CommonAModel): +class CheckItem(BaseModel): """ 检查工作-隐患关联表 """ diff --git a/apps/dpm/serializers.py b/apps/dpm/serializers.py index c4818914..74a0fb0f 100644 --- a/apps/dpm/serializers.py +++ b/apps/dpm/serializers.py @@ -6,6 +6,7 @@ from apps.utils.constants import EXCLUDE_FIELDS from apps.system.models import Dictionary from django_celery_beat.models import PeriodicTask import time +from django.db import transaction class RiskPointCreateUpdateSerializer(CustomModelSerializer): @@ -73,32 +74,37 @@ class RiskSerializer(CustomModelSerializer): fields = '__all__' -class CheckTaskSetCreateUpdateSerializer(CustomModelSerializer): +class CheckTaskSetCreateSerializer(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: + def create(self, validated_data): + with transaction.atomic(): + sch = validated_data["myschedule"] 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 + pobj.name = 'checktask_' + time.strftime('%Y%m%d%H%M%S') + pobj.task = 'apps.dpm.tasks.dispath_checkwork_task' + if sch.crontab: + pobj.crontab = sch.crontab + elif sch.interval: + pobj.interval = sch.interval + pobj.save() + validated_data["periodictask"] = pobj + ins = super().create(validated_data) + pobj.kwargs = json.dumps({'checktaskset': ins.id}) + pobj.save() + return ins + +class CheckTaskSetUpdateSerializer(CustomModelSerializer): + class Meta: + model = CheckTaskSet + fields = ["expire", "note"] class CheckTaskSetSerializer(CustomModelSerializer): + user_duty_name = serializers.CharField(source="user_duty.name", read_only=True) + 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) diff --git a/apps/dpm/tasks.py b/apps/dpm/tasks.py index 12f7a7a9..33c368d8 100644 --- a/apps/dpm/tasks.py +++ b/apps/dpm/tasks.py @@ -1,27 +1,32 @@ +from __future__ import absolute_import, unicode_literals 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 +from django.db import transaction @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 + with transaction.atomic(): + CheckWork.objects.filter(checktaskset=cts).update(usable=False) + cw = CheckWork() + cw.type = 20 + cw.checktaskset = cts + now = timezone.now() + cw.time_start = now + local_time = timezone.localtime(now) + cw.name = f'风险点排查_{local_time.strftime('%Y%m%d%H%M%S')}' + 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) diff --git a/apps/dpm/urls.py b/apps/dpm/urls.py index ee1ca829..5afdd73e 100644 --- a/apps/dpm/urls.py +++ b/apps/dpm/urls.py @@ -1,4 +1,4 @@ -from apps.dpm.views import RiskPointViewSet, RiskViewSet +from apps.dpm.views import RiskPointViewSet, RiskViewSet, CheckTaskSetViewSet from django.urls import path, include from rest_framework.routers import DefaultRouter @@ -8,6 +8,7 @@ HTML_BASE_URL = 'dpm/' router = DefaultRouter() router.register('riskpoint', RiskPointViewSet, basename='riskpoint') router.register('risk', RiskViewSet, basename='risk') +router.register('checktaskset', CheckTaskSetViewSet, basename='checktaskset') urlpatterns = [ path(API_BASE_URL, include(router.urls)), ] diff --git a/apps/dpm/views.py b/apps/dpm/views.py index d832c7bc..0520f39e 100644 --- a/apps/dpm/views.py +++ b/apps/dpm/views.py @@ -1,5 +1,6 @@ -from apps.dpm.serializers import RiskPointCreateUpdateSerializer, RiskPointSerializer, RiskCreateUpdateSerializer, RiskSerializer, CheckTaskSetCreateUpdateSerializer, CheckTaskSetSerializer, CheckWork_10_CreateUpdateSerializer, CheckWorkSerializer -from apps.utils.viewsets import CustomModelViewSet +from apps.dpm.serializers import RiskPointCreateUpdateSerializer, RiskPointSerializer, RiskCreateUpdateSerializer, RiskSerializer, CheckTaskSetCreateSerializer, CheckTaskSetUpdateSerializer, CheckTaskSetSerializer, CheckWork_10_CreateUpdateSerializer, CheckWorkSerializer +from apps.utils.viewsets import CustomModelViewSet, CustomGenericViewSet +from apps.utils.mixins import CustomListModelMixin, BulkDestroyModelMixin, BulkCreateModelMixin from apps.dpm.models import CheckTaskSet, CheckWork, RiskPoint, Risk from rest_framework.decorators import action from rest_framework.response import Response @@ -29,12 +30,12 @@ class RiskViewSet(CustomModelViewSet): filterset_fields = ['results'] -class CheckTaskSetViewSet(CustomModelViewSet): +class CheckTaskSetViewSet(CustomListModelMixin, BulkCreateModelMixin, BulkDestroyModelMixin, CustomGenericViewSet): queryset = CheckTaskSet.objects.all() - create_serializer_class = CheckTaskSetCreateUpdateSerializer - update_serializer_class = CheckTaskSetCreateUpdateSerializer + create_serializer_class = CheckTaskSetCreateSerializer + update_serializer_class = CheckTaskSetUpdateSerializer serializer_class = CheckTaskSetSerializer - select_related_fields = ['periodictask'] + select_related_fields = ['periodictask', "myschedule", "user_duty"] search_fields = ['note'] filterset_fields = ['periodictask__enabled'] @@ -54,8 +55,7 @@ class CheckTaskSetViewSet(CustomModelViewSet): with transaction.atomic(): periodictask = instance.periodictask instance.delete() - periodictask.enabled = False - periodictask.save() + periodictask.delete() class CheckWorkViewSet(CustomModelViewSet):