diff --git a/server/apps/supervision/migrations/0035_complaint_oinspect_pgoal_pgoaldept_pt_rc_risk_task2_task2do.py b/server/apps/supervision/migrations/0035_complaint_oinspect_pgoal_pgoaldept_pt_rc_risk_task2_task2do.py new file mode 100644 index 0000000..b6b0764 --- /dev/null +++ b/server/apps/supervision/migrations/0035_complaint_oinspect_pgoal_pgoaldept_pt_rc_risk_task2_task2do.py @@ -0,0 +1,216 @@ +# Generated by Django 3.0.5 on 2023-05-15 06:53 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0022_delete_historicaldict'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('supervision', '0034_auto_20230308_1204'), + ] + + operations = [ + migrations.CreateModel( + name='Task2', + fields=[ + ('id', models.AutoField(auto_created=True, 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(default=2023, verbose_name='年份')), + ('cycle', models.PositiveSmallIntegerField(default=0, help_text='1-6个周期', verbose_name='所属周期')), + ('type', models.PositiveSmallIntegerField(choices=[(10, '目标制定'), (20, '日常监督')], default=20, verbose_name='任务类型')), + ('state', models.PositiveSmallIntegerField(choices=[(10, '创建中'), (20, '进行中'), (30, '已关闭')], default=20, verbose_name='任务状态')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='task2_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='task2_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Task2Do', + fields=[ + ('id', models.AutoField(auto_created=True, 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='删除标记')), + ('count_up', models.PositiveSmallIntegerField(default=0, verbose_name='完成上报内容数')), + ('count_all', models.PositiveSmallIntegerField(default=8, verbose_name='需上报内容数')), + ('num_issue', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='已发放报告数量')), + ('num_expect', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='应发报告数')), + ('num_error', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='不准确报告数')), + ('num_overdue', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='超期报告数')), + ('num_complaint', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='客户投诉数')), + ('num_pt', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='能力验证数')), + ('num_risk', models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='风险识别数')), + ('num_ocheck', 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='task2do_belong_dept', to='system.Organization', verbose_name='所属部门')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='task2do_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('task2', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='task2dept_task2', to='supervision.Task2', verbose_name='关联任务')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='task2do_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Risk', + fields=[ + ('id', models.AutoField(auto_created=True, 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='删除标记')), + ('content', models.TextField(verbose_name='内容')), + ('level', models.PositiveSmallIntegerField(choices=[(10, '主要风险'), (20, '严重风险'), (30, '重大风险')], default=10, verbose_name='风险等级')), + ('code', models.CharField(max_length=100, verbose_name='风险代码')), + ('state', models.PositiveSmallIntegerField(choices=[(10, '未整改'), (20, '整改中'), (30, '整改完成')], default=10, verbose_name='整改状态')), + ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='risk_belong_dept', to='system.Organization', 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='创建人')), + ('task2', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='supervision.Task2', verbose_name='关联任务')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='risk_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Rc', + fields=[ + ('id', models.AutoField(auto_created=True, 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='删除标记')), + ('number', models.CharField(max_length=100, verbose_name='报告证书编号')), + ('etype', models.PositiveSmallIntegerField(choices=[(10, '出错'), (20, '超期')], default=0, verbose_name='异常情况')), + ('number_correct', models.CharField(blank=True, default='', max_length=100, verbose_name='更改后报告证书编号')), + ('reason_error', models.CharField(blank=True, default='', max_length=100, verbose_name='出错原因')), + ('date_accept', models.DateField(blank=True, null=True, verbose_name='业务受理日期')), + ('date_expect', models.DateField(blank=True, null=True, verbose_name='预计发放日期')), + ('date_issue', models.DateField(blank=True, null=True, verbose_name='实际发放日期')), + ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='rc_belong_dept', to='system.Organization', verbose_name='所属部门')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='rc_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('task2', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='supervision.Task2', verbose_name='关联任务')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='rc_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Pt', + fields=[ + ('id', models.AutoField(auto_created=True, 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=100, verbose_name='名称')), + ('number', models.CharField(max_length=100, verbose_name='编号')), + ('organizer', models.CharField(max_length=100, verbose_name='组织方')), + ('params', models.TextField(verbose_name='参加参数名称')), + ('result', models.PositiveSmallIntegerField(choices=[(10, '满意'), (20, '有问题'), (30, '不满意')], default=10, verbose_name='结果')), + ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pt_belong_dept', to='system.Organization', verbose_name='所属部门')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pt_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('task2', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='supervision.Task2', verbose_name='关联任务')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pt_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PgoalDept', + fields=[ + ('id', models.AutoField(auto_created=True, 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(default=2023, verbose_name='年份')), + ('goal_name', models.CharField(max_length=100, verbose_name='目标名称')), + ('goal_key', models.CharField(blank=True, default='other', max_length=100, verbose_name='目标key值')), + ('goal_value_a', models.FloatField(blank=True, default=0, verbose_name='基础值')), + ('goal_value_b', models.FloatField(default=0, verbose_name='设定值')), + ('goal_value_c', models.FloatField(blank=True, default=0, verbose_name='实际值')), + ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pgoaldept_belong_dept', to='system.Organization', verbose_name='所属部门')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pgoaldept_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('goal_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='goal_file', to='system.File', verbose_name='当前文件ID')), + ('goal_files', models.ManyToManyField(blank=True, related_name='goal_files', to='system.File', verbose_name='历史文件')), + ('task2', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='supervision.Task2', verbose_name='关联任务')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pgoaldept_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Pgoal', + fields=[ + ('id', models.AutoField(auto_created=True, 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(default=2023, unique=True, verbose_name='年份')), + ('pgoal_1', models.FloatField(default=0, verbose_name='重大质量事故-基础值')), + ('pgoal_2', models.FloatField(default=0, verbose_name='报告/证书合格率-基础值')), + ('pgoal_3', models.FloatField(default=0, verbose_name='报告/证书及时率-基础值')), + ('pgoal_4', models.FloatField(default=0, verbose_name='能力验证满意率-基础值')), + ('pgoal_5', models.FloatField(default=0, verbose_name='客户投诉处理满意率-基础值')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pgoal_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('pgoal_1_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pgoal_1_file', to='system.File')), + ('pgoal_2_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pgoal_2_file', to='system.File')), + ('pgoal_3_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pgoal_3_file', to='system.File')), + ('pgoal_4_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pgoal_4_file', to='system.File')), + ('pgoal_5_file', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pgoal_5_file', to='system.File')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='pgoal_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Oinspect', + fields=[ + ('id', models.AutoField(auto_created=True, 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='删除标记')), + ('cate', models.PositiveSmallIntegerField(choices=[(10, '市场监管部门检查'), (20, '行业主管部门检查'), (30, '其他检查')], default=30, verbose_name='检查分类')), + ('checker', models.CharField(max_length=100, verbose_name='检查方')), + ('date_inspect', models.DateField(verbose_name='检查日期')), + ('result', models.TextField(verbose_name='检查结果')), + ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='oinspect_belong_dept', to='system.Organization', verbose_name='所属部门')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='oinspect_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('task2', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='supervision.Task2', verbose_name='关联任务')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='oinspect_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Complaint', + fields=[ + ('id', models.AutoField(auto_created=True, 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='删除标记')), + ('complainant', models.CharField(max_length=100, verbose_name='投诉人')), + ('content', models.TextField(verbose_name='投诉内容')), + ('date_occurrence', models.DateField(verbose_name='投诉日期')), + ('date_feedback', models.DateField(verbose_name='反馈日期')), + ('is_satisfied', models.BooleanField(default=True, verbose_name='是否满意')), + ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='complaint_belong_dept', to='system.Organization', verbose_name='所属部门')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='complaint_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('task2', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='supervision.Task2', verbose_name='关联任务')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='complaint_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/server/apps/supervision/migrations/0036_auto_20230515_1718.py b/server/apps/supervision/migrations/0036_auto_20230515_1718.py new file mode 100644 index 0000000..50dd665 --- /dev/null +++ b/server/apps/supervision/migrations/0036_auto_20230515_1718.py @@ -0,0 +1,25 @@ +# Generated by Django 3.0.5 on 2023-05-15 09:18 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('system', '0022_delete_historicaldict'), + ('supervision', '0035_complaint_oinspect_pgoal_pgoaldept_pt_rc_risk_task2_task2do'), + ] + + operations = [ + migrations.AddField( + model_name='pgoaldept', + name='goal_o_file', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='goal_o_file', to='system.File', verbose_name='原文件ID'), + ), + migrations.AddField( + model_name='task2', + name='depts', + field=models.ManyToManyField(blank=True, through='supervision.Task2Do', to='system.Organization', verbose_name='执行公司'), + ), + ] diff --git a/server/apps/supervision/migrations/0037_auto_20230517_0944.py b/server/apps/supervision/migrations/0037_auto_20230517_0944.py new file mode 100644 index 0000000..8f2b38e --- /dev/null +++ b/server/apps/supervision/migrations/0037_auto_20230517_0944.py @@ -0,0 +1,33 @@ +# Generated by Django 3.0.5 on 2023-05-17 01:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('supervision', '0036_auto_20230515_1718'), + ] + + operations = [ + migrations.AlterField( + model_name='pgoaldept', + name='goal_value_a', + field=models.FloatField(verbose_name='基础值'), + ), + migrations.AlterField( + model_name='pgoaldept', + name='goal_value_b', + field=models.FloatField(verbose_name='设定值'), + ), + migrations.AlterField( + model_name='pgoaldept', + name='goal_value_c', + field=models.FloatField(blank=True, null=True, verbose_name='实际值'), + ), + migrations.AlterField( + model_name='pgoaldept', + name='year', + field=models.PositiveSmallIntegerField(verbose_name='年份'), + ), + ] diff --git a/server/apps/supervision/migrations/0038_auto_20230517_0951.py b/server/apps/supervision/migrations/0038_auto_20230517_0951.py new file mode 100644 index 0000000..9ed9fb4 --- /dev/null +++ b/server/apps/supervision/migrations/0038_auto_20230517_0951.py @@ -0,0 +1,43 @@ +# Generated by Django 3.0.5 on 2023-05-17 01:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('supervision', '0037_auto_20230517_0944'), + ] + + operations = [ + migrations.AlterField( + model_name='pgoal', + name='pgoal_1', + field=models.FloatField(verbose_name='重大质量事故-基础值'), + ), + migrations.AlterField( + model_name='pgoal', + name='pgoal_2', + field=models.FloatField(verbose_name='报告/证书合格率-基础值'), + ), + migrations.AlterField( + model_name='pgoal', + name='pgoal_3', + field=models.FloatField(verbose_name='报告/证书及时率-基础值'), + ), + migrations.AlterField( + model_name='pgoal', + name='pgoal_4', + field=models.FloatField(verbose_name='能力验证满意率-基础值'), + ), + migrations.AlterField( + model_name='pgoal', + name='pgoal_5', + field=models.FloatField(verbose_name='客户投诉处理满意率-基础值'), + ), + migrations.AlterField( + model_name='pgoal', + name='year', + field=models.PositiveSmallIntegerField(unique=True, verbose_name='年份'), + ), + ] diff --git a/server/apps/supervision/migrations/0039_auto_20230517_1419.py b/server/apps/supervision/migrations/0039_auto_20230517_1419.py new file mode 100644 index 0000000..e7e5bff --- /dev/null +++ b/server/apps/supervision/migrations/0039_auto_20230517_1419.py @@ -0,0 +1,68 @@ +# Generated by Django 3.0.5 on 2023-05-17 06:19 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('supervision', '0038_auto_20230517_0951'), + ] + + operations = [ + migrations.RemoveField( + model_name='complaint', + name='task2', + ), + migrations.RemoveField( + model_name='oinspect', + name='task2', + ), + migrations.RemoveField( + model_name='pgoaldept', + name='task2', + ), + migrations.RemoveField( + model_name='pt', + name='task2', + ), + migrations.RemoveField( + model_name='rc', + name='task2', + ), + migrations.RemoveField( + model_name='risk', + name='task2', + ), + migrations.AddField( + model_name='complaint', + name='task2do', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='supervision.Task2Do', verbose_name='关联任务执行'), + ), + migrations.AddField( + model_name='oinspect', + name='task2do', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='supervision.Task2Do', verbose_name='关联任务执行'), + ), + migrations.AddField( + model_name='pgoaldept', + name='task2do', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='supervision.Task2Do', verbose_name='关联任务执行'), + ), + migrations.AddField( + model_name='pt', + name='task2do', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='supervision.Task2Do', verbose_name='关联任务执行'), + ), + migrations.AddField( + model_name='rc', + name='task2do', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='supervision.Task2Do', verbose_name='关联任务执行'), + ), + migrations.AddField( + model_name='risk', + name='task2do', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='supervision.Task2Do', verbose_name='关联任务执行'), + ), + ] diff --git a/server/apps/supervision/models.py b/server/apps/supervision/models.py index f7e023e..6b3dd7f 100644 --- a/server/apps/supervision/models.py +++ b/server/apps/supervision/models.py @@ -112,4 +112,164 @@ class TAction(CommonAModel): reason_1 = models.ForeignKey(Dict, verbose_name='变更主要原因', related_name='taction_r1', on_delete= models.SET_NULL, null=True, blank=True) reason_2 = models.ForeignKey(Dict, verbose_name='变更次要原因', related_name='taction_r2', on_delete= models.SET_NULL, null=True, blank=True) value_old = JSONField('原值', null=True, blank=True, default=dict) - value_new = JSONField('新值', null=True, blank=True, default=dict) \ No newline at end of file + value_new = JSONField('新值', null=True, blank=True, default=dict) + +class Pgoal(CommonAModel): + """ + 基础目标 + """ + basedict = { + "pgoal_1": "重大质量事故", + "pgoal_2": "报告/证书合格率", + "pgoal_3": "报告/证书及时率", + "pgoal_4": "能力验证满意率", + "pgoal_5": "客户投诉处理满意率" + } + year = models.PositiveSmallIntegerField('年份', unique=True) + pgoal_1 = models.FloatField('重大质量事故-基础值') + pgoal_2 = models.FloatField('报告/证书合格率-基础值') + pgoal_3 = models.FloatField('报告/证书及时率-基础值') + pgoal_4 = models.FloatField('能力验证满意率-基础值') + pgoal_5 = models.FloatField('客户投诉处理满意率-基础值') + pgoal_1_file = models.ForeignKey(File, related_name='pgoal_1_file', on_delete=models.SET_NULL, null=True, blank=True) + pgoal_2_file = models.ForeignKey(File, related_name='pgoal_2_file', on_delete=models.SET_NULL, null=True, blank=True) + pgoal_3_file = models.ForeignKey(File, related_name='pgoal_3_file', on_delete=models.SET_NULL, null=True, blank=True) + pgoal_4_file = models.ForeignKey(File, related_name='pgoal_4_file', on_delete=models.SET_NULL, null=True, blank=True) + pgoal_5_file = models.ForeignKey(File, related_name='pgoal_5_file', on_delete=models.SET_NULL, null=True, blank=True) + +class Task2(CommonAModel): + """ + 报送任务2 + """ + TASK2_CREATE = 10 + TASK2_DOING = 20 + TASK2_CLOSE = 30 + TASK2_STATES = ( + (TASK2_CREATE, '创建中'), + (TASK2_DOING, '进行中'), + (TASK2_CLOSE, '已关闭'), + ) + TASK2_F = 10 + TASK2_S = 20 + TASK2_TYPES = ( + (TASK2_F, '目标制定'), + (TASK2_S, '日常监督') + ) + + year = models.PositiveSmallIntegerField('年份', default=2023) + cycle = models.PositiveSmallIntegerField('所属周期', default=0, help_text='1-6个周期') + type = models.PositiveSmallIntegerField('任务类型', choices=TASK2_TYPES, default=20) + state = models.PositiveSmallIntegerField('任务状态', choices=TASK2_STATES, default=20) + depts = models.ManyToManyField(Organization, verbose_name='执行公司', through='supervision.task2do', blank=True) + + +class Task2Do(CommonBModel): + """任务执行情况 + """ + task2 = models.ForeignKey(Task2, verbose_name='关联任务', on_delete=models.CASCADE, related_name='task2dept_task2') + count_up = models.PositiveSmallIntegerField('完成上报内容数', default=0) + count_all = models.PositiveSmallIntegerField('需上报内容数', default=8) + + num_issue = models.PositiveSmallIntegerField('已发放报告数量', null=True, blank=True) + num_expect = models.PositiveSmallIntegerField('应发报告数', null=True, blank=True) + + num_error = models.PositiveSmallIntegerField('不准确报告数', null=True, blank=True) + num_overdue = models.PositiveSmallIntegerField('超期报告数', null=True, blank=True) + num_complaint = models.PositiveSmallIntegerField('客户投诉数', null=True, blank=True) + num_pt = models.PositiveSmallIntegerField('能力验证数', null=True, blank=True) + num_risk = models.PositiveSmallIntegerField('风险识别数', null=True, blank=True) + num_ocheck = models.PositiveSmallIntegerField('外部检查数', null=True, blank=True) + + +class PgoalDept(CommonBModel): + """企业年度目标值 + """ + year = models.PositiveSmallIntegerField('年份') + goal_name = models.CharField('目标名称', max_length=100) + goal_key = models.CharField('目标key值', max_length=100, default='other', blank=True) + goal_value_a = models.FloatField('基础值') + goal_o_file = models.ForeignKey(File, related_name='goal_o_file', verbose_name='原文件ID', on_delete=models.SET_NULL, null=True, blank=True) + goal_value_b = models.FloatField('设定值') + goal_value_c = models.FloatField('实际值', null=True, blank=True) + goal_file = models.ForeignKey(File, related_name='goal_file', verbose_name='当前文件ID', on_delete=models.SET_NULL, null=True, blank=True) + goal_files = models.ManyToManyField(File, related_name='goal_files', verbose_name='历史文件', blank=True) + task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True) + + +class Rc(CommonBModel): + """报告或证书 + """ + etype_choices = ( + (10, '出错'), + (20, '超期') + ) + number = models.CharField('报告证书编号', max_length=100) + etype = models.PositiveSmallIntegerField('异常情况', default=0, choices=etype_choices) + number_correct = models.CharField('更改后报告证书编号', max_length=100, default='', blank=True) + reason_error = models.CharField('出错原因', max_length=100, default='', blank=True) + date_accept = models.DateField('业务受理日期', null=True, blank=True) + date_expect = models.DateField('预计发放日期', null=True, blank=True) + date_issue = models.DateField('实际发放日期', null=True, blank=True) + task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True) + + +class Complaint(CommonBModel): + """客户投诉 + """ + complainant = models.CharField('投诉人', max_length=100) + content = models.TextField('投诉内容') + date_occurrence = models.DateField('投诉日期') + date_feedback = models.DateField('反馈日期') + is_satisfied = models.BooleanField('是否满意', default=True) + task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True) + + +class Pt(CommonBModel): + """能力验证 + """ + pt_result_choices = ( + (10, '满意'), + (20, '有问题'), + (30, '不满意') + ) + name = models.CharField('名称', max_length=100) + number = models.CharField('编号', max_length=100) + organizer = models.CharField('组织方', max_length=100) + params = models.TextField('参加参数名称') + result = models.PositiveSmallIntegerField('结果', choices=pt_result_choices, default=10) + task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True) + + +class Risk(CommonBModel): + """风险识别 + """ + risk_level_choices = ( + (10, '主要风险'), + (20, '严重风险'), + (30, '重大风险') + ) + risk_state_choices = ( + (10, '未整改'), + (20, '整改中'), + (30, '整改完成') + ) + content = models.TextField('内容') + level = models.PositiveSmallIntegerField('风险等级', choices=risk_level_choices, default=10) + code = models.CharField('风险代码', max_length=100) + state = models.PositiveSmallIntegerField('整改状态', choices=risk_state_choices, default=10) + task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True) + + +class Oinspect(CommonBModel): + """外部检查 + """ + oinspect_cate_choices = ( + (10, '市场监管部门检查'), + (20, '行业主管部门检查'), + (30, '其他检查') + ) + cate = models.PositiveSmallIntegerField('检查分类', choices=oinspect_cate_choices, default=30) + checker = models.CharField('检查方', max_length=100) + date_inspect = models.DateField('检查日期') + result = models.TextField('检查结果') + task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True) \ No newline at end of file diff --git a/server/apps/supervision/serializers.py b/server/apps/supervision/serializers.py index 9caea8b..78db033 100644 --- a/server/apps/supervision/serializers.py +++ b/server/apps/supervision/serializers.py @@ -2,6 +2,7 @@ from django.db.models.base import Model from rest_framework import serializers from .models import * from apps.system.serializers import OrganizationSerializer,FileListSerializer,UserSimpleSerializer,OrganizationSimpleSerializer, FileSimpleSerializer +from rest_framework.exceptions import ParseError class ContentSerializer(serializers.ModelSerializer): @@ -77,4 +78,102 @@ class TaskDeptSerializer(serializers.ModelSerializer): @staticmethod def setup_eager_loading(queryset): queryset = queryset.select_related('task', 'dept') - return queryset \ No newline at end of file + return queryset + + +class PgoalCreateUpdateSerializer(serializers.ModelSerializer): + class Meta: + model = Pgoal + fields = ['year', 'pgoal_1', 'pgoal_2', 'pgoal_3', 'pgoal_4', 'pgoal_5', 'pgoal_1_file', 'pgoal_2_file', 'pgoal_3_file', 'pgoal_4_file', 'pgoal_5_file'] + + +class PgoalSerializer(serializers.ModelSerializer): + pgoal_1_file_ = FileSimpleSerializer(source='pgoal_1_file', read_only=True) + pgoal_2_file_ = FileSimpleSerializer(source='pgoal_2_file', read_only=True) + pgoal_3_file_ = FileSimpleSerializer(source='pgoal_3_file', read_only=True) + pgoal_4_file_ = FileSimpleSerializer(source='pgoal_4_file', read_only=True) + pgoal_5_file_ = FileSimpleSerializer(source='pgoal_5_file', read_only=True) + class Meta: + model = Pgoal + fields = '__all__' + + +# class Task2CreateUpdateSerializer(serializers.ModelSerializer): +# class Meta: +# model = Task2 +# fields = ['year', 'cycle', 'type'] + + +class Task2Serializer(serializers.ModelSerializer): + create_by_name = serializers.CharField(source='create_by.name', read_only=True) + class Meta: + model = Task2 + fields = '__all__' + read_only_fields = ['create_time', 'update_time', 'create_by', 'update_by', 'belong_dept', 'state', 'is_deleted', 'depts'] + + def update(self, instance, validated_data): + validated_data.pop('type') # type不可编辑 + if instance.state != Task2.TASK2_CLOSE: + raise ParseError('非创建状态不可编辑') + return super().update(instance, validated_data) + +class Task2DeptsSerializer(serializers.Serializer): + ids = serializers.PrimaryKeyRelatedField(label="部门ID列表", many=True, queryset=Organization.objects.all()) + + +class Task2DoSerializer(serializers.ModelSerializer): + belong_dept_ = OrganizationSimpleSerializer(source='belong_dept', read_only=True) + task2_ = Task2Serializer(source='task2', read_only=True) + class Meta: + model = Task2Do + fields = '__all__' + +class ValidateMixin: + def validate(self, attrs): + task2do = attrs.get('task2do', None) + if task2do: + if task2do.task2.state == Task2.TASK2_CLOSE: + raise ParseError('任务已关闭不可处理') + attrs['year'] = task2do.task2.year + attrs['belong_dept'] = task2do.task2.belong_dept + return attrs + +class BaseMeta: + fields = '__all__' + read_only_fields = ['create_time', 'update_time', 'create_by', 'update_by', 'is_deleted'] + +class PgoalDeptSerializer(ValidateMixin, serializers.ModelSerializer): + goal_file_ = FileSimpleSerializer(source='goal_file', read_only=True) + class Meta(BaseMeta): + model = PgoalDept + read_only_fields = BaseMeta.read_only_fields + ['goal_value_a', 'goal_value_c', 'goal_files', 'goal_key'] + + +class RcSerializer(ValidateMixin, serializers.ModelSerializer): + + class Meta(BaseMeta): + model = Rc + +class ComplaintSerializer(ValidateMixin, serializers.ModelSerializer): + + class Meta(BaseMeta): + model = Complaint + +class PtSerializer(ValidateMixin, serializers.ModelSerializer): + + class Meta(BaseMeta): + model = Pt + +class RiskSerializer(ValidateMixin, serializers.ModelSerializer): + + class Meta(BaseMeta): + model = Risk + +class OinspectSerializer(ValidateMixin, serializers.ModelSerializer): + + class Meta(BaseMeta): + model = Oinspect + + +class NoRecordSerializer(serializers.Serializer): + key = serializers.ChoiceField(label='字段key', choices=['num_error', 'num_overdue', 'num_complaint', 'num_pt', 'num_risk', 'num_oinspect']) \ No newline at end of file diff --git a/server/apps/supervision/urls.py b/server/apps/supervision/urls.py index cbb8155..82f5c96 100644 --- a/server/apps/supervision/urls.py +++ b/server/apps/supervision/urls.py @@ -1,13 +1,23 @@ from apps.supervision.serializers import TaskDeptSerializer from django.urls import path, include from rest_framework import routers -from .views import ContentViewSet, TaskViewSet,RecordViewSet, TaskDeptViewSet +from .views import (ContentViewSet, TaskViewSet,RecordViewSet, TaskDeptViewSet, PogalViewSet, Task2ViewSet, Task2DoViewSet, PgoalDeptViewSet, +RcViewSet, ComplaintViewSet, PtViewSet, RiskViewSet, OinspectViewSet) router = routers.DefaultRouter() router.register('content', ContentViewSet, basename="content") router.register('task', TaskViewSet, basename="task") router.register('record', RecordViewSet, basename="record") router.register('taskdept', TaskDeptViewSet, basename="taskdept") +router.register('pgoal', PogalViewSet, basename='pgoal') +router.register('task2', Task2ViewSet, basename='task2') +router.register('task2do', Task2DoViewSet, basename='task2do') +router.register('pgoaldept', PgoalDeptViewSet, basename='pgoaldept') +router.register('rc', RcViewSet, basename='rc') +router.register('complaint', ComplaintViewSet, basename='complaint') +router.register('pt', PtViewSet, basename='pt') +router.register('risk', RiskViewSet, basename='risk') +router.register('oinspect', OinspectViewSet, basename='oinspect') urlpatterns = [ path('', include(router.urls)) ] \ No newline at end of file diff --git a/server/apps/supervision/views.py b/server/apps/supervision/views.py index c6c307a..2bd25c0 100644 --- a/server/apps/supervision/views.py +++ b/server/apps/supervision/views.py @@ -7,7 +7,7 @@ from django.shortcuts import render from django.utils import timezone from rest_framework import status from rest_framework.decorators import action, permission_classes -from rest_framework.mixins import ListModelMixin +from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin from rest_framework.response import Response from rest_framework.viewsets import GenericViewSet, ModelViewSet from utils.pagination import PageOrNot @@ -16,6 +16,7 @@ from apps.system.mixins import CreateUpdateCustomMixin from apps.system.models import Organization from apps.system.permission import get_permission_list, has_permission from apps.system.permission_data import RbacFilterSet +from django.db import transaction from .filters import RecordFilter from .models import * @@ -394,4 +395,217 @@ class TaskDeptViewSet(ModelViewSet): Record.objects.filter(task=obj.task, belong_dept=obj.dept).delete() # 删除相应上报记录 obj.delete() return Response() - \ No newline at end of file + + +class PogalViewSet(CreateUpdateCustomMixin, ModelViewSet): + perms_map = {'get': '*', 'post': 'pgoal', + 'put': 'pgoal', 'delete': 'pgoal'} + queryset = Pgoal.objects.all() + serializer_class = PgoalSerializer + filterset_fields = ['year'] + ordering = ['-year'] + + def get_serializer_class(self): + if self.action in ['create', 'update']: + return PgoalCreateUpdateSerializer + return super().get_serializer_class() + +class Task2ViewSet(CreateUpdateCustomMixin, ModelViewSet): + perms_map = {'get': '*', 'post': 'task2', + 'put': 'task2', 'delete': 'task2'} + queryset = Task2.objects.all() + serializer_class = Task2Serializer + filterset_fields = ['year', 'cycle', 'type', 'state'] + ordering = ['-create_time'] + + @action(methods=['put'], detail=True, perms_map = {'put':'task2'}) + def close(self, request, *args, **kwargs): + """关闭任务 + + 关闭任务 + """ + obj = self.get_object() + if obj.state == Task2.TASK2_DOING: + for i in Task2Do.objects.filter(task2=obj): + if i.count_up < i.count_all: + raise ParseError('存在公司未完成报送') + obj.state = Task2.TASK2_CLOSE + obj.save() + return Response() + + @transaction.atomic + @action(methods=['put'], detail=True, perms_map = {'put':'task2'}) + def start(self, request, *args, **kwargs): + """ + 开始执行 + """ + obj = self.get_object() + if obj.state == Task2.TASK2_CREATE: + tds = Task2Do.objects.filter(task2=obj) + if not tds.exists(): + raise ParseError('未添加执行公司') + if obj.type == Task2.TASK2_F: + try: + pg = Pgoal.objects.get(year=obj.year) + except: + raise ParseError('未配置年度基础目标') + for i in tds: + for k, v in enumerate(Pgoal.basedict): + pds = PgoalDept.objects.filter(year=i.year, task2do=i, goal_key=k) + if pds.exists(): + pds.update(**{'goal_name': v, 'goal_value_a': getattr(pg, k), 'goal_o_file': getattr(pg, k+'_file')}) + else: + PgoalDept.objects.create(**{'year': i.year, 'task2do': i, 'belong_dept': i.belong_dept, + 'goal_name': v, 'goal_key': k, 'goal_value_a': getattr(pg, k), 'goal_o_file': getattr(pg, k+'_file')}) + obj.state = Task2.TASK2_DOING + obj.save() + return Response() + + @action(methods=['post'], detail=True, perms_map = {'post':'task2'}, serializer_class=Task2DeptsSerializer) + def add_depts(self, request, *args, **kwargs): + """添加执行部门 + """ + task2 = self.get_object() + if task2.state == Task2.TASK2_CLOSE: + raise ParseError('任务已关闭,不可操作') + sr = Task2DeptsSerializer(data=request.data) + sr.is_valid(raise_exception=True) + vdata = sr.validated_data + count_all = 8 + if task2.type == Task2.TASK2_F: + count_all = 5 + for i in vdata['ids']: + Task2Do.objects.get_or_create(task2=task2, belong_dept=i, defaults={'task2': task2, 'belong_dept': i, 'count_all': count_all}) + return Response() + + +class Task2DoViewSet(ListModelMixin, GenericViewSet): + perms_map = {'get': '*'} + queryset = Task2Do.objects.select_related('belong_dept', 'task2').all() + serializer_class = Task2DoSerializer + ordering = ['belong_dept__sort'] + + cfields = ['num_issue', 'num_expect', 'num_error', 'num_overdue', 'num_complaint', 'num_pt', 'num_risk', 'num_oinspect'] + + @classmethod + def countup_task2do(cls, instance): + """计算并更新某部门日常监督任务完成数量 + """ + count_up = 0 + for i in cls.cfields: + if getattr(instance, i) is not None: + count_up = count_up + 1 + instance.count_up = count_up + instance.save() + + @action(methods=['put'], detail=True, perms_map = {'post':'task2do'}, serializer_class=NoRecordSerializer) + def no_record(self, request, *args, **kwargs): + """没有记录 + + 没有记录 + """ + obj = self.get_object() + setattr(obj, request.data.get('key'), 0) + obj.save() + self.countup_task2do(obj) + return Response() + + @action(methods=['get'], detail=False, perms_map = {'post':'task2do'}) + def my(self, request, *args, **kwargs): + """我的任务 + + 我的任务 + """ + queryset = Task2Do.objects.exclude(task2__state=10).order_by('-create_time') + belong_dept = self.request.query_params.get('belong_dept', None) + if belong_dept: + queryset = queryset.filter(belong_dept=belong_dept) + else: + mydept = request.user.dept + belong_depts = get_child_queryset2(mydept) + queryset = queryset.filter(belong_dept = belong_depts) + serializer = Task2DoSerializer(queryset, many=True) + return Response(serializer.data) + + +class Domixin: + perms_map = {'get': '*', 'put': 'task2do', 'post': 'task2do', 'delete': 'task2do'} + ordering = ['create_time'] + ordering_fields = ['create_time', 'belong_dept__sort'] + + def countnum_task2do_field(self, task2do): + for k, v in self.count_dict: + setattr(task2do, k, self.queryset.model.objects.filter({**{'task2do': task2do}, **v}).count()) + task2do.save() + # 更新count_up字段 + Task2DoViewSet.countup_task2do(task2do) + + def countup_task2do(self, task2do): + if task2do.task2.type == Task2.TASK2_F: + task2do.count_up = PgoalDept.objects.filter(task2do=task2do).count() + task2do.save() + elif task2do.task2.type == Task2.TASK2_S: + self.countnum_task2do_field(task2do) + + @transaction.atomic + def perform_create(self, serializer): + instance = super().perform_create(serializer) + self.countup_task2do(instance.task2do) + + @transaction.atomic + def perform_destroy(self, instance): + task2do = instance.task2do + instance.delete(soft=False) + self.countup_task2do(task2do) + + +class PgoalDeptViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet): + queryset = PgoalDept.objects.all() + serializer_class = PgoalDeptSerializer + + def perform_update(self, serializer): + instance = super().perform_update(serializer) + goal_file = instance.goal_file + if goal_file: + instance.goal_files.add(goal_file) + + +class RcViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet): + queryset = Rc.objects.all() + serializer_class = RcSerializer + count_dict = { + "num_error": {'etype': 10}, + "num_overdue": {'etype': 20} + } + + +class ComplaintViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet): + queryset = Complaint.objects.all() + serializer_class = ComplaintSerializer + count_dict = { + "num_complaint": {} + } + + +class PtViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet): + queryset = Pt.objects.all() + serializer_class = PtSerializer + count_dict = { + "num_pt": {} + } + + +class RiskViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet): + queryset = Risk.objects.all() + serializer_class = RiskSerializer + count_dict = { + "num_risk": {} + } + + +class OinspectViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet): + queryset = Oinspect.objects.all() + serializer_class = OinspectSerializer + count_dict = { + "num_oinspect": {} + } diff --git a/server/apps/system/mixins.py b/server/apps/system/mixins.py index 5a737f0..869c825 100644 --- a/server/apps/system/mixins.py +++ b/server/apps/system/mixins.py @@ -14,7 +14,8 @@ class CreateUpdateModelBMixin: 业务用基本表B用 """ def perform_create(self, serializer): - serializer.save(create_by = self.request.user, belong_dept=self.request.user.dept) + belong_dept = serializer.validated_data.get('belong_dept', self.request.user.dept) + serializer.save(create_by = self.request.user, belong_dept=belong_dept) def perform_update(self, serializer): serializer.save(update_by = self.request.user) @@ -25,7 +26,8 @@ class CreateUpdateCustomMixin: """ def perform_create(self, serializer): if hasattr(self.queryset.model, 'belong_dept'): - serializer.save(create_by = self.request.user, belong_dept=self.request.user.dept) + belong_dept = serializer.validated_data.get('belong_dept', self.request.user.dept) + serializer.save(create_by = self.request.user, belong_dept=belong_dept) else: serializer.save(create_by = self.request.user) def perform_update(self, serializer):