Merge branch 'educoder' of https://bdgit.educoder.net/Hjqreturn/pgfqe6ch8 into educoder
commit
41a1795b32
@ -0,0 +1,5 @@
|
||||
class Managements::BaseController < ApplicationController
|
||||
layout 'base_management'
|
||||
|
||||
before_filter :require_business
|
||||
end
|
@ -0,0 +1,80 @@
|
||||
class Managements::SchoolsController < Managements::BaseController
|
||||
before_filter :set_navigation_bar
|
||||
before_filter :contrast_column_select_options, only: [:data_contrast]
|
||||
|
||||
def statistics
|
||||
@sub_type = 1
|
||||
params[:sort_by] ||= :teacher_count
|
||||
params[:sort_direction] ||= :desc
|
||||
|
||||
schools = Management::SchoolReportService.new(params).call
|
||||
@schools = paginateHelper schools
|
||||
|
||||
respond_to do |format|
|
||||
format.html { load_statistic_total }
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
def data_grow
|
||||
@sub_type = 2
|
||||
params[:data_type] ||= 'grow'
|
||||
params[:sort_by] ||= :teacher_increase_count
|
||||
params[:sort_direction] ||= :desc
|
||||
|
||||
service = Management::SchoolDataGrowService.new(params)
|
||||
@grow_summary = service.grow_summary
|
||||
|
||||
@obj_count, @reports = service.call
|
||||
@obj_pages = Paginator.new(@obj_count, Management::SchoolDataGrowService::PAGE_SIZE, params[:page])
|
||||
end
|
||||
|
||||
def data_contrast
|
||||
params[:contrast_column] = :teacher_increase_count if params[:contrast_column].blank?
|
||||
params[:sort_direction] ||= :desc
|
||||
params[:sort_by] ||= :percentage
|
||||
|
||||
# 无对比日期时直接返回无数据页面
|
||||
if useless_contrast_date_parameter?
|
||||
@obj_count, @reports = 0, []
|
||||
return
|
||||
end
|
||||
|
||||
@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
|
||||
|
||||
def statistics_xlsx
|
||||
@schools = Management::SchoolReportService.new(params).call
|
||||
|
||||
filename = ["学校统计总表", params[:keyword], Time.zone.now.strftime('%Y%m%d%H%M%S')].join('-') << ".xlsx"
|
||||
render xlsx: "statistics_xlsx", filename: filename
|
||||
end
|
||||
|
||||
private
|
||||
def set_navigation_bar
|
||||
@menu_type = 1
|
||||
end
|
||||
|
||||
def contrast_column_select_options
|
||||
@select_options = Management::SchoolDataContrastService::CONTRAST_COLUMN_LIST.map do |column|
|
||||
[I18n.t("school_daily_report.#{column}"), column]
|
||||
end
|
||||
end
|
||||
|
||||
def useless_contrast_date_parameter?
|
||||
params[:begin_date].blank? && params[:end_date].blank? &&
|
||||
params[:other_begin_date].blank? &¶ms[:other_end_date].blank?
|
||||
end
|
||||
|
||||
def load_statistic_total
|
||||
@teacher_total = User.teacher.count
|
||||
@student_total = User.student.count
|
||||
@course_total = Course.count
|
||||
@active_course_total = Course.where(is_end: false).count
|
||||
@shixun_homework_total = HomeworkCommon.where(homework_type: 4).count
|
||||
@other_homework_total = HomeworkCommon.where(homework_type: [1, 3]).count
|
||||
end
|
||||
end
|
@ -0,0 +1,45 @@
|
||||
module CustomSortable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do |base|
|
||||
base.instance_variable_set("@_sort_options", {})
|
||||
base.instance_variable_set("@_sort_columns", [])
|
||||
base.instance_variable_set("@_sort_directions", %w(asc desc))
|
||||
end
|
||||
|
||||
def custom_sort(relations, sort_by, sort_direction)
|
||||
sort_by ||= self.class.sort_options[:default_by]
|
||||
sort_direction ||= self.class.sort_options[:default_direction]
|
||||
|
||||
return relations unless self.class.check_sort_parameter_validate(sort_by.to_s, sort_direction.to_s)
|
||||
|
||||
order_method = self.class.sort_options[:reorder] ? :reorder : :order
|
||||
relations.send(order_method, "#{sort_by} #{sort_direction}")
|
||||
end
|
||||
|
||||
def multiple_custom_sort(relations, opts)
|
||||
opts.each do |sort_by, sort_direction|
|
||||
relations = custom_sort(relations, sort_by, sort_direction)
|
||||
end
|
||||
relations
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def sort_columns(*columns)
|
||||
opts = columns.extract_options!
|
||||
@_sort_options[:default_by] = opts[:default_by].to_s
|
||||
@_sort_options[:default_direction] = opts[:default_direction].to_s
|
||||
@_sort_options[:reorder] = opts[:reorder]
|
||||
|
||||
@_sort_columns = columns.map(&:to_s)
|
||||
end
|
||||
|
||||
def check_sort_parameter_validate(sort_by, sort_direction)
|
||||
(sort_by.blank? || @_sort_columns.include?(sort_by)) && @_sort_directions.include?(sort_direction)
|
||||
end
|
||||
|
||||
def sort_options
|
||||
@_sort_options
|
||||
end
|
||||
end
|
||||
end
|
@ -1,6 +1,7 @@
|
||||
class Customer < ActiveRecord::Base
|
||||
default_scope :order => 'customers.created_at desc'
|
||||
belongs_to :partner
|
||||
has_one :school
|
||||
has_many :partners, :through => :partner_customers
|
||||
has_many :partner_customers, :dependent => :destroy
|
||||
belongs_to :school
|
||||
has_many :users
|
||||
end
|
||||
|
@ -0,0 +1,8 @@
|
||||
class Openi < ActiveRecord::Base
|
||||
attr_accessible :allow, :avatar_url, :email, :login, :name, :openi_user_id, :user_id
|
||||
belongs_to :user
|
||||
|
||||
def self.find_by_login(login)
|
||||
Openi.where(login: login).first
|
||||
end
|
||||
end
|
@ -0,0 +1,5 @@
|
||||
class PartnerCustomer < ActiveRecord::Base
|
||||
# attr_accessible :title, :body
|
||||
belongs_to :partner
|
||||
belongs_to :customer
|
||||
end
|
@ -0,0 +1,3 @@
|
||||
class SchoolDailyReport < ActiveRecord::Base
|
||||
belongs_to :school
|
||||
end
|
@ -0,0 +1,61 @@
|
||||
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
|
||||
|
||||
count = reports.count('distinct(school_id)')
|
||||
reports = reports.group(:school_id).limit(PAGE_SIZE).offset(offset)
|
||||
|
||||
[count, reports]
|
||||
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
|
||||
end
|
@ -0,0 +1,54 @@
|
||||
class Management::SchoolReportService
|
||||
include CustomSortable
|
||||
|
||||
attr_reader :params
|
||||
|
||||
sort_columns :student_count, :teacher_count, :homework_count, :other_homework_count,
|
||||
:course_count, :active_course_count, :nearly_course_time,
|
||||
default_by: :teacher_count, default_direction: :desc
|
||||
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
schools = School.select(select_columns_sql)
|
||||
|
||||
keyword = params[:keyword].try(:to_s).try(:strip)
|
||||
if keyword.present?
|
||||
schools = schools.where("schools.name LIKE :keyword OR schools.id LIKE :keyword", keyword: "%#{keyword}%")
|
||||
end
|
||||
|
||||
schools = custom_sort(schools, params[:sort_by], params[:sort_direction])
|
||||
|
||||
schools
|
||||
end
|
||||
|
||||
private
|
||||
def select_columns_sql
|
||||
<<-SQL
|
||||
schools.id, schools.name,
|
||||
(
|
||||
SELECT COUNT(*) FROM user_extensions ue
|
||||
WHERE ue.school_id = schools.id AND ue.identity = #{User::STUDENT}
|
||||
) student_count,
|
||||
(
|
||||
SELECT COUNT(*) FROM user_extensions ue
|
||||
WHERE ue.school_id = schools.id AND ue.identity = #{User::TEACHER}
|
||||
) teacher_count,
|
||||
(
|
||||
SELECT COUNT(*) FROM homework_commons hc
|
||||
LEFT JOIN courses ON courses.id = hc.course_id
|
||||
WHERE courses.school_id = schools.id AND hc.homework_type = 4
|
||||
) homework_count,
|
||||
(
|
||||
SELECT COUNT(*) FROM homework_commons hc
|
||||
LEFT JOIN courses ON courses.id = hc.course_id
|
||||
WHERE courses.school_id = schools.id AND hc.homework_type IN (1,3)
|
||||
) other_homework_count,
|
||||
(SELECT COUNT(*) FROM courses cs WHERE cs.school_id = schools.id) course_count ,
|
||||
(SELECT MAX(cs.updated_at) FROM courses cs WHERE cs.school_id = schools.id) nearly_course_time ,
|
||||
(SELECT COUNT(*) FROM courses acs WHERE acs.school_id = schools.id AND acs.is_end = false) active_course_count
|
||||
SQL
|
||||
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,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title><%= h html_title %></title>
|
||||
<meta name="description" content="高校智能课堂与综合实训平台" />
|
||||
<meta name="keywords" content="智能课堂,实训项目" />
|
||||
<%= csrf_meta_tag %>
|
||||
<%= favicon %>
|
||||
<%= javascript_edu_index_heads %>
|
||||
<%= stylesheet_link_tag 'educoder/edu-main', 'educoder/edu-all', 'educoder/magic-check' %>
|
||||
|
||||
</head>
|
||||
|
||||
<div class="newContainer">
|
||||
<div class="newHeader" id="nHeader">
|
||||
<%= render 'layouts/logined_header' %>
|
||||
</div>
|
||||
<div class="newMain clearfix">
|
||||
<%= yield %>
|
||||
</div>
|
||||
<%= render :partial => 'layouts/footer' %>
|
||||
</div>
|
||||
<div id="ajax-indicator" style="display:none;">
|
||||
<span><%= l(:label_loading) %></span>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
<%= javascript_include_tag 'educoder/edu_application','educoder/jquery.raty' %>
|
||||
</html>
|
||||
|
@ -1,14 +1,12 @@
|
||||
<% @partners.each_with_index do |partner,index| %>
|
||||
<li class="clearfix">
|
||||
<%= link_to "#{partner.name}", partners_managements_path(:partner => partner), :class => "#{partner.id == @current_partner.id ? 'active' : ''} fl" %>
|
||||
<% if false %>
|
||||
<%= link_to "#{partner.school.name}", partners_managements_path(:partner => partner), :class => "#{@current_partner && partner.id == @current_partner.id ? 'active' : ''} fl" %>
|
||||
<div class="fr mr10 edu-menu-panel mt5">
|
||||
<i class="iconfont icon-sandian color-grey-9 font-14"></i>
|
||||
<ul class="edu-menuSmall-list edu-txt-center">
|
||||
<li><a href="javascript:void(0)">查看</a></li>
|
||||
<li><a href="javascript:void(0)" onclick="delPartners();">删除</a></li>
|
||||
<li><a href="<%= partners_managements_path(:partner => partner) %>">查看</a></li>
|
||||
<li><a href="javascript:void(0)" onclick="delPartners('<%= delete_partner_managements_path(:partner_id => partner) %>');">删除</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
@ -0,0 +1 @@
|
||||
$("#partner_list").html("<%= j(render :partial => "partner_list") %>")
|
@ -0,0 +1,305 @@
|
||||
<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] %>
|
||||
<!-- 新增数据 -->
|
||||
<%= hidden_field_tag :grow_begin_date, params[:grow_begin_date] %>
|
||||
<%= hidden_field_tag :grow_end_date, params[:grow_end_date] %>
|
||||
|
||||
<div class="grow-date-container" style="width: 450px;display: <%= params[:data_type] == 'grow' ? 'block' : 'none' %>">
|
||||
<%= text_field_tag :grow_date_input, params[:grow_date_input],
|
||||
class: 'grow-date-input winput-220-30', placeholder: '请选择时间段',
|
||||
style: 'width: 400px;' %>
|
||||
</div>
|
||||
<div class="contrast-date-container" style="width: 450px;display: <%= params[:data_type] == 'contrast' ? 'block' : 'none' %>">
|
||||
<%= 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>
|
||||
|
||||
<div style="float: left;">
|
||||
<%= hidden_field_tag :data_type, params[:data_type] || 'grow' %>
|
||||
<% 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 grow-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 grow-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 growFormUrl = "<%= school_data_grow_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 growBtn = searchForm.find(".grow-btn");
|
||||
var contrastDateContainer = searchForm.find('.contrast-date-container');
|
||||
var growDateContainer = searchForm.find('.grow-date-container');
|
||||
|
||||
// 数据对比日期输入框
|
||||
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']");
|
||||
|
||||
// 新增数据日期输入框
|
||||
var growBeginDateInput = searchForm.find("input[name='grow_begin_date']");
|
||||
var growEndDateInput = searchForm.find("input[name='grow_end_date']");
|
||||
|
||||
// 数据展示切换: 数据对比、新增数据
|
||||
searchForm.on('click', ".contrast-btn", function(){
|
||||
if(contrastBtn.hasClass("task-btn-orange")) { return }
|
||||
changeDataType("contrast");
|
||||
submitForm();
|
||||
});
|
||||
searchForm.on('click', ".grow-btn", function(){
|
||||
if(growBtn.hasClass("task-btn-orange")) { return }
|
||||
changeDataType("grow");
|
||||
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 : growFormUrl;
|
||||
|
||||
$.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 true;
|
||||
}
|
||||
|
||||
if (beginDateInput.val() != "" && endDateInput.val() != "" &&
|
||||
otherBeginDateInput.val() != "" && otherBeginDateInput.val() != "") {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
var changeDataType = function(dataType){
|
||||
if (dataTypeInput.val() == dataType) { return }
|
||||
|
||||
if (dataType == "contrast") {
|
||||
contrastBtn.addClass("task-btn-orange");
|
||||
growBtn.removeClass("task-btn-orange");
|
||||
dataTypeInput.val('contrast');
|
||||
growDateContainer.hide();
|
||||
contrastDateContainer.show();
|
||||
|
||||
clearGrowDateInput();
|
||||
} else {
|
||||
contrastBtn.removeClass("task-btn-orange");
|
||||
growBtn.addClass("task-btn-orange");
|
||||
dataTypeInput.val('grow');
|
||||
growDateContainer.show();
|
||||
contrastDateContainer.hide();
|
||||
|
||||
clearContrastDateInput();
|
||||
}
|
||||
};
|
||||
|
||||
var clearGrowDateInput = function() {
|
||||
searchForm.find("input[name='grow_begin_date']").val('');
|
||||
searchForm.find("input[name='grow_end_date']").val('');
|
||||
searchForm.find("input[name='grow_date_input']").val('');
|
||||
};
|
||||
|
||||
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 baseOptions = {
|
||||
dateFormat: 'yy-mm-dd',
|
||||
minDate: new Date('2017-04-01'),
|
||||
maxDate: -1
|
||||
}
|
||||
|
||||
var contrastDateOptions = {
|
||||
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;
|
||||
}
|
||||
},
|
||||
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();
|
||||
}
|
||||
};
|
||||
contrastDateOptions = $.extend({}, locale, baseOptions, contrastDateOptions);
|
||||
searchForm.find(".date-input").datepicker(contrastDateOptions);
|
||||
searchForm.find(".other-date-input").datepicker(contrastDateOptions);
|
||||
|
||||
var growOptions = {
|
||||
onSelect: function(selectedDate) {
|
||||
if(!$(this).data().datepicker.first){
|
||||
$(this).data().datepicker.inline = true;
|
||||
$(this).data().datepicker.first = selectedDate;
|
||||
|
||||
growBeginDateInput.val("");
|
||||
growEndDateInput.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;
|
||||
}
|
||||
|
||||
growBeginDateInput.val(begin_date);
|
||||
growEndDateInput.val(end_date);
|
||||
|
||||
// 展示所选时间
|
||||
$(this).val(begin_date + " 至 " + end_date);
|
||||
$(this).data().datepicker.inline = false;
|
||||
}
|
||||
},
|
||||
onClose:function(){
|
||||
var date = $(this).data().datepicker.first;
|
||||
|
||||
if (date && growBeginDateInput.val() == '') {
|
||||
growBeginDateInput.val(date);
|
||||
growEndDateInput.val(date);
|
||||
}
|
||||
|
||||
delete $(this).data().datepicker.first;
|
||||
$(this).data().datepicker.inline = false;
|
||||
|
||||
submitForm();
|
||||
}
|
||||
};
|
||||
growOptions = $.extend({}, locale, baseOptions, growOptions)
|
||||
searchForm.find(".grow-date-input").datepicker(growOptions);
|
||||
});
|
||||
</script>
|
@ -0,0 +1,51 @@
|
||||
<div style="background-color: #fafafa;">
|
||||
统计总计:
|
||||
<% if params[:grow_begin_date].present? %>
|
||||
<%= params[:grow_date_input] %>
|
||||
<% else %>
|
||||
昨日至今日,
|
||||
<% end %>
|
||||
新增教师<span class="color-red"><%= @grow_summary.teacher_increase_count || 0 %></span>人,
|
||||
新增学生<span class="color-red"><%= @grow_summary.student_increase_count || 0 %></span>人,
|
||||
新增课堂<span class="color-red"><%= @grow_summary.course_increase_count || 0 %></span>个,
|
||||
新增实训<span class="color-red"><%= @grow_summary.shixun_increase_count || 0 %></span>个,
|
||||
活跃用户<span class="color-red"><%= @grow_summary.active_user_count || 0 %></span>个
|
||||
</div>
|
||||
<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_data_grow_managements_path) %></th>
|
||||
<th width="12%"><%= sort_tag('新增学生', name: 'student_increase_count', path: school_data_grow_managements_path) %></th>
|
||||
<th width="12%"><%= sort_tag('新增课堂', name: 'course_increase_count', path: school_data_grow_managements_path) %></th>
|
||||
<th width="12%"><%= sort_tag('新增实训', name: 'shixun_increase_count', path: school_data_grow_managements_path) %></th>
|
||||
<th width="12%"><%= sort_tag('活跃用户', name: 'active_user_count', path: school_data_grow_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_data_grow_ref_pages">
|
||||
<%= pagination_links_full @obj_pages, @obj_count, per_page_links: false, remote: true, flag: true, is_new: true, path: school_data_grow_managements_path(params.except(:page)) %>
|
||||
</ul>
|
||||
<div class="cl"></div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,42 @@
|
||||
<table class="edu-pop-table edu-txt-center" cellpadding="0" cellspacing="0" style="table-layout: fixed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="6%">序号</th>
|
||||
<th width="6%">ID</th>
|
||||
<th width="14%" class="edu-txt-left">单位名称</th>
|
||||
|
||||
<th width="10%"><%= sort_tag('教师总人数', name: 'teacher_count', path: school_report_managements_path) %></th>
|
||||
<th width="10%"><%= sort_tag('学生总人数', name: 'student_count', path: school_report_managements_path) %></th>
|
||||
<th width="10%"><%= sort_tag('课堂总数', name: 'course_count', path: school_report_managements_path) %></th>
|
||||
<th width="10%"><%= sort_tag('正在进行课堂数', name: 'active_course_count', path: school_report_managements_path) %></th>
|
||||
<th width="10%"><%= sort_tag('实训作业总数', name: 'homework_count', path: school_report_managements_path) %></th>
|
||||
<th width="10%"><%= sort_tag('其它作业总数', name: 'other_homework_count', path: school_report_managements_path) %></th>
|
||||
<th width="14%"><%= sort_tag('动态时间', name: 'nearly_course_time', path: school_report_managements_path) %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @schools.each_with_index do |school, index| %>
|
||||
<tr>
|
||||
<td><%= (@obj_pages.page - 1) * @obj_pages.per_page + index + 1 %></td>
|
||||
<td><%= school['id'] %></td>
|
||||
<td class="edu-txt-left"><%= school['name'] %></td>
|
||||
<td><%= school['teacher_count'] %></td>
|
||||
<td><%= school['student_count'] %></td>
|
||||
<td><%= school['course_count'] %></td>
|
||||
<td><%= school['active_course_count'] %></td>
|
||||
<td><%= school['homework_count'] %></td>
|
||||
<td><%= school['other_homework_count'] %></td>
|
||||
<td><%= format_time school['nearly_course_time'] %></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_report_ref_pages">
|
||||
<%= pagination_links_full @obj_pages, @obj_count, per_page_links: false, remote: true, flag: true, is_new: true, path: school_report_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/data_grow_list'%>
|
||||
</div>
|
@ -0,0 +1,2 @@
|
||||
$("#managements-school-data").html("<%= j(render 'managements/schools/data_grow_list') %>")
|
||||
$(".management-school-data-form-box").html("<%= j(render 'managements/schools/contrast_search_form') %>")
|
@ -0,0 +1,45 @@
|
||||
<div class="edu-con-top clearfix xmt10 bor-grey-e mt10">
|
||||
<%= form_tag(school_report_managements_path(params), method: :get, remote: true, id: 'school_report_search_form') do %>
|
||||
<%= 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', onclick: "$('#school_report_search_form').submit();" %>
|
||||
<%= link_to '清除', 'javascript:clearSearchCondition()', class: 'fl task-btn ml5 mt2 mt10' %>
|
||||
|
||||
<div style="float: right;">
|
||||
<%= link_to '导出Excel', school_statistics_xlsx_managements_path(format: :xlsx),
|
||||
class: 'fl task-btn task-btn-orange mt10 mr20 export-statistic-btn',
|
||||
onclick: 'exportSchoolStatistic();' %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="edu-con-bg01 clearfix mt10 bor-grey-e pt10 pb10">
|
||||
<div class="pl15">
|
||||
统计总计:
|
||||
教师总人数<span class="color-red"><%= @teacher_total %></span>人,
|
||||
学生总人数<span class="color-red"><%= @student_total %></span>人,
|
||||
课堂总数<span class="color-red"><%= @course_total %></span>个,
|
||||
正在进行课堂总数<span class="color-red"><%= @active_course_total %></span>个,
|
||||
实训作业总数<span class="color-red"><%= @shixun_homework_total %></span>个,
|
||||
其它作业总数<span class="color-red"><%= @other_homework_total %></span>个,
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="edu-con-bg01 mt15" id="managements_school_report">
|
||||
<%= render 'managements/schools/statistics_list'%>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function clearSearchCondition(){
|
||||
$("#school_report_search_form input[name='keyword']").val("");
|
||||
$('#school_report_search_form').submit();
|
||||
}
|
||||
|
||||
function exportSchoolStatistic(){
|
||||
var form = $("#school_report_search_form")
|
||||
var exportLink = form.find(".export-statistic-btn");
|
||||
var keyword = form.find("input[name='keyword']").val();
|
||||
exportLink.attr("href", exportLink.attr("href").split('?')[0] + "?keyword=" + keyword);
|
||||
}
|
||||
</script>
|
@ -0,0 +1 @@
|
||||
$("#managements_school_report").html("<%= j(render 'managements/schools/statistics_list') %>")
|
@ -0,0 +1,20 @@
|
||||
wb = xlsx_package.workbook
|
||||
wb.add_worksheet(name: "统计总表") do |sheet|
|
||||
sheet.add_row %w(ID 单位名称 教师总人数 学生总人数 课堂总数 正在进行课堂数 实训作业总数 其它作业总数 动态时间)
|
||||
|
||||
total = @schools.count
|
||||
buffer_size = 500
|
||||
times = total % 500 > 0 ? total / 500 + 1 : total / 500
|
||||
|
||||
times.times do |index|
|
||||
schools = @schools.limit(buffer_size).offset(index * buffer_size)
|
||||
|
||||
schools.each do |school|
|
||||
sheet.add_row([
|
||||
school['id'].to_s, school['name'].to_s, school['teacher_count'].to_s, school['student_count'].to_s,
|
||||
school['course_count'].to_s, school['active_course_count'].to_s, school['homework_count'].to_s,
|
||||
school['other_homework_count'].to_s, format_time(school['nearly_course_time'])
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
@ -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,9 @@
|
||||
class CreatePartnerCustomers < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :partner_customers do |t|
|
||||
t.references :partner
|
||||
t.references :customer
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,29 @@
|
||||
class ModifyPartnerAndCustomer < ActiveRecord::Migration
|
||||
def up
|
||||
add_column :customers, :school_id, :integer
|
||||
add_column :partners, :school_id, :integer
|
||||
|
||||
schools = School.where("customer_id is not null or partner_id is not null")
|
||||
|
||||
schools.each do |school|
|
||||
if school.customer_id
|
||||
customer = Customer.find_by_id(school.customer_id)
|
||||
customer.update_column(:school_id, school.id) if customer
|
||||
end
|
||||
if school.partner_id
|
||||
partner = Partner.find_by_id(school.partner_id)
|
||||
partner.update_column(:school_id, school.id) if partner
|
||||
end
|
||||
end
|
||||
|
||||
# 迁移关联关系
|
||||
customers = Customer.where(nil)
|
||||
customers.each do |customer|
|
||||
PartnerCustomer.create(partner_id: customer.partner_id, customer_id: customer.id)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def down
|
||||
end
|
||||
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,5 @@
|
||||
class AddBusinessToUser < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :users, :business, :boolean, :default => false
|
||||
end
|
||||
end
|
@ -0,0 +1,15 @@
|
||||
class CreateOpenis < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :openis do |t|
|
||||
t.integer :user_id
|
||||
t.integer :openi_user_id
|
||||
t.string :login
|
||||
t.string :avatar_url
|
||||
t.string :name
|
||||
t.string :email
|
||||
t.integer :allow
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
@ -0,0 +1,9 @@
|
||||
class AddIndexToSchoolDailyReports < ActiveRecord::Migration
|
||||
def change
|
||||
add_index :school_daily_reports, [:date, :teacher_increase_count]
|
||||
add_index :school_daily_reports, [:date, :student_increase_count]
|
||||
add_index :school_daily_reports, [:date, :course_increase_count]
|
||||
add_index :school_daily_reports, [:date, :shixun_increase_count]
|
||||
add_index :school_daily_reports, [:date, :active_user_count]
|
||||
end
|
||||
end
|
@ -0,0 +1,108 @@
|
||||
#coding=utf-8
|
||||
|
||||
namespace :school_daily_report do
|
||||
desc 'daily statistic school task'
|
||||
task daily_statistic: :environment do
|
||||
StatisticSchoolDailyReportTask.new.call
|
||||
end
|
||||
|
||||
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
|
@ -0,0 +1,11 @@
|
||||
FactoryGirl.define do
|
||||
factory :openi do
|
||||
user_id 1
|
||||
openi_user_id 1
|
||||
login "MyString"
|
||||
avatar_url "MyString"
|
||||
name "MyString"
|
||||
email "MyString"
|
||||
allow 1
|
||||
end
|
||||
end
|
@ -0,0 +1,5 @@
|
||||
FactoryGirl.define do
|
||||
factory :partner_customer do
|
||||
|
||||
end
|
||||
end
|
@ -0,0 +1,5 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Openi, :type => :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
@ -0,0 +1,5 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe PartnerCustomer, :type => :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
Loading…
Reference in new issue