parent
f37d02bcfb
commit
01668fe3f8
@ -1,20 +1,44 @@
|
|||||||
class Managements::SchoolsController < Managements::BaseController
|
class Managements::SchoolsController < Managements::BaseController
|
||||||
before_filter :set_navigation_bar
|
before_filter :set_navigation_bar
|
||||||
before_filter :set_default_sort_params, only: :statistics
|
before_filter :contrast_column_select_options, only: [:data_contrast]
|
||||||
|
|
||||||
def statistics
|
def statistics
|
||||||
@sub_type = 1
|
@sub_type = 1
|
||||||
|
params[:sort_by] ||= :teacher_count
|
||||||
|
params[:sort_direction] ||= :desc
|
||||||
|
|
||||||
schools = Management::SchoolReportService.new(params).call
|
schools = Management::SchoolReportService.new(params).call
|
||||||
@schools = paginateHelper schools
|
@schools = paginateHelper schools
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def yesterday_data
|
||||||
|
@sub_type = 2
|
||||||
|
params[:sort_by] ||= :teacher_increase_count
|
||||||
|
params[:sort_direction] ||= :desc
|
||||||
|
|
||||||
|
reports = Management::SchoolYesterdayDataService.new(params).call
|
||||||
|
@reports = paginateHelper reports
|
||||||
|
end
|
||||||
|
|
||||||
|
def data_contrast
|
||||||
|
params[:contrast_column] = :teacher_increase_count if params[:contrast_column].blank?
|
||||||
|
params[:sort_direction] ||= :desc
|
||||||
|
params[:sort_by] ||= :percentage
|
||||||
|
|
||||||
|
@obj_count, @reports = Management::SchoolDataContrastService.new(params).call
|
||||||
|
@obj_pages = Paginator.new(@obj_count, Management::SchoolDataContrastService::PAGE_SIZE, params[:page])
|
||||||
|
rescue Management::SchoolDataContrastService::ParameterError
|
||||||
|
raise '参数错误'
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def set_navigation_bar
|
def set_navigation_bar
|
||||||
@menu_type = 1
|
@menu_type = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_default_sort_params
|
def contrast_column_select_options
|
||||||
params[:sort_by] ||= :teacher_count
|
@select_options = Management::SchoolDataContrastService::CONTRAST_COLUMN_LIST.map do |column|
|
||||||
params[:sort_direction] ||= :desc
|
[I18n.t("school_daily_report.#{column}"), column]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -0,0 +1,3 @@
|
|||||||
|
class SchoolDailyReport < ActiveRecord::Base
|
||||||
|
belongs_to :school
|
||||||
|
end
|
@ -0,0 +1,66 @@
|
|||||||
|
class Management::SchoolDataContrastService
|
||||||
|
ParameterError = Class.new(StandardError)
|
||||||
|
|
||||||
|
PAGE_SIZE = 20
|
||||||
|
CONTRAST_COLUMN_LIST = %w(
|
||||||
|
teacher_increase_count student_increase_count course_increase_count
|
||||||
|
shixun_increase_count active_user_count
|
||||||
|
).freeze
|
||||||
|
|
||||||
|
attr_reader :params, :sort_direction, :contrast_column
|
||||||
|
|
||||||
|
def initialize(params)
|
||||||
|
@params = params
|
||||||
|
@sort_direction = params[:sort_direction].to_s
|
||||||
|
@contrast_column = params[:contrast_column].to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def call
|
||||||
|
validate_parameter!
|
||||||
|
reports = SchoolDailyReport.select(select_columns)
|
||||||
|
|
||||||
|
keyword = params[:keyword].try(:to_s).try(:strip)
|
||||||
|
if keyword.present?
|
||||||
|
reports = reports.where("school_name LIKE :keyword OR school_id LIKE :keyword", keyword: "%#{keyword}%")
|
||||||
|
end
|
||||||
|
|
||||||
|
reports = reports.group(:school_id)
|
||||||
|
count = reports.count.count
|
||||||
|
|
||||||
|
[count, SchoolDailyReport.find_by_sql(query_report_sql(reports.to_sql))]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def validate_parameter!
|
||||||
|
if %i[begin_date end_date other_begin_date other_end_date].any? { |key| params[key].blank? }
|
||||||
|
raise ParameterError
|
||||||
|
end
|
||||||
|
|
||||||
|
unless %w(desc asc).include?(sort_direction)
|
||||||
|
raise ParameterError
|
||||||
|
end
|
||||||
|
|
||||||
|
unless CONTRAST_COLUMN_LIST.include?(contrast_column)
|
||||||
|
raise ParameterError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def format_date(date)
|
||||||
|
Time.zone.parse(date).strftime("%Y-%m-%d")
|
||||||
|
end
|
||||||
|
|
||||||
|
def offset
|
||||||
|
(params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * PAGE_SIZE
|
||||||
|
end
|
||||||
|
|
||||||
|
def select_columns
|
||||||
|
"school_id, school_name,"\
|
||||||
|
"SUM(IF(date BETWEEN '#{format_date(params[:begin_date])}' AND '#{format_date(params[:end_date])}', #{contrast_column}, 0)) total,"\
|
||||||
|
"SUM(IF(date BETWEEN '#{format_date(params[:other_begin_date])}' AND '#{format_date(params[:other_end_date])}', #{contrast_column}, 0)) other_total"
|
||||||
|
end
|
||||||
|
|
||||||
|
def query_report_sql(from_sql)
|
||||||
|
"SELECT reports.*, (other_total - total) increase, (IF(other_total - total = 0, 0.0, round((other_total - total) / IF(total = 0, 1, total), 5))) percentage "\
|
||||||
|
"FROM (#{from_sql}) reports ORDER BY percentage #{sort_direction} LIMIT #{PAGE_SIZE} OFFSET #{offset}"
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,44 @@
|
|||||||
|
class StatisticSchoolDailyReportTask
|
||||||
|
def call
|
||||||
|
School.find_each do |school|
|
||||||
|
# 新增教师和学生
|
||||||
|
users = User.joins(:user_extensions)
|
||||||
|
.where(user_extensions: { school_id: school.id })
|
||||||
|
|
||||||
|
teacher_count = users.where(created_on: yesterday, user_extensions: { identity: User::TEACHER }).count
|
||||||
|
student_count = users.where(created_on: yesterday, user_extensions: { identity: User::STUDENT }).count
|
||||||
|
|
||||||
|
# 活跃用户
|
||||||
|
active_user_count = users.where(last_login_on: yesterday).count
|
||||||
|
|
||||||
|
# 新增课堂
|
||||||
|
course_count = school.courses.where(created_at: yesterday).count
|
||||||
|
|
||||||
|
# 新增实训
|
||||||
|
shixun_count = Shixun.joins(creator: :user_extensions)
|
||||||
|
.where('user_extensions.school_id = ?', school.id)
|
||||||
|
.where(created_at: yesterday).count
|
||||||
|
|
||||||
|
create_params = {
|
||||||
|
school_id: school.id, school_name: school.name, teacher_increase_count: teacher_count,
|
||||||
|
student_increase_count: student_count, course_increase_count: course_count,
|
||||||
|
shixun_increase_count: shixun_count, active_user_count: active_user_count, date: current_date
|
||||||
|
}
|
||||||
|
SchoolDailyReport.create!(create_params)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def current_date
|
||||||
|
@_current_date ||= Time.zone.now.beginning_of_day - 1.day
|
||||||
|
end
|
||||||
|
|
||||||
|
def yesterday
|
||||||
|
@_yesterday ||= begin
|
||||||
|
# 每日凌晨5点为节点
|
||||||
|
end_time = Time.zone.now.beginning_of_day + 5.hour
|
||||||
|
begin_time = end_time - 1.day
|
||||||
|
begin_time..end_time
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,223 @@
|
|||||||
|
<form class="management-school-data-form">
|
||||||
|
<div style="float: left; margin: 10px 10px 10px 25px;">
|
||||||
|
<%= hidden_field_tag :contrast_column, params[:contrast_column] %>
|
||||||
|
<%= hidden_field_tag :begin_date, params[:begin_date] %>
|
||||||
|
<%= hidden_field_tag :end_date, params[:end_date] %>
|
||||||
|
<%= hidden_field_tag :other_begin_date, params[:other_begin_date] %>
|
||||||
|
<%= hidden_field_tag :other_end_date, params[:other_end_date] %>
|
||||||
|
|
||||||
|
<%= text_field_tag :date_input, params[:date_input],
|
||||||
|
class: 'date-input winput-200-30', placeholder: '请选择时间段一' %>
|
||||||
|
<span>VS</span>
|
||||||
|
<%= text_field_tag :other_date_input, params[:other_date_input],
|
||||||
|
class: 'other-date-input winput-200-30', placeholder: '请选择时间段二' %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="float: left;">
|
||||||
|
<%= hidden_field_tag :data_type, params[:data_type] || 'yesterday' %>
|
||||||
|
<% if params[:data_type] == 'contrast' %>
|
||||||
|
<a href="javascript:void(0)" class="fl task-btn ml5 mt10 contrast-btn task-btn-orange">时间对比</a>
|
||||||
|
<a href="javascript:void(0)" class="fl task-btn ml5 mt10 yesterday-btn">日新增</a>
|
||||||
|
<% else %>
|
||||||
|
<a href="javascript:void(0)" class="fl task-btn ml5 mt10 contrast-btn">时间对比</a>
|
||||||
|
<a href="javascript:void(0)" class="fl task-btn ml5 mt10 yesterday-btn task-btn-orange">日新增</a>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= text_field_tag :keyword, params[:keyword], placeholder: '请输入单位名称或者ID关键字进行搜索',
|
||||||
|
class: 'fl task-form-30 task-height-30 mt10', style: 'margin: 10px 10px 10px 25px;' %>
|
||||||
|
<%= link_to '搜索', 'javascript:void(0)', class: 'fl task-btn task-btn-orange ml5 mt10 search-btn' %>
|
||||||
|
<%= link_to '清除', 'javascript:void(0)', class: 'fl task-btn ml5 mt2 mt10 reset-btn' %>
|
||||||
|
</form>
|
||||||
|
<script>
|
||||||
|
$(function(){
|
||||||
|
var yesterdayFormUrl = "<%= school_yesterday_data_managements_path %>";
|
||||||
|
var contrastFormUrl = "<%= school_data_contrast_managements_path %>";
|
||||||
|
|
||||||
|
var searchForm = $(".management-school-data-form");
|
||||||
|
var dataTypeInput = searchForm.find("input[name='data_type']");
|
||||||
|
var keywordInput = searchForm.find("input[name='keyword']");
|
||||||
|
var contrastBtn = searchForm.find(".contrast-btn");
|
||||||
|
var yesterdayBtn = searchForm.find(".yesterday-btn");
|
||||||
|
|
||||||
|
var beginDateInput = searchForm.find("input[name='begin_date']");
|
||||||
|
var endDateInput = searchForm.find("input[name='end_date']");
|
||||||
|
var otherBeginDateInput = searchForm.find("input[name='other_begin_date']");
|
||||||
|
var otherEndDateInput = searchForm.find("input[name='other_end_date']");
|
||||||
|
|
||||||
|
// 数据展示切换: 数据对比、日新增
|
||||||
|
searchForm.on('click', ".contrast-btn", function(){
|
||||||
|
if(contrastBtn.hasClass("task-btn-orange")) { return }
|
||||||
|
changeDataType("contrast");
|
||||||
|
});
|
||||||
|
searchForm.on('click', ".yesterday-btn", function(){
|
||||||
|
if(yesterdayBtn.hasClass("task-btn-orange")) { return }
|
||||||
|
changeDataType("yesterday");
|
||||||
|
submitForm();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 搜索按钮
|
||||||
|
searchForm.on('click', ".search-btn", function(){
|
||||||
|
submitForm();
|
||||||
|
});
|
||||||
|
searchForm.on("click", ".reset-btn", function(){
|
||||||
|
keywordInput.val("");
|
||||||
|
submitForm();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.contrast-column-select').on('change', function() {
|
||||||
|
searchForm.find("input[name='contrast_column']").val($('.contrast-column-select').val());
|
||||||
|
submitForm();
|
||||||
|
});
|
||||||
|
|
||||||
|
var submitForm = function(){
|
||||||
|
if(!validateFrom()) { return }
|
||||||
|
|
||||||
|
var form = searchForm;
|
||||||
|
var url = dataTypeInput.val() == "contrast" ? contrastFormUrl : yesterdayFormUrl;
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
data: form.serialize(),
|
||||||
|
dataType: "script"
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
var validateFrom = function(){
|
||||||
|
if (dataTypeInput.val() != "contrast") { return true; }
|
||||||
|
|
||||||
|
if (beginDateInput.val() == "" || endDateInput.val() == "" ||
|
||||||
|
otherBeginDateInput.val() == "" || otherBeginDateInput.val() == "") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
var changeDataType = function(dataType){
|
||||||
|
if (dataTypeInput.val() == dataType) { return }
|
||||||
|
|
||||||
|
if (dataType == "contrast") {
|
||||||
|
contrastBtn.addClass("task-btn-orange");
|
||||||
|
yesterdayBtn.removeClass("task-btn-orange");
|
||||||
|
dataTypeInput.val('contrast');
|
||||||
|
} else {
|
||||||
|
contrastBtn.removeClass("task-btn-orange");
|
||||||
|
yesterdayBtn.addClass("task-btn-orange");
|
||||||
|
dataTypeInput.val('yesterday');
|
||||||
|
|
||||||
|
clearContrastDateInput();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var clearContrastDateInput = function(){
|
||||||
|
searchForm.find("input[name='begin_date']").val('');
|
||||||
|
searchForm.find("input[name='end_date']").val('');
|
||||||
|
searchForm.find("input[name='other_begin_date']").val('');
|
||||||
|
searchForm.find("input[name='other_end_date']").val('');
|
||||||
|
searchForm.find("input[name='date_input']").val('');
|
||||||
|
searchForm.find("input[name='other_date_input']").val('');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 日期选择
|
||||||
|
var locale = {
|
||||||
|
clearText: '清除',
|
||||||
|
clearStatus: '清除已选日期',
|
||||||
|
closeText: '关闭',
|
||||||
|
closeStatus: '不改变当前选择',
|
||||||
|
prevText: '< 上月',
|
||||||
|
prevStatus: '显示上月',
|
||||||
|
prevBigText: '<<',
|
||||||
|
prevBigStatus: '显示上一年',
|
||||||
|
nextText: '下月>',
|
||||||
|
nextStatus: '显示下月',
|
||||||
|
nextBigText: '>>',
|
||||||
|
nextBigStatus: '显示下一年',
|
||||||
|
currentText: '今天',
|
||||||
|
currentStatus: '显示本月',
|
||||||
|
monthNames: ['一月','二月','三月','四月','五月','六月', '七月','八月','九月','十月','十一月','十二月'],
|
||||||
|
monthNamesShort: ['一月','二月','三月','四月','五月','六月', '七月','八月','九月','十月','十一月','十二月'],
|
||||||
|
monthStatus: '选择月份',
|
||||||
|
yearStatus: '选择年份',
|
||||||
|
weekHeader: '周',
|
||||||
|
weekStatus: '年内周次',
|
||||||
|
dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
|
||||||
|
dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
|
||||||
|
dayNamesMin: ['日','一','二','三','四','五','六'],
|
||||||
|
dayStatus: '设置 DD 为一周起始',
|
||||||
|
dateStatus: '选择 m月 d日, DD',
|
||||||
|
dateFormat: 'yy-mm-dd',
|
||||||
|
firstDay: 1,
|
||||||
|
initStatus: '请选择日期',
|
||||||
|
isRTL: false
|
||||||
|
};
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
dateFormat: 'yy-mm-dd',
|
||||||
|
minDate: new Date('2017-04-01'),
|
||||||
|
maxDate: -1,
|
||||||
|
onSelect: function(selectedDate) {
|
||||||
|
if(!$(this).data().datepicker.first){
|
||||||
|
$(this).data().datepicker.inline = true;
|
||||||
|
$(this).data().datepicker.first = selectedDate;
|
||||||
|
|
||||||
|
if($(this).hasClass("date-input")){
|
||||||
|
beginDateInput.val("");
|
||||||
|
endDateInput.val("");
|
||||||
|
} else {
|
||||||
|
otherBeginDateInput.val("");
|
||||||
|
otherEndDateInput.val("");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
// 计算时间先后顺序
|
||||||
|
var begin_date = null;
|
||||||
|
var end_date = null;
|
||||||
|
if(selectedDate > $(this).data().datepicker.first){
|
||||||
|
begin_date = $(this).data().datepicker.first;
|
||||||
|
end_date = selectedDate;
|
||||||
|
}else{
|
||||||
|
begin_date = selectedDate;
|
||||||
|
end_date = $(this).data().datepicker.first;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录所选时间
|
||||||
|
if($(this).hasClass("date-input")){
|
||||||
|
beginDateInput.val(begin_date);
|
||||||
|
endDateInput.val(end_date);
|
||||||
|
} else {
|
||||||
|
otherBeginDateInput.val(begin_date);
|
||||||
|
otherEndDateInput.val(end_date);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 展示所选时间
|
||||||
|
$(this).val(begin_date + " 至 " + end_date);
|
||||||
|
$(this).data().datepicker.inline = false;
|
||||||
|
|
||||||
|
// 切换数据类型
|
||||||
|
changeDataType("contrast");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onClose:function(){
|
||||||
|
var date = $(this).data().datepicker.first;
|
||||||
|
|
||||||
|
if (date) {
|
||||||
|
if($(this).hasClass("date-input") && beginDateInput.val() == ""){
|
||||||
|
beginDateInput.val(date);
|
||||||
|
endDateInput.val(date);
|
||||||
|
} else if ($(this).hasClass("other-date-input") && otherBeginDateInput.val() == "") {
|
||||||
|
otherBeginDateInput.val(date);
|
||||||
|
otherEndDateInput.val(date);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete $(this).data().datepicker.first;
|
||||||
|
$(this).data().datepicker.inline = false;
|
||||||
|
|
||||||
|
submitForm();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
options = $.extend({}, locale, options);
|
||||||
|
searchForm.find(".date-input").datepicker(options);
|
||||||
|
searchForm.find(".other-date-input").datepicker(options);
|
||||||
|
});
|
||||||
|
</script>
|
@ -0,0 +1,38 @@
|
|||||||
|
<table class="edu-pop-table edu-txt-center" cellpadding="0" cellspacing="0" style="table-layout: fixed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th width="6%">序号</th>
|
||||||
|
<th width="10%">ID</th>
|
||||||
|
<th width="24%" class="edu-txt-left">单位名称</th>
|
||||||
|
|
||||||
|
<th width="12%"><%= sort_tag('新增教师', name: 'teacher_increase_count', path: school_yesterday_data_managements_path) %></th>
|
||||||
|
<th width="12%"><%= sort_tag('新增学生', name: 'student_increase_count', path: school_yesterday_data_managements_path) %></th>
|
||||||
|
<th width="12%"><%= sort_tag('新增课堂', name: 'course_increase_count', path: school_yesterday_data_managements_path) %></th>
|
||||||
|
<th width="12%"><%= sort_tag('新增实训', name: 'shixun_increase_count', path: school_yesterday_data_managements_path) %></th>
|
||||||
|
<th width="12%"><%= sort_tag('活跃用户', name: 'active_user_count', path: school_yesterday_data_managements_path) %></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% @reports.each_with_index do |report, index| %>
|
||||||
|
<tr>
|
||||||
|
<td><%= (@obj_pages.page - 1) * @obj_pages.per_page + index + 1 %></td>
|
||||||
|
<td><%= report.school_id %></td>
|
||||||
|
<td class="edu-txt-left"><%= report.school_name %></td>
|
||||||
|
<td><%= report.teacher_increase_count %></td>
|
||||||
|
<td><%= report.student_increase_count %></td>
|
||||||
|
<td><%= report.course_increase_count %></td>
|
||||||
|
<td><%= report.shixun_increase_count %></td>
|
||||||
|
<td><%= report.active_user_count %></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div style="text-align:center;" class="new_expand">
|
||||||
|
<div class="pages_user_show" style="width:auto; display:inline-block;margin: 18px 0;">
|
||||||
|
<ul id="school_yesterday_data_ref_pages">
|
||||||
|
<%= pagination_links_full @obj_pages, @obj_count, per_page_links: false, remote: true, flag: true, is_new: true, path: school_yesterday_data_managements_path(params.except(:page)) %>
|
||||||
|
</ul>
|
||||||
|
<div class="cl"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,2 @@
|
|||||||
|
$("#managements-school-data").html("<%= j(render 'managements/schools/data_contrast_list') %>")
|
||||||
|
$(".management-school-data-form-box").html("<%= j(render 'managements/schools/contrast_search_form') %>")
|
@ -0,0 +1,9 @@
|
|||||||
|
<div class="edu-con-top clearfix xmt10 bor-grey-e mt10">
|
||||||
|
<div class="management-school-data-form-box">
|
||||||
|
<%= render 'managements/schools/contrast_search_form' %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="edu-con-bg01 mt15" id="managements-school-data">
|
||||||
|
<%= render 'managements/schools/yesterday_data_list'%>
|
||||||
|
</div>
|
@ -0,0 +1,2 @@
|
|||||||
|
$("#managements-school-data").html("<%= j(render 'managements/schools/yesterday_data_list') %>")
|
||||||
|
$(".management-school-data-form-box").html("<%= j(render 'managements/schools/contrast_search_form') %>")
|
@ -0,0 +1,7 @@
|
|||||||
|
zh:
|
||||||
|
school_daily_report:
|
||||||
|
teacher_increase_count: 新增教师
|
||||||
|
student_increase_count: 新增学生
|
||||||
|
course_increase_count: 新增课堂
|
||||||
|
shixun_increase_count: 新增实训
|
||||||
|
active_user_count: 活跃用户
|
@ -0,0 +1,24 @@
|
|||||||
|
# Use this file to easily define all of your cron jobs.
|
||||||
|
#
|
||||||
|
# It's helpful, but not entirely necessary to understand cron before proceeding.
|
||||||
|
# http://en.wikipedia.org/wiki/Cron
|
||||||
|
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# set :output, "/path/to/my/cron_log.log"
|
||||||
|
#
|
||||||
|
# every 2.hours do
|
||||||
|
# command "/usr/bin/some_great_command"
|
||||||
|
# runner "MyModel.some_method"
|
||||||
|
# rake "some:great:rake:task"
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# every 4.days do
|
||||||
|
# runner "AnotherModel.prune_old_records"
|
||||||
|
# end
|
||||||
|
|
||||||
|
# Learn more: http://github.com/javan/whenever
|
||||||
|
|
||||||
|
every 1.days, at: '5:00 am' do
|
||||||
|
runner 'StatisticSchoolDailyReportTask.new.call'
|
||||||
|
end
|
@ -0,0 +1,18 @@
|
|||||||
|
class CreateSchoolDailyReports < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :school_daily_reports do |t|
|
||||||
|
t.integer :school_id
|
||||||
|
t.string :school_name
|
||||||
|
t.integer :teacher_increase_count
|
||||||
|
t.integer :student_increase_count
|
||||||
|
t.integer :course_increase_count
|
||||||
|
t.integer :shixun_increase_count
|
||||||
|
t.integer :active_user_count
|
||||||
|
|
||||||
|
t.date :date
|
||||||
|
t.timestamps
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index :school_daily_reports, [:school_id, :date], unique: true
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,103 @@
|
|||||||
|
#coding=utf-8
|
||||||
|
|
||||||
|
namespace :school_daily_report do
|
||||||
|
desc 'statistic school daily report data before now'
|
||||||
|
task :statistic, [:date] => :environment do |_, args|
|
||||||
|
date = Time.zone.parse(args[:date]).beginning_of_day
|
||||||
|
current_date = (Time.zone.now - 5.hour).beginning_of_day
|
||||||
|
custom_logger("statistic range: #{date}..#{current_date}")
|
||||||
|
|
||||||
|
while current_date > date
|
||||||
|
date_str = date.strftime('%Y-%m-%d')
|
||||||
|
# 检查当天数据是否已经统计
|
||||||
|
if SchoolDailyReport.exists?(date: date)
|
||||||
|
custom_logger("Skip! statistics data exist, date: #{date_str}")
|
||||||
|
date += 1.day
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
school_count = School.count
|
||||||
|
query_times = school_count % query_size == 0 ? school_count / query_size : (school_count / query_size) + 1
|
||||||
|
|
||||||
|
custom_logger("Start statistic => Date: #{date_str}, school count: #{school_count}, insert times: #{query_times} ~")
|
||||||
|
query_times.times do |index|
|
||||||
|
sql = school_daily_report_sql(date, query_size, index * query_size)
|
||||||
|
reports = School.find_by_sql(sql)
|
||||||
|
|
||||||
|
data = reports.map do |report|
|
||||||
|
[
|
||||||
|
report['id'], report['name'], report['teacher_count'], report['student_count'], report['course_count'],
|
||||||
|
report['shixun_count'], report['active_user_count'], date_str, current_datetime, current_datetime
|
||||||
|
]
|
||||||
|
end
|
||||||
|
batch_create_school_daily_reports!(data)
|
||||||
|
end
|
||||||
|
custom_logger("Statistic complete! date: #{date_str}")
|
||||||
|
|
||||||
|
date += 1.day
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc 'clear school daily report data'
|
||||||
|
task clear: :environment do
|
||||||
|
SchoolDailyReport.destroy_all
|
||||||
|
end
|
||||||
|
|
||||||
|
def query_size
|
||||||
|
100
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_datetime
|
||||||
|
Time.zone.now.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
end
|
||||||
|
|
||||||
|
def custom_logger(str)
|
||||||
|
p(str)
|
||||||
|
end
|
||||||
|
|
||||||
|
def batch_create_school_daily_reports!(arr)
|
||||||
|
sql = build_insert_report_sql(arr)
|
||||||
|
SchoolDailyReport.connection.execute(sql)
|
||||||
|
end
|
||||||
|
|
||||||
|
def build_insert_report_sql(arr)
|
||||||
|
prefix = 'INSERT INTO school_daily_reports(school_id, school_name, teacher_increase_count, student_increase_count, '\
|
||||||
|
'course_increase_count, shixun_increase_count, active_user_count, date, created_at, updated_at) VALUES'
|
||||||
|
# [[1,2], [3,4]] => ['"1", "2"', '"3", "4"'] => '("1", "2"),("3", "4")'
|
||||||
|
values = '(' + arr.map { |item| '"' + item.join('","') + '"' }.join('),(') + ')'
|
||||||
|
|
||||||
|
prefix + values
|
||||||
|
end
|
||||||
|
|
||||||
|
def school_daily_report_sql(date, limit, offset)
|
||||||
|
begin_date = (date + 5.hour).strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
end_date = (date + 1.day + 5.hour).strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
<<-SQL
|
||||||
|
SELECT schools.id, schools.name, (
|
||||||
|
SELECT COUNT(*) FROM users u
|
||||||
|
LEFT JOIN user_extensions ue ON ue.user_id = u.id
|
||||||
|
WHERE ue.school_id = schools.id AND ue.identity = #{User::STUDENT}
|
||||||
|
AND u.created_on BETWEEN "#{begin_date}" AND "#{end_date}"
|
||||||
|
) student_count, (
|
||||||
|
SELECT COUNT(*) FROM users u
|
||||||
|
LEFT JOIN user_extensions ue ON ue.user_id = u.id
|
||||||
|
WHERE ue.school_id = schools.id AND ue.identity = #{User::TEACHER}
|
||||||
|
AND u.created_on BETWEEN "#{begin_date}" AND "#{end_date}"
|
||||||
|
) teacher_count, (
|
||||||
|
SELECT COUNT(*) FROM courses cs
|
||||||
|
WHERE cs.school_id = schools.id
|
||||||
|
AND cs.created_at BETWEEN "#{begin_date}" AND "#{end_date}"
|
||||||
|
) course_count, (
|
||||||
|
SELECT COUNT(*) FROM shixuns sx
|
||||||
|
LEFT JOIN users u ON sx.user_id = u.id
|
||||||
|
LEFT JOIN user_extensions ue ON ue.user_id = u.id
|
||||||
|
WHERE ue.school_id = schools.id AND sx.created_at BETWEEN "#{begin_date}" AND "#{end_date}"
|
||||||
|
) shixun_count, (
|
||||||
|
SELECT COUNT(*) FROM users u
|
||||||
|
LEFT JOIN user_extensions ue ON ue.user_id = u.id
|
||||||
|
WHERE ue.school_id = schools.id AND u.last_login_on BETWEEN "#{begin_date}" AND "#{end_date}"
|
||||||
|
) active_user_count FROM schools LIMIT #{limit} OFFSET #{offset}
|
||||||
|
SQL
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in new issue