访客注册,相关方入厂审核后账号创建

This commit is contained in:
曹前明 2022-07-28 19:02:19 +08:00
parent d8b2ac28a3
commit d93d7bbd17
22 changed files with 169 additions and 82 deletions

11
apps/auth1/services.py Normal file
View File

@ -0,0 +1,11 @@
from django.core.cache import cache
from rest_framework.exceptions import ParseError
def check_phone_code(phone, code, raise_exception=True):
code_exist = cache.get(phone, None)
if code_exist == code:
return True
if raise_exception:
raise ParseError('验证码错误')
return False

View File

@ -13,6 +13,7 @@ import json
from django.conf import settings
from rest_framework_simplejwt.tokens import RefreshToken
from django.core.cache import cache
from apps.auth1.services import check_phone_code
from apps.utils.sms import send_sms
from apps.utils.tools import rannum
from apps.utils.wxmp import wxmpClient
@ -181,11 +182,9 @@ class CodeLogin(CreateAPIView):
def post(self, request):
phone = request.data['phone']
code = request.data['code']
code_exist = cache.get(phone, None)
if code_exist == code:
user = User.objects.filter(phone=phone).first()
if user:
ret = get_tokens_for_user(user)
return Response(ret)
raise ParseError('账户不存在或已禁用')
raise ParseError('验证码错误')
check_phone_code(phone, code)
user = User.objects.filter(phone=phone).first()
if user:
ret = get_tokens_for_user(user)
return Response(ret)
raise ParseError('账户不存在或已禁用')

View File

@ -56,11 +56,3 @@ def backup_media():
completed = subprocess.run(command, shell=True, capture_output=True, text=True)
return completed
@shared_task(base=CustomTask)
def get_wx_token():
r = requests.get('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}'.format(
settings.WX_APPID, settings.WX_APPSECRET)).text
token = json.loads(r)['access_token']
cache.set('wx_token', token)
return token

View File

@ -5,7 +5,7 @@ from rest_framework.response import Response
from rest_framework.serializers import Serializer
from rest_framework.decorators import action
from apps.develop.serializers import GenerateVoiceSerializer, SendSmsSerializer, TestTaskSerializer
from apps.develop.tasks import backup_database, backup_media, get_wx_token, reload_web_git, reload_server_git, reload_server_only
from apps.develop.tasks import backup_database, backup_media, reload_web_git, reload_server_git, reload_server_only
from rest_framework.exceptions import APIException, ParseError
from apps.system.models import User
from apps.system.tasks import show
@ -15,6 +15,7 @@ from django.core.cache import cache
import requests
from apps.utils.viewsets import CustomGenericViewSet
from apps.utils.wx import wxClient
# Create your views here.
@ -153,11 +154,8 @@ class TestViewSet(CustomGenericViewSet):
微信模板消息发送测试
"""
wx_token = cache.get('wx_token', None)
if not wx_token:
wx_token = get_wx_token()
data = {
"touser": 'ocAnm5vab6QGOnf2dqpuUZGJ0xyw',
"touser": "ocAnm5vab6QGOnf2dqpuUZGJ0xyw",
"template_id": "wczl-hB_bs8CpxwO8_KZuogSTPFXqhBxf8C5HjKl2M4",
"url": "http://weixin.qq.com/download",
# "miniprogram":{
@ -172,5 +170,5 @@ class TestViewSet(CustomGenericViewSet):
},
}
}
requests.post(url='https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='+wx_token, json=data)
return Response({'wx_token': wx_token, 'wx_openid': 'ocAnm5vab6QGOnf2dqpuUZGJ0xyw'})
res = wxClient.send_tem_msg(data=data)
return Response(res)

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2022-07-28 10:58
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('hrm', '0004_alter_employee_phone'),
]
operations = [
migrations.AlterField(
model_name='employee',
name='phone',
field=models.CharField(blank=True, max_length=11, null=True, unique=True, verbose_name='手机号'),
),
]

View File

@ -24,7 +24,7 @@ class Employee(CommonBModel):
verbose_name='系统账号',
on_delete=models.PROTECT, null=True, blank=True)
name = models.CharField('姓名', max_length=20)
phone = models.CharField('手机号', max_length=11, null=True, blank=True)
phone = models.CharField('手机号', max_length=11, null=True, blank=True, unique=True)
email = models.EmailField('邮箱号', null=True, blank=True)
number = models.CharField('人员编号', max_length=50, null=True, blank=True)
photo = models.CharField('证件照', max_length=1000, null=True, blank=True)

View File

@ -26,13 +26,13 @@ class EmployeeSimpleSerializer(CustomModelSerializer):
fields = ['id', 'type', 'name', 'belong_dept', 'belong_dept_name', 'post', 'post_name', 'photo', 'third_info']
class EmployeeBaseSerializer(CustomModelSerializer):
def save(self, **kwargs):
if self.validated_data.get('user', None):
user = self.validated_data['user']
self.validated_data['name'] = user.name
self.validated_data['belong_dept'] = user.belong_dept
return super().save(**kwargs)
# class EmployeeBaseSerializer(CustomModelSerializer):
# def save(self, **kwargs):
# if self.validated_data.get('user', None):
# user = self.validated_data['user']
# self.validated_data['name'] = user.name
# self.validated_data['belong_dept'] = user.belong_dept
# return super().save(**kwargs)
def phone_check(phone):
@ -42,21 +42,15 @@ def phone_check(phone):
return phone
class EmployeeImproveSerializer(CustomModelSerializer):
class Meta:
model = Employee
fields = ['phone', 'email']
class EmployeeCreateUpdateSerializer(EmployeeBaseSerializer):
phone = serializers.CharField(label="手机号")
class EmployeeCreateUpdateSerializer(CustomModelSerializer):
class Meta:
model = Employee
exclude = EXCLUDE_FIELDS + ['is_atwork', 'last_check_time',
'not_work_remark', 'third_info', 'type']
'not_work_remark',
'third_info',
'type', 'name', 'phone', 'belong_dept', 'post', 'user']
extra_kwargs = {
'phone': {'required': True},
'number': {'required': True},
'photo': {'required': True},
'id_number': {'required': True},
@ -77,13 +71,20 @@ class EmployeeCreateUpdateSerializer(EmployeeBaseSerializer):
return instance
class EmployeeImproveSerializer(CustomModelSerializer):
class Meta:
model = Employee
fields = ['photo', 'id_number', 'email', 'gender', 'signature']
class ChannelAuthoritySerializer(serializers.Serializer):
pks = serializers.ListField(child=serializers.CharField(max_length=20), label="员工ID列表")
channels = serializers.ListField(child=serializers.CharField(max_length=20), label="门通道ID列表")
class EmployeeSerializer(EmployeeBaseSerializer):
class EmployeeSerializer(CustomModelSerializer):
belong_dept_ = DeptSimpleSerializer(source='belong_dept', read_only=True)
user_ = UserSimpleSerializer(source='user', read_only=True)
belong_dept_name = serializers.CharField(source='belong_dept.name', read_only=True)
post_name = serializers.CharField(source='post.name', read_only=True)
blt_ = serializers.SerializerMethodField()

View File

@ -19,4 +19,7 @@ def updateEmployee(sender, instance, created, **kwargs):
if not ep_created:
ep.belong_dept = instance.belong_dept
ep.post = instance.post
if instance.phone != ep.phone:
ep.phone = instance.phone
ep.save()
ep.save()

View File

@ -19,6 +19,7 @@ from apps.hrm.serializers import (CertificateCreateUpdateSerializer, Certificate
EmployeeNotWorkRemarkSerializer,
EmployeeSerializer,
NotWorkRemarkListSerializer)
from apps.hrm.services import HrmService
from apps.third.clients import dhClient
from apps.third.tapis import dhapis
@ -79,9 +80,6 @@ class EmployeeViewSet(CustomModelViewSet):
serializer = EmployeeImproveSerializer(instance=ep, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
if ep.phone:
user.phone = ep.phone
user.save()
return Response()
@action(methods=['post'], detail=True, perms_map={'post': 'employee.notworkremark'},

View File

@ -57,7 +57,9 @@ class RpartySimpleSerializer(CustomModelSerializer):
class RpartyAssignSerializer(serializers.Serializer):
username = serializers.CharField(label='用户名')
name = serializers.CharField(label="姓名")
phone = serializers.CharField(label="手机号")
username = serializers.CharField(label="账号")
class RfileListSerializer(CustomModelSerializer):

View File

@ -1,9 +1,12 @@
from threading import Thread
from apps.hrm.errors import PHONE_EXIST
from apps.hrm.models import Certificate, Employee
from apps.hrm.services import HrmService
from apps.system.models import User, UserPost
from apps.wf.models import Ticket, Transition
from apps.rpm.models import Rcertificate, Rfile, Rpj, Rpjcertificate, Rpjfile, Rpjmember
from rest_framework.exceptions import ParseError
from django.contrib.auth.hashers import make_password
def bind_rpj(ticket: Ticket, transition: Transition, new_ticket_data: dict):
rpj = Rpj.objects.get(id=new_ticket_data['rpj'])
@ -20,6 +23,7 @@ def bind_rpj(ticket: Ticket, transition: Transition, new_ticket_data: dict):
def rpj_audit_end(ticket):
rpj = Rpj.objects.get(ticket=ticket)
rpj_dept = rpj.rparty.dept
# 更新入厂项目人员库
for i in Rpjmember.objects.filter(rpj=rpj):
rep = i.remployee
@ -35,6 +39,27 @@ def rpj_audit_end(ticket):
ep.type = 'remployee'
ep.belong_dept = rpj.rparty.dept
ep.save()
# 给相关方人员创建账户
user = ep.user
if user: # 如果该人员有账户
pass
else:
user_e = User()
user_e.name = rep.name
user_e.phone = rep.phone
user_e.type = 'remployee'
user_e.password = make_password('0000')
user_e.save()
ep.user = user_e
ep.save()
# 账号划给部门
UserPost.objects.get_or_create(user=ep.user, dept=rpj_dept,
defaults={
'user': ep.user,
'dept': rpj_dept
})
# 回写
rep.employee = ep
rep.rpj = rpj # 更新当前入厂项目
rep.save()
@ -56,7 +81,7 @@ def rpj_audit_end(ticket):
ct.file = i.file
ct.employee = i.rpj_member.remployee.employee
ct.save()
# 更新相关方资料库
# 更新相关方资料库后续可从资料库里选择
for i in Rpjfile.objects.filter(rpj=rpj):
rf = Rfile.objects.filter(file_cate=i.file_cate, rparty=i.rpj.rparty).first()
if rf:

View File

@ -4,6 +4,7 @@ from apps.hrm.serializers import CertificateCreateUpdateSerializer, CertificateS
from apps.rpm.models import Rcertificate, Remployee, Rparty, Rfile, Rpjfile, Rpjmember, Rpj
from apps.rpm.serializers import RcertificateCreateUpdateSerializer, RcertificateSerializer, RemployeeCreateSerializer, RemployeeSerializer, RpartyAssignSerializer, RpartyCreateUpdateSerializer, RfileListSerializer, RpartySerializer, RpjListSerializer, RpjfileSerializer, RpjfileUpdateSerializer, RpjmemberCreateSerializer, RpjmemberCreatesSerializer, RpjCreateUpdateSerializer, RpjmemberSerializer, RpjmemberUpdateSerializer
from apps.system.models import Dictionary, Post, User, UserPost
from apps.system.serializers import UserCreateSerializer
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, DestroyModelMixin, UpdateModelMixin
from apps.utils.mixins import CustomDestoryModelMixin
@ -32,13 +33,10 @@ class RpartyViewSet(CustomModelViewSet):
obj = self.get_object()
if obj.admin:
raise ParseError('已存在管理员账号')
username = request.data.get('username')
password = make_password('0000')
user = User.objects.create(username=username,
password=password,
type='remployee',
belong_dept=obj.dept)
obj.admin = user
serializer = UserCreateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
ins = serializer.save(type='remployee')
obj.admin = ins
obj.save()
return Response()

View File

@ -0,0 +1,19 @@
# Generated by Django 3.2.12 on 2022-07-28 10:58
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('system', '0004_auto_20220724_1305'),
]
operations = [
migrations.AlterField(
model_name='userpost',
name='post',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='up_post', to='system.post'),
),
]

View File

@ -157,7 +157,7 @@ class UserPost(BaseModel):
"""
name = models.CharField('名称', max_length=20, null=True, blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='up_user')
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='up_post')
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='up_post', null=True, blank=True)
dept = models.ForeignKey(Dept, on_delete=models.CASCADE, related_name='up_dept')
sort = models.PositiveSmallIntegerField('排序', default=1)

View File

@ -2,6 +2,7 @@
from django_celery_beat.models import PeriodicTask, CrontabSchedule, IntervalSchedule
from rest_framework import serializers
from django_celery_results.models import TaskResult
from apps.hrm.errors import PHONE_EXIST
from apps.system.errors import USERNAME_EXIST
from apps.utils.serializers import CustomModelSerializer
from apps.utils.constants import EXCLUDE_FIELDS, EXCLUDE_FIELDS_BASE
@ -297,7 +298,7 @@ class UserListSerializer(CustomModelSerializer):
用户列表序列化
"""
belong_dept_ = DeptSimpleSerializer(source='belong_dept', read_only=True)
posts_ = PostSimpleSerializer(source='posts', many=True)
# posts_ = PostSimpleSerializer(source='posts', many=True)
class Meta:
model = User
@ -309,9 +310,10 @@ class UserListSerializer(CustomModelSerializer):
# raise serializers.ValidationError(**PHONE_F_WRONG)
# return phone
# def phone_exist(phone):
# if User.objects.filter(phone=phone).exists():
# raise serializers.ValidationError(**PHONE_EXIST)
def phone_exist(phone):
if User.objects.filter(phone=phone).exists():
raise serializers.ValidationError(**PHONE_EXIST)
def user_exist(username):
@ -340,6 +342,7 @@ class UserCreateSerializer(CustomModelSerializer):
创建用户序列化
"""
username = serializers.CharField(required=True, validators=[user_exist])
phone = serializers.CharField(required=False, validators=[phone_exist])
class Meta:
model = User

View File

@ -403,7 +403,7 @@ class UserViewSet(CustomModelViewSet):
filterset_class = UserFilterSet
search_fields = ['username', 'name', 'phone', 'email']
select_related_fields = ['superior', 'belong_dept']
prefetch_related_fields = ['posts']
prefetch_related_fields = ['posts', 'roles', 'depts']
def filter_queryset(self, queryset):
if not self.detail:

View File

@ -1,7 +1,7 @@
from rest_framework import serializers
from apps.am.models import Area
from apps.hrm.serializers import EmployeeBaseSerializer, EmployeeSimpleSerializer
from apps.hrm.serializers import EmployeeSimpleSerializer
from apps.third.models import BltBind, TDevice, Tlog
from apps.utils.serializers import CustomModelSerializer
from django.db import transaction

View File

@ -17,7 +17,7 @@ def get_user_perms_map(user):
if user.is_superuser:
user_perms_map = {'superuser': None}
else:
objs = UserPost.objects.filter(user=user)
objs = UserPost.objects.filter(user=user).exclude(post=None)
for i in objs:
dept_id = str(i.dept.id)
for pr in PostRole.objects.filter(post=i.post):

View File

@ -1,7 +1,9 @@
from django.core.cache import cache
import json
import time
from threading import Thread
import uuid
from async_timeout import timeout
import requests
from django.conf import settings
@ -13,7 +15,6 @@ from apps.utils.tools import print_roundtrip
from django.utils.timezone import now
import traceback
requests.packages.urllib3.disable_warnings()
# 实例化myLogger
myLogger = logging.getLogger('log')
@ -29,7 +30,7 @@ class WxClient:
self.app_id = app_id
self.app_secret = app_secret
self.isRuning = True
self.token = None
self.token = cache.get(self.app_id + '_token', None) # 普通token
self.t = None # 线程
self.log = {}
self.setup()
@ -43,7 +44,8 @@ class WxClient:
}
_, ret = self.request(url='/cgi-bin/token', params=parmas, method='get')
self.token = ret['access_token']
time.sleep(3600)
cache.set(self.app_id + '_token', self.token, timeout=3600)
time.sleep(4000)
def setup(self):
t = Thread(target=self._get_token_loop, args=(), daemon=True)
@ -127,5 +129,13 @@ class WxClient:
_, res = self.request('/sns/oauth2/access_token', params=params, method='get')
return res
def send_tem_msg(self, data: dict):
"""发送模板消息
"""
_, res = self.request('/cgi-bin/message/template/send',
params={'access_token': self.token}, json=data, method='post')
return res
wxClient = WxClient()

View File

@ -81,7 +81,8 @@ class VpeopleSerializer(CustomModelSerializer):
class VisitorRegisterSerializer(serializers.Serializer):
name = serializers.CharField(label="姓名")
username = serializers.CharField(label="账户名", required=False)
phone = serializers.CharField(label="手机号")
code = serializers.CharField(label='手机号验证码')
wxmp_openid = serializers.CharField(label='微信小程序ID', required=False)
wx_openid = serializers.CharField(label='微信公众号ID', required=False)

View File

@ -27,6 +27,8 @@ def visit_audit_end(ticket):
visitor = i.visitor
if visitor.id_number and visitor.photo:
ep = Employee.objects.filter(id_number=visitor.id_number).first()
elif visitor.phone:
ep = Employee.objects.filter(phone=visitor.phone).first()
else:
ep = Employee.objects.filter(name=visitor.name, id_number=None).first()
if ep:

View File

@ -1,6 +1,9 @@
from django.shortcuts import render
from apps.auth1.services import check_phone_code
from apps.auth1.views import get_tokens_for_user
from apps.hrm.models import Employee
from apps.system.models import User
from apps.utils.tools import ranstr
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet, GenericViewSet
from apps.vm.models import Visit, Visitor, Vpeople
from apps.vm.serializers import VisitCreateUpdateSerializer, VisitDetailSerializer, VisitSerializer, VisitorCreateSerializer, VisitorRegisterSerializer, VisitorSerializer, VpeopleCreateSerializer, VpeopleSerializer
@ -67,6 +70,7 @@ class VisitorViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Custo
@action(methods=['post'], detail=False,
authentication_classes=[], permission_classes=[],
serializer_class=VisitorRegisterSerializer)
@transaction.atomic
def register(self, request, *args, **kwargs):
"""访客账户注册
@ -75,21 +79,24 @@ class VisitorViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, Custo
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
if vdata.get('username', None): # 如果是用户名注册
user = User.objects.get_queryset(all=True).filter(username=vdata['username']).first()
if user:
raise ParseError('账号已存在或禁用不可注册')
else:
password = make_password('0000')
user = User.objects.create(name=vdata['name'],
username=vdata['username'],
type='visitor',
password=password)
return Response({'user': user.id}, status=201)
elif vdata.get('wxmp_openid', None): # 如果是微信小程序注册
pass
elif vdata.get('wx_openid', None): # 如果是微信公众号注册
pass
name = vdata['name']
phone = vdata['phone']
code = vdata['code']
check_phone_code(phone, code)
# 查询是否已注册
user = User.objects.filter(phone=phone).first()
if user:
raise ParseError('该手机号已注册,请直接登录')
user = User()
user.type = 'visitor'
user.name = name
user.username = 'V_' + ranstr(10)
user.phone = phone
user.password = make_password('0000')
user.wx_openid = vdata.get('wx_openid', None)
user.wxmp_openid = vdata.get('wxmp_openid', None)
user.save()
return Response(get_tokens_for_user(user))
class VpeopleViewSet(ListModelMixin, RetrieveModelMixin, CreateModelMixin, DestroyModelMixin, CustomGenericViewSet):