stats: move date formatting out of the Stat model
Before this commit, the monthly dossiers count was serialized into the Stat record using human-formatted dates, as: ```ruby s.dossiers_in_the_last_4_months = { "octobre 2021"=>409592, "novembre 2021"=>497823, "décembre 2021"=>38170, "janvier 2022"=>0 } ``` Turns out the ordering of keys in a serialized hash is not guaranteed. After a round-trip to the database, the keys will be wrongly sorted. Instead we want to save raw Date objects, which will preserve the ordering. The date formatting can be applied at display-time by the controller. Fix #6848
This commit is contained in:
parent
7c4bb4d1cf
commit
e6cf07b810
3 changed files with 53 additions and 34 deletions
|
@ -31,7 +31,7 @@ class StatsController < ApplicationController
|
|||
@procedures_in_the_last_4_months = last_four_months_serie(procedures, :published_at)
|
||||
|
||||
@dossiers_cumulative = stat.dossiers_cumulative
|
||||
@dossiers_in_the_last_4_months = stat.dossiers_in_the_last_4_months
|
||||
@dossiers_in_the_last_4_months = format_keys_as_months(stat.dossiers_in_the_last_4_months)
|
||||
end
|
||||
|
||||
def download
|
||||
|
@ -136,11 +136,18 @@ class StatsController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def format_keys_as_months(series)
|
||||
series.transform_keys do |k|
|
||||
date = k.is_a?(Date) ? k : (Date.parse(k) rescue k)
|
||||
l(date, format: "%B %Y")
|
||||
end
|
||||
end
|
||||
|
||||
def last_four_months_serie(association, date_attribute)
|
||||
association
|
||||
series = association
|
||||
.group_by_month(date_attribute, last: 4, current: super_admin_signed_in?)
|
||||
.count
|
||||
.transform_keys { |date| l(date, format: "%B %Y") }
|
||||
format_keys_as_months(series)
|
||||
end
|
||||
|
||||
def cumulative_month_serie(association, date_attribute)
|
||||
|
|
|
@ -80,11 +80,7 @@ class Stat < ApplicationRecord
|
|||
association.group_by_month(date_attribute, last: 4, current: false).count
|
||||
end
|
||||
|
||||
month_serie(sum_hashes(*timeseries))
|
||||
end
|
||||
|
||||
def month_serie(date_serie)
|
||||
date_serie.keys.sort.each_with_object({}) { |date, h| h[I18n.l(date, format: "%B %Y")] = date_serie[date] }
|
||||
sum_hashes(*timeseries).sort.to_h
|
||||
end
|
||||
|
||||
def cumulative_month_serie(associations_with_date_attribute)
|
||||
|
|
|
@ -57,24 +57,30 @@ describe Stat do
|
|||
create(:dossier, state: :en_construction, depose_at: i.months.ago)
|
||||
create(:deleted_dossier, dossier_id: i + 100, state: :en_construction, deleted_at: i.month.ago)
|
||||
end
|
||||
rs = Stat.send(:cumulative_month_serie, [
|
||||
[Dossier.state_not_brouillon, :depose_at],
|
||||
[DeletedDossier.where.not(state: :brouillon), :deleted_at]
|
||||
s = Stat.new({
|
||||
dossiers_cumulative:
|
||||
Stat.send(:cumulative_month_serie, [
|
||||
[Dossier.state_not_brouillon, :depose_at],
|
||||
[DeletedDossier.where.not(state: :brouillon), :deleted_at]
|
||||
])
|
||||
})
|
||||
s.save!
|
||||
s.reload
|
||||
# Use `Hash#to_a` to also test the key ordering
|
||||
expect(s.dossiers_cumulative.to_a).to eq([
|
||||
[formatted_n_months_ago(12), 2],
|
||||
[formatted_n_months_ago(11), 4],
|
||||
[formatted_n_months_ago(10), 6],
|
||||
[formatted_n_months_ago(9), 8],
|
||||
[formatted_n_months_ago(8), 10],
|
||||
[formatted_n_months_ago(7), 12],
|
||||
[formatted_n_months_ago(6), 14],
|
||||
[formatted_n_months_ago(5), 16],
|
||||
[formatted_n_months_ago(4), 18],
|
||||
[formatted_n_months_ago(3), 20],
|
||||
[formatted_n_months_ago(2), 22],
|
||||
[formatted_n_months_ago(1), 24]
|
||||
])
|
||||
expect(rs).to eq({
|
||||
12 => 2,
|
||||
11 => 4,
|
||||
10 => 6,
|
||||
9 => 8,
|
||||
8 => 10,
|
||||
7 => 12,
|
||||
6 => 14,
|
||||
5 => 16,
|
||||
4 => 18,
|
||||
3 => 20,
|
||||
2 => 22,
|
||||
1 => 24
|
||||
}.transform_keys { |i| i.months.ago.beginning_of_month.to_date })
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -85,16 +91,22 @@ describe Stat do
|
|||
create(:dossier, state: :en_construction, depose_at: i.months.ago)
|
||||
create(:deleted_dossier, dossier_id: i + 100, state: :en_construction, deleted_at: i.month.ago)
|
||||
end
|
||||
rs = Stat.send(:last_four_months_serie, [
|
||||
[Dossier.state_not_brouillon, :depose_at],
|
||||
[DeletedDossier.where.not(state: :brouillon), :deleted_at]
|
||||
])
|
||||
expect(rs).to eq({
|
||||
"juillet 2021" => 2,
|
||||
"août 2021" => 2,
|
||||
"septembre 2021" => 2,
|
||||
"octobre 2021" => 2
|
||||
s = Stat.new({
|
||||
dossiers_in_the_last_4_months:
|
||||
Stat.send(:last_four_months_serie, [
|
||||
[Dossier.state_not_brouillon, :depose_at],
|
||||
[DeletedDossier.where.not(state: :brouillon), :deleted_at]
|
||||
])
|
||||
})
|
||||
s.save!
|
||||
s.reload
|
||||
# Use `Hash#to_a` to also test the key ordering
|
||||
expect(s.dossiers_in_the_last_4_months.to_a).to eq([
|
||||
['2021-07-01', 2],
|
||||
['2021-08-01', 2],
|
||||
['2021-09-01', 2],
|
||||
['2021-10-01', 2]
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -104,4 +116,8 @@ describe Stat do
|
|||
expect(Stat.send(:sum_hashes, *[{ a: 1, b: 2, d: 5 }, { a: 2, b: 3, c: 5 }])).to eq({ a: 3, b: 5, c: 5, d: 5 })
|
||||
end
|
||||
end
|
||||
|
||||
def formatted_n_months_ago(i)
|
||||
i.months.ago.beginning_of_month.to_date.to_s
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue