remove extra Dossier call in projection

This commit is contained in:
simon lehericey 2021-04-26 10:35:22 +02:00
parent fd6f110210
commit 7b94c2de88
6 changed files with 68 additions and 29 deletions

View file

@ -1,5 +1,5 @@
class DossierProjectionService class DossierProjectionService
class DossierProjection < Struct.new(:dossier, :columns) class DossierProjection < Struct.new(:dossier_id, :state, :archived, :columns)
end end
TABLE = 'table' TABLE = 'table'
@ -18,7 +18,10 @@ class DossierProjectionService
# - the order of the intermediary query results are unknown # - the order of the intermediary query results are unknown
# - some values can be missing (if a revision added or removed them) # - some values can be missing (if a revision added or removed them)
def self.project(dossiers_ids, fields) def self.project(dossiers_ids, fields)
fields state_field = { TABLE => 'self', COLUMN => 'state' }
archived_field = { TABLE => 'self', COLUMN => 'archived' }
([state_field, archived_field] + fields) # the view needs state and archived dossier attributes
.each { |f| f[:id_value_h] = {} } .each { |f| f[:id_value_h] = {} }
.group_by { |f| f[TABLE] } # one query per table .group_by { |f| f[TABLE] } # one query per table
.each do |table, fields| .each do |table, fields|
@ -40,7 +43,15 @@ class DossierProjectionService
Dossier Dossier
.where(id: dossiers_ids) .where(id: dossiers_ids)
.pluck(:id, *fields.map { |f| f[COLUMN].to_sym }) .pluck(:id, *fields.map { |f| f[COLUMN].to_sym })
.each { |id, *columns| fields.zip(columns).each { |field, value| field[:id_value_h][id] = value&.strftime('%d/%m/%Y') } } .each do |id, *columns|
fields.zip(columns).each do |field, value|
if [state_field, archived_field].include?(field)
field[:id_value_h][id] = value
else
field[:id_value_h][id] = value&.strftime('%d/%m/%Y') # other fields are datetime
end
end
end
when 'individual' when 'individual'
Individual Individual
.where(dossier_id: dossiers_ids) .where(dossier_id: dossiers_ids)
@ -74,11 +85,13 @@ class DossierProjectionService
end end
end end
Dossier dossiers_ids.map do |dossier_id|
.select(:id, :state, :archived) # the dossier object is needed in the view DossierProjection.new(
.find(dossiers_ids) # keeps dossiers_ids order and raise exception if one is missing dossier_id,
.map do |dossier| state_field[:id_value_h][dossier_id],
DossierProjection.new(dossier, fields.map { |f| f[:id_value_h][dossier.id] }) archived_field[:id_value_h][dossier_id],
fields.map { |f| f[:id_value_h][dossier_id] }
)
end end
end end
end end

View file

@ -23,7 +23,13 @@
- else - else
%p.menu-item Le téléchargement des pièces jointes est désactivé pour les dossiers de plus de #{number_to_human_size Dossier::TAILLE_MAX_ZIP}. %p.menu-item Le téléchargement des pièces jointes est désactivé pour les dossiers de plus de #{number_to_human_size Dossier::TAILLE_MAX_ZIP}.
= render partial: "instructeurs/procedures/dossier_actions", locals: { procedure: dossier.procedure, dossier: dossier, dossier_is_followed: current_instructeur&.follow?(dossier) } = render partial: "instructeurs/procedures/dossier_actions",
locals: { procedure_id: dossier.procedure.id,
dossier_id: dossier.id,
state: dossier.state,
archived: dossier.archived,
dossier_is_followed: current_instructeur&.follow?(dossier) }
.state-button .state-button
= render partial: "state_button", locals: { dossier: dossier } = render partial: "state_button", locals: { dossier: dossier }

View file

@ -1,19 +1,19 @@
- if dossier.en_construction_ou_instruction? - if Dossier::EN_CONSTRUCTION_OU_INSTRUCTION.include?(state)
- if dossier_is_followed - if dossier_is_followed
= link_to unfollow_instructeur_dossier_path(procedure, dossier), method: :patch, class: 'button' do = link_to unfollow_instructeur_dossier_path(procedure_id, dossier_id), method: :patch, class: 'button' do
%span.icon.unfollow> %span.icon.unfollow>
Ne plus suivre Ne plus suivre
- else - else
= link_to follow_instructeur_dossier_path(procedure, dossier), method: :patch, class: 'button' do = link_to follow_instructeur_dossier_path(procedure_id, dossier_id), method: :patch, class: 'button' do
%span.icon.follow> %span.icon.follow>
Suivre le dossier Suivre le dossier
- elsif dossier.termine? - elsif Dossier::TERMINE.include?(state)
- if dossier.archived - if archived
= link_to unarchive_instructeur_dossier_path(procedure, dossier), method: :patch, class: 'button' do = link_to unarchive_instructeur_dossier_path(procedure_id, dossier_id), method: :patch, class: 'button' do
%span.icon.unarchive> %span.icon.unarchive>
Désarchiver le dossier Désarchiver le dossier
- else - else
= link_to archive_instructeur_dossier_path(procedure, dossier), method: :patch, class: 'button' do = link_to archive_instructeur_dossier_path(procedure_id, dossier_id), method: :patch, class: 'button' do
%span.icon.archive> %span.icon.archive>
Archiver le dossier Archiver le dossier

View file

@ -131,27 +131,32 @@
%tbody %tbody
- @projected_dossiers.each do |p| - @projected_dossiers.each do |p|
- dossier = p.dossier - path = instructeur_dossier_path(@procedure, p.dossier_id)
- path = instructeur_dossier_path(@procedure, dossier.id)
%tr %tr
%td.folder-col %td.folder-col
%a.cell-link{ href: path } %a.cell-link{ href: path }
%span.icon.folder %span.icon.folder
- if @not_archived_notifications_dossier_ids.include?(dossier.id) - if @not_archived_notifications_dossier_ids.include?(p.dossier_id)
%span.notifications{ 'aria-label': 'notifications' } %span.notifications{ 'aria-label': 'notifications' }
%td.number-col %td.number-col
%a.cell-link{ href: path }= dossier.id %a.cell-link{ href: path }= p.dossier_id
- p.columns.each do |column| - p.columns.each do |column|
%td %td
%a.cell-link{ href: path }= column %a.cell-link{ href: path }= column
%td.status-col %td.status-col
%a.cell-link{ href: path }= status_badge(dossier.state) %a.cell-link{ href: path }= status_badge(p.state)
%td.action-col.follow-col= render partial: 'dossier_actions',
locals: { procedure_id: @procedure.id,
dossier_id: p.dossier_id,
state: p.state,
archived: p.archived,
dossier_is_followed: @followed_dossiers_id.include?(p.dossier_id) }
%td.action-col.follow-col= render partial: 'dossier_actions', locals: { procedure: @procedure, dossier: dossier, dossier_is_followed: @followed_dossiers_id.include?(dossier.id) }
= pagination = pagination
- else - else
%h2.empty-text Aucun dossier %h2.empty-text Aucun dossier

View file

@ -31,6 +31,12 @@
%td.status-col %td.status-col
= link_to(dossier_linked_path(current_instructeur, dossier), class: 'cell-link') do = link_to(dossier_linked_path(current_instructeur, dossier), class: 'cell-link') do
= status_badge(dossier.state) = status_badge(dossier.state)
%td.action-col.follow-col= render partial: 'instructeurs/procedures/dossier_actions', locals: { procedure: dossier.procedure, dossier: dossier, dossier_is_followed: @followed_dossiers_id.include?(dossier.id) } %td.action-col.follow-col= render partial: "instructeurs/procedures/dossier_actions",
locals: { procedure_id: dossier.procedure.id,
dossier_id: dossier.id,
state: dossier.state,
archived: dossier.archived,
dossier_is_followed: @followed_dossiers_id.include?(dossier.id) }
- else - else
%h2 Aucun dossier correspondant à votre recherche n'a été trouvé %h2 Aucun dossier correspondant à votre recherche n'a été trouvé

View file

@ -5,8 +5,8 @@ describe DossierProjectionService do
context 'with multiple dossier' do context 'with multiple dossier' do
let!(:procedure) { create(:procedure, :with_type_de_champ) } let!(:procedure) { create(:procedure, :with_type_de_champ) }
let!(:dossier_1) { create(:dossier, procedure: procedure) } let!(:dossier_1) { create(:dossier, procedure: procedure) }
let!(:dossier_2) { create(:dossier, procedure: procedure) } let!(:dossier_2) { create(:dossier, :en_construction, :archived, procedure: procedure) }
let!(:dossier_3) { create(:dossier, procedure: procedure) } let!(:dossier_3) { create(:dossier, :en_instruction, procedure: procedure) }
let(:dossiers_ids) { [dossier_3.id, dossier_1.id, dossier_2.id] } let(:dossiers_ids) { [dossier_3.id, dossier_1.id, dossier_2.id] }
let(:fields) do let(:fields) do
@ -26,11 +26,20 @@ describe DossierProjectionService do
let(:result) { subject } let(:result) { subject }
it 'respects the dossiers_ids order and returns nil for empty result' do it 'respects the dossiers_ids order, returns state, archived and nil for empty result' do
expect(result.length).to eq(3) expect(result.length).to eq(3)
expect(result[0].dossier.id).to eq(dossier_3.id)
expect(result[1].dossier.id).to eq(dossier_1.id) expect(result[0].dossier_id).to eq(dossier_3.id)
expect(result[2].dossier.id).to eq(dossier_2.id) expect(result[1].dossier_id).to eq(dossier_1.id)
expect(result[2].dossier_id).to eq(dossier_2.id)
expect(result[0].state).to eq('en_instruction')
expect(result[1].state).to eq('brouillon')
expect(result[2].state).to eq('en_construction')
expect(result[0].archived).to be false
expect(result[1].archived).to be false
expect(result[2].archived).to be true
expect(result[0].columns[0]).to be nil expect(result[0].columns[0]).to be nil
expect(result[1].columns[0]).to eq('champ_1') expect(result[1].columns[0]).to eq('champ_1')