校验上传的证件照片
This commit is contained in:
parent
3f0d73416b
commit
b04d372e19
|
@ -61,10 +61,11 @@ class Access(CommonADModel):
|
|||
type = models.PositiveSmallIntegerField('准入类型', choices=ACCESS_CHOICE)
|
||||
area = models.ForeignKey(Area, verbose_name='关联区域',
|
||||
on_delete=models.CASCADE)
|
||||
obj_cate = models.CharField('对象类型', max_length=20, help_text='post/org/people')
|
||||
obj_cate = models.CharField('对象类型', max_length=20, help_text='post/org/people/visit')
|
||||
post = models.ForeignKey(Post, verbose_name='关联岗位', on_delete=models.CASCADE, null=True, blank=True)
|
||||
dept = models.ForeignKey(Dept, verbose_name='关联部门', on_delete=models.CASCADE, null=True, blank=True)
|
||||
employee = models.ForeignKey(Employee, verbose_name='关联人员', on_delete=models.CASCADE, null=True, blank=True)
|
||||
visit = models.ForeignKey('vm.visit', verbose_name='关联访客项目', on_delete=models.SET_NULL, db_constraint=False, null=True, blank=True)
|
||||
stay_minute_min = models.PositiveSmallIntegerField('最短停留时间', default=0)
|
||||
stay_minute_max = models.PositiveSmallIntegerField('最长停留时间', default=0)
|
||||
sort = models.PositiveSmallIntegerField('排序', default=1)
|
||||
|
|
|
@ -1,8 +1,28 @@
|
|||
from apps.opm.models import Operation, Opl
|
||||
from apps.opm.models import Operation, Opl, OplWorker
|
||||
from apps.opm.serializers import OplCloseSerializer
|
||||
from apps.wf.models import Ticket, Transition
|
||||
|
||||
|
||||
def get_op_manager(state, ticket, new_ticket_data, handler):
|
||||
"""_summary_
|
||||
|
||||
Args:
|
||||
state (_type_): 工作流节点实例
|
||||
ticket (_type_): 工单实例
|
||||
new_ticket_data (_type_): 提交的工单数据
|
||||
handler (_type_): 处理人实例
|
||||
"""
|
||||
opl = Opl.objects.filter(ticket=ticket).first()
|
||||
if opl:
|
||||
return [opl.charger.id]
|
||||
|
||||
|
||||
def get_op_workers(state, ticket, new_ticket_data, handler):
|
||||
opl = Opl.objects.filter(ticket=ticket).first()
|
||||
if opl:
|
||||
return list(OplWorker.objects.filter(opl=opl).values_list('worker__id', flat=True))
|
||||
|
||||
|
||||
def bind_opl(ticket: Ticket, transition: Transition, new_ticket_data: dict):
|
||||
opl = Opl.objects.get(id=new_ticket_data['opl'])
|
||||
ticket_data = ticket.ticket_data
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 3.2.12 on 2022-07-07 07:22
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wf', '0003_ticket_belong_dept'),
|
||||
('vm', '0002_visit_visitors'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='visit',
|
||||
name='ticket',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='wf.ticket', verbose_name='关联工单'),
|
||||
),
|
||||
]
|
|
@ -2,6 +2,7 @@ from django.db import models
|
|||
from apps.hrm.models import Employee
|
||||
from apps.utils.models import CommonAModel, CommonBModel, BaseModel
|
||||
from apps.system.models import User
|
||||
from apps.wf.models import Ticket
|
||||
|
||||
|
||||
# Create your models here.
|
||||
|
@ -42,6 +43,8 @@ class Visit(CommonBModel):
|
|||
count_people = models.PositiveSmallIntegerField('来访人数', null=True, blank=True)
|
||||
receptionist = models.ForeignKey(User, verbose_name='接待人', on_delete=models.CASCADE)
|
||||
visitors = models.ManyToManyField('vm.visitor', through='vm.vpeople', related_name='v_visitors')
|
||||
ticket = models.ForeignKey(Ticket, verbose_name='关联工单',
|
||||
on_delete=models.SET_NULL, null=True, blank=True)
|
||||
# create_by 创建人
|
||||
|
||||
|
||||
|
|
|
@ -5,6 +5,9 @@ from apps.vm.models import Visit, Visitor, Vpeople
|
|||
from apps.hrm.serializers import phone_check
|
||||
from rest_framework import serializers
|
||||
from rest_framework.exceptions import ParseError
|
||||
from django.db import transaction
|
||||
from apps.third.clients import dhClient
|
||||
from apps.third.tapis import dhapis
|
||||
|
||||
|
||||
class VisitCreateUpdateSerializer(CustomModelSerializer):
|
||||
|
@ -27,6 +30,12 @@ class VisitorCreateSerializer(CustomModelSerializer):
|
|||
model = Visitor
|
||||
fields = ['name', 'phone', 'photo', 'id_number']
|
||||
|
||||
def create(self, validated_data):
|
||||
with transaction.atomic():
|
||||
# 校验上传的证件照
|
||||
dhClient.request(**dhapis['person_img_upload'], file_path_rela=validated_data['photo'])
|
||||
super().create(validated_data)
|
||||
|
||||
|
||||
class VisitorSerializer(CustomModelSerializer):
|
||||
class Meta:
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
from apps.hrm.models import Employee
|
||||
from apps.vm.models import Visit, Vpeople
|
||||
|
||||
|
||||
def bind_visit(ticket, transition, new_ticket_data: dict):
|
||||
visit = Visit.objects.get(id=new_ticket_data['visit'])
|
||||
visit.ticket = ticket
|
||||
if visit.state == Visit.V_CREATE:
|
||||
visit.state = Visit.V_AUDIT
|
||||
visit.save()
|
||||
|
||||
|
||||
def get_receptionist(state, ticket, new_ticket_data, handler):
|
||||
visit = Visit.objects.filter(ticket=ticket).first()
|
||||
if visit:
|
||||
return [visit.receptionist.id]
|
||||
|
||||
|
||||
def visit_audit_end(ticket):
|
||||
visit = Visit.objects.get(ticket=ticket)
|
||||
if visit.state == Visit.V_AUDIT:
|
||||
visit.state = Visit.V_ENTER
|
||||
visit.save()
|
||||
# 更新企业访客人员库
|
||||
for i in Vpeople.objects.filter(visit=visit):
|
||||
visitor = i.visitor
|
||||
ep = Employee.objects.filter(id_number=visitor.id_number, type='visitor').first()
|
||||
if ep:
|
||||
pass
|
||||
else:
|
||||
ep = Employee()
|
||||
ep.name = visitor.name
|
||||
ep.phone = visitor.phone
|
||||
ep.photo = visitor.photo
|
||||
ep.id_number = visitor.id_number
|
||||
ep.save()
|
||||
visitor.employee = ep
|
||||
visitor.save()
|
|
@ -6,25 +6,3 @@ from apps.vm.models import Visit, Vpeople
|
|||
from celery import shared_task
|
||||
|
||||
|
||||
@shared_task(base=CustomTask)
|
||||
def visit_audit_end(ticket_id):
|
||||
visit = Visit.objects.get(ticket__id=ticket_id)
|
||||
if visit.state == Visit.V_AUDIT:
|
||||
visit.state = Visit.V_ENTER
|
||||
visit.save()
|
||||
# 更新企业访客人员库
|
||||
for i in Vpeople.objects.filter(visit=visit):
|
||||
visitor = i.visitor
|
||||
ep = Employee.objects.filter(id_number=visitor.id_number).first()
|
||||
if ep:
|
||||
pass
|
||||
else:
|
||||
ep = Employee()
|
||||
ep.name = visitor.name
|
||||
ep.phone = visitor.phone
|
||||
ep.photo = visitor.photo
|
||||
ep.id_number = visitor.id_number
|
||||
ep.type = 'visitor'
|
||||
ep.save()
|
||||
visitor.employee = ep
|
||||
visitor.save()
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 3.2.12 on 2022-07-07 07:11
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('system', '0002_user_post'),
|
||||
('wf', '0002_auto_20220707_0957'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='ticket',
|
||||
name='belong_dept',
|
||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ticket_belong_dept', to='system.dept', verbose_name='所属部门'),
|
||||
),
|
||||
]
|
|
@ -1,5 +1,5 @@
|
|||
from django.db import models
|
||||
from apps.utils.models import CommonAModel
|
||||
from apps.utils.models import CommonAModel, CommonBModel
|
||||
from apps.system.models import User
|
||||
from apps.utils.models import BaseModel
|
||||
|
||||
|
@ -223,7 +223,7 @@ class CustomField(CommonAModel):
|
|||
parent = models.ForeignKey('self', verbose_name='父字段', on_delete=models.SET_NULL, null=True, blank=True)
|
||||
|
||||
|
||||
class Ticket(CommonAModel):
|
||||
class Ticket(CommonBModel):
|
||||
"""
|
||||
工单
|
||||
"""
|
||||
|
|
|
@ -165,7 +165,7 @@ class WfService(object):
|
|||
module, func = destination_participant.rsplit(".", 1)
|
||||
m = importlib.import_module(module)
|
||||
f = getattr(m, func)
|
||||
destination_participant = f(state=state, ticket=ticket, new_ticket_data=new_ticket_data, hander=handler)
|
||||
destination_participant = f(state=state, ticket=ticket, new_ticket_data=new_ticket_data, handler=handler)
|
||||
# else:
|
||||
# destination_participant = getattr(GetParticipants, destination_participant)(
|
||||
# state=state, ticket=ticket, new_ticket_data=new_ticket_data, hander=handler)
|
||||
|
@ -181,10 +181,10 @@ class WfService(object):
|
|||
depts = get_parent_queryset(ticket.belong_dept)
|
||||
user_queryset = user_queryset.filter(dept__in=depts)
|
||||
elif state.filter_policy == 2:
|
||||
depts = get_parent_queryset(ticket.create_by.dept)
|
||||
depts = get_parent_queryset(ticket.create_by.belong_dept)
|
||||
user_queryset = user_queryset.filter(dept__in=depts)
|
||||
elif state.filter_policy == 3:
|
||||
depts = get_parent_queryset(handler.dept)
|
||||
depts = get_parent_queryset(handler.belong_dept)
|
||||
user_queryset = user_queryset.filter(dept__in=depts)
|
||||
destination_participant = list(user_queryset.values_list('id', flat=True))
|
||||
if type(destination_participant) == list:
|
||||
|
@ -214,7 +214,7 @@ class WfService(object):
|
|||
current_participant_count = 0
|
||||
participant_type = ticket.participant_type
|
||||
participant = ticket.participant
|
||||
state = ticket.stateF
|
||||
state = ticket.state
|
||||
if participant_type == State.PARTICIPANT_TYPE_PERSONAL:
|
||||
if user.id != participant:
|
||||
return dict(permission=False, msg="非当前处理人", need_accept=False)
|
||||
|
@ -365,6 +365,8 @@ class WfService(object):
|
|||
participant_type=0, intervene_type=Transition.TRANSITION_INTERVENE_TYPE_CC,
|
||||
participant=None, participant_cc=destination_state.participant_cc)
|
||||
|
||||
cls.task_ticket(ticket=ticket)
|
||||
|
||||
return ticket
|
||||
|
||||
@classmethod
|
||||
|
@ -372,22 +374,13 @@ class WfService(object):
|
|||
"""
|
||||
执行任务(自定义任务或通知)
|
||||
"""
|
||||
# 如果目标状态是脚本则异步执行
|
||||
state = ticket.state
|
||||
if state.participant_type == State.PARTICIPANT_TYPE_ROBOT:
|
||||
module, func = state.participant.rsplit(".", 1)
|
||||
m = importlib.import_module(module)
|
||||
f = getattr(m, func)
|
||||
ticket.script_run_last_result = False
|
||||
ticket.save()
|
||||
f.delay(ticket_id=ticket.id, script_str=state.participant) # 里面要加入回调才能继续流转
|
||||
|
||||
# 如果目标状态有func,由func执行额外操作(比如发送通知)
|
||||
if state.on_reach_func:
|
||||
module, func = state.func.rsplit(".", 1)
|
||||
module, func = state.on_reach_func.rsplit(".", 1)
|
||||
m = importlib.import_module(module)
|
||||
f = getattr(m, func)
|
||||
f.delay(ticket_id=ticket.id) # 不用加入回调
|
||||
f(ticket=ticket) # 同步执行
|
||||
else:
|
||||
# wf默认发送通知
|
||||
last_log = TicketFlow.objects.filter(ticket=ticket).order_by('-create_time').first()
|
||||
|
@ -395,5 +388,14 @@ class WfService(object):
|
|||
last_log.intervene_type == Transition.TRANSITION_INTERVENE_TYPE_DELIVER or
|
||||
ticket.in_add_node):
|
||||
# 如果状态变化或是转交加签的情况再发送通知
|
||||
from tasks import send_ticket_notice
|
||||
from apps.wf.tasks import send_ticket_notice
|
||||
send_ticket_notice.delay(ticket_id=ticket.id)
|
||||
|
||||
# 如果目标状态是脚本则异步执行
|
||||
if state.participant_type == State.PARTICIPANT_TYPE_ROBOT:
|
||||
module, func = state.participant.rsplit(".", 1)
|
||||
m = importlib.import_module(module)
|
||||
f = getattr(m, func)
|
||||
ticket.script_run_last_result = False
|
||||
ticket.save()
|
||||
f.delay(ticket_id=ticket.id, script_str=state.participant) # 里面要加入回调才能继续流转
|
||||
|
|
|
@ -7,9 +7,9 @@ from apps.wf.serializers import TicketDetailSerializer
|
|||
|
||||
|
||||
@shared_task(base=CustomTask)
|
||||
def send_ticket_notice(ticket):
|
||||
def send_ticket_notice(ticket_id):
|
||||
"""
|
||||
发送通知
|
||||
"""
|
||||
data = TicketDetailSerializer(instance=ticket).data
|
||||
pass
|
||||
|
|
@ -42,6 +42,9 @@ class WorkflowViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
|||
ordering_fields = ['create_time']
|
||||
ordering = ['-create_time']
|
||||
|
||||
def get_object(self):
|
||||
return super().get_object()
|
||||
|
||||
@action(methods=['get'], detail=True, perms_map={'get': 'workflow:update'},
|
||||
pagination_class=None, serializer_class=StateSerializer)
|
||||
def states(self, request, pk=None):
|
||||
|
@ -93,7 +96,6 @@ class WorkflowViewSet(CreateUpdateModelAMixin, ModelViewSet):
|
|||
ret['field_list'] = field_list
|
||||
return Response(ret)
|
||||
|
||||
|
||||
class StateViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
perms_map = {'get': '*', 'post': 'workflow:update',
|
||||
'put': 'workflow:update', 'delete': 'workflow:update'}
|
||||
|
@ -130,7 +132,7 @@ class CustomFieldViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin,
|
|||
|
||||
|
||||
class TicketViewSet(CreateUpdateCustomMixin, CreateModelMixin, ListModelMixin, RetrieveModelMixin, GenericViewSet):
|
||||
perms_map = {'get': '*', 'post': 'ticket:create'}
|
||||
perms_map = {'get': '*', 'post': '*'}
|
||||
queryset = Ticket.objects.all()
|
||||
serializer_class = TicketSerializer
|
||||
search_fields = ['title']
|
||||
|
@ -184,7 +186,7 @@ class TicketViewSet(CreateUpdateCustomMixin, CreateModelMixin, ListModelMixin, R
|
|||
create_by=request.user,
|
||||
create_time=timezone.now(),
|
||||
act_state=Ticket.TICKET_ACT_STATE_DRAFT,
|
||||
belong_dept=request.user.dept,
|
||||
belong_dept=request.user.belong_dept,
|
||||
ticket_data=save_ticket_data) # 先创建出来
|
||||
# 更新title和sn
|
||||
title = vdata.get('title', '')
|
||||
|
@ -198,7 +200,6 @@ class TicketViewSet(CreateUpdateCustomMixin, CreateModelMixin, ListModelMixin, R
|
|||
ticket.save()
|
||||
ticket = WfService.handle_ticket(ticket=ticket, transition=transition, new_ticket_data=ticket_data,
|
||||
handler=request.user, created=True)
|
||||
WfService.task_ticket(ticket)
|
||||
return Response(TicketSerializer(instance=ticket).data)
|
||||
|
||||
@action(methods=['get'], detail=False, perms_map={'get': '*'})
|
||||
|
@ -228,7 +229,6 @@ class TicketViewSet(CreateUpdateCustomMixin, CreateModelMixin, ListModelMixin, R
|
|||
ticket = WfService.handle_ticket(ticket=ticket, transition=vdata['transition'],
|
||||
new_ticket_data=new_ticket_data, handler=request.user,
|
||||
suggestion=vdata['suggestion'])
|
||||
WfService.task_ticket(ticket)
|
||||
return Response(TicketSerializer(instance=ticket).data)
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post': '*'})
|
||||
|
@ -252,7 +252,6 @@ class TicketViewSet(CreateUpdateCustomMixin, CreateModelMixin, ListModelMixin, R
|
|||
suggestion=vdata['suggestion'], participant_type=State.PARTICIPANT_TYPE_PERSONAL,
|
||||
intervene_type=Transition.TRANSITION_INTERVENE_TYPE_DELIVER,
|
||||
participant=request.user, transition=None)
|
||||
WfService.task_ticket(ticket)
|
||||
return Response()
|
||||
|
||||
@action(methods=['get'], detail=True, perms_map={'get': '*'})
|
||||
|
@ -350,7 +349,6 @@ class TicketViewSet(CreateUpdateCustomMixin, CreateModelMixin, ListModelMixin, R
|
|||
suggestion=suggestion, participant_type=State.PARTICIPANT_TYPE_PERSONAL,
|
||||
intervene_type=Transition.TRANSITION_INTERVENE_TYPE_ADD_NODE,
|
||||
participant=request.user, transition=None)
|
||||
WfService.task_ticket(ticket)
|
||||
return Response()
|
||||
|
||||
@action(methods=['post'], detail=True, perms_map={'post': '*'}, serializer_class=TicketAddNodeEndSerializer)
|
||||
|
|
Loading…
Reference in New Issue