demarches-normaliennes/spec/models/stat_spec.rb
Pierre de La Morinerie e6cf07b810 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
2022-02-02 14:13:53 +01:00

123 lines
5.3 KiB
Ruby

include ActiveSupport::Testing::TimeHelpers
describe Stat do
describe '.deleted_dossiers_states' do
subject { Stat.send(:deleted_dossiers_states) }
it 'find counts for columns' do
create(:deleted_dossier, dossier_id: create(:dossier).id, state: :termine)
create(:deleted_dossier, dossier_id: create(:dossier).id, state: :en_construction, deleted_at: 1.month.ago)
create(:deleted_dossier, dossier_id: create(:dossier).id, state: :en_construction, deleted_at: 2.months.ago)
create(:deleted_dossier, dossier_id: create(:dossier).id, state: :brouillon, deleted_at: 3.months.ago)
create(:deleted_dossier, dossier_id: create(:dossier).id, state: :en_construction, deleted_at: 3.months.ago)
create(:deleted_dossier, dossier_id: create(:dossier).id, state: :en_instruction, deleted_at: 3.months.ago)
create(:deleted_dossier, dossier_id: create(:dossier).id, state: :accepte, deleted_at: 3.months.ago)
create(:deleted_dossier, dossier_id: create(:dossier).id, state: :refuse, deleted_at: 3.months.ago)
create(:deleted_dossier, dossier_id: create(:dossier).id, state: :sans_suite, deleted_at: 3.months.ago)
expect(subject["not_brouillon"]).to eq(8)
expect(subject["dossiers_depose_avant_30_jours"]).to eq(1)
expect(subject["dossiers_deposes_entre_60_et_30_jours"]).to eq(1)
expect(subject["brouillon"]).to eq(1)
expect(subject["en_construction"]).to eq(3)
expect(subject["en_instruction"]).to eq(1)
expect(subject["termines"]).to eq(3)
end
end
describe '.update_stats' do
it 'merges dossiers_states and deleted_dossiers_states' do
stats = {
"not_brouillon" => 1,
"dossiers_depose_avant_30_jours" => 2,
"dossiers_deposes_entre_60_et_30_jours" => 3,
"brouillon" => 4,
"en_construction" => 5,
"en_instruction" => 6,
"termines" => 7
}
allow(Stat).to receive(:dossiers_states).and_return(stats)
allow(Stat).to receive(:deleted_dossiers_states).and_return(stats)
Stat.update_stats
computed_stats = Stat.first
expect(computed_stats.dossiers_not_brouillon).to eq(stats["not_brouillon"] * 2)
expect(computed_stats.dossiers_depose_avant_30_jours).to eq(stats["dossiers_depose_avant_30_jours"] * 2)
expect(computed_stats.dossiers_deposes_entre_60_et_30_jours).to eq(stats["dossiers_deposes_entre_60_et_30_jours"] * 2)
expect(computed_stats.dossiers_brouillon).to eq(stats["brouillon"] * 2)
expect(computed_stats.dossiers_en_construction).to eq(stats["en_construction"] * 2)
expect(computed_stats.dossiers_en_instruction).to eq(stats["en_instruction"] * 2)
expect(computed_stats.dossiers_termines).to eq(stats["termines"] * 2)
end
end
describe '.cumulative_hash' do
it 'works count and cumulate counters by month for both dossier and deleted dossiers' do
12.downto(1).map do |i|
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
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]
])
end
end
describe '.last_four_months_hash' do
it 'works count and cumulate counters by month for both dossier and deleted dossiers' do
travel_to Time.zone.local(2021, 11, 25) do
4.downto(1).map do |i|
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
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
describe '.sum_hashes' do
it 'sum up hashes keys' 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