def do_merge_city_stat_member_time(province_dict: dict, city_code_list=None): """ 合并省份统计信息 :param province_dict: :param city_code_list :return: """ query_dict = {} if province_dict: query_dict['province_code'] = {'$in': [code for code in province_dict.keys()]} if city_code_list: query_dict['city_code'] = {'$in': city_code_list} else: query_dict['city_code'] = {'$ne': None} # 取前一天凌晨12点之前的数据 time_match = get_yesterday() query_dict['updated_dt'] = {'$lt': time_match} match_stage = MatchStage(query_dict) group_stage = GroupStage('city_code', quantity={'$sum': '$learn_times'}, province_code={'$first': '$province_code'}) sort_stage = SortStage([('quantity', DESC)]) p_lookup_stage = LookupStage(AdministrativeDivision, 'province_code', 'post_code', 'province_list') c_lookup_stage = LookupStage(AdministrativeDivision, '_id', 'post_code', 'city_list') city_cursor = MemberLearningDayStatistics.sync_aggregate( [match_stage, group_stage, sort_stage, p_lookup_stage, c_lookup_stage]) t_province_dict = {} t_province_dict = get_merge_city_data(city_cursor, province_dict, t_province_dict) if t_province_dict: province_dict.update(t_province_dict)
def do_merge_city_stat_member_quantity(province_dict: dict, choice_time, city_code_list=None): """ 合并省份统计信息 :param province_dict: :param city_code_list :param choice_time :return: """ query_dict = {} if province_dict: query_dict['province_code'] = {'$in': [code for code in province_dict.keys()]} if city_code_list: query_dict['city_code'] = {'$in': city_code_list} else: query_dict['city_code'] = {'$ne': None} if not choice_time: # 取前一天凌晨12点之前的数据 yesterday = get_yesterday() query_dict['updated_dt'] = {'$lt': yesterday} else: # 当天下一天凌晨的时候 max_choice_time = choice_time.replace(hour=23, minute=59, second=59, microsecond=999) query_dict['updated_dt'] = {'$gte': choice_time, '$lt': max_choice_time} query_dict['status'] = STATUS_USER_ACTIVE match_stage = MatchStage(query_dict) group_stage = GroupStage('city_code', quantity={'$sum': 1}, province_code={'$first': '$province_code'}) sort_stage = SortStage([('quantity', DESC)]) p_lookup_stage = LookupStage(AdministrativeDivision, 'province_code', 'post_code', 'province_list') c_lookup_stage = LookupStage(AdministrativeDivision, '_id', 'post_code', 'city_list') city_cursor = Member.sync_aggregate([match_stage, group_stage, sort_stage, p_lookup_stage, c_lookup_stage]) t_province_dict = {} t_province_dict = get_merge_city_data(city_cursor, province_dict, t_province_dict) if t_province_dict: province_dict.update(t_province_dict)
def do_statistics_member_quantity(cache_key, city_code_list, choice_time): """开始统计 :param cache_key: :param city_code_list: :param choice_time :return: """ RedisCache.set(cache_key, KEY_CACHE_REPORT_DOING_NOW, 5 * 60) stage_list = [] if city_code_list: stage_list.append(MatchStage({'city_code': {'$in': city_code_list}})) if not choice_time: # 取前一天凌晨12点之前的数据 yesterday_time = get_yesterday() time_match = MatchStage({'updated_dt': {'$lt': yesterday_time}}) else: # 当天下一天凌晨的时候 max_choice_time = choice_time.replace(hour=23, minute=59, second=59, microsecond=999) time_match = MatchStage({'updated_dt': {'$gte': choice_time, '$lt': max_choice_time}}) stage_list.append(time_match) stage_list.append(MatchStage({'status': STATUS_USER_ACTIVE})) group_stage = GroupStage('province_code', quantity={'$sum': 1}) lookup_stage = LookupStage(AdministrativeDivision, '_id', 'post_code', 'ad_list') sort_stage = SortStage([('quantity', DESC)]) stage_list += [group_stage, lookup_stage, sort_stage] province_cursor = Member.sync_aggregate(stage_list) province_dict = {} while True: try: province_stat = province_cursor.next() if province_stat: province_code = province_stat.id if province_stat.id else '000000' quantity = province_stat.quantity title = 'undefined' ad_list = province_stat.ad_list if ad_list: ad: FacadeO = ad_list[0] if ad: title = ad.title.replace('省', '').replace('市', '') province_dict[province_code] = { 'code': province_code, 'title': title, 'data': quantity } except StopIteration: break # 合并城市统计信息 do_merge_city_stat_member_quantity(province_dict, choice_time, city_code_list) data = [v for v in province_dict.values()] if not data: early_warning_empty("start_statistics_member_quantity", cache_key, city_code_list, '学习近况中人数数据为空,请检查!') RedisCache.set(cache_key, msgpack.packb(data))
def do_stat_in_history(history_model, city_code_list, choice_time, ad_map={}): """ :param history_model: :param city_code_list: :param ad_map: :param choice_time :return: """ # 取前一天凌晨12点之前的数据 time_match = get_yesterday() if not choice_time: match_stage = MatchStage({'updated_dt': {'$lt': time_match}}) else: # 当天下一天凌晨的时候 max_choice_time = choice_time.replace(hour=23, minute=59, second=59, microsecond=999) match_stage = MatchStage({'updated_dt': {'$gte': choice_time, '$lt': max_choice_time}}) cursor = history_model.sync_aggregate([ match_stage, GroupStage('member_cid', quantity={"$sum": 1}), LookupStage(Member, '_id', 'cid', 'member_list'), ProjectStage(**{ 'province_code': {'$arrayElemAt': ['$member_list.province_code', 0]}, 'city_code': {'$arrayElemAt': ['$member_list.city_code', 0]}, 'quantity': '$quantity' }), MatchStage({'city_code': {'$in': city_code_list}}), GroupStage('city_code', quantity={'$sum': "$quantity"}, province_code={'$first': '$province_code'}), SortStage([('quantity', DESC)]) ]) data = {} while True: try: his = cursor.next() city_data = data.get(his.province_code, {}) city = ad_map.get(his.id) if not city: city = AdministrativeDivision.sync_find_one({'code': his.id, 'parent_code': {'$ne': None}}) ad_map[city.code] = city city_data[city.title] = his.quantity data[his.province_code] = city_data except StopIteration: break except Exception as e: logger.error(str(e)) continue return data, ad_map
async def post(self): """ :return: """ time = datetime.datetime.now() export_time = datetime2str(time, date_format='%Y-%m-%d %H:%M:%S') order = self.get_argument('order', '') chart_name = self.get_argument('chart_name', '') # 答题活跃度的数据 data_dict = self.get_argument('data', '') data_list = [] condition_title_list = [] # 没有筛选条件的总体活跃度 if data_dict: data_dict = json.loads(data_dict) condition_title_list = list(data_dict.keys()) data_list = list(data_dict.values()) # 有筛选条件的数据 if '总体活跃度' in condition_title_list: position = condition_title_list.index('总体活跃度') else: position = data_list.index(max(sum(data_list))) if len(data_list) > position: condition_title_list.remove(condition_title_list[position]) # 可管理的省份名称 manage_region_title_list = [] manage_region_code_list = self.current_user.manage_region_code_list if manage_region_code_list: for manage_region_code in manage_region_code_list: manage_region_province = await AdministrativeDivision.find_one( { 'code': manage_region_code, 'record_flag': 1, 'parent_code': None }) if manage_region_province: manage_region_title_list.append( manage_region_province.title) else: manage_region_city = await AdministrativeDivision.find_one( { 'code': manage_region_code, 'record_flag': 1 }) province = await manage_region_city.parent manage_region_title_list.append(province.title) try: output = BytesIO() workbook = Workbook(output, {'in_memory': True}) title_format = workbook.add_format({ 'font_size': 12, 'bold': '1', 'valign': 'vcenter', 'align': 'center', 'font_name': 'Microsoft YaHei', 'border': 1 }) data_format = workbook.add_format({ 'valign': 'vcenter', 'align': 'left', 'font_name': 'Microsoft YaHei', 'border': 1 }) data_center_format = workbook.add_format({ 'valign': 'vcenter', 'align': 'center', 'font_name': 'Microsoft YaHei', 'border': 1 }) if order == "1" and chart_name: pass # 公民科学素质学习答题趋势统计 if order == '2' and chart_name: answer_tendency_date = self.get_argument( 'answer_tendency_date', '') answer_tendency_data = self.get_argument( 'answer_tendency_data', '') answer_tendency_data = json.loads(answer_tendency_data) answer_tendency_date = json.loads(answer_tendency_date) answer_tendency_date = deal_with_data(answer_tendency_date) if answer_tendency_date and answer_tendency_data: worksheet = workbook.add_worksheet(name=chart_name) worksheet.merge_range(1, 2, 1, 5, '导出时间' + export_time, cell_format=title_format) worksheet.merge_range(0, 0, 0, 2, chart_name, cell_format=title_format) worksheet.merge_range(1, 0, 1, 1, '筛选条件', cell_format=title_format) worksheet.merge_range(2, 0, 3, 1, '总体答题次数', cell_format=title_format) worksheet.write_string(2, 2, '日期', cell_format=data_format) worksheet.write_string(3, 2, '答题次数', cell_format=data_format) answer_tendency_title = list(answer_tendency_data.keys()) answer_data_list = list(answer_tendency_data.values()) # 有筛选条件的数据 if '总体答题次数' in answer_tendency_title: position = answer_tendency_title.index('总体答题次数') else: position = answer_data_list.index( max(sum(answer_data_list))) if len(answer_data_list) > position: answer_tendency_title.remove( answer_tendency_title[position]) for index, date in enumerate(answer_tendency_date): worksheet.write_string(2, 3 + index, date) if '总体答题次数' in list(answer_tendency_data.keys()): worksheet.write_string( 3, 3 + index, str(answer_tendency_data['总体答题次数'][index]), cell_format=data_center_format) else: max_data_list = max(sum(answer_data_list)) worksheet.write_string( 3, 2 + order, max_data_list[index - 1], cell_format=data_center_format) if answer_tendency_title: # 有筛选条件得数据写入到excel for index, condition_title in enumerate( answer_tendency_title): worksheet.merge_range(2 * (index + 2) + index + 1, 0, 2 * (index + 2) + 2 + index, 1, condition_title, cell_format=title_format) worksheet.write_string(2 * (index + 2) + index + 1, 2, '日期', cell_format=data_format) worksheet.write_string(2 * (index + 2) + index + 2, 2, '答题次数', cell_format=data_format) for condition_index, data in enumerate( answer_tendency_data[condition_title]): worksheet.write_string(2 * (index + 2) + index + 2, 2 + condition_index + 1, str(data), cell_format=data_format) worksheet.write_string( 2 * (index + 2) + index + 1, 2 + condition_index + 1, answer_tendency_date[condition_index], cell_format=data_format) if order == '3' and chart_name and data_dict: # 活跃度的导出excel worksheet = workbook.add_worksheet(name=chart_name) for order in range(1, 31): worksheet.write_string(2, 2 + order, str(order), cell_format=data_center_format) if '总体活跃度' in list(data_dict.keys()): worksheet.write_string(3, 2 + order, data_dict['总体活跃度'][order - 1] + '%', cell_format=data_center_format) else: max_data_list = max(sum(data_list)) worksheet.write_string(3, 2 + order, max_data_list[order - 1] + '%', cell_format=data_center_format) worksheet.merge_range(1, 2, 1, 5, '导出时间' + export_time, cell_format=title_format) worksheet.merge_range(0, 0, 0, 2, chart_name, cell_format=title_format) worksheet.merge_range(1, 0, 1, 1, '筛选条件', cell_format=title_format) worksheet.merge_range(2, 0, 3, 1, '总体活跃度(%)', cell_format=title_format) worksheet.write_string(2, 2, '活跃天数', cell_format=data_format) worksheet.write_string(3, 2, '活跃度(%)', cell_format=data_format) if condition_title_list: # 有筛选条件得数据写入到excel for index, condition_title in enumerate( condition_title_list): worksheet.merge_range(2 * (index + 2) + index + 1, 0, 2 * (index + 2) + 2 + index, 1, condition_title, cell_format=title_format) worksheet.write_string(2 * (index + 2) + index + 1, 2, '活跃天数', cell_format=data_format) for order in range(1, 31): worksheet.write_string(2 * (index + 2) + index + 1, 2 + order, str(order), cell_format=data_format) worksheet.write_string(2 * (index + 2) + index + 2, 2, '活跃度(%)', cell_format=data_format) for condition_index, data in enumerate( data_dict[condition_title]): worksheet.write_string(2 * (index + 2) + index + 2, 2 + condition_index + 1, data, cell_format=data_format) # 每日参与top5的导出数据 if order == '4' and chart_name: # 每日参与top_5的数据 stat_category = self.get_argument('stat_category', '') top_five_data_list = self.get_argument('top_five_data', '') if top_five_data_list: top_five_data_list = json.loads(top_five_data_list) date_list = self.get_argument('date', '') if date_list: date_list = json.loads(date_list) date_list = deal_with_data(date_list) if stat_category and top_five_data_list and date_list: data_series_dict, province_and_city_dict = deal_with_data_excel( date_list, top_five_data_list) # {'江苏': ['南京', '苏州‘], '浙江':['杭州']} total_data_dict = {} # 某个省下面的所有的市 报表中有数据的市 city_title_list = [] # 报表中省的列表 province_title_list = [] # 省和市的列表 total_title = [] show_name_list = [] show_data_list = [] # 需要添加undefined的省份 need_append_undifend_province_list = [] for top_five_data in top_five_data_list: temple_data = [] temple_name = [] for index, data in enumerate(top_five_data): total_title.append(data['name']) if data['name'] and data['value']: temple_name.append( {date_list[index]: data['name']}) temple_data.append( {date_list[index]: data['value']}) show_name_list.append(temple_name) show_data_list.append(temple_data) total_title = [title for title in total_title if title] for total in total_title: if ' ' in total: province_title_list.append(total.split(' ')[0]) city_title_list.append(total.split(' ')[1]) if total.split(' ')[1] == 'undefined': need_append_undifend_province_list.append( total.split(' ')[0]) province_title_list = list(set(province_title_list)) city_title_list = list( set([city for city in city_title_list if city])) for province_title in province_title_list: total_data_dict[province_title] = city_title_list province = await AdministrativeDivision.find_one({ 'title': province_title, 'parent_code': None }) if province: belong_provice_city_title_list = await AdministrativeDivision.distinct( 'title', {'parent_code': province.code}) total_data_dict[province_title] = list( set(city_title_list) & set(belong_provice_city_title_list)) total_data_dict[province_title] = list( set(city_title_list) & set(belong_provice_city_title_list)) # 各个省的市的个数 length_list = [] for index, city_title in enumerate( list(total_data_dict.values())): if list(total_data_dict.keys() )[index] in need_append_undifend_province_list: total_data_dict.get( list(total_data_dict.keys())[index]).append( 'undefined') for index, city_title in enumerate( list(total_data_dict.values())): if city_title: length_list.append(len(city_title)) province_length = sum(length_list) + len( list(total_data_dict.values())) if province_length == 0: province_length = 10 worksheet = workbook.add_worksheet(name=chart_name + '(' + stat_category + ')') worksheet.merge_range(0, 0, province_length, 0, '每日参与' + stat_category, cell_format=data_format) worksheet.merge_range(1, 1, province_length, 1, '导出时间: ' + export_time, cell_format=data_format) worksheet.merge_range(0, 2, 0, 4, '日期', cell_format=data_center_format) for index, date in enumerate(date_list): worksheet.write_string(0, 5 + index, date, cell_format=data_format) worksheet.merge_range(1, 2, province_length, 2, '省份', cell_format=data_center_format) city_map = {} province_map = {} if total_data_dict: choice_city_title_list = list(total_data_dict.values()) for index, data in enumerate(choice_city_title_list): if index == 0: worksheet.merge_range( 1, 3, 1 + len(data), 3, list(total_data_dict.keys())[index], cell_format=data_center_format) else: worksheet.merge_range( 1 + sum(length_list[:index]) + index, 3, sum(length_list[:index + 1]) + index + 1, 3, list(total_data_dict.keys())[index], cell_format=data_center_format) if index == 0: for city_index, city in enumerate(data): if city == 'undefined': city = '_' worksheet.write_string( 1, 4, list(total_data_dict.keys())[index], cell_format=data_center_format) worksheet.write_string( 2 + city_index, 4, city, cell_format=data_center_format) worksheet.write_string( 1, 5, '6666', cell_format=data_format) city_map[city] = 2 + city_index province_map[list( total_data_dict.keys())[index]] = 1 Position(city, 2 + city_index, 4) Position( list(total_data_dict.keys())[index], 1, 4) else: for city_index, city in enumerate(data): if city == 'undefined': city = '_' worksheet.write_string( sum(length_list[:index]) + index + 1, 4, list(total_data_dict.keys())[index], cell_format=data_center_format) worksheet.write_string( sum(length_list[:index]) + index + 2 + city_index, 4, city, cell_format=data_center_format) city_map[city] = sum( length_list[:index] ) + 2 + index + city_index province_map[list( total_data_dict.keys())[index]] = sum( length_list[:index]) + index + 1 Position( city, sum(length_list[:index]) + 2 + index + city_index, 4) Position( list(total_data_dict.keys())[index], sum(length_list[:index]) + index + 1, 4) for index, data in enumerate(choice_city_title_list): if index == 0: for key, value in data_series_dict.items(): if key.split(' ')[0] == 'undefined': position = Position( key.split(' ')[0], city_map['_'], 4) else: position = Position( key.split(' ')[0], city_map[key.split(' ')[0]], 4) if position: order = date_list.index( key.split(' ')[1]) worksheet.write_number( position.row, 5 + order, int(value)) else: for key, value in data_series_dict.items(): if key.split(' ')[0] == 'undefined': position = Position( key.split(' ')[0], city_map['_'], 4) else: position = Position( key.split(' ')[0], city_map[key.split(' ')[0]], 4) if position: order = date_list.index( key.split(' ')[1]) worksheet.write_number( position.row, 5 + order, int(value)) for order, date in enumerate(date_list): for index, value in enumerate( list(province_map.values())): if index != len(list( province_map.values())) - 1: first = value + 2 end = list(province_map.values())[index + 1] else: first = list( province_map.values())[index] + 2 end = province_length + 1 col = 5 + order col = convert(col) first = col + str(first) end = col + str(end) worksheet.write_formula( value, 5 + order, '=SUM(' + first + ':' + end + ')') # 学习近况的导出数据 if order == '1' and chart_name: # 取前一天凌晨12点之前的数据 time_match = get_yesterday() time_match_stage = MatchStage( {'updated_dt': { '$lt': time_match }}) province_code_list, city_code_list, _ = await do_different_administrative_division2( self.current_user.manage_region_code_list) month_stage_list = [] member_stage_list = [] accuracy_stage_list = [] if province_code_list: month_stage_list.append( MatchStage( {'province_code': { '$in': province_code_list }})) member_stage_list.append( MatchStage( {'province_code': { '$in': province_code_list }})) accuracy_stage_list.append( MatchStage( {'province_code': { '$in': province_code_list }})) if city_code_list: month_stage_list.append( MatchStage({'city_code': { '$in': city_code_list }})) member_stage_list.append( MatchStage({'city_code': { '$in': city_code_list }})) accuracy_stage_list.append( MatchStage({'city_code': { '$in': city_code_list }})) add_fields_stage = AddFieldsStage( t_accuracy={ '$cond': { 'if': { '$eq': ['$t_total', 0] }, 'then': 0, 'else': { '$divide': ['$t_correct', '$t_total'] } } }) member_stage_list.append( MatchStage({'status': STATUS_USER_ACTIVE})) month_group_stage = GroupStage( { 'province_code': '$province_code', 'created_dt': { "$dateToString": { "format": "%Y-%m", "date": "$created_dt" } } }, sum={'$sum': '$learn_times'}) lookup_stage = LookupStage(AdministrativeDivision, '_id', 'post_code', 'ad_list') member_group_stage = GroupStage( { 'province_code': '$province_code', 'created_dt': { "$dateToString": { "format": "%Y-%m", "date": "$created_dt" } } }, sum={'$sum': 1}) accuracy_group_stage = GroupStage( { 'province_code': '$province_code', 'created_dt': { "$dateToString": { "format": "%Y-%m", "date": "$created_dt" } } }, t_total={'$sum': '$total'}, t_correct={'$sum': '$correct'}) group_stage = GroupStage('province_code', t_total={'$sum': '$total'}, t_correct={'$sum': '$correct'}) month_sort_stage = SortStage([('_id.created_dt', ASC)]) # 次数 month_stage_list.extend([ time_match_stage, month_group_stage, lookup_stage, month_sort_stage ]) # 人数 member_stage_list.extend([ time_match_stage, member_group_stage, lookup_stage, month_sort_stage ]) accuracy_province_stage_list = copy.deepcopy( accuracy_stage_list) accuracy_province_stage_list.extend([ time_match_stage, group_stage, lookup_stage, add_fields_stage, month_sort_stage ]) # 省和月份共同筛选的正确率 accuracy_stage_list.extend([ time_match_stage, accuracy_group_stage, lookup_stage, add_fields_stage, month_sort_stage ]) # 只有省的正确率 month_province_list = MemberLearningDayStatistics.aggregate( month_stage_list) member_province_list = Member.aggregate(member_stage_list) accuracy_province_list = MemberSubjectStatistics.aggregate( accuracy_stage_list) total_accuracy = MemberSubjectStatistics.aggregate( accuracy_province_stage_list) month_province_dict = {} member_province_dict = {} accuracy_province_dict = {} date_list = [] province_title_list = [] province_map = {} member_date_list = [] accuracy_date_list = [] # 次数 while await month_province_list.fetch_next: month_province = month_province_list.next_object() if month_province: province_dt = month_province.id if month_province.id else '000000' province = await AdministrativeDivision.find_one({ 'code': province_dt.get('province_code'), 'record_flag': 1, 'parent_code': None }) if province_dt.get('created_dt') not in date_list: date_list.append(province_dt.get('created_dt')) province_title = '' if province: province_title = province.title province_title_list.append(province_title) province_title_list = list(set(province_title_list)) dt = province_dt.get('created_dt') month_province_dict[province_title + ' ' + dt] = month_province.sum # 人数 while await member_province_list.fetch_next: member_province = member_province_list.next_object() if member_province: member_province_id = member_province.id if member_province.id else '' province = await AdministrativeDivision.find_one({ 'code': member_province_id.get('province_code'), 'record_flag': 1, 'parent_code': None }) province_title = '' if province: province_title = province.title dt = member_province_id.get('created_dt') if member_province_id.get( 'created_dt') not in member_date_list: member_date_list.append( member_province_id.get('created_dt')) member_province_dict[province_title + ' ' + dt] = member_province.sum # 正确率 while await accuracy_province_list.fetch_next: accuracy_province = accuracy_province_list.next_object() if accuracy_province: accuracy_province_id = accuracy_province.id if accuracy_province.id else '' province = await AdministrativeDivision.find_one({ 'code': accuracy_province_id.get('province_code'), 'record_flag': 1, 'parent_code': None }) province_title = '' if province: province_title = province.title dt = accuracy_province_id.get('created_dt') if accuracy_province_id.get( 'created_dt') not in accuracy_date_list: accuracy_date_list.append( accuracy_province_id.get('created_dt')) if accuracy_province.t_total == 0: accuracy_province_dict[province_title + ' ' + dt] = 0 else: accuracy_province_dict[ province_title + ' ' + dt] = (accuracy_province.t_correct / accuracy_province.t_total) * 100 province_dict = {} # 总的题目 total_quantity_list = [] # 总的答对题目 correct_quantity_list = [] # 总的正确率 while await total_accuracy.fetch_next: province_stat = total_accuracy.next_object() if province_stat: province_code = province_stat.id if province_stat.id else '000000' total = province_stat.t_total if province_stat.t_total else 0 correct = province_stat.t_correct if province_stat.t_correct else 0 province = await AdministrativeDivision.find_one({ 'code': province_code, 'record_flag': 1, 'parent_code': None }) province_title = '' if province: province_title = province.title province_dict[province_title] = round( correct / total * 100 if total > 0 else 0, 2) total_quantity_list.append(total) correct_quantity_list.append(correct) # 次数的sheet print(date_list) worksheet = workbook.add_worksheet(name='次数') worksheet.merge_range(0, 0, 0, len(date_list) + 1, '公民参与科学素质学习状况', cell_format=title_format) worksheet.write_string(1, 0, '已累计次数', cell_format=data_center_format) worksheet.merge_range(1, 2, 1, len(date_list) + 1, '导出时间:' + export_time, cell_format=data_center_format) worksheet.merge_range(2, 0, 3, 0, '省份', cell_format=data_center_format) worksheet.merge_range(2, 1, 3, 1, '人数汇总(人)', cell_format=data_center_format) worksheet.merge_range(2, 2, 2, 6, '每月新增人数(人)', cell_format=data_center_format) insert_excel(date_list, worksheet, data_center_format, province_title_list, province_map, month_province_dict) # 人数的sheet worksheet = workbook.add_worksheet(name='人数') worksheet.merge_range(0, 0, 0, len(member_date_list) + 1, '公民参与科学素质学习状况', cell_format=title_format) worksheet.write_string(1, 0, '已累计人数', cell_format=data_center_format) worksheet.merge_range(1, 2, 1, len(member_date_list) + 1, '导出时间:' + export_time, cell_format=data_center_format) worksheet.merge_range(2, 0, 3, 0, '省份', cell_format=data_center_format) worksheet.merge_range(2, 1, 3, 1, '人数汇总(人/次)', cell_format=data_center_format) worksheet.merge_range(2, 2, 2, 6, '每月新增人数(人/次)', cell_format=data_center_format) insert_excel(member_date_list, worksheet, data_center_format, province_title_list, province_map, member_province_dict) # 正确率的sheet worksheet = workbook.add_worksheet(name='正确率') total_province_accuracy = round( sum(correct_quantity_list) / sum(total_quantity_list) * 100, 2) worksheet.merge_range(0, 0, 0, len(date_list) + 1, '公民参与科学素质学习状况', cell_format=title_format) worksheet.merge_range(1, 0, 1, 1, '总体正确率' + str(total_province_accuracy) + '%', cell_format=data_center_format) worksheet.merge_range(1, 2, 1, len(date_list) + 1, '导出时间:' + export_time, cell_format=data_center_format) worksheet.merge_range(2, 0, 3, 0, '省份', cell_format=data_center_format) worksheet.merge_range(2, 1, 3, 1, '正确率', cell_format=data_center_format) worksheet.merge_range(2, 2, 2, 6, '每月正确率波动(%)', cell_format=data_center_format) for index, date in enumerate(accuracy_date_list): worksheet.write_string(3, 2 + index, date, cell_format=data_center_format) for index, province_title in enumerate(province_title_list): worksheet.write_string(4 + index, 0, province_title, cell_format=data_center_format) worksheet.write_string(4 + index, 1, str(province_dict[province_title]), cell_format=data_center_format) province_map[province_title] = 4 + index for month_province, value in accuracy_province_dict.items(): value = round(value, 2) position = Position( month_province.split(' ')[0], province_map[month_province.split(' ')[0]], 0) order = accuracy_date_list.index( month_province.split(' ')[1]) worksheet.write_string(position.row, 2 + order, str(value)) workbook.close() self.set_header( 'Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ) self.set_header( 'Content-Disposition', "attachment;filename*=utf-8''{}.xlsx".format( quote(chart_name.encode('utf-8')))) self.write(output.getvalue()) self.finish() except Exception: logger.error(traceback.format_exc())
def do_statistics_subject_radar(cache_key, root_dimension_code, m_city_code_list, province_code_list, city_code_list, gender_list, age_group_list, education_list): """ :param cache_key: :param root_dimension_code: :param m_city_code_list: :param province_code_list: :param city_code_list: :param gender_list: :param age_group_list: :param education_list: :return: """ RedisCache.set(cache_key, KEY_CACHE_REPORT_DOING_NOW, 5 * 60) data = [] dimension = SubjectDimension.sync_find_one( dict(code=root_dimension_code, status=STATUS_SUBJECT_DIMENSION_ACTIVE)) if not dimension: raise ValueError( 'can not find dimension by `root_dimension_code`(%s)' % root_dimension_code) stage_list = [] # 取前一天凌晨12点之前的数据 time_match = get_yesterday() stage_list.append(MatchStage({'updated_dt': {'$lt': time_match}})) if m_city_code_list: stage_list.append(MatchStage({'city_code': {'$in': m_city_code_list}})) query_dict = {} if province_code_list: query_dict['province_code'] = {'$in': province_code_list} if city_code_list: query_dict['city_code'] = {'$in': city_code_list} if gender_list: query_dict['gender'] = { '$in': [int(s_gender) for s_gender in gender_list] } if age_group_list: query_dict['age_group'] = { '$in': [int(s_age_group) for s_age_group in age_group_list] } if education_list: query_dict['education'] = { '$in': [int(s_education) for s_education in education_list] } if query_dict: stage_list.append(MatchStage(query_dict)) stage_list.append( GroupStage('dimension.%s' % dimension.cid, total={'$sum': '$total'}, correct={'$sum': '$correct'})) stage_list.append( LookupStage(SubjectDimension, '_id', 'cid', 'dimension_list')) stat_result = MemberSubjectStatistics.sync_aggregate(stage_list) while True: try: mds = stat_result.next() if mds: code, title, ordered = '', '', 0 if hasattr(mds, 'dimension_list') and mds.dimension_list: dimension = mds.dimension_list[0] if dimension: code = dimension.code title = dimension.title ordered = dimension.ordered data.append( dict(code=code, title=title, ordered=ordered, correct=mds.correct, total=mds.total)) except StopIteration: break if not data: early_warning_empty("start_statistics_subject_parameter_radar", cache_key, locals(), '获取维度正确率雷达图统计数据为空,请检查!') RedisCache.set(cache_key, msgpack.packb(data))
def do_create_query(max_q, m_province_code_list, m_city_code_list, s_province_code_list, s_city_code_list, s_gender_list, s_age_group_list, s_education_list): """ :param max_q: :param m_province_code_list: :param m_city_code_list: :param s_province_code_list: :param s_city_code_list: :param s_gender_list: :param s_age_group_list: :param s_education_list: :return: """ if max_q is not None: stage_list = [] match_dict = {} if m_province_code_list: match_dict['province_code'] = {'$in': m_province_code_list} if m_city_code_list: match_dict['city_code'] = {'$in': m_city_code_list} s_and_list = [] # 取前一天凌晨12点之前的数据 time_match = get_yesterday() s_and_list.append({'updated_dt': {'$lt': time_match}}) if s_province_code_list: s_and_list.append({'province_code': {'$in': s_province_code_list}}) if s_city_code_list: s_and_list.append({'city_code': {'$in': s_city_code_list}}) if s_gender_list: s_and_list.append({ 'gender': { '$in': [int(s_gender) for s_gender in s_gender_list] } }) if s_age_group_list: s_and_list.append({ 'age_group': { '$in': [int(s_age_group) for s_age_group in s_age_group_list] } }) if s_education_list: s_and_list.append({ 'education': { '$in': [int(s_education) for s_education in s_education_list] } }) if s_and_list: match_dict['$and'] = s_and_list if match_dict: stage_list.append(MatchStage(match_dict)) group_dict = {} for i in range(max_q): group_dict[str(i)] = {'$sum': '$quantity_detail.%s' % i} if group_dict: stage_list.append(GroupStage(None, **group_dict)) return stage_list return None
def do_statistics_accuracy(cache_key, city_code_list, choice_time): """ 学习状况-正确率 :param cache_key: :param city_code_list: :param choice_time :return: """ RedisCache.set(cache_key, KEY_CACHE_REPORT_DOING_NOW) # 取前一天凌晨12点之前的数据 time_match = get_yesterday() if not choice_time: match_stage = MatchStage({'updated_dt': {'$lt': time_match}}) else: # 当天下一天凌晨的时候 max_choice_time = choice_time.replace(hour=23, minute=59, second=59, microsecond=999) match_stage = MatchStage({'updated_dt': {'$gte': choice_time, '$lt': max_choice_time}}) stage_list = [match_stage] if city_code_list: stage_list.append(MatchStage({'city_code': {'$in': city_code_list}})) group_stage = GroupStage('province_code', t_total={'$sum': '$total'}, t_correct={'$sum': '$correct'}) add_fields_stage = AddFieldsStage(t_accuracy={ '$cond': { 'if': {'$eq': ['$t_total', 0]}, 'then': 0, 'else': { '$divide': ['$t_correct', '$t_total'] } } }) sort_stage = SortStage([('t_accuracy', DESC)]) lookup_stage = LookupStage(AdministrativeDivision, '_id', 'post_code', 'ad_list') stage_list.extend([group_stage, add_fields_stage, sort_stage, lookup_stage]) province_stat_list = MemberSubjectStatistics.sync_aggregate(stage_list) province_dict = {} while True: try: province_stat = province_stat_list.next() if province_stat: province_code = province_stat.id if province_stat.id else '000000' total = province_stat.t_total if province_stat.t_total else 0 correct = province_stat.t_correct if province_stat.t_correct else 0 title = 'undefined' ad_list = province_stat.ad_list if ad_list: ad: FacadeO = ad_list[0] if ad: title = ad.title.replace('省', '').replace('市', '') province_dict[province_code] = { 'code': province_code, 'title': title, 'correct': correct, 'total': total, 'data': round(correct / total * 100 if total > 0 else 0, 2) } except StopIteration: break # 合并城市统计信息 do_merge_city_stat_accuracy(province_dict, city_code_list) data = [v for v in province_dict.values()] RedisCache.set(cache_key, msgpack.packb(data)) if not data: early_warning_empty("start_statistics_member_accuracy", cache_key, city_code_list, '学习近况中正确率数据为空,请检查!') return data
def do_statistics_subject_cross(cache_key, main_dimension_code, second_dimension_code, m_city_code_list, province_code_list, city_code_list, gender_list, age_group_list, education_list): """ :param cache_key: :param main_dimension_code: :param second_dimension_code: :param m_city_code_list: :param province_code_list: :param city_code_list: :param gender_list: :param age_group_list: :param education_list: :return: """ RedisCache.set(cache_key, KEY_CACHE_REPORT_DOING_NOW, 5 * 60) main_dimension = SubjectDimension.sync_find_one( dict(code=main_dimension_code, status=STATUS_SUBJECT_DIMENSION_ACTIVE)) main_sub_dimension_list = SubjectDimension.sync_find(dict(parent_cid=main_dimension.cid)).sort( [('ordered', ASC)]).to_list(None) second_dimension = SubjectDimension.sync_find_one( dict(code=second_dimension_code, status=STATUS_SUBJECT_DIMENSION_ACTIVE)) second_sub_dimension_list = SubjectDimension.sync_find(dict(parent_cid=second_dimension.cid)).sort( [('ordered', ASC)]).to_list(None) data = [] for index, m_dimen in enumerate(main_sub_dimension_list): sub_data_list = [] for s_dimen in second_sub_dimension_list: stage_list = [] # 取前一天凌晨12点之前的数据 time_match = get_yesterday() stage_list.append(MatchStage({'updated_dt': {'$lt': time_match}})) match_dict = {'dimension.%s' % main_dimension.cid: m_dimen.cid, 'dimension.%s' % second_dimension.cid: s_dimen.cid} if m_city_code_list: match_dict['city_code'] = {'$in': m_city_code_list} stage_list.append(MatchStage(match_dict)) query_dict = {} if province_code_list: query_dict['province_code'] = {'$in': province_code_list} if city_code_list: query_dict['city_code'] = {'$in': city_code_list} if gender_list: query_dict['gender'] = {'$in': [int(s_gender) for s_gender in gender_list]} if age_group_list: query_dict['age_group'] = {'$in': [int(s_age_group) for s_age_group in age_group_list]} if education_list: query_dict['education'] = {'$in': [int(s_education) for s_education in education_list]} if query_dict: stage_list.append(MatchStage(query_dict)) # 分组 group_params = { 'total': {'$sum': '$total'}, 'correct': {'$sum': '$correct'} } stage_list.append(GroupStage(None, **group_params)) stat_result = MemberSubjectStatistics.sync_aggregate( stage_list).to_list(None) tmp_data = { 'code': s_dimen.code, 'title': s_dimen.title, 'ordered': s_dimen.ordered, 'correct': stat_result[0].correct if stat_result else 0, 'total': stat_result[0].total if stat_result else 0 } sub_data_list.append(tmp_data) main_data = { 'code': str(index + 1), 'title': m_dimen.title, 'ordered': index + 1, 'sub': sub_data_list } data.append(main_data) if data: data.sort(key=lambda x: x.get('ordered', 0)) if not data: early_warning_empty("start_statistics_subject_parameter_cross", cache_key, locals(), '获取维度正确率统计数据为空,请检查!') RedisCache.set(cache_key, msgpack.packb(data))
def do_statistics_member_top_n(cache_key, m_city_code_list, stat_type, top_n, time_range): """ :param cache_key: :param m_city_code_list: :param stat_type: :param top_n: :param time_range: :return: """ RedisCache.set(cache_key, KEY_CACHE_REPORT_DOING_NOW, 5 * 60) stage_list = [] # 取前一天凌晨12点之前的数据 time_match = get_yesterday() stage_list.append(MatchStage({'updated_dt': {'$lt': time_match}})) if m_city_code_list: stage_list.append(MatchStage({'city_code': {'$in': m_city_code_list}})) s_code = '' e_code = '' if time_range: suffix = time_range[-1:] range_num = int(time_range.replace(suffix, '')) delta = None if suffix.upper() == 'D': delta = datetime.timedelta(days=range_num) elif suffix.upper() == 'M': delta = datetime.timedelta(days=range_num * 30) elif suffix.upper() == 'Y': delta = datetime.timedelta(days=range_num * 365) if delta: s_code = datetime2str(datetime.datetime.now() - delta, date_format='%Y%m%d000000') e_code = datetime2str(datetime.datetime.now(), date_format='%Y%m%d000000') if s_code and e_code: stage_list.append( MatchStage({'daily_code': { '$gte': s_code, '$lte': e_code }})) stage_list.extend([ GroupStage({ 'daily_code': '$daily_code', 'member_cid': '$member_cid', 'province_code': '$province_code' } if stat_type == 1 else { 'daily_code': '$daily_code', 'member_cid': '$member_cid', 'province_code': '$province_code', 'city_code': '$city_code' }, learn_times={'$sum': '$learn_times'}), GroupStage({ 'daily_code': '$_id.daily_code', 'province_code': '$_id.province_code' } if stat_type == 1 else { 'daily_code': '$_id.daily_code', 'province_code': '$_id.province_code', 'city_code': '$_id.city_code' }, count={'$sum': 1}, times={'$sum': '$learn_times'}), LookupStage(AdministrativeDivision, '_id.province_code', 'post_code', 'province_list'), LookupStage(AdministrativeDivision, '_id.city_code', 'post_code', 'city_list'), ProjectStage( **{ '_id': False, 'daily_code': '$_id.daily_code', 'count': '$count', 'times': '$times', 'province_code': '$_id.province_code', 'province_title': '$province_list.title', 'ad_code': '$_id.province_code' if stat_type == 1 else '$_id.city_code', 'ad_title': '$province_list.title' if stat_type == 1 else '$city_list.title' }), SortStage([('daily_code', ASC), ('count', DESC)]) ]) # 检索数据 data = [] stat_cursor = MemberDailyStatistics.sync_aggregate(stage_list) t_code, t_list = None, None top_n_found = False while True: try: daily_stat = stat_cursor.next() if daily_stat: daily_code = daily_stat.daily_code if not daily_code == t_code: t_code = daily_code t_list = [] top_n_found = False print(t_code) if len(t_list) < top_n: t_list.append({ 'date': daily_code[:8], 'ad_code': daily_stat.ad_code, 'province_title': daily_stat.province_title[0] if daily_stat.province_title and stat_type == 2 else '', 'title': daily_stat.ad_title[0] if daily_stat.ad_title else 'undefined', 'quantity': daily_stat.count, 'times': daily_stat.times }) elif not top_n_found: if t_code is not None: data.append(t_list) top_n_found = True except StopIteration: break if not data: early_warning_empty("start_statistics_member_top_n", cache_key, locals(), '每日参与TOP5统计数据为空,请检查!') RedisCache.set(cache_key, msgpack.packb(data))
def do_statistics_member_active(cache_key, m_city_code_list, province_code_list, city_code_list, gender_list, age_group_list, education_list): """ :param cache_key: :param m_city_code_list: :param province_code_list: :param city_code_list: :param gender_list: :param age_group_list: :param education_list: :return: """ RedisCache.set(cache_key, KEY_CACHE_REPORT_DOING_NOW, 5 * 60) # 统计数据 stage_list = [] if m_city_code_list: stage_list.append(MatchStage({'city_code': {'$in': m_city_code_list}})) # 取前一天凌晨12点之前的数据 time_match = get_yesterday() stage_list.append(MatchStage({'updated_dt': {'$lt': time_match}})) query_dict = {} if province_code_list: query_dict['province_code'] = {'$in': province_code_list} if city_code_list: query_dict['city_code'] = {'$in': city_code_list} if gender_list: query_dict['gender'] = { '$in': [int(s_gender) for s_gender in gender_list] } if age_group_list: query_dict['age_group'] = { '$in': [int(s_age_group) for s_age_group in age_group_list] } if education_list: query_dict['education'] = { '$in': [int(s_education) for s_education in education_list] } if query_dict: stage_list.append(MatchStage(query_dict)) stage_list.extend([ GroupStage('learning_code', quantity={'$sum': 1}), SortStage([('_id', ASC)]), LimitStage(8) ]) mld_stat_cursor = MemberLearningDayStatistics.sync_aggregate(stage_list) data = [] while True: try: mld_stat = mld_stat_cursor.next() if mld_stat: data.append({ 'days': mld_stat.id, 'quantity': mld_stat.quantity }) except StopIteration: break all_members = sum([d.get('quantity') for d in data]) data_dict = {'data_list': data, 'all_members': all_members} if not data_dict: early_warning_empty("start_statistics_member_active", cache_key, locals(), '答题活跃度统计数据为空,请检查!') RedisCache.set(cache_key, msgpack.packb(data_dict))
def do_statistics_quiz_trends(cache_key, stat_type, m_city_code_list, province_code_list, city_code_list, gender_list, age_group_list, education_list, time_range): """ :param cache_key: :param stat_type: :param m_city_code_list: :param province_code_list: :param city_code_list: :param gender_list: :param age_group_list: :param education_list: :param time_range: :return: """ RedisCache.set(cache_key, KEY_CACHE_REPORT_DOING_NOW, 20 * 60) basic_stages = [] if m_city_code_list: basic_stages.append( MatchStage({'city_code': { '$in': m_city_code_list }})) if province_code_list: basic_stages.append( MatchStage({'province_code': { '$in': province_code_list }})) if city_code_list: basic_stages.append(MatchStage({'city_code': {'$in': city_code_list}})) if gender_list: basic_stages.append(MatchStage({'sex': {"$in": gender_list}})) if age_group_list: basic_stages.append(MatchStage({'age_group': {'$in': age_group_list}})) if education_list: basic_stages.append(MatchStage({'education': {'$in': education_list}})) yesterday = get_yesterday() time_match = MatchStage({'created_dt': {'$lte': yesterday}}) if time_range: suffix = time_range[-1:] range_num = int(time_range.replace(suffix, '')) delta = None if suffix.upper() == 'D': delta = datetime.timedelta(days=range_num) elif suffix.upper() == 'M': delta = datetime.timedelta(days=range_num * 30) elif suffix.upper() == 'Y': delta = datetime.timedelta(days=range_num * 365) start_dt = yesterday - delta time_match = MatchStage( {'created_dt': { '$gt': start_dt, '$lt': yesterday }}) data = [] game_data = do_stat_in_history(MemberGameHistory, time_match, basic_stages, stat_type) ckpt_data = do_stat_in_history(MemberCheckPointHistory, time_match, basic_stages, stat_type) for k, v in game_data.items(): try: ckpt_data[k] += v except KeyError: ckpt_data[k] = v data.append({k: ckpt_data[k]}) if not data: early_warning_empty("start_statistics_quiz_trends", cache_key, locals(), '答题趋势统计数据为空,请检查!') RedisCache.set(cache_key, msgpack.packb(data))
def do_statistics_learning_situation(cache_key, chart_type=None, m_city_code_list=None, gender_list=None, province_code_list=None, city_code_list=None, age_group_list=None, education_list=None, dimension=None, time_range=None, dimension_code=None): """ :param cache_key: :param chart_type: :param m_city_code_list: :param gender_list: :param province_code_list: :param city_code_list: :param age_group_list: :param education_list: :param dimension: :param time_range: :param dimension_code: :return: """ RedisCache.set(cache_key, KEY_CACHE_REPORT_DOING_NOW, 5 * 60) stage_list = [] # 取前一天凌晨12点之前的数据 time_match = get_yesterday() stage_list.append(MatchStage({'created_dt': {'$lt': time_match}})) s_code, e_code = '', '' if chart_type == 1: s_code, e_code = get_daily_code_range(time_range) if city_code_list: stage_list.append(MatchStage({'city_code': {'$in': m_city_code_list}})) parent_dimension_cid, dimension_cid = get_dimension(dimension_code) if parent_dimension_cid and dimension_cid: stage_list.append( MatchStage({'dimension.%s' % parent_dimension_cid: dimension_cid})) query_dict = {} if s_code and e_code: query_dict['daily_code'] = {'$gte': s_code, '$lte': e_code} if province_code_list: query_dict['province_code'] = {'$in': province_code_list} if city_code_list: query_dict['city_code'] = {'$in': city_code_list} if gender_list: query_dict['gender'] = { '$in': [int(s_gender) for s_gender in gender_list] } if age_group_list: query_dict['age_group'] = { '$in': [int(s_age_group) for s_age_group in age_group_list] } if education_list: query_dict['education'] = { '$in': [int(s_education) for s_education in education_list] } if dimension: try: s_dimension = json.loads(dimension) for k, v in s_dimension.items(): query_dict['dimension.%s' % k] = {'$in': v} except Exception: pass if query_dict: stage_list.append(MatchStage(query_dict)) stage_list.append( GroupStage('daily_code' if chart_type == 1 else 'learning_code', total={'$sum': '$subject_total_quantity'}, correct={'$sum': '$subject_correct_quantity'})) stage_list.append(SortStage([('_id', ASC)])) if chart_type == 2: stage_list.append(MatchStage({'_id': {'$lte': 20}})) data = [] # 检索数据 if chart_type == 1: stat_cursor = MemberDailyDimensionStatistics.sync_aggregate(stage_list) else: stat_cursor = MemberLearningDayDimensionStatistics.sync_aggregate( stage_list) while True: try: md_stat = stat_cursor.next() if md_stat: data.append({ md_stat.id[:8] if chart_type == 1 else md_stat.id: { 'total': md_stat.total, 'correct': md_stat.correct } }) except StopIteration: break if not data: early_warning_empty("start_statistics_learning_situation", cache_key, locals(), '学习效果中数据为空,请检查!') RedisCache.set(cache_key, msgpack.packb(data))