async def change_withdraw_record(request, *args, **kwargs): async def withdraw_record(id): async with db.conn.acquire() as con: st = await con.prepare( 'select id, account_id, amount from "account_withdraw" where id=$1' ) data = await st.fetchrow(id) return data withdraw_infos = request.json.get('withdraw_id') status = request.json.get('status') if isinstance(withdraw_infos, list): for withdraw in withdraw_infos: wd = await withdraw_record(withdraw) if not wd: return response_json(None, code=PARAMS_ERROR_CODE) if status == WITHDRAW_REJECTED: await withdraw_rejected_account(wd['account_id'], wd['id'], wd['amount']) elif status == WITHDRAW_AGREE: await withdraw_agree_account(wd['id']) else: return response_json(None, code=PARAMS_ERROR_CODE) return response_json(None)
async def send_verify_code(request, user): user_id = user.get('user_id') phone = request.args.get("phone", None) logger.info(f'user request verify_code, user_id:{user_id}, phone:{phone}') if phone is not None: check_phone_res = await check_phone(phone) if check_phone_res: ''' 发送验证码 1. 正则校验手机号 1. 根据手机号,生成6位随机数字 2. 记录手机号与其验证码缓存关系 ''' if await check_rate(user_id, phone): return response_json(None, SHORT_MSG_SEND_FREQUENTLY, 'send frequently.') # 调用频繁 verify_code = str(random.randint(0, 999999)).zfill(6) val_redis_key = SEND_MSG_VAL_REDIS_KEY.format(user_id=user_id, phone=phone) await redis.conn.set(val_redis_key, verify_code, ex=60 * 60 * 1) content = MSG_TEMPLATE.format(verify_code=verify_code) return await send_msg(phone, content) else: return response_json(None, PARAMS_ERROR_CODE, 'this phone may not be exists.') else: return response_json(None, PARAMS_ERROR_CODE, 'this phone may not be exists.')
async def withdraw_list_admin(request, *args, **kwargs): """提现列表""" current_page = int(request.raw_args.get('current_page', 0)) page_size = int(request.raw_args.get('page_size', 20)) params = request.json sql, sql_count = await withdraw_sql(params) sql = sql + ''' limit ''' + str(page_size) + ''' offset ''' + str( current_page * page_size) async with db.conn.acquire() as con: select_result = records_to_list(await con.fetch(sql)) select_count = await con.fetchval(sql_count) page_info = get_page_info(page_size, current_page, select_count) return response_json(select_result, page_info=page_info)
async def send_msg(phone, content): timestamp = str(int(time.time())) user_id = 'JJ0679' pwd = '595489' m = hashlib.md5() pwd_str = user_id + '00000000' + pwd + timestamp m.update(bytes(pwd_str, encoding='utf-8')) pwd_md5 = m.hexdigest() params = { 'userid': user_id, 'pwd': pwd_md5, 'mobile': phone, 'content': quote(content.encode('gbk')), 'timestamp': timestamp } await send_msg_montent(params) return response_json(None)
async def user_withdraw_view(request, user): '''用户提现页''' user_id = user.get('user_id') data = {} async with db.conn.acquire() as con: select_stmt = await con.prepare( '''select id, user_id, balance_amount, withdrawing_amount from "account" where user_id=$1''' ) user_withdraw_info = dict(await select_stmt.fetchrow(user_id)) slip_stmt = await con.prepare( '''select exists(select id from "account_withdraw" where account_id=$1 and status in ($2, $3) limit 1)''' ) is_withdrawed = await slip_stmt.fetchval(user_withdraw_info['id'], WITHDRAW_SUCCESSED, WITHDRAWING) data.update({'is_withdrawed': is_withdrawed}) data.update(user_withdraw_info) return response_json(data)
async def keyword_list(request, user): """查询关键字列表""" user_id = user.get('user_id') user_keywords = await find_user_key_words(user_id) keywords_list = [] if user_keywords is not None: for key, value in user_keywords.items(): result_dict = { 'batch_id': key, 'keywords': value['keywords'], 'bind_group_counts': len(value['group_codes']), 'reply_content': value['reply_content'], 'trigger_times': value['trigger_times'], 'group_codes': value['group_codes'] } keywords_list.append(result_dict) return response_json(keywords_list)
async def launch_history(request, **kwargs): user_id = kwargs['user']['user_id'] current_page = int(request.raw_args.get('current_page')) page_size = int(request.raw_args.get('page_size')) logger.debug(f'launch history req, user_id:{user_id}') async with db.conn.acquire() as con: user_task_stmt = await con.prepare( '''select id as task_id, to_char(send_date, 'YYYY-MM-DD HH24:MI:SS') as send_date, jsonb_array_length(group_ids)::varchar as group_count, status as send_flag from "group_task" where user_id = $1 and type = 2 and status =1 and create_date >= (current_date - 2) order by create_date desc limit $2 offset $3''') user_tasks = await user_task_stmt.fetch(user_id, page_size, current_page * page_size) task_list = records_to_list(user_tasks) history_count_stmt = await con.prepare( '''select count(1) from "group_task" where user_id = $1 and type = 2 and status = 1 and create_date >= (current_date - 2)''' ) total_records = await history_count_stmt.fetchval(user_id) page_info = get_page_info(page_size, current_page, total_records) return response_json(task_list, page_info=page_info)
async def problem_feedback(request, *args, **kwargs): current_page = int(request.raw_args.get('current_page', 0)) page_size = int(request.raw_args.get('page_size', 20)) params = request.json sql, sql_count = await problem_sql(params) sql = sql + ''' limit ''' + str(page_size) + ''' offset ''' + str( current_page * page_size) async with db.conn.acquire() as con: select_result = records_to_list(await con.fetch(sql)) select_count = await con.fetchval(sql_count) for result in select_result: if result['code'] is not None: result['robot_info'] = result['name'] + '(' + result[ 'wechat_no'] + ')' page_info = get_page_info(page_size, current_page, select_count) return response_json(select_result, page_info=page_info)
async def exception_group_pull(request, user, group_id): '''异常群拉回''' user_id = user.get('user_id') async with db.conn.acquire() as con: get_robot_stmt = await con.prepare( '''select "robot".code, "robot".qr_code from "robot_group_map" left join "robot" on "robot_group_map".robot_id = "robot".id where "robot_group_map".group_id = $1 and "robot_group_map".status <> 3''') get_group_stmt = await con.prepare( '''select name from "group" where id = $1 limit 1''') get_user_stmt = await con.prepare( '''select code from "user" where id = $1 limit 1''') robot = await get_robot_stmt.fetchrow(group_id) robot_code = robot.get('code') qr_code = robot.get('qr_code') user_code = await get_user_stmt.fetchval(user_id) group_name = await get_group_stmt.fetchval(group_id) content = GROUP_ROBOT_CALL_BACK_WORD.format(group_name=group_name) await send_text_msg(robot_code, user_code, content=content) return response_json(qr_code)
async def get_alt_msg(request, *args, **kwargs): """获取@用户机器人信息""" user_id = kwargs['user']['user_id'] current_page = int(request.raw_args.get('current_page', 0)) page_size = int(request.raw_args.get('page_size', 20)) async with db.conn.acquire() as con: select_altmsg = await con.prepare( '''select "alt_msg".msg_id as msg_id, "group".name as group_name, "alt_msg".msg_content as msg_content, "group".code as group_code, "alt_msg".status as status from "alt_msg" left join "group" on "group".id="alt_msg".group_id where "group".status !=3 and "alt_msg".user_id = $1 and "alt_msg".create_date >=(current_date - interval '3' day) order by "alt_msg".create_date desc limit $2 offset $3''') msg_infos = records_to_list(await select_altmsg.fetch( user_id, page_size, current_page * page_size)) select_count = await con.prepare( '''select count(1) from "alt_msg" left join "group" on "group".id="alt_msg".group_id where "group".status !=3 and "alt_msg".user_id = $1 and "alt_msg".create_date >=(current_date - interval '3' day)''' ) total_records = await select_count.fetchval(user_id) page_info = get_page_info(page_size, current_page, total_records) return response_json(msg_infos, page_info=page_info)
async def export_result(request, *args, **kwargs): params = request.json sql, sql_count = await withdraw_sql(params) async with db.conn.acquire() as con: select_result = records_to_list(await con.fetch(sql)) if not select_result: return response_json(None) title = ['phone', 'amount', 'create_date', 'paid_date', 'status'] out = io.BytesIO() workbook = xlsxwriter.Workbook(out) worksheet = workbook.add_worksheet() for item in title: worksheet.write(0, title.index(item), item) for item in select_result: worksheet.write( select_result.index(item) + 1, 0, item['phone'] if item['phone'] is not None else '') worksheet.write( select_result.index(item) + 1, 1, item['amount'] if item['amount'] is not None else '') worksheet.write( select_result.index(item) + 1, 2, item['create_date'] if item['create_date'] is not None else '') worksheet.write( select_result.index(item) + 1, 3, item['paid_date'] if item['paid_date'] is not None else '') worksheet.write( select_result.index(item) + 1, 4, item['status'] if item['status'] is not None else '') workbook.close() out.seek(0) filename = quote("提现列表.xlsx") return raw(out.getvalue(), headers={ 'Content-Disposition': 'attachment;filename*=utf-8{0}'.format(filename) }, content_type='application/vnd.ms-excel;chartset=utf-8')
async def mass_message_detail_view(request, task_id, *args, **kwargs): '''群发消息详情''' async def mass_message_detail(id): async with db.conn.acquire() as con: st = await con.prepare( '''select group_ids::jsonb as "groups_info", content::jsonb, to_char(send_date, 'YYYY-MM-DD HH24:MI:SS') as send_date from "group_task" where id=$1 and status<>3''') group_task = await st.fetchrow(id) if not group_task: return group_task = dict(group_task) gst = await con.prepare( 'select id, name from "group" where code = any($1) and status <> 3' ) group_codes = ujson.loads(group_task['groups_info']) groups = await gst.fetch(group_codes) group_task['groups_info'] = records_to_list(groups) group_task['content'] = ujson.loads(group_task['content']) return group_task data = await mass_message_detail(task_id) return response_json(data)
async def user_share_poster(request, user_id): """用户分享海报""" async def streaming_fn(response): await response.write(image_bytes.getvalue()) type = request.raw_args.get('type', None) if type is not None: background_image = os.path.join(BASE_DIR, 'static/{}.png').format(type) else: background_image = os.path.join(BASE_DIR, 'static/background.png') user_info = await get_user_info(user_id) if user_info is None: return response_json({}, RESOURCE_NOT_FOUND_CODE, msg='用户不存在') head_url = user_info['head_url'] name = user_info['nickname'] channel = user_info.get('channel', None) qr_code_url = QR_CODE_URL + '?sharing_user_id=' + user_id if channel is not None: qr_code_url = qr_code_url + '&channel=' + channel image_bytes = await create_user_share_poster(qr_code_url, head_url, name, background_image, type) return stream(streaming_fn, content_type='image/jpeg')
async def mass_message_task_view(request, user): '''群发消息页面''' async def mass_message_data(direction, current_page, page_size): async with db.conn.acquire() as con: if direction == 'up': st = await con.prepare( '''select to_char(send_date, 'YYYY-MM-DD HH24:MI:SS') as send_date, jsonb_array_length(group_ids)::int as group_counts, status, id from "group_task" where user_id=$1 and status <> $2 and type=1 and send_date >= timestamp 'today' and send_date <= (current_date + interval '3' day) order by send_date desc limit $3 offset $4''') st_count = await con.prepare( '''select count(1) from "group_task" where user_id=$1 and status <> $2 and type=1 and send_date >= timestamp 'today' and send_date < (current_date + interval '3' day)''' ) else: st = await con.prepare( '''select to_char(send_date, 'YYYY-MM-DD HH24:MI:SS') as send_date, jsonb_array_length(group_ids)::int as group_counts, status, id from "group_task" where user_id=$1 and status <> $2 and type=1 and send_date < timestamp 'today' and send_date >= (current_date - interval '3' day) order by send_date desc limit $3 offset $4''') st_count = await con.prepare( '''select count(1) from "group_task" where user_id=$1 and status <> $2 and type=1 and send_date < timestamp 'today' and send_date >= (current_date - interval '3' day)''' ) count = await st_count.fetchval(user['user_id'], FAIL_DELETE) datas = await st.fetch(user['user_id'], FAIL_DELETE, page_size, current_page * page_size) return records_to_list(datas), count current_page = int(request.raw_args.get('current_page', 0)) page_size = int(request.raw_args.get('page_size', 20)) direction = request.raw_args.get('direction', 'up') datas, count = await mass_message_data(direction, current_page, page_size) page_info = get_page_info(page_size, current_page, count) return response_json(datas, page_info=page_info)
async def get_user_groups_disciples(request, *args, **kwargs): """首页获取用户群数量和徒弟徒孙数量""" user_id = kwargs['user']['user_id'] async with db.conn.acquire() as con: select_groups = await con.prepare( '''select count(1) from "group" where user_id =$1 and status !=3''' ) group_count = await select_groups.fetchval(user_id) select_apprentice = await con.prepare( '''select count(1) from "sharing_record" where sharing_user_id =$1 and status !=3''') apprentice_count = await select_apprentice.fetchval(user_id) select_disciple = await con.prepare( '''with t as (select user_id from sharing_record where sharing_user_id=$1) select count(1) from sharing_record,t where sharing_record.sharing_user_id=t.user_id''' ) disciple_count = await select_disciple.fetchval(user_id) result = { 'group_count': group_count, 'disciples': int(apprentice_count) + int(disciple_count), # 徒弟徒孙数量 'apprentice': int(apprentice_count), # 徒弟数量 'disciple': int(disciple_count) # 徒孙数量 } return response_json(data=result)
async def set_app_status(request): '''设置app_status''' data = request.json data_json = ujson.dumps(data) await redis.conn.set(APP_STATUS_REDIS_KEY, data_json) return response_json(data)
async def alt_switch_info(request, *args, **kwargs): user_id = kwargs['user']['user_id'] user_info = await get_user_by_id(user_id) if user_info is not None: switch = user_info['alt_switch'] return response_json(switch)
async def get_user_id(request, user): user_id = user.get('user_id') return response_json(user_id)
async def users_statistic_view(request): '''bi数据统计回传, 账户加钱、群同步 { "settle_date": "", "timestamp": "", "sign": "", "data": {"code": "amount"} } ''' async def need_settlement_groups(groups): groups_join = ','.join(groups.keys()) async with db.conn.acquire() as con: st = await con.prepare( '''select "group".id as group_id, "group".code, "user".id as user_id, "user".code as user_code from "group" join "user" on "group".user_id="user".id where "group".status<>3 and exists(select tmp_code from (select unnest(string_to_array($1, ',')) as tmp_code) as tmp where tmp.tmp_code="group".code) order by "user".code''') data = await st.fetch(groups_join) return records_to_list(data) async def coroutine_thread_run_settle(groups, settle_date): settle_groups = await need_settlement_groups(groups) logger.info(f'need settle groups: {len(settle_groups)}') for user_code, items in await async_groupby(settle_groups, 'user_code'): copy_items = list(items) for item in copy_items: item['amount'] = groups.get(item['code'], 0) logger.debug(f'adv settle user code: {user_code}') try: await signle_user_groups_settlement(user_code, copy_items, settle_date, settle_type=TYPE.AD_CLICK) except Exception as e: logger.error(f'user [{user_code} settle occer error: [{e}]]') async def check_settle_day_exist(date): async with db.conn.acquire() as con: st = await con.prepare( 'select count(*) from "account_slip" where settle_date=$1 and amount_type=$2' ) count = await st.fetchval(date, TYPE.AD_CLICK) if count > 0: logger.info(f'exist settle day {date} and find count {count}') return True return False logger.debug(f'settlement callback data #: {request.json}') timestamp = request.json.get('timestamp') sign = request.json.get('sign') settlement_date = request.json.get('settle_date') # 数据校验 if not all([str(timestamp), sign, settlement_date]): return response_json(None, code=PARAMS_ERROR_CODE) secret_md5 = md5() secret_md5.update('#'.join([timestamp, MD5_SECRET_KEY]).encode('utf-8')) if secret_md5.hexdigest() != sign: return response_json(None, code=PARAMS_ERROR_CODE) groups = request.json.get('data', {}) settle_date = str_to_date(settlement_date) if await check_settle_day_exist(settle_date): logger.error(f'exist duplicate call ad click, date {settle_date}') return response_json(None, code=DUPLICATE_REQUEST_CODE) loop = asyncio.get_event_loop() asyncio.run_coroutine_threadsafe( coroutine_thread_run_settle(groups, settle_date), loop) return response_json(None)
async def set_marquee_info(request): """设置跑马灯""" date = request.json data_json = ujson.dumps(date) await redis.conn.set(APP_MARQUEE_REDIS_KEY, data_json) return response_json('SUCCESS')
async def no_click_groups(request): group_codes = request.json.get('group_codes') logger.info(f'receive BI no click groups, count:{len(group_codes)}') redis_key = NO_CLICK_GROUPS_REDIS_KEY.format(today=today()) await redis.conn.set(redis_key, ujson.dumps(group_codes), ex=24 * 60 * 60) return response_json(None)
async def users_info(request): ''' 返回给BI的数据 { "user_id": string, // 用户id "maps": { "father_id": string, // 师傅 "grand_father_id": string // 师爷 }, "groups": ["", ""] // 群id } } ''' async def get_user_relationships(user_id): async with db.conn.acquire() as con: st = await con.prepare('''with recursive parent as ( select user_id, sharing_user_id, 0 as depth from "sharing_record" where user_id=$1 union select psr.user_id, psr.sharing_user_id, depth - 1 from "sharing_record" psr join parent p on p.sharing_user_id=psr.user_id where p.depth > -1) select "user".code as code, parent.depth from parent join "user" on parent.sharing_user_id="user".id; ''') users = await st.fetch(user_id) results = {'grand_father_id': None} for user in users: if user['depth'] == 0: results.update({'father_id': user['code']}) elif user['depth'] == -1: results.update({'grand_father_id': user['code']}) if len(results) == 1 and not results.get('grand_father_id'): results = None return results async def get_user_ids(datetime, user_ids): async with db.conn.acquire() as con: st = await con.prepare( '''select "user".id as user_id, "user".code as user_code, "group".code as group_code from "user" join "group" on "user".id="group".user_id where "user".status<>3 and "group".status <>3 and "user".create_date <= to_timestamp($1, 'YYYY-MM-DD HH24:MI:SS') and "group".create_date <= to_timestamp($2, 'YYYY-MM-DD HH24:MI:SS') and "user".id=any($3) order by "user".id''' ) users = await st.fetch(datetime, datetime, user_ids) return records_to_list(users), records_to_value_list( users, 'user_code') async def get_user_counts(datetime): async with db.conn.acquire() as con: st = await con.prepare('''select "user".id from "user" join "group" on "user".id="group".user_id where "user".status<>3 and "group".status <>3 and "user".create_date <= to_timestamp($1, 'YYYY-MM-DD HH24:MI:SS') and "group".create_date <= to_timestamp($2, 'YYYY-MM-DD HH24:MI:SS') group by "user".id''' ) total_users = await st.fetch(datetime, datetime) return records_to_value_list(total_users, 'id'), len(total_users) async def async_groupby(users, sort_key): return groupby(users, key=itemgetter(sort_key)) async def pre_next_page_count(current_page, page_size): return current_page * page_size, (current_page + 1) * page_size logger.debug(f'receiver bi data: {request.json}') datetime = request.json.get('datetime') current_page = int(request.raw_args.get('current_page')) page_size = int(request.raw_args.get('page_size')) timestamp = request.json.get('timestamp') sign = request.json.get('sign') # 数据校验 if not all([timestamp, sign]): return response_json(None, code=PARAMS_ERROR_CODE) secret_md5 = md5() secret_md5.update('#'.join([timestamp, MD5_SECRET_KEY]).encode('utf-8')) if secret_md5.hexdigest() != sign: return response_json(None, code=PARAMS_ERROR_CODE) data = [] static_users, user_counts = await get_user_counts(datetime) pre_count, next_count = await pre_next_page_count(current_page, page_size) page_user_ids = static_users[pre_count:next_count] users, user_codes = await get_user_ids(datetime, page_user_ids) cache_maps = {} if user_codes: maps = await redis.conn.hmget(COMPLETE_USER_REDIS_KEY, user_codes) for key, value in zip(user_codes, maps): cache_maps[key] = value for user_code, items in await async_groupby(users, 'user_code'): user_maps = cache_maps.get(user_code) copy_items = list(items) user_id = copy_items[0]['user_id'] groups = [] for item in copy_items: groups.append(item['group_code']) if not user_maps: user_maps = await get_user_relationships(user_id=user_id) data.append({ 'user_id': user_code, 'groups': groups, 'maps': user_maps }) page_info = get_page_info(page_size, current_page, user_counts) return response_json(data, page_info=page_info)
async def launch_switch(request, *args, **kwargs): '''设置投放开关''' group_info = request.json await currency_launch_switch(group_info) return response_json(None, msg='设置成功')
async def completion_task_view(request, task_id, *args, **kwargs): '''补全群发消息''' async def check_can_created_today(user_id, send_date): async with db.conn.acquire() as con: st = await con.prepare( '''select to_char(send_date, 'YYYY-MM-DD') as day, count(1) as count from "group_task" where user_id=$1 and status<>$2 and type = 1 group by to_char(send_date, 'YYYY-MM-DD')''' ) day_group_count = records_to_list(await st.fetch(user_id, FAIL_DELETE)) date = str_to_datetime(send_date) if date <= datetime.now(): return False str_date = date.strftime('%Y-%m-%d') for item in day_group_count: if item['day'] == str_date and item['count'] >= MAX_MASS_MSG_AMOUNT: logger.info( f'user [{user_id}] create mass msg max day [{str_date}]') return False return True async def check_group_same_time_created(send_date, group_ids): date = str_to_datetime(send_date) str_date_minute = date.strftime('%Y-%m-%d %H:%M') async with db.conn.acquire() as con: st = await con.prepare('''select count(1) from "group_task" where to_char(send_date, 'YYYY-MM-DD HH24:MI') = $1 and status<>3 and type = 1 and group_ids ?| $2''' ) count = await st.fetchval(str_date_minute, group_ids) if count > 0: return False return True async def combine_content(message): '''组合消息''' task_content = await redis.conn.get( MASS_MSG_TASK_CREATE_REDIS_KEY.format(task_id=task_id)) if not task_content: return None content = ujson.loads(task_content) content.append(message) return content async def save_task(id, content, group_ids, user_id, send_date): async with db.conn.acquire() as con: task_stmt = await con.prepare( '''insert into "group_task" (id, user_id, group_ids, content, status, send_date, type) values ($1, $2, $3, $4, $5, to_timestamp($6, 'YYYY-MM-DD HH24:MI:SS'), 1)''' ) await task_stmt.fetchval(id, user_id, group_ids, content, NOT_SEND_MSG, send_date) await redis.conn.expire( MASS_MSG_TASK_CREATE_REDIS_KEY.format(task_id=id), 0) async def create_redis_task(id, send_date): '''创建群发缓存''' timestamp = int(send_date.timestamp()) await redis.conn.zadd(TASK_MSG_MONITOR_REDIS_KEY, timestamp, id) user_id = kwargs['user']['user_id'] message = request.json.get('message') group_ids = request.json.get('group_ids') send_date = request.json.get('send_date') if not all([message, group_ids, send_date]): return response_json(None, code=PARAMS_ERROR_CODE, msg='缺少必要的参数') if not await check_can_created_today(user_id, send_date): return response_json(None, code=CREATED_FAILED_CODE, msg='达到当日最大创建次数') if not await check_group_same_time_created(send_date, group_ids): return response_json(None, code=EXISTS_SAME_TIME_CREATED_CODE, msg='同一群存在相同的发送时间') if not await aly_text_check(message['content']): return response_json(None, code=SENSITIVE_WORD_CODE, msg='检测到敏感词汇') content = await combine_content(message) if not content: return response_json(None, code=RESOURCE_NOT_FOUND_CODE, msg='群发消息已过期') content = ujson.dumps(content) group_ids = ujson.dumps(group_ids) await save_task(task_id, content, group_ids, user_id, send_date) send_date = str_to_datetime(send_date) await create_redis_task(task_id, send_date) return response_json(None)
async def user_withdraw_request_view(request, user, *args, **kwargs): '''用户发起提现请求''' async def static_user_withdrow_balance_month(account_id): async with db.conn.acquire() as con: select_stmt = await con.prepare( '''select case when sum(amount) is not null then sum(amount) else 0 end as balance from "account_withdraw" where account_id=$1 and status=any($2) and create_date >= date_trunc('month', current_date)''' ) balance = await select_stmt.fetchval( account_id, [WITHDRAWING, WITHDRAW_SUCCESSED]) return balance async def add_user_withdraw_record(account_id, user_id, amount): async with db.conn.acquire() as con: async with con.transaction(): insert_stmt = await con.prepare( '''insert into "account_withdraw" (id, account_id, user_id, amount, review_status, status) values(uuid_generate_v4(), $1, $2, $3, 0, 0) ''') update_stmt = await con.prepare( '''update "account" set balance_amount = balance_amount-$1, withdrawing_amount = withdrawing_amount+$2, update_date=now() where id=$3''' ) await insert_stmt.fetch(account_id, user_id, amount) await update_stmt.fetch(amount, amount, account_id) async def is_withdraw_today(account_id): async with db.conn.acquire() as con: st = await con.prepare( '''select exists(select id from "account_withdraw" where account_id=$1 and status=$2 and create_date >= timestamp 'today')''') is_withdraw = await st.fetchval(account_id, WITHDRAWING) return is_withdraw user_id = user.get('user_id') withdraw_balance = request.json.get('balance', None) balance_amounts = [1, 20, 50, 100, 200, 500] # 余额参数校验 if withdraw_balance is None or withdraw_balance not in balance_amounts: return response_json(None, code=PARAMS_ERROR_CODE, msg='未获取到提现金额参数') account_info = dict(await get_account_info(user_id)) if account_info['balance_amount'] < withdraw_balance: return response_json(None, code=INSUFFICIENT_AMOUNT_CODE, msg='提现金额超过当前余额') # 用户校验 user_info = dict(await get_user_by_id(user_id)) if not user_info.get('phone'): return response_json(None, code=MISS_PHONE_CODE, msg='请补全用户手机号') if user_info.get('status', 1) == 2: return response_json(None, code=WITHDRAW_FAILED_CODE, msg='用户已封号禁止提现') month_withdraw_balance = await static_user_withdrow_balance_month( account_info['id']) # 超800税收身份证信息补全提醒 if month_withdraw_balance + Decimal( withdraw_balance) > WITHDRAW_TAX_AMOUNT: if not user_info.get('identity_info'): return response_json(None, code=MISS_IDCARD_CODE, msg='请补全用户身份证信息') if await is_withdraw_today(account_info['id']): return response_json(None, code=REVOKED_TODAY_CODE, msg='今天已提现') logger.info( f'user [{user_id} request withdraw balance [{withdraw_balance}]') await add_user_withdraw_record(account_info['id'], user_id, withdraw_balance) return response_json(None, msg='提现进入审核状态')
async def long_to_short_view(request): long_url = request.json.get('url') short_url = await long_to_short(long_url) return response_json(short_url)
async def robot_distribution_view(request): """ - 分配机器人 - 更新或绑定师徒关系 - 创建机器人用户展示表 """ async def exists_user_access(union_id): async with db.conn.acquire() as con: select_stmt = await con.prepare( '''select "robot_access".id from "robot_access" join "robot" on "robot".id="robot_access".robot_id where "robot_access".union_id=$1 and "robot".status<>3 order by "robot_access".create_date desc limit 1''') access_id = await select_stmt.fetchval(union_id) return access_id async def update_user_access(user_access_id, sharing_user_id=None, channel=None): if not sharing_user_id: is_sharing_user = False else: is_sharing_user = True async with db.conn.acquire() as con: update_stmt = await con.prepare( '''update "robot_access" set sharing_user_id=case when $1 then $2 else sharing_user_id end, channel=case when $3 then $4 else channel end, update_date=now() where id=$5 returning robot_id''') return await update_stmt.fetchval(is_sharing_user, sharing_user_id, is_sharing_user, channel, user_access_id) async def create_user_access(open_id, union_id, robot_id, sharing_user_id=None, channel=None): async with db.conn.acquire() as con: insert_stmt = await con.prepare('''insert into "robot_access" (id, open_id, union_id, robot_id, sharing_user_id, channel, status) values (uuid_generate_v4(), $1, $2, $3, $4, $5, $6)''') await insert_stmt.fetch(open_id, union_id, robot_id, sharing_user_id, channel, CREATE_STATUS) async def robot_info(robot_id): '''查询机器人信息''' async with db.conn.acquire() as con: select_stmt = await con.prepare( 'select head_url, qr_code, wechat_no, name from "robot" where id=$1' ) robot = await select_stmt.fetchrow(robot_id) return robot open_id = request.json.get('open_id') union_id = request.json.get('union_id') if not open_id or not union_id: return response_json(None, code=PARAMS_ERROR_CODE, msg='缺少必要参数open_id或union_id') sharing_user_id = request.json.get('sharing_user_id', None) channel = request.json.get('channel', None) access_id = await exists_user_access(union_id) if access_id: if not sharing_user_id or sharing_user_id == 'null': sharing_user_id = None if not channel: channel = None robot_id = await update_user_access(access_id, sharing_user_id, channel) else: robot_id = await robot_distribution(channel=channel) if not robot_id: logger.warning(f'not match distribute robot for user [{open_id}]') return response_json(None, code=ROBOT_NOT_ENOUGH_CODE, msg='没有可分配的机器人') await create_user_access(open_id, union_id, robot_id, sharing_user_id, channel) await robot_today_display_record(robot_id) logger.info(f'distribute robot [{robot_id}] for user [{open_id}]') robot = await robot_info(robot_id) return response_json(dict(robot))