This commit is contained in:
shijing 2023-05-31 17:20:50 +08:00
commit f5e237b635
24 changed files with 493 additions and 63 deletions

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class AbilityConfig(AppConfig): class AbilityConfig(AppConfig):
name = 'ability' name = 'apps.ability'

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class QualityConfig(AppConfig): class QualityConfig(AppConfig):
name = 'consulting' name = 'apps.consulting'

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class CrmConfig(AppConfig): class CrmConfig(AppConfig):
name = 'crm' name = 'apps.crm'

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class ExamConfig(AppConfig): class ExamConfig(AppConfig):
name = 'exam' name = 'apps.exam'

View File

@ -2,5 +2,5 @@ from django.apps import AppConfig
class OpsConfig(AppConfig): class OpsConfig(AppConfig):
name = 'ops' name = 'apps.ops'
verbose_name = '系统监控' verbose_name = '系统监控'

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class QualityConfig(AppConfig): class QualityConfig(AppConfig):
name = 'quality' name = 'apps.quality'

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class SupervisionConfig(AppConfig): class SupervisionConfig(AppConfig):
name = 'supervision' name = 'apps.supervision'

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.5 on 2023-05-22 07:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('supervision', '0039_auto_20230517_1419'),
]
operations = [
migrations.AlterField(
model_name='task2',
name='state',
field=models.PositiveSmallIntegerField(choices=[(10, '创建中'), (20, '进行中'), (30, '已关闭')], default=10, verbose_name='任务状态'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.0.5 on 2023-05-22 07:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('supervision', '0040_auto_20230522_1515'),
]
operations = [
migrations.AlterField(
model_name='task2',
name='cycle',
field=models.PositiveSmallIntegerField(blank=True, default=0, help_text='1-6个周期', verbose_name='所属周期'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2023-05-23 06:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('supervision', '0041_auto_20230522_1518'),
]
operations = [
migrations.AlterField(
model_name='pgoaldept',
name='goal_value_b',
field=models.FloatField(blank=True, null=True, verbose_name='设定值'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2023-05-26 08:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('supervision', '0042_alter_pgoaldept_goal_value_b'),
]
operations = [
migrations.AlterField(
model_name='pgoaldept',
name='goal_value_a',
field=models.FloatField(blank=True, null=True, verbose_name='基础值'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2023-05-29 00:38
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('supervision', '0043_alter_pgoaldept_goal_value_a'),
]
operations = [
migrations.RenameField(
model_name='task2do',
old_name='num_ocheck',
new_name='num_oinspect',
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2023-05-29 01:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('supervision', '0044_rename_num_ocheck_task2do_num_oinspect'),
]
operations = [
migrations.AddField(
model_name='rc',
name='remark',
field=models.TextField(blank=True, null=True, verbose_name='备注'),
),
]

View File

@ -0,0 +1,38 @@
# Generated by Django 3.2.12 on 2023-05-29 04:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('supervision', '0045_rc_remark'),
]
operations = [
migrations.AddField(
model_name='pt',
name='handle_result',
field=models.PositiveSmallIntegerField(choices=[(0, '/'), (10, '已整改'), (20, '被暂停'), (30, '已被撤销认可资格')], default=0, help_text="((0, '/'), (10, '已整改'), (20, '被暂停'), (30, '已被撤销认可资格'))", verbose_name='处理结果'),
),
migrations.AlterField(
model_name='oinspect',
name='cate',
field=models.PositiveSmallIntegerField(choices=[(10, '市场监管部门检查'), (20, '行业主管部门检查'), (30, '其他检查')], default=30, help_text="((10, '市场监管部门检查'), (20, '行业主管部门检查'), (30, '其他检查'))", verbose_name='检查分类'),
),
migrations.AlterField(
model_name='pt',
name='result',
field=models.PositiveSmallIntegerField(choices=[(10, '满意'), (20, '有问题'), (30, '不满意')], default=10, help_text="((10, '满意'), (20, '有问题'), (30, '不满意'))", verbose_name='结果'),
),
migrations.AlterField(
model_name='risk',
name='level',
field=models.PositiveSmallIntegerField(choices=[(10, '主要风险'), (20, '严重风险'), (30, '重大风险')], default=10, help_text="((10, '主要风险'), (20, '严重风险'), (30, '重大风险'))", verbose_name='风险等级'),
),
migrations.AlterField(
model_name='risk',
name='state',
field=models.PositiveSmallIntegerField(choices=[(10, '未整改'), (20, '整改中'), (30, '整改完成')], default=10, help_text="((10, '未整改'), (20, '整改中'), (30, '整改完成'))", verbose_name='整改状态'),
),
]

View File

@ -0,0 +1,28 @@
# Generated by Django 3.2.12 on 2023-05-31 08:29
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('supervision', '0046_auto_20230529_1206'),
]
operations = [
migrations.AddField(
model_name='task2do',
name='num_acc',
field=models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='重大质量事故'),
),
migrations.AddField(
model_name='task2do',
name='num_complaint_10',
field=models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='满意客户投诉数'),
),
migrations.AddField(
model_name='task2do',
name='num_pt_10',
field=models.PositiveSmallIntegerField(blank=True, null=True, verbose_name='满意能力验证数'),
),
]

View File

@ -1,6 +1,6 @@
from django.db import models from django.db import models
from utils.model import BaseModel from utils.model import BaseModel
from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File from apps.system.models import CommonAModel, CommonBModel, Organization, User, Dict, File, CommonADModel, CommonBDModel
from django.contrib.postgres.fields import JSONField from django.contrib.postgres.fields import JSONField
# Create your models here. # Create your models here.
@ -114,7 +114,7 @@ class TAction(CommonAModel):
value_old = JSONField('原值', null=True, blank=True, default=dict) value_old = JSONField('原值', null=True, blank=True, default=dict)
value_new = JSONField('新值', null=True, blank=True, default=dict) value_new = JSONField('新值', null=True, blank=True, default=dict)
class Pgoal(CommonAModel): class Pgoal(CommonADModel):
""" """
基础目标 基础目标
""" """
@ -137,7 +137,7 @@ class Pgoal(CommonAModel):
pgoal_4_file = models.ForeignKey(File, related_name='pgoal_4_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) pgoal_5_file = models.ForeignKey(File, related_name='pgoal_5_file', on_delete=models.SET_NULL, null=True, blank=True)
class Task2(CommonAModel): class Task2(CommonADModel):
""" """
报送任务2 报送任务2
""" """
@ -157,46 +157,49 @@ class Task2(CommonAModel):
) )
year = models.PositiveSmallIntegerField('年份', default=2023) year = models.PositiveSmallIntegerField('年份', default=2023)
cycle = models.PositiveSmallIntegerField('所属周期', default=0, help_text='1-6个周期') cycle = models.PositiveSmallIntegerField('所属周期', default=0, help_text='1-6个周期', blank=True)
type = models.PositiveSmallIntegerField('任务类型', choices=TASK2_TYPES, default=20) type = models.PositiveSmallIntegerField('任务类型', choices=TASK2_TYPES, default=20)
state = models.PositiveSmallIntegerField('任务状态', choices=TASK2_STATES, default=20) state = models.PositiveSmallIntegerField('任务状态', choices=TASK2_STATES, default=10)
depts = models.ManyToManyField(Organization, verbose_name='执行公司', through='supervision.task2do', blank=True) depts = models.ManyToManyField(Organization, verbose_name='执行公司', through='supervision.task2do', blank=True)
class Task2Do(CommonBModel): class Task2Do(CommonBDModel):
"""任务执行情况 """任务执行情况
""" """
task2 = models.ForeignKey(Task2, verbose_name='关联任务', on_delete=models.CASCADE, related_name='task2dept_task2') task2 = models.ForeignKey(Task2, verbose_name='关联任务', on_delete=models.CASCADE, related_name='task2dept_task2')
count_up = models.PositiveSmallIntegerField('完成上报内容数', default=0) count_up = models.PositiveSmallIntegerField('完成上报内容数', default=0)
count_all = models.PositiveSmallIntegerField('需上报内容数', default=8) count_all = models.PositiveSmallIntegerField('需上报内容数', default=9)
num_issue = models.PositiveSmallIntegerField('已发放报告数量', null=True, blank=True) num_issue = models.PositiveSmallIntegerField('已发放报告数量', null=True, blank=True)
num_expect = models.PositiveSmallIntegerField('应发报告数', null=True, blank=True) num_expect = models.PositiveSmallIntegerField('应发报告数', null=True, blank=True)
num_acc = models.PositiveSmallIntegerField('重大质量事故', null=True, blank=True)
num_error = models.PositiveSmallIntegerField('不准确报告数', null=True, blank=True) num_error = models.PositiveSmallIntegerField('不准确报告数', null=True, blank=True)
num_overdue = models.PositiveSmallIntegerField('超期报告数', null=True, blank=True) num_overdue = models.PositiveSmallIntegerField('超期报告数', null=True, blank=True)
num_complaint = models.PositiveSmallIntegerField('客户投诉数', null=True, blank=True) num_complaint = models.PositiveSmallIntegerField('客户投诉数', null=True, blank=True)
num_complaint_10 = models.PositiveSmallIntegerField('满意客户投诉数', null=True, blank=True)
num_pt = models.PositiveSmallIntegerField('能力验证数', null=True, blank=True) num_pt = models.PositiveSmallIntegerField('能力验证数', null=True, blank=True)
num_pt_10 = models.PositiveSmallIntegerField('满意能力验证数', null=True, blank=True)
num_risk = models.PositiveSmallIntegerField('风险识别数', null=True, blank=True) num_risk = models.PositiveSmallIntegerField('风险识别数', null=True, blank=True)
num_ocheck = models.PositiveSmallIntegerField('外部检查数', null=True, blank=True) num_oinspect = models.PositiveSmallIntegerField('外部检查数', null=True, blank=True)
class PgoalDept(CommonBModel): class PgoalDept(CommonBDModel):
"""企业年度目标值 """企业年度目标值
""" """
year = models.PositiveSmallIntegerField('年份') year = models.PositiveSmallIntegerField('年份')
goal_name = models.CharField('目标名称', max_length=100) goal_name = models.CharField('目标名称', max_length=100)
goal_key = models.CharField('目标key值', max_length=100, default='other', blank=True) goal_key = models.CharField('目标key值', max_length=100, default='other', blank=True)
goal_value_a = models.FloatField('基础值') goal_value_a = models.FloatField('基础值', null=True, blank=True)
goal_o_file = models.ForeignKey(File, related_name='goal_o_file', verbose_name='原文件ID', on_delete=models.SET_NULL, null=True, blank=True) 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_b = models.FloatField('设定值', null=True, blank=True)
goal_value_c = models.FloatField('实际值', null=True, blank=True) 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_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) 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) task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True)
class Rc(CommonBModel): class Rc(CommonBDModel):
"""报告或证书 """报告或证书
""" """
etype_choices = ( etype_choices = (
@ -211,9 +214,10 @@ class Rc(CommonBModel):
date_expect = models.DateField('预计发放日期', null=True, blank=True) date_expect = models.DateField('预计发放日期', null=True, blank=True)
date_issue = 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) task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True)
remark = models.TextField('备注', null=True, blank=True)
class Complaint(CommonBModel): class Complaint(CommonBDModel):
"""客户投诉 """客户投诉
""" """
complainant = models.CharField('投诉人', max_length=100) complainant = models.CharField('投诉人', max_length=100)
@ -224,7 +228,7 @@ class Complaint(CommonBModel):
task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True) task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True)
class Pt(CommonBModel): class Pt(CommonBDModel):
"""能力验证 """能力验证
""" """
pt_result_choices = ( pt_result_choices = (
@ -232,15 +236,22 @@ class Pt(CommonBModel):
(20, '有问题'), (20, '有问题'),
(30, '不满意') (30, '不满意')
) )
pt_hresult_choices = (
(0, '/'),
(10, '已整改'),
(20, '被暂停'),
(30, '已被撤销认可资格')
)
name = models.CharField('名称', max_length=100) name = models.CharField('名称', max_length=100)
number = models.CharField('编号', max_length=100) number = models.CharField('编号', max_length=100)
organizer = models.CharField('组织方', max_length=100) organizer = models.CharField('组织方', max_length=100)
params = models.TextField('参加参数名称') params = models.TextField('参加参数名称')
result = models.PositiveSmallIntegerField('结果', choices=pt_result_choices, default=10) result = models.PositiveSmallIntegerField('结果', choices=pt_result_choices, default=10, help_text=str(pt_result_choices))
handle_result = models.PositiveSmallIntegerField('处理结果', choices = pt_hresult_choices, default=0, help_text=str(pt_hresult_choices))
task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True) task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True)
class Risk(CommonBModel): class Risk(CommonBDModel):
"""风险识别 """风险识别
""" """
risk_level_choices = ( risk_level_choices = (
@ -254,13 +265,13 @@ class Risk(CommonBModel):
(30, '整改完成') (30, '整改完成')
) )
content = models.TextField('内容') content = models.TextField('内容')
level = models.PositiveSmallIntegerField('风险等级', choices=risk_level_choices, default=10) level = models.PositiveSmallIntegerField('风险等级', choices=risk_level_choices, default=10, help_text=str(risk_level_choices))
code = models.CharField('风险代码', max_length=100) code = models.CharField('风险代码', max_length=100)
state = models.PositiveSmallIntegerField('整改状态', choices=risk_state_choices, default=10) state = models.PositiveSmallIntegerField('整改状态', choices=risk_state_choices, default=10, help_text=str(risk_state_choices))
task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True) task2do = models.ForeignKey('supervision.task2do', verbose_name= '关联任务执行', on_delete=models.SET_NULL, null=True, blank=True)
class Oinspect(CommonBModel): class Oinspect(CommonBDModel):
"""外部检查 """外部检查
""" """
oinspect_cate_choices = ( oinspect_cate_choices = (
@ -268,7 +279,7 @@ class Oinspect(CommonBModel):
(20, '行业主管部门检查'), (20, '行业主管部门检查'),
(30, '其他检查') (30, '其他检查')
) )
cate = models.PositiveSmallIntegerField('检查分类', choices=oinspect_cate_choices, default=30) cate = models.PositiveSmallIntegerField('检查分类', choices=oinspect_cate_choices, default=30, help_text=str(oinspect_cate_choices))
checker = models.CharField('检查方', max_length=100) checker = models.CharField('检查方', max_length=100)
date_inspect = models.DateField('检查日期') date_inspect = models.DateField('检查日期')
result = models.TextField('检查结果') result = models.TextField('检查结果')

View File

@ -112,7 +112,7 @@ class Task2Serializer(serializers.ModelSerializer):
read_only_fields = ['create_time', 'update_time', 'create_by', 'update_by', 'belong_dept', 'state', 'is_deleted', 'depts'] read_only_fields = ['create_time', 'update_time', 'create_by', 'update_by', 'belong_dept', 'state', 'is_deleted', 'depts']
def update(self, instance, validated_data): def update(self, instance, validated_data):
validated_data.pop('type') # type不可编辑 validated_data.pop('type', None) # type不可编辑
if instance.state != Task2.TASK2_CLOSE: if instance.state != Task2.TASK2_CLOSE:
raise ParseError('非创建状态不可编辑') raise ParseError('非创建状态不可编辑')
return super().update(instance, validated_data) return super().update(instance, validated_data)
@ -131,23 +131,35 @@ class Task2DoSerializer(serializers.ModelSerializer):
class ValidateMixin: class ValidateMixin:
def validate(self, attrs): def validate(self, attrs):
task2do = attrs.get('task2do', None) task2do = attrs.get('task2do', None)
attrs['create_by'] = self.context['request'].user
attrs['belong_dept'] = self.context['request'].user.dept
if task2do: if task2do:
if task2do.task2.state == Task2.TASK2_CLOSE: if task2do.task2.state == Task2.TASK2_CLOSE:
raise ParseError('任务已关闭不可处理') raise ParseError('任务已关闭不可处理')
attrs['year'] = task2do.task2.year attrs['belong_dept'] = task2do.belong_dept
attrs['belong_dept'] = task2do.task2.belong_dept
return attrs return attrs
class BaseMeta: class BaseMeta:
fields = '__all__' fields = '__all__'
read_only_fields = ['create_time', 'update_time', 'create_by', 'update_by', 'is_deleted'] read_only_fields = ['create_time', 'update_time', 'create_by', 'update_by', 'is_deleted', 'belong_dept']
class PgoalDeptSerializer(ValidateMixin, serializers.ModelSerializer): class PgoalDeptSerializer(serializers.ModelSerializer):
goal_file_ = FileSimpleSerializer(source='goal_file', read_only=True) goal_file_ = FileSimpleSerializer(source='goal_file', read_only=True)
goal_o_file_ = FileSimpleSerializer(source='goal_o_file', read_only=True)
class Meta(BaseMeta): class Meta(BaseMeta):
model = PgoalDept model = PgoalDept
read_only_fields = BaseMeta.read_only_fields + ['goal_value_a', 'goal_value_c', 'goal_files', 'goal_key'] read_only_fields = BaseMeta.read_only_fields + ['goal_value_a', 'goal_value_c', 'goal_files', 'goal_key', 'goal_file_', 'goal_o_file', 'goal_o_file_']
def validate(self, attrs):
task2do = attrs.get('task2do', None)
attrs['create_by'] = self.context['request'].user
attrs['belong_dept'] = self.context['request'].user.dept
if task2do:
if task2do.task2.state == Task2.TASK2_CLOSE:
raise ParseError('任务已关闭不可处理')
attrs['year'] = task2do.task2.year
attrs['belong_dept'] = task2do.belong_dept
return attrs
class RcSerializer(ValidateMixin, serializers.ModelSerializer): class RcSerializer(ValidateMixin, serializers.ModelSerializer):
@ -177,3 +189,17 @@ class OinspectSerializer(ValidateMixin, serializers.ModelSerializer):
class NoRecordSerializer(serializers.Serializer): class NoRecordSerializer(serializers.Serializer):
key = serializers.ChoiceField(label='字段key', choices=['num_error', 'num_overdue', 'num_complaint', 'num_pt', 'num_risk', 'num_oinspect']) key = serializers.ChoiceField(label='字段key', choices=['num_error', 'num_overdue', 'num_complaint', 'num_pt', 'num_risk', 'num_oinspect'])
class UpdateFieldSerializer(serializers.ModelSerializer):
class Meta:
model = Task2Do
fields = ['num_issue', 'num_expect', 'num_acc']
extra_kwargs = {'num_issue': {'required': True}, 'num_expect': {'required': True}, 'num_acc': {'required': True}}
class ImpSerializer(serializers.Serializer):
path = serializers.CharField(label='文件地址')
task2do = serializers.PrimaryKeyRelatedField(label='关联task2do的ID值', queryset = Task2Do.objects.all())

View File

@ -11,6 +11,7 @@ from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelM
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet, ModelViewSet from rest_framework.viewsets import GenericViewSet, ModelViewSet
from utils.pagination import PageOrNot from utils.pagination import PageOrNot
from openpyxl import load_workbook
from apps.system.mixins import CreateUpdateCustomMixin from apps.system.mixins import CreateUpdateCustomMixin
from apps.system.models import Organization from apps.system.models import Organization
@ -410,6 +411,7 @@ class PogalViewSet(CreateUpdateCustomMixin, ModelViewSet):
return PgoalCreateUpdateSerializer return PgoalCreateUpdateSerializer
return super().get_serializer_class() return super().get_serializer_class()
class Task2ViewSet(CreateUpdateCustomMixin, ModelViewSet): class Task2ViewSet(CreateUpdateCustomMixin, ModelViewSet):
perms_map = {'get': '*', 'post': 'task2', perms_map = {'get': '*', 'post': 'task2',
'put': 'task2', 'delete': 'task2'} 'put': 'task2', 'delete': 'task2'}
@ -434,7 +436,7 @@ class Task2ViewSet(CreateUpdateCustomMixin, ModelViewSet):
return Response() return Response()
@transaction.atomic @transaction.atomic
@action(methods=['put'], detail=True, perms_map = {'put':'task2'}) @action(methods=['put'], detail=True, perms_map = {'put':'task2'}, serializer_class=serializers.Serializer)
def start(self, request, *args, **kwargs): def start(self, request, *args, **kwargs):
""" """
开始执行 开始执行
@ -450,13 +452,13 @@ class Task2ViewSet(CreateUpdateCustomMixin, ModelViewSet):
except: except:
raise ParseError('未配置年度基础目标') raise ParseError('未配置年度基础目标')
for i in tds: for i in tds:
for k, v in enumerate(Pgoal.basedict): for key in Pgoal.basedict:
pds = PgoalDept.objects.filter(year=i.year, task2do=i, goal_key=k) pds = PgoalDept.objects.filter(task2do=i, goal_key=key)
if pds.exists(): if pds.exists():
pds.update(**{'goal_name': v, 'goal_value_a': getattr(pg, k), 'goal_o_file': getattr(pg, k+'_file')}) pds.update(**{'goal_name': Pgoal.basedict[key], 'goal_value_a': getattr(pg, key), 'goal_o_file': getattr(pg, key+'_file')})
else: else:
PgoalDept.objects.create(**{'year': i.year, 'task2do': i, 'belong_dept': i.belong_dept, PgoalDept.objects.create(**{'year': i.task2.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')}) 'goal_name': Pgoal.basedict[key], 'goal_key': key, 'goal_value_a': getattr(pg, key), 'goal_o_file': getattr(pg, key+'_file')})
obj.state = Task2.TASK2_DOING obj.state = Task2.TASK2_DOING
obj.save() obj.save()
return Response() return Response()
@ -471,11 +473,11 @@ class Task2ViewSet(CreateUpdateCustomMixin, ModelViewSet):
sr = Task2DeptsSerializer(data=request.data) sr = Task2DeptsSerializer(data=request.data)
sr.is_valid(raise_exception=True) sr.is_valid(raise_exception=True)
vdata = sr.validated_data vdata = sr.validated_data
count_all = 8 count_all = 9
if task2.type == Task2.TASK2_F: if task2.type == Task2.TASK2_F:
count_all = 5 count_all = 5
for i in vdata['ids']: 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}) Task2Do.objects.get_or_create(task2=task2, belong_dept=i, defaults={'task2': task2, 'belong_dept': i, 'count_all': count_all, 'create_by': self.request.user})
return Response() return Response()
@ -484,7 +486,7 @@ class Task2DoViewSet(ListModelMixin, GenericViewSet):
queryset = Task2Do.objects.select_related('belong_dept', 'task2').all() queryset = Task2Do.objects.select_related('belong_dept', 'task2').all()
serializer_class = Task2DoSerializer serializer_class = Task2DoSerializer
ordering = ['belong_dept__sort'] ordering = ['belong_dept__sort']
filterset_fields = ['task2', 'belong_dept', 'task2__year', 'task2__cycle']
cfields = ['num_issue', 'num_expect', 'num_error', 'num_overdue', 'num_complaint', 'num_pt', 'num_risk', 'num_oinspect'] cfields = ['num_issue', 'num_expect', 'num_error', 'num_overdue', 'num_complaint', 'num_pt', 'num_risk', 'num_oinspect']
@classmethod @classmethod
@ -498,19 +500,38 @@ class Task2DoViewSet(ListModelMixin, GenericViewSet):
instance.count_up = count_up instance.count_up = count_up
instance.save() instance.save()
@action(methods=['put'], detail=True, perms_map = {'post':'task2do'}, serializer_class=NoRecordSerializer) @action(methods=['put'], detail=True, perms_map = {'put':'task2do'}, serializer_class=UpdateFieldSerializer)
def save_num(self, request, *args, **kwargs):
"""保存数值
保存数值
"""
obj = self.get_object()
obj.num_issue = request.data.get('num_issue', 0)
obj.num_expect = request.data.get('num_expect', 0)
obj.num_acc = request.data.get('num_acc', 0)
obj.update_by = request.user
obj.save()
self.countup_task2do(obj)
return Response()
@action(methods=['put'], detail=True, perms_map = {'put':'task2do'}, serializer_class=NoRecordSerializer)
def no_record(self, request, *args, **kwargs): def no_record(self, request, *args, **kwargs):
"""没有记录 """没有记录
没有记录 没有记录
""" """
obj = self.get_object() obj = self.get_object()
setattr(obj, request.data.get('key'), 0) theattr = getattr(obj, request.data.get('key'), None)
if theattr is None:
theattr = 0
else:
raise ParseError('已有记录')
obj.save() obj.save()
self.countup_task2do(obj) self.countup_task2do(obj)
return Response() return Response()
@action(methods=['get'], detail=False, perms_map = {'post':'task2do'}) @action(methods=['get'], detail=False, perms_map = {'get':'task2do'})
def my(self, request, *args, **kwargs): def my(self, request, *args, **kwargs):
"""我的任务 """我的任务
@ -523,7 +544,7 @@ class Task2DoViewSet(ListModelMixin, GenericViewSet):
else: else:
mydept = request.user.dept mydept = request.user.dept
belong_depts = get_child_queryset2(mydept) belong_depts = get_child_queryset2(mydept)
queryset = queryset.filter(belong_dept = belong_depts) queryset = queryset.filter(belong_dept__in = belong_depts)
serializer = Task2DoSerializer(queryset, many=True) serializer = Task2DoSerializer(queryset, many=True)
return Response(serializer.data) return Response(serializer.data)
@ -532,80 +553,233 @@ class Domixin:
perms_map = {'get': '*', 'put': 'task2do', 'post': 'task2do', 'delete': 'task2do'} perms_map = {'get': '*', 'put': 'task2do', 'post': 'task2do', 'delete': 'task2do'}
ordering = ['create_time'] ordering = ['create_time']
ordering_fields = ['create_time', 'belong_dept__sort'] ordering_fields = ['create_time', 'belong_dept__sort']
filterset_fields = ['task2do', 'task2do__task2', 'task2do__belong_dept']
def countnum_task2do_field(self, task2do): def countnum_task2do_field(self, task2do):
for k, v in self.count_dict: for k, v in self.count_dict.items():
setattr(task2do, k, self.queryset.model.objects.filter({**{'task2do': task2do}, **v}).count()) setattr(task2do, k, self.queryset.model.objects.filter(**{**{'task2do': task2do}, **v}).count())
task2do.save() task2do.save()
# 更新count_up字段 # 更新count_up字段
Task2DoViewSet.countup_task2do(task2do) Task2DoViewSet.countup_task2do(task2do)
def countup_task2do(self, task2do): def countup_task2do(self, task2do):
if task2do.task2.type == Task2.TASK2_F: if task2do.task2.type == Task2.TASK2_F:
task2do.count_up = PgoalDept.objects.filter(task2do=task2do).count() task2do.count_up = PgoalDept.objects.filter(task2do=task2do).exclude(goal_value_b=None).count()
task2do.save() task2do.save()
elif task2do.task2.type == Task2.TASK2_S: elif task2do.task2.type == Task2.TASK2_S:
self.countnum_task2do_field(task2do) self.countnum_task2do_field(task2do)
@transaction.atomic @transaction.atomic
def perform_create(self, serializer): def perform_create(self, serializer):
instance = super().perform_create(serializer) instance = serializer.save()
self.countup_task2do(instance.task2do) self.countup_task2do(instance.task2do)
@transaction.atomic @transaction.atomic
def perform_destroy(self, instance): def perform_destroy(self, instance):
task2do = instance.task2do task2do = instance.task2do
instance.delete(soft=False) instance.delete()
self.countup_task2do(task2do) self.countup_task2do(task2do)
class PgoalDeptViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet): class PgoalDeptViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet):
queryset = PgoalDept.objects.all() queryset = PgoalDept.objects.all()
serializer_class = PgoalDeptSerializer serializer_class = PgoalDeptSerializer
filterset_fields = ['goal_key', 'belong_dept', 'year', 'task2do']
def perform_update(self, serializer): def perform_update(self, serializer):
instance = super().perform_update(serializer) instance = serializer.save()
goal_file = instance.goal_file goal_file = instance.goal_file
if goal_file: if goal_file:
instance.goal_files.add(goal_file) instance.goal_files.add(goal_file)
class ImpMixin:
def get_enum(self, val, atuple, ind):
for i in atuple:
if i[1] == val:
return i[0]
raise ParseError('{}: 请选择固定选项值'.format(ind))
class RcViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet): def make_data(self, data, sheet, i, etype):
raise NotImplementedError()
def gen_imp_view(self, request, start: int, mySerializer, etype=0):
sr = ImpSerializer(data=request.data)
sr.is_valid(raise_exception=True)
vdata = sr.validated_data
path = vdata['path']
if not path.endswith('.xlsx'):
raise ParseError('请提供xlsx格式文件')
task2do = vdata['task2do']
fullpath = settings.BASE_DIR + path
wb = load_workbook(fullpath,data_only=True)
sheet = wb.worksheets[0]
datalist = []
i = start
while sheet['b'+str(i)].value:
data = {}
data['task2do'] = task2do.id
data = self.make_data(data, sheet, i, etype)
datalist.append(data)
i = i + 1
sr = mySerializer(data=datalist, many=True)
sr.is_valid()
err_msg = ''
for ind, val in enumerate(sr.errors):
if val:
for i in val:
err_msg = '{}行: {}'.format(5+ind, i + str(val[i][0]))
if err_msg != '':
raise ParseError(err_msg)
else:
sr.save(create_by=request.user)
return Response()
class RcViewSet(ImpMixin, Domixin, CreateUpdateCustomMixin, ModelViewSet):
queryset = Rc.objects.all() queryset = Rc.objects.all()
serializer_class = RcSerializer serializer_class = RcSerializer
count_dict = { count_dict = {
"num_error": {'etype': 10}, "num_error": {'etype': 10},
"num_overdue": {'etype': 20} "num_overdue": {'etype': 20}
} }
filterset_fields = ['etype', 'task2do', 'task2do__belong_dept', 'task2do__task2__year']
class ComplaintViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet): def make_data(self, data, sheet, i, etype):
data['etype'] = etype
if etype == 10:
data['number'] = sheet['b'+str(i)].value
data['number_correct'] = sheet['c'+str(i)].value
data['reason_error'] = sheet['d'+str(i)].value
data['date_issue'] = sheet['e'+str(i)].value
else:
data['number'] = sheet['b'+str(i)].value
data['date_accept'] = sheet['c'+str(i)].value
data['date_expect'] = sheet['d'+str(i)].value
data['date_issue'] = sheet['e'+str(i)].value
data['remark'] = sheet['f'+str(i)].value
return data
@action(methods=['post'], detail=False, perms_map = {'post':'task2do'}, serializer_class=ImpSerializer)
@transaction.atomic
def imp_error(self, request, *args, **kwargs):
"""导入表格
导入表格
"""
return self.gen_imp_view(request, 5, RcSerializer, 10)
@action(methods=['post'], detail=False, perms_map = {'post':'task2do'}, serializer_class=ImpSerializer)
@transaction.atomic
def imp_overdue(self, request, *args, **kwargs):
"""导入表格
导入表格
"""
return self.gen_imp_view(request, 5, RcSerializer, 20)
class ComplaintViewSet(ImpMixin, Domixin, CreateUpdateCustomMixin, ModelViewSet):
queryset = Complaint.objects.all() queryset = Complaint.objects.all()
serializer_class = ComplaintSerializer serializer_class = ComplaintSerializer
count_dict = { count_dict = {
"num_complaint": {} "num_complaint": {},
"num_complaint_10": {'is_satisfied': True}
} }
filterset_fields = ['task2do', 'task2do__belong_dept', 'task2do__task2__year']
def make_data(self, data, sheet, i, etype):
data['complainant'] = sheet['b'+str(i)].value
data['date_occurrence'] = sheet['c'+str(i)].value
data['content'] = sheet['d'+str(i)].value
data['date_feedback'] = sheet['e'+str(i)].value
data['is_satisfied'] = True if sheet['f'+str(i)].value == '' else False
return data
@action(methods=['post'], detail=False, perms_map = {'post':'task2do'}, serializer_class=ImpSerializer)
@transaction.atomic
def imp(self, request, *args, **kwargs):
"""导入表格
导入表格
"""
return self.gen_imp_view(request, 5, ComplaintSerializer)
class PtViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet): class PtViewSet(ImpMixin, Domixin, CreateUpdateCustomMixin, ModelViewSet):
queryset = Pt.objects.all() queryset = Pt.objects.all()
serializer_class = PtSerializer serializer_class = PtSerializer
count_dict = { count_dict = {
"num_pt": {} "num_pt": {},
"num_pt_10": {'result': 10}
} }
filterset_fields = ['task2do', 'task2do__belong_dept', 'task2do__task2__year']
def make_data(self, data, sheet, i, etype):
data['name'] = sheet['b'+str(i)].value
data['number'] = sheet['c'+str(i)].value
data['organizer'] = sheet['d'+str(i)].value
data['params'] = sheet['e'+str(i)].value
data['result'] = self.get_enum(sheet['f'+str(i)].value, Pt.pt_result_choices, i)
data['handle_result'] = self.get_enum(sheet['g'+str(i)].value, Pt.pt_hresult_choices, i)
return data
@action(methods=['post'], detail=False, perms_map = {'post':'task2do'}, serializer_class=ImpSerializer)
@transaction.atomic
def imp(self, request, *args, **kwargs):
"""导入表格
导入表格
"""
return self.gen_imp_view(request, 5, PtSerializer)
class RiskViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet): class RiskViewSet(ImpMixin, Domixin, CreateUpdateCustomMixin, ModelViewSet):
queryset = Risk.objects.all() queryset = Risk.objects.all()
serializer_class = RiskSerializer serializer_class = RiskSerializer
count_dict = { count_dict = {
"num_risk": {} "num_risk": {}
} }
filterset_fields = ['task2do', 'task2do__belong_dept', 'task2do__task2__year']
def make_data(self, data, sheet, i, etype):
data['content'] = sheet['b'+str(i)].value
data['level'] = self.get_enum(sheet['c'+str(i)].value, Risk.risk_level_choices, i)
data['code'] = sheet['d'+str(i)].value
data['state'] = self.get_enum(sheet['e'+str(i)].value, Risk.risk_state_choices, i)
return data
@action(methods=['post'], detail=False, perms_map = {'post':'task2do'}, serializer_class=ImpSerializer)
@transaction.atomic
def imp(self, request, *args, **kwargs):
"""导入表格
导入表格
"""
return self.gen_imp_view(request, 5, RiskSerializer)
class OinspectViewSet(Domixin, CreateUpdateCustomMixin, ModelViewSet): class OinspectViewSet(ImpMixin, Domixin, CreateUpdateCustomMixin, ModelViewSet):
queryset = Oinspect.objects.all() queryset = Oinspect.objects.all()
serializer_class = OinspectSerializer serializer_class = OinspectSerializer
count_dict = { count_dict = {
"num_oinspect": {} "num_oinspect": {}
} }
filterset_fields = ['task2do', 'task2do__belong_dept', 'task2do__task2__year']
def make_data(self, data, sheet, i, etype):
data['cate'] = self.get_enum(sheet['b'+str(i)].value, Oinspect.oinspect_cate_choices, i)
data['checker'] = sheet['c'+str(i)].value
data['date_inspect'] = sheet['d'+str(i)].value
data['result'] = sheet['e'+str(i)].value
return data
@action(methods=['post'], detail=False, perms_map = {'post':'task2do'}, serializer_class=ImpSerializer)
@transaction.atomic
def imp(self, request, *args, **kwargs):
"""导入表格
导入表格
"""
return self.gen_imp_view(request, 5, OinspectSerializer)

View File

@ -2,5 +2,5 @@ from django.apps import AppConfig
class RbacConfig(AppConfig): class RbacConfig(AppConfig):
name = 'system' name = 'apps.system'
verbose_name = '系统管理' verbose_name = '系统管理'

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2023-05-23 06:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('system', '0022_delete_historicaldict'),
]
operations = [
migrations.AlterField(
model_name='user',
name='first_name',
field=models.CharField(blank=True, max_length=150, verbose_name='first name'),
),
]

View File

@ -167,6 +167,17 @@ class Dict(SoftModel):
def __str__(self): def __str__(self):
return self.name return self.name
class CommonADModel(BaseModel):
"""
业务用基本表A,包含create_by, update_by字段,物理删除
"""
create_by = models.ForeignKey(
User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='创建人', related_name='%(class)s_create_by')
update_by = models.ForeignKey(
User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='最后编辑人', related_name='%(class)s_update_by')
class Meta:
abstract = True
class CommonAModel(SoftModel): class CommonAModel(SoftModel):
""" """
@ -194,6 +205,19 @@ class CommonBModel(SoftModel):
class Meta: class Meta:
abstract = True abstract = True
class CommonBDModel(BaseModel):
"""
业务用基本表B,包含create_by, update_by, belong_dept字段,物理删除
"""
create_by = models.ForeignKey(
User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='创建人', related_name='%(class)s_create_by')
update_by = models.ForeignKey(
User, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='最后编辑人', related_name='%(class)s_update_by')
belong_dept = models.ForeignKey(
Organization, null=True, blank=True, on_delete=models.SET_NULL, verbose_name='所属部门', related_name='%(class)s_belong_dept')
class Meta:
abstract = True
class File(CommonAModel): class File(CommonAModel):
""" """

View File

@ -2,4 +2,4 @@ from django.apps import AppConfig
class VodConfig(AppConfig): class VodConfig(AppConfig):
name = 'vod' name = 'apps.vod'

Binary file not shown.

View File

@ -126,6 +126,9 @@ USE_TZ = True
CORS_ALLOW_CREDENTIALS = True CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True CORS_ORIGIN_ALLOW_ALL = True
# 默认主键
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/ # https://docs.djangoproject.com/en/3.0/howto/static-files/