1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-12-01 12:24:28 +01:00

statistics: global export to excel

This commit is contained in:
Sylvain 2016-07-12 12:03:38 +02:00
parent 569cc1b737
commit d84238b331
5 changed files with 114 additions and 9 deletions

View File

@ -604,9 +604,6 @@ Application.Controllers.controller 'ExportStatisticsController', [ '$scope', '$u
$scope.setRequest = -> $scope.setRequest = ->
if $scope.export.type == 'global' if $scope.export.type == 'global'
$scope.actionUrl = '/stats/global/export' $scope.actionUrl = '/stats/global/export'
$scope.query = JSON.stringify(query)
else
$scope.actionUrl = '/stats/'+index.key+'/export'
$scope.query = JSON.stringify( $scope.query = JSON.stringify(
"query": "query":
"bool": "bool":
@ -614,11 +611,16 @@ Application.Controllers.controller 'ExportStatisticsController', [ '$scope', '$u
{ {
"range": "range":
"date": "date":
"gte": moment(info.dates.start).format() "gte": moment($scope.dates.start).format()
"lte": moment(info.dates.end).format() "lte": moment($scope.dates.end).format()
} }
] ]
) )
else
$scope.actionUrl = '/stats/'+index.key+'/export'
$scope.query = JSON.stringify(query)
## ##
# Callback to close the modal, telling the caller what is exported # Callback to close the modal, telling the caller what is exported

View File

@ -24,6 +24,7 @@
show-button-bar="false" show-button-bar="false"
placeholder="{{ 'start' | translate }}" placeholder="{{ 'start' | translate }}"
ng-click="toggleStartDatePicker($event)" ng-click="toggleStartDatePicker($event)"
ng-change="setRequest()"
required="required"/> required="required"/>
<span class="input-group-btn"> <span class="input-group-btn">
<button type="button" class="btn btn-default btn-search-datepicker" ng-click="toggleStartDatePicker($event)"> <button type="button" class="btn btn-default btn-search-datepicker" ng-click="toggleStartDatePicker($event)">
@ -47,6 +48,7 @@
show-button-bar="false" show-button-bar="false"
placeholder="{{ 'end' | translate }}" placeholder="{{ 'end' | translate }}"
ng-click="toggleEndDatePicker($event)" ng-click="toggleEndDatePicker($event)"
ng-change="setRequest()"
required="required"/> required="required"/>
<span class="input-group-btn"> <span class="input-group-btn">
<button type="button" class="btn btn-default btn-search-datepicker" ng-click="toggleEndDatePicker($event)"> <button type="button" class="btn btn-default btn-search-datepicker" ng-click="toggleEndDatePicker($event)">

View File

@ -16,7 +16,7 @@ class API::StatisticsController < API::ApiController
end end
def export_#{path} def export_#{path}
authorize :statistic, :#{path}? authorize :statistic, :export_#{path}?
query = MultiJson.load(params[:body]) query = MultiJson.load(params[:body])
type_key = params[:type_key] type_key = params[:type_key]
@ -43,9 +43,25 @@ class API::StatisticsController < API::ApiController
end end
def export_global def export_global
authorize :statistic, :export_global?
# query all stats with range arguments # query all stats with range arguments
Elasticsearch::Model.client.search query = MultiJson.load(params[:body])
render xls: []
@results = Elasticsearch::Model.client.search({index: 'stats', scroll: '30s', body: query})
scroll_id = @results['_scroll_id']
while @results['hits']['hits'].size != @results['hits']['total']
scroll_res = Elasticsearch::Model.client.scroll(scroll: '30s', scroll_id: scroll_id)
@results['hits']['hits'].concat(scroll_res['hits']['hits'])
scroll_id = scroll_res['_scroll_id']
end
ids = @results['hits']['hits'].map { |u| u['_source']['userId'] }
@users = User.includes(:profile).where(:id => ids)
@indices = StatisticIndex.all.includes(:statistic_fields, :statistic_types => [:statistic_sub_types])
render xlsx: 'export_global.xlsx', filename: "statistics.xlsx"
end end
def scroll def scroll

View File

@ -1,5 +1,6 @@
class StatisticPolicy < ApplicationPolicy class StatisticPolicy < ApplicationPolicy
%w(index account event machine project subscription training user scroll).each do |action| %w(index account event machine project subscription training user scroll export_subscription export_machine
export_training export_event export_account export_project export_global).each do |action|
define_method "#{action}?" do define_method "#{action}?" do
user.is_admin? user.is_admin?
end end

View File

@ -0,0 +1,84 @@
wb = xlsx_package.workbook
header = wb.styles.add_style :b => true, :bg_color => Stylesheet.primary.upcase.gsub('#', 'FF'), :fg_color => 'FFFFFFFF'
date = wb.styles.add_style :format_code => Rails.application.secrets.excel_date_format
@indices.each do |index|
if index.table
index.statistic_types.each do |type|
# see https://msdn.microsoft.com/fr-fr/library/c6bdca6y(v=vs.90).aspx for unauthorized character list
sheet_name = "#{index.label} - #{type.label}".gsub(/[*|\\:"<>?\/]/,'').truncate(31)
wb.add_worksheet(name: sheet_name) do |sheet|
## data table
# heading labels
columns = [t('export.date'), t('export.user'), t('export.email'), t('export.phone'), t('export.gender'), t('export.age'), t('export.type')]
columns.push type.label unless type.simple
index.statistic_fields.each do |f|
columns.push f.label
end
columns.push t('export.revenue') if index.ca
sheet.add_row columns, :style => header
# data rows
@results['hits']['hits'].each do |hit|
# check that the current result is for the given index and type
if hit['_type'] == index.es_type_key and hit['_source']['type'] == type.key
# get matching objects
user = get_item(@users, hit['_source']['userId'])
subtype = get_item(type.statistic_sub_types, hit['_source']['subType'], 'key')
# start to fill data and associated styles and data-types
data = [
Date::strptime(hit['_source']['date'],'%Y-%m-%d'),
user.profile.full_name,
user.email,
user.profile.phone,
t("export.#{hit['_source']['gender']}"),
hit['_source']['age'],
subtype.nil? ? "" : subtype.label
]
styles = [date, nil, nil, nil, nil, nil, nil]
types = [:date, :string, :string, :string, :string, :integer, :string]
# do not proceed with the 'stat' field if the type is declared as 'simple'
unless type.simple
data.push hit['_source']['stat']
styles.push nil
types.push :string
end
# proceed additional fields
index.statistic_fields.each do |f|
field_data = hit['_source'][f.key]
case f.data_type
when 'date'
data.push Date::strptime(field_data, '%Y-%m-%d')
styles.push date
types.push :date
when 'list'
data.push field_data.map{|e| e['name'] }.join(', ')
styles.push nil
types.push :string
when 'number'
data.push field_data
styles.push nil
types.push :float
else
data.push field_data
styles.push nil
types.push :string
end
end
# proceed teh 'ca' field if requested
if index.ca
data.push hit['_source']['ca']
styles.push nil
types.push :float
end
# finally, add the data row to the workbook's sheet
sheet.add_row data, :style => styles, :types => types
end
end
end
end
end
end