@@ -78,6 +78,8 @@ urlpatterns += [  | 
            ||
| 78 | 78 | 
                url(r'^tg/close$', tourguidegroup_views.tg_group_close_api, name='tg_group_close_api'), # 旅行团关闭  | 
            
| 79 | 79 | 
                url(r'^tg/gather/start$', tourguidegroup_views.tg_group_gather_start_api, name='tg_group_gather_start_api'), # 旅行团设置集合时间和地点  | 
            
| 80 | 80 | 
                # url(r'^tg/gather/end$', tourguidegroup_views.tg_group_gather_end_api, name='tg_group_gather_end_api'), # 旅行团集合结束,清理数据  | 
            
| 81 | 
                + url(r'^tg/token$', tourguidegroup_views.tg_group_token_api, name='tg_group_token_api'), # 旅行团权限管理票据  | 
            |
| 82 | 
                + url(r'^tg/transfer$', tourguidegroup_views.tg_group_transfer_api, name='tg_group_transfer_api'), # 旅行团权限管理转移  | 
            |
| 81 | 83 | 
                ]  | 
            
| 82 | 84 | 
                 | 
            
| 83 | 85 | 
                # 旅行团用户相关  | 
            
                @@ -74,6 +74,7 @@ class GroupInfo(CreateUpdateMixin):  | 
            ||
| 74 | 74 | 
                'phone': self.phone,  | 
            
| 75 | 75 | 
                'started_at': tc.remove_microsecond(self.started_at),  | 
            
| 76 | 76 | 
                'ended_at': tc.remove_microsecond(self.ended_at),  | 
            
| 77 | 
                + 'total_persons': self.total_persons,  | 
            |
| 77 | 78 | 
                'gather_at': tc.remove_microsecond(self.gather_at),  | 
            
| 78 | 79 | 
                'gather_lon': self.gather_lon,  | 
            
| 79 | 80 | 
                'gather_lat': self.gather_lat,  | 
            
                @@ -15,7 +15,7 @@ from TimeConvert import TimeConvert as tc  | 
            ||
| 15 | 15 | 
                 | 
            
| 16 | 16 | 
                from account.models import UserInfo  | 
            
| 17 | 17 | 
                from group.models import GroupInfo, GroupUserInfo  | 
            
| 18 | 
                -from utils.error.errno_utils import GroupStatusCode, UserStatusCode  | 
            |
| 18 | 
                +from utils.error.errno_utils import GroupStatusCode, TokenStatusCode, UserStatusCode  | 
            |
| 19 | 19 | 
                from utils.error.response_utils import response  | 
            
| 20 | 20 | 
                from utils.redis.rgroup import get_group_info, get_group_users_info, set_group_info, set_group_users_info  | 
            
| 21 | 21 | 
                from utils.redis.rkeys import TOUR_GUIDE_GROUP_CUR_GATHER_INFO, TOUR_GUIDE_GROUP_CUR_SESSION  | 
            
                @@ -211,7 +211,7 @@ def tg_group_close_api(request):  | 
            ||
| 211 | 211 | 
                # Redis 群组数据缓存更新  | 
            
| 212 | 212 | 
                set_group_info(group)  | 
            
| 213 | 213 | 
                 | 
            
| 214 | 
                - return response(200, u'Close Tour Guide Group Success', u'旅行团关闭成功')  | 
            |
| 214 | 
                + return response(200, 'Close Tour Guide Group Success', u'旅行团关闭成功')  | 
            |
| 215 | 215 | 
                 | 
            
| 216 | 216 | 
                 | 
            
| 217 | 217 | 
                @logit  | 
            
                @@ -253,4 +253,87 @@ def tg_group_gather_start_api(request):  | 
            ||
| 253 | 253 | 
                'gather_lat': gather_lat,  | 
            
| 254 | 254 | 
                }, cls=DjangoJSONEncoder)).execute()  | 
            
| 255 | 255 | 
                 | 
            
| 256 | 
                - return response(200, u'Set Tour Guide Group Gather Info Success', u'设置旅行团集合信息成功')  | 
            |
| 256 | 
                + return response(200, 'Set Tour Guide Group Gather Info Success', u'设置旅行团集合信息成功')  | 
            |
| 257 | 
                +  | 
            |
| 258 | 
                +  | 
            |
| 259 | 
                +@logit  | 
            |
| 260 | 
                +def tg_group_token_api(request):  | 
            |
| 261 | 
                + """  | 
            |
| 262 | 
                + 旅行团权限管理票据  | 
            |
| 263 | 
                + :param request:  | 
            |
| 264 | 
                + :return:  | 
            |
| 265 | 
                + """  | 
            |
| 266 | 
                +    group_id = request.POST.get('group_id', '')
               | 
            |
| 267 | 
                +    admin_id = request.POST.get('admin_id', '') or request.POST.get('user_id', '')
               | 
            |
| 268 | 
                +  | 
            |
| 269 | 
                +    return response(200, 'Generate Token Success', u'生成票据成功', {
               | 
            |
| 270 | 
                + 'token': r.token(group_id + admin_id, ex_time=180)  | 
            |
| 271 | 
                + })  | 
            |
| 272 | 
                +  | 
            |
| 273 | 
                +  | 
            |
| 274 | 
                +@logit  | 
            |
| 275 | 
                +def tg_group_transfer_api(request):  | 
            |
| 276 | 
                + """  | 
            |
| 277 | 
                + 旅行团权限管理转移  | 
            |
| 278 | 
                + :param request:  | 
            |
| 279 | 
                + :return:  | 
            |
| 280 | 
                + """  | 
            |
| 281 | 
                +    group_id = request.POST.get('group_id', '')
               | 
            |
| 282 | 
                +    admin_id = request.POST.get('admin_id', '')  # 导游唯一标识,识别二维码获取
               | 
            |
| 283 | 
                +    user_id = request.POST.get('user_id', '')
               | 
            |
| 284 | 
                +    token = request.POST.get('token', '')
               | 
            |
| 285 | 
                +  | 
            |
| 286 | 
                + # 票据校验  | 
            |
| 287 | 
                + if not r.token_exists(group_id + admin_id, token):  | 
            |
| 288 | 
                + return response(TokenStatusCode.TOKEN_NOT_FOUND)  | 
            |
| 289 | 
                +  | 
            |
| 290 | 
                + # 用户校验  | 
            |
| 291 | 
                + try:  | 
            |
| 292 | 
                + user = UserInfo.objects.get(user_id=user_id)  | 
            |
| 293 | 
                + except UserInfo.DoesNotExist:  | 
            |
| 294 | 
                + return response(UserStatusCode.USER_NOT_FOUND)  | 
            |
| 295 | 
                +  | 
            |
| 296 | 
                + # 群组校验  | 
            |
| 297 | 
                + try:  | 
            |
| 298 | 
                + group = GroupInfo.objects.get(group_id=group_id)  | 
            |
| 299 | 
                + except GroupInfo.DoesNotExist:  | 
            |
| 300 | 
                + return response(GroupStatusCode.GROUP_NOT_FOUND)  | 
            |
| 301 | 
                +  | 
            |
| 302 | 
                + # 权限校验  | 
            |
| 303 | 
                + if not GroupUserInfo.objects.filter(group_id=group_id, user_id=admin_id, admin=True, status=True).exists():  | 
            |
| 304 | 
                + return response(GroupStatusCode.NO_TRANSFER_PERMISSION)  | 
            |
| 305 | 
                +  | 
            |
| 306 | 
                + # 群组用户记录创建,若记录不存在,则创建,若记录已存在,则更新  | 
            |
| 307 | 
                + group_user, created = GroupUserInfo.objects.get_or_create(  | 
            |
| 308 | 
                + group_id=group_id,  | 
            |
| 309 | 
                + user_id=user_id,  | 
            |
| 310 | 
                +        defaults={
               | 
            |
| 311 | 
                + 'nickname': user.final_nickname,  | 
            |
| 312 | 
                + 'avatar': user.avatar,  | 
            |
| 313 | 
                + 'user_status': GroupUserInfo.PASSED,  | 
            |
| 314 | 
                + 'passed_at': tc.utc_datetime(),  | 
            |
| 315 | 
                + 'subadmin': True,  | 
            |
| 316 | 
                + 'name': user.name,  | 
            |
| 317 | 
                + 'phone': user.phone,  | 
            |
| 318 | 
                + }  | 
            |
| 319 | 
                + )  | 
            |
| 320 | 
                +  | 
            |
| 321 | 
                + if not created:  | 
            |
| 322 | 
                + group_user.current_id = -1  | 
            |
| 323 | 
                + group_user.nickname = user.final_nickname  | 
            |
| 324 | 
                + group_user.avatar = user.avatar  | 
            |
| 325 | 
                + group_user.user_status = GroupUserInfo.PASSED  | 
            |
| 326 | 
                + group_user.passed_at = tc.utc_datetime()  | 
            |
| 327 | 
                + group_user.subadmin = True  | 
            |
| 328 | 
                + group_user.name = user.name  | 
            |
| 329 | 
                + group_user.phone = user.phone  | 
            |
| 330 | 
                + group_user.save()  | 
            |
| 331 | 
                +  | 
            |
| 332 | 
                + # Redis 群组用户数据缓存  | 
            |
| 333 | 
                + group_users = set_group_users_info(group)  | 
            |
| 334 | 
                +  | 
            |
| 335 | 
                +    return response(200, 'Create Tour Guide Group Success', u'旅行团创建成功', {
               | 
            |
| 336 | 
                + 'group_id': group_id,  | 
            |
| 337 | 
                + 'group': group.data,  | 
            |
| 338 | 
                + 'users': group_users,  | 
            |
| 339 | 
                + })  | 
            
                @@ -78,8 +78,7 @@ def tgu_group_user_join_api(request):  | 
            ||
| 78 | 78 | 
                group_user.save()  | 
            
| 79 | 79 | 
                 | 
            
| 80 | 80 | 
                if group_user.user_status != GroupUserInfo.PASSED:  | 
            
| 81 | 
                - group_user.current_id = -1 if group.group_from == GroupInfo.SESSION_GROUP else int(  | 
            |
| 82 | 
                - r.get(GROUP_LAST_PHOTO_PK % group_id) or -1)  | 
            |
| 81 | 
                + group_user.current_id = int(r.get(GROUP_LAST_PHOTO_PK % group_id) or -1)  | 
            |
| 83 | 82 | 
                group_user.nickname = nickname or user.final_nickname  | 
            
| 84 | 83 | 
                group_user.avatar = user.avatar  | 
            
| 85 | 84 | 
                # group_user.admin = False # Admin Field Default False, Should Not Assign  | 
            
                @@ -26,7 +26,7 @@ mock==2.0.0  | 
            ||
| 26 | 26 | 
                pep8==1.7.0  | 
            
| 27 | 27 | 
                pywe-oauth==1.0.1  | 
            
| 28 | 28 | 
                records==0.4.3  | 
            
| 29 | 
                -redis-extensions==1.0.29  | 
            |
| 29 | 
                +redis-extensions==1.0.31  | 
            |
| 30 | 30 | 
                requests==2.12.1  | 
            
| 31 | 31 | 
                rlog==0.2  | 
            
| 32 | 32 | 
                shortuuid==0.4.3  | 
            
                @@ -67,7 +67,8 @@ class GroupStatusCode(BaseStatusCode):  | 
            ||
| 67 | 67 | 
                NO_PASS_PERMISSION = StatusCodeField(402015, u'No Pass Permission', description=u'没有通过权限')  | 
            
| 68 | 68 | 
                NO_REFUSE_PERMISSION = StatusCodeField(402016, u'No Refuse Permission', description=u'没有拒绝权限')  | 
            
| 69 | 69 | 
                NO_CLOSE_PERMISSION = StatusCodeField(402017, u'No Close Permission', description=u'没有关闭权限')  | 
            
| 70 | 
                - NO_LOCATION_PERMISSION = StatusCodeField(402018, u'No Location Permission', description=u'没有地理位置权限')  | 
            |
| 70 | 
                + NO_TRANSFER_PERMISSION = StatusCodeField(402018, u'No Transfer Permission', description=u'没有转移权限')  | 
            |
| 71 | 
                + NO_LOCATION_PERMISSION = StatusCodeField(402019, u'No Location Permission', description=u'没有地理位置权限')  | 
            |
| 71 | 72 | 
                 | 
            
| 72 | 73 | 
                DUPLICATE_JOIN_REQUEST = StatusCodeField(402020, u'Duplicate Join Request', description=u'重复加群申请')  | 
            
| 73 | 74 | 
                JOIN_REQUEST_NOT_FOUND = StatusCodeField(402021, u'Join Request Not Found', description=u'加群申请不存在')  | 
            
                @@ -115,3 +116,8 @@ class WithdrawStatusCode(BaseStatusCode):  | 
            ||
| 115 | 116 | 
                class MessageStatusCode(BaseStatusCode):  | 
            
| 116 | 117 | 
                """ 消息相关错误码 4090xx """  | 
            
| 117 | 118 | 
                MESSAGE_NOT_FOUND = StatusCodeField(409001, u'Message Not Found', description=u'消息不存在')  | 
            
| 119 | 
                +  | 
            |
| 120 | 
                +  | 
            |
| 121 | 
                +class TokenStatusCode(BaseStatusCode):  | 
            |
| 122 | 
                + """ 票据相关错误码 4090xx """  | 
            |
| 123 | 
                + TOKEN_NOT_FOUND = StatusCodeField(409901, u'Token Not Found', description=u'票据不存在')  |