项目制定

This commit is contained in:
caoqianming 2020-08-21 15:52:15 +08:00
parent 0a551786c3
commit 0487fac0c2
15 changed files with 348 additions and 20 deletions

View File

@ -22,7 +22,7 @@ class Standard(CommonAModel):
verbose_name_plural = verbose_name verbose_name_plural = verbose_name
def __str__(self): def __str__(self):
return self.name return self.code + '-' + self.name
class ImplementRule(CommonAModel): class ImplementRule(CommonAModel):
@ -44,7 +44,7 @@ class ImplementRule(CommonAModel):
verbose_name_plural = verbose_name verbose_name_plural = verbose_name
def __str__(self): def __str__(self):
return self.name return self.code +'-'+ self.name
class UnitType(CommonAModel): class UnitType(CommonAModel):

View File

@ -6,31 +6,50 @@ from apps.system.serializers import DictSerializer
class StandardSerializer(serializers.ModelSerializer): class StandardSerializer(serializers.ModelSerializer):
fullname = serializers.SerializerMethodField(read_only=True)
class Meta: class Meta:
model = Standard model = Standard
fields = '__all__' fields = '__all__'
def get_fullname(self, obj):
fullname = obj.code + ' ' + obj.name
if obj.code in obj.name:
fullname = obj.name
return fullname
class ImplementRuleSerializer(serializers.ModelSerializer): class ImplementRuleSerializer(serializers.ModelSerializer):
cert_field_ = DictSerializer(source='cert_field', read_only=True) cert_field_ = DictSerializer(source='cert_field', read_only=True)
fullname = serializers.SerializerMethodField(read_only=True)
class Meta: class Meta:
model = ImplementRule model = ImplementRule
fields = '__all__' fields = '__all__'
def get_fullname(self, obj):
fullname = obj.code + ' ' + obj.name
if obj.code in obj.name:
fullname = obj.name
return fullname
class ImplementRuleListSerializer(serializers.ModelSerializer): class ImplementRuleListSerializer(serializers.ModelSerializer):
pv_scope = DictSerializer() pv_scope = DictSerializer()
pv_class = DictSerializer() pv_class = DictSerializer()
cert_field = DictSerializer() cert_field = DictSerializer()
ccc_list = DictSerializer(many=True) ccc_list = DictSerializer(many=True)
fullname = serializers.SerializerMethodField(read_only=True)
class Meta: class Meta:
model = ImplementRule model = ImplementRule
fields = ['id', 'code', 'name', 'cert_field', 'pv_scope', 'pv_class', 'create_time', 'ccc_list'] fields = ['id', 'code', 'name', 'cert_field', 'pv_scope', 'pv_class', 'create_time', 'ccc_list', 'fullname']
@staticmethod @staticmethod
def setup_eager_loading(queryset): def setup_eager_loading(queryset):
""" Perform necessary eager loading of data. """ """ Perform necessary eager loading of data. """
queryset = queryset.select_related('pv_scope','pv_class', 'cert_field') queryset = queryset.select_related('pv_scope','pv_class', 'cert_field')
queryset = queryset.prefetch_related('ccc_list',) queryset = queryset.prefetch_related('ccc_list',)
return queryset return queryset
def get_fullname(self, obj):
fullname = obj.code + ' ' + obj.name
if obj.code in obj.name:
fullname = obj.name
return fullname
# def get_cert_field(self, obj): # def get_cert_field(self, obj):
# return obj.get_cert_field_display() # return obj.get_cert_field_display()

View File

@ -21,7 +21,7 @@ class ImplementRuleViewSet(CreateUpdateCustomMixin, OptimizationMixin, ModelView
queryset = ImplementRule.objects.all() queryset = ImplementRule.objects.all()
serializer_class = ImplementRuleSerializer serializer_class = ImplementRuleSerializer
search_fields = ['name', 'code', 'cert_field'] search_fields = ['name', 'code', 'cert_field']
filterset_fields = ['pv_scope', 'cert_field', 'cert_field__code'] filterset_fields = ['pv_scope', 'cert_field', 'cert_field__code', 'ccc_list']
ordering = ['-create_time'] ordering = ['-create_time']
def get_serializer_class(self): def get_serializer_class(self):

View File

@ -0,0 +1,8 @@
from django_filters import rest_framework as filters
from .models import *
class CertAppFilter(filters.FilterSet):
noproject = filters.BooleanFilter(field_name='project', lookup_expr='isnull')
class Meta:
model = CertApp
fields = ['status', 'noproject']

View File

@ -0,0 +1,20 @@
# Generated by Django 3.0.7 on 2020-08-17 01:48
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('certset', '0016_auto_20200805_1435'),
('project', '0019_auto_20200813_1744'),
]
operations = [
migrations.AddField(
model_name='unit',
name='standard',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='certset.Standard', verbose_name='采用标准'),
),
]

View File

@ -0,0 +1,33 @@
# Generated by Django 3.0.7 on 2020-08-18 03:53
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('certset', '0016_auto_20200805_1435'),
('project', '0020_unit_standard'),
]
operations = [
migrations.AddField(
model_name='unit',
name='implementrule',
field=models.ForeignKey(default=6, on_delete=django.db.models.deletion.DO_NOTHING, to='certset.ImplementRule', verbose_name='采用规则'),
preserve_default=False,
),
migrations.AlterField(
model_name='unit',
name='standard',
field=models.ForeignKey(default=2, on_delete=django.db.models.deletion.DO_NOTHING, to='certset.Standard', verbose_name='采用标准'),
preserve_default=False,
),
migrations.AlterField(
model_name='unit',
name='unittype',
field=models.ForeignKey(default=4, on_delete=django.db.models.deletion.DO_NOTHING, to='certset.UnitType', verbose_name='单元类型'),
preserve_default=False,
),
]

View File

@ -0,0 +1,47 @@
# Generated by Django 3.0.7 on 2020-08-18 09:04
import django.contrib.postgres.fields.jsonb
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('crm', '0011_enterprise_parent'),
('project', '0021_auto_20200818_1153'),
]
operations = [
migrations.AddField(
model_name='certapp',
name='scope',
field=models.TextField(blank=True, null=True, verbose_name='认证范围'),
),
migrations.AddField(
model_name='project',
name='assign_date',
field=models.DateField(blank=True, null=True, verbose_name='下达日期'),
),
migrations.AddField(
model_name='project',
name='auditee',
field=models.ForeignKey(default=43, on_delete=django.db.models.deletion.DO_NOTHING, related_name='project_auditee', to='crm.Enterprise', verbose_name='受审核方'),
preserve_default=False,
),
migrations.AddField(
model_name='project',
name='auditee_v',
field=django.contrib.postgres.fields.jsonb.JSONField(default=dict, verbose_name='受审核方'),
),
migrations.AddField(
model_name='project',
name='number',
field=models.CharField(blank=True, max_length=100, null=True, verbose_name='项目编号'),
),
migrations.AddField(
model_name='project',
name='remark',
field=models.TextField(blank=True, null=True, verbose_name='备注'),
),
]

View File

@ -0,0 +1,22 @@
# Generated by Django 3.0.7 on 2020-08-21 01:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('project', '0022_auto_20200818_1704'),
]
operations = [
migrations.AlterModelOptions(
name='project',
options={'verbose_name': '认证项目', 'verbose_name_plural': '认证项目'},
),
migrations.AddField(
model_name='project',
name='status',
field=models.CharField(choices=[('待下达', '待下达'), ('待派差', '待派差'), ('进行中', '进行中'), ('已中止', '已中止'), ('已完成', '已完成')], default='待下达', max_length=50, verbose_name='项目状态'),
),
]

View File

@ -0,0 +1,21 @@
# Generated by Django 3.0.7 on 2020-08-21 02:04
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('project', '0023_auto_20200821_0957'),
]
operations = [
migrations.AddField(
model_name='project',
name='assign_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='下达人'),
),
]

View File

@ -0,0 +1,46 @@
# Generated by Django 3.0.7 on 2020-08-21 07:41
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 = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('system', '0028_auto_20200807_1018'),
('project', '0024_project_assign_by'),
]
operations = [
migrations.AddField(
model_name='project',
name='can_paichai',
field=models.BooleanField(default=False, verbose_name='是否可派差'),
),
migrations.CreateModel(
name='Plan',
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=1000, verbose_name='计划名称')),
('month', 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='plan_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='plan_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='plan_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')),
],
options={
'verbose_name': '审核计划',
'verbose_name_plural': '审核计划',
},
),
migrations.AddField(
model_name='project',
name='plan',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='project.Plan', verbose_name='所属计划'),
),
]

View File

@ -4,17 +4,54 @@ from django.db import models
from rest_framework.exceptions import ParseError from rest_framework.exceptions import ParseError
from simple_history.models import HistoricalRecords from simple_history.models import HistoricalRecords
from apps.certset.models import ImplementRule, UnitType, EvaluationItem from apps.certset.models import ImplementRule, UnitType, EvaluationItem, Standard
from apps.crm.models import Enterprise from apps.crm.models import Enterprise
from apps.system.models import CommonAModel, CommonBModel, Dict, User from apps.system.models import CommonAModel, CommonBModel, Dict, User
# Create your models here. # Create your models here.
class Plan(CommonBModel):
"""
计划(项目组)
"""
name = models.CharField('计划名称', max_length = 1000)
month = models.DateField('计划审核月份', null=True, blank=True)
class Meta:
verbose_name = '审核计划'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
class Project(CommonBModel): class Project(CommonBModel):
""" """
认证项目 认证项目
""" """
pass status_choices = (
('待下达', '待下达'),
('待派差', '待派差'),
('进行中', '进行中'),
('已中止', '已中止'),
('已完成', '已完成')
)
status = models.CharField('项目状态', choices=status_choices, default='待下达', max_length=50)
number = models.CharField('项目编号', max_length = 100, null=True, blank=True)
auditee = models.ForeignKey(Enterprise, related_name='project_auditee', on_delete=models.DO_NOTHING, verbose_name='受审核方')
auditee_v = JSONField(verbose_name='受审核方', default=dict)
remark = models.TextField('备注', null=True, blank=True)
assign_date = models.DateField('下达日期', null=True, blank=True)
assign_by = models.ForeignKey(User, verbose_name='下达人', on_delete=models.SET_NULL, null=True, blank=True)
can_paichai = models.BooleanField('是否可派差', default = False)
plan = models.ForeignKey(Plan, verbose_name='所属计划', on_delete=models.SET_NULL, null=True, blank=True)
class Meta:
verbose_name = '认证项目'
verbose_name_plural = verbose_name
def __str__(self):
return self.number
class CertApp(CommonBModel): class CertApp(CommonBModel):
""" """
@ -60,6 +97,7 @@ class CertApp(CommonBModel):
manufacture_v = JSONField(verbose_name='制造商', null=True) manufacture_v = JSONField(verbose_name='制造商', null=True)
factory = models.ForeignKey(Enterprise, on_delete=models.CASCADE, related_name='certapp_factory', null=True, blank=True) factory = models.ForeignKey(Enterprise, on_delete=models.CASCADE, related_name='certapp_factory', null=True, blank=True)
factory_v = JSONField(verbose_name='生产厂', null=True) factory_v = JSONField(verbose_name='生产厂', null=True)
scope = models.TextField('认证范围', null=True, blank=True)
class Meta: class Meta:
verbose_name = '认证受理' verbose_name = '认证受理'
@ -161,7 +199,9 @@ class Unit(CommonBModel):
""" """
name = models.CharField('单元名称', max_length=200) name = models.CharField('单元名称', max_length=200)
description = models.TextField('单元描述', blank=True) description = models.TextField('单元描述', blank=True)
unittype = models.ForeignKey(UnitType, verbose_name='单元类型', on_delete = models.SET_NULL, null=True, blank=True) implementrule = models.ForeignKey(ImplementRule, verbose_name='采用规则', on_delete=models.DO_NOTHING)
unittype = models.ForeignKey(UnitType, verbose_name='单元类型', on_delete = models.DO_NOTHING)
standard = models.ForeignKey(Standard, verbose_name='采用标准', on_delete = models.DO_NOTHING)
certapp = models.ForeignKey(CertApp, verbose_name='所属业务', on_delete = models.CASCADE) certapp = models.ForeignKey(CertApp, verbose_name='所属业务', on_delete = models.CASCADE)
class Meta: class Meta:
@ -171,3 +211,10 @@ class Unit(CommonBModel):
def __str__(self): def __str__(self):
return self.name return self.name
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
obj = self.certapp
objs = Unit.objects.filter(certapp=obj, is_deleted=False).values_list('name', flat=True)
obj.scope = obj.factory_v['address'] + ':' + ';'.join(objs)
obj.save()

View File

@ -3,7 +3,7 @@ from rest_framework import serializers
from .models import * from .models import *
from apps.system.serializers import DictSerializer, UserListSerializer from apps.system.serializers import DictSerializer, UserListSerializer
# from apps.certset.serializers import ImplementRuleSerializer from apps.certset.serializers import StandardSerializer
class ApplicationCreateSerializer(serializers.ModelSerializer): class ApplicationCreateSerializer(serializers.ModelSerializer):
number = serializers.CharField(required=False) number = serializers.CharField(required=False)
@ -46,6 +46,20 @@ class CertappSerializer(serializers.ModelSerializer):
fields = '__all__' fields = '__all__'
class UnitSerializer(serializers.ModelSerializer): class UnitSerializer(serializers.ModelSerializer):
standard_ = StandardSerializer(source='standard', read_only=True)
class Meta: class Meta:
model = Unit model = Unit
fields = '__all__' fields = '__all__'
class ProjectSerializer(serializers.ModelSerializer):
create_by_ = UserListSerializer(source='create_by', read_only=True)
certapps = serializers.SerializerMethodField()
class Meta:
model = Project
fields = '__all__'
def get_certapps(self, obj):
certapps = []
for i in CertApp.objects.filter(is_deleted=False, project=obj):
certapps.append(i.cert_field.code +'(' + i.cccpv_class.name +')')
return certapps

View File

@ -7,6 +7,7 @@ router.register('application', ApplicationViewSet, basename="application")
router.register('subapplication', SubApplicationViewSet, basename="subapplication") router.register('subapplication', SubApplicationViewSet, basename="subapplication")
router.register('certapp', CertappViewset, basename="certapp") router.register('certapp', CertappViewset, basename="certapp")
router.register('unit', UnitViewSet, basename="unit") router.register('unit', UnitViewSet, basename="unit")
router.register('project', ProjectViewSet, basename="project")
urlpatterns = [ urlpatterns = [
path('', include(router.urls)) path('', include(router.urls))
] ]

View File

@ -10,9 +10,10 @@ from apps.system.models import Dict
from apps.system.permission_data import RbacFilterSet from apps.system.permission_data import RbacFilterSet
from apps.system.mixins import CreateUpdateCustomMixin, OptimizationMixin from apps.system.mixins import CreateUpdateCustomMixin, OptimizationMixin
import random import random
from rest_framework.decorators import action
from .filters import *
# Create your views here. # Create your views here.
class ApplicationViewSet(CreateUpdateCustomMixin, ModelViewSet): class ApplicationViewSet(CreateUpdateCustomMixin, RbacFilterSet, ModelViewSet):
""" """
认证申请 认证申请
""" """
@ -30,7 +31,7 @@ class ApplicationViewSet(CreateUpdateCustomMixin, ModelViewSet):
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(create_by = self.request.user, belong_dept=self.request.user.dept, number=random.randrange(1000,2000)) serializer.save(create_by = self.request.user, belong_dept=self.request.user.dept, number=random.randrange(1000,2000))
class SubApplicationViewSet(CreateUpdateCustomMixin, ModelViewSet): class SubApplicationViewSet(CreateUpdateCustomMixin, RbacFilterSet, ModelViewSet):
""" """
子认证申请 子认证申请
""" """
@ -61,7 +62,7 @@ class SubApplicationViewSet(CreateUpdateCustomMixin, ModelViewSet):
return None return None
return self.paginator.paginate_queryset(queryset, self.request, view=self) return self.paginator.paginate_queryset(queryset, self.request, view=self)
class CertappViewset(CreateUpdateCustomMixin, ModelViewSet): class CertappViewset(CreateUpdateCustomMixin, RbacFilterSet, ModelViewSet):
""" """
申请受理 申请受理
""" """
@ -69,24 +70,75 @@ class CertappViewset(CreateUpdateCustomMixin, ModelViewSet):
queryset = CertApp.objects.all() queryset = CertApp.objects.all()
serializer_class = CertappSerializer serializer_class = CertappSerializer
ordering = ['-create_time'] ordering = ['-create_time']
filterset_fields = ['status', 'project']
# filterset_class = CertAppFilter
def paginate_queryset(self, queryset):
if ((not self.request.query_params.get('page', None)) and (self.request.query_params.get('status', None))) or (self.paginator is None):
return None
return self.paginator.paginate_queryset(queryset, self.request, view=self)
return queryset
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
postdata = request.data postdata = request.data
postdata['number'] = random.randrange(1000,2000) postdata['number'] = random.randrange(1000,2000)
if postdata.get('field_code', None): if postdata.get('field_code', None):
postdata['cert_field'] = Dict.objects.get(code=postdata['field_code']).id postdata['cert_field'] = Dict.objects.get(code=postdata['field_code']).id
print(postdata)
serializer = self.get_serializer(data=postdata) serializer = self.get_serializer(data=postdata)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
self.perform_create(serializer) self.perform_create(serializer)
headers = self.get_success_headers(serializer.data) headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
class UnitViewSet(CreateUpdateCustomMixin, ModelViewSet): @action(methods=['put'], detail=True, perms_map={'put':'complete_certapp'},
url_name='complete_certapp')
def complete(self, request, pk=None):
"""
完成受理
"""
obj = self.get_object()
obj.status = '已受理'
obj.save()
return Response(status=status.HTTP_200_OK)
class UnitViewSet(CreateUpdateCustomMixin, RbacFilterSet, ModelViewSet):
""" """
产品单元 产品单元
""" """
perms_map = {'get': 'certapp_view', 'post':'certapp_create', 'put':'certapp_update','delete': 'certapp_delete'} perms_map = {'get': 'certapp_view', 'post':'certapp_create', 'put':'certapp_update','delete': 'certapp_delete'}
queryset = Unit.objects.all() queryset = Unit.objects.all()
serializer_class = UnitSerializer serializer_class = UnitSerializer
ordering = ['-create_time'] ordering = ['pk']
filterset_fields = ['certapp']
class ProjectViewSet(CreateUpdateCustomMixin, RbacFilterSet, ModelViewSet):
perms_map = {'get': 'project_view', 'post':'project_create', 'put':'project_update','delete': 'project_delete'}
queryset = Project.objects.all()
serializer_class = ProjectSerializer
ordering = ['pk']
def create(self, request, *args, **kwargs):
postdata = request.data
postdata['number'] = random.randrange(8000,9000)
serializer = self.get_serializer(data=postdata)
serializer.is_valid(raise_exception=True)
instance = serializer.save(create_by = self.request.user, belong_dept=self.request.user.dept)
if 'certapps' in postdata and postdata['certapps']:
CertApp.objects.filter(pk__in = postdata['certapps']).update(project=instance, status='进行中')
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
@action(methods=['put'], detail=True, perms_map={'put':'project_assgin'},
url_name='project_assgin')
def assgin(self, request, pk=None):
"""
下达项目
"""
obj = self.get_object()
if obj.status == '待下达':
obj.status = '待派差'
obj.save()
return Response(status=status.HTTP_200_OK)
else:
return Response('状态有误', status=status.HTTP_400_BAD_REQUEST)

View File

@ -50,9 +50,7 @@ class RbacFilterSet(CreateUpdateModelBMixin, object):
return queryset return queryset
elif '仅本人' in data_range: elif '仅本人' in data_range:
queryset = queryset.filter(Q(create_by=user)|Q(update_by=user)) queryset = queryset.filter(Q(create_by=user)|Q(update_by=user))
return queryset return queryset
if hasattr(self.get_serializer_class(), 'setup_eager_loading'):
queryset = self.get_serializer_class().setup_eager_loading(queryset) # 性能优化
return queryset return queryset