>
|
|
15
|
+from utils.version_utils import is_version_match
|
|
14
|
16
|
|
|
15
|
17
|
|
|
16
|
18
|
@logit
|
|
|
|
@@ -67,6 +69,33 @@ def online_api(request):
|
|
67
|
69
|
|
|
68
|
70
|
|
|
69
|
71
|
@logit
|
|
|
72
|
+def guest_api(request):
|
|
|
73
|
+ """ 游客状态 """
|
|
|
74
|
+ src = int(request.POST.get('src', 0))
|
|
|
75
|
+
|
|
|
76
|
+ gen = get_guest_entrance_control(src)
|
|
|
77
|
+
|
|
|
78
|
+ # 是否配置游客入口控制信息
|
|
|
79
|
+ if not gen:
|
|
|
80
|
+ return response(UserStatusCode.GUEST_NOT_ALLOWED)
|
|
|
81
|
+
|
|
|
82
|
+ # 平台校验
|
|
|
83
|
+ platform = gen.get('platform', '')
|
|
|
84
|
+ if request.Android:
|
|
|
85
|
+ if platform not in [GuestEntranceControlInfo.ADR, GuestEntranceControlInfo.BOTH]:
|
|
|
86
|
+ return response(UserStatusCode.GUEST_NOT_ALLOWED)
|
|
|
87
|
+ else:
|
|
|
88
|
+ if platform not in [GuestEntranceControlInfo.IOS, GuestEntranceControlInfo.BOTH]:
|
|
|
89
|
+ return response(UserStatusCode.GUEST_NOT_ALLOWED)
|
|
|
90
|
+
|
|
|
91
|
+ # 版本校验
|
|
|
92
|
+ if not is_version_match(request, gen):
|
|
|
93
|
+ return response(UserStatusCode.GUEST_NOT_ALLOWED)
|
|
|
94
|
+
|
|
|
95
|
+ return response(200, 'Guest Login Allowed', u'游客登录开启')
|
|
|
96
|
+
|
|
|
97
|
+
|
|
|
98
|
+@logit
|
|
70
|
99
|
def splash_api(request):
|
|
71
|
100
|
""" 启动页面 """
|
|
72
|
101
|
src = int(request.POST.get('src', 0))
|
|
|
|
@@ -86,7 +115,7 @@ def feedback_api(request):
|
|
86
|
115
|
feedback = request.POST.get('feedback', '')
|
|
87
|
116
|
src = int(request.POST.get('src', 0))
|
|
88
|
117
|
|
|
89
|
|
- if not UserInfo.objects.filter(user_id=user_id).exists():
|
|
|
118
|
+ if not UserInfo.objects.filter(user_id=user_id, status=True).exists():
|
|
90
|
119
|
return response(UserStatusCode.USER_NOT_FOUND)
|
|
91
|
120
|
|
|
92
|
121
|
FeedbackInfo.objects.create(
|
|
|
|
@@ -110,6 +139,7 @@ def download_api(request):
|
|
110
|
139
|
elif src == LatestAppInfo.PAIAI_TOURGUIDE:
|
|
111
|
140
|
wx_url = settings.PAI2_TOURGUIDE_DOWNLOAD_WX_URL
|
|
112
|
141
|
return redirect(wx_url)
|
|
|
142
|
+
|
|
113
|
143
|
if request.iOS:
|
|
114
|
144
|
if src == LatestAppInfo.PAIAI_USER:
|
|
115
|
145
|
ios_url = settings.PAI2_USER_DOWNLOAD_IOS_URL
|
|
|
|
@@ -118,4 +148,5 @@ def download_api(request):
|
|
118
|
148
|
elif src == LatestAppInfo.PAIAI_TOURGUIDE:
|
|
119
|
149
|
ios_url = settings.PAI2_TOURGUIDE_DOWNLOAD_IOS_URL
|
|
120
|
150
|
return redirect(ios_url)
|
|
|
151
|
+
|
|
121
|
152
|
return redirect(get_latest_app(src).get('latest_adr_url', ''))
|
|
|
|
@@ -56,3 +56,20 @@ class VersionMixin(models.Model):
|
|
56
|
56
|
|
|
57
|
57
|
class Meta:
|
|
58
|
58
|
abstract = True
|
|
|
59
|
+
|
|
|
60
|
+
|
|
|
61
|
+class PaiaiSrcMixin(models.Model):
|
|
|
62
|
+ PAIAI_USER = 0
|
|
|
63
|
+ PAIAI_LENSMAN = 1
|
|
|
64
|
+ PAIAI_TOURGUIDE = 2
|
|
|
65
|
+
|
|
|
66
|
+ SRC = (
|
|
|
67
|
+ (PAIAI_USER, u'拍爱用户端'),
|
|
|
68
|
+ (PAIAI_LENSMAN, u'拍爱摄影师端'),
|
|
|
69
|
+ (PAIAI_TOURGUIDE, u'拍爱导游端'),
|
|
|
70
|
+ )
|
|
|
71
|
+
|
|
|
72
|
+ src = models.IntegerField(_(u'src'), choices=SRC, default=PAIAI_USER, help_text=u'来源', db_index=True)
|
|
|
73
|
+
|
|
|
74
|
+ class Meta:
|
|
|
75
|
+ abstract = True
|
|
|
|
@@ -292,7 +292,7 @@ PAI2_TOURGUIDE_DOWNLOAD_IOS_URL = 'https://pai.ai'
|
|
292
|
292
|
GROUP_PER_PAGE = 20 # 群组每页数量
|
|
293
|
293
|
|
|
294
|
294
|
# 游客设置
|
|
295
|
|
-GUEST_USER_ID = 'guest'
|
|
|
295
|
+PAI2_TOURGUIDE_GUEST_UNIONID = 'oCGajv3Slxef2RuM4Sr-S2jTZwD4'
|
|
296
|
296
|
|
|
297
|
297
|
# 版本设置
|
|
298
|
298
|
MIN_VERSION = '0.0.0'
|
|
|
|
@@ -37,7 +37,7 @@ def wx_order_create_api(request):
|
|
37
|
37
|
|
|
38
|
38
|
# 群组照片校验
|
|
39
|
39
|
try:
|
|
40
|
|
- group_photo = GroupPhotoInfo.objects.get(pk=photo_id)
|
|
|
40
|
+ group_photo = GroupPhotoInfo.objects.get(pk=photo_id, status=True)
|
|
41
|
41
|
except GroupPhotoInfo.DoesNotExist:
|
|
42
|
42
|
return response(GroupPhotoStatusCode.GROUP_PHOTO_NOT_FOUND)
|
|
43
|
43
|
|
|
|
|
@@ -238,7 +238,7 @@ def wx_order_detail_api(request):
|
|
238
|
238
|
order_id = request.POST.get('order_id', '')
|
|
239
|
239
|
|
|
240
|
240
|
try:
|
|
241
|
|
- order = OrderInfo.objects.get(order_id=order_id)
|
|
|
241
|
+ order = OrderInfo.objects.get(order_id=order_id, status=True)
|
|
242
|
242
|
except OrderInfo.DoesNotExist:
|
|
243
|
243
|
return response(OrderStatusCode.WX_ORDER_NOT_FOUND)
|
|
244
|
244
|
|
|
|
|
@@ -152,7 +152,7 @@ def session_join_api(request):
|
|
152
|
152
|
r.sadd(GROUP_USERS_PASSED_SET % group_id, user_id)
|
|
153
|
153
|
|
|
154
|
154
|
# 获取 Session 照片
|
|
155
|
|
- photos = PhotosInfo.objects.filter(session_id=session_id)
|
|
|
155
|
+ photos = PhotosInfo.objects.filter(session_id=session_id, status=True)
|
|
156
|
156
|
|
|
157
|
157
|
#
|
|
158
|
158
|
if group_created:
|
|
|
|
@@ -205,7 +205,7 @@ def session_join_api(request):
|
|
205
|
205
|
|
|
206
|
206
|
@logit
|
|
207
|
207
|
def session_detail(request, session_id):
|
|
208
|
|
- photos = PhotosInfo.objects.filter(session_id=session_id)
|
|
|
208
|
+ photos = PhotosInfo.objects.filter(session_id=session_id, status=True)
|
|
209
|
209
|
return render(request, 'photo/session_detail.html', {'photos': photos})
|
|
210
|
210
|
|
|
211
|
211
|
|
|
|
|
@@ -1,17 +1,14 @@
|
|
1
|
1
|
# -*- coding: utf-8 -*-
|
|
2
|
2
|
|
|
3
|
|
-from operation.models import LatestAppInfo
|
|
4
|
3
|
from utils.redis.connect import r
|
|
5
|
4
|
from utils.redis.rkeys import LATEST_APP_INFO
|
|
6
|
5
|
|
|
7
|
6
|
|
|
8
|
|
-# 最新 APP 相关
|
|
9
|
|
-
|
|
10
|
|
-
|
|
11
|
7
|
def set_latest_app(src=0):
|
|
12
|
8
|
""" 设置最新 APP 信息 """
|
|
|
9
|
+ from operation.models import LatestAppInfo
|
|
13
|
10
|
try:
|
|
14
|
|
- appinfo = LatestAppInfo.objects.filter(src=src)[0].data
|
|
|
11
|
+ appinfo = LatestAppInfo.objects.filter(src=src, status=True)[0].data
|
|
15
|
12
|
except IndexError:
|
|
16
|
13
|
appinfo = {}
|
|
17
|
14
|
r.setjson(LATEST_APP_INFO % src, appinfo)
|
|
|
|
@@ -7,9 +7,6 @@ from utils.redis.connect import r
|
|
7
|
7
|
from utils.redis.rkeys import TODAY_INCOME, TOTAL_INCOME, WEEK_INCOME, WEEK_SOLD
|
|
8
|
8
|
|
|
9
|
9
|
|
|
10
|
|
-# 简报相关
|
|
11
|
|
-
|
|
12
|
|
-
|
|
13
|
10
|
def set_brief_info(uid, ptype, fee, dt=None):
|
|
14
|
11
|
""" 更新简报信息 """
|
|
15
|
12
|
ymd, week = (tc.local_string(tc.to_local_datetime(dt), format='%Y%m%d'), Week.withdate(dt)) if dt else (tc.local_string(format='%Y%m%d'), Week.thisweek().isoformat())
|
|
|
|
@@ -43,10 +43,10 @@ def retrieve_group_user_status():
|
|
43
|
43
|
def retrieve_group_photo_watchers():
|
|
44
|
44
|
group_photos = GroupPhotoInfo.objects.filter(status=True)
|
|
45
|
45
|
for group_photo in group_photos:
|
|
46
|
|
- photo_comments = PhotoCommentInfo.objects.filter(photo_id=group_photo.pk)
|
|
|
46
|
+ photo_comments = PhotoCommentInfo.objects.filter(photo_id=group_photo.pk, status=True)
|
|
47
|
47
|
for photo_comment in photo_comments:
|
|
48
|
48
|
r.sadd(GROUP_PHOTO_WATCHER_SET % group_photo.pk, photo_comment.user_id)
|
|
49
|
|
- photo_thumbups = PhotoThumbUpInfo.objects.filter(photo_id=group_photo.pk)
|
|
|
49
|
+ photo_thumbups = PhotoThumbUpInfo.objects.filter(photo_id=group_photo.pk, status=True)
|
|
50
|
50
|
for photo_thumbup in photo_thumbups:
|
|
51
|
51
|
r.sadd(GROUP_PHOTO_WATCHER_SET % group_photo.pk, photo_thumbup.user_id)
|
|
52
|
52
|
|
|
|
|
@@ -8,14 +8,10 @@ from utils.redis.rkeys import (GROUP_INFO, GROUP_PHOTO_COMMENT_LIST, GROUP_PHOTO
|
|
8
|
8
|
GROUP_USERS_KV_INFO)
|
|
9
|
9
|
|
|
10
|
10
|
|
|
11
|
|
-# 群组信息相关
|
|
12
|
|
-
|
|
13
|
|
-
|
|
14
|
11
|
def set_group_info(group):
|
|
15
|
12
|
""" 设置群组信息 """
|
|
16
|
|
- group_data = group.data
|
|
17
|
|
- r.setexjson(GROUP_INFO % group.group_id, r.REDIS_EXPIRED_ONE_MONTH, group_data, cls=DjangoJSONEncoder)
|
|
18
|
|
- return group_data
|
|
|
13
|
+ r.setexjson(GROUP_INFO % group.group_id, r.REDIS_EXPIRED_ONE_MONTH, group.data, cls=DjangoJSONEncoder)
|
|
|
14
|
+ return group.data
|
|
19
|
15
|
|
|
20
|
16
|
|
|
21
|
17
|
def set_group_info_by_id(group_id):
|
|
|
|
@@ -107,19 +103,19 @@ def get_group_photo_thumbup_flag(photo_id, user_id):
|
|
107
|
103
|
""" 获取群组照片用户点赞标识信息 """
|
|
108
|
104
|
if r.exists(GROUP_PHOTO_THUMB_UP % (photo_id, user_id)):
|
|
109
|
105
|
return True
|
|
110
|
|
- else:
|
|
111
|
|
- from group.models import PhotoThumbUpInfo
|
|
112
|
|
- if PhotoThumbUpInfo.objects.filter(photo_id=photo_id, user_id=user_id, thumbup=True).exists():
|
|
113
|
|
- set_group_photo_thumbup_flag(photo_id, user_id)
|
|
114
|
|
- return True
|
|
115
|
|
- else:
|
|
116
|
|
- return False
|
|
|
106
|
+
|
|
|
107
|
+ from group.models import PhotoThumbUpInfo
|
|
|
108
|
+ if PhotoThumbUpInfo.objects.filter(photo_id=photo_id, user_id=user_id, thumbup=True, status=True).exists():
|
|
|
109
|
+ set_group_photo_thumbup_flag(photo_id, user_id)
|
|
|
110
|
+ return True
|
|
|
111
|
+
|
|
|
112
|
+ return False
|
|
117
|
113
|
|
|
118
|
114
|
|
|
119
|
115
|
def set_group_photo_comment_list(photo_id):
|
|
120
|
116
|
""" 设置群组照片用户评论列表 """
|
|
121
|
117
|
from group.models import PhotoCommentInfo
|
|
122
|
|
- photo_comments = PhotoCommentInfo.objects.filter(photo_id=photo_id)
|
|
|
118
|
+ photo_comments = PhotoCommentInfo.objects.filter(photo_id=photo_id, status=True)
|
|
123
|
119
|
photo_comments = [comment.comment_info for comment in photo_comments]
|
|
124
|
120
|
r.setjson(GROUP_PHOTO_COMMENT_LIST % photo_id, photo_comments, cls=DjangoJSONEncoder)
|
|
125
|
121
|
return photo_comments
|
|
|
|
@@ -133,7 +129,7 @@ def get_group_photo_comment_list(photo_id):
|
|
133
|
129
|
def set_group_photo_thumbup_list(photo_id):
|
|
134
|
130
|
""" 设置群组照片用户点赞列表 """
|
|
135
|
131
|
from group.models import PhotoThumbUpInfo
|
|
136
|
|
- photo_thumbups = PhotoThumbUpInfo.objects.filter(photo_id=photo_id, thumbup=True)
|
|
|
132
|
+ photo_thumbups = PhotoThumbUpInfo.objects.filter(photo_id=photo_id, thumbup=True, status=True)
|
|
137
|
133
|
photo_thumbups = [thumbup.thumbup_info for thumbup in photo_thumbups]
|
|
138
|
134
|
r.setjson(GROUP_PHOTO_THUMB_UP_LIST % photo_id, photo_thumbups, cls=DjangoJSONEncoder)
|
|
139
|
135
|
return photo_thumbups
|
|
|
|
@@ -4,20 +4,17 @@ from utils.redis.connect import r
|
|
4
|
4
|
from utils.redis.rkeys import GUEST_ENTRANCE_CONTROL_INFO
|
|
5
|
5
|
|
|
6
|
6
|
|
|
7
|
|
-# 游客入口控制相关
|
|
8
|
|
-
|
|
9
|
|
-
|
|
10
|
7
|
def set_guest_entrance_control(gen):
|
|
11
|
8
|
""" 设置游客入口控制 """
|
|
12
|
|
- r.setjson(GUEST_ENTRANCE_CONTROL_INFO, gen.data)
|
|
|
9
|
+ r.setjson(GUEST_ENTRANCE_CONTROL_INFO % gen.src, gen.data)
|
|
13
|
10
|
return gen.data
|
|
14
|
11
|
|
|
15
|
12
|
|
|
16
|
|
-def get_guest_entrance_control():
|
|
|
13
|
+def get_guest_entrance_control(src=0):
|
|
17
|
14
|
""" 获取游客入口控制 """
|
|
18
|
|
- return r.getjson(GUEST_ENTRANCE_CONTROL_INFO)
|
|
|
15
|
+ return r.getjson(GUEST_ENTRANCE_CONTROL_INFO % src)
|
|
19
|
16
|
|
|
20
|
17
|
|
|
21
|
|
-def delete_guest_entrance_control():
|
|
|
18
|
+def delete_guest_entrance_control(src=0):
|
|
22
|
19
|
""" 删除游客入口控制 """
|
|
23
|
|
- return r.delete(GUEST_ENTRANCE_CONTROL_INFO)
|
|
|
20
|
+ return r.delete(GUEST_ENTRANCE_CONTROL_INFO % src)
|
|
|
|
@@ -1,7 +1,7 @@
|
|
1
|
1
|
# -*- coding: utf-8 -*-
|
|
2
|
2
|
|
|
3
|
3
|
# 唯一标识相关
|
|
4
|
|
-UUID_LIST = 'uuid:list' # List, 唯一标识列表
|
|
|
4
|
+UUID_LIST = 'uuid:list' # List,唯一标识列表
|
|
5
|
5
|
|
|
6
|
6
|
# 用户相关
|
|
7
|
7
|
PROFILE_INFO = 'profile:info:%s' # STRING,用户信息,user_id
|
|
|
|
@@ -59,7 +59,7 @@ SYSTEM_MESSAGE_READ_INFO = 'system:message:read:info:%s' # STRING,系统消
|
|
59
|
59
|
SYSTEM_MESSAGE_DELETED_INFO = 'system:message:deleted:info:%s' # STRING,系统消息删除信息,user_id
|
|
60
|
60
|
|
|
61
|
61
|
# 游客入口相关
|
|
62
|
|
-GUEST_ENTRANCE_CONTROL_INFO = 'guest:entrance:control:info' # STRING,游客入口控制信息
|
|
|
62
|
+GUEST_ENTRANCE_CONTROL_INFO = 'guest:entrance:control:info:%s' # STRING,游客入口控制信息,src
|
|
63
|
63
|
|
|
64
|
64
|
# APP 相关
|
|
65
|
65
|
LATEST_APP_INFO = 'latest:app:info:%s' # STRING,最新 APP 信息,src
|
|
|
|
@@ -1,15 +1,12 @@
|
|
1
|
1
|
# -*- coding: utf-8 -*-
|
|
2
|
2
|
|
|
3
|
|
-from message.models import SystemMessageDeleteInfo, SystemMessageReadInfo
|
|
4
|
3
|
from utils.redis.connect import r
|
|
5
|
4
|
from utils.redis.rkeys import SYSTEM_MESSAGE_DELETED_INFO, SYSTEM_MESSAGE_READ_INFO
|
|
6
|
5
|
|
|
7
|
6
|
|
|
8
|
|
-# 系统消息相关
|
|
9
|
|
-
|
|
10
|
|
-
|
|
11
|
7
|
def set_system_message_read_info(user_id):
|
|
12
|
8
|
""" 设置系统消息读取信息 """
|
|
|
9
|
+ from message.models import SystemMessageReadInfo
|
|
13
|
10
|
read_messages = SystemMessageReadInfo.objects.filter(user_id=user_id, status=True)
|
|
14
|
11
|
read_message_ids = [msg.msg_id for msg in read_messages]
|
|
15
|
12
|
r.setexjson(SYSTEM_MESSAGE_READ_INFO % user_id, r.REDIS_EXPIRED_ONE_MONTH, read_message_ids)
|
|
|
|
@@ -23,6 +20,7 @@ def get_system_message_read_info(user_id):
|
|
23
|
20
|
|
|
24
|
21
|
def set_system_message_delete_info(user_id):
|
|
25
|
22
|
""" 设置系统消息删除信息 """
|
|
|
23
|
+ from message.models import SystemMessageDeleteInfo
|
|
26
|
24
|
deleted_messages = SystemMessageDeleteInfo.objects.filter(user_id=user_id, status=True)
|
|
27
|
25
|
deleted_message_ids = [msg.msg_id for msg in deleted_messages]
|
|
28
|
26
|
r.setexjson(SYSTEM_MESSAGE_DELETED_INFO % user_id, r.REDIS_EXPIRED_ONE_MONTH, deleted_message_ids)
|
|
|
|
@@ -6,14 +6,10 @@ from utils.redis.connect import r
|
|
6
|
6
|
from utils.redis.rkeys import LENSMAN_PHOTO_ORDER_RECORD
|
|
7
|
7
|
|
|
8
|
8
|
|
|
9
|
|
-# 摄影师照片购买记录相关
|
|
10
|
|
-
|
|
11
|
|
-
|
|
12
|
9
|
def set_lensman_order_record(porder):
|
|
13
|
10
|
""" 设置摄影师照片购买记录 """
|
|
14
|
|
- porder_info = porder.porder_info
|
|
15
|
|
- r.setexjson(LENSMAN_PHOTO_ORDER_RECORD % (porder.photo_id, porder.user_id), r.REDIS_EXPIRED_ONE_MONTH, porder_info, cls=DjangoJSONEncoder)
|
|
16
|
|
- return porder_info
|
|
|
11
|
+ r.setexjson(LENSMAN_PHOTO_ORDER_RECORD % (porder.photo_id, porder.user_id), r.REDIS_EXPIRED_ONE_MONTH, porder.porder_info, cls=DjangoJSONEncoder)
|
|
|
12
|
+ return porder.porder_info
|
|
17
|
13
|
|
|
18
|
14
|
|
|
19
|
15
|
def set_lensman_order_record_by_id(photo_id, user_id):
|
|
|
|
@@ -1,15 +1,12 @@
|
|
1
|
1
|
# -*- coding: utf-8 -*-
|
|
2
|
2
|
|
|
3
|
|
-from account.models import LensmanInfo
|
|
4
|
3
|
from utils.redis.connect import r
|
|
5
|
4
|
from utils.redis.rkeys import LENSMAN_PHOTO_PRICE_FIXED
|
|
6
|
5
|
|
|
7
|
6
|
|
|
8
|
|
-# 最新 APP 相关
|
|
9
|
|
-
|
|
10
|
|
-
|
|
11
|
7
|
def set_lensman_price_fixed(user_id):
|
|
12
|
8
|
""" 设置摄影师价格设定 """
|
|
|
9
|
+ from account.models import LensmanInfo
|
|
13
|
10
|
try:
|
|
14
|
11
|
lensman = LensmanInfo.objects.get(lensman_id=user_id)
|
|
15
|
12
|
except LensmanInfo.DoesNotExist:
|
|
|
|
@@ -4,9 +4,6 @@ from utils.redis.connect import r
|
|
4
|
4
|
from utils.redis.rkeys import PROFILE_INFO
|
|
5
|
5
|
|
|
6
|
6
|
|
|
7
|
|
-# 用户相关
|
|
8
|
|
-
|
|
9
|
|
-
|
|
10
|
7
|
def set_profile_info(user):
|
|
11
|
8
|
""" 设置用户信息 """
|
|
12
|
9
|
r.setjson(PROFILE_INFO % user.user_id, user.data)
|
|
|
|
@@ -4,9 +4,6 @@ from utils.redis.connect import r
|
|
4
|
4
|
from utils.redis.rkeys import TOUR_GUIDE_GROUP_USER_OWN
|
|
5
|
5
|
|
|
6
|
6
|
|
|
7
|
|
-# 导游相关
|
|
8
|
|
-
|
|
9
|
|
-
|
|
10
|
7
|
def set_tour_guide_own_group(user_id, group_id):
|
|
11
|
8
|
""" 设置导游拥有的旅行团 """
|
|
12
|
9
|
r.set(TOUR_GUIDE_GROUP_USER_OWN % user_id, group_id)
|
|
|
|
@@ -4,9 +4,6 @@ from utils.redis.connect import r
|
|
4
|
4
|
from utils.redis.rkeys import TOUR_GUIDE_GROUP_USER_BELONG
|
|
5
|
5
|
|
|
6
|
6
|
|
|
7
|
|
-# 旅行团成员相关
|
|
8
|
|
-
|
|
9
|
|
-
|
|
10
|
7
|
def set_tour_user_belong_group(user_id, group_id):
|
|
11
|
8
|
""" 设置旅行团成员所属的旅行团 """
|
|
12
|
9
|
r.set(TOUR_GUIDE_GROUP_USER_BELONG % user_id, group_id)
|