Exemple #1
0
def get_race_mapping_info(info: MemberStatisticInfo):
    """
    获取行政区域信息、公司单位、当前关卡
    :param info:
    :return:
    """
    race_cid = info.race_cid
    member_cid = info.member_cid
    city_name_list, district_name_list = get_address(race_cid)
    check_point_cids, _checkpoint_map = get_checkpoint_cid_list(race_cid)
    race_mapping = RaceMapping.sync_find_one({'race_cid': race_cid, 'member_cid': member_cid,
                                              'auth_address.province': {'$ne': None},
                                              'auth_address.city': {"$in": city_name_list},
                                              'auth_address.district': {"$in": district_name_list}})
    if race_mapping:
        info.province = race_mapping.auth_address.get('province')
        info.city = race_mapping.auth_address.get('city')
        info.district = race_mapping.auth_address.get('district')
        info.town = race_mapping.auth_address.get('town')
        info.mobile = race_mapping.mobile
        info.check_point_cid = race_mapping.race_check_point_cid
        if race_mapping.race_check_point_cid:
            info.check_point_index = _checkpoint_map[race_mapping.race_check_point_cid]
        else:
            info.check_point_index = 1

        # 单位信息
        if race_mapping.company_cid:
            company = Company.sync_get_by_cid(race_mapping.company_cid)
            info.company_cid = company.cid
            info.company_name = company.title
        return True
    else:
        return False
Exemple #2
0
def is_new_user(info: MemberStatisticInfo):
    """
    判断是否为当日新用户
    :param info:
    :return:
    """
    race_cid = info.race_cid
    member_cid = info.member_cid
    current_date = str2datetime(info.daily_code, '%Y%m%d').replace(hour=0, minute=0, second=0, microsecond=0)
    checkpoint_cid_list, _checkpoint_map = get_checkpoint_cid_list(race_cid)
    has_history = MemberCheckPointHistory.sync_find_one(
        {'member_cid': member_cid, 'check_point_cid': {'$in': checkpoint_cid_list},
         'created_dt': {'$lt': current_date}})
    if has_history:
        race_mapping = RaceMapping.sync_find_one({'race_cid': race_cid, 'member_cid': member_cid})
        if format(race_mapping.created_dt, "%Y%m%d") == info.daily_code:
            info.is_new_user = 1
        else:
            info.is_new_user = 0
    else:
        # 之前报名活动,但未答题的情况
        race_mapping = RaceMapping.sync_find_one({'race_cid': race_cid, 'member_cid': member_cid})
        if format(race_mapping.created_dt, "%Y%m%d") == info.daily_code:
            info.is_new_user = 1
        else:
            info.is_new_user = 0
def clear(race_cid, daily_code):
    """
    清空一天数据
    :param race_cid:
    :param daily_code:
    :return:
    """
    MemberStatisticInfo.sync_delete_many({"race_cid": race_cid, 'daily_code': daily_code})
Exemple #4
0
def repair(race_cid):
    new_member = MemberStatisticInfo.sync_distinct("member_cid", {
        'race_cid': race_cid,
        'is_new_user': 1
    })
    total_member = MemberStatisticInfo.sync_distinct("member_cid",
                                                     {'race_cid': race_cid})
    more = list(set(total_member) - set(new_member))
    print(more)
Exemple #5
0
def test(race_cid):
    member_cid_list = MemberStatisticInfo.sync_distinct(
        "member_cid", {
            'race_cid': race_cid,
            'is_new_user': 1
        })
    list2 = MemberStatisticInfo.sync_distinct('member_cid',
                                              {'race_cid': race_cid})
    cursor2 = MemberStatisticInfo.sync_find({'race_cid': race_cid})
    print(len(member_cid_list))
    print(len(list2))
    count = 0
    count1 = 0
    dailiy = set()
    for member in cursor2:
        count += 1
        if member.member_cid not in member_cid_list:
            count1 += 1
            print('-----------------------')
            dailiy.add(member.daily_code)
            print(member.daily_code, member.member_cid, member.is_new_user,
                  member.draw_red_packet_amount)
            race_mapping = RaceMapping.sync_find_one({
                'race_cid':
                race_cid,
                'member_cid':
                member.member_cid
            })
            print(11, race_mapping.cid,
                  format(race_mapping.created_dt, "%Y%m%d"),
                  race_mapping.updated_dt)
            current_date = str2datetime(member.daily_code,
                                        '%Y%m%d').replace(hour=0,
                                                          minute=0,
                                                          second=0,
                                                          microsecond=0)
            has_history = MemberCheckPointHistory.sync_find_one({
                'member_cid':
                member.member_cid,
                'created_dt': {
                    '$lt': current_date
                }
            })
            if has_history:
                print(222, has_history)
            else:
                print(None)
    print('total', count)
    print('no', count1)
    temp = list(dailiy)
    temp.sort()
    print(temp)
    return temp
Exemple #6
0
def export_new_info(workbook, race_cid, s_daily_code='', e_daily_code=''):
    """
    新增信息
    :param workbook:
    :param race_cid:
    :param s_daily_code:
    :param e_daily_code:
    :return:
    """
    match = MatchStage({'race_cid': race_cid})
    if s_daily_code and e_daily_code:
        match['daily_code'] = {'$gte': s_daily_code, '$lte': e_daily_code}
    group = GroupStage(
        {
            'daily_code': '$daily_code',
            'race_cid': '$race_cid'
        },
        enter_times={'$sum': '$enter_times'},
        draw_red_packet_count={'$sum': '$draw_red_packet_count'},
        draw_red_packet_amount={'$sum': '$draw_red_packet_amount'},
        new_user_count={'$sum': '$is_new_user'})
    sort = SortStage([('_id.daily_code', ASC)])
    total_user_count = 0
    total_enter_times = 0
    total_draw_red_packet_count = 0
    total_draw_red_packet_amount = 0
    exported_member_list = MemberStatisticInfo.sync_aggregate(
        [match, group, sort]).to_list(None)

    sheet = workbook.add_worksheet("新增信息")
    sheet.merge_range(0, 0, 0, 1, '日期')
    sheet.merge_range(0, 2, 0, 3, '新增会员数')
    sheet.merge_range(0, 4, 0, 5, '新增答题次数')
    sheet.merge_range(0, 6, 0, 7, '新增红包领取数')
    sheet.merge_range(0, 8, 0, 9, '新增红包领取金额')
    sheet.merge_range(0, 10, 0, 11, '总会员数')
    sheet.merge_range(0, 12, 0, 13, '总答题次数')
    sheet.merge_range(0, 14, 0, 15, '总红包领取数')
    sheet.merge_range(0, 16, 0, 17, '总红包领取金额')
    for index, info in enumerate(exported_member_list):
        row = index + 1
        sheet.merge_range(row, 0, row, 1, info.id.get('daily_code'))
        sheet.merge_range(row, 2, row, 3, info.new_user_count)
        sheet.merge_range(row, 4, row, 5, info.enter_times)
        sheet.merge_range(row, 6, row, 7, info.draw_red_packet_count)
        sheet.merge_range(row, 8, row, 9, info.draw_red_packet_amount)
        total_user_count += info.new_user_count
        total_enter_times += info.enter_times
        total_draw_red_packet_count += info.draw_red_packet_count
        total_draw_red_packet_amount += info.draw_red_packet_amount
        sheet.merge_range(row, 10, row, 11, total_user_count)
        sheet.merge_range(row, 12, row, 13, total_enter_times)
        sheet.merge_range(row, 14, row, 15, total_draw_red_packet_count)
        sheet.merge_range(row, 16, row, 17, total_draw_red_packet_amount)
Exemple #7
0
def test2(race_cid):
    total = MemberStatisticInfo.sync_count({
        'race_cid': race_cid,
        'is_new_user': 1
    })
    cursor = MemberStatisticInfo.sync_aggregate([
        MatchStage({
            'race_cid': race_cid,
            'is_new_user': 1
        }),
        GroupStage('member_cid', count={'$sum': 1}),
        MatchStage({'count': {
            '$gt': 1
        }})
    ])
    for stat in cursor:
        print(stat.id, stat.count)
        cursor1 = MemberStatisticInfo.sync_find({'member_cid': stat.id})
        for s in cursor1:
            print(s.daily_code, s.is_new_user, s.is_special_user)
    print(total)
def is_final_pass(info: MemberStatisticInfo):
    """
    判断该用户是否通关
    :param info:
    :return:
    """
    race_cid = info.race_cid
    member_cid = info.member_cid

    last_check_point_cid = get_last_check_point_cid(race_cid)
    # 当前关卡不是最后一关,则未通关
    if info.check_point_cid != last_check_point_cid:
        info.is_final_passed = 0
    else:
        # 如果答题历史表中有最后一关答题记录且答题成功,则通关
        record = MemberCheckPointHistory.sync_find_one(
            {'member_cid': member_cid, 'check_point_cid': last_check_point_cid,
             'status': 1})
        if record:
            info.is_final_passed = 1
        else:
            info.is_final_passed = 0
def deal_member_without_history(race_cid, daily_code):
    """
    处理报名活动但未答题的会员
    :param race_cid:
    :param daily_code:
    :return:
    """
    city_name_list, district_name_list = get_address(race_cid)
    checkpoint_cid, _checkpoint_map = get_checkpoint_cid_list(race_cid)
    start_date = str2datetime(daily_code, '%Y%m%d').replace(hour=0,
                                                            minute=0,
                                                            second=0,
                                                            microsecond=0)
    end_date = start_date + datetime.timedelta(days=1)

    member_cid_with_history = MemberCheckPointHistory.sync_distinct(
        "member_cid", {
            'check_point_cid': {
                '$in': checkpoint_cid
            },
            'created_dt': {
                '$gte': start_date,
                '$lt': end_date
            }
        })
    race_member_match = MatchStage({
        "race_cid": race_cid,
        'member_cid': {
            '$nin': member_cid_with_history
        },
        'auth_address.city': {
            "$in": city_name_list
        },
        'auth_address.district': {
            "$in": district_name_list
        },
        'created_dt': {
            '$gte': start_date,
            '$lt': end_date
        }
    })
    member_group = GroupStage({'member_cid': '$member_cid'},
                              auth_address={'$first': '$auth_address'},
                              company_cid={'$first': '$company_cid'},
                              mobile={'$first': '$mobile'},
                              created_dt={'$first': '$created_dt'})
    member_project = ProjectStage(
        **{
            'cid': '$cid',
            'member_cid': '$_id.member_cid',
            'auth_address': '$auth_address',
            'mobile': '$mobile',
            'created_dt': '$created_dt',
            'company_cid': '$company_cid'
        })
    member_without_history = RaceMapping.sync_aggregate(
        [race_member_match, member_group, member_project]).batch_size(4)
    member_amount_map = get_red_packet_info(race_cid, start_date, end_date)

    red_member_cid_list = member_amount_map.keys()
    member_no_history_list = []
    count = 0
    while True:
        try:
            stat = member_without_history.next()
            count += 1
            if stat.member_cid in red_member_cid_list:
                continue
            # 根据member_cid查对应的member信息
            temp_member = Member.sync_get_by_cid(stat.member_cid)
            if not temp_member:
                print("no history未找到对应member_cid:%s" % stat.member_cid)
                continue
            info_special = MemberStatisticInfo()
            info_special.is_special_user = 1
            info_special.race_cid = race_cid
            info_special.member_cid = stat.member_cid
            info_special.daily_code = format(stat.created_dt, '%Y%m%d')
            info_special.nick_name = temp_member.nick_name
            info_special.open_id = temp_member.open_id
            if stat.mobile:
                info_special.mobile = stat.mobile
            else:
                info_special.mobile = temp_member.mobile
            info_special.first_time_login = temp_member.created_dt
            info_special.enter_times = 1
            info_special.answer_times = 0
            info_special.true_answer_times = 0
            info_special.is_final_passed = 0
            info_special.is_new_user = 1
            info_special.grant_red_packet_amount = 0.0
            info_special.grant_red_packet_count = 0
            info_special.draw_red_packet_count = 0
            info_special.draw_red_packet_amount = 0.0

            info_special.province = stat.auth_address.get('province')
            info_special.city = stat.auth_address.get('city')
            info_special.district = stat.auth_address.get('district')
            info_special.town = stat.auth_address.get('town')
            info_special.check_point_cid = stat.race_check_point_cid
            if stat.race_check_point_cid:
                info_special.check_point_index = _checkpoint_map[
                    stat.race_check_point_cid]
            else:
                info_special.check_point_index = 1
            if stat.company_cid:
                company = Company.sync_get_by_cid(stat.company_cid)
                info_special.company_cid = company.cid
                info_special.company_name = company.title

            member_no_history_list.append(info_special)
            # logger.info("Success without history: member_cid:%s is_final_Pass:%s" % (info_special.member_cid,info_special.is_final_passed))
            if len(member_no_history_list) % 500 == 0:
                MemberStatisticInfo.sync_insert_many(member_no_history_list)
                member_no_history_list = []
        except StopIteration:
            break
        except CursorNotFound:
            member_without_history = RaceMapping.sync_aggregate(
                [race_member_match, member_group,
                 member_project]).skip(count).batch_size(4)
        except Exception as e:
            logger.info(
                "Fail: without history daily_code:%s,member_cid:%s,race_cid: %s"
                % (info_special.daily_code, info_special.member_cid, race_cid))
    if len(member_no_history_list) > 0:
        MemberStatisticInfo.sync_insert_many(member_no_history_list)
def daily_member_statistic(race_cid, daily_code):
    """
    统计每日活动下的会员
    :param race_cid:
    :param daily_code:
    :return:
    """
    start_date = str2datetime(daily_code, '%Y%m%d').replace(hour=0,
                                                            minute=0,
                                                            second=0,
                                                            microsecond=0)
    end_date = start_date + datetime.timedelta(days=1)
    check_point_cids, _checkpoint_map = get_checkpoint_cid_list(race_cid)

    # 当日答题记录
    history_match = MatchStage({
        'created_dt': {
            '$gte': start_date,
            '$lt': end_date
        },
        'check_point_cid': {
            '$in': check_point_cids
        }
    })
    history_group = GroupStage({'member_cid': '$member_cid'},
                               enter_times={'$sum': 1},
                               results_list={'$push': '$result'})
    history_project = ProjectStage(
        **{
            'member_cid': '$_id.member_cid',
            'results_list': '$results_list',
            'enter_times': '$enter_times'
        })

    # 红包信息
    member_amount_map = get_red_packet_info(race_cid, start_date, end_date)
    # member_cid: amount

    check_point_history_cursor = MemberCheckPointHistory.sync_aggregate(
        [history_match, history_group, history_project],
        allowDiskUse=True).batch_size(4)
    member_statistic_list = []
    count = 0
    while True:
        try:
            cursor = check_point_history_cursor.next()
            count += 1
            # 根据member_cid查对应的member信息
            temp_member = Member.sync_get_by_cid(cursor.member_cid)
            if not temp_member:
                print("normal未找到对应member_cid:%s" % cursor.member_cid)
                continue
            info = MemberStatisticInfo()
            info.daily_code = daily_code
            info.race_cid = race_cid
            # 会员信息
            info.member_cid = cursor.member_cid
            info.nick_name = temp_member.nick_name
            info.open_id = temp_member.open_id
            info.mobile = temp_member.mobile
            info.first_time_login = temp_member.created_dt
            info.enter_times = cursor.enter_times
            # 答题数量、正确数
            for results in cursor.results_list:
                info.answer_times += len(results)
                info.true_answer_times += len([
                    result for result in results if result.get('true_answer')
                ])

            # race_mapping相关信息,地理位置
            has_race_mapping = get_race_mapping_info(info)
            if not has_race_mapping:
                print("normal未找到对应race_mapping,race_cid:%s,member_cid:%s" %
                      (info.race_cid, info.member_cid))
                continue
            # 是否为当日新用户
            is_new_user(info)
            # 最后一关
            is_final_pass(info)

            # 红包信息
            try:
                value = member_amount_map.pop(info.member_cid)
            except KeyError:
                value = None

            if not value:
                value = {
                    'grant_count': 0,
                    'grant_amount': 0,
                    'draw_count': 0,
                    'draw_amount': 0
                }

            info.grant_red_packet_amount = value.get('grant_amount')
            info.grant_red_packet_count = value.get('grant_count')
            info.draw_red_packet_amount = value.get('draw_amount')
            info.draw_red_packet_count = value.get('draw_count')

            # 保存记录
            member_statistic_list.append(info)
            # logger.info("Success: member_cid:%s is_final_Pass:%s is_new:%s" % (
            #     info.member_cid, info.is_final_passed, info.is_new_user))
            print("Success: member_cid:%s is_final_Pass:%s is_new:%s" %
                  (info.member_cid, info.is_final_passed, info.is_new_user))
            if len(member_statistic_list) % 500 == 0:
                MemberStatisticInfo.sync_insert_many(member_statistic_list)
                member_statistic_list = []
        except StopIteration:
            break
        except CursorNotFound:
            check_point_history_cursor = MemberCheckPointHistory.sync_aggregate(
                [history_match, history_group,
                 history_project]).skip(count).batch_size(4)
        except Exception as e:
            logger.error(e)
            logger.info("Fail: daily_code:%s,race_cid: %s" %
                        (daily_code, race_cid))
            member_statistic_list = []

    member_statistic_list += insert_from_member_amount_map(
        member_amount_map, daily_code, race_cid)
    if len(member_statistic_list) > 0:
        MemberStatisticInfo.sync_insert_many(member_statistic_list)
def insert_from_member_amount_map(member_amount_map: dict, daily_code,
                                  race_cid):
    """

    :param member_amount_map:
    :param daily_code:
    :return:
    """
    if not member_amount_map:
        return []

    ret_list = []
    for member_cid, value in member_amount_map.items():
        temp_member = Member.sync_get_by_cid(member_cid)
        if not temp_member:
            print("RedPacket未找到对应member_cid:%s" % member_cid)
            continue
        info = MemberStatisticInfo()
        info.daily_code = daily_code
        info.race_cid = race_cid
        # 会员信息
        info.member_cid = member_cid
        info.nick_name = temp_member.nick_name
        info.open_id = temp_member.open_id
        info.mobile = temp_member.mobile
        info.first_time_login = temp_member.created_dt

        # race_mapping相关信息,地理位置
        has_race_mapping = get_race_mapping_info(info)
        if not has_race_mapping:
            print("RedPacket未找到对应race_mapping,race_cid:%s,member_cid:%s" %
                  (info.race_cid, info.member_cid))
            continue

        # 是否为当日新用户
        is_new_user(info)
        # 最后一关
        is_final_pass(info)

        info.grant_red_packet_amount = value.get('grant_amount')
        info.grant_red_packet_count = value.get('grant_count')
        info.draw_red_packet_amount = value.get('draw_amount')
        info.draw_red_packet_count = value.get('draw_count')
        print("Success: member_cid:%s is_final_Pass:%s is_new:%s" %
              (info.member_cid, info.is_final_passed, info.is_new_user))
        ret_list.append(info)

    return ret_list
Exemple #12
0
def export_member_to_excel(workbook,
                           race_cid,
                           s_daily_code=None,
                           e_daily_code=None):
    """
    会员信息导入
    :param workbook:
    :param race_cid:
    :param s_daily_code:
    :param e_daily_code:
    :return:
    """
    match = MatchStage({'race_cid': race_cid})
    if s_daily_code and e_daily_code:
        match['daily_code'] = {'$gte': s_daily_code, '$lte': e_daily_code}
    group = GroupStage(
        {
            'member_cid': '$member_cid',
            'race_cid': '$race_cid'
        },
        nick_name={'$first': '$nick_name'},
        open_id={'$first': '$open_id'},
        province={'$first': '$province'},
        city={'$first': '$city'},
        district={'$first': '$district'},
        mobile={'$first': '$mobile'},
        check_point_index={'$max': '$check_point_index'},
        is_final_passed={'$max': '$is_final_passed'},
        first_time_login={'$first': '$first_time_login'},
        enter_times={'$sum': '$enter_times'},
        draw_red_packet_count={'$sum': '$draw_red_packet_count'},
        draw_red_packet_amount={'$sum': '$draw_red_packet_amount'},
    )
    sort_stage = SortStage([('first_time_login', ASC)])
    exported_member_list = MemberStatisticInfo.sync_aggregate(
        [match, group, sort_stage], allowDiskUse=True).to_list(None)
    sheet = workbook.add_worksheet("会员信息")
    sheet.merge_range(0, 0, 0, 1, '昵称')
    sheet.merge_range(0, 2, 0, 3, 'open_id')
    sheet.merge_range(0, 4, 0, 5, '城市')
    sheet.merge_range(0, 6, 0, 7, '区县')
    sheet.merge_range(0, 8, 0, 9, '手机号码')
    sheet.merge_range(0, 10, 0, 11, '答题次数')
    sheet.merge_range(0, 12, 0, 13, '当前关卡数')
    sheet.merge_range(0, 14, 0, 15, '第一次进入小程序时间')
    sheet.merge_range(0, 16, 0, 17, '领取红包数')
    sheet.merge_range(0, 18, 0, 19, '领取红包金额')

    for index, member_info in enumerate(exported_member_list):
        row = index + 1
        sheet.merge_range(row, 0, row, 1, member_info.nick_name)
        sheet.merge_range(row, 2, row, 3, member_info.open_id)
        sheet.merge_range(row, 4, row, 5, member_info.city)
        sheet.merge_range(row, 6, row, 7, member_info.district)
        sheet.merge_range(row, 8, row, 9,
                          member_info.mobile if member_info.mobile else '')
        sheet.merge_range(row, 10, row, 11, member_info.enter_times)
        if member_info.is_final_passed == 1:
            sheet.merge_range(row, 12, row, 13, '已通关')
        else:
            sheet.merge_range(row, 12, row, 13,
                              str(member_info.check_point_index))
        sheet.merge_range(row, 14, row, 15,
                          member_info.first_time_login.strftime("%Y-%m-%d"))
        sheet.merge_range(row, 16, row, 17, member_info.draw_red_packet_count)
        sheet.merge_range(row, 18, row, 19, member_info.draw_red_packet_amount)
def generate_race_middle(race_cid: str, start):
    """
    生成中间表
    :return:
    """
    if not isinstance(race_cid, str):
        raise ValueError("race_cid is not str")
    prov_match = MatchStage({'province': {'$ne': None}})
    race = Race.sync_get_by_cid(race_cid)
    #  市级活动,如六安市,扬州市
    if race.city_code:
        city_code_list = AdministrativeDivision.sync_distinct('code', {'code': race.city_code})
        #  该活动的所属城市范围
        city_name_list = AdministrativeDivision.sync_distinct('title', {'code': race.city_code})
    else:
        prov = AdministrativeDivision.sync_find_one({'code': race.province_code})
        city_code_list = AdministrativeDivision.sync_distinct('code', {'parent_code': race.province_code})
        city_name_list = AdministrativeDivision.sync_distinct('title', {'parent_code': race.province_code})
        prov_match = MatchStage({'province': prov.title})
    dist_list = []
    for city_code in city_code_list:
        #  该活动区县的范围
        dist_list += AdministrativeDivision.sync_distinct('title', {'parent_code': city_code})
    lookup_stage = LookupStage(Member, 'member_cid', 'cid', 'member_list')
    has_town_match = {'race_cid': race_cid, 'city': {'$in': city_name_list}, 'district': {'$in': dist_list},
                      'member_cid': {'$ne': None}, 'town': {'$ne': None}}

    no_town_match = {'race_cid': race_cid, 'city': {'$in': city_name_list}, 'district': {'$in': dist_list},
                     'member_cid': {'$ne': None}, 'town': {'$eq': None}}
    if start != "total":
        start_time = transform_time_format(start)
        end_time = transform_time_format(start + datetime.timedelta(days=1))
        has_town_match['daily_code'] = {'$gte': start_time, '$lt': end_time}
        no_town_match['daily_code'] = {'$gte': start_time, '$lt': end_time}
    cursor = MemberStatisticInfo.sync_aggregate(
        [
            MatchStage(has_town_match),
            lookup_stage,
            prov_match,
            MatchStage({'member_list': {'$ne': []}}),
            GroupStage(
                {"daily_code": "$daily_code", 'district': '$district', 'city': '$city', 'town': '$town'},
                province={"$first": "$province"}, town={"$last": "$town"},
                status_list={'$push': '$is_new_user'}, pass_status_list={'$push': '$is_final_passed'},
                enter_times={'$sum': "$enter_times"}, count_sum={'$sum': "$grant_red_packet_count"},
                amount_sum={'$sum': "$grant_red_packet_amount"},
                receive_count_sum={'$sum': "$draw_red_packet_count"},
                receive_amount_sum={'$sum': "$draw_red_packet_amount"},
                answer_times={'$sum': '$answer_times'},
                true_answer_times={'$sum': '$true_answer_times'},
                sum={'$sum': 1}),
        ]
    )
    no_town_cursor = MemberStatisticInfo.sync_aggregate(
        [
            MatchStage(no_town_match),
            lookup_stage,
            prov_match,
            MatchStage({'member_list': {'$ne': []}}),
            GroupStage(
                {"daily_code": "$daily_code", 'district': '$district', 'city': '$city'},
                province={"$first": "$province"}, town={"$last": "$town"},
                status_list={'$push': '$is_new_user'}, pass_status_list={'$push': '$is_final_passed'},
                enter_times={'$sum': "$enter_times"}, count_sum={'$sum': "$grant_red_packet_count"},
                amount_sum={'$sum': "$grant_red_packet_amount"},
                receive_count_sum={'$sum': "$draw_red_packet_count"},
                receive_amount_sum={'$sum': "$draw_red_packet_amount"},
                answer_times={'$sum': '$answer_times'},
                true_answer_times={'$sum': '$true_answer_times'},
                sum={'$sum': 1}),
        ]
    )
    while True:
        try:
            race_member_info = cursor.next()
            daily_code = race_member_info.id.get('daily_code')
            status_list = race_member_info.status_list
            pass_status_list = race_member_info.pass_status_list
            district = race_member_info.id.get('district')
            city = race_member_info.id.get('city')
            if district and city:
                race_enter_info = RaceMemberEnterInfoStatistic(daily_code=daily_code, race_cid=race_cid)
                race_enter_info.province = race_member_info.province
                race_enter_info.city = city
                race_enter_info.district = district
                race_enter_info.town = race_member_info.town
                race_enter_info.company_cid = race_member_info.company_cid if race_member_info.company_cid else None
                race_enter_info.company_name = race_member_info.company_name if race_member_info.company_name else None
                race_enter_info.increase_enter_count = status_list.count(1)  # 每日新增
                race_enter_info.enter_count = race_member_info.sum  # 每日参与
                race_enter_info.pass_count = pass_status_list.count(1)  # 每日通关人数
                race_enter_info.enter_times = race_member_info.enter_times  # 每日参与次数
                race_enter_info.grant_red_packet_count = race_member_info.count_sum  # 红包发放数量
                race_enter_info.grant_red_packet_amount = race_member_info.amount_sum  # 红包发放金额
                race_enter_info.draw_red_packet_count = race_member_info.receive_count_sum  # 红包领取数量
                race_enter_info.draw_red_packet_amount = race_member_info.receive_amount_sum  # 红包领取金额
                race_enter_info.correct_percent = round(
                    race_member_info.true_answer_times / race_member_info.answer_times,
                    2) if race_member_info.answer_times != 0 else 0
                race_enter_info.answer_times = race_member_info.answer_times  # 总答题数量
                race_enter_info.true_answer_times = race_member_info.true_answer_times  # 总答对题目数量
                race_enter_info.sync_save()
            else:
                continue
        except StopIteration:
            break
        except Exception as e:
            raise e

    while True:
        try:
            race_member_info = no_town_cursor.next()
            daily_code = race_member_info.id.get('daily_code')
            status_list = race_member_info.status_list
            pass_status_list = race_member_info.pass_status_list
            district = race_member_info.id.get('district')
            city = race_member_info.id.get('city')
            if district and city:
                race_enter_info = RaceMemberEnterInfoStatistic(daily_code=daily_code, race_cid=race_cid)
                race_enter_info.province = race_member_info.province
                race_enter_info.city = city
                race_enter_info.district = district
                race_enter_info.company_cid = race_member_info.company_cid if race_member_info.company_cid else None
                race_enter_info.company_name = race_member_info.company_name if race_member_info.company_name else None
                race_enter_info.increase_enter_count = status_list.count(1)  # 每日新增
                race_enter_info.enter_count = race_member_info.sum  # 每日参与
                race_enter_info.pass_count = pass_status_list.count(1)  # 每日通关人数
                race_enter_info.enter_times = race_member_info.enter_times  # 每日参与次数
                race_enter_info.grant_red_packet_count = race_member_info.count_sum  # 红包发放数量
                race_enter_info.grant_red_packet_amount = race_member_info.amount_sum  # 红包发放金额
                race_enter_info.draw_red_packet_count = race_member_info.receive_count_sum  # 红包领取数量
                race_enter_info.draw_red_packet_amount = race_member_info.receive_amount_sum  # 红包领取金额
                race_enter_info.correct_percent = round(
                    race_member_info.true_answer_times / race_member_info.answer_times,
                    2) if race_member_info.answer_times != 0 else 0  # 正确率
                race_enter_info.answer_times = race_member_info.answer_times  # 总答题数量
                race_enter_info.true_answer_times = race_member_info.true_answer_times  # 总答对题目数量
                race_enter_info.sync_save()
            else:
                continue
        except StopIteration:
            break
        except Exception as e:
            raise e