dev_partners
Alec Zhou 6 years ago
commit 59e084ba48

@ -63,7 +63,8 @@ gem 'elasticsearch-rails'
gem 'oauth2' gem 'oauth2'
# xlsx # xlsx
# gem 'axlsx_rails', '0.3.0' gem 'axlsx', '3.0.0.pre'
gem 'axlsx_rails', '0.3.0'
#Ruby 2.2+ has removed test/unit from the core library. #Ruby 2.2+ has removed test/unit from the core library.
if RUBY_VERSION>='2.2' if RUBY_VERSION>='2.2'

@ -16,13 +16,17 @@ class Managements::SchoolsController < Managements::BaseController
end end
end end
def yesterday_data def data_grow
@sub_type = 2 @sub_type = 2
params[:data_type] ||= 'grow'
params[:sort_by] ||= :teacher_increase_count params[:sort_by] ||= :teacher_increase_count
params[:sort_direction] ||= :desc params[:sort_direction] ||= :desc
reports = Management::SchoolYesterdayDataService.new(params).call service = Management::SchoolDataGrowService.new(params)
@reports = paginateHelper reports @grow_summary = service.grow_summary
@obj_count, @reports = service.call
@obj_pages = Paginator.new(@obj_count, Management::SchoolDataGrowService::PAGE_SIZE, params[:page])
end end
def data_contrast def data_contrast
@ -30,6 +34,12 @@ class Managements::SchoolsController < Managements::BaseController
params[:sort_direction] ||= :desc params[:sort_direction] ||= :desc
params[:sort_by] ||= :percentage params[:sort_by] ||= :percentage
# 无对比日期时直接返回无数据页面
if useless_contrast_date_parameter?
@obj_count, @reports = 0, []
return
end
@obj_count, @reports = Management::SchoolDataContrastService.new(params).call @obj_count, @reports = Management::SchoolDataContrastService.new(params).call
@obj_pages = Paginator.new(@obj_count, Management::SchoolDataContrastService::PAGE_SIZE, params[:page]) @obj_pages = Paginator.new(@obj_count, Management::SchoolDataContrastService::PAGE_SIZE, params[:page])
rescue Management::SchoolDataContrastService::ParameterError rescue Management::SchoolDataContrastService::ParameterError
@ -54,6 +64,11 @@ class Managements::SchoolsController < Managements::BaseController
end end
end end
def useless_contrast_date_parameter?
params[:begin_date].blank? && params[:end_date].blank? &&
params[:other_begin_date].blank? &&params[:other_end_date].blank?
end
def load_statistic_total def load_statistic_total
@teacher_total = User.teacher.count @teacher_total = User.teacher.count
@student_total = User.student.count @student_total = User.student.count

@ -0,0 +1,81 @@
class Management::SchoolDataGrowService
include CustomSortable
PAGE_SIZE = 20
attr_reader :params
sort_columns :teacher_increase_count, :student_increase_count,
:course_increase_count, :shixun_increase_count, :active_user_count,
default_by: :teacher_increase_count, default_direction: :desc
def initialize(params)
@params = params
end
def call
reports = query_reports.group(:school_id)
count = reports.count.count
reports = reports.select(
'school_id, school_name,'\
'SUM(teacher_increase_count) teacher_increase_count,'\
'SUM(student_increase_count) student_increase_count,'\
'SUM(course_increase_count) course_increase_count,'\
'SUM(shixun_increase_count) shixun_increase_count,'\
'SUM(active_user_count) active_user_count'
)
reports = custom_sort(reports, params[:sort_by], params[:sort_direction])
reports = reports.limit(PAGE_SIZE).offset(offset)
[count, reports]
end
def grow_summary
@_grow_summary ||= begin
query_reports.select(
'SUM(teacher_increase_count) teacher_increase_count,'\
'SUM(student_increase_count) student_increase_count,'\
'SUM(course_increase_count) course_increase_count,'\
'SUM(shixun_increase_count) shixun_increase_count,'\
'SUM(active_user_count) active_user_count'
).first
end
end
private
def query_reports
reports = SchoolDailyReport.where(date: query_date)
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
end
def query_date
if params[:grow_begin_date].present?
begin_time = Time.zone.parse(params[:grow_begin_date])
end_date = if params[:grow_end_date].present?
Time.zone.parse(params[:grow_end_date])
end
end_date.blank? || end_date == begin_time ? begin_time : begin_time..end_date
else
yesterday
end
end
def yesterday
# 每日凌晨5点为节点, 25日凌晨4点、3点、2点等等未到更新数据时间点看到的数据是23日-24日的统计数据
(Time.zone.now - 5.hours).beginning_of_day - 1.days
end
def offset
(params[:page].to_i.zero? ? 0 : params[:page].to_i - 1) * PAGE_SIZE
end
end

@ -1,32 +0,0 @@
class Management::SchoolYesterdayDataService
include CustomSortable
attr_reader :params
sort_columns :student_increase_count, :teacher_increase_count,
:course_increase_count, :shixun_increase_count, :active_user_count,
default_by: :teacher_increase_count, default_direction: :desc
def initialize(params)
@params = params
end
def call
reports = SchoolDailyReport.where(date: yesterday)
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 = custom_sort(reports, params[:sort_by], params[:sort_direction])
reports
end
private
def yesterday
# 每日凌晨5点为节点, 25日凌晨4点、3点、2点等等未到更新数据时间点看到的数据是23日-24日的统计数据
(Time.zone.now - 5.hours).beginning_of_day - 1.days
end
end

@ -35,7 +35,7 @@
<li class="fl edu-admin-nav-li edu-position <%= 'active' if @menu_type == 1 %>"><a href="javascript:void(0);" class="edu-admin-nav-a">学校+</a> <li class="fl edu-admin-nav-li edu-position <%= 'active' if @menu_type == 1 %>"><a href="javascript:void(0);" class="edu-admin-nav-a">学校+</a>
<ul class="edu-admin-nav-inner edu-absolute"> <ul class="edu-admin-nav-inner edu-absolute">
<li><%= link_to '统计总表', school_report_managements_path %></li> <li><%= link_to '统计总表', school_report_managements_path %></li>
<li><%= link_to '数据变化报表', school_yesterday_data_managements_path %></li> <li><%= link_to '数据变化报表', school_data_grow_managements_path %></li>
</ul> </ul>
</li> </li>
<li class="fl edu-admin-nav-li edu-position <%= 'active' if @menu_type == 2 %>"><a href="javascript:void(0);" class="edu-admin-nav-a">课堂+</a> <li class="fl edu-admin-nav-li edu-position <%= 'active' if @menu_type == 2 %>"><a href="javascript:void(0);" class="edu-admin-nav-a">课堂+</a>

@ -1,26 +1,37 @@
<form class="management-school-data-form"> <form class="management-school-data-form">
<div style="float: left; margin: 10px 10px 10px 25px;"> <div style="float: left; margin: 10px 10px 10px 25px;">
<!-- 数据对比 -->
<%= hidden_field_tag :contrast_column, params[:contrast_column] %> <%= hidden_field_tag :contrast_column, params[:contrast_column] %>
<%= hidden_field_tag :begin_date, params[:begin_date] %> <%= hidden_field_tag :begin_date, params[:begin_date] %>
<%= hidden_field_tag :end_date, params[:end_date] %> <%= hidden_field_tag :end_date, params[:end_date] %>
<%= hidden_field_tag :other_begin_date, params[:other_begin_date] %> <%= hidden_field_tag :other_begin_date, params[:other_begin_date] %>
<%= hidden_field_tag :other_end_date, params[:other_end_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], <%= text_field_tag :date_input, params[:date_input],
class: 'date-input winput-200-30', placeholder: '请选择时间段一' %> class: 'date-input winput-200-30', placeholder: '请选择时间段一' %>
<span>VS</span> <span>VS</span>
<%= text_field_tag :other_date_input, params[:other_date_input], <%= text_field_tag :other_date_input, params[:other_date_input],
class: 'other-date-input winput-200-30', placeholder: '请选择时间段二' %> class: 'other-date-input winput-200-30', placeholder: '请选择时间段二' %>
</div> </div>
</div>
<div style="float: left;"> <div style="float: left;">
<%= hidden_field_tag :data_type, params[:data_type] || 'yesterday' %> <%= hidden_field_tag :data_type, params[:data_type] || 'grow' %>
<% if params[:data_type] == 'contrast' %> <% 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 contrast-btn task-btn-orange">时间对比</a>
<a href="javascript:void(0)" class="fl task-btn ml5 mt10 yesterday-btn">日新增</a> <a href="javascript:void(0)" class="fl task-btn ml5 mt10 grow-btn">新增数据</a>
<% else %> <% 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 contrast-btn">时间对比</a>
<a href="javascript:void(0)" class="fl task-btn ml5 mt10 yesterday-btn task-btn-orange">日新增</a> <a href="javascript:void(0)" class="fl task-btn ml5 mt10 grow-btn task-btn-orange">新增数据</a>
<% end %> <% end %>
</div> </div>
@ -31,28 +42,36 @@
</form> </form>
<script> <script>
$(function(){ $(function(){
var yesterdayFormUrl = "<%= school_yesterday_data_managements_path %>"; var growFormUrl = "<%= school_data_grow_managements_path %>";
var contrastFormUrl = "<%= school_data_contrast_managements_path %>"; var contrastFormUrl = "<%= school_data_contrast_managements_path %>";
var searchForm = $(".management-school-data-form"); var searchForm = $(".management-school-data-form");
var dataTypeInput = searchForm.find("input[name='data_type']"); var dataTypeInput = searchForm.find("input[name='data_type']");
var keywordInput = searchForm.find("input[name='keyword']"); var keywordInput = searchForm.find("input[name='keyword']");
var contrastBtn = searchForm.find(".contrast-btn"); var contrastBtn = searchForm.find(".contrast-btn");
var yesterdayBtn = searchForm.find(".yesterday-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 beginDateInput = searchForm.find("input[name='begin_date']");
var endDateInput = searchForm.find("input[name='end_date']"); var endDateInput = searchForm.find("input[name='end_date']");
var otherBeginDateInput = searchForm.find("input[name='other_begin_date']"); var otherBeginDateInput = searchForm.find("input[name='other_begin_date']");
var otherEndDateInput = searchForm.find("input[name='other_end_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(){ searchForm.on('click', ".contrast-btn", function(){
if(contrastBtn.hasClass("task-btn-orange")) { return } if(contrastBtn.hasClass("task-btn-orange")) { return }
changeDataType("contrast"); changeDataType("contrast");
submitForm();
}); });
searchForm.on('click', ".yesterday-btn", function(){ searchForm.on('click', ".grow-btn", function(){
if(yesterdayBtn.hasClass("task-btn-orange")) { return } if(growBtn.hasClass("task-btn-orange")) { return }
changeDataType("yesterday"); changeDataType("grow");
submitForm(); submitForm();
}); });
@ -74,7 +93,7 @@
if(!validateFrom()) { return } if(!validateFrom()) { return }
var form = searchForm; var form = searchForm;
var url = dataTypeInput.val() == "contrast" ? contrastFormUrl : yesterdayFormUrl; var url = dataTypeInput.val() == "contrast" ? contrastFormUrl : growFormUrl;
$.ajax({ $.ajax({
url: url, url: url,
@ -86,12 +105,18 @@
var validateFrom = function(){ var validateFrom = function(){
if (dataTypeInput.val() != "contrast") { return true; } if (dataTypeInput.val() != "contrast") { return true; }
if (beginDateInput.val() == "" || endDateInput.val() == "" || // 全部为空时,需要展示空数据页
otherBeginDateInput.val() == "" || otherBeginDateInput.val() == "") { if (beginDateInput.val() == "" && endDateInput.val() == "" &&
return false; otherBeginDateInput.val() == "" && otherBeginDateInput.val() == "") {
return true;
} }
if (beginDateInput.val() != "" && endDateInput.val() != "" &&
otherBeginDateInput.val() != "" && otherBeginDateInput.val() != "") {
return true; return true;
}
return false;
}; };
var changeDataType = function(dataType){ var changeDataType = function(dataType){
@ -99,17 +124,29 @@
if (dataType == "contrast") { if (dataType == "contrast") {
contrastBtn.addClass("task-btn-orange"); contrastBtn.addClass("task-btn-orange");
yesterdayBtn.removeClass("task-btn-orange"); growBtn.removeClass("task-btn-orange");
dataTypeInput.val('contrast'); dataTypeInput.val('contrast');
growDateContainer.hide();
contrastDateContainer.show();
clearGrowDateInput();
} else { } else {
contrastBtn.removeClass("task-btn-orange"); contrastBtn.removeClass("task-btn-orange");
yesterdayBtn.addClass("task-btn-orange"); growBtn.addClass("task-btn-orange");
dataTypeInput.val('yesterday'); dataTypeInput.val('grow');
growDateContainer.show();
contrastDateContainer.hide();
clearContrastDateInput(); 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(){ var clearContrastDateInput = function(){
searchForm.find("input[name='begin_date']").val(''); searchForm.find("input[name='begin_date']").val('');
searchForm.find("input[name='end_date']").val(''); searchForm.find("input[name='end_date']").val('');
@ -152,10 +189,13 @@
isRTL: false isRTL: false
}; };
var options = { var baseOptions = {
dateFormat: 'yy-mm-dd', dateFormat: 'yy-mm-dd',
minDate: new Date('2017-04-01'), minDate: new Date('2017-04-01'),
maxDate: -1, maxDate: -1
}
var contrastDateOptions = {
onSelect: function(selectedDate) { onSelect: function(selectedDate) {
if(!$(this).data().datepicker.first){ if(!$(this).data().datepicker.first){
$(this).data().datepicker.inline = true; $(this).data().datepicker.inline = true;
@ -192,9 +232,6 @@
// 展示所选时间 // 展示所选时间
$(this).val(begin_date + " 至 " + end_date); $(this).val(begin_date + " 至 " + end_date);
$(this).data().datepicker.inline = false; $(this).data().datepicker.inline = false;
// 切换数据类型
changeDataType("contrast");
} }
}, },
onClose:function(){ onClose:function(){
@ -216,8 +253,53 @@
submitForm(); submitForm();
} }
}; };
options = $.extend({}, locale, options); contrastDateOptions = $.extend({}, locale, baseOptions, contrastDateOptions);
searchForm.find(".date-input").datepicker(options); searchForm.find(".date-input").datepicker(contrastDateOptions);
searchForm.find(".other-date-input").datepicker(options); 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> </script>

@ -6,8 +6,15 @@
options_for_select(@select_options, params[:contrast_column]), options_for_select(@select_options, params[:contrast_column]),
class: 'fl task-height-30 contrast-column-select', class: 'fl task-height-30 contrast-column-select',
style: 'position: absolute; right: 30px; top: 15px;' %> style: 'position: absolute; right: 30px; top: 15px;' %>
<% if @obj_count.nonzero? %>
<div style="position: absolute; left: 20px; bottom: 0; font-size: 12px;">
说明:新增数=时段二-时段一;新增百分比=(新增数/时段一)*100%(保留小数点后五位)
</div>
<% end %>
</div> </div>
<% if @obj_count.nonzero? %>
<table class="edu-pop-table edu-txt-center" cellpadding="0" cellspacing="0" style="table-layout: fixed"> <table class="edu-pop-table edu-txt-center" cellpadding="0" cellspacing="0" style="table-layout: fixed">
<thead> <thead>
<tr> <tr>
@ -63,6 +70,11 @@
<div class="cl"></div> <div class="cl"></div>
</div> </div>
</div> </div>
<% else %>
<div style="padding-top: 150px; height: 250px; text-align: center; color: grey; font-size: 14px;">
暂无数据,请选择时间段对比
</div>
<% end %>
<style> <style>
.right-border::after { .right-border::after {
position: absolute; position: absolute;

@ -1,3 +1,16 @@
<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"> <table class="edu-pop-table edu-txt-center" cellpadding="0" cellspacing="0" style="table-layout: fixed">
<thead> <thead>
<tr> <tr>
@ -5,11 +18,11 @@
<th width="10%">ID</th> <th width="10%">ID</th>
<th width="24%" class="edu-txt-left">单位名称</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: 'teacher_increase_count', path: school_data_grow_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: 'student_increase_count', path: school_data_grow_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: 'course_increase_count', path: school_data_grow_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: 'shixun_increase_count', path: school_data_grow_managements_path) %></th>
<th width="12%"><%= sort_tag('活跃用户', name: 'active_user_count', path: school_yesterday_data_managements_path) %></th> <th width="12%"><%= sort_tag('活跃用户', name: 'active_user_count', path: school_data_grow_managements_path) %></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -30,8 +43,8 @@
<div style="text-align:center;" class="new_expand"> <div style="text-align:center;" class="new_expand">
<div class="pages_user_show" style="width:auto; display:inline-block;margin: 18px 0;"> <div class="pages_user_show" style="width:auto; display:inline-block;margin: 18px 0;">
<ul id="school_yesterday_data_ref_pages"> <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_yesterday_data_managements_path(params.except(:page)) %> <%= 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> </ul>
<div class="cl"></div> <div class="cl"></div>
</div> </div>

@ -5,5 +5,5 @@
</div> </div>
<div class="edu-con-bg01 mt15" id="managements-school-data"> <div class="edu-con-bg01 mt15" id="managements-school-data">
<%= render 'managements/schools/yesterday_data_list'%> <%= render 'managements/schools/data_grow_list'%>
</div> </div>

@ -1,2 +1,2 @@
$("#managements-school-data").html("<%= j(render 'managements/schools/yesterday_data_list') %>") $("#managements-school-data").html("<%= j(render 'managements/schools/data_grow_list') %>")
$(".management-school-data-form-box").html("<%= j(render 'managements/schools/contrast_search_form') %>") $(".management-school-data-form-box").html("<%= j(render 'managements/schools/contrast_search_form') %>")

@ -39,7 +39,7 @@
function exportSchoolStatistic(){ function exportSchoolStatistic(){
var form = $("#school_report_search_form") var form = $("#school_report_search_form")
var exportLink = form.find(".export-statistic-btn"); var exportLink = form.find(".export-statistic-btn");
var keyword = form.find("input[name='keyword'").val(); var keyword = form.find("input[name='keyword']").val();
exportLink.attr("href", exportLink.attr("href") + "?keyword=" + keyword); exportLink.attr("href", exportLink.attr("href").split('?')[0] + "?keyword=" + keyword);
} }
</script> </script>

@ -726,7 +726,7 @@ RedmineApp::Application.routes.draw do ## oauth相关
delete :delete_partner delete :delete_partner
get :customers_list get :customers_list
get :school_report, controller: 'managements::schools', action: 'statistics' get :school_report, controller: 'managements::schools', action: 'statistics'
get :school_yesterday_data, controller: 'managements::schools', action: 'yesterday_data' get :school_data_grow, controller: 'managements::schools', action: 'data_grow'
get :school_data_contrast, controller: 'managements::schools', action: 'data_contrast' get :school_data_contrast, controller: 'managements::schools', action: 'data_contrast'
get :school_statistics_xlsx, controller: 'managements::schools', action: 'statistics_xlsx' get :school_statistics_xlsx, controller: 'managements::schools', action: 'statistics_xlsx'
end end

Loading…
Cancel
Save