+from logit import logit
12
+from TimeConvert import TimeConvert as tc
13
+
14
+from account.models import UserInfo
15
+from group.models import GroupInfo, GroupUserInfo
16
+from utils.error.errno_utils import GroupStatusCode, UserStatusCode
17
+from utils.error.response_utils import response
18
+from utils.redis.rgroup import get_group_info, get_group_users_info, set_group_info, set_group_users_info
19
+from utils.redis.rkeys import TOUR_GUIDE_GROUP_CUR_SESSION
20
+from utils.redis.rtourguide import set_tour_guide_own_group
21
+
22
+
23
+r = settings.REDIS_CACHE
24
+
25
+
26
+@logit
27
+def tg_group_create_api(request):
28
+    """
29
+    导游团创建
30
+    :param request:
31
+    :return:
32
+    """
33
+    user_id = request.POST.get('user_id', '')
34
+    group_name = request.POST.get('group_name', '')
35
+    group_default_avatar = int(request.POST.get('group_default_avatar', 0))
36
+    started_at = request.POST.get('started_at', '')
37
+    ended_at = request.POST.get('ended_at', '')
38
+
39
+    # 用户校验
40
+    try:
41
+        user = UserInfo.objects.get(user_id=user_id)
42
+    except UserInfo.DoesNotExist:
43
+        return response(UserStatusCode.USER_NOT_FOUND)
44
+
45
+    # 权限校验
46
+    if not user.istourguide:
47
+        return response(GroupStatusCode.NOT_GROUP_ADMIN)
48
+
49
+    # 导游团校验
50
+    if GroupInfo.objects.filter(
51
+        admin_id=user_id,
52
+        group_closed=False,
53
+        status=True,
54
+        ended_at__gt=tc.utc_datetime(),
55
+    ).exists():
56
+        return response(GroupStatusCode.COULD_HAVE_ONLY_ONE_ACTIVE_GROUP)
57
+
58
+    # 群组唯一标识
59
+    group_id = CurtailUUID.uuid(GroupInfo, 'group_id')
60
+
61
+    # 群组记录创建
62
+    group = GroupInfo.objects.create(
63
+        group_id=group_id,
64
+        admin_id=user_id,
65
+        group_name=group_name,
66
+        group_default_avatar=group_default_avatar,
67
+        group_from=GroupInfo.TOURGUIDE_GROUP,
68
+        started_at=started_at,
69
+        ended_at=ended_at,
70
+    )
71
+
72
+    # Redis 群组数据缓存
73
+    group_info = set_group_info(group)
74
+
75
+    # 群组用户记录创建
76
+    GroupUserInfo.objects.create(
77
+        group_id=group_id,
78
+        user_id=user_id,
79
+        nickname=user.final_nickname,
80
+        avatar=user.avatar,
81
+        admin=True,
82
+        user_status=GroupUserInfo.PASSED,
83
+        passed_at=tc.utc_datetime(),
84
+        subadmin=True,
85
+    )
86
+
87
+    # Redis 群组用户数据缓存
88
+    group_users = set_group_users_info(group)
89
+
90
+    # Redis 设置导游拥有的导游团
91
+    set_tour_guide_own_group(user_id, group_id)
92
+
93
+    return response(200, 'Create Tour Guide Group Success', u'导游团创建成功', {
94
+        'group_id': group_id,
95
+        'group': group_info,
96
+        'users': group_users,
97
+    })
98
+
99
+
100
+@logit
101
+def tg_group_detail_api(request):
102
+    """
103
+    导游团详情
104
+    :param request:
105
+    :return:
106
+    """
107
+    group_id = request.POST.get('group_id', '')
108
+    user_id = request.POST.get('user_id', '')
109
+
110
+    return response(200, 'Get Tour Guide Group Detail Info Success', u'获取导游团详情成功', {
111
+        'group_id': group_id,
112
+        'group': get_group_info(group_id),
113
+        'users': get_group_users_info(group_id, user_id),
114
+    })
115
+
116
+
117
+@logit
118
+def tg_group_update_api(request):
119
+    """
120
+    导游团更新
121
+    :param request:
122
+    :return:
123
+    """
124
+    group_id = request.POST.get('group_id', '')
125
+    admin_id = request.POST.get('admin_id', '') or request.POST.get('user_id', '')
126
+    group_name = request.POST.get('group_name', '')
127
+    group_desc = request.POST.get('group_desc', '')
128
+
129
+    group_avatar = request.FILES.get('group_avatar', '')
130
+
131
+    started_at = request.POST.get('started_at', '')
132
+    ended_at = request.POST.get('ended_at', '')
133
+
134
+    # 群组校验
135
+    try:
136
+        group = GroupInfo.objects.get(group_id=group_id)
137
+    except GroupInfo.DoesNotExist:
138
+        return response(GroupStatusCode.GROUP_NOT_FOUND)
139
+
140
+    # 权限校验
141
+    if group.admin_id != admin_id:
142
+        return response(GroupStatusCode.NO_UPDATE_PERMISSION)
143
+
144
+    # 群组名称更新
145
+    if group_name:
146
+        group.group_name = group_name
147
+    # 群组描述更新
148
+    if group_desc:
149
+        group.group_desc = group_desc
150
+    # 群组头像更新
151
+    if group_avatar:
152
+        _, extension = os.path.splitext(group_avatar.name)
153
+        group_avatar_path = 'group/{uuid}_{extension}'.format(uuid=shortuuid.uuid(), extension=extension)
154
+        if default_storage.exists(group_avatar_path):
155
+            default_storage.delete(group_avatar_path)
156
+        default_storage.save(group_avatar_path, group_avatar)
157
+        group.group_avatar = group_avatar_path
158
+    # 起止时间更新
159
+    group.started_at = started_at
160
+    group.ended_at = ended_at
161
+    group.save()
162
+
163
+    # Redis 群组数据缓存更新
164
+    group_info = set_group_info(group)
165
+
166
+    return response(200, 'Update Group Success', u'群组更新成功', {
167
+        'group_id': group_id,
168
+        'group': group_info,
169
+        'users': get_group_users_info(group_id, admin_id),
170
+    })
171
+
172
+
173
+@logit
174
+def tg_group_close_api(request):
175
+    """
176
+    导游团关闭
177
+    :param request:
178
+    :return:
179
+    """
180
+    group_id = request.POST.get('group_id', '')
181
+    admin_id = request.POST.get('admin_id', '') or request.POST.get('user_id', '')
182
+
183
+    # 群组校验
184
+    try:
185
+        group = GroupInfo.objects.get(group_id=group_id)
186
+    except GroupInfo.DoesNotExist:
187
+        return response(GroupStatusCode.GROUP_NOT_FOUND)
188
+
189
+    # 权限校验
190
+    if group.admin_id != admin_id:
191
+        return response(GroupStatusCode.NO_CLOSE_PERMISSION)
192
+
193
+    # 群组解锁
194
+    group.group_closed = True
195
+    group.closed_at = tc.utc_datetime()
196
+    group.save()
197
+
198
+    # Redis 群组数据缓存更新
199
+    set_group_info(group)
200
+
201
+    return response(200, u'Close Tour Guide Group Success', u'导游团关闭成功')
202
+
203
+
204
+@logit
205
+def tg_group_gather_start_api(request):
206
+    """
207
+    导游团设置集合时间和地点
208
+    :param request:
209
+    :return:
210
+    """
211
+    group_id = request.POST.get('group_id', '')
212
+    admin_id = request.POST.get('admin_id', '') or request.POST.get('user_id', '')
213
+    gather_at = request.POST.get('gather_at', '')
214
+    gather_lon = request.POST.get('lon', '')  # 经度
215
+    gather_lat = request.POST.get('lat', '')  # 纬度
216
+
217
+    # 群组校验
218
+    try:
219
+        group = GroupInfo.objects.get(group_id=group_id)
220
+    except GroupInfo.DoesNotExist:
221
+        return response(GroupStatusCode.GROUP_NOT_FOUND)
222
+
223
+    # 权限校验
224
+    if not GroupUserInfo.objects.filter(group_id=group_id, user_id=admin_id, subadmin=True, status=True).exists():
225
+        return response(GroupStatusCode.NO_UPDATE_PERMISSION)
226
+
227
+    # 集合信息设置
228
+    group.gather_at = gather_at
229
+    group.gather_lon = gather_lon
230
+    group.gather_lat = gather_lat
231
+    group.save()
232
+
233
+    # Redis 群组数据缓存更新
234
+    set_group_info(group)
235
+
236
+    # 更新Session
237
+    r.set(TOUR_GUIDE_GROUP_CUR_SESSION, shortuuid.uuid())
238
+
239
+    return response(200, u'Set Tour Guide Group Gather Info Success', u'设置导游团集合信息成功')

+ 184 - 0
group/tourguidegroupuser_views.py

@@ -0,0 +1,184 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from __future__ import division
4
+
5
+import json
6
+
7
+from django.conf import settings
8
+from logit import logit
9
+from TimeConvert import TimeConvert as tc
10
+
11
+from account.models import UserInfo
12
+from group.models import GroupInfo, GroupUserInfo
13
+from utils.error.errno_utils import GroupStatusCode, GroupUserStatusCode, UserStatusCode
14
+from utils.error.response_utils import response
15
+from utils.group_photo_utils import get_current_photos
16
+from utils.redis.rgroup import get_group_info, get_group_users_info, set_group_users_info
17
+from utils.redis.rkeys import (GROUP_LAST_PHOTO_PK, GROUP_USERS_DELETED_SET, GROUP_USERS_PASSED_SET,
18
+                               GROUP_USERS_QUIT_SET, GROUP_USERS_REFUSED_SET, TOUR_GUIDE_GROUP_CUR_SESSION,
19
+                               TOUR_GUIDE_GROUP_GEO_INFO, TOUR_GUIDE_GROUP_USER_GEO_LIST)
20
+from utils.redis.rtourguide import get_tour_guide_own_group
21
+
22
+
23
+r = settings.REDIS_CACHE
24
+
25
+
26
+@logit
27
+def tgu_group_user_join_api(request):
28
+    """
29
+    导游团用户加群
30
+    :param request:
31
+    :return:
32
+    """
33
+    admin_id = request.POST.get('admin_id', '')  # 导游唯一标识,识别二维码获取
34
+    user_id = request.POST.get('user_id', '')
35
+    nickname = request.POST.get('nickname', '')
36
+
37
+    # 获取导游团唯一标识
38
+    group_id = get_tour_guide_own_group(admin_id)
39
+
40
+    # 用户校验
41
+    try:
42
+        user = UserInfo.objects.get(user_id=user_id)
43
+    except UserInfo.DoesNotExist:
44
+        return response(UserStatusCode.USER_NOT_FOUND)
45
+
46
+    # 群组校验
47
+    try:
48
+        group = GroupInfo.objects.get(group_id=group_id)
49
+    except GroupInfo.DoesNotExist:
50
+        return response(GroupStatusCode.GROUP_NOT_FOUND)
51
+
52
+    # 群组锁定校验
53
+    if group.group_lock:
54
+        return response(GroupStatusCode.GROUP_HAS_LOCKED)
55
+
56
+    # 群组用户记录创建,若记录不存在,则创建,若记录已存在,则更新
57
+    group_user, created = GroupUserInfo.objects.get_or_create(
58
+        group_id=group_id,
59
+        user_id=user_id,
60
+    )
61
+    if group_user.user_status != GroupUserInfo.PASSED:
62
+        group_user.current_id = -1 if group.group_from == GroupInfo.SESSION_GROUP else int(
63
+            r.get(GROUP_LAST_PHOTO_PK % group_id) or -1)
64
+        group_user.nickname = nickname or user.final_nickname
65
+        group_user.avatar = user.avatar
66
+        # group_user.admin = False  # Admin Field Default False, Should Not Assign
67
+        group_user.user_status = GroupUserInfo.PASSED
68
+        group_user.passed_at = tc.utc_datetime()
69
+        group_user.save()
70
+
71
+    # Redis 群组用户数据缓存
72
+    set_group_users_info(group)
73
+
74
+    # Redis 群组通过集合缓存
75
+    r.srem(GROUP_USERS_REFUSED_SET % group_id, user_id)
76
+    r.srem(GROUP_USERS_DELETED_SET % group_id, user_id)
77
+    r.srem(GROUP_USERS_QUIT_SET % group_id, user_id)
78
+    r.sadd(GROUP_USERS_PASSED_SET % group_id, user_id)
79
+
80
+    curinfo = get_current_photos(group_id, user_id, group_user.current_id)
81
+
82
+    return response(200, 'Apply Success', u'申请成功', {
83
+        'current_id': curinfo.get('current_id', ''),
84
+        'photos': curinfo.get('photos', ''),
85
+        'group_id': group_id,
86
+        'group': get_group_info(group_id),
87
+        'user_id': user_id,
88
+        'users': get_group_users_info(group_id, user_id),
89
+    })
90
+
91
+
92
+@logit
93
+def tgu_group_user_update_api(request):
94
+    """
95
+    导游团用户更新
96
+    :param request:
97
+    :return:
98
+    """
99
+    group_id = request.POST.get('group_id', '')
100
+    admin_id = request.POST.get('admin_id', '')  # 导游唯一标识
101
+    user_id = request.POST.get('user_id', '')
102
+
103
+    name = request.POST.get('name', '')
104
+    phone = request.POST.get('phone', '')
105
+    relative_person = request.POST.get('relative_person', '')
106
+    remark = request.POST.get('remark', '')
107
+
108
+    # 群组校验
109
+    try:
110
+        group = GroupInfo.objects.get(group_id=group_id)
111
+    except GroupInfo.DoesNotExist:
112
+        return response(GroupStatusCode.GROUP_NOT_FOUND)
113
+
114
+    # 权限校验
115
+    if not GroupUserInfo.objects.filter(group_id=group_id, user_id=admin_id, subadmin=True, status=True).exists():
116
+        return response(GroupStatusCode.NO_UPDATE_PERMISSION)
117
+
118
+    try:
119
+        group_user = GroupUserInfo.objects.get(group_id=group_id, user_id=user_id, status=True)
120
+    except GroupUserInfo.DoesNotExist:
121
+        return response(GroupUserStatusCode.GROUP_USER_NOT_FOUND)
122
+
123
+    # 用户信息更新
124
+    # TODO: Whether sync name and phone to UserInfo or not?
125
+    group_user.name = name
126
+    group_user.phone = phone
127
+    group_user.relative_person = relative_person
128
+    group_user.remark = remark
129
+    group_user.save()
130
+
131
+    # Redis 群组用户数据缓存
132
+    group_users = set_group_users_info(group)
133
+
134
+    return response(200, 'Update Group Success', u'群组更新成功', {
135
+        'group_id': group_id,
136
+        'group': group.data,
137
+        'users': group_users,
138
+    })
139
+
140
+
141
+@logit
142
+def tgu_group_user_locations_api(request):
143
+    """
144
+    导游团所有用户位置信息
145
+    :param request:
146
+    :return:
147
+    """
148
+    group_id = request.POST.get('group_id', '')
149
+    admin_id = request.POST.get('admin_id', '')  # 导游唯一标识
150
+
151
+    # 权限校验
152
+    if not GroupUserInfo.objects.filter(group_id=group_id, user_id=admin_id, subadmin=True, status=True).exists():
153
+        return response(GroupStatusCode.NO_LOCATION_PERMISSION)
154
+
155
+    return response(200, 'Get Tour Guide Group All User Location Success', u'获取导游团用户地理位置信息成功', {
156
+        'group_id': group_id,
157
+        'locations': r.georadius(TOUR_GUIDE_GROUP_GEO_INFO % group_id, 0, 0, '+inf', unit='m', withdist=True, withcoord=True, sort='ASC')
158
+        # 'locations': [['x', 0.33, (2.68220901489e-06, 1.26736058093e-06)]]
159
+    })
160
+
161
+
162
+@logit
163
+def tgu_group_user_location_api(request):
164
+    """
165
+    导游团单个用户位置信息
166
+    :param request:
167
+    :return:
168
+    """
169
+    group_id = request.POST.get('group_id', '')
170
+    admin_id = request.POST.get('admin_id', '')  # 导游唯一标识
171
+    user_id = request.POST.get('user_id', '')
172
+
173
+    # 权限校验
174
+    if not GroupUserInfo.objects.filter(group_id=group_id, user_id=admin_id, subadmin=True, status=True).exists():
175
+        return response(GroupStatusCode.NO_LOCATION_PERMISSION)
176
+
177
+    session_id = r.get(TOUR_GUIDE_GROUP_CUR_SESSION % group_id)
178
+    locations = r.lrange(TOUR_GUIDE_GROUP_USER_GEO_LIST % (group_id, session_id, user_id), 0, -1)
179
+
180
+    return response(200, 'Get Tour Guide Group User Location Success', u'获取导游团用户地理位置信息成功', {
181
+        'group_id': group_id,
182
+        'user_id': user_id,
183
+        'locations': [json.loads(loc) for loc in locations]
184
+    })

+ 1 - 0
pai2/settings.py

@@ -46,6 +46,7 @@ INSTALLED_APPS = (
46 46
     'django_q',
47 47
     'api',
48 48
     'account',
49
+    'geo',
49 50
     'group',
50 51
     'message',
51 52
     'operation',

+ 19 - 11
utils/error/errno_utils.py

@@ -54,26 +54,34 @@ class PhotoStatusCode(BaseStatusCode):
54 54
 
55 55
 
56 56
 class GroupStatusCode(BaseStatusCode):
57
-    """ 群组相关错误码 4020xx """
57
+    """ 群组/团相关错误码 4020xx """
58 58
     GROUP_NOT_FOUND = StatusCodeField(402001, u'Group Not Found', description=u'群组不存在')
59 59
     GROUP_HAS_LOCKED = StatusCodeField(402002, u'Group Has Locked', description=u'群组已锁定')
60 60
     NOT_GROUP_ADMIN = StatusCodeField(402003, u'Not Group Admin', description=u'非群组管理员')
61
-    NO_UPDATE_PERMISSION = StatusCodeField(402004, u'No Update Permission', description=u'没有更新权限')
62
-    NO_LOCK_PERMISSION = StatusCodeField(402005, u'No Lock Permission', description=u'没有锁定权限')
63
-    NO_UNLOCK_PERMISSION = StatusCodeField(402006, u'No Unlock Permission', description=u'没有解锁权限')
64
-    NO_REMOVE_PERMISSION = StatusCodeField(402007, u'No Remove Permission', description=u'没有移除权限')
65
-    NO_QUIT_PERMISSION = StatusCodeField(402008, u'No Quit Permission', description=u'没有退出权限')
66
-    NO_PASS_PERMISSION = StatusCodeField(402009, u'No Pass Permission', description=u'没有通过权限')
67
-    NO_REFUSE_PERMISSION = StatusCodeField(402010, u'No Refuse Permission', description=u'没有拒绝权限')
68
-    DUPLICATE_JOIN_REQUEST = StatusCodeField(402011, u'Duplicate Join Request', description=u'重复加群申请')
69
-    JOIN_REQUEST_NOT_FOUND = StatusCodeField(402012, u'Join Request Not Found', description=u'加群申请不存在')
61
+
62
+    NO_UPDATE_PERMISSION = StatusCodeField(402010, u'No Update Permission', description=u'没有更新权限')
63
+    NO_LOCK_PERMISSION = StatusCodeField(402011, u'No Lock Permission', description=u'没有锁定权限')
64
+    NO_UNLOCK_PERMISSION = StatusCodeField(402012, u'No Unlock Permission', description=u'没有解锁权限')
65
+    NO_REMOVE_PERMISSION = StatusCodeField(402013, u'No Remove Permission', description=u'没有移除权限')
66
+    NO_QUIT_PERMISSION = StatusCodeField(402014, u'No Quit Permission', description=u'没有退出权限')
67
+    NO_PASS_PERMISSION = StatusCodeField(402015, u'No Pass Permission', description=u'没有通过权限')
68
+    NO_REFUSE_PERMISSION = StatusCodeField(402016, u'No Refuse Permission', description=u'没有拒绝权限')
69
+    NO_CLOSE_PERMISSION = StatusCodeField(402017, u'No Close Permission', description=u'没有关闭权限')
70
+    NO_LOCATION_PERMISSION = StatusCodeField(402018, u'No Location Permission', description=u'没有地理位置权限')
71
+
72
+    DUPLICATE_JOIN_REQUEST = StatusCodeField(402020, u'Duplicate Join Request', description=u'重复加群申请')
73
+    JOIN_REQUEST_NOT_FOUND = StatusCodeField(402021, u'Join Request Not Found', description=u'加群申请不存在')
74
+
75
+    COULD_HAVE_ONLY_ONE_ACTIVE_GROUP = StatusCodeField(402030, u'Could Have Only One Active Group', description=u'只能创建一个活跃团')
70 76
 
71 77
 
72 78
 class GroupUserStatusCode(BaseStatusCode):
73
-    """ 群组用户相关错误码 4021xx """
79
+    """ 群组/团用户相关错误码 4021xx """
74 80
     GROUP_USER_NOT_FOUND = StatusCodeField(402101, u'Group User Not Found', description=u'群组用户不存在')
75 81
     GROUP_USER_HAS_DELETED = StatusCodeField(402102, u'Group User Has Deleted', description=u'群组用户被移除')
76 82
 
83
+    USER_HAS_NOT_JOIN_GROUP = StatusCodeField(402131, u'User Has Not Join Group', description=u'用户未加入导游团')
84
+
77 85
 
78 86
 class GroupPhotoStatusCode(BaseStatusCode):
79 87
     """ 群组照片(飞图)相关错误码 4022xx """

+ 8 - 0
utils/redis/rkeys.py

@@ -6,6 +6,14 @@ UUID_LIST = 'uuid:list'  # List, 唯一标识列表
6 6
 # 用户相关
7 7
 PROFILE_INFO = 'profile:info:%s'  # STRING,用户信息,user_id
8 8
 
9
+# 导游相关
10
+TOUR_GUIDE_GROUP_GEO_INFO = 'tour:guide:group:geo:info:%s'  # ZSET,旅游团地理位置信息,group_id
11
+TOUR_GUIDE_GROUP_CUR_SESSION = 'tour:guide:group:cur:session:%s'  # STRING,旅游团当前Session,group_id,导游设置集合时间的时候更新
12
+TOUR_GUIDE_GROUP_USER_GEO_LIST = 'tour:guide:group:user:geo:list:%s:%s:%s'  # LIST,旅游团当前用户地理位置列表,group_id、session_id、user_id
13
+
14
+TOUR_GUIDE_GROUP_USER_OWN = 'tour:guide:group:user:own:%s'  # STRING,导游当前拥有的导游团,user_id,导游创建导游团的时候更新
15
+TOUR_GUIDE_GROUP_USER_BELONG = 'tour:guide:group:user:belong:%s'  # STRING,用户当前所属导游团,user_id,用户加入导游团的时候更新
16
+
9 17
 # 群组相关
10 18
 GROUP_INFO = 'group:info:%s'  # STRING,群组信息,group_id
11 19
 

+ 21 - 0
utils/redis/rtourguide.py

@@ -0,0 +1,21 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.conf import settings
4
+
5
+from utils.redis.rkeys import TOUR_GUIDE_GROUP_USER_OWN
6
+
7
+
8
+r = settings.REDIS_CACHE
9
+
10
+
11
+# 导游相关
12
+
13
+
14
+def set_tour_guide_own_group(user_id, group_id):
15
+    """ 设置导游拥有的导游团 """
16
+    r.set(TOUR_GUIDE_GROUP_USER_OWN % user_id, group_id)
17
+
18
+
19
+def get_tour_guide_own_group(user_id):
20
+    """ 获取导游拥有的导游团 """
21
+    return r.get(TOUR_GUIDE_GROUP_USER_OWN % user_id)

thermometer - Gogs: Go Git Service

Keine Beschreibung

huangqimin001: a6bdd3725f :tada: Initial vor 4 Jahren
..
data a6bdd3725f :tada: Initial vor 4 Jahren