mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-19 08:52:25 +01:00
Merge branch 'dev' for release 5.5.4
This commit is contained in:
commit
48d8b5dfab
@ -1,5 +1,10 @@
|
||||
# Changelog Fab-manager
|
||||
|
||||
## v5.5.4 2022 November 17
|
||||
|
||||
- Fix a bug: unable to download an existing export of the statistics
|
||||
- Fix a security issue: updated loader-utils to 2.0.4 to fix [CVE-2022-37601](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-37601), [CVE-2022-37603](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-37603) and [CVE-2022-37599](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-37599)
|
||||
|
||||
## v5.5.3 2022 November 17
|
||||
|
||||
- By default, sort invoices by date in the admin list
|
||||
|
@ -30,7 +30,7 @@ class Statistics::QueryService
|
||||
query: params[:body],
|
||||
key: params[:type_key])
|
||||
else
|
||||
File.root.join(export.file)
|
||||
Rails.root.join(export.file)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fab-manager",
|
||||
"version": "5.5.3",
|
||||
"version": "5.5.4",
|
||||
"description": "Fab-manager is the FabLab management solution. It provides a comprehensive, web-based, open-source tool to simplify your administrative tasks and your marker's projects.",
|
||||
"keywords": [
|
||||
"fablab",
|
||||
|
14
test/fixtures/statistic_custom_aggregations.yml
vendored
14
test/fixtures/statistic_custom_aggregations.yml
vendored
@ -6,3 +6,17 @@ one:
|
||||
field: "available_hours"
|
||||
es_index: "fablab"
|
||||
es_type: "availabilities"
|
||||
|
||||
two:
|
||||
query: '{"size":0, "aggregations":{"%{aggs_name}":{"sum":{"field":"nb_total_places"}}}, "query":{"bool":{"must":[{"range":{"start_at":{"gte":"%{start_date}", "lte":"%{end_date}"}}}, {"match":{"available_type":"training"}}]}}}'
|
||||
statistic_type_id: 3
|
||||
field: "available_tickets"
|
||||
es_index: "fablab"
|
||||
es_type: "availabilities"
|
||||
|
||||
three:
|
||||
query: '{"size":0, "aggregations":{"%{aggs_name}":{"avg":{"field":"ca", "script":"BigDecimal.valueOf(_value).setScale(1, RoundingMode.HALF_UP)", "missing": 0}}}, "query":{"bool":{"must":[{"range":{"date":{"gte":"%{start_date}", "lte":"%{end_date}"}}}]}}}'
|
||||
statistic_type_id: 15
|
||||
field: "average_cart"
|
||||
es_index: "stats"
|
||||
es_type: "order"
|
||||
|
13
test/fixtures/statistic_indices.yml
vendored
13
test/fixtures/statistic_indices.yml
vendored
@ -11,7 +11,7 @@ statistic_index_1:
|
||||
statistic_index_2:
|
||||
id: 2
|
||||
es_type_key: machine
|
||||
label: Créneaux machines
|
||||
label: Heures machines
|
||||
created_at: 2016-04-04 14:11:33.359367000 Z
|
||||
updated_at: 2016-04-04 14:11:33.359367000 Z
|
||||
table: true
|
||||
@ -29,7 +29,7 @@ statistic_index_3:
|
||||
statistic_index_4:
|
||||
id: 4
|
||||
es_type_key: event
|
||||
label: Ateliers/Stages
|
||||
label: Évènements
|
||||
created_at: 2016-04-04 14:11:33.366381000 Z
|
||||
updated_at: 2016-04-04 14:11:33.366381000 Z
|
||||
table: true
|
||||
@ -70,3 +70,12 @@ statistic_index_8:
|
||||
updated_at: 2017-02-13 14:08:36.211740000 Z
|
||||
table: true
|
||||
ca: true
|
||||
|
||||
statistic_index_9:
|
||||
id: 9
|
||||
es_type_key: order
|
||||
label: Commandes
|
||||
created_at: 2022-10-11 13:31:22.962460
|
||||
updated_at: 2022-10-11 13:31:22.962460 Z
|
||||
table: true
|
||||
ca: true
|
||||
|
14
test/fixtures/statistic_sub_types.yml
vendored
14
test/fixtures/statistic_sub_types.yml
vendored
@ -153,3 +153,17 @@ statistic_sub_type_22:
|
||||
- month
|
||||
created_at: 2016-04-04 15:18:28.864495000 Z
|
||||
updated_at: 2016-04-04 15:18:28.864495000 Z
|
||||
|
||||
statistic_sub_type_23:
|
||||
id: 23
|
||||
key: paid-processed
|
||||
label: Payée et/ou traitée
|
||||
created_at: 2022-10-12 08:55:05.167910 Z
|
||||
updated_at: 2022-10-12 08:55:05.167910 Z
|
||||
|
||||
statistic_sub_type_24:
|
||||
id: 24
|
||||
key: aborted
|
||||
label: Interrompue
|
||||
created_at: 2022-10-12 08:55:05.209986 Z
|
||||
updated_at: 2022-10-12 08:55:05.209986 Z
|
||||
|
15
test/fixtures/statistic_type_sub_types.yml
vendored
15
test/fixtures/statistic_type_sub_types.yml
vendored
@ -243,3 +243,18 @@ statistic_type_sub_type_35:
|
||||
statistic_sub_type_id: 22
|
||||
created_at: 2016-04-04 15:18:28.867317000 Z
|
||||
updated_at: 2016-04-04 15:18:28.867317000 Z
|
||||
|
||||
statistic_type_sub_type_36:
|
||||
id: 36
|
||||
statistic_type_id: 15
|
||||
statistic_sub_type_id: 23
|
||||
created_at: 2022-10-12 08:55:05.187077
|
||||
updated_at: 2022-10-12 08:55:05.187077
|
||||
|
||||
statistic_type_sub_type_37:
|
||||
id: 37
|
||||
statistic_type_id: 15
|
||||
statistic_sub_type_id: 24
|
||||
created_at: 2022-10-12 08:55:05.211284
|
||||
updated_at: 2022-10-12 08:55:05.211284
|
||||
|
||||
|
22
test/fixtures/statistic_types.yml
vendored
22
test/fixtures/statistic_types.yml
vendored
@ -92,8 +92,8 @@ statistic_type_9:
|
||||
statistic_type_10:
|
||||
id: 10
|
||||
statistic_index_id: 1
|
||||
key: '2592000'
|
||||
label: 'Durée : one month'
|
||||
key: '2629746'
|
||||
label: 'Durée : un mois'
|
||||
graph: true
|
||||
created_at: 2016-04-04 15:15:21.110438000 Z
|
||||
updated_at: 2016-04-04 15:15:21.110438000 Z
|
||||
@ -102,8 +102,8 @@ statistic_type_10:
|
||||
statistic_type_11:
|
||||
id: 11
|
||||
statistic_index_id: 1
|
||||
key: '5184000'
|
||||
label: 'Durée : 2 months'
|
||||
key: '5259492'
|
||||
label: 'Durée : 2 mois'
|
||||
graph: true
|
||||
created_at: 2016-04-04 15:17:24.950033000 Z
|
||||
updated_at: 2016-04-04 15:17:24.950033000 Z
|
||||
@ -133,8 +133,18 @@ statistic_type_14:
|
||||
id: 14
|
||||
statistic_index_id: 1
|
||||
key: '31556952'
|
||||
label: 'Durée : 1 year'
|
||||
label: 'Durée : 1 an'
|
||||
graph: true
|
||||
created_at: 2016-04-04 15:17:24.950033000 Z
|
||||
updated_at: 2016-04-04 15:17:24.950033000 Z
|
||||
simple: true
|
||||
simple: true
|
||||
|
||||
statistic_type_15:
|
||||
id: 15
|
||||
statistic_index_id: 9
|
||||
key: store
|
||||
label: Boutique
|
||||
graph: true
|
||||
created_at: 2022-10-11 13:31:23.004224 Z
|
||||
updated_at: 2022-10-11 13:31:23.004224 Z
|
||||
simple: true
|
||||
|
111
test/integration/exports/statistics_export_test.rb
Normal file
111
test/integration/exports/statistics_export_test.rb
Normal file
@ -0,0 +1,111 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
require 'rubyXL'
|
||||
|
||||
module Exports; end
|
||||
|
||||
class Exports::StatisticsExportTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
admin = User.with_role(:admin).first
|
||||
login_as(admin, scope: :user)
|
||||
end
|
||||
|
||||
test 'export machine reservations statistics to Excel' do
|
||||
# Build the stats for the June 2015, a machine reservation should have happened at the time
|
||||
::Statistics::BuilderService.generate_statistic({ start_date: '2015-06-01'.to_date.beginning_of_day,
|
||||
end_date: '2015-06-30'.to_date.end_of_day })
|
||||
# Create a new export
|
||||
post '/stats/machine/export', {
|
||||
params: {
|
||||
type_key: 'booking',
|
||||
body: '{"query":{"bool":{"must":[{"term":{"type":"booking"}},{"range":{"date":{"gte":"2015-06-01T02:00:00+02:00",' \
|
||||
'"lte":"2015-06-30T23:59:59+02:00"}}}]}},"sort":[{"date":{"order":"desc"}}],"aggs":{"total_ca":{"sum":{"field":"ca"}}, ' \
|
||||
'"average_age":{"avg":{"field":"age"}},"total_stat":{"sum":{"field":"stat"}}}}'
|
||||
}
|
||||
}
|
||||
|
||||
# Check response format & status
|
||||
assert_equal 200, response.status, response.body
|
||||
assert_equal Mime[:json], response.content_type
|
||||
|
||||
# Check the export was created correctly
|
||||
res = json_response(response.body)
|
||||
e = Export.where(id: res[:export_id]).first
|
||||
assert_not_nil e, 'Export was not created in database'
|
||||
|
||||
# Run the worker
|
||||
worker = StatisticsExportWorker.new
|
||||
worker.perform(e.id)
|
||||
|
||||
# notification
|
||||
assert_not_empty Notification.where(attached_object: e)
|
||||
|
||||
# resulting XLSX file
|
||||
assert FileTest.exist?(e.file), 'XLSX file was not generated'
|
||||
workbook = RubyXL::Parser.parse(e.file)
|
||||
|
||||
# test worksheet
|
||||
assert_not_nil workbook[StatisticIndex.find_by(es_type_key: 'machine').label]
|
||||
|
||||
# test data
|
||||
reservation = Reservation.find(2)
|
||||
wb = workbook[StatisticIndex.find_by(es_type_key: 'machine').label]
|
||||
assert_equal 1, wb.sheet_data[0][1].value
|
||||
assert_equal 15.0, wb.sheet_data[1][1].value
|
||||
assert_equal reservation.user.statistic_profile.age.to_i, wb.sheet_data[2][1].value
|
||||
assert_equal reservation.created_at.to_date, wb.sheet_data[5][0].value.to_date
|
||||
assert_equal reservation.user.profile.full_name, wb.sheet_data[5][1].value
|
||||
assert_equal reservation.user.email, wb.sheet_data[5][2].value
|
||||
assert_equal reservation.user.profile.phone, wb.sheet_data[5][3].value
|
||||
assert_equal I18n.t("export.#{reservation.user.statistic_profile.str_gender}"), wb.sheet_data[5][4].value
|
||||
assert_equal reservation.user.statistic_profile.age.to_i, wb.sheet_data[5][5].value
|
||||
assert_equal reservation.reservable.name, wb.sheet_data[5][6].value
|
||||
assert_equal reservation.invoice_items.first.invoice.total / 100.0, wb.sheet_data[5][7].value
|
||||
|
||||
# Clean XLSX file
|
||||
require 'fileutils'
|
||||
FileUtils.rm(e.file)
|
||||
end
|
||||
|
||||
test 'export global statistics to Excel' do
|
||||
# Build the stats for the June 2015
|
||||
::Statistics::BuilderService.generate_statistic({ start_date: '2015-06-01'.to_date.beginning_of_day,
|
||||
end_date: '2015-06-30'.to_date.end_of_day })
|
||||
# Create a new export
|
||||
post '/stats/global/export', {
|
||||
params: {
|
||||
type_key: 'booking',
|
||||
body: '{"query":{"bool":{"must":[{"range":{"date":{"gte":"2015-06-01T02:00:00+02:00","lte":"2015-06-30T23:59:59+02:00"}}}]}}}'
|
||||
}
|
||||
}
|
||||
|
||||
# Check response format & status
|
||||
assert_equal 200, response.status, response.body
|
||||
assert_equal Mime[:json], response.content_type
|
||||
|
||||
# Check the export was created correctly
|
||||
res = json_response(response.body)
|
||||
e = Export.where(id: res[:export_id]).first
|
||||
assert_not_nil e, 'Export was not created in database'
|
||||
|
||||
# Run the worker
|
||||
worker = StatisticsExportWorker.new
|
||||
worker.perform(e.id)
|
||||
|
||||
# notification
|
||||
assert_not_empty Notification.where(attached_object: e)
|
||||
|
||||
# resulting XLSX file
|
||||
assert FileTest.exist?(e.file), 'XLSX file was not generated'
|
||||
workbook = RubyXL::Parser.parse(e.file)
|
||||
|
||||
# test worksheets
|
||||
StatisticIndex.where(table: true).includes(:statistic_fields, statistic_types: [:statistic_sub_types]).each do |index|
|
||||
index.statistic_types.each do |type|
|
||||
sheet_name = "#{index.label} - #{type.label}".gsub(%r{[*|\\:"<>?/]}, '').truncate(31)
|
||||
assert_not_nil workbook[sheet_name], "#{sheet_name} not found"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -5382,9 +5382,9 @@ loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.4.0:
|
||||
json5 "^1.0.1"
|
||||
|
||||
loader-utils@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129"
|
||||
integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c"
|
||||
integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==
|
||||
dependencies:
|
||||
big.js "^5.2.2"
|
||||
emojis-list "^3.0.0"
|
||||
|
Loading…
x
Reference in New Issue
Block a user