This commit is contained in:
caoqianming 2020-10-29 08:40:29 +08:00
parent cb734240e2
commit c3fbfa02fa
13 changed files with 264 additions and 89 deletions

View File

@ -152,7 +152,7 @@ export const asyncRoutes = [
path: 'certapp/:id/:action/',
name: 'Certappmember',
component: () => import('@/views/certapp/certapphandle'),
meta: { title: '派', icon: 'example', perms: ['plan_view'] },
meta: { title: '派', icon: 'example', perms: ['plan_view'] },
hidden: true
},
]
@ -289,6 +289,13 @@ export const asyncRoutes = [
meta: { title: '证书颁发', icon: 'example', perms: ['certificate_issue'] },
hidden: true
},
{
path: 'certapp/:id/issue/',
name: 'Certappissue',
component: () => import('@/views/certapp/certapphandle'),
meta: { title: '发证/通知', icon: 'example', perms: ['certapp_issue'] },
hidden: true
},
]
},
{

View File

@ -218,7 +218,7 @@ getDictList({type__code:'cert_decision', pageoff:true}).then(res=>{
if (!valid) return;
accessCertapp(this.certapp, this.formData).then((res) => {
this.$message.success('成功')
});
})
});
},
handleAcessunit(val,id){
@ -227,7 +227,7 @@ getDictList({type__code:'cert_decision', pageoff:true}).then(res=>{
this.formData.state = res.data.state
this.$emit("stateChange", res.data.state);
this.$emit("flowChange");
})
}).catch(()=>{this.getUnitList()})
}
}

View File

@ -35,15 +35,19 @@
>刷新</el-button>
</el-col>
</el-row>
<el-card style="margin-top:6px">
<div slot="header" class="clearfix">
<span>待评定业务</span>
</div>
<el-table
v-loading="listLoading"
:data="tableData.results"
style="width: 100%;margin-top:10px;"
border
fit
stripe
highlight-current-row
height="320"
@row-click="handleRclick"
>
<el-table-column type="index" width="50" />
<el-table-column label="申请单号">
@ -99,6 +103,55 @@
:limit.sync="listQuery.page_size"
@pagination="getList"
/>
</el-card>
<el-card style="margin-top:6px">
<div slot="header" class="clearfix">
<span>本业务认证单元</span>
</div>
<el-table
v-loading="listLoading2"
:data="tableData2"
border
fit
stripe
highlight-current-row
height="320"
>
<el-table-column type="index" width="50" />
<el-table-column label="单元名称">
<template slot-scope="scope" v-if="scope.row.certunit_">{{ scope.row.certunit_.name }}</template>
</el-table-column>
<el-table-column label="单元描述">
<template slot-scope="scope" v-if="scope.row.certunit_">
{{scope.row.certunit_.description}}
</template>
</el-table-column>
<el-table-column label="状态">
<template slot-scope="scope">
{{ scope.row.teststate}}
</template>
</el-table-column>
<el-table-column label="认证决定">
<template slot-scope="scope" v-if="scope.row.decision_">
{{ scope.row.decision_.name }}
</template>
</el-table-column>
<el-table-column label="关联证书">
<template slot-scope="scope" v-if="scope.row.certificate_">{{ scope.row.certificate_.number}}</template>
</el-table-column>
<el-table-column label="操作" fixed="right">
<template slot-scope="scope" >
<el-button
v-if="scope.row.teststate=='待评定'"
type="primary"
size="small"
:disabled="!checkPermission(['certapp_accessment'])"
@click="handleAccessment2(scope)"
>评定</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
@ -110,15 +163,20 @@ import checkPermission from '@/utils/permission'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { genTree } from '../../utils'
import { getCertappunitList } from "@/api/certappunit"
export default {
components: { Pagination, Treeselect },
data() {
return {
nowCetapp:{},
tableData: {count:0},
listLoading: true,
tableData2: [],
listLoading: false,
listLoading2:false,
listQuery: {
page: 1,
page_size: 20
page_size: 20,
certappunit_certapp__teststate:'待评定'
},
deptOptions: [],
field_list:[]
@ -148,7 +206,8 @@ export default {
resetFilter() {
this.listQuery = {
page: 1,
page_size: 20
page_size: 20,
certappunit_certapp__teststate:'待评定'
}
this.getList()
},
@ -179,7 +238,25 @@ this.$router.push({
name: "Certappaccess",
params: { id: scope.row.id, action:'access' },
});
}
},
handleAccessment2(scope) {
this.$router.push({
name: "Certappaccess",
params: { id: this.nowCetapp.id, action:'access' },
});
},
handleRclick(row, column, event) {
this.listLoading2 = true;
this.nowCetapp = {id:row.id,number:row.number}
getCertappunitList({ certapp: row.id, pageoff:true})
.then((res) => {
this.tableData2 = res.data;
this.listLoading2 = false;
})
.catch((e) => {
this.listLoading2 = false;
});
},
}
};
</script>

View File

@ -44,7 +44,7 @@
<el-tab-pane label="认证评定" name="Certappaccess" v-if="certapp" lazy>
<access :certapp="certapp" :key="Certappaccesskey" @stateChange="stateChange" @flowChange="flowChange"></access>
</el-tab-pane>
<el-tab-pane label="证书颁发/通知" name="Certissue" v-if="certapp" lazy>
<el-tab-pane label="证书颁发/通知" name="Certappissue" v-if="certapp" lazy>
<issue :certapp="certapp"></issue>
</el-tab-pane>
</el-tabs>

View File

@ -14,6 +14,9 @@
<el-table-column label="单元名称">
<template slot-scope="scope" v-if="scope.row.certunit_">{{ scope.row.certunit_.name }}</template>
</el-table-column>
<el-table-column label="状态">
<template slot-scope="scope" >{{ scope.row.teststate }}</template>
</el-table-column>
<el-table-column label="认证决定">
<template slot-scope="scope" v-if="scope.row.decision_">
{{ scope.row.decision_.name }}

View File

@ -1,6 +1,7 @@
<template>
<div class="app-container">
<div style="display:flex">
<el-row :gutter="6">
<el-col :xs="24" :md="4">
<treeselect
v-model="listQuery.user__dept"
:multiple="false"
@ -8,15 +9,18 @@
placeholder="所属组织"
:disable-branch-nodes="true"
@input="handleFilter"
style="width: 280px" clearable/>
style="width: 100%" clearable/>
</el-col>
<el-col :xs="24" :md="4">
<el-input
v-model="listQuery.search"
placeholder="姓名/易记码/编号/注册领域"
style="width: 300px;margin-left:10px"
style="width: 100%"
class="filter-item"
@keyup.enter.native="handleFilter"
/>
</el-col>
<el-col :xs="24" :md="4">
<el-button
class="filter-item"
type="primary"
@ -28,17 +32,22 @@
type="primary"
icon="el-icon-refresh-left"
@click="resetFilter"
>刷新重置</el-button>
>刷新</el-button>
</el-col>
</el-row>
<el-card style="margin-top:6px">
<div slot="header" class="clearfix">
<span>待处理业务</span>
</div>
<el-table
v-loading="listLoading"
:data="tableData.results"
style="width: 100%;margin-top:10px;"
border
fit
stripe
highlight-current-row
height="320"
@row-click="handleRclick"
>
<el-table-column type="index" width="50" />
<el-table-column label="申请单号">
@ -75,9 +84,9 @@
<el-button
type="primary"
size="small"
:disabled="!checkPermission(['certapp_accessment'])"
:disabled="!checkPermission(['certificate_issue'])"
@click="handleIssue(scope)"
></el-button>
>/通知</el-button>
<el-button
size="small"
:disabled="!checkPermission(['certapp_detail'])"
@ -94,6 +103,55 @@
:limit.sync="listQuery.page_size"
@pagination="getList"
/>
</el-card>
<el-card style="margin-top:6px">
<div slot="header" class="clearfix">
<span>本业务认证单元</span>
</div>
<el-table
v-loading="listLoading2"
:data="tableData2"
border
fit
stripe
highlight-current-row
height="320"
>
<el-table-column type="index" width="50" />
<el-table-column label="单元名称">
<template slot-scope="scope" v-if="scope.row.certunit_">{{ scope.row.certunit_.name }}</template>
</el-table-column>
<el-table-column label="单元描述">
<template slot-scope="scope" v-if="scope.row.certunit_">
{{scope.row.certunit_.description}}
</template>
</el-table-column>
<el-table-column label="状态">
<template slot-scope="scope">
{{ scope.row.teststate}}
</template>
</el-table-column>
<el-table-column label="认证决定">
<template slot-scope="scope" v-if="scope.row.decision_">
{{ scope.row.decision_.name }}
</template>
</el-table-column>
<el-table-column label="关联证书">
<template slot-scope="scope" v-if="scope.row.certificate_">{{ scope.row.certificate_.number}}</template>
</el-table-column>
<el-table-column label="操作" fixed="right">
<template slot-scope="scope" >
<el-button
v-if="scope.row.teststate=='已评定'"
type="primary"
size="small"
:disabled="!checkPermission(['certificate_issue'])"
@click="handleIssue2(scope)"
>发证/通知</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
@ -105,15 +163,20 @@ import checkPermission from '@/utils/permission'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import { genTree } from '../../utils'
import { getCertappunitList } from "@/api/certappunit"
export default {
components: { Pagination, Treeselect },
data() {
return {
nowCetapp:{},
tableData: {count:0},
listLoading: true,
tableData2: [],
listLoading: false,
listLoading2:false,
listQuery: {
page: 1,
page_size: 20
page_size: 20,
certappunit_certapp__teststate:'已评定'
},
deptOptions: [],
field_list:[]
@ -143,7 +206,8 @@ export default {
resetFilter() {
this.listQuery = {
page: 1,
page_size: 20
page_size: 20,
certappunit_certapp__teststate:'待评定'
}
this.getList()
},
@ -171,10 +235,28 @@ this.$router.push({
},
handleIssue(scope) {
this.$router.push({
name: "Certissue",
name: "Certappissue",
params: { id: scope.row.id, action:'issue' },
});
}
},
handleIssue2(scope) {
this.$router.push({
name: "Certappissue",
params: { id: this.nowCetapp.id, action:'issue' },
});
},
handleRclick(row, column, event) {
this.listLoading2 = true;
this.nowCetapp = {id:row.id,number:row.number}
getCertappunitList({ certapp: row.id, pageoff:true})
.then((res) => {
this.tableData2 = res.data;
this.listLoading2 = false;
})
.catch((e) => {
this.listLoading2 = false;
});
},
}
};
</script>

View File

@ -2,40 +2,8 @@ from utils import serializer
from rest_framework import serializers
from .models import *
from apps.system.serializers import DictSimpleSerializer, UserListSerializer, UserSimpleSerializer
from apps.project.models import Project
from apps.plan.models import Member
from apps.project.serializers import PlanSerializer
from apps.plan.serializers import MemberSerializer
class ProjectSerializerX(serializers.ModelSerializer):
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
certapps = serializers.SerializerMethodField()
plan_ = PlanSerializer(source='plan', read_only=True)
members = serializers.SerializerMethodField()
class Meta:
model = Project
fields = '__all__'
def get_certapps(self, obj):
certapps = []
for i in obj.certapp_project.filter(is_deleted=False):
certapps.append(i.cert_field.code +'(' + i.cccpv_class.name +')')
return certapps
def get_members(self, obj):
queryset = obj.certapp_project.all()
members = Member.objects.filter(certapp__in=queryset, is_deleted=False).distinct('is_leader','user').order_by('-is_leader')
serializer = MemberSerializer(members, many=True)
return serializer.data
@staticmethod
def setup_eager_loading(queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.select_related('create_by', 'plan')
queryset = queryset.prefetch_related('certapp_project',)
return queryset
from apps.project.models import CertApp
from apps.system.serializers import DictSimpleSerializer, UserSimpleSerializer
class CertappSerializerX(serializers.ModelSerializer):
cert_field_ = DictSimpleSerializer(source='cert_field', read_only=True)
@ -43,7 +11,6 @@ class CertappSerializerX(serializers.ModelSerializer):
cnas_scopes_ = DictSimpleSerializer(source='cnas_scopes', many=True , read_only=True)
create_by_ = UserSimpleSerializer(source='create_by', read_only=True)
accept_by_ = UserSimpleSerializer(source='accept_by', read_only=True)
members = serializers.SerializerMethodField()
class Meta:
model = CertApp
fields = '__all__'
@ -55,7 +22,3 @@ class CertappSerializerX(serializers.ModelSerializer):
queryset = queryset.prefetch_related('cnas_scopes', 'member_certapp')
return queryset
def get_members(self, obj):
members = Member.objects.filter(certapp=obj, is_deleted=False).order_by('-is_leader')
serializer = MemberSerializer(members, many=True)
return serializer.data

View File

@ -4,14 +4,19 @@ from rest_framework.mixins import ListModelMixin
from .models import *
from .serializers import *
from apps.project.models import *
from apps.project.models import CertApp
# Create your views here.
class CertaccessViewSet(PageOrNot, ListModelMixin, GenericViewSet):
"""
业务评定
"""
perms_map = {'get': 'access_view'}
queryset = CertApp.objects.all()
serializer_class = CertappSerializerX
filterset_fields = []
ordering = ['-create_time']
def get_queryset(self):
queryset = CertApp.objects.filter(state__in=['产品检测', '评定', '出证'])
if hasattr(self.get_serializer_class(), 'setup_eager_loading'):
queryset = self.get_serializer_class().setup_eager_loading(queryset)
return queryset

View File

@ -29,10 +29,7 @@ class EnterpriseAddressSerializer(serializers.ModelSerializer):
model = EnterpriseAddress
fields = '__all__'
class SimpEnterpriseSerializer(serializers.ModelSerializer):
class Meta:
model = Enterprise
fields = ['name']
class CertunitSerializer(serializers.ModelSerializer):
standard_ = StandardSerializer(source='standard', read_only=True)
enterprise_ = serializers.CharField(source='enterprise',read_only=True)
@ -40,14 +37,15 @@ class CertunitSerializer(serializers.ModelSerializer):
model = Certunit
fields = '__all__'
class CertunitSimpleSerializer(serializers.ModelSerializer):
enterprise_ = SimpEnterpriseSerializer(source='enterprise',read_only=True)
class Meta:
model = Certunit
fields = ['id', 'name','description','enterprise','enterprise_']
class EnterpriseSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Enterprise
fields = ['id', 'name']
class CertunitSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Certunit
fields = ['id', 'name','description']

View File

@ -48,14 +48,29 @@ class MemberViewSet(CreateUpdateCustomMixin, PageOrNot, ModelViewSet):
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
if CertApp.object.get(pk=request.data['certapp'])!='策划':
return Response('业务状态异常,操作失败', status = status.HTTP_400_BAD_REQUEST)
if CertApp.objects.get(pk=request.data['certapp']).project.state !='策划':
return Response('项目状态异常,操作失败', status = status.HTTP_400_BAD_REQUEST)
if Member.objects.filter(user = request.data['user'], certapp=request.data['certapp'], is_deleted=False).exists():
return Response('已存在该成员', status= status.HTTP_400_BAD_REQUEST)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if CertApp.objects.get(pk=request.data['certapp']).project.state !='策划中':
return Response('项目状态异常,操作失败', status = status.HTTP_400_BAD_REQUEST)
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
return Response(serializer.data)
@action(methods=['put'], detail=True, perms_map={'put':'audit_days'},
url_name='audit_days')
def days(self, request, *args, **kwargs):

View File

@ -0,0 +1,21 @@
# Generated by Django 3.0.7 on 2020-10-23 03:09
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', '0053_project_feedback_remark'),
]
operations = [
migrations.AddField(
model_name='certappunit',
name='assessor',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='certappunit_assessor', to=settings.AUTH_USER_MODEL, verbose_name='评定人'),
),
]

View File

@ -243,7 +243,7 @@ class Certappunit(CommonBModel):
('待提取报告', '待提取报告'),
('待实验室整改', '待实验室整改'),
('待评定', '待评定'),
('评定完成', '评定完成'),
('评定', '评定'),
('任务撤销', '任务撤销'),
)
@ -272,7 +272,7 @@ class Certappunit(CommonBModel):
remarks = models.TextField('检验反馈备注', null=True, blank=True)
path = models.CharField('文件地址', max_length=1000, null=True, blank=True)
inspectionstate = models.CharField('实验室检验状态', choices=charge_choices,null=True, blank=True, max_length=50)
assessor = models.ForeignKey(User, related_name='certappunit_assessor', on_delete=models.SET_NULL, null=True, blank=True, verbose_name='评定人')
class Meta:
verbose_name = '认证单元'
verbose_name_plural = verbose_name

View File

@ -78,7 +78,7 @@ class CertappViewset(PageOrNot, RbacFilterSet, ModelViewSet):
queryset = CertApp.objects.all()
serializer_class = CertappSerializer
ordering = ['-create_time']
filterset_fields = ['state', 'project']
filterset_fields = ['state', 'project', 'certappunit_certapp__teststate']
# filterset_class = CertAppFilter
@ -206,12 +206,16 @@ class CertappunitViewset(PageOrNot, ModelViewSet):
单元评定
"""
obj = self.get_object()
if obj.teststate == '待评定':
if request.data['decision']:
obj.decision = Dict.objects.get(pk=request.data['decision'])
else:
obj.decision = None
obj.teststate = '已评定'
obj.save()
return Response(status=status.HTTP_200_OK)
else:
return Response('项目状态异常,操作失败', status=status.HTTP_400_BAD_REQUEST)
@action(methods=['put'], detail=True, perms_map={'put':'certapp_testtask'}, url_name='certappunit_testtask')
def testtask(self, request, pk=None):
"""