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:
parent
569cc1b737
commit
d84238b331
@ -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
|
||||||
|
@ -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)">
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
84
app/views/api/statistics/export_global.xlsx.axlsx
Normal file
84
app/views/api/statistics/export_global.xlsx.axlsx
Normal 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
|
Loading…
Reference in New Issue
Block a user