def login(cls, phone: str, password: str) -> dict: """ 登录 :param phone: :param password: :return: """ mes = {"message": "success"} cli = mongo_db.get_client() col = mongo_db.get_conn(table_name=cls.get_table_name(), db_client=cli) with cli.start_session(causal_consistency=True) as session: with session.start_transaction(): f = {"phone": phone} r = col.find_one(filter=f, session=session) if r is None: mes['message'] = "手机号码未注册" else: pw2 = r['password'] if password != pw2: mes['message'] = '密码错误' else: _id = r['_id'] mes['_id'] = _id now = datetime.datetime.now() f = dict() f['_id'] = _id u = {"$set": {"last_login": now}} # 更新最后的登录时间 col.find_one_and_update(filter=f, update=u, session=session) return mes
def add(cls, **kwargs) -> dict: """ 添加角色 :param kwargs: :return: """ mes = {"message": "success"} role_name = kwargs.get("role_name", '') db = orm_module.get_client() conn = orm_module.get_conn(table_name=cls.get_table_name(), db_client=db) write_concern = WriteConcern(w=1, j=True) with db.start_session(causal_consistency=True) as ses: with ses.start_transaction(write_concern=write_concern): r = conn.find_one(filter={'role_name': role_name}) if r is not None: ms = "角色 {} 已存在!".format(role_name) mes['message'] = ms else: """添加""" r = conn.insert_one(kwargs) if r is None: ms = "保存用户账户失败" mes['message'] = ms else: pass return mes
def register(cls, phone: str, password: str) -> dict: """ 注册 :param phone: :param password: :return: """ mes = {"message": "success"} cli = mongo_db.get_client() col = mongo_db.get_conn(table_name=cls.get_table_name(), db_client=cli) with cli.start_session(causal_consistency=True) as session: with session.start_transaction(): f = {"phone": phone} r = col.find_one(filter=f, session=session) if isinstance(r, dict): mes['message'] = "手机号码重复" else: f['password'] = password nick_name = "用户{}".format(phone[-4:]) f['nick_name'] = nick_name now = datetime.datetime.now() f['create_date'] = now r = col.insert_one(document=f, session=session) if r is None: mes['message'] = "插入失败" else: pass return mes
def add_user(cls, **kwargs) -> dict: """ 添加用户 :param kwargs: :return: """ mes = {"message": "success"} user_name = kwargs.get("user_name", '') pwd = kwargs.get("password", '') args = {"user_name": user_name, "password": pwd} db = orm_module.get_client() conn = orm_module.get_conn(table_name=cls.get_table_name(), db_client=db) write_concern = WriteConcern(w=1, j=True) with db.start_session(causal_consistency=True) as ses: with ses.start_transaction(write_concern=write_concern): r = conn.find_one(filter={'user_name': user_name}) if r is not None: ms = "账户 {} 已存在!".format(user_name) mes['message'] = ms else: """提取其他信息""" role_id_str = kwargs.get("role_id", '') if isinstance(role_id_str, str) and len(role_id_str) == 24: role_id = ObjectId(role_id_str) elif isinstance(role_id_str, ObjectId): role_id = role_id_str else: role_id = None args['role_id'] = role_id args['dept_id'] = None now = datetime.datetime.now() # 创建时间 args['time'] = now args['last'] = now args['status'] = 1 nick_name = kwargs.get("nick_name", "") if isinstance(nick_name, str) and len(nick_name) > 0: args['nick_name'] = nick_name else: nick_name = "guest_{}".format( str(random.randint(1, 99)).zfill(2)) args['nick_name'] = nick_name r = conn.insert_one(args) if r is None: ms = "保存用户账户失败" mes['message'] = ms else: pass return mes
def un_follow(cls, user_id: (str, ObjectId)) -> dict: """ 取消跟踪老师 :param user_id: :return: """ mes = {"message": "取消跟踪失败"} user = cls.find_by_id(o_id=user_id, to_dict=True) if isinstance(user, dict): user_id = user['_id'] f = {"_id": user_id} u = {"$set": {"follow": []}} db = mongo_db.get_client() con1 = mongo_db.get_conn(table_name=cls.get_table_name(), db_client=db) con2 = mongo_db.get_conn(table_name=FollowRecord.get_table_name(), db_client=db) w = WriteConcern(w=1, j=True) with db.start_session(causal_consistency=True) as ses: with ses.start_transaction(): r = con1.find_one_and_update( filter=f, upsert=False, update=u, return_document=ReturnDocument.AFTER, session=ses) if r is None or len(r['follow']) > 0: mes['message'] = "保存数据失败" else: f2 = {"user_id": user_id, "end": {"$exists": False}} u2 = {"$set": {"end": datetime.datetime.now()}} r2 = con2.find_one_and_update( filter=f2, upsert=True, update=u2, return_document=ReturnDocument.AFTER, session=ses) if r2 is None or not isinstance( r2.get("end"), datetime.datetime): mes['message'] = "保存record失败" else: mes['message'] = "success" else: ms = "错误的用户id: {}".format(user_id) logger.exception(msg=ms) print(ms) mes['message'] = "用户id错误" return mes
def change_pw(cls, u_id: ObjectId, pwd_old: str, pw_n1: str, pw_n2: str) -> dict: """ 修改密码 :param u_id: :param pwd_old: :param pw_n1: :param pw_n2: :return: """ mes = {"message": 'unknow error!'} db_client = orm_module.get_client() w = orm_module.get_write_concern() col = orm_module.get_conn(table_name=cls.get_table_name(), db_client=db_client, write_concern=w) with db_client.start_session(causal_consistency=True) as ses: with ses.start_transaction(write_concern=w): f = {"_id": u_id} p = ["_id", "password"] r = col.find_one(filter=f, projection=p) if r is None: mes['message'] = "错误的用户id:{}".format(u_id) else: if r.get("password", "").lower() == pwd_old.lower(): if pw_n1 == pw_n2: pw = pw_n1.lower() u = {"$set": {"password": pw}} r = col.find_one_and_update( filter=f, update=u, return_document=orm_module.ReturnDocument.AFTER ) if r['password'] == pw: mes['message'] = "success" else: mes['message'] = "保存失败" else: mes['message'] = "原始密码错误" return mes
def follow(cls, user_id: (str, ObjectId), t_id: (str, ObjectId)) -> dict: """ 用户跟单行为。 1. 如果用户积分不足,那就不能跟单 2. 如果用户已经跟随了一位老师,那就换人。同时扣分 :param user_id: :param t_id: 老师id :return: """ """计算是否需要扣除跟单积分""" user = cls.find_by_id(o_id=user_id, to_dict=True) if isinstance(user, dict): user_id = user['_id'] score = user.get("score", None) if score is None: score = Score.re_calculate(u_dict=user) f_id = ObjectId(t_id) if isinstance( t_id, str) and len(t_id) == 24 else t_id now = datetime.datetime.now() res = {"message": "关注失败"} """ 跟单扣分制度: 参考上一周的老师胜率排行榜 第一 -500, 第二 -300, 第三-200, 第四第五-100, >6 -50 """ num_dict = {0: -500, 1: -300, 2: -200, 3: -100, 4: -100} ses = mongo_db.get_conn(table_name="teacher") f = dict() s = [("win_ratio", -1)] p = ['_id', "win_ratio"] rank = ses.find(filter=f, sort=s, projection=p) rank = { x['_id']: { "index": i + 1, "num": num_dict.get(i, -50) } for i, x in enumerate(rank) } x = rank[f_id] num = x['num'] i = x['index'] if score >= abs(num): score += num temp = { "type": "follow", "num": num, "user_id": user_id, "desc": "跟随老师 {}, 排名: {}".format(t_id, i), "time": now } """事务,开始添加扣分记录和更新用户积分""" client = mongo_db.get_client() t1 = client[mongo_db.db_name][Score.get_table_name()] t2 = client[mongo_db.db_name][WXUser.get_table_name()] t3 = client[mongo_db.db_name][FollowRecord.get_table_name()] with client.start_session(causal_consistency=True) as ses: with ses.start_transaction(): t1.insert_one(document=temp, session=ses) f = {"_id": user_id} u = {"$set": {"score": score, "follow": [f_id]}} t2.find_one_and_update(filter=f, update=u, upsert=False, session=ses) """ 检查用户以前是否有跟踪老师? 检查的方式是:检查用户的follow记录。如果有,更新再新建。没有,新建。 """ follow = user.get("follow", dict()) if len(follow) == 0: """没有跟随过老师""" pass else: """有跟随过老师,需要先终结以前的跟随关系。""" f2 = {"user_id": user_id, "t_id": f_id} u2 = {"$set": {"end": now}} t3.find_one_and_update(filter=f2, update=u2, upsert=False, session=ses) """添加一条跟随老师的记录""" temp = { "_id": ObjectId(), "user_id": user_id, "t_id": f_id, "begin": now } t3.insert_one(document=temp, session=ses) res['message'] = "success" else: res['message'] = "积分不足" return res else: ms = "错误的user_id: {}".format(user_id) logger.exception(msg=ms) raise ValueError(ms)
def every_week_mon_check(cls) -> list: """ 每个星期一,对本周还在关注老师的用户进行扣分.(先扣分),生产环境下,这是给celery的定时任务使用的 :return: 操作情况的数组 [{"_id": user_id, "num":-500, "follow": True },...] """ res = list() f = {"follow.0": {"$exists": True}} # 有关注老师的用户 p = ['_id', "follow", 'score'] us = WXUser.find(filter_dict=f, projection=p) now = datetime.datetime.now() rank = TeacherRank.get_rank(cur_time=now) """扣分:上周排行第一 -500, 第二 -300, 第三-200, 第四第五-100, >6 -50""" num_dict = {0: -500, 1: -300, 2: -200, 3: -100, 4: -100} rank_dict = dict() for i, x in enumerate(rank): rank_dict[x['_id']] = {"index": i, "num": num_dict[i]} for x in us: u_id = x['_id'] f_id = x.get("follow", list()) f_id = None if len(f_id) == 0 else f_id[0] score = x.get("score") if score is None: score = cls.re_calculate(u_dict=x) if f_id in rank: """关注的老师在上周的排行榜内""" s = rank_dict[f_id] num = s['num'] if score >= abs(num): """积分够本周扣分""" score += num temp = { "type": "follow", "num": num, "user_id": u_id, "desc": "跟随老师 {}, 排名: {}".format(f_id, s['index'] + 1), "time": now } """事务,添加一条扣分记录,并修改用户积分""" client = mongo_db.get_client() t1 = client[mongo_db.db_name][cls.get_table_name()] t2 = client[mongo_db.db_name][WXUser.get_table_name()] with client.start_session(causal_consistency=True) as ses: with ses.start_transaction(): t1.insert_one(document=temp, session=ses) f = {"_id": u_id} u = {"$set": {"score": score}} r = t2.find_one_and_update(filter=f, update=u, upsert=False, session=ses) if r is None: ms = "用户:{} 关注扣分失败".format(u_id) print(ms) logger.exception(msg=ms) res.append({"_id": u_id, "error": ms}) else: res.append({ "_id": u_id, "num": num, "follow": True }) else: """积分不够扣分的,直接解除关注就行了""" f = {"_id": u_id} u = {"$set": {"follow": []}} r = WXUser.find_one_and_update(filter_dict=f, update_dict=u, upsert=False) if r is None: ms = "用户:{} 解除关注失败".format(u_id) print(ms) logger.exception(msg=ms) res.append({"_id": u_id, "error": ms}) else: res.append({"_id": u_id, "num": 0, "follow": False}) return res
def re_calculate(cls, u_id: (str, ObjectId) = None, u_dict: dict = None) -> int: """ 重新计算用户积分并写入记录。会逐一检查用户的积分记录,重新初始化用户积分的时候使用 1. 补齐缺少的积分增减记录 2. 计算相关的的记录的积分 3. 返回最后的分值, :param u_id: :param u_dict: :return: """ user_dict = u_dict if isinstance(u_dict, dict) and "_id" in u_dict else \ WXUser.find_by_id(o_id=u_id, to_dict=True) if isinstance(user_dict, dict) and "_id" in user_dict: user_id = user_dict['_id'] """重新计算历史积分""" f = {"user_id": user_id} s = {"time": -1} rs = cls.find(filter_dict=f, sort_dict=s) score = 0 inserts = list() init = False # 初始化过? bind_phone = False # 绑定手机过? for x in rs: score += x.get("num", 0) if x['type'] == "init": init = True elif x['type'] == 'bind_phone': bind_phone = True else: score += x['num'] now = datetime.datetime.now() if not init: temp = { "type": "init", "num": 50, "user_id": user_id, "desc": "用户初始化", "time": now } inserts.append(temp) if not bind_phone: # score += 1000 temp = { "type": "bind_phone", "num": 100, "user_id": user_id, "desc": "绑定手机", "time": now } inserts.append(temp) else: pass """事务,开始添加扣分记录和更新用户积分""" client = mongo_db.get_client() t1 = client[mongo_db.db_name][cls.get_table_name()] t2 = client[mongo_db.db_name][WXUser.get_table_name()] with client.start_session(causal_consistency=True) as ses: with ses.start_transaction(): t1.insert_many(documents=inserts, session=ses) f = {"_id": user_id} u = {"$set": {"score": score}} t2.find_one_and_update(filter=f, update=u, upsert=False, session=ses) return score else: ms = "无效的用户! u_id:{}, u_dict: {}".format(u_id, user_dict) logger.exception(msg=ms) raise ValueError(ms)