Merge pull request #5547 from tchak/exports-with-revisions
Include in exports types_de_champ from all revisions
This commit is contained in:
commit
8bc1369c2c
6 changed files with 117 additions and 27 deletions
|
@ -649,19 +649,19 @@ class Dossier < ApplicationRecord
|
||||||
log_dossier_operation(avis.claimant, :demander_un_avis, avis)
|
log_dossier_operation(avis.claimant, :demander_un_avis, avis)
|
||||||
end
|
end
|
||||||
|
|
||||||
def spreadsheet_columns_csv
|
def spreadsheet_columns_csv(types_de_champ:, types_de_champ_private:)
|
||||||
spreadsheet_columns(with_etablissement: true)
|
spreadsheet_columns(with_etablissement: true, types_de_champ: types_de_champ, types_de_champ_private: types_de_champ_private)
|
||||||
end
|
end
|
||||||
|
|
||||||
def spreadsheet_columns_xlsx
|
def spreadsheet_columns_xlsx(types_de_champ:, types_de_champ_private:)
|
||||||
spreadsheet_columns
|
spreadsheet_columns(types_de_champ: types_de_champ, types_de_champ_private: types_de_champ_private)
|
||||||
end
|
end
|
||||||
|
|
||||||
def spreadsheet_columns_ods
|
def spreadsheet_columns_ods(types_de_champ:, types_de_champ_private:)
|
||||||
spreadsheet_columns
|
spreadsheet_columns(types_de_champ: types_de_champ, types_de_champ_private: types_de_champ_private)
|
||||||
end
|
end
|
||||||
|
|
||||||
def spreadsheet_columns(with_etablissement: false)
|
def spreadsheet_columns(with_etablissement: false, types_de_champ:, types_de_champ_private:)
|
||||||
columns = [
|
columns = [
|
||||||
['ID', id.to_s],
|
['ID', id.to_s],
|
||||||
['Email', user.email]
|
['Email', user.email]
|
||||||
|
@ -728,18 +728,34 @@ class Dossier < ApplicationRecord
|
||||||
columns << ['Groupe instructeur', groupe_instructeur.label]
|
columns << ['Groupe instructeur', groupe_instructeur.label]
|
||||||
end
|
end
|
||||||
|
|
||||||
columns + champs_for_export + annotations_for_export
|
columns + champs_for_export(types_de_champ) + champs_private_for_export(types_de_champ_private)
|
||||||
end
|
end
|
||||||
|
|
||||||
def champs_for_export
|
def champs_for_export(types_de_champ)
|
||||||
champs.reject(&:exclude_from_export?).map do |champ|
|
# Index values by stable_id
|
||||||
[champ.libelle, champ.for_export]
|
values = champs.reject(&:exclude_from_export?).reduce({}) do |champs, champ|
|
||||||
|
champs[champ.stable_id] = champ.for_export
|
||||||
|
champs
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get all the champs values for the types de champ in the final list.
|
||||||
|
# Dossier might not have corresponding champ – display nil.
|
||||||
|
types_de_champ.map do |type_de_champ|
|
||||||
|
[type_de_champ.libelle, values[type_de_champ.stable_id]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def annotations_for_export
|
def champs_private_for_export(types_de_champ)
|
||||||
champs_private.reject(&:exclude_from_export?).map do |champ|
|
# Index values by stable_id
|
||||||
[champ.libelle, champ.for_export]
|
values = champs_private.reject(&:exclude_from_export?).reduce({}) do |champs, champ|
|
||||||
|
champs[champ.stable_id] = champ.for_export
|
||||||
|
champs
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get all the champs values for the types de champ in the final list.
|
||||||
|
# Dossier might not have corresponding champ – display nil.
|
||||||
|
types_de_champ.map do |type_de_champ|
|
||||||
|
[type_de_champ.libelle, values[type_de_champ.stable_id]]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -61,10 +61,13 @@ class Procedure < ApplicationRecord
|
||||||
belongs_to :published_revision, class_name: 'ProcedureRevision', optional: true
|
belongs_to :published_revision, class_name: 'ProcedureRevision', optional: true
|
||||||
has_many :deleted_dossiers, dependent: :destroy
|
has_many :deleted_dossiers, dependent: :destroy
|
||||||
|
|
||||||
has_many :published_types_de_champ, through: :published_revision, source: :types_de_champ
|
has_many :published_types_de_champ, -> { ordered }, through: :published_revision, source: :types_de_champ
|
||||||
has_many :published_types_de_champ_private, through: :published_revision, source: :types_de_champ_private
|
has_many :published_types_de_champ_private, -> { ordered }, through: :published_revision, source: :types_de_champ_private
|
||||||
has_many :draft_types_de_champ, through: :draft_revision, source: :types_de_champ
|
has_many :draft_types_de_champ, -> { ordered }, through: :draft_revision, source: :types_de_champ
|
||||||
has_many :draft_types_de_champ_private, through: :draft_revision, source: :types_de_champ_private
|
has_many :draft_types_de_champ_private, -> { ordered }, through: :draft_revision, source: :types_de_champ_private
|
||||||
|
|
||||||
|
has_many :all_types_de_champ, -> { joins(:procedure).where('types_de_champ.revision_id != procedures.draft_revision_id').ordered }, through: :revisions, source: :types_de_champ
|
||||||
|
has_many :all_types_de_champ_private, -> { joins(:procedure).where('types_de_champ.revision_id != procedures.draft_revision_id').ordered }, through: :revisions, source: :types_de_champ_private
|
||||||
|
|
||||||
has_one :module_api_carto, dependent: :destroy
|
has_one :module_api_carto, dependent: :destroy
|
||||||
has_one :attestation_template, dependent: :destroy
|
has_one :attestation_template, dependent: :destroy
|
||||||
|
@ -85,6 +88,34 @@ class Procedure < ApplicationRecord
|
||||||
brouillon? ? draft_types_de_champ_private : published_types_de_champ_private
|
brouillon? ? draft_types_de_champ_private : published_types_de_champ_private
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def types_de_champ_for_export
|
||||||
|
if brouillon?
|
||||||
|
draft_types_de_champ
|
||||||
|
else
|
||||||
|
all_types_de_champ
|
||||||
|
.uniq
|
||||||
|
.reject(&:exclude_from_export?)
|
||||||
|
.filter(&:active_revision?)
|
||||||
|
.group_by(&:stable_id).values.map do |types_de_champ|
|
||||||
|
types_de_champ.sort_by(&:created_at).last
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def types_de_champ_private_for_export
|
||||||
|
if brouillon?
|
||||||
|
draft_types_de_champ_private
|
||||||
|
else
|
||||||
|
all_types_de_champ_private
|
||||||
|
.uniq
|
||||||
|
.reject(&:exclude_from_export?)
|
||||||
|
.filter(&:active_revision?)
|
||||||
|
.group_by(&:stable_id).values.map do |types_de_champ|
|
||||||
|
types_de_champ.sort_by(&:created_at).last
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
has_many :administrateurs_procedures
|
has_many :administrateurs_procedures
|
||||||
has_many :administrateurs, through: :administrateurs_procedures, after_remove: -> (procedure, _admin) { procedure.validate! }
|
has_many :administrateurs, through: :administrateurs_procedures, after_remove: -> (procedure, _admin) { procedure.validate! }
|
||||||
has_many :groupe_instructeurs, dependent: :destroy
|
has_many :groupe_instructeurs, dependent: :destroy
|
||||||
|
|
|
@ -50,7 +50,7 @@ class ProcedureRevision < ApplicationRecord
|
||||||
elsif type_de_champ.parent.present?
|
elsif type_de_champ.parent.present?
|
||||||
find_or_clone_type_de_champ(type_de_champ.parent.stable_id).types_de_champ.find_by!(stable_id: id)
|
find_or_clone_type_de_champ(type_de_champ.parent.stable_id).types_de_champ.find_by!(stable_id: id)
|
||||||
else
|
else
|
||||||
type_de_champ.revise!
|
revise_type_de_champ(type_de_champ)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -98,6 +98,15 @@ class ProcedureRevision < ApplicationRecord
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def revise_type_de_champ(type_de_champ)
|
||||||
|
types_de_champ_association = type_de_champ.private? ? :revision_types_de_champ_private : :revision_types_de_champ
|
||||||
|
association = send(types_de_champ_association).find_by!(type_de_champ: type_de_champ)
|
||||||
|
cloned_type_de_champ = type_de_champ.deep_clone(include: [:types_de_champ], &type_de_champ.method(:clone_attachments))
|
||||||
|
cloned_type_de_champ.revision = self
|
||||||
|
association.update!(type_de_champ: cloned_type_de_champ)
|
||||||
|
cloned_type_de_champ
|
||||||
|
end
|
||||||
|
|
||||||
def find_type_de_champ_by_id(id)
|
def find_type_de_champ_by_id(id)
|
||||||
types_de_champ.find_by(stable_id: id) ||
|
types_de_champ.find_by(stable_id: id) ||
|
||||||
types_de_champ_private.find_by(stable_id: id) ||
|
types_de_champ_private.find_by(stable_id: id) ||
|
||||||
|
|
|
@ -58,6 +58,7 @@ class TypeDeChamp < ApplicationRecord
|
||||||
|
|
||||||
store_accessor :options, :cadastres, :quartiers_prioritaires, :parcelles_agricoles, :mnhn, :old_pj, :drop_down_options, :skip_pj_validation
|
store_accessor :options, :cadastres, :quartiers_prioritaires, :parcelles_agricoles, :mnhn, :old_pj, :drop_down_options, :skip_pj_validation
|
||||||
has_many :revision_types_de_champ, class_name: 'ProcedureRevisionTypeDeChamp', dependent: :destroy, inverse_of: :type_de_champ
|
has_many :revision_types_de_champ, class_name: 'ProcedureRevisionTypeDeChamp', dependent: :destroy, inverse_of: :type_de_champ
|
||||||
|
has_many :revisions, through: :revision_types_de_champ
|
||||||
|
|
||||||
delegate :tags_for_template, to: :dynamic_type
|
delegate :tags_for_template, to: :dynamic_type
|
||||||
|
|
||||||
|
@ -200,6 +201,10 @@ class TypeDeChamp < ApplicationRecord
|
||||||
!private?
|
!private?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def active_revision?
|
||||||
|
revisions.include?(procedure.active_revision)
|
||||||
|
end
|
||||||
|
|
||||||
def self.type_champ_to_class_name(type_champ)
|
def self.type_champ_to_class_name(type_champ)
|
||||||
"TypesDeChamp::#{type_champ.classify}TypeDeChamp"
|
"TypesDeChamp::#{type_champ.classify}TypeDeChamp"
|
||||||
end
|
end
|
||||||
|
@ -248,13 +253,6 @@ class TypeDeChamp < ApplicationRecord
|
||||||
GraphQL::Schema::UniqueWithinType.encode('Champ', stable_id)
|
GraphQL::Schema::UniqueWithinType.encode('Champ', stable_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def revise!
|
|
||||||
types_de_champ_association = private? ? :revision_types_de_champ_private : :revision_types_de_champ
|
|
||||||
association = revision.send(types_de_champ_association).find_by!(type_de_champ: self)
|
|
||||||
association.update!(type_de_champ: deep_clone(include: [:types_de_champ], &method(:clone_attachments)))
|
|
||||||
association.type_de_champ
|
|
||||||
end
|
|
||||||
|
|
||||||
FEATURE_FLAGS = {}
|
FEATURE_FLAGS = {}
|
||||||
|
|
||||||
def self.type_de_champ_types_for(procedure, user)
|
def self.type_de_champ_types_for(procedure, user)
|
||||||
|
|
|
@ -64,7 +64,7 @@ class ProcedureExportService
|
||||||
def options_for(table, format)
|
def options_for(table, format)
|
||||||
options = case table
|
options = case table
|
||||||
when :dossiers
|
when :dossiers
|
||||||
{ instances: dossiers.to_a, sheet_name: 'Dossiers', spreadsheet_columns: :"spreadsheet_columns_#{format}" }
|
{ instances: dossiers.to_a, sheet_name: 'Dossiers', spreadsheet_columns: spreadsheet_columns(format) }
|
||||||
when :etablissements
|
when :etablissements
|
||||||
{ instances: etablissements.to_a, sheet_name: 'Etablissements' }
|
{ instances: etablissements.to_a, sheet_name: 'Etablissements' }
|
||||||
when :avis
|
when :avis
|
||||||
|
@ -82,4 +82,13 @@ class ProcedureExportService
|
||||||
|
|
||||||
options
|
options
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def spreadsheet_columns(format)
|
||||||
|
types_de_champ = @procedure.types_de_champ_for_export
|
||||||
|
types_de_champ_private = @procedure.types_de_champ_private_for_export
|
||||||
|
|
||||||
|
Proc.new do |instance|
|
||||||
|
instance.send(:"spreadsheet_columns_#{format}", types_de_champ: types_de_champ, types_de_champ_private: types_de_champ_private)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1343,4 +1343,31 @@ describe Dossier do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "champs_for_export" do
|
||||||
|
let(:procedure) { create(:procedure, :with_type_de_champ, :with_datetime, :with_yes_no) }
|
||||||
|
let(:text_type_de_champ) { procedure.types_de_champ.find { |type_de_champ| type_de_champ.type_champ == TypeDeChamp.type_champs.fetch(:text) } }
|
||||||
|
let(:yes_no_type_de_champ) { procedure.types_de_champ.find { |type_de_champ| type_de_champ.type_champ == TypeDeChamp.type_champs.fetch(:yes_no) } }
|
||||||
|
let(:datetime_type_de_champ) { procedure.types_de_champ.find { |type_de_champ| type_de_champ.type_champ == TypeDeChamp.type_champs.fetch(:datetime) } }
|
||||||
|
let(:dossier) { create(:dossier, procedure: procedure) }
|
||||||
|
let(:dossier_second_revision) { create(:dossier, procedure: procedure) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
procedure.publish!
|
||||||
|
dossier
|
||||||
|
procedure.draft_revision.remove_type_de_champ(text_type_de_champ.stable_id)
|
||||||
|
procedure.draft_revision.add_type_de_champ(type_champ: TypeDeChamp.type_champs.fetch(:text), libelle: 'New text field')
|
||||||
|
procedure.draft_revision.find_or_clone_type_de_champ(yes_no_type_de_champ.stable_id).update(libelle: 'Updated yes/no')
|
||||||
|
procedure.update(published_revision: procedure.draft_revision, draft_revision: procedure.create_new_revision)
|
||||||
|
dossier.reload
|
||||||
|
procedure.reload
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should have champs from all revisions" do
|
||||||
|
expect(dossier.types_de_champ.map(&:libelle)).to eq([text_type_de_champ.libelle, datetime_type_de_champ.libelle, "Yes/no"])
|
||||||
|
expect(dossier_second_revision.types_de_champ.map(&:libelle)).to eq([datetime_type_de_champ.libelle, "Updated yes/no", "New text field"])
|
||||||
|
expect(dossier.champs_for_export(dossier.procedure.types_de_champ_for_export).map { |(libelle)| libelle }).to eq([datetime_type_de_champ.libelle, "Updated yes/no", "New text field"])
|
||||||
|
expect(dossier.champs_for_export(dossier.procedure.types_de_champ_for_export)).to eq(dossier_second_revision.champs_for_export(dossier_second_revision.procedure.types_de_champ_for_export))
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue