diff --git a/app/validators/export_template_validator.rb b/app/validators/export_template_validator.rb index 2a1158ed6..6d291ea3d 100644 --- a/app/validators/export_template_validator.rb +++ b/app/validators/export_template_validator.rb @@ -1,54 +1,66 @@ class ExportTemplateValidator < ActiveModel::Validator - def validate(record) - validate_default_dossier_directory(record) - validate_pdf_name(record) - validate_pjs(record) + def validate(export_template) + validate_all_templates(export_template) + + return if export_template.errors.any? # no need to continue if the templates are invalid + + validate_dossier_folder(export_template) + validate_export_pdf(export_template) + validate_pjs(export_template) + + validate_different_templates(export_template) end private - def validate_default_dossier_directory(record) - mention = attribute_content_mention(record, :default_dossier_directory) - if mention&.fetch("id", nil) != "dossier_number" - record.errors.add :tiptap_default_dossier_directory, :dossier_number_mandatory + def validate_all_templates(export_template) + [export_template.dossier_folder, export_template.export_pdf, *export_template.pjs].each(&:template_string) + + rescue StandardError + export_template.errors.add(:base, :invalid_template) + end + + def validate_dossier_folder(export_template) + if !mentions(export_template.dossier_folder.template).include?('dossier_number') + export_template.errors.add(:dossier_folder, :dossier_number_required) end end - def validate_pdf_name(record) - if attribute_content_text(record, :pdf_name).blank? && attribute_content_mention(record, :pdf_name).blank? - record.errors.add :tiptap_pdf_name, :blank + def mentions(template) + TiptapService.used_tags_and_libelle_for(template).map(&:first) + end + + def validate_export_pdf(export_template) + return if !export_template.export_pdf.enabled? + + if export_template.export_pdf.template_string.empty? + export_template.errors.add(:export_pdf, :blank) end end - def attribute_content_text(record, attribute) - attribute_content(record, attribute)&.find { |elem| elem["type"] == "text" }&.fetch("text", nil) - end + def validate_pjs(export_template) + libelle_by_stable_ids = pj_libelle_by_stable_id(export_template) - def attribute_content_mention(record, attribute) - attribute_content(record, attribute)&.find { |elem| elem["type"] == "mention" }&.fetch("attrs", nil) - end - - def attribute_content(record, attribute) - content = record.content[attribute.to_s]&.fetch("content", nil) - if content.is_a?(Array) - content.first&.fetch("content", nil) + export_template.pjs.filter(&:enabled?).each do |pj| + if pj.template_string.empty? + libelle = libelle_by_stable_ids[pj.stable_id] + export_template.errors.add(libelle, I18n.t(:blank, scope: 'errors.messages')) + end end end - def validate_pjs(record) - record.content["pjs"]&.each do |pj| - pj_sym = pj.symbolize_keys - libelle = record.groupe_instructeur.procedure.exportables_pieces_jointes.find { _1.stable_id.to_s == pj_sym[:stable_id] }&.libelle&.to_sym - validate_content(record, pj_sym[:path], libelle) - end + def validate_different_templates(export_template) + templates = [export_template.export_pdf, *export_template.pjs] + .filter(&:enabled?) + .map(&:template_string) + + return if templates.uniq.size == templates.size + + export_template.errors.add(:base, :different_templates) end - def validate_content(record, attribute_content, attribute) - if attribute_content.nil? || attribute_content["content"].nil? || - attribute_content["content"].first.nil? || - attribute_content["content"].first["content"].nil? || - (attribute_content["content"].first["content"].find { |elem| elem["text"].blank? } && attribute_content["content"].first["content"].find { |elem| elem["type"] == "mention" }["attrs"].blank?) - record.errors.add attribute, I18n.t(:blank, scope: 'errors.messages') - end + def pj_libelle_by_stable_id(export_template) + export_template.procedure.exportables_pieces_jointes + .pluck(:stable_id, :libelle).to_h end end diff --git a/config/locales/models/export_templates/en.yml b/config/locales/models/export_templates/en.yml index e6cd08856..9ec65402c 100644 --- a/config/locales/models/export_templates/en.yml +++ b/config/locales/models/export_templates/en.yml @@ -15,3 +15,5 @@ en: models: export_template: dossier_number_mandatory: "must contain dossier's number" + different_templates: "Files must have different names" + invalid_template: "A file name is invalid" diff --git a/config/locales/models/export_templates/fr.yml b/config/locales/models/export_templates/fr.yml index 60852aee0..04ef38215 100644 --- a/config/locales/models/export_templates/fr.yml +++ b/config/locales/models/export_templates/fr.yml @@ -15,3 +15,5 @@ fr: models: export_template: dossier_number_mandatory: doit contenir le numéro du dossier + different_templates: Les fichiers doivent avoir des noms différents + invalid_template: Un nom de fichier est invalide diff --git a/spec/validators/export_template_validator_spec.rb b/spec/validators/export_template_validator_spec.rb new file mode 100644 index 000000000..53e1c7f0a --- /dev/null +++ b/spec/validators/export_template_validator_spec.rb @@ -0,0 +1,79 @@ +describe ExportTemplateValidator do + let(:validator) { ExportTemplateValidator.new } + + describe 'validate' do + let(:exportables_pieces_jointes) { [double('pj', stable_id: 3, libelle: 'libelle')] } + let(:pj_libelle_by_stable_id) { exportables_pieces_jointes.map { |pj| [pj.stable_id, pj.libelle] }.to_h } + + def empty_template(enabled: true, stable_id: nil) + { template: { type: "doc", content: [] }, enabled: enabled, stable_id: stable_id }.compact + end + + def errors(export_template) = export_template.errors.map { [_1.attribute, _1.message] } + + before do + allow(validator).to receive(:pj_libelle_by_stable_id).and_return(pj_libelle_by_stable_id) + validator.validate(export_template) + end + + context 'with a default export template' do + let(:export_template) { build(:export_template) } + + it { expect(export_template.errors.count).to eq(0) } + end + + context 'with a invalid template' do + let(:export_template) do + export_pdf = { template: { is: 'invalid' }, enabled: true } + build(:export_template, export_pdf:) + end + + it { expect(errors(export_template)).to eq([[:base, "Un nom de fichier est invalide"]]) } + end + + context 'with a empty export_pdf' do + let(:export_template) { build(:export_template, export_pdf: empty_template) } + + it { expect(errors(export_template)).to eq([[:export_pdf, "doit être rempli"]]) } + end + + context 'with a empty export_pdf disabled' do + let(:export_template) { build(:export_template, export_pdf: empty_template(enabled: false)) } + + it { expect(export_template.errors.count).to eq(0) } + end + + context 'with a dossier_folder without dossier_number' do + let(:export_template) do + dossier_folder = ExportItem.default(prefix: 'dossier') + dossier_folder.template[:content][0][:content][1][:attrs][:id] = :other + + build(:export_template, dossier_folder:) + end + + it { expect(errors(export_template)).to eq([[:dossier_folder, "doit contenir le numéro du dossier"]]) } + end + + context 'with a empty pj' do + let(:export_template) { build(:export_template, pjs: [empty_template(stable_id: 3)]) } + + it { expect(errors(export_template)).to eq([[:libelle, "doit être rempli"]]) } + end + + context 'with a empty pj disabled' do + let(:export_template) { build(:export_template, pjs: [empty_template(enabled: false)]) } + + it { expect(export_template.errors.count).to eq(0) } + end + + context 'with multiple files bearing the same template' do + let(:export_item) { ExportItem.default(prefix: 'same') } + + let(:export_template) do + build(:export_template, export_pdf: export_item, pjs: [export_item]) + end + + it { expect(errors(export_template)).to eq([[:base, "Les fichiers doivent avoir des noms différents"]]) } + end + end +end