diff --git a/.scss-lint.yml b/.scss-lint.yml
index dfa4bc00d79..d615d0ea121 100644
--- a/.scss-lint.yml
+++ b/.scss-lint.yml
@@ -150,7 +150,7 @@ linters:
properties: {}
PseudoElement:
- enabled: true
+ enabled: false # otherwise rules on ::marker fails
# To enable later
QualifyingElement:
diff --git a/app/assets/stylesheets/dossier_edit.scss b/app/assets/stylesheets/dossier_edit.scss
index ae57abd6d67..9690a508f37 100644
--- a/app/assets/stylesheets/dossier_edit.scss
+++ b/app/assets/stylesheets/dossier_edit.scss
@@ -42,11 +42,6 @@ $dossier-actions-bar-border-width: 1px;
}
}
- .characters-count {
- position: relative;
- top: -1rem;
- }
-
.warning {
margin-bottom: 20px;
background-color: #f9b91666;
diff --git a/app/assets/stylesheets/dsfr.scss b/app/assets/stylesheets/dsfr.scss
index ef709bd1ece..7eb7a556980 100644
--- a/app/assets/stylesheets/dsfr.scss
+++ b/app/assets/stylesheets/dsfr.scss
@@ -1,5 +1,15 @@
@import "colors";
+// overwrite DSFR style for SimpleFormatComponent, some user use markdown with
+// ordered list having paragraph between list item
+ol.fr-ol-content--override {
+ list-style-type: decimal;
+
+ li::marker {
+ content: inherit;
+ }
+}
+
// override default transparent background on inputs & font-size to 16px by default
input,
textarea,
diff --git a/app/assets/stylesheets/forms.scss b/app/assets/stylesheets/forms.scss
index f3cf44ca23d..d234a108863 100644
--- a/app/assets/stylesheets/forms.scss
+++ b/app/assets/stylesheets/forms.scss
@@ -43,14 +43,13 @@
font-style: italic;
}
- .fr-input-group,
- .fr-select-group {
+ .fr-input-group {
margin-bottom: 1rem;
}
.section-2 {
margin-top: 1.5rem;
- padding-top: 2rem;
+ padding-top: 1rem;
border-top: 2px solid var(--border-default-grey);
}
@@ -67,16 +66,6 @@
margin-bottom: 1rem;
}
- // Keep only bottom margin in nested (consecutive) header sections, ie. first legend for a same level
- .fr-fieldset > .fr-fieldset__legend + .fr-fieldset__element > .fr-fieldset:first-of-type .header-section {
- margin-top: 0 !important;
- }
-
- // Don't cumulate margin-bottoms for inlined elements (radio...), because .fr-fieldset has already its own
- .fr-fieldset__element > .fr-fieldset > .fr-fieldset__element.fr-fieldset__element--inline {
- margin-bottom: 0;
- }
-
legend {
width: 100%;
}
@@ -97,7 +86,7 @@
.mandatory {
- color: $dark-red;
+ fill: currentColor;
}
label:not(.fr-label),
@@ -158,7 +147,6 @@
}
&.editable-champ-checkbox {
- p,
label {
padding-left: 28px;
font-weight: normal;
@@ -256,7 +244,7 @@
user-select: none;
&:last-of-type {
- margin-bottom: $default-fields-spacer;
+ margin-bottom: 0;
}
&:hover {
@@ -293,17 +281,21 @@
}
}
- input[type=text],
- input[type=email],
+ .fr-label {
+ // la description d'un champ peut contenir du markup (markdown->html),
+ // on herite donc la fontsize/mrgin/padding du fr-hint-text
+ .fr-hint-text > * {
+ font-size: inherit;
+ margin: inherit;
+ // disabled for pf to allow ul/ol tags to work
+ // padding: inherit;
+ }
+ }
+
input[type=password],
- input[type=date],
- input[type=datetime-local],
- input[type=number],
- input[type=tel],
- textarea,
select {
display: block;
- margin-bottom: $default-fields-spacer;
+ margin-bottom: 0;
&.small-margin {
margin-bottom: $default-spacer;
@@ -327,13 +319,6 @@
}
input[type=text]:not([data-address='true']),
- input[type=email],
- input[type=password],
- input[type=date],
- input[type=number],
- input[type=tel],
- input[type=datetime-local],
- textarea,
select {
border-radius: 4px;
border: solid 1px $border-grey;
@@ -375,8 +360,8 @@
input[type=date],
input[type=number],
input[type=datetime-local],
- input[type=tel],
- textarea {
+ textarea,
+ input[type=tel], {
@media (max-width: $two-columns-breakpoint) {
width: 100%;
}
@@ -435,7 +420,7 @@
margin-left: 5px;
margin-right: 4px;
- margin-bottom: $default-fields-spacer;
+ margin-bottom: 0;
}
[data-reach-combobox-input] {
@@ -522,16 +507,6 @@
color: $dark-grey;
}
- .datetime {
- input[type=date] {
- display: inline-block;
- }
-
- select {
- display: inline-block;
- }
- }
-
.header-subsection {
font-size: 22px;
color: $blue-france-500;
@@ -554,20 +529,6 @@
}
}
- .siret-info {
- margin-top: -$default-fields-spacer;
- margin-bottom: $default-fields-spacer;
- // Ensure the bottom-margin is not collapsed when the element is empty
- min-height: 1px;
- }
-
- .rna-info {
- margin-top: -$default-fields-spacer;
- margin-bottom: $default-fields-spacer;
- // Ensure the bottom-margin is not collapsed when the element is empty
- min-height: 1px;
- }
-
.send-wrapper {
display: flex;
width: 100%;
@@ -641,12 +602,6 @@
}
}
-[data-react-component-value]:not([data-react-component-value^="ComboMultiple"]) {
- [data-reach-combobox-input]:not(.no-margin) {
- margin-bottom: $default-fields-spacer;
- }
-}
-
[data-react-component-value^="ComboMultiple"] {
margin-bottom: $default-fields-spacer;
diff --git a/app/assets/stylesheets/manager.scss b/app/assets/stylesheets/manager.scss
index 7e0be3a879b..de6abef3fdb 100644
--- a/app/assets/stylesheets/manager.scss
+++ b/app/assets/stylesheets/manager.scss
@@ -52,7 +52,7 @@
opacity: 0.6;
}
-.mandatory {
+.manager-mandatory {
color: #A10005;
font-size: 18px;
}
diff --git a/app/components/attachment/edit_component/edit_component.html.haml b/app/components/attachment/edit_component/edit_component.html.haml
index 2d81e95063c..116271c19ce 100644
--- a/app/components/attachment/edit_component/edit_component.html.haml
+++ b/app/components/attachment/edit_component/edit_component.html.haml
@@ -1,4 +1,4 @@
-.attachment.fr-upload-group{ { id: attachment ? dom_id(attachment, :edit) : nil, class: class_names("fr-mb-2w": !(as_multiple? && downloadable?)) }.compact, **replace_controller_attributes }
+.attachment.fr-upload-group{ { id: attachment ? dom_id(attachment, :edit) : nil, class: class_names("fr-mb-1w": !(as_multiple? && downloadable?)) }.compact, **replace_controller_attributes }
- if persisted?
%div{ id: dom_id(attachment, :persisted_row) }
.flex.flex-gap-2{ class: class_names("attachment-error": attachment.virus_scanner_error?) }
diff --git a/app/components/attachment/multiple_component/multiple_component.html.haml b/app/components/attachment/multiple_component/multiple_component.html.haml
index ecca7269f43..ab507b8aee7 100644
--- a/app/components/attachment/multiple_component/multiple_component.html.haml
+++ b/app/components/attachment/multiple_component/multiple_component.html.haml
@@ -1,10 +1,11 @@
-.fr-mb-4w.attachment-multiple{ class: class_names("fr-downloads-group": view_as == :download, "destroyable": user_can_destroy?), **replace_controller_attributes }
+.attachment-multiple{ class: class_names("fr-downloads-group": view_as == :download, "destroyable": user_can_destroy?), **replace_controller_attributes }
= template
- %ul
- - each_attachment do |attachment, index|
- %li{ id: dom_id(attachment) }
- = render Attachment::EditComponent.new(champ:, attached_file:, attachment:, index:, as_multiple: true, view_as:, user_can_destroy:, user_can_replace:, form_object_name:)
+ - if @attachments.size >= 1
+ %ul.fr-my-1v
+ - each_attachment do |attachment, index|
+ %li{ id: dom_id(attachment) }
+ = render Attachment::EditComponent.new(champ:, attached_file:, attachment:, index:, as_multiple: true, view_as:, user_can_destroy:, user_can_replace:, form_object_name:)
%div{ id: empty_component_id, class: class_names("hidden": !can_attach_next?) }
= render Attachment::EditComponent.new(champ:, attached_file:, attachment: nil, index: attachments_count, user_can_destroy:, user_can_replace:, form_object_name:)
diff --git a/app/components/dossiers/autosave_footer_component/autosave_footer_component.html.haml b/app/components/dossiers/autosave_footer_component/autosave_footer_component.html.haml
index 78e38c3c4d8..976e29b265d 100644
--- a/app/components/dossiers/autosave_footer_component/autosave_footer_component.html.haml
+++ b/app/components/dossiers/autosave_footer_component/autosave_footer_component.html.haml
@@ -1,5 +1,5 @@
.autosave.autosave-state-idle{ data: { controller: 'autosave-status' } }
- %p.autosave-explanation.fr-text--sm
+ %p.autosave-explanation.fr-text--sm.fr-mb-0
%span.autosave-explanation-text
- if annotation?
= t('.annotations.explanation')
@@ -10,7 +10,7 @@
- if !annotation?
= link_to t('.more_information'), t("links.common.faq.autosave_url"), class: 'autosave-more-infos fr-link fr-link--sm', **external_link_attributes
- %p.autosave-status.succeeded
+ %p.autosave-status.succeeded.fr-mb-0
%span.autosave-icon.icon.accept
%span.autosave-label
- if annotation?
@@ -22,7 +22,7 @@
- if !annotation?
= link_to t('.more_information'), t("links.common.faq.autosave_url"), class: 'autosave-more-infos fr-link fr-link--sm', **external_link_attributes
- %p.autosave-status.failed
+ %p.autosave-status.failed.fr-mb-0
%span.autosave-icon ⚠️
%span.autosave-label
- if annotation?
diff --git a/app/components/dossiers/edit_footer_component/edit_footer_component.en.yml b/app/components/dossiers/edit_footer_component/edit_footer_component.en.yml
index c6b8c398d90..098e6ec0b86 100644
--- a/app/components/dossiers/edit_footer_component/edit_footer_component.en.yml
+++ b/app/components/dossiers/edit_footer_component/edit_footer_component.en.yml
@@ -3,4 +3,4 @@ en:
submit: Submit the file
submit_changes: Submit file changes
submitting: Submitting…
- invite_notice: You are invited to make amendments to this file but only the owner themselves can submit it.
+ invite_notice: You are invited to make amendments to this file but only the owner themselves can submit it.
diff --git a/app/components/dossiers/edit_footer_component/edit_footer_component.fr.yml b/app/components/dossiers/edit_footer_component/edit_footer_component.fr.yml
index decf8b3fc80..33937aed683 100644
--- a/app/components/dossiers/edit_footer_component/edit_footer_component.fr.yml
+++ b/app/components/dossiers/edit_footer_component/edit_footer_component.fr.yml
@@ -3,4 +3,4 @@ fr:
submit: Déposer le dossier
submit_changes: Déposer les modifications
submitting: Envoi en cours…
- invite_notice: En tant qu’invité, vous pouvez remplir ce formulaire – mais le titulaire du dossier doit le déposer lui-même.
+ invite_notice: En tant qu’invité, vous pouvez remplir ce formulaire – mais le titulaire du dossier doit le déposer lui-même.
diff --git a/app/components/dossiers/edit_footer_component/edit_footer_component.html.haml b/app/components/dossiers/edit_footer_component/edit_footer_component.html.haml
index 277fb5d0bfd..d2569106ebe 100644
--- a/app/components/dossiers/edit_footer_component/edit_footer_component.html.haml
+++ b/app/components/dossiers/edit_footer_component/edit_footer_component.html.haml
@@ -9,8 +9,12 @@
- if @dossier.brouillon? && !owner?
- .send-notice.invite-cannot-submit
- = t('.invite_notice')
+ .fr-pb-2w.invite-cannot-submit
+ = render ::Dsfr::AlertComponent.new(state: :info, title: nil, size: :sm, heading_level: :p, extra_class_names:'') do |c|
+ - c.body do
+ %p.fr-pb-0= t('.invite_notice').html_safe
+
+
- if !annotation?
= render partial: "shared/dossiers/submit_is_over", locals: { dossier: @dossier }
diff --git a/app/components/dsfr/input_component.rb b/app/components/dsfr/input_component.rb
index 2717624701f..dca55d51eb2 100644
--- a/app/components/dsfr/input_component.rb
+++ b/app/components/dsfr/input_component.rb
@@ -1,4 +1,6 @@
class Dsfr::InputComponent < ApplicationComponent
+ include Dsfr::InputErrorable
+
delegate :object, to: :@form
delegate :errors, to: :object
@@ -18,10 +20,10 @@ def initialize(form:, attribute:, input_type: :text_field, opts: {}, required: t
# and and valid on input only if another input is invalid
def input_group_opts
opts = {
- class: class_names('fr-input-group': true,
- 'fr-password': password?,
- "fr-input-group--error": errors_on_attribute?,
- "fr-input-group--valid": !errors_on_attribute? && errors_on_another_attribute?)
+ class: class_names({
+ 'fr-input-group': true,
+ 'fr-password': password?
+ }.merge(input_group_error_class_names))
}
if email?
opts[:data] = { controller: 'email-input' }
@@ -33,38 +35,7 @@ def label_opts
{ class: class_names('fr-label': true, 'fr-password__label': password?) }
end
- def input_opts
- @opts[:class] = class_names(map_array_to_hash_with_true(@opts[:class])
- .merge('fr-password__input': password?,
- 'fr-input': true,
- 'fr-mb-0': true,
- 'fr-input--error': errors_on_attribute?))
-
- if errors_on_attribute? || describedby?
- @opts.deep_merge!(aria: {
- describedby: describedby_id,
- invalid: errors_on_attribute?
- })
- end
-
- if @required
- @opts[:required] = true
- end
-
- if email?
- @opts.deep_merge!(data: {
- action: "blur->email-input#checkEmail",
- 'email-input-target': 'input'
- })
- end
- @opts
- end
-
# errors helpers
- def errors_on_attribute?
- errors.has_key?(attribute_or_rich_body)
- end
-
def error_messages
errors.full_messages_for(attribute_or_rich_body)
end
@@ -78,10 +49,6 @@ def label
object.class.human_attribute_name(@attribute)
end
- def hint
- I18n.t("activerecord.attributes.#{object.class.name.underscore}.hints.#{@attribute}")
- end
-
# kind of input helpers
def password?
@input_type == :password_field
@@ -96,27 +63,4 @@ def show_password_id
end
private
-
- def hint?
- I18n.exists?("activerecord.attributes.#{object.class.name.underscore}.hints.#{@attribute}")
- end
-
- def errors_on_another_attribute?
- !errors.empty?
- end
-
- # lookup for edge case from `form.rich_text_area`
- # rich text uses _rich_#{attribute}, but it is saved on #{attribute}, as well as error messages
- def attribute_or_rich_body
- case @input_type
- when :rich_text_area
- @attribute.to_s.sub(/\Arich_/, '').to_sym
- else
- @attribute
- end
- end
-
- def map_array_to_hash_with_true(array_or_string_or_nil)
- Array(array_or_string_or_nil).to_h { [_1, true] }
- end
end
diff --git a/app/components/dsfr/input_errorable.rb b/app/components/dsfr/input_errorable.rb
new file mode 100644
index 00000000000..9c8164172cd
--- /dev/null
+++ b/app/components/dsfr/input_errorable.rb
@@ -0,0 +1,108 @@
+module Dsfr
+ module InputErrorable
+ extend ActiveSupport::Concern
+ included do
+ delegate :object, to: :@form
+ delegate :errors, to: :object
+
+ private
+
+ # lookup for edge case from `form.rich_text_area`
+ # rich text uses _rich_#{attribute}, but it is saved on #{attribute}, as well as error messages
+ def attribute_or_rich_body
+ case @input_type
+ when :rich_text_area
+ @attribute.to_s.sub(/\Arich_/, '').to_sym
+ else
+ @attribute
+ end
+ end
+
+ def input_group_error_class_names
+ {
+ "fr-input-group--error": errors_on_attribute?,
+ "fr-input-group--valid": !errors_on_attribute? && errors_on_another_attribute?
+ }
+ end
+
+ def input_error_class_names
+ { 'fr-input--error': errors_on_attribute? }
+ end
+
+ def input_error_opts
+ {
+ aria: {
+ describedby: describedby_id,
+ invalid: errors_on_attribute?
+ }
+ }
+ end
+
+ def input_opts(other_opts = {})
+ @opts = @opts.deep_merge!(other_opts)
+ @opts[:class] = class_names(map_array_to_hash_with_true(@opts[:class])
+ .merge({
+ 'fr-password__input': password?,
+ 'fr-input': true,
+ 'fr-mb-0': true
+ }.merge(input_error_class_names)))
+
+ if errors_on_attribute?
+ @opts.deep_merge!(aria: {
+ describedby: describedby_id,
+ invalid: errors_on_attribute?
+ })
+ end
+
+ if @required
+ @opts[:required] = true
+ end
+
+ if email?
+ @opts.deep_merge!(data: {
+ action: "blur->email-input#checkEmail",
+ 'email-input-target': 'input'
+ })
+ end
+ @opts
+ end
+
+ def describedby_id
+ dom_id(@champ, :error_full_messages)
+ end
+
+ def errors_on_another_attribute?
+ !errors.empty?
+ end
+
+ def errors_on_attribute?
+ errors.has_key?(attribute_or_rich_body)
+ end
+
+ # errors helpers
+ def error_full_messages
+ errors.full_messages_for(attribute_or_rich_body)
+ end
+
+ def map_array_to_hash_with_true(array_or_string_or_nil)
+ Array(array_or_string_or_nil).to_h { [_1, true] }
+ end
+
+ def hint
+ I18n.t("activerecord.attributes.#{object.class.name.underscore}.hints.#{@attribute}")
+ end
+
+ def password?
+ false
+ end
+
+ def email?
+ false
+ end
+
+ def hint?
+ I18n.exists?("activerecord.attributes.#{object.class.name.underscore}.hints.#{@attribute}")
+ end
+ end
+ end
+end
diff --git a/app/components/editable_champ/champ_label_component.rb b/app/components/editable_champ/champ_label_component.rb
index de0a6fea30b..967a95584d0 100644
--- a/app/components/editable_champ/champ_label_component.rb
+++ b/app/components/editable_champ/champ_label_component.rb
@@ -1,5 +1,8 @@
class EditableChamp::ChampLabelComponent < ApplicationComponent
+ include Dsfr::InputErrorable
+
def initialize(form:, champ:, seen_at: nil)
@form, @champ, @seen_at = form, champ, seen_at
+ @attribute = :value
end
end
diff --git a/app/components/editable_champ/champ_label_component/champ_label_component.html.haml b/app/components/editable_champ/champ_label_component/champ_label_component.html.haml
index d860df31405..eda623420cc 100644
--- a/app/components/editable_champ/champ_label_component/champ_label_component.html.haml
+++ b/app/components/editable_champ/champ_label_component/champ_label_component.html.haml
@@ -1,10 +1,9 @@
= # we do this trick because some html elements should use 'label' and some should be plain paragraphs
- if @champ.html_label?
- = @form.label @champ.main_value_name, id: @champ.labelledby_id, for: @champ.input_id do
- - render EditableChamp::ChampLabelContentComponent.new champ: @champ, seen_at: @seen_at
+ = @form.label @champ.main_value_name, id: @champ.labelledby_id, for: @champ.input_id, class: 'fr-label' do
+ - render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at
- else
- .form-label.mb-4{ id: @champ.labelledby_id }
- = render EditableChamp::ChampLabelContentComponent.new champ: @champ, seen_at: @seen_at
+ .fr-label.mb-4{ id: @champ.labelledby_id }
+ = render EditableChamp::ChampLabelContentComponent.new form: @form, champ: @champ, seen_at: @seen_at
+
-- if @champ.description.present?
- .notice{ id: @champ.describedby_id }= render SimpleFormatComponent.new(@champ.description, allow_a: true)
diff --git a/app/components/editable_champ/champ_label_content_component.rb b/app/components/editable_champ/champ_label_content_component.rb
index 60025939e67..21069fe98f0 100644
--- a/app/components/editable_champ/champ_label_content_component.rb
+++ b/app/components/editable_champ/champ_label_content_component.rb
@@ -1,8 +1,10 @@
class EditableChamp::ChampLabelContentComponent < ApplicationComponent
include ApplicationHelper
+ include Dsfr::InputErrorable
- def initialize(champ:, seen_at: nil)
- @champ, @seen_at = champ, seen_at
+ def initialize(form:, champ:, seen_at: nil)
+ @form, @champ, @seen_at = form, champ, seen_at
+ @attribute = :value
end
def highlight_if_unseen_class
diff --git a/app/components/editable_champ/champ_label_content_component/champ_label_content_component.en.yml b/app/components/editable_champ/champ_label_content_component/champ_label_content_component.en.yml
index 9d642dd7263..fbbc60b2e67 100644
--- a/app/components/editable_champ/champ_label_content_component/champ_label_content_component.en.yml
+++ b/app/components/editable_champ/champ_label_content_component/champ_label_content_component.en.yml
@@ -4,3 +4,5 @@ en:
modified_at: "modified on %{datetime}"
check_content_rebased: The type of this field or its description has been modified by the administration. Check its content.
optional_champ: (optional)
+ recommended_size: The recommended maximum size is %{size} characters.
+ titre_identite_notice: National identity card (front side only), passport, residency permit or other proof of identity.
diff --git a/app/components/editable_champ/champ_label_content_component/champ_label_content_component.fr.yml b/app/components/editable_champ/champ_label_content_component/champ_label_content_component.fr.yml
index 0201f614036..d129bfa1edc 100644
--- a/app/components/editable_champ/champ_label_content_component/champ_label_content_component.fr.yml
+++ b/app/components/editable_champ/champ_label_content_component/champ_label_content_component.fr.yml
@@ -4,3 +4,5 @@ fr:
modified_at: "modifié le %{datetime}"
check_content_rebased: Le type de ce champ ou sa description ont été modifiés par l'administration. Vérifier son contenu.
optional_champ: (facultatif)
+ recommended_size: La taille maximale conseillée est de %{size} caractères.
+ titre_identite_notice: Carte nationale d’identité (uniquement le recto), passeport, titre de séjour ou autre justificatif d’identité.
diff --git a/app/components/editable_champ/champ_label_content_component/champ_label_content_component.html.haml b/app/components/editable_champ/champ_label_content_component/champ_label_content_component.html.haml
index c71eab31565..bfa3148f3f1 100644
--- a/app/components/editable_champ/champ_label_content_component/champ_label_content_component.html.haml
+++ b/app/components/editable_champ/champ_label_content_component/champ_label_content_component.html.haml
@@ -18,3 +18,15 @@
- if @champ.rebased_at.present? && @champ.rebased_at > (@seen_at || @champ.updated_at) && current_user.owns_or_invite?(@champ.dossier)
%span.updated-at.highlighted
= t('.check_content_rebased')
+
+- if @champ.titre_identite?
+ %span.fr-hint-text= t('.titre_identite_notice')
+
+- if hint?
+ %span.fr-hint-text= hint
+
+- if @champ.description.present?
+ %span.fr-hint-text{ id: @champ.describedby_id }= render SimpleFormatComponent.new(@champ.description, allow_a: true)
+
+- if @champ.textarea?
+ %span.sr-only= t('.recommended_size', size: @champ.character_limit_base)
diff --git a/app/components/editable_champ/date_component/date_component.html.haml b/app/components/editable_champ/date_component/date_component.html.haml
index 335ba79436b..14c083d0e6f 100644
--- a/app/components/editable_champ/date_component/date_component.html.haml
+++ b/app/components/editable_champ/date_component/date_component.html.haml
@@ -1,9 +1,9 @@
= @form.date_field :value,
- id: @champ.input_id,
+ input_opts(id: @champ.input_id,
aria: { describedby: @champ.describedby_id },
value: @champ.value,
required: @champ.required?,
min: @champ.type_de_champ.min.present? ? @champ.type_de_champ.min : nil,
max: @champ.type_de_champ.max.present? ? @champ.type_de_champ.max : Date.iso8601('2100-12-31'),
placeholder: 'aaaa-mm-jj',
- class: "width-33-desktop"
+ class: "width-33-desktop")
diff --git a/app/components/editable_champ/datetime_component/datetime_component.html.haml b/app/components/editable_champ/datetime_component/datetime_component.html.haml
index 5f0b4dab718..9b6931e72b6 100644
--- a/app/components/editable_champ/datetime_component/datetime_component.html.haml
+++ b/app/components/editable_champ/datetime_component/datetime_component.html.haml
@@ -1,2 +1 @@
-.datetime
- = @form.datetime_field(:value, value: formatted_value_for_datetime_locale, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, data: { controller: 'datetime' })
+= @form.datetime_field(:value, input_opts(value: formatted_value_for_datetime_locale, id: @champ.input_id, aria: { describedby: @champ.describedby_id }, data: { controller: 'datetime' }))
diff --git a/app/components/editable_champ/decimal_number_component/decimal_number_component.html.haml b/app/components/editable_champ/decimal_number_component/decimal_number_component.html.haml
index f0cd272a5cd..0c9c6c0d70c 100644
--- a/app/components/editable_champ/decimal_number_component/decimal_number_component.html.haml
+++ b/app/components/editable_champ/decimal_number_component/decimal_number_component.html.haml
@@ -1,6 +1 @@
-= @form.number_field :value,
- id: @champ.input_id,
- aria: { describedby: @champ.describedby_id },
- step: :any,
- placeholder: "3.14",
- required: @champ.required?
+= @form.number_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, step: :any, placeholder: "3.14", required: @champ.required?))
diff --git a/app/components/editable_champ/dossier_link_component/dossier_link_component.html.haml b/app/components/editable_champ/dossier_link_component/dossier_link_component.html.haml
index 3e4169f40a8..2db3bd8057c 100644
--- a/app/components/editable_champ/dossier_link_component/dossier_link_component.html.haml
+++ b/app/components/editable_champ/dossier_link_component/dossier_link_component.html.haml
@@ -1,18 +1,8 @@
-.dossier-link
- = @form.text_field :value,
- id: @champ.input_id,
- aria: { describedby: @champ.describedby_id },
- inputmode: :numeric,
- min: 1,
- pattern: "[0-9]{1,12}",
- placeholder: "Numéro de dossier",
- autocomplete: 'off',
- required: @champ.required?,
- class: "width-33-desktop #{@champ.blank? ? '' : 'small-margin'}"
+= @form.text_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, inputmode: :numeric, min: 1, pattern: "[0-9]{1,12}", placeholder: "Numéro de dossier", autocomplete: 'off', required: @champ.required?, class: "width-33-desktop #{@champ.blank? ? '' : 'small-margin'}"))
- - if !@champ.blank?
- - if dossier.blank?
- .fr-error-text.fr-mb-4w
- = t('.not_found')
- - else
- .fr-info-text.fr-mb-4w= sanitize(dossier.text_summary)
+- if !@champ.blank?
+ - if dossier.blank?
+ .fr-error-text.fr-mb-4w
+ = t('.not_found')
+ - else
+ .fr-info-text.fr-mb-4w= sanitize(dossier.text_summary)
diff --git a/app/components/editable_champ/editable_champ_base_component.rb b/app/components/editable_champ/editable_champ_base_component.rb
index 08408a95cff..21b0d49d4ad 100644
--- a/app/components/editable_champ/editable_champ_base_component.rb
+++ b/app/components/editable_champ/editable_champ_base_component.rb
@@ -1,5 +1,8 @@
class EditableChamp::EditableChampBaseComponent < ApplicationComponent
- def initialize(form:, champ:, seen_at: nil)
- @form, @champ, @seen_at = form, champ, seen_at
+ include Dsfr::InputErrorable
+
+ def initialize(form:, champ:, seen_at: nil, opts: {})
+ @form, @champ, @seen_at, @opts = form, champ, seen_at, opts
+ @attribute = :value
end
end
diff --git a/app/components/editable_champ/editable_champ_component.rb b/app/components/editable_champ/editable_champ_component.rb
index f335a181e88..a4a553af980 100644
--- a/app/components/editable_champ/editable_champ_component.rb
+++ b/app/components/editable_champ/editable_champ_component.rb
@@ -1,6 +1,9 @@
class EditableChamp::EditableChampComponent < ApplicationComponent
+ include Dsfr::InputErrorable
+
def initialize(form:, champ:, seen_at: nil)
@form, @champ, @seen_at = form, champ, seen_at
+ @attribute = :value
end
private
@@ -21,8 +24,12 @@ def component_class
def html_options
{
class: class_names(
- "editable-champ-#{@champ.type_champ}": true,
- "hidden": !@champ.visible?
+ {
+ 'editable-champ': true,
+ "editable-champ-#{@champ.type_champ}": true,
+ "hidden": !@champ.visible?,
+ "fr-input-group": true
+ }.merge(input_group_error_class_names)
),
id: @champ.input_group_id,
data: { controller: stimulus_controller, **data_dependent_conditions, **stimulus_values }
diff --git a/app/components/editable_champ/editable_champ_component/editable_champ_component.en.yml b/app/components/editable_champ/editable_champ_component/editable_champ_component.en.yml
index 48cb6286e8b..e944e6ca508 100644
--- a/app/components/editable_champ/editable_champ_component/editable_champ_component.en.yml
+++ b/app/components/editable_champ/editable_champ_component/editable_champ_component.en.yml
@@ -1,4 +1,4 @@
---
en:
titre_identite_notice: National identity card (front side only), passport, residency permit or other proof of identity.
- datetime_notice: "Expected format : dd/mm/yyyy hh:mm"
+
diff --git a/app/components/editable_champ/editable_champ_component/editable_champ_component.fr.yml b/app/components/editable_champ/editable_champ_component/editable_champ_component.fr.yml
index c7e4f5d7e30..dc1731448ad 100644
--- a/app/components/editable_champ/editable_champ_component/editable_champ_component.fr.yml
+++ b/app/components/editable_champ/editable_champ_component/editable_champ_component.fr.yml
@@ -1,4 +1,3 @@
---
fr:
titre_identite_notice: Carte nationale d’identité (uniquement le recto), passeport, titre de séjour ou autre justificatif d’identité.
- datetime_notice: "Format attendu : jj/mm/aaaa hh:mm"
diff --git a/app/components/editable_champ/editable_champ_component/editable_champ_component.html.haml b/app/components/editable_champ/editable_champ_component/editable_champ_component.html.haml
index c73824c8156..89b4f35213a 100644
--- a/app/components/editable_champ/editable_champ_component/editable_champ_component.html.haml
+++ b/app/components/editable_champ/editable_champ_component/editable_champ_component.html.haml
@@ -1,10 +1,15 @@
-.editable-champ{ html_options }
+= content_tag(:div, html_options) do
- if has_label?(@champ)
= render EditableChamp::ChampLabelComponent.new form: @form, champ: @champ, seen_at: @seen_at
- - if @champ.titre_identite?
- %p.notice= t('.titre_identite_notice')
- - elsif @champ.datetime?
- %p.notice= t('.datetime_notice')
+ = render component_class.new(form: @form, champ: @champ, seen_at: @seen_at)
+
+ - if errors_on_attribute?
+ - if error_full_messages.size == 1
+ %p.fr-error-text{ id: describedby_id }= error_full_messages.first
+ - else
+ .fr-error-text{ id: describedby_id }
+ %ul.list-style-type-none.fr-pl-0
+ - error_full_messages.each do |error_message|
+ %li= error_message
= @form.hidden_field :id, value: @champ.id
- = render component_class.new(form: @form, champ: @champ, seen_at: @seen_at)
diff --git a/app/components/editable_champ/email_component.rb b/app/components/editable_champ/email_component.rb
index fbc0774e2a4..b7dbcddb2c4 100644
--- a/app/components/editable_champ/email_component.rb
+++ b/app/components/editable_champ/email_component.rb
@@ -1,2 +1,5 @@
class EditableChamp::EmailComponent < EditableChamp::EditableChampBaseComponent
+ def email?
+ true
+ end
end
diff --git a/app/components/editable_champ/email_component/email_component.html.haml b/app/components/editable_champ/email_component/email_component.html.haml
index 152253c70f8..9f77ce08abe 100644
--- a/app/components/editable_champ/email_component/email_component.html.haml
+++ b/app/components/editable_champ/email_component/email_component.html.haml
@@ -1,5 +1 @@
-= @form.email_field :value,
- id: @champ.input_id,
- aria: { describedby: @champ.describedby_id },
- placeholder: t(".placeholder"),
- required: @champ.required?
+= @form.email_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: t(".placeholder"), required: @champ.required?))
diff --git a/app/components/editable_champ/etablissement_titre_component/etablissement_titre_component.html.haml b/app/components/editable_champ/etablissement_titre_component/etablissement_titre_component.html.haml
index ebbfdd2c5a0..79e9b3584c0 100644
--- a/app/components/editable_champ/etablissement_titre_component/etablissement_titre_component.html.haml
+++ b/app/components/editable_champ/etablissement_titre_component/etablissement_titre_component.html.haml
@@ -1,4 +1,4 @@
-.explication
+%p.fr-info-text
= raison_sociale_or_name(@etablissement)
= @etablissement.entreprise_forme_juridique
- if @etablissement.entreprise_capital_social.present?
diff --git a/app/components/editable_champ/iban_component/iban_component.html.haml b/app/components/editable_champ/iban_component/iban_component.html.haml
index 151bfaa562e..3c2bc8425d6 100644
--- a/app/components/editable_champ/iban_component/iban_component.html.haml
+++ b/app/components/editable_champ/iban_component/iban_component.html.haml
@@ -1,8 +1 @@
-= @form.text_field :value,
- id: @champ.input_id,
- placeholder: t(".placeholder"),
- required: @champ.required?,
- aria: { describedby: @champ.describedby_id },
- data: { controller: 'format', format: 'iban' },
- class: "width-66-desktop",
- maxlength: 34 + 9 # count space separator of 4 digits-groups
+= @form.text_field(:value, input_opts(id: @champ.input_id, placeholder: t(".placeholder"), required: @champ.required?, aria: { describedby: @champ.describedby_id }, data: { controller: 'format', format: 'iban' }, class: "width-66-desktop", maxlength: 34 + 9)) # count space separator of 4 digits-groups
diff --git a/app/components/editable_champ/integer_number_component/integer_number_component.html.haml b/app/components/editable_champ/integer_number_component/integer_number_component.html.haml
index 3cd29643bd1..24ee9657e12 100644
--- a/app/components/editable_champ/integer_number_component/integer_number_component.html.haml
+++ b/app/components/editable_champ/integer_number_component/integer_number_component.html.haml
@@ -1,7 +1 @@
-= @form.number_field :value,
- id: @champ.input_id,
- aria: { describedby: @champ.describedby_id },
- min: @champ.type_de_champ.min.present? ? @champ.type_de_champ.min : nil,
- max: @champ.type_de_champ.max.present? ? @champ.type_de_champ.max : nil,
- placeholder: 5,
- required: @champ.required?
+= @form.number_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: 5, required: @champ.required?, min: @champ.type_de_champ.min.presence, max: @champ.type_de_champ.max.presence))
diff --git a/app/components/editable_champ/number_component/number_component.html.haml b/app/components/editable_champ/number_component/number_component.html.haml
index 8ee884bcc20..4da3486d15e 100644
--- a/app/components/editable_champ/number_component/number_component.html.haml
+++ b/app/components/editable_champ/number_component/number_component.html.haml
@@ -1,5 +1 @@
-= @form.number_field :value,
- id: @champ.input_id,
- aria: { describedby: @champ.describedby_id },
- placeholder: @champ.libelle,
- required: @champ.required?
+= @form.number_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: @champ.libelle, required: @champ.required?))
diff --git a/app/components/editable_champ/phone_component/phone_component.html.haml b/app/components/editable_champ/phone_component/phone_component.html.haml
index 8ac56bb64e0..d9b0797839c 100644
--- a/app/components/editable_champ/phone_component/phone_component.html.haml
+++ b/app/components/editable_champ/phone_component/phone_component.html.haml
@@ -1,9 +1,4 @@
-# Allowed @formats:
-# very light validation is made client-side
-# stronger validation is made server-side
-= @form.phone_field :value,
- id: @champ.input_id,
- aria: { describedby: @champ.describedby_id },
- placeholder: t(".placeholder"),
- required: @champ.required?,
- pattern: "[^a-zA-Z]+"
+= @form.phone_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: t(".placeholder"), required: @champ.required?, pattern: "[^a-z^A-Z]+"))
diff --git a/app/components/editable_champ/rna_component/rna_component.html.haml b/app/components/editable_champ/rna_component/rna_component.html.haml
index ed679038332..b57423b27e3 100644
--- a/app/components/editable_champ/rna_component/rna_component.html.haml
+++ b/app/components/editable_champ/rna_component/rna_component.html.haml
@@ -1,12 +1,4 @@
-= @form.text_field :value,
- id: @champ.input_id,
- aria: { describedby: @champ.describedby_id },
- placeholder: t(".placeholder"),
- data: { controller: 'turbo-input', turbo_input_load_on_connect_value: @champ.prefilled? && @champ.value.present? && @champ.data.blank?, turbo_input_url_value: champs_rna_path(@champ.id) },
- required: @champ.required?,
- pattern: "W[0-9]{9}",
- title: t(".title"),
- class: "width-33-desktop",
- maxlength: 10
+= @form.text_field(:value, input_opts( id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: t(".placeholder"), data: { controller: 'turbo-input', turbo_input_load_on_connect_value: @champ.prefilled? && @champ.value.present? && @champ.data.blank?, turbo_input_url_value: champs_rna_path(@champ.id) }, required: @champ.required?, pattern: "W[0-9]{9}", title: t(".title"), class: "width-33-desktop", maxlength: 10))
+
.rna-info{ id: dom_id(@champ, :rna_info) }
= render 'shared/champs/rna/association', champ: @champ, error: nil
diff --git a/app/components/editable_champ/siret_component/siret_component.html.haml b/app/components/editable_champ/siret_component/siret_component.html.haml
index 19caf8e7f6f..c87ce7b4b12 100644
--- a/app/components/editable_champ/siret_component/siret_component.html.haml
+++ b/app/components/editable_champ/siret_component/siret_component.html.haml
@@ -1,13 +1,4 @@
-= @form.text_field :value,
- id: @champ.input_id,
- aria: { describedby: @champ.describedby_id },
- placeholder: t(".placeholder"),
- data: { controller: 'turbo-input', turbo_input_load_on_connect_value: @champ.prefilled? && @champ.value.present? && @champ.etablissement.blank?, turbo_input_url_value: champs_siret_path(@champ.id) },
- required: @champ.required?,
- pattern: "[A-Z0-9][0-9]{5}",
- title: t(".title"),
- class: "width-33-desktop",
- maxlength: 6
+= @form.text_field(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, placeholder: t(".placeholder"), data: { controller: 'turbo-input', turbo_input_load_on_connect_value: @champ.prefilled? && @champ.value.present? && @champ.etablissement.blank?, turbo_input_url_value: champs_siret_path(@champ.id) }, required: @champ.required?, pattern: "[A-Z0-9][0-9]{5}", title: t(".title"), class: "width-33-desktop", maxlength: 14))
.spinner.right.hidden
.siret-info{ id: dom_id(@champ, :siret_info) }
- if @champ.etablissement.present?
diff --git a/app/components/editable_champ/text_component/text_component.html.haml b/app/components/editable_champ/text_component/text_component.html.haml
index 326166a21bd..e88fc333281 100644
--- a/app/components/editable_champ/text_component/text_component.html.haml
+++ b/app/components/editable_champ/text_component/text_component.html.haml
@@ -1,4 +1 @@
-= @form.text_field :value,
- id: @champ.input_id,
- required: @champ.required?,
- aria: { describedby: @champ.describedby_id }
+= @form.text_field(:value, input_opts(id: @champ.input_id, required: @champ.required?, aria: { describedby: @champ.describedby_id }))
diff --git a/app/components/editable_champ/textarea_component/textarea_component.en.yml b/app/components/editable_champ/textarea_component/textarea_component.en.yml
index 18b61d2a0a3..8e9b499018a 100644
--- a/app/components/editable_champ/textarea_component/textarea_component.en.yml
+++ b/app/components/editable_champ/textarea_component/textarea_component.en.yml
@@ -1,4 +1,3 @@
en:
remaining_characters: You have %{remaining_words} characters remaining.
excess_characters: You have %{excess_words} characters too many.
- recommended_size: The recommended maximum size is %{size} characters.
diff --git a/app/components/editable_champ/textarea_component/textarea_component.fr.yml b/app/components/editable_champ/textarea_component/textarea_component.fr.yml
index e9d5a7a1227..fa8fafdc1ec 100644
--- a/app/components/editable_champ/textarea_component/textarea_component.fr.yml
+++ b/app/components/editable_champ/textarea_component/textarea_component.fr.yml
@@ -1,4 +1,3 @@
fr:
remaining_characters: Il vous reste %{remaining_words} caractères.
excess_characters: Vous avez dépassé la taille conseillée de %{excess_words} caractères. Réduire le nombre de caractères.
- recommended_size: La taille maximale conseillée est de %{size} caractères.
diff --git a/app/components/editable_champ/textarea_component/textarea_component.html.haml b/app/components/editable_champ/textarea_component/textarea_component.html.haml
index 8a18048ed0f..ac0e7bb5638 100644
--- a/app/components/editable_champ/textarea_component/textarea_component.html.haml
+++ b/app/components/editable_champ/textarea_component/textarea_component.html.haml
@@ -1,16 +1,9 @@
-%span.sr-only= t('.recommended_size', size: @champ.character_limit_base)
-
-~ @form.text_area :value,
- id: @champ.input_id,
- aria: { describedby: @champ.describedby_id },
- rows: 6,
- required: @champ.required?,
- value: html_to_string(@champ.value)
+~ @form.text_area(:value, input_opts(id: @champ.input_id, aria: { describedby: @champ.describedby_id }, rows: 6, required: @champ.required?, value: html_to_string(@champ.value)))
- if @champ.character_limit_info?
- %span.fr-icon-information-fill.fr-text-default--info.characters-count
+ %p.fr-info-text
= t('.remaining_characters', remaining_words: @champ.remaining_characters)
- if @champ.character_limit_warning?
- %span.fr-icon-warning-fill.fr-text-default--warning.characters-count
+ %p.fr-icon--sm.fr-mt-4v.fr-mb-0.fr-hint-text.fr-icon-warning-fill.fr-text-default--warning.characters-count
= t('.excess_characters', excess_words: @champ.excess_characters)
diff --git a/app/components/simple_format_component.rb b/app/components/simple_format_component.rb
index 02f9b86b56b..40c0a13186f 100644
--- a/app/components/simple_format_component.rb
+++ b/app/components/simple_format_component.rb
@@ -1,14 +1,14 @@
class SimpleFormatComponent < ApplicationComponent
# see: https://github.com/vmg/redcarpet#and-its-like-really-simple-to-use
REDCARPET_EXTENSIONS = {
- no_intra_emphasis: false,
+ no_intra_emphasis: true,
+ disable_indented_code_blocks: true,
+ space_after_headers: true,
tables: false,
fenced_code_blocks: false,
autolink: false,
- disable_indented_code_blocks: false,
strikethrough: false,
lax_spacing: false,
- space_after_headers: false,
superscript: false,
underline: false,
highlight: false,
@@ -27,15 +27,7 @@ class SimpleFormatComponent < ApplicationComponent
def initialize(text, allow_a: true, class_names_map: {})
@allow_a = allow_a
- @text = (text || "").gsub(/\R/, "\n\n") # force double \n otherwise a single one won't split paragraph
- .split("\n\n")
- .map { _1.sub(/^\s+(?=[0-9]\.|[^ *-])/, "") } # this block prevent redcarpet to consider " text" as block code by lstriping
- .join("\n\n")
- .gsub(EMAIL_IN_TEXT_REGEX) { _1.gsub('_', '\\_') } # Workaround for redcarpet bug on autolink email having _. Cf tests
-
- if !@allow_a
- @text = @text.gsub(SIMPLE_URL_REGEX) { _1.gsub('_', '\\_') } # Escape underscores in URLs
- end
+ @text = (text || "").gsub(/\R(?=\S)/, "\n\n")
@renderer = Redcarpet::Markdown.new(
Redcarpet::BareRenderer.new(class_names_map:),
@@ -52,6 +44,6 @@ def tags
end
def attributes
- ['target', 'rel', 'href', 'class', 'title', 'size,', 'face,', 'color', 'src']
+ ['target', 'rel', 'href', 'class', 'title', 'value', 'size,', 'face,', 'color', 'src']
end
end
diff --git a/app/controllers/administrateurs/administrateur_controller.rb b/app/controllers/administrateurs/administrateur_controller.rb
index d6c41ed7237..ff93420d9be 100644
--- a/app/controllers/administrateurs/administrateur_controller.rb
+++ b/app/controllers/administrateurs/administrateur_controller.rb
@@ -1,6 +1,8 @@
module Administrateurs
class AdministrateurController < ApplicationController
before_action :authenticate_administrateur!
+ before_action :alert_for_missing_siret_service
+ before_action :alert_for_missing_service
helper_method :administrateur_as_manager?
def nav_bar_profile
@@ -38,5 +40,42 @@ def administrateur_as_manager?
current_administrateur.administrateurs_procedures
.exists?(procedure_id: id, manager: true)
end
+
+ def alert_for_missing_siret_service
+ procedures = missing_siret_services
+ if procedures.any?
+ errors = []
+ errors << I18n.t('shared.procedures.no_siret')
+ procedures.each do |p|
+ errors << I18n.t('shared.procedures.add_siret_to_service_without_siret_html', link: edit_admin_service_path(p.service, procedure_id: p.id), nom: p.service.nom)
+ end
+ flash.now.alert = errors
+ end
+ end
+
+ def missing_siret_services
+ current_administrateur
+ .procedures.publiees
+ .joins(:service)
+ .where(service: { siret: nil })
+ end
+
+ def alert_for_missing_service
+ procedures = missing_service
+ if procedures.any?
+ errors = []
+ errors << I18n.t('shared.procedures.no_service')
+ procedures.each do |p|
+ errors << I18n.t('shared.procedures.add_service_html', link: admin_services_path(procedure_id: p.id), id: p.id)
+ end
+ flash.now.alert = errors
+ end
+ end
+
+ def missing_service
+ current_administrateur
+ .procedures.publiees
+ .where(service_id: nil)
+ end
end
end
diff --git a/app/controllers/administrateurs/services_controller.rb b/app/controllers/administrateurs/services_controller.rb
index 19567336e1a..c1b8478fb3a 100644
--- a/app/controllers/administrateurs/services_controller.rb
+++ b/app/controllers/administrateurs/services_controller.rb
@@ -1,5 +1,7 @@
module Administrateurs
class ServicesController < AdministrateurController
+ skip_before_action :alert_for_missing_siret_service, only: :edit
+ skip_before_action :alert_for_missing_service, only: :edit
def index
@services = services.ordered
@procedure = procedure
diff --git a/app/lib/api_entreprise/api.rb b/app/lib/api_entreprise/api.rb
index feced9855e5..91c30dea574 100644
--- a/app/lib/api_entreprise/api.rb
+++ b/app/lib/api_entreprise/api.rb
@@ -91,14 +91,16 @@ def current_status
private
- def recipient
- @procedure&.service && @procedure.service.siret.presence || ENV.fetch('API_ENTREPRISE_DEFAULT_SIRET')
+ def recipient_for(siret_or_siren)
+ service_siret = @procedure&.service && @procedure.service.siret.presence
+ return service_siret if service_siret && !service_siret.starts_with?(siret_or_siren)
+ ENV.fetch('API_ENTREPRISE_DEFAULT_SIRET')
end
def call_with_siret(resource_name, siret_or_siren, user_id: nil)
url = make_url(resource_name, siret_or_siren)
- params = build_params(user_id)
+ params = build_params(user_id, siret_or_siren)
call(url, params)
end
@@ -144,8 +146,8 @@ def make_url(resource_name, siret_or_siren = nil)
[API_ENTREPRISE_URL, format(resource_name, id: siret_or_siren)].compact.join("/")
end
- def build_params(user_id)
- params = base_params
+ def build_params(user_id, siret_or_siren)
+ params = base_params(siret_or_siren)
params[:object] = if api_object.present?
api_object
@@ -158,10 +160,10 @@ def build_params(user_id)
params
end
- def base_params
+ def base_params(siret_or_siren)
{
context: APPLICATION_NAME,
- recipient: recipient,
+ recipient: recipient_for(siret_or_siren),
non_diffusables: true
}
end
diff --git a/app/lib/redcarpet/bare_renderer.rb b/app/lib/redcarpet/bare_renderer.rb
index 5e4e9850a24..d8944374caf 100644
--- a/app/lib/redcarpet/bare_renderer.rb
+++ b/app/lib/redcarpet/bare_renderer.rb
@@ -10,7 +10,14 @@ def list(content, list_type)
end
def list_item(content, list_type)
- content_tag(:li, content.strip.gsub(/<\/?p>/, ''), {}, false)
+ item_number = content.match(/\[value:(\d+)\]/)
+ text = content.strip
+ .gsub(/<\/?p>/, '')
+ .gsub(/\[value:\d+\]/, '')
+ .gsub(/\n/, '
')
+ attributes = item_number.present? ? { value: item_number[1] } : {}
+
+ content_tag(:li, text, attributes, false)
end
def paragraph(text)
diff --git a/app/models/champ.rb b/app/models/champ.rb
index 0ae9e6a9d5d..faa26454ddb 100644
--- a/app/models/champ.rb
+++ b/app/models/champ.rb
@@ -57,6 +57,7 @@ class Champ < ApplicationRecord
:dossier_link?,
:departement?,
:region?,
+ :textarea?,
:titre_identite?,
:header_section?,
:checkbox?,
@@ -252,7 +253,7 @@ def clone(fork = false)
value_attributes = fork || !private? ? [:value, :value_json, :data, :external_id] : []
relationships = fork || !private? ? [:etablissement, :geo_areas] : []
- deep_clone(only: champ_attributes + value_attributes, include: relationships) do |original, kopy|
+ deep_clone(only: champ_attributes + value_attributes, include: relationships, validate: !fork) do |original, kopy|
PiecesJustificativesService.clone_attachments(original, kopy)
end
end
diff --git a/app/services/api_geo_service.rb b/app/services/api_geo_service.rb
index e14979e3dc7..d35146e1e9a 100644
--- a/app/services/api_geo_service.rb
+++ b/app/services/api_geo_service.rb
@@ -79,7 +79,7 @@ def commune_code(departement_code, name)
private
def communes_by_postal_code_map
- Rails.cache.fetch('api_geo_communes_v2', expires_in: 1.week) do
+ Rails.cache.fetch('api_geo_communes', expires_in: 1.day, version: 3) do
departements
.filter { _1[:code] != '99' }
.flat_map { communes(_1[:code]) }
@@ -88,7 +88,7 @@ def communes_by_postal_code_map
end
def get_from_api_geo(scope)
- Rails.cache.fetch("api_geo_#{scope}_v2", expires_in: 1.week) do
+ Rails.cache.fetch("api_geo_#{scope}", expires_in: 1.day, version: 3) do
JSON.parse(Rails.root.join('lib', 'data', 'api_geo', "#{scope}.json").read, symbolize_names: true)
end
end
diff --git a/app/views/fields/types_de_champ_collection_field/_type_champ_line.html.haml b/app/views/fields/types_de_champ_collection_field/_type_champ_line.html.haml
index 2c0ba90d5a6..6e79abb2120 100644
--- a/app/views/fields/types_de_champ_collection_field/_type_champ_line.html.haml
+++ b/app/views/fields/types_de_champ_collection_field/_type_champ_line.html.haml
@@ -2,7 +2,7 @@
%td.cell-data
= type_de_champ.libelle
- if type_de_champ.mandatory?
- %span.mandatory *
+ %span.manager-mandatory *
%td.cell-data
= I18n.t("activerecord.attributes.type_de_champ.type_champs.#{type_de_champ.type_champ}")
diff --git a/app/views/shared/champs/rna/_association.html.haml b/app/views/shared/champs/rna/_association.html.haml
index 572a214027e..f38ed4be7a8 100644
--- a/app/views/shared/champs/rna/_association.html.haml
+++ b/app/views/shared/champs/rna/_association.html.haml
@@ -1,11 +1,11 @@
- case error
- when :invalid
- %p.pt-1
+ %p.fr-error-text
Le numéro RNA doit commencer par un W majuscule suivi de 9 chiffres
- when :not_found
- %p.pt-1= t('.not_found')
+ %p.fr-error-text= t('.not_found')
- when :network_error
- %p.pt-1= t('.network_error')
+ %p.fr-error-text= t('.network_error')
- else
- if champ.value.present?
- %p.pt-1= t('.data_fetched', title: champ.title)
+ %p.fr-info-text= t('.data_fetched', title: champ.title)
diff --git a/app/views/shared/champs/siret/_etablissement.html.haml b/app/views/shared/champs/siret/_etablissement.html.haml
index dbb781f4426..82fe1705d93 100644
--- a/app/views/shared/champs/siret/_etablissement.html.haml
+++ b/app/views/shared/champs/siret/_etablissement.html.haml
@@ -1,19 +1,20 @@
- case siret
- when :invalid_length
- = t('errors.messages.invalid_siret_length')
+ %p.fr-error-text= t('errors.messages.invalid_siret_length')
- when :invalid_checksum
- = t('errors.messages.invalid_siret_checksum')
+ %p.fr-error-text= t('errors.messages.invalid_siret_checksum')
- when :not_found
- Nous n’avons pas trouvé d’établissement correspondant à ce numéro TAHITI.
- = link_to('Plus d’informations', t("links.common.faq.erreur_siret_url"), **external_link_attributes)
+ %p.fr-error-text
+ Nous n’avons pas trouvé d’établissement correspondant à ce numéro TAHITI.
+ = link_to('Plus d’informations', t("links.common.faq.erreur_siret_url"), **external_link_attributes)
- when :network_error
- = t('errors.messages.siret_network_error')
+ %p.fr-error-text= t('errors.messages.siret_network_error')
- when :api_entreprise_down
- = t('errors.messages.api_entreprise_down')
+ %p.fr-error-text= t('errors.messages.api_entreprise_down')
- when :empty
// NOOP
@@ -22,4 +23,4 @@
- if siret == etablissement&.siret && raison_sociale_or_name(etablissement).present?
= render EditableChamp::EtablissementTitreComponent.new(etablissement: etablissement)
- else
- Ce numéro TAHITI existe, nous en récupérons les informations.
+ %p.fr-info-text Ce numéro TAHITI existe, nous en récupérons les informations.
diff --git a/app/views/users/dossiers/papertrail.pdf.prawn b/app/views/users/dossiers/papertrail.pdf.prawn
index 5b2b4976ec1..847572e480a 100644
--- a/app/views/users/dossiers/papertrail.pdf.prawn
+++ b/app/views/users/dossiers/papertrail.pdf.prawn
@@ -49,6 +49,7 @@ prawn_document(margin: [top_margin, right_margin, bottom_margin, left_margin], p
pdf.fill_color grey
pdf.text "#{Individual.human_attribute_name(:prenom)} : #{@dossier.individual.prenom}", size: 10, character_spacing: -0.2, align: :justify
pdf.text "#{Individual.human_attribute_name(:nom)} : #{@dossier.individual.nom.upcase}", size: 10, character_spacing: -0.2, align: :justify
+ pdf.text "#{User.human_attribute_name(:email)} : #{@dossier.user.email}", size: 10, character_spacing: -0.2, align: :justify
end
end
diff --git a/app/views/users/dossiers/update.turbo_stream.haml b/app/views/users/dossiers/update.turbo_stream.haml
index a8daa34cb02..e998f507c1d 100644
--- a/app/views/users/dossiers/update.turbo_stream.haml
+++ b/app/views/users/dossiers/update.turbo_stream.haml
@@ -9,7 +9,7 @@
= render EditableChamp::EditableChampComponent.new champ:, form:
- else
= turbo_stream.update champ.labelledby_id do
- = render EditableChamp::ChampLabelContentComponent.new champ:
+ = render EditableChamp::ChampLabelContentComponent.new champ:, form:
= turbo_stream.remove_all(".editable-champ .spinner-removable");
= turbo_stream.hide_all(".editable-champ .spinner");
diff --git a/config/locales/en.yml b/config/locales/en.yml
index f201e17f1c8..28a83c0d2c1 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -880,6 +880,11 @@ en:
merger_token_expired: "The delay to merge your %{provider} and %{application_name} accounts is expired. Please retry."
shared:
procedures:
+ no_siret: "Some procedures have service without siret. Please update."
+ add_siret_to_service_without_siret_html: Add siret for service %{nom}
+ no_service: "Some procedures have no service."
+ add_service_html: Add service to procedure %{id}
+
stats:
usual_processing_time: "Usual processing time"
processing_time_description: "%{percentile}% of submitted files in the last %{span} days were processed in less than %{days}."
diff --git a/config/locales/fr.yml b/config/locales/fr.yml
index 27d3b0e864d..69ea93ac68f 100644
--- a/config/locales/fr.yml
+++ b/config/locales/fr.yml
@@ -937,6 +937,11 @@ fr:
merger_token_expired: "Le délai pour fusionner les comptes %{provider} et %{application_name} est expiré. Veuillez recommencer la procédure pour vous fusionner les comptes."
shared:
procedures:
+ no_siret: "Vous n’avez pas renseigné le siret du service pour certaines de vos démarches. Merci de les modifier."
+ add_siret_to_service_without_siret_html: Ajouter le siret du service %{nom}
+ no_service: "Certaines de vos démarches n’ont pas de service associé."
+ add_service_html: Ajouter un service à la démarche %{id}
+
stats:
usual_processing_time: "Temps de traitement usuel"
processing_time_description: "%{percentile}% des demandes des %{span} derniers jours ont été traitées en moins de %{days}."
diff --git a/config/locales/models/champs/datetime_champ/en.yml b/config/locales/models/champs/datetime_champ/en.yml
new file mode 100644
index 00000000000..eb0b92533e3
--- /dev/null
+++ b/config/locales/models/champs/datetime_champ/en.yml
@@ -0,0 +1,7 @@
+en:
+ activerecord:
+ attributes:
+ champs/datetime_champ:
+ hints:
+ value: "Expected format : dd/mm/yyyy hh:mm"
+
diff --git a/config/locales/models/champs/datetime_champ/fr.yml b/config/locales/models/champs/datetime_champ/fr.yml
new file mode 100644
index 00000000000..1035c03d8f7
--- /dev/null
+++ b/config/locales/models/champs/datetime_champ/fr.yml
@@ -0,0 +1,7 @@
+fr:
+ activerecord:
+ attributes:
+ champs/datetime_champ:
+ hints:
+ value: "Format attendu : jj/mm/aaaa hh:mm"
+
diff --git a/lib/data/api_geo/communes-13.json b/lib/data/api_geo/communes-13.json
index d64fa086b5f..f46c7ddf721 100644
--- a/lib/data/api_geo/communes-13.json
+++ b/lib/data/api_geo/communes-13.json
@@ -1 +1 @@
-[{"name":"Aix-en-Provence","code":"13001","epci_code":"200054807","departement_code":"13","postal_code":"13080"},{"name":"Aix-en-Provence","code":"13001","epci_code":"200054807","departement_code":"13","postal_code":"13090"},{"name":"Aix-en-Provence","code":"13001","epci_code":"200054807","departement_code":"13","postal_code":"13100"},{"name":"Aix-en-Provence","code":"13001","epci_code":"200054807","departement_code":"13","postal_code":"13290"},{"name":"Aix-en-Provence","code":"13001","epci_code":"200054807","departement_code":"13","postal_code":"13540"},{"name":"Allauch","code":"13002","epci_code":"200054807","departement_code":"13","postal_code":"13190"},{"name":"Alleins","code":"13003","epci_code":"200054807","departement_code":"13","postal_code":"13980"},{"name":"Arles","code":"13004","epci_code":"241300417","departement_code":"13","postal_code":"13104"},{"name":"Arles","code":"13004","epci_code":"241300417","departement_code":"13","postal_code":"13123"},{"name":"Arles","code":"13004","epci_code":"241300417","departement_code":"13","postal_code":"13129"},{"name":"Arles","code":"13004","epci_code":"241300417","departement_code":"13","postal_code":"13200"},{"name":"Arles","code":"13004","epci_code":"241300417","departement_code":"13","postal_code":"13280"},{"name":"Aubagne","code":"13005","epci_code":"200054807","departement_code":"13","postal_code":"13400"},{"name":"Aureille","code":"13006","epci_code":"241300375","departement_code":"13","postal_code":"13930"},{"name":"Auriol","code":"13007","epci_code":"200054807","departement_code":"13","postal_code":"13390"},{"name":"Aurons","code":"13008","epci_code":"200054807","departement_code":"13","postal_code":"13121"},{"name":"La Barben","code":"13009","epci_code":"200054807","departement_code":"13","postal_code":"13330"},{"name":"Barbentane","code":"13010","epci_code":"200035087","departement_code":"13","postal_code":"13570"},{"name":"Les Baux-de-Provence","code":"13011","epci_code":"241300375","departement_code":"13","postal_code":"13520"},{"name":"Beaurecueil","code":"13012","epci_code":"200054807","departement_code":"13","postal_code":"13100"},{"name":"Belcodène","code":"13013","epci_code":"200054807","departement_code":"13","postal_code":"13720"},{"name":"Berre-l’Étang","code":"13014","epci_code":"200054807","departement_code":"13","postal_code":"13130"},{"name":"Bouc-Bel-Air","code":"13015","epci_code":"200054807","departement_code":"13","postal_code":"13320"},{"name":"La Bouilladisse","code":"13016","epci_code":"200054807","departement_code":"13","postal_code":"13720"},{"name":"Boulbon","code":"13017","epci_code":"241300417","departement_code":"13","postal_code":"13150"},{"name":"Cabannes","code":"13018","epci_code":"200035087","departement_code":"13","postal_code":"13440"},{"name":"Cabriès","code":"13019","epci_code":"200054807","departement_code":"13","postal_code":"13480"},{"name":"Cadolive","code":"13020","epci_code":"200054807","departement_code":"13","postal_code":"13950"},{"name":"Carry-le-Rouet","code":"13021","epci_code":"200054807","departement_code":"13","postal_code":"13620"},{"name":"Cassis","code":"13022","epci_code":"200054807","departement_code":"13","postal_code":"13260"},{"name":"Ceyreste","code":"13023","epci_code":"200054807","departement_code":"13","postal_code":"13600"},{"name":"Charleval","code":"13024","epci_code":"200054807","departement_code":"13","postal_code":"13350"},{"name":"Châteauneuf-le-Rouge","code":"13025","epci_code":"200054807","departement_code":"13","postal_code":"13790"},{"name":"Châteauneuf-les-Martigues","code":"13026","epci_code":"200054807","departement_code":"13","postal_code":"13220"},{"name":"Châteaurenard","code":"13027","epci_code":"200035087","departement_code":"13","postal_code":"13160"},{"name":"La Ciotat","code":"13028","epci_code":"200054807","departement_code":"13","postal_code":"13600"},{"name":"Cornillon-Confoux","code":"13029","epci_code":"200054807","departement_code":"13","postal_code":"13250"},{"name":"Cuges-les-Pins","code":"13030","epci_code":"200054807","departement_code":"13","postal_code":"13780"},{"name":"La Destrousse","code":"13031","epci_code":"200054807","departement_code":"13","postal_code":"13112"},{"name":"Éguilles","code":"13032","epci_code":"200054807","departement_code":"13","postal_code":"13510"},{"name":"Ensuès-la-Redonne","code":"13033","epci_code":"200054807","departement_code":"13","postal_code":"13820"},{"name":"Eygalières","code":"13034","epci_code":"241300375","departement_code":"13","postal_code":"13810"},{"name":"Eyguières","code":"13035","epci_code":"200054807","departement_code":"13","postal_code":"13430"},{"name":"Eyragues","code":"13036","epci_code":"200035087","departement_code":"13","postal_code":"13630"},{"name":"La Fare-les-Oliviers","code":"13037","epci_code":"200054807","departement_code":"13","postal_code":"13580"},{"name":"Fontvieille","code":"13038","epci_code":"241300375","departement_code":"13","postal_code":"13990"},{"name":"Fos-sur-Mer","code":"13039","epci_code":"200054807","departement_code":"13","postal_code":"13270"},{"name":"Fuveau","code":"13040","epci_code":"200054807","departement_code":"13","postal_code":"13710"},{"name":"Gardanne","code":"13041","epci_code":"200054807","departement_code":"13","postal_code":"13120"},{"name":"Gémenos","code":"13042","epci_code":"200054807","departement_code":"13","postal_code":"13420"},{"name":"Gignac-la-Nerthe","code":"13043","epci_code":"200054807","departement_code":"13","postal_code":"13180"},{"name":"Grans","code":"13044","epci_code":"200054807","departement_code":"13","postal_code":"13450"},{"name":"Graveson","code":"13045","epci_code":"200035087","departement_code":"13","postal_code":"13690"},{"name":"Gréasque","code":"13046","epci_code":"200054807","departement_code":"13","postal_code":"13850"},{"name":"Istres","code":"13047","epci_code":"200054807","departement_code":"13","postal_code":"13118"},{"name":"Istres","code":"13047","epci_code":"200054807","departement_code":"13","postal_code":"13800"},{"name":"Jouques","code":"13048","epci_code":"200054807","departement_code":"13","postal_code":"13490"},{"name":"Lamanon","code":"13049","epci_code":"200054807","departement_code":"13","postal_code":"13113"},{"name":"Lambesc","code":"13050","epci_code":"200054807","departement_code":"13","postal_code":"13410"},{"name":"Lançon-Provence","code":"13051","epci_code":"200054807","departement_code":"13","postal_code":"13680"},{"name":"Maillane","code":"13052","epci_code":"200035087","departement_code":"13","postal_code":"13910"},{"name":"Mallemort","code":"13053","epci_code":"200054807","departement_code":"13","postal_code":"13370"},{"name":"Marignane","code":"13054","epci_code":"200054807","departement_code":"13","postal_code":"13700"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13001"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13002"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13003"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13004"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13005"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13006"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13007"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13008"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13009"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13010"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13011"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13012"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13013"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13014"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13015"},{"name":"Marseille","code":"13055","epci_code":"200054807","departement_code":"13","postal_code":"13016"},{"name":"Martigues","code":"13056","epci_code":"200054807","departement_code":"13","postal_code":"13117"},{"name":"Martigues","code":"13056","epci_code":"200054807","departement_code":"13","postal_code":"13500"},{"name":"Mas-Blanc-des-Alpilles","code":"13057","epci_code":"241300375","departement_code":"13","postal_code":"13103"},{"name":"Maussane-les-Alpilles","code":"13058","epci_code":"241300375","departement_code":"13","postal_code":"13520"},{"name":"Meyrargues","code":"13059","epci_code":"200054807","departement_code":"13","postal_code":"13650"},{"name":"Meyreuil","code":"13060","epci_code":"200054807","departement_code":"13","postal_code":"13590"},{"name":"Saint-Pierre-de-Mézoargues","code":"13061","epci_code":"241300417","departement_code":"13","postal_code":"13150"},{"name":"Mimet","code":"13062","epci_code":"200054807","departement_code":"13","postal_code":"13105"},{"name":"Miramas","code":"13063","epci_code":"200054807","departement_code":"13","postal_code":"13140"},{"name":"Mollégès","code":"13064","epci_code":"200035087","departement_code":"13","postal_code":"13940"},{"name":"Mouriès","code":"13065","epci_code":"241300375","departement_code":"13","postal_code":"13890"},{"name":"Noves","code":"13066","epci_code":"200035087","departement_code":"13","postal_code":"13550"},{"name":"Orgon","code":"13067","epci_code":"200035087","departement_code":"13","postal_code":"13660"},{"name":"Paradou","code":"13068","epci_code":"241300375","departement_code":"13","postal_code":"13520"},{"name":"Pélissanne","code":"13069","epci_code":"200054807","departement_code":"13","postal_code":"13330"},{"name":"La Penne-sur-Huveaune","code":"13070","epci_code":"200054807","departement_code":"13","postal_code":"13821"},{"name":"Les Pennes-Mirabeau","code":"13071","epci_code":"200054807","departement_code":"13","postal_code":"13170"},{"name":"Peynier","code":"13072","epci_code":"200054807","departement_code":"13","postal_code":"13790"},{"name":"Peypin","code":"13073","epci_code":"200054807","departement_code":"13","postal_code":"13124"},{"name":"Peyrolles-en-Provence","code":"13074","epci_code":"200054807","departement_code":"13","postal_code":"13860"},{"name":"Plan-de-Cuques","code":"13075","epci_code":"200054807","departement_code":"13","postal_code":"13380"},{"name":"Plan-d’Orgon","code":"13076","epci_code":"200035087","departement_code":"13","postal_code":"13750"},{"name":"Port-de-Bouc","code":"13077","epci_code":"200054807","departement_code":"13","postal_code":"13110"},{"name":"Port-Saint-Louis-du-Rhône","code":"13078","epci_code":"200054807","departement_code":"13","postal_code":"13230"},{"name":"Puyloubier","code":"13079","epci_code":"200054807","departement_code":"13","postal_code":"13114"},{"name":"Le Puy-Sainte-Réparade","code":"13080","epci_code":"200054807","departement_code":"13","postal_code":"13610"},{"name":"Rognac","code":"13081","epci_code":"200054807","departement_code":"13","postal_code":"13340"},{"name":"Rognes","code":"13082","epci_code":"200054807","departement_code":"13","postal_code":"13840"},{"name":"Rognonas","code":"13083","epci_code":"200035087","departement_code":"13","postal_code":"13870"},{"name":"La Roque-d’Anthéron","code":"13084","epci_code":"200054807","departement_code":"13","postal_code":"13640"},{"name":"Roquefort-la-Bédoule","code":"13085","epci_code":"200054807","departement_code":"13","postal_code":"13830"},{"name":"Roquevaire","code":"13086","epci_code":"200054807","departement_code":"13","postal_code":"13360"},{"name":"Rousset","code":"13087","epci_code":"200054807","departement_code":"13","postal_code":"13790"},{"name":"Le Rove","code":"13088","epci_code":"200054807","departement_code":"13","postal_code":"13740"},{"name":"Saint-Andiol","code":"13089","epci_code":"200035087","departement_code":"13","postal_code":"13670"},{"name":"Saint-Antonin-sur-Bayon","code":"13090","epci_code":"200054807","departement_code":"13","postal_code":"13100"},{"name":"Saint-Cannat","code":"13091","epci_code":"200054807","departement_code":"13","postal_code":"13760"},{"name":"Saint-Chamas","code":"13092","epci_code":"200054807","departement_code":"13","postal_code":"13250"},{"name":"Saint-Estève-Janson","code":"13093","epci_code":"200054807","departement_code":"13","postal_code":"13610"},{"name":"Saint-Étienne-du-Grès","code":"13094","epci_code":"241300375","departement_code":"13","postal_code":"13103"},{"name":"Saint-Marc-Jaumegarde","code":"13095","epci_code":"200054807","departement_code":"13","postal_code":"13100"},{"name":"Saintes-Maries-de-la-Mer","code":"13096","epci_code":"241300417","departement_code":"13","postal_code":"13460"},{"name":"Saint-Martin-de-Crau","code":"13097","epci_code":"241300417","departement_code":"13","postal_code":"13310"},{"name":"Saint-Mitre-les-Remparts","code":"13098","epci_code":"200054807","departement_code":"13","postal_code":"13920"},{"name":"Saint-Paul-lès-Durance","code":"13099","epci_code":"200054807","departement_code":"13","postal_code":"13115"},{"name":"Saint-Rémy-de-Provence","code":"13100","epci_code":"241300375","departement_code":"13","postal_code":"13210"},{"name":"Saint-Savournin","code":"13101","epci_code":"200054807","departement_code":"13","postal_code":"13119"},{"name":"Saint-Victoret","code":"13102","epci_code":"200054807","departement_code":"13","postal_code":"13730"},{"name":"Salon-de-Provence","code":"13103","epci_code":"200054807","departement_code":"13","postal_code":"13300"},{"name":"Sausset-les-Pins","code":"13104","epci_code":"200054807","departement_code":"13","postal_code":"13960"},{"name":"Sénas","code":"13105","epci_code":"200054807","departement_code":"13","postal_code":"13560"},{"name":"Septèmes-les-Vallons","code":"13106","epci_code":"200054807","departement_code":"13","postal_code":"13240"},{"name":"Simiane-Collongue","code":"13107","epci_code":"200054807","departement_code":"13","postal_code":"13109"},{"name":"Tarascon","code":"13108","epci_code":"241300417","departement_code":"13","postal_code":"13150"},{"name":"Le Tholonet","code":"13109","epci_code":"200054807","departement_code":"13","postal_code":"13100"},{"name":"Trets","code":"13110","epci_code":"200054807","departement_code":"13","postal_code":"13530"},{"name":"Vauvenargues","code":"13111","epci_code":"200054807","departement_code":"13","postal_code":"13126"},{"name":"Velaux","code":"13112","epci_code":"200054807","departement_code":"13","postal_code":"13880"},{"name":"Venelles","code":"13113","epci_code":"200054807","departement_code":"13","postal_code":"13770"},{"name":"Ventabren","code":"13114","epci_code":"200054807","departement_code":"13","postal_code":"13122"},{"name":"Vernègues","code":"13115","epci_code":"200054807","departement_code":"13","postal_code":"13116"},{"name":"Verquières","code":"13116","epci_code":"200035087","departement_code":"13","postal_code":"13670"},{"name":"Vitrolles","code":"13117","epci_code":"200054807","departement_code":"13","postal_code":"13127"},{"name":"Coudoux","code":"13118","epci_code":"200054807","departement_code":"13","postal_code":"13111"},{"name":"Carnoux-en-Provence","code":"13119","epci_code":"200054807","departement_code":"13","postal_code":"13470"},{"name":"Marseille 1er Arrondissement","code":"13201","departement_code":"13","postal_code":"13001"},{"name":"Marseille 2e Arrondissement","code":"13202","departement_code":"13","postal_code":"13002"},{"name":"Marseille 3e Arrondissement","code":"13203","departement_code":"13","postal_code":"13003"},{"name":"Marseille 4e Arrondissement","code":"13204","departement_code":"13","postal_code":"13004"},{"name":"Marseille 5e Arrondissement","code":"13205","departement_code":"13","postal_code":"13005"},{"name":"Marseille 6e Arrondissement","code":"13206","departement_code":"13","postal_code":"13006"},{"name":"Marseille 7e Arrondissement","code":"13207","departement_code":"13","postal_code":"13007"},{"name":"Marseille 8e Arrondissement","code":"13208","departement_code":"13","postal_code":"13008"},{"name":"Marseille 9e Arrondissement","code":"13209","departement_code":"13","postal_code":"13009"},{"name":"Marseille 10e Arrondissement","code":"13210","departement_code":"13","postal_code":"13010"},{"name":"Marseille 11e Arrondissement","code":"13211","departement_code":"13","postal_code":"13011"},{"name":"Marseille 12e Arrondissement","code":"13212","departement_code":"13","postal_code":"13012"},{"name":"Marseille 13e Arrondissement","code":"13213","departement_code":"13","postal_code":"13013"},{"name":"Marseille 14e Arrondissement","code":"13214","departement_code":"13","postal_code":"13014"},{"name":"Marseille 15e Arrondissement","code":"13215","departement_code":"13","postal_code":"13015"},{"name":"Marseille 16e Arrondissement","code":"13216","departement_code":"13","postal_code":"13016"}]
\ No newline at end of file
+[{"name":"Aix-en-Provence","code":"13001","epci_code":"200054807","departement_code":"13","postal_code":"13080"},{"name":"Aix-en-Provence","code":"13001","epci_code":"200054807","departement_code":"13","postal_code":"13090"},{"name":"Aix-en-Provence","code":"13001","epci_code":"200054807","departement_code":"13","postal_code":"13100"},{"name":"Aix-en-Provence","code":"13001","epci_code":"200054807","departement_code":"13","postal_code":"13290"},{"name":"Aix-en-Provence","code":"13001","epci_code":"200054807","departement_code":"13","postal_code":"13540"},{"name":"Allauch","code":"13002","epci_code":"200054807","departement_code":"13","postal_code":"13190"},{"name":"Alleins","code":"13003","epci_code":"200054807","departement_code":"13","postal_code":"13980"},{"name":"Arles","code":"13004","epci_code":"241300417","departement_code":"13","postal_code":"13104"},{"name":"Arles","code":"13004","epci_code":"241300417","departement_code":"13","postal_code":"13123"},{"name":"Arles","code":"13004","epci_code":"241300417","departement_code":"13","postal_code":"13129"},{"name":"Arles","code":"13004","epci_code":"241300417","departement_code":"13","postal_code":"13200"},{"name":"Arles","code":"13004","epci_code":"241300417","departement_code":"13","postal_code":"13280"},{"name":"Aubagne","code":"13005","epci_code":"200054807","departement_code":"13","postal_code":"13400"},{"name":"Aureille","code":"13006","epci_code":"241300375","departement_code":"13","postal_code":"13930"},{"name":"Auriol","code":"13007","epci_code":"200054807","departement_code":"13","postal_code":"13390"},{"name":"Aurons","code":"13008","epci_code":"200054807","departement_code":"13","postal_code":"13121"},{"name":"La Barben","code":"13009","epci_code":"200054807","departement_code":"13","postal_code":"13330"},{"name":"Barbentane","code":"13010","epci_code":"200035087","departement_code":"13","postal_code":"13570"},{"name":"Les Baux-de-Provence","code":"13011","epci_code":"241300375","departement_code":"13","postal_code":"13520"},{"name":"Beaurecueil","code":"13012","epci_code":"200054807","departement_code":"13","postal_code":"13100"},{"name":"Belcodène","code":"13013","epci_code":"200054807","departement_code":"13","postal_code":"13720"},{"name":"Berre-l’Étang","code":"13014","epci_code":"200054807","departement_code":"13","postal_code":"13130"},{"name":"Bouc-Bel-Air","code":"13015","epci_code":"200054807","departement_code":"13","postal_code":"13320"},{"name":"La Bouilladisse","code":"13016","epci_code":"200054807","departement_code":"13","postal_code":"13720"},{"name":"Boulbon","code":"13017","epci_code":"241300417","departement_code":"13","postal_code":"13150"},{"name":"Cabannes","code":"13018","epci_code":"200035087","departement_code":"13","postal_code":"13440"},{"name":"Cabriès","code":"13019","epci_code":"200054807","departement_code":"13","postal_code":"13480"},{"name":"Cadolive","code":"13020","epci_code":"200054807","departement_code":"13","postal_code":"13950"},{"name":"Carry-le-Rouet","code":"13021","epci_code":"200054807","departement_code":"13","postal_code":"13620"},{"name":"Cassis","code":"13022","epci_code":"200054807","departement_code":"13","postal_code":"13260"},{"name":"Ceyreste","code":"13023","epci_code":"200054807","departement_code":"13","postal_code":"13600"},{"name":"Charleval","code":"13024","epci_code":"200054807","departement_code":"13","postal_code":"13350"},{"name":"Châteauneuf-le-Rouge","code":"13025","epci_code":"200054807","departement_code":"13","postal_code":"13790"},{"name":"Châteauneuf-les-Martigues","code":"13026","epci_code":"200054807","departement_code":"13","postal_code":"13220"},{"name":"Châteaurenard","code":"13027","epci_code":"200035087","departement_code":"13","postal_code":"13160"},{"name":"La Ciotat","code":"13028","epci_code":"200054807","departement_code":"13","postal_code":"13600"},{"name":"Cornillon-Confoux","code":"13029","epci_code":"200054807","departement_code":"13","postal_code":"13250"},{"name":"Cuges-les-Pins","code":"13030","epci_code":"200054807","departement_code":"13","postal_code":"13780"},{"name":"La Destrousse","code":"13031","epci_code":"200054807","departement_code":"13","postal_code":"13112"},{"name":"Éguilles","code":"13032","epci_code":"200054807","departement_code":"13","postal_code":"13510"},{"name":"Ensuès-la-Redonne","code":"13033","epci_code":"200054807","departement_code":"13","postal_code":"13820"},{"name":"Eygalières","code":"13034","epci_code":"241300375","departement_code":"13","postal_code":"13810"},{"name":"Eyguières","code":"13035","epci_code":"200054807","departement_code":"13","postal_code":"13430"},{"name":"Eyragues","code":"13036","epci_code":"200035087","departement_code":"13","postal_code":"13630"},{"name":"La Fare-les-Oliviers","code":"13037","epci_code":"200054807","departement_code":"13","postal_code":"13580"},{"name":"Fontvieille","code":"13038","epci_code":"241300375","departement_code":"13","postal_code":"13990"},{"name":"Fos-sur-Mer","code":"13039","epci_code":"200054807","departement_code":"13","postal_code":"13270"},{"name":"Fuveau","code":"13040","epci_code":"200054807","departement_code":"13","postal_code":"13710"},{"name":"Gardanne","code":"13041","epci_code":"200054807","departement_code":"13","postal_code":"13120"},{"name":"Gémenos","code":"13042","epci_code":"200054807","departement_code":"13","postal_code":"13420"},{"name":"Gignac-la-Nerthe","code":"13043","epci_code":"200054807","departement_code":"13","postal_code":"13180"},{"name":"Grans","code":"13044","epci_code":"200054807","departement_code":"13","postal_code":"13450"},{"name":"Graveson","code":"13045","epci_code":"200035087","departement_code":"13","postal_code":"13690"},{"name":"Gréasque","code":"13046","epci_code":"200054807","departement_code":"13","postal_code":"13850"},{"name":"Istres","code":"13047","epci_code":"200054807","departement_code":"13","postal_code":"13118"},{"name":"Istres","code":"13047","epci_code":"200054807","departement_code":"13","postal_code":"13800"},{"name":"Jouques","code":"13048","epci_code":"200054807","departement_code":"13","postal_code":"13490"},{"name":"Lamanon","code":"13049","epci_code":"200054807","departement_code":"13","postal_code":"13113"},{"name":"Lambesc","code":"13050","epci_code":"200054807","departement_code":"13","postal_code":"13410"},{"name":"Lançon-Provence","code":"13051","epci_code":"200054807","departement_code":"13","postal_code":"13680"},{"name":"Maillane","code":"13052","epci_code":"200035087","departement_code":"13","postal_code":"13910"},{"name":"Mallemort","code":"13053","epci_code":"200054807","departement_code":"13","postal_code":"13370"},{"name":"Marignane","code":"13054","epci_code":"200054807","departement_code":"13","postal_code":"13700"},{"name":"Martigues","code":"13056","epci_code":"200054807","departement_code":"13","postal_code":"13117"},{"name":"Martigues","code":"13056","epci_code":"200054807","departement_code":"13","postal_code":"13500"},{"name":"Mas-Blanc-des-Alpilles","code":"13057","epci_code":"241300375","departement_code":"13","postal_code":"13103"},{"name":"Maussane-les-Alpilles","code":"13058","epci_code":"241300375","departement_code":"13","postal_code":"13520"},{"name":"Meyrargues","code":"13059","epci_code":"200054807","departement_code":"13","postal_code":"13650"},{"name":"Meyreuil","code":"13060","epci_code":"200054807","departement_code":"13","postal_code":"13590"},{"name":"Saint-Pierre-de-Mézoargues","code":"13061","epci_code":"241300417","departement_code":"13","postal_code":"13150"},{"name":"Mimet","code":"13062","epci_code":"200054807","departement_code":"13","postal_code":"13105"},{"name":"Miramas","code":"13063","epci_code":"200054807","departement_code":"13","postal_code":"13140"},{"name":"Mollégès","code":"13064","epci_code":"200035087","departement_code":"13","postal_code":"13940"},{"name":"Mouriès","code":"13065","epci_code":"241300375","departement_code":"13","postal_code":"13890"},{"name":"Noves","code":"13066","epci_code":"200035087","departement_code":"13","postal_code":"13550"},{"name":"Orgon","code":"13067","epci_code":"200035087","departement_code":"13","postal_code":"13660"},{"name":"Paradou","code":"13068","epci_code":"241300375","departement_code":"13","postal_code":"13520"},{"name":"Pélissanne","code":"13069","epci_code":"200054807","departement_code":"13","postal_code":"13330"},{"name":"La Penne-sur-Huveaune","code":"13070","epci_code":"200054807","departement_code":"13","postal_code":"13821"},{"name":"Les Pennes-Mirabeau","code":"13071","epci_code":"200054807","departement_code":"13","postal_code":"13170"},{"name":"Peynier","code":"13072","epci_code":"200054807","departement_code":"13","postal_code":"13790"},{"name":"Peypin","code":"13073","epci_code":"200054807","departement_code":"13","postal_code":"13124"},{"name":"Peyrolles-en-Provence","code":"13074","epci_code":"200054807","departement_code":"13","postal_code":"13860"},{"name":"Plan-de-Cuques","code":"13075","epci_code":"200054807","departement_code":"13","postal_code":"13380"},{"name":"Plan-d’Orgon","code":"13076","epci_code":"200035087","departement_code":"13","postal_code":"13750"},{"name":"Port-de-Bouc","code":"13077","epci_code":"200054807","departement_code":"13","postal_code":"13110"},{"name":"Port-Saint-Louis-du-Rhône","code":"13078","epci_code":"200054807","departement_code":"13","postal_code":"13230"},{"name":"Puyloubier","code":"13079","epci_code":"200054807","departement_code":"13","postal_code":"13114"},{"name":"Le Puy-Sainte-Réparade","code":"13080","epci_code":"200054807","departement_code":"13","postal_code":"13610"},{"name":"Rognac","code":"13081","epci_code":"200054807","departement_code":"13","postal_code":"13340"},{"name":"Rognes","code":"13082","epci_code":"200054807","departement_code":"13","postal_code":"13840"},{"name":"Rognonas","code":"13083","epci_code":"200035087","departement_code":"13","postal_code":"13870"},{"name":"La Roque-d’Anthéron","code":"13084","epci_code":"200054807","departement_code":"13","postal_code":"13640"},{"name":"Roquefort-la-Bédoule","code":"13085","epci_code":"200054807","departement_code":"13","postal_code":"13830"},{"name":"Roquevaire","code":"13086","epci_code":"200054807","departement_code":"13","postal_code":"13360"},{"name":"Rousset","code":"13087","epci_code":"200054807","departement_code":"13","postal_code":"13790"},{"name":"Le Rove","code":"13088","epci_code":"200054807","departement_code":"13","postal_code":"13740"},{"name":"Saint-Andiol","code":"13089","epci_code":"200035087","departement_code":"13","postal_code":"13670"},{"name":"Saint-Antonin-sur-Bayon","code":"13090","epci_code":"200054807","departement_code":"13","postal_code":"13100"},{"name":"Saint-Cannat","code":"13091","epci_code":"200054807","departement_code":"13","postal_code":"13760"},{"name":"Saint-Chamas","code":"13092","epci_code":"200054807","departement_code":"13","postal_code":"13250"},{"name":"Saint-Estève-Janson","code":"13093","epci_code":"200054807","departement_code":"13","postal_code":"13610"},{"name":"Saint-Étienne-du-Grès","code":"13094","epci_code":"241300375","departement_code":"13","postal_code":"13103"},{"name":"Saint-Marc-Jaumegarde","code":"13095","epci_code":"200054807","departement_code":"13","postal_code":"13100"},{"name":"Saintes-Maries-de-la-Mer","code":"13096","epci_code":"241300417","departement_code":"13","postal_code":"13460"},{"name":"Saint-Martin-de-Crau","code":"13097","epci_code":"241300417","departement_code":"13","postal_code":"13310"},{"name":"Saint-Mitre-les-Remparts","code":"13098","epci_code":"200054807","departement_code":"13","postal_code":"13920"},{"name":"Saint-Paul-lès-Durance","code":"13099","epci_code":"200054807","departement_code":"13","postal_code":"13115"},{"name":"Saint-Rémy-de-Provence","code":"13100","epci_code":"241300375","departement_code":"13","postal_code":"13210"},{"name":"Saint-Savournin","code":"13101","epci_code":"200054807","departement_code":"13","postal_code":"13119"},{"name":"Saint-Victoret","code":"13102","epci_code":"200054807","departement_code":"13","postal_code":"13730"},{"name":"Salon-de-Provence","code":"13103","epci_code":"200054807","departement_code":"13","postal_code":"13300"},{"name":"Sausset-les-Pins","code":"13104","epci_code":"200054807","departement_code":"13","postal_code":"13960"},{"name":"Sénas","code":"13105","epci_code":"200054807","departement_code":"13","postal_code":"13560"},{"name":"Septèmes-les-Vallons","code":"13106","epci_code":"200054807","departement_code":"13","postal_code":"13240"},{"name":"Simiane-Collongue","code":"13107","epci_code":"200054807","departement_code":"13","postal_code":"13109"},{"name":"Tarascon","code":"13108","epci_code":"241300417","departement_code":"13","postal_code":"13150"},{"name":"Le Tholonet","code":"13109","epci_code":"200054807","departement_code":"13","postal_code":"13100"},{"name":"Trets","code":"13110","epci_code":"200054807","departement_code":"13","postal_code":"13530"},{"name":"Vauvenargues","code":"13111","epci_code":"200054807","departement_code":"13","postal_code":"13126"},{"name":"Velaux","code":"13112","epci_code":"200054807","departement_code":"13","postal_code":"13880"},{"name":"Venelles","code":"13113","epci_code":"200054807","departement_code":"13","postal_code":"13770"},{"name":"Ventabren","code":"13114","epci_code":"200054807","departement_code":"13","postal_code":"13122"},{"name":"Vernègues","code":"13115","epci_code":"200054807","departement_code":"13","postal_code":"13116"},{"name":"Verquières","code":"13116","epci_code":"200035087","departement_code":"13","postal_code":"13670"},{"name":"Vitrolles","code":"13117","epci_code":"200054807","departement_code":"13","postal_code":"13127"},{"name":"Coudoux","code":"13118","epci_code":"200054807","departement_code":"13","postal_code":"13111"},{"name":"Carnoux-en-Provence","code":"13119","epci_code":"200054807","departement_code":"13","postal_code":"13470"},{"name":"Marseille 1er Arrondissement","code":"13201","departement_code":"13","postal_code":"13001"},{"name":"Marseille 2e Arrondissement","code":"13202","departement_code":"13","postal_code":"13002"},{"name":"Marseille 3e Arrondissement","code":"13203","departement_code":"13","postal_code":"13003"},{"name":"Marseille 4e Arrondissement","code":"13204","departement_code":"13","postal_code":"13004"},{"name":"Marseille 5e Arrondissement","code":"13205","departement_code":"13","postal_code":"13005"},{"name":"Marseille 6e Arrondissement","code":"13206","departement_code":"13","postal_code":"13006"},{"name":"Marseille 7e Arrondissement","code":"13207","departement_code":"13","postal_code":"13007"},{"name":"Marseille 8e Arrondissement","code":"13208","departement_code":"13","postal_code":"13008"},{"name":"Marseille 9e Arrondissement","code":"13209","departement_code":"13","postal_code":"13009"},{"name":"Marseille 10e Arrondissement","code":"13210","departement_code":"13","postal_code":"13010"},{"name":"Marseille 11e Arrondissement","code":"13211","departement_code":"13","postal_code":"13011"},{"name":"Marseille 12e Arrondissement","code":"13212","departement_code":"13","postal_code":"13012"},{"name":"Marseille 13e Arrondissement","code":"13213","departement_code":"13","postal_code":"13013"},{"name":"Marseille 14e Arrondissement","code":"13214","departement_code":"13","postal_code":"13014"},{"name":"Marseille 15e Arrondissement","code":"13215","departement_code":"13","postal_code":"13015"},{"name":"Marseille 16e Arrondissement","code":"13216","departement_code":"13","postal_code":"13016"}]
\ No newline at end of file
diff --git a/lib/data/api_geo/communes-69.json b/lib/data/api_geo/communes-69.json
index 500ae9d2dd7..5b89993abf0 100644
--- a/lib/data/api_geo/communes-69.json
+++ b/lib/data/api_geo/communes-69.json
@@ -1 +1 @@
-[{"name":"Affoux","code":"69001","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Aigueperse","code":"69002","epci_code":"200067817","departement_code":"69","postal_code":"69790"},{"name":"Albigny-sur-Saône","code":"69003","epci_code":"200046977","departement_code":"69","postal_code":"69250"},{"name":"Alix","code":"69004","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Ambérieux","code":"69005","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"Amplepuis","code":"69006","epci_code":"200040566","departement_code":"69","postal_code":"69550"},{"name":"Ampuis","code":"69007","epci_code":"200077014","departement_code":"69","postal_code":"69420"},{"name":"Ancy","code":"69008","epci_code":"200040566","departement_code":"69","postal_code":"69490"},{"name":"Anse","code":"69009","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"L’Arbresle","code":"69010","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Les Ardillats","code":"69012","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Arnas","code":"69013","epci_code":"200040590","departement_code":"69","postal_code":"69400"},{"name":"Aveize","code":"69014","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Azolette","code":"69016","epci_code":"200067817","departement_code":"69","postal_code":"69790"},{"name":"Bagnols","code":"69017","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Beaujeu","code":"69018","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Belleville-en-Beaujolais","code":"69019","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Belmont-d’Azergues","code":"69020","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Bessenay","code":"69021","epci_code":"246900625","departement_code":"69","postal_code":"69690"},{"name":"Bibost","code":"69022","epci_code":"246900625","departement_code":"69","postal_code":"69690"},{"name":"Blacé","code":"69023","epci_code":"200040590","departement_code":"69","postal_code":"69460"},{"name":"Val d’Oingt","code":"69024","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Le Breuil","code":"69026","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Brignais","code":"69027","epci_code":"246900757","departement_code":"69","postal_code":"69530"},{"name":"Brindas","code":"69028","epci_code":"246900724","departement_code":"69","postal_code":"69126"},{"name":"Bron","code":"69029","epci_code":"200046977","departement_code":"69","postal_code":"69500"},{"name":"Brullioles","code":"69030","epci_code":"200066587","departement_code":"69","postal_code":"69690"},{"name":"Brussieu","code":"69031","epci_code":"200066587","departement_code":"69","postal_code":"69690"},{"name":"Bully","code":"69032","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Cailloux-sur-Fontaines","code":"69033","epci_code":"200046977","departement_code":"69","postal_code":"69270"},{"name":"Caluire-et-Cuire","code":"69034","epci_code":"200046977","departement_code":"69","postal_code":"69300"},{"name":"Cenves","code":"69035","epci_code":"200067817","departement_code":"69","postal_code":"69840"},{"name":"Cercié","code":"69036","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Chambost-Allières","code":"69037","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Chambost-Longessaigne","code":"69038","epci_code":"200066587","departement_code":"69","postal_code":"69770"},{"name":"Chamelet","code":"69039","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Champagne-au-Mont-d’Or","code":"69040","epci_code":"200046977","departement_code":"69","postal_code":"69410"},{"name":"La Chapelle-sur-Coise","code":"69042","epci_code":"200066587","departement_code":"69","postal_code":"69590"},{"name":"Chaponost","code":"69043","epci_code":"246900757","departement_code":"69","postal_code":"69630"},{"name":"Charbonnières-les-Bains","code":"69044","epci_code":"200046977","departement_code":"69","postal_code":"69260"},{"name":"Charentay","code":"69045","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Charly","code":"69046","epci_code":"200046977","departement_code":"69","postal_code":"69390"},{"name":"Charnay","code":"69047","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Chasselay","code":"69049","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Châtillon","code":"69050","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Chaussan","code":"69051","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"Chazay-d’Azergues","code":"69052","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Chénas","code":"69053","epci_code":"200067817","departement_code":"69","postal_code":"69840"},{"name":"Chénelette","code":"69054","epci_code":"200040566","departement_code":"69","postal_code":"69430"},{"name":"Les Chères","code":"69055","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Chessy","code":"69056","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Chevinay","code":"69057","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Chiroubles","code":"69058","epci_code":"200067817","departement_code":"69","postal_code":"69115"},{"name":"Civrieux-d’Azergues","code":"69059","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Claveisolles","code":"69060","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Cogny","code":"69061","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Coise","code":"69062","epci_code":"200066587","departement_code":"69","postal_code":"69590"},{"name":"Collonges-au-Mont-d’Or","code":"69063","epci_code":"200046977","departement_code":"69","postal_code":"69660"},{"name":"Condrieu","code":"69064","epci_code":"200077014","departement_code":"69","postal_code":"69420"},{"name":"Corcelles-en-Beaujolais","code":"69065","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Cours","code":"69066","epci_code":"200040566","departement_code":"69","postal_code":"69470"},{"name":"Courzieu","code":"69067","epci_code":"246900625","departement_code":"69","postal_code":"69690"},{"name":"Couzon-au-Mont-d’Or","code":"69068","epci_code":"200046977","departement_code":"69","postal_code":"69270"},{"name":"Craponne","code":"69069","epci_code":"200046977","departement_code":"69","postal_code":"69290"},{"name":"Cublize","code":"69070","epci_code":"200040566","departement_code":"69","postal_code":"69550"},{"name":"Curis-au-Mont-d’Or","code":"69071","epci_code":"200046977","departement_code":"69","postal_code":"69250"},{"name":"Dardilly","code":"69072","epci_code":"200046977","departement_code":"69","postal_code":"69570"},{"name":"Denicé","code":"69074","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Dième","code":"69075","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Dommartin","code":"69076","epci_code":"246900625","departement_code":"69","postal_code":"69380"},{"name":"Dracé","code":"69077","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Duerne","code":"69078","epci_code":"200066587","departement_code":"69","postal_code":"69850"},{"name":"Échalas","code":"69080","epci_code":"200077014","departement_code":"69","postal_code":"69700"},{"name":"Écully","code":"69081","epci_code":"200046977","departement_code":"69","postal_code":"69130"},{"name":"Émeringes","code":"69082","epci_code":"200067817","departement_code":"69","postal_code":"69840"},{"name":"Éveux","code":"69083","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Fleurie","code":"69084","epci_code":"200067817","departement_code":"69","postal_code":"69820"},{"name":"Fleurieu-sur-Saône","code":"69085","epci_code":"200046977","departement_code":"69","postal_code":"69250"},{"name":"Fleurieux-sur-l’Arbresle","code":"69086","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Fontaines-Saint-Martin","code":"69087","epci_code":"200046977","departement_code":"69","postal_code":"69270"},{"name":"Fontaines-sur-Saône","code":"69088","epci_code":"200046977","departement_code":"69","postal_code":"69270"},{"name":"Francheville","code":"69089","epci_code":"200046977","departement_code":"69","postal_code":"69340"},{"name":"Frontenas","code":"69090","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Givors","code":"69091","epci_code":"200046977","departement_code":"69","postal_code":"69700"},{"name":"Gleizé","code":"69092","epci_code":"200040590","departement_code":"69","postal_code":"69400"},{"name":"Grandris","code":"69093","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Grézieu-la-Varenne","code":"69094","epci_code":"246900724","departement_code":"69","postal_code":"69290"},{"name":"Grézieu-le-Marché","code":"69095","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Grigny","code":"69096","epci_code":"200046977","departement_code":"69","postal_code":"69520"},{"name":"Les Haies","code":"69097","epci_code":"200077014","departement_code":"69","postal_code":"69420"},{"name":"Les Halles","code":"69098","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Haute-Rivoire","code":"69099","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Irigny","code":"69100","epci_code":"200046977","departement_code":"69","postal_code":"69540"},{"name":"Joux","code":"69102","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Juliénas","code":"69103","epci_code":"200067817","departement_code":"69","postal_code":"69840"},{"name":"Jullié","code":"69104","epci_code":"200067817","departement_code":"69","postal_code":"69840"},{"name":"Lacenas","code":"69105","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Lachassagne","code":"69106","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"Lamure-sur-Azergues","code":"69107","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Lancié","code":"69108","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Lantignié","code":"69109","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Larajasse","code":"69110","epci_code":"200066587","departement_code":"69","postal_code":"69590"},{"name":"Légny","code":"69111","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Lentilly","code":"69112","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Létra","code":"69113","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Limas","code":"69115","epci_code":"200040590","departement_code":"69","postal_code":"69400"},{"name":"Limonest","code":"69116","epci_code":"200046977","departement_code":"69","postal_code":"69760"},{"name":"Lissieu","code":"69117","epci_code":"200046977","departement_code":"69","postal_code":"69380"},{"name":"Loire-sur-Rhône","code":"69118","epci_code":"200077014","departement_code":"69","postal_code":"69700"},{"name":"Longes","code":"69119","epci_code":"200077014","departement_code":"69","postal_code":"69420"},{"name":"Longessaigne","code":"69120","epci_code":"200066587","departement_code":"69","postal_code":"69770"},{"name":"Lozanne","code":"69121","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Lucenay","code":"69122","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"Lyon","code":"69123","epci_code":"200046977","departement_code":"69","postal_code":"69001"},{"name":"Lyon","code":"69123","epci_code":"200046977","departement_code":"69","postal_code":"69002"},{"name":"Lyon","code":"69123","epci_code":"200046977","departement_code":"69","postal_code":"69003"},{"name":"Lyon","code":"69123","epci_code":"200046977","departement_code":"69","postal_code":"69004"},{"name":"Lyon","code":"69123","epci_code":"200046977","departement_code":"69","postal_code":"69005"},{"name":"Lyon","code":"69123","epci_code":"200046977","departement_code":"69","postal_code":"69006"},{"name":"Lyon","code":"69123","epci_code":"200046977","departement_code":"69","postal_code":"69007"},{"name":"Lyon","code":"69123","epci_code":"200046977","departement_code":"69","postal_code":"69008"},{"name":"Lyon","code":"69123","epci_code":"200046977","departement_code":"69","postal_code":"69009"},{"name":"Marchampt","code":"69124","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Marcilly-d’Azergues","code":"69125","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Marcy","code":"69126","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"Marcy-l’Étoile","code":"69127","epci_code":"200046977","departement_code":"69","postal_code":"69280"},{"name":"Meaux-la-Montagne","code":"69130","epci_code":"200040566","departement_code":"69","postal_code":"69550"},{"name":"Messimy","code":"69131","epci_code":"246900724","departement_code":"69","postal_code":"69510"},{"name":"Meys","code":"69132","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Millery","code":"69133","epci_code":"246900757","departement_code":"69","postal_code":"69390"},{"name":"Moiré","code":"69134","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Deux-Grosnes","code":"69135","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Deux-Grosnes","code":"69135","epci_code":"200067817","departement_code":"69","postal_code":"69860"},{"name":"Montagny","code":"69136","epci_code":"246900757","departement_code":"69","postal_code":"69700"},{"name":"Montmelas-Saint-Sorlin","code":"69137","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Montromant","code":"69138","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Montrottier","code":"69139","epci_code":"200066587","departement_code":"69","postal_code":"69770"},{"name":"Morancé","code":"69140","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"Mornant","code":"69141","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"La Mulatière","code":"69142","epci_code":"200046977","departement_code":"69","postal_code":"69350"},{"name":"Neuville-sur-Saône","code":"69143","epci_code":"200046977","departement_code":"69","postal_code":"69250"},{"name":"Odenas","code":"69145","epci_code":"200067817","departement_code":"69","postal_code":"69460"},{"name":"Orliénas","code":"69148","epci_code":"246900740","departement_code":"69","postal_code":"69530"},{"name":"Oullins","code":"69149","epci_code":"200046977","departement_code":"69","postal_code":"69600"},{"name":"Le Perréon","code":"69151","epci_code":"200040590","departement_code":"69","postal_code":"69460"},{"name":"Pierre-Bénite","code":"69152","epci_code":"200046977","departement_code":"69","postal_code":"69310"},{"name":"Poleymieux-au-Mont-d’Or","code":"69153","epci_code":"200046977","departement_code":"69","postal_code":"69250"},{"name":"Pollionnay","code":"69154","epci_code":"246900724","departement_code":"69","postal_code":"69290"},{"name":"Pomeys","code":"69155","epci_code":"200066587","departement_code":"69","postal_code":"69590"},{"name":"Pommiers","code":"69156","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"Vindry-sur-Turdine","code":"69157","epci_code":"200040566","departement_code":"69","postal_code":"69490"},{"name":"Porte des Pierres Dorées","code":"69159","epci_code":"200040574","departement_code":"69","postal_code":"69400"},{"name":"Porte des Pierres Dorées","code":"69159","epci_code":"200040574","departement_code":"69","postal_code":"69640"},{"name":"Poule-les-Écharmeaux","code":"69160","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Propières","code":"69161","epci_code":"200067817","departement_code":"69","postal_code":"69790"},{"name":"Quincié-en-Beaujolais","code":"69162","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Quincieux","code":"69163","epci_code":"200046977","departement_code":"69","postal_code":"69650"},{"name":"Ranchal","code":"69164","epci_code":"200040566","departement_code":"69","postal_code":"69470"},{"name":"Régnié-Durette","code":"69165","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Riverie","code":"69166","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"Rivolet","code":"69167","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Rochetaillée-sur-Saône","code":"69168","epci_code":"200046977","departement_code":"69","postal_code":"69270"},{"name":"Ronno","code":"69169","epci_code":"200040566","departement_code":"69","postal_code":"69550"},{"name":"Rontalon","code":"69170","epci_code":"246900740","departement_code":"69","postal_code":"69510"},{"name":"Sain-Bel","code":"69171","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Salles-Arbuissonnas-en-Beaujolais","code":"69172","epci_code":"200040590","departement_code":"69","postal_code":"69460"},{"name":"Sarcey","code":"69173","epci_code":"246900625","departement_code":"69","postal_code":"69490"},{"name":"Les Sauvages","code":"69174","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Savigny","code":"69175","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Soucieu-en-Jarrest","code":"69176","epci_code":"246900740","departement_code":"69","postal_code":"69510"},{"name":"Sourcieux-les-Mines","code":"69177","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Souzy","code":"69178","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Beauvallon","code":"69179","epci_code":"246900740","departement_code":"69","postal_code":"69700"},{"name":"Saint-André-la-Côte","code":"69180","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"Saint-Appolinaire","code":"69181","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Saint-Bonnet-des-Bruyères","code":"69182","epci_code":"200067817","departement_code":"69","postal_code":"69790"},{"name":"Saint-Bonnet-le-Troncy","code":"69183","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Sainte-Catherine","code":"69184","epci_code":"200066587","departement_code":"69","postal_code":"69440"},{"name":"Saint-Clément-de-Vers","code":"69186","epci_code":"200067817","departement_code":"69","postal_code":"69790"},{"name":"Saint-Clément-les-Places","code":"69187","epci_code":"200066587","departement_code":"69","postal_code":"69930"},{"name":"Saint-Clément-sur-Valsonne","code":"69188","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Sainte-Colombe","code":"69189","epci_code":"200077014","departement_code":"69","postal_code":"69560"},{"name":"Sainte-Consorce","code":"69190","epci_code":"246900724","departement_code":"69","postal_code":"69280"},{"name":"Saint-Cyr-au-Mont-d’Or","code":"69191","epci_code":"200046977","departement_code":"69","postal_code":"69450"},{"name":"Saint-Cyr-le-Chatoux","code":"69192","epci_code":"200040590","departement_code":"69","postal_code":"69870"},{"name":"Saint-Cyr-sur-le-Rhône","code":"69193","epci_code":"200077014","departement_code":"69","postal_code":"69560"},{"name":"Saint-Didier-au-Mont-d’Or","code":"69194","epci_code":"200046977","departement_code":"69","postal_code":"69370"},{"name":"Saint-Didier-sur-Beaujeu","code":"69196","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Saint-Étienne-des-Oullières","code":"69197","epci_code":"200040590","departement_code":"69","postal_code":"69460"},{"name":"Saint-Étienne-la-Varenne","code":"69198","epci_code":"200067817","departement_code":"69","postal_code":"69460"},{"name":"Saint-Fons","code":"69199","epci_code":"200046977","departement_code":"69","postal_code":"69190"},{"name":"Saint-Forgeux","code":"69200","epci_code":"200040566","departement_code":"69","postal_code":"69490"},{"name":"Sainte-Foy-l’Argentière","code":"69201","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Sainte-Foy-lès-Lyon","code":"69202","epci_code":"200046977","departement_code":"69","postal_code":"69110"},{"name":"Saint-Genis-l’Argentière","code":"69203","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Saint-Genis-Laval","code":"69204","epci_code":"200046977","departement_code":"69","postal_code":"69230"},{"name":"Saint-Genis-les-Ollières","code":"69205","epci_code":"200046977","departement_code":"69","postal_code":"69290"},{"name":"Saint-Georges-de-Reneins","code":"69206","epci_code":"200067817","departement_code":"69","postal_code":"69830"},{"name":"Saint-Germain-au-Mont-d’Or","code":"69207","epci_code":"200046977","departement_code":"69","postal_code":"69650"},{"name":"Saint-Germain-Nuelles","code":"69208","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Saint-Igny-de-Vers","code":"69209","epci_code":"200067817","departement_code":"69","postal_code":"69790"},{"name":"Saint-Jean-des-Vignes","code":"69212","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Saint-Jean-la-Bussière","code":"69214","epci_code":"200040566","departement_code":"69","postal_code":"69550"},{"name":"Saint-Julien","code":"69215","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Saint-Julien-sur-Bibost","code":"69216","epci_code":"246900625","departement_code":"69","postal_code":"69690"},{"name":"Saint-Just-d’Avray","code":"69217","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Saint-Lager","code":"69218","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Saint-Laurent-d’Agny","code":"69219","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"Saint-Laurent-de-Chamousset","code":"69220","epci_code":"200066587","departement_code":"69","postal_code":"69930"},{"name":"Saint-Marcel-l’Éclairé","code":"69225","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Saint-Martin-en-Haut","code":"69227","epci_code":"200066587","departement_code":"69","postal_code":"69850"},{"name":"Chabanière","code":"69228","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"Saint-Nizier-d’Azergues","code":"69229","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Sainte-Paule","code":"69230","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Saint-Pierre-la-Palud","code":"69231","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Saint-Romain-au-Mont-d’Or","code":"69233","epci_code":"200046977","departement_code":"69","postal_code":"69270"},{"name":"Saint-Romain-de-Popey","code":"69234","epci_code":"200040566","departement_code":"69","postal_code":"69490"},{"name":"Saint-Romain-en-Gal","code":"69235","epci_code":"200077014","departement_code":"69","postal_code":"69560"},{"name":"Saint-Romain-en-Gier","code":"69236","epci_code":"200077014","departement_code":"69","postal_code":"69700"},{"name":"Saint-Symphorien-sur-Coise","code":"69238","epci_code":"200066587","departement_code":"69","postal_code":"69590"},{"name":"Saint-Vérand","code":"69239","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Saint-Vincent-de-Reins","code":"69240","epci_code":"200040566","departement_code":"69","postal_code":"69240"},{"name":"Taluyers","code":"69241","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"Taponas","code":"69242","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Tarare","code":"69243","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Tassin-la-Demi-Lune","code":"69244","epci_code":"200046977","departement_code":"69","postal_code":"69160"},{"name":"Ternand","code":"69245","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Theizé","code":"69246","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Thizy-les-Bourgs","code":"69248","epci_code":"200040566","departement_code":"69","postal_code":"69240"},{"name":"Thurins","code":"69249","epci_code":"246900724","departement_code":"69","postal_code":"69510"},{"name":"La Tour-de-Salvagny","code":"69250","epci_code":"200046977","departement_code":"69","postal_code":"69890"},{"name":"Trèves","code":"69252","epci_code":"200077014","departement_code":"69","postal_code":"69420"},{"name":"Tupin-et-Semons","code":"69253","epci_code":"200077014","departement_code":"69","postal_code":"69420"},{"name":"Valsonne","code":"69254","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Vaugneray","code":"69255","epci_code":"246900724","departement_code":"69","postal_code":"69670"},{"name":"Vaulx-en-Velin","code":"69256","epci_code":"200046977","departement_code":"69","postal_code":"69120"},{"name":"Vaux-en-Beaujolais","code":"69257","epci_code":"200040590","departement_code":"69","postal_code":"69460"},{"name":"Vauxrenard","code":"69258","epci_code":"200067817","departement_code":"69","postal_code":"69820"},{"name":"Vénissieux","code":"69259","epci_code":"200046977","departement_code":"69","postal_code":"69200"},{"name":"Vernaison","code":"69260","epci_code":"200046977","departement_code":"69","postal_code":"69390"},{"name":"Vernay","code":"69261","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Villechenève","code":"69263","epci_code":"200066587","departement_code":"69","postal_code":"69770"},{"name":"Villefranche-sur-Saône","code":"69264","epci_code":"200040590","departement_code":"69","postal_code":"69400"},{"name":"Ville-sur-Jarnioux","code":"69265","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Villeurbanne","code":"69266","epci_code":"200046977","departement_code":"69","postal_code":"69100"},{"name":"Villié-Morgon","code":"69267","epci_code":"200067817","departement_code":"69","postal_code":"69910"},{"name":"Vourles","code":"69268","epci_code":"246900757","departement_code":"69","postal_code":"69390"},{"name":"Yzeron","code":"69269","epci_code":"246900724","departement_code":"69","postal_code":"69510"},{"name":"Chaponnay","code":"69270","epci_code":"246900765","departement_code":"69","postal_code":"69970"},{"name":"Chassieu","code":"69271","epci_code":"200046977","departement_code":"69","postal_code":"69680"},{"name":"Communay","code":"69272","epci_code":"246900765","departement_code":"69","postal_code":"69360"},{"name":"Corbas","code":"69273","epci_code":"200046977","departement_code":"69","postal_code":"69960"},{"name":"Décines-Charpieu","code":"69275","epci_code":"200046977","departement_code":"69","postal_code":"69150"},{"name":"Feyzin","code":"69276","epci_code":"200046977","departement_code":"69","postal_code":"69320"},{"name":"Genas","code":"69277","epci_code":"246900575","departement_code":"69","postal_code":"69740"},{"name":"Genay","code":"69278","epci_code":"200046977","departement_code":"69","postal_code":"69730"},{"name":"Jonage","code":"69279","epci_code":"200046977","departement_code":"69","postal_code":"69330"},{"name":"Jons","code":"69280","epci_code":"246900575","departement_code":"69","postal_code":"69330"},{"name":"Marennes","code":"69281","epci_code":"246900765","departement_code":"69","postal_code":"69970"},{"name":"Meyzieu","code":"69282","epci_code":"200046977","departement_code":"69","postal_code":"69330"},{"name":"Mions","code":"69283","epci_code":"200046977","departement_code":"69","postal_code":"69780"},{"name":"Montanay","code":"69284","epci_code":"200046977","departement_code":"69","postal_code":"69250"},{"name":"Pusignan","code":"69285","epci_code":"246900575","departement_code":"69","postal_code":"69330"},{"name":"Rillieux-la-Pape","code":"69286","epci_code":"200046977","departement_code":"69","postal_code":"69140"},{"name":"Saint-Bonnet-de-Mure","code":"69287","epci_code":"246900575","departement_code":"69","postal_code":"69720"},{"name":"Saint-Laurent-de-Mure","code":"69288","epci_code":"246900575","departement_code":"69","postal_code":"69720"},{"name":"Saint-Pierre-de-Chandieu","code":"69289","epci_code":"246900575","departement_code":"69","postal_code":"69780"},{"name":"Saint-Priest","code":"69290","epci_code":"200046977","departement_code":"69","postal_code":"69800"},{"name":"Saint-Symphorien-d’Ozon","code":"69291","epci_code":"246900765","departement_code":"69","postal_code":"69360"},{"name":"Sathonay-Camp","code":"69292","epci_code":"200046977","departement_code":"69","postal_code":"69580"},{"name":"Sathonay-Village","code":"69293","epci_code":"200046977","departement_code":"69","postal_code":"69580"},{"name":"Sérézin-du-Rhône","code":"69294","epci_code":"246900765","departement_code":"69","postal_code":"69360"},{"name":"Simandres","code":"69295","epci_code":"246900765","departement_code":"69","postal_code":"69360"},{"name":"Solaize","code":"69296","epci_code":"200046977","departement_code":"69","postal_code":"69360"},{"name":"Ternay","code":"69297","epci_code":"246900765","departement_code":"69","postal_code":"69360"},{"name":"Toussieu","code":"69298","epci_code":"246900575","departement_code":"69","postal_code":"69780"},{"name":"Colombier-Saugnieu","code":"69299","epci_code":"246900575","departement_code":"69","postal_code":"69124"},{"name":"Colombier-Saugnieu","code":"69299","epci_code":"246900575","departement_code":"69","postal_code":"69125"},{"name":"Lyon 1er Arrondissement","code":"69381","departement_code":"69","postal_code":"69001"},{"name":"Lyon 2e Arrondissement","code":"69382","departement_code":"69","postal_code":"69002"},{"name":"Lyon 3e Arrondissement","code":"69383","departement_code":"69","postal_code":"69003"},{"name":"Lyon 4e Arrondissement","code":"69384","departement_code":"69","postal_code":"69004"},{"name":"Lyon 5e Arrondissement","code":"69385","departement_code":"69","postal_code":"69005"},{"name":"Lyon 6e Arrondissement","code":"69386","departement_code":"69","postal_code":"69006"},{"name":"Lyon 7e Arrondissement","code":"69387","departement_code":"69","postal_code":"69007"},{"name":"Lyon 8e Arrondissement","code":"69388","departement_code":"69","postal_code":"69008"},{"name":"Lyon 9e Arrondissement","code":"69389","departement_code":"69","postal_code":"69009"}]
\ No newline at end of file
+[{"name":"Affoux","code":"69001","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Aigueperse","code":"69002","epci_code":"200067817","departement_code":"69","postal_code":"69790"},{"name":"Albigny-sur-Saône","code":"69003","epci_code":"200046977","departement_code":"69","postal_code":"69250"},{"name":"Alix","code":"69004","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Ambérieux","code":"69005","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"Amplepuis","code":"69006","epci_code":"200040566","departement_code":"69","postal_code":"69550"},{"name":"Ampuis","code":"69007","epci_code":"200077014","departement_code":"69","postal_code":"69420"},{"name":"Ancy","code":"69008","epci_code":"200040566","departement_code":"69","postal_code":"69490"},{"name":"Anse","code":"69009","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"L’Arbresle","code":"69010","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Les Ardillats","code":"69012","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Arnas","code":"69013","epci_code":"200040590","departement_code":"69","postal_code":"69400"},{"name":"Aveize","code":"69014","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Azolette","code":"69016","epci_code":"200067817","departement_code":"69","postal_code":"69790"},{"name":"Bagnols","code":"69017","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Beaujeu","code":"69018","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Belleville-en-Beaujolais","code":"69019","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Belmont-d’Azergues","code":"69020","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Bessenay","code":"69021","epci_code":"246900625","departement_code":"69","postal_code":"69690"},{"name":"Bibost","code":"69022","epci_code":"246900625","departement_code":"69","postal_code":"69690"},{"name":"Blacé","code":"69023","epci_code":"200040590","departement_code":"69","postal_code":"69460"},{"name":"Val d’Oingt","code":"69024","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Le Breuil","code":"69026","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Brignais","code":"69027","epci_code":"246900757","departement_code":"69","postal_code":"69530"},{"name":"Brindas","code":"69028","epci_code":"246900724","departement_code":"69","postal_code":"69126"},{"name":"Bron","code":"69029","epci_code":"200046977","departement_code":"69","postal_code":"69500"},{"name":"Brullioles","code":"69030","epci_code":"200066587","departement_code":"69","postal_code":"69690"},{"name":"Brussieu","code":"69031","epci_code":"200066587","departement_code":"69","postal_code":"69690"},{"name":"Bully","code":"69032","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Cailloux-sur-Fontaines","code":"69033","epci_code":"200046977","departement_code":"69","postal_code":"69270"},{"name":"Caluire-et-Cuire","code":"69034","epci_code":"200046977","departement_code":"69","postal_code":"69300"},{"name":"Cenves","code":"69035","epci_code":"200067817","departement_code":"69","postal_code":"69840"},{"name":"Cercié","code":"69036","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Chambost-Allières","code":"69037","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Chambost-Longessaigne","code":"69038","epci_code":"200066587","departement_code":"69","postal_code":"69770"},{"name":"Chamelet","code":"69039","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Champagne-au-Mont-d’Or","code":"69040","epci_code":"200046977","departement_code":"69","postal_code":"69410"},{"name":"La Chapelle-sur-Coise","code":"69042","epci_code":"200066587","departement_code":"69","postal_code":"69590"},{"name":"Chaponost","code":"69043","epci_code":"246900757","departement_code":"69","postal_code":"69630"},{"name":"Charbonnières-les-Bains","code":"69044","epci_code":"200046977","departement_code":"69","postal_code":"69260"},{"name":"Charentay","code":"69045","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Charly","code":"69046","epci_code":"200046977","departement_code":"69","postal_code":"69390"},{"name":"Charnay","code":"69047","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Chasselay","code":"69049","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Châtillon","code":"69050","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Chaussan","code":"69051","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"Chazay-d’Azergues","code":"69052","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Chénas","code":"69053","epci_code":"200067817","departement_code":"69","postal_code":"69840"},{"name":"Chénelette","code":"69054","epci_code":"200040566","departement_code":"69","postal_code":"69430"},{"name":"Les Chères","code":"69055","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Chessy","code":"69056","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Chevinay","code":"69057","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Chiroubles","code":"69058","epci_code":"200067817","departement_code":"69","postal_code":"69115"},{"name":"Civrieux-d’Azergues","code":"69059","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Claveisolles","code":"69060","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Cogny","code":"69061","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Coise","code":"69062","epci_code":"200066587","departement_code":"69","postal_code":"69590"},{"name":"Collonges-au-Mont-d’Or","code":"69063","epci_code":"200046977","departement_code":"69","postal_code":"69660"},{"name":"Condrieu","code":"69064","epci_code":"200077014","departement_code":"69","postal_code":"69420"},{"name":"Corcelles-en-Beaujolais","code":"69065","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Cours","code":"69066","epci_code":"200040566","departement_code":"69","postal_code":"69470"},{"name":"Courzieu","code":"69067","epci_code":"246900625","departement_code":"69","postal_code":"69690"},{"name":"Couzon-au-Mont-d’Or","code":"69068","epci_code":"200046977","departement_code":"69","postal_code":"69270"},{"name":"Craponne","code":"69069","epci_code":"200046977","departement_code":"69","postal_code":"69290"},{"name":"Cublize","code":"69070","epci_code":"200040566","departement_code":"69","postal_code":"69550"},{"name":"Curis-au-Mont-d’Or","code":"69071","epci_code":"200046977","departement_code":"69","postal_code":"69250"},{"name":"Dardilly","code":"69072","epci_code":"200046977","departement_code":"69","postal_code":"69570"},{"name":"Denicé","code":"69074","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Dième","code":"69075","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Dommartin","code":"69076","epci_code":"246900625","departement_code":"69","postal_code":"69380"},{"name":"Dracé","code":"69077","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Duerne","code":"69078","epci_code":"200066587","departement_code":"69","postal_code":"69850"},{"name":"Échalas","code":"69080","epci_code":"200077014","departement_code":"69","postal_code":"69700"},{"name":"Écully","code":"69081","epci_code":"200046977","departement_code":"69","postal_code":"69130"},{"name":"Émeringes","code":"69082","epci_code":"200067817","departement_code":"69","postal_code":"69840"},{"name":"Éveux","code":"69083","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Fleurie","code":"69084","epci_code":"200067817","departement_code":"69","postal_code":"69820"},{"name":"Fleurieu-sur-Saône","code":"69085","epci_code":"200046977","departement_code":"69","postal_code":"69250"},{"name":"Fleurieux-sur-l’Arbresle","code":"69086","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Fontaines-Saint-Martin","code":"69087","epci_code":"200046977","departement_code":"69","postal_code":"69270"},{"name":"Fontaines-sur-Saône","code":"69088","epci_code":"200046977","departement_code":"69","postal_code":"69270"},{"name":"Francheville","code":"69089","epci_code":"200046977","departement_code":"69","postal_code":"69340"},{"name":"Frontenas","code":"69090","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Givors","code":"69091","epci_code":"200046977","departement_code":"69","postal_code":"69700"},{"name":"Gleizé","code":"69092","epci_code":"200040590","departement_code":"69","postal_code":"69400"},{"name":"Grandris","code":"69093","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Grézieu-la-Varenne","code":"69094","epci_code":"246900724","departement_code":"69","postal_code":"69290"},{"name":"Grézieu-le-Marché","code":"69095","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Grigny","code":"69096","epci_code":"200046977","departement_code":"69","postal_code":"69520"},{"name":"Les Haies","code":"69097","epci_code":"200077014","departement_code":"69","postal_code":"69420"},{"name":"Les Halles","code":"69098","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Haute-Rivoire","code":"69099","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Irigny","code":"69100","epci_code":"200046977","departement_code":"69","postal_code":"69540"},{"name":"Joux","code":"69102","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Juliénas","code":"69103","epci_code":"200067817","departement_code":"69","postal_code":"69840"},{"name":"Jullié","code":"69104","epci_code":"200067817","departement_code":"69","postal_code":"69840"},{"name":"Lacenas","code":"69105","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Lachassagne","code":"69106","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"Lamure-sur-Azergues","code":"69107","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Lancié","code":"69108","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Lantignié","code":"69109","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Larajasse","code":"69110","epci_code":"200066587","departement_code":"69","postal_code":"69590"},{"name":"Légny","code":"69111","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Lentilly","code":"69112","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Létra","code":"69113","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Limas","code":"69115","epci_code":"200040590","departement_code":"69","postal_code":"69400"},{"name":"Limonest","code":"69116","epci_code":"200046977","departement_code":"69","postal_code":"69760"},{"name":"Lissieu","code":"69117","epci_code":"200046977","departement_code":"69","postal_code":"69380"},{"name":"Loire-sur-Rhône","code":"69118","epci_code":"200077014","departement_code":"69","postal_code":"69700"},{"name":"Longes","code":"69119","epci_code":"200077014","departement_code":"69","postal_code":"69420"},{"name":"Longessaigne","code":"69120","epci_code":"200066587","departement_code":"69","postal_code":"69770"},{"name":"Lozanne","code":"69121","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Lucenay","code":"69122","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"Marchampt","code":"69124","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Marcilly-d’Azergues","code":"69125","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Marcy","code":"69126","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"Marcy-l’Étoile","code":"69127","epci_code":"200046977","departement_code":"69","postal_code":"69280"},{"name":"Meaux-la-Montagne","code":"69130","epci_code":"200040566","departement_code":"69","postal_code":"69550"},{"name":"Messimy","code":"69131","epci_code":"246900724","departement_code":"69","postal_code":"69510"},{"name":"Meys","code":"69132","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Millery","code":"69133","epci_code":"246900757","departement_code":"69","postal_code":"69390"},{"name":"Moiré","code":"69134","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Deux-Grosnes","code":"69135","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Deux-Grosnes","code":"69135","epci_code":"200067817","departement_code":"69","postal_code":"69860"},{"name":"Montagny","code":"69136","epci_code":"246900757","departement_code":"69","postal_code":"69700"},{"name":"Montmelas-Saint-Sorlin","code":"69137","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Montromant","code":"69138","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Montrottier","code":"69139","epci_code":"200066587","departement_code":"69","postal_code":"69770"},{"name":"Morancé","code":"69140","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"Mornant","code":"69141","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"La Mulatière","code":"69142","epci_code":"200046977","departement_code":"69","postal_code":"69350"},{"name":"Neuville-sur-Saône","code":"69143","epci_code":"200046977","departement_code":"69","postal_code":"69250"},{"name":"Odenas","code":"69145","epci_code":"200067817","departement_code":"69","postal_code":"69460"},{"name":"Orliénas","code":"69148","epci_code":"246900740","departement_code":"69","postal_code":"69530"},{"name":"Oullins","code":"69149","epci_code":"200046977","departement_code":"69","postal_code":"69600"},{"name":"Le Perréon","code":"69151","epci_code":"200040590","departement_code":"69","postal_code":"69460"},{"name":"Pierre-Bénite","code":"69152","epci_code":"200046977","departement_code":"69","postal_code":"69310"},{"name":"Poleymieux-au-Mont-d’Or","code":"69153","epci_code":"200046977","departement_code":"69","postal_code":"69250"},{"name":"Pollionnay","code":"69154","epci_code":"246900724","departement_code":"69","postal_code":"69290"},{"name":"Pomeys","code":"69155","epci_code":"200066587","departement_code":"69","postal_code":"69590"},{"name":"Pommiers","code":"69156","epci_code":"200040574","departement_code":"69","postal_code":"69480"},{"name":"Vindry-sur-Turdine","code":"69157","epci_code":"200040566","departement_code":"69","postal_code":"69490"},{"name":"Porte des Pierres Dorées","code":"69159","epci_code":"200040574","departement_code":"69","postal_code":"69400"},{"name":"Porte des Pierres Dorées","code":"69159","epci_code":"200040574","departement_code":"69","postal_code":"69640"},{"name":"Poule-les-Écharmeaux","code":"69160","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Propières","code":"69161","epci_code":"200067817","departement_code":"69","postal_code":"69790"},{"name":"Quincié-en-Beaujolais","code":"69162","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Quincieux","code":"69163","epci_code":"200046977","departement_code":"69","postal_code":"69650"},{"name":"Ranchal","code":"69164","epci_code":"200040566","departement_code":"69","postal_code":"69470"},{"name":"Régnié-Durette","code":"69165","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Riverie","code":"69166","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"Rivolet","code":"69167","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Rochetaillée-sur-Saône","code":"69168","epci_code":"200046977","departement_code":"69","postal_code":"69270"},{"name":"Ronno","code":"69169","epci_code":"200040566","departement_code":"69","postal_code":"69550"},{"name":"Rontalon","code":"69170","epci_code":"246900740","departement_code":"69","postal_code":"69510"},{"name":"Sain-Bel","code":"69171","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Salles-Arbuissonnas-en-Beaujolais","code":"69172","epci_code":"200040590","departement_code":"69","postal_code":"69460"},{"name":"Sarcey","code":"69173","epci_code":"246900625","departement_code":"69","postal_code":"69490"},{"name":"Les Sauvages","code":"69174","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Savigny","code":"69175","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Soucieu-en-Jarrest","code":"69176","epci_code":"246900740","departement_code":"69","postal_code":"69510"},{"name":"Sourcieux-les-Mines","code":"69177","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Souzy","code":"69178","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Beauvallon","code":"69179","epci_code":"246900740","departement_code":"69","postal_code":"69700"},{"name":"Saint-André-la-Côte","code":"69180","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"Saint-Appolinaire","code":"69181","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Saint-Bonnet-des-Bruyères","code":"69182","epci_code":"200067817","departement_code":"69","postal_code":"69790"},{"name":"Saint-Bonnet-le-Troncy","code":"69183","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Sainte-Catherine","code":"69184","epci_code":"200066587","departement_code":"69","postal_code":"69440"},{"name":"Saint-Clément-de-Vers","code":"69186","epci_code":"200067817","departement_code":"69","postal_code":"69790"},{"name":"Saint-Clément-les-Places","code":"69187","epci_code":"200066587","departement_code":"69","postal_code":"69930"},{"name":"Saint-Clément-sur-Valsonne","code":"69188","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Sainte-Colombe","code":"69189","epci_code":"200077014","departement_code":"69","postal_code":"69560"},{"name":"Sainte-Consorce","code":"69190","epci_code":"246900724","departement_code":"69","postal_code":"69280"},{"name":"Saint-Cyr-au-Mont-d’Or","code":"69191","epci_code":"200046977","departement_code":"69","postal_code":"69450"},{"name":"Saint-Cyr-le-Chatoux","code":"69192","epci_code":"200040590","departement_code":"69","postal_code":"69870"},{"name":"Saint-Cyr-sur-le-Rhône","code":"69193","epci_code":"200077014","departement_code":"69","postal_code":"69560"},{"name":"Saint-Didier-au-Mont-d’Or","code":"69194","epci_code":"200046977","departement_code":"69","postal_code":"69370"},{"name":"Saint-Didier-sur-Beaujeu","code":"69196","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Saint-Étienne-des-Oullières","code":"69197","epci_code":"200040590","departement_code":"69","postal_code":"69460"},{"name":"Saint-Étienne-la-Varenne","code":"69198","epci_code":"200067817","departement_code":"69","postal_code":"69460"},{"name":"Saint-Fons","code":"69199","epci_code":"200046977","departement_code":"69","postal_code":"69190"},{"name":"Saint-Forgeux","code":"69200","epci_code":"200040566","departement_code":"69","postal_code":"69490"},{"name":"Sainte-Foy-l’Argentière","code":"69201","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Sainte-Foy-lès-Lyon","code":"69202","epci_code":"200046977","departement_code":"69","postal_code":"69110"},{"name":"Saint-Genis-l’Argentière","code":"69203","epci_code":"200066587","departement_code":"69","postal_code":"69610"},{"name":"Saint-Genis-Laval","code":"69204","epci_code":"200046977","departement_code":"69","postal_code":"69230"},{"name":"Saint-Genis-les-Ollières","code":"69205","epci_code":"200046977","departement_code":"69","postal_code":"69290"},{"name":"Saint-Georges-de-Reneins","code":"69206","epci_code":"200067817","departement_code":"69","postal_code":"69830"},{"name":"Saint-Germain-au-Mont-d’Or","code":"69207","epci_code":"200046977","departement_code":"69","postal_code":"69650"},{"name":"Saint-Germain-Nuelles","code":"69208","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Saint-Igny-de-Vers","code":"69209","epci_code":"200067817","departement_code":"69","postal_code":"69790"},{"name":"Saint-Jean-des-Vignes","code":"69212","epci_code":"200040574","departement_code":"69","postal_code":"69380"},{"name":"Saint-Jean-la-Bussière","code":"69214","epci_code":"200040566","departement_code":"69","postal_code":"69550"},{"name":"Saint-Julien","code":"69215","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Saint-Julien-sur-Bibost","code":"69216","epci_code":"246900625","departement_code":"69","postal_code":"69690"},{"name":"Saint-Just-d’Avray","code":"69217","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Saint-Lager","code":"69218","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Saint-Laurent-d’Agny","code":"69219","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"Saint-Laurent-de-Chamousset","code":"69220","epci_code":"200066587","departement_code":"69","postal_code":"69930"},{"name":"Saint-Marcel-l’Éclairé","code":"69225","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Saint-Martin-en-Haut","code":"69227","epci_code":"200066587","departement_code":"69","postal_code":"69850"},{"name":"Chabanière","code":"69228","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"Saint-Nizier-d’Azergues","code":"69229","epci_code":"200040566","departement_code":"69","postal_code":"69870"},{"name":"Sainte-Paule","code":"69230","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Saint-Pierre-la-Palud","code":"69231","epci_code":"246900625","departement_code":"69","postal_code":"69210"},{"name":"Saint-Romain-au-Mont-d’Or","code":"69233","epci_code":"200046977","departement_code":"69","postal_code":"69270"},{"name":"Saint-Romain-de-Popey","code":"69234","epci_code":"200040566","departement_code":"69","postal_code":"69490"},{"name":"Saint-Romain-en-Gal","code":"69235","epci_code":"200077014","departement_code":"69","postal_code":"69560"},{"name":"Saint-Romain-en-Gier","code":"69236","epci_code":"200077014","departement_code":"69","postal_code":"69700"},{"name":"Saint-Symphorien-sur-Coise","code":"69238","epci_code":"200066587","departement_code":"69","postal_code":"69590"},{"name":"Saint-Vérand","code":"69239","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Saint-Vincent-de-Reins","code":"69240","epci_code":"200040566","departement_code":"69","postal_code":"69240"},{"name":"Taluyers","code":"69241","epci_code":"246900740","departement_code":"69","postal_code":"69440"},{"name":"Taponas","code":"69242","epci_code":"200067817","departement_code":"69","postal_code":"69220"},{"name":"Tarare","code":"69243","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Tassin-la-Demi-Lune","code":"69244","epci_code":"200046977","departement_code":"69","postal_code":"69160"},{"name":"Ternand","code":"69245","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Theizé","code":"69246","epci_code":"200040574","departement_code":"69","postal_code":"69620"},{"name":"Thizy-les-Bourgs","code":"69248","epci_code":"200040566","departement_code":"69","postal_code":"69240"},{"name":"Thurins","code":"69249","epci_code":"246900724","departement_code":"69","postal_code":"69510"},{"name":"La Tour-de-Salvagny","code":"69250","epci_code":"200046977","departement_code":"69","postal_code":"69890"},{"name":"Trèves","code":"69252","epci_code":"200077014","departement_code":"69","postal_code":"69420"},{"name":"Tupin-et-Semons","code":"69253","epci_code":"200077014","departement_code":"69","postal_code":"69420"},{"name":"Valsonne","code":"69254","epci_code":"200040566","departement_code":"69","postal_code":"69170"},{"name":"Vaugneray","code":"69255","epci_code":"246900724","departement_code":"69","postal_code":"69670"},{"name":"Vaulx-en-Velin","code":"69256","epci_code":"200046977","departement_code":"69","postal_code":"69120"},{"name":"Vaux-en-Beaujolais","code":"69257","epci_code":"200040590","departement_code":"69","postal_code":"69460"},{"name":"Vauxrenard","code":"69258","epci_code":"200067817","departement_code":"69","postal_code":"69820"},{"name":"Vénissieux","code":"69259","epci_code":"200046977","departement_code":"69","postal_code":"69200"},{"name":"Vernaison","code":"69260","epci_code":"200046977","departement_code":"69","postal_code":"69390"},{"name":"Vernay","code":"69261","epci_code":"200067817","departement_code":"69","postal_code":"69430"},{"name":"Villechenève","code":"69263","epci_code":"200066587","departement_code":"69","postal_code":"69770"},{"name":"Villefranche-sur-Saône","code":"69264","epci_code":"200040590","departement_code":"69","postal_code":"69400"},{"name":"Ville-sur-Jarnioux","code":"69265","epci_code":"200040590","departement_code":"69","postal_code":"69640"},{"name":"Villeurbanne","code":"69266","epci_code":"200046977","departement_code":"69","postal_code":"69100"},{"name":"Villié-Morgon","code":"69267","epci_code":"200067817","departement_code":"69","postal_code":"69910"},{"name":"Vourles","code":"69268","epci_code":"246900757","departement_code":"69","postal_code":"69390"},{"name":"Yzeron","code":"69269","epci_code":"246900724","departement_code":"69","postal_code":"69510"},{"name":"Chaponnay","code":"69270","epci_code":"246900765","departement_code":"69","postal_code":"69970"},{"name":"Chassieu","code":"69271","epci_code":"200046977","departement_code":"69","postal_code":"69680"},{"name":"Communay","code":"69272","epci_code":"246900765","departement_code":"69","postal_code":"69360"},{"name":"Corbas","code":"69273","epci_code":"200046977","departement_code":"69","postal_code":"69960"},{"name":"Décines-Charpieu","code":"69275","epci_code":"200046977","departement_code":"69","postal_code":"69150"},{"name":"Feyzin","code":"69276","epci_code":"200046977","departement_code":"69","postal_code":"69320"},{"name":"Genas","code":"69277","epci_code":"246900575","departement_code":"69","postal_code":"69740"},{"name":"Genay","code":"69278","epci_code":"200046977","departement_code":"69","postal_code":"69730"},{"name":"Jonage","code":"69279","epci_code":"200046977","departement_code":"69","postal_code":"69330"},{"name":"Jons","code":"69280","epci_code":"246900575","departement_code":"69","postal_code":"69330"},{"name":"Marennes","code":"69281","epci_code":"246900765","departement_code":"69","postal_code":"69970"},{"name":"Meyzieu","code":"69282","epci_code":"200046977","departement_code":"69","postal_code":"69330"},{"name":"Mions","code":"69283","epci_code":"200046977","departement_code":"69","postal_code":"69780"},{"name":"Montanay","code":"69284","epci_code":"200046977","departement_code":"69","postal_code":"69250"},{"name":"Pusignan","code":"69285","epci_code":"246900575","departement_code":"69","postal_code":"69330"},{"name":"Rillieux-la-Pape","code":"69286","epci_code":"200046977","departement_code":"69","postal_code":"69140"},{"name":"Saint-Bonnet-de-Mure","code":"69287","epci_code":"246900575","departement_code":"69","postal_code":"69720"},{"name":"Saint-Laurent-de-Mure","code":"69288","epci_code":"246900575","departement_code":"69","postal_code":"69720"},{"name":"Saint-Pierre-de-Chandieu","code":"69289","epci_code":"246900575","departement_code":"69","postal_code":"69780"},{"name":"Saint-Priest","code":"69290","epci_code":"200046977","departement_code":"69","postal_code":"69800"},{"name":"Saint-Symphorien-d’Ozon","code":"69291","epci_code":"246900765","departement_code":"69","postal_code":"69360"},{"name":"Sathonay-Camp","code":"69292","epci_code":"200046977","departement_code":"69","postal_code":"69580"},{"name":"Sathonay-Village","code":"69293","epci_code":"200046977","departement_code":"69","postal_code":"69580"},{"name":"Sérézin-du-Rhône","code":"69294","epci_code":"246900765","departement_code":"69","postal_code":"69360"},{"name":"Simandres","code":"69295","epci_code":"246900765","departement_code":"69","postal_code":"69360"},{"name":"Solaize","code":"69296","epci_code":"200046977","departement_code":"69","postal_code":"69360"},{"name":"Ternay","code":"69297","epci_code":"246900765","departement_code":"69","postal_code":"69360"},{"name":"Toussieu","code":"69298","epci_code":"246900575","departement_code":"69","postal_code":"69780"},{"name":"Colombier-Saugnieu","code":"69299","epci_code":"246900575","departement_code":"69","postal_code":"69124"},{"name":"Colombier-Saugnieu","code":"69299","epci_code":"246900575","departement_code":"69","postal_code":"69125"},{"name":"Lyon 1er Arrondissement","code":"69381","departement_code":"69","postal_code":"69001"},{"name":"Lyon 2e Arrondissement","code":"69382","departement_code":"69","postal_code":"69002"},{"name":"Lyon 3e Arrondissement","code":"69383","departement_code":"69","postal_code":"69003"},{"name":"Lyon 4e Arrondissement","code":"69384","departement_code":"69","postal_code":"69004"},{"name":"Lyon 5e Arrondissement","code":"69385","departement_code":"69","postal_code":"69005"},{"name":"Lyon 6e Arrondissement","code":"69386","departement_code":"69","postal_code":"69006"},{"name":"Lyon 7e Arrondissement","code":"69387","departement_code":"69","postal_code":"69007"},{"name":"Lyon 8e Arrondissement","code":"69388","departement_code":"69","postal_code":"69008"},{"name":"Lyon 9e Arrondissement","code":"69389","departement_code":"69","postal_code":"69009"}]
\ No newline at end of file
diff --git a/lib/data/api_geo/communes-75.json b/lib/data/api_geo/communes-75.json
index 6fc2b0e5616..35b0a4d506b 100644
--- a/lib/data/api_geo/communes-75.json
+++ b/lib/data/api_geo/communes-75.json
@@ -1 +1 @@
-[{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75001"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75002"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75003"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75004"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75005"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75006"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75007"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75008"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75009"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75010"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75011"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75012"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75013"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75014"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75015"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75016"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75017"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75018"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75019"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75020"},{"name":"Paris","code":"75056","epci_code":"200054781","departement_code":"75","postal_code":"75116"},{"name":"Paris 1er Arrondissement","code":"75101","departement_code":"75","postal_code":"75001"},{"name":"Paris 2e Arrondissement","code":"75102","departement_code":"75","postal_code":"75002"},{"name":"Paris 3e Arrondissement","code":"75103","departement_code":"75","postal_code":"75003"},{"name":"Paris 4e Arrondissement","code":"75104","departement_code":"75","postal_code":"75004"},{"name":"Paris 5e Arrondissement","code":"75105","departement_code":"75","postal_code":"75005"},{"name":"Paris 6e Arrondissement","code":"75106","departement_code":"75","postal_code":"75006"},{"name":"Paris 7e Arrondissement","code":"75107","departement_code":"75","postal_code":"75007"},{"name":"Paris 8e Arrondissement","code":"75108","departement_code":"75","postal_code":"75008"},{"name":"Paris 9e Arrondissement","code":"75109","departement_code":"75","postal_code":"75009"},{"name":"Paris 10e Arrondissement","code":"75110","departement_code":"75","postal_code":"75010"},{"name":"Paris 11e Arrondissement","code":"75111","departement_code":"75","postal_code":"75011"},{"name":"Paris 12e Arrondissement","code":"75112","departement_code":"75","postal_code":"75012"},{"name":"Paris 13e Arrondissement","code":"75113","departement_code":"75","postal_code":"75013"},{"name":"Paris 14e Arrondissement","code":"75114","departement_code":"75","postal_code":"75014"},{"name":"Paris 15e Arrondissement","code":"75115","departement_code":"75","postal_code":"75015"},{"name":"Paris 16e Arrondissement","code":"75116","departement_code":"75","postal_code":"75016"},{"name":"Paris 16e Arrondissement","code":"75116","departement_code":"75","postal_code":"75116"},{"name":"Paris 17e Arrondissement","code":"75117","departement_code":"75","postal_code":"75017"},{"name":"Paris 18e Arrondissement","code":"75118","departement_code":"75","postal_code":"75018"},{"name":"Paris 19e Arrondissement","code":"75119","departement_code":"75","postal_code":"75019"},{"name":"Paris 20e Arrondissement","code":"75120","departement_code":"75","postal_code":"75020"}]
\ No newline at end of file
+[{"name":"Paris 1er Arrondissement","code":"75101","departement_code":"75","postal_code":"75001"},{"name":"Paris 2e Arrondissement","code":"75102","departement_code":"75","postal_code":"75002"},{"name":"Paris 3e Arrondissement","code":"75103","departement_code":"75","postal_code":"75003"},{"name":"Paris 4e Arrondissement","code":"75104","departement_code":"75","postal_code":"75004"},{"name":"Paris 5e Arrondissement","code":"75105","departement_code":"75","postal_code":"75005"},{"name":"Paris 6e Arrondissement","code":"75106","departement_code":"75","postal_code":"75006"},{"name":"Paris 7e Arrondissement","code":"75107","departement_code":"75","postal_code":"75007"},{"name":"Paris 8e Arrondissement","code":"75108","departement_code":"75","postal_code":"75008"},{"name":"Paris 9e Arrondissement","code":"75109","departement_code":"75","postal_code":"75009"},{"name":"Paris 10e Arrondissement","code":"75110","departement_code":"75","postal_code":"75010"},{"name":"Paris 11e Arrondissement","code":"75111","departement_code":"75","postal_code":"75011"},{"name":"Paris 12e Arrondissement","code":"75112","departement_code":"75","postal_code":"75012"},{"name":"Paris 13e Arrondissement","code":"75113","departement_code":"75","postal_code":"75013"},{"name":"Paris 14e Arrondissement","code":"75114","departement_code":"75","postal_code":"75014"},{"name":"Paris 15e Arrondissement","code":"75115","departement_code":"75","postal_code":"75015"},{"name":"Paris 16e Arrondissement","code":"75116","departement_code":"75","postal_code":"75016"},{"name":"Paris 16e Arrondissement","code":"75116","departement_code":"75","postal_code":"75116"},{"name":"Paris 17e Arrondissement","code":"75117","departement_code":"75","postal_code":"75017"},{"name":"Paris 18e Arrondissement","code":"75118","departement_code":"75","postal_code":"75018"},{"name":"Paris 19e Arrondissement","code":"75119","departement_code":"75","postal_code":"75019"},{"name":"Paris 20e Arrondissement","code":"75120","departement_code":"75","postal_code":"75020"}]
\ No newline at end of file
diff --git a/lib/tasks/api_geo_data.rake b/lib/tasks/api_geo_data.rake
index a87ddf73b2f..1efd247afe9 100644
--- a/lib/tasks/api_geo_data.rake
+++ b/lib/tasks/api_geo_data.rake
@@ -21,7 +21,9 @@ namespace :api_geo_data do
data = []
PATH.join("#{filename}.json").open('w') do |f|
response = Typhoeus.get("#{API_GEO_URL}/#{query}")
- json = JSON.parse(response.body).map(&:symbolize_keys).flat_map do |result|
+ json = JSON.parse(response.body).map(&:symbolize_keys).filter do |result|
+ !result[:code].in?(['75056', '13055', '69123'])
+ end.flat_map do |result|
item = {
name: result[:nom].tr("'", '’'),
code: result[:code],
diff --git a/lib/tasks/deployment/20230725101602_remove_toplevel_communes.rake b/lib/tasks/deployment/20230725101602_remove_toplevel_communes.rake
new file mode 100644
index 00000000000..fc16cdc8180
--- /dev/null
+++ b/lib/tasks/deployment/20230725101602_remove_toplevel_communes.rake
@@ -0,0 +1,28 @@
+namespace :after_party do
+ desc 'Deployment task: remove_toplevel_communes'
+ task remove_toplevel_communes: :environment do
+ puts "Running deploy task 'remove_toplevel_communes'"
+
+ communes = Champs::CommuneChamp.where(external_id: ['75056', '13055', '69123'])
+ progress = ProgressReport.new(communes.count)
+
+ communes.find_each do |commune|
+ external_id = case commune.external_id
+ when '75056'
+ '75101'
+ when '13055'
+ '13201'
+ when '69123'
+ '69381'
+ end
+ commune.update_columns(external_id:, value: APIGeoService.commune_name(commune.code_departement, external_id))
+ progress.inc
+ end
+ progress.finish
+
+ # Update task as completed. If you remove the line below, the task will
+ # run with every deploy (or every time you call after_party:run).
+ AfterParty::TaskRecord
+ .create version: AfterParty::TaskRecorder.new(__FILE__).timestamp
+ end
+end
diff --git a/spec/components/simple_format_component_spec.rb b/spec/components/simple_format_component_spec.rb
index dc6cf6cbbff..97c30adee43 100644
--- a/spec/components/simple_format_component_spec.rb
+++ b/spec/components/simple_format_component_spec.rb
@@ -47,11 +47,61 @@
<<~TEXT
1. 1er paragraphe
2. paragraphe
+ 4. 4eme paragraphe
TEXT
end
it { expect(page).to have_selector("ol", count: 1) }
- it { expect(page).to have_selector("li", count: 2) }
+ it { expect(page).to have_selector("li", count: 3) }
+ # pf numbering doesn't respect 4 and produce 1,2,3
+ # it { expect(page.native.inner_html).to match('value="1"') }
+ # it { expect(page.native.inner_html).to match('value="4"') }
+ end
+
+ context 'multi line lists' do
+ # pf creates paragraphs when it is not indented under a list item.
+ let(:text) do
+ <<~TEXT
+ Lorsque nous souhaitons envoyer ce message :
+
+ 1. Premier point de la recette
+ Commentaire 1
+ 2. Deuxième point de la recette
+ Commentaire 2
+
+ 4. Troisième point de la recette
+ Commentaire 3
+
+ trois nouveaux paragraphes
+ sur plusieures
+ lignes
+
+ - 1er point de la recette
+ * 2eme point de la recette
+ avec des détailles
+ + 3eme point de la recette
+ beaucoup
+ de détails
+
+ conclusion
+ TEXT
+ end
+
+ it { expect(page).to have_selector("ol", count: 1) }
+ it { expect(page).to have_selector("ul", count: 1) }
+ it { expect(page).to have_selector("li", count: 6) }
+ it { expect(page).to have_selector("p", count: 6) }
+ end
+
+ context 'strong' do
+ let(:text) do
+ <<~TEXT
+ 1er paragraphe **fort** un_mot_pas_italic
+ TEXT
+ end
+
+ it { expect(page).to have_selector("strong", count: 1) }
+ it { expect(page).not_to have_selector("em") }
end
context 'auto-link' do
diff --git a/spec/controllers/administrateurs/procedures_controller_spec.rb b/spec/controllers/administrateurs/procedures_controller_spec.rb
index 713f67fdcba..fef25a74cec 100644
--- a/spec/controllers/administrateurs/procedures_controller_spec.rb
+++ b/spec/controllers/administrateurs/procedures_controller_spec.rb
@@ -298,7 +298,7 @@
let(:service_2) { create(:service, nom: 'DDT du Loiret') }
let!(:procedure_with_service_1) { create(:procedure_with_dossiers, :published, organisation: nil, service: service_1, dossiers_count: 2) }
let!(:procedure_with_service_2) { create(:procedure_with_dossiers, :published, organisation: nil, service: service_2, dossiers_count: 2) }
- let!(:procedure_without_service) { create(:procedure_with_dossiers, :published, organisation: 'DDT du Loiret', dossiers_count: 2) }
+ let!(:procedure_without_service) { create(:procedure_with_dossiers, :published, service: nil, organisation: 'DDT du Loiret', dossiers_count: 2) }
it 'groups procedures with services as well as procedures with organisations' do
expect(grouped_procedures.length).to eq 2
diff --git a/spec/controllers/administrateurs/services_controller_spec.rb b/spec/controllers/administrateurs/services_controller_spec.rb
index f2cbcbedf6d..56f487e237d 100644
--- a/spec/controllers/administrateurs/services_controller_spec.rb
+++ b/spec/controllers/administrateurs/services_controller_spec.rb
@@ -157,4 +157,36 @@ def post_add_to_procedure
it { expect(procedure.reload.service_id).to be_nil }
end
end
+
+ describe "#index" do
+ let(:admin) { create(:administrateur) }
+
+ before do
+ sign_in(admin.user)
+ end
+
+ context 'when admin has service without siret' do
+ let(:service) { create(:service) }
+ let(:procedure) { create(:procedure, :published, service: service, administrateur: admin) }
+
+ it 'display alert when admin has service without siret' do
+ service.siret = nil
+ service.save(validate: false)
+ get :index, params: { procedure_id: procedure.id }
+ expect(flash.alert.first).to eq "Vous n’avez pas renseigné le siret du service pour certaines de vos démarches. Merci de les modifier."
+ expect(flash.alert.last).to include(service.nom)
+ end
+ end
+
+ context 'when admin has procedure without service' do
+ let(:procedure) { create(:procedure, :published, service: nil, administrateur: admin) }
+
+ it 'display alert' do
+ get :index, params: { procedure_id: procedure.id }
+ expect(procedure.service).to be nil
+ expect(flash.alert.first).to eq "Certaines de vos démarches n’ont pas de service associé."
+ expect(flash.alert.last).to include "démarche #{procedure.id}"
+ end
+ end
+ end
end
diff --git a/spec/factories/procedure.rb b/spec/factories/procedure.rb
index 2da0618334e..42a9234c5dd 100644
--- a/spec/factories/procedure.rb
+++ b/spec/factories/procedure.rb
@@ -327,6 +327,7 @@
unpublished_at { nil }
closed_at { nil }
zones { [association(:zone, strategy: :build)] }
+ service { association :service, administrateur: administrateurs.first }
end
trait :closed do
diff --git a/spec/lib/api_entreprise/api_spec.rb b/spec/lib/api_entreprise/api_spec.rb
index 19a7f85c6de..20d90da1baf 100644
--- a/spec/lib/api_entreprise/api_spec.rb
+++ b/spec/lib/api_entreprise/api_spec.rb
@@ -95,10 +95,23 @@
end
context 'with a service with siret' do
- let(:procedure) { create(:procedure, :with_service) }
- it 'send default recipient' do
- subject
- expect(WebMock).to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v3\/insee\/sirene\/unites_legales\/#{siren}/).with(query: hash_including({ recipient: procedure.service.siret }))
+ context 'with a siren entreprise not equivalent to siret service' do
+ let(:procedure) { create(:procedure, :with_service) }
+ it 'send default recipient' do
+ subject
+ expect(WebMock).to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v3\/insee\/sirene\/unites_legales\/#{siren}/).with(query: hash_including({ recipient: procedure.service.siret }))
+ end
+ end
+
+ context 'with a siren entreprise equivalent to siret service' do
+ let(:procedure) { create(:procedure, :with_service) }
+ let(:siren) { procedure.service.siret[0..8] }
+ let(:dinum_siret) { "13002526500013" }
+ it 'send default recipient' do
+ ENV["API_ENTREPRISE_DEFAULT_SIRET"] = dinum_siret
+ subject
+ expect(WebMock).to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v3\/insee\/sirene\/unites_legales\/#{siren}/).with(query: hash_including({ recipient: dinum_siret }))
+ end
end
end
end
diff --git a/spec/models/concern/dossier_clone_concern_spec.rb b/spec/models/concern/dossier_clone_concern_spec.rb
index 4d9f35d42eb..aa8b31481ce 100644
--- a/spec/models/concern/dossier_clone_concern_spec.rb
+++ b/spec/models/concern/dossier_clone_concern_spec.rb
@@ -207,6 +207,26 @@
# rubocop:enable Lint/BooleanSymbol
end
+
+ context 'when associated record is invalid' do
+ let(:procedure) do
+ create(:procedure, types_de_champ_public: [
+ { type: :carte, libelle: "Carte", stable_id: 992, mandatory: true }
+ ])
+ end
+
+ before do
+ champ = dossier.champs.find { _1.stable_id == 992 }
+ geo_area = build(:geo_area, champ:, geometry: { "i'm" => "invalid" })
+ geo_area.save!(validate: false)
+ end
+
+ it 'can still fork' do
+ new_dossier.champs.load # load relation so champs are validated below
+
+ expect(new_dossier.champs.find { _1.stable_id == 992 }.geo_areas.first).not_to be_valid
+ end
+ end
end
end
end
diff --git a/spec/services/api_geo_service_spec.rb b/spec/services/api_geo_service_spec.rb
index c17ccc5576a..b3b52300b48 100644
--- a/spec/services/api_geo_service_spec.rb
+++ b/spec/services/api_geo_service_spec.rb
@@ -47,9 +47,9 @@
describe 'communes_by_postal_code' do
it 'return results' do
expect(APIGeoService.communes_by_postal_code('01500').size).to eq(8)
- expect(APIGeoService.communes_by_postal_code('75019').size).to eq(2)
- expect(APIGeoService.communes_by_postal_code('69005').size).to eq(2)
- expect(APIGeoService.communes_by_postal_code('13006').size).to eq(2)
+ expect(APIGeoService.communes_by_postal_code('75019').size).to eq(1)
+ expect(APIGeoService.communes_by_postal_code('69005').size).to eq(1)
+ expect(APIGeoService.communes_by_postal_code('13006').size).to eq(1)
expect(APIGeoService.communes_by_postal_code('73480').size).to eq(3)
expect(APIGeoService.communes_by_postal_code('20000').first[:code]).to eq('2A004')
expect(APIGeoService.communes_by_postal_code('37160').size).to eq(7)
diff --git a/spec/system/users/brouillon_spec.rb b/spec/system/users/brouillon_spec.rb
index 6dc80a5b031..410b2f0b5b7 100644
--- a/spec/system/users/brouillon_spec.rb
+++ b/spec/system/users/brouillon_spec.rb
@@ -431,7 +431,7 @@
let(:procedure) do
create(:procedure, :published, :for_individual,
types_de_champ_public: [
- { type: :integer_number, libelle: 'age', stable_id: age_stable_id },
+ { type: :integer_number, libelle: 'age du candidat', stable_id: age_stable_id },
{ type: :yes_no, libelle: 'permis de conduire', stable_id: permis_stable_id, condition: permis_condition },
{ type: :header_section, libelle: 'info voiture', condition: permis_condition },
{ type: :integer_number, libelle: 'tonnage', stable_id: tonnage_stable_id, condition: tonnage_condition },
@@ -444,12 +444,12 @@
fill_individual
- expect(page).to have_css('label', text: 'age', visible: true)
+ expect(page).to have_css('label', text: 'age du candidat', visible: true)
expect(page).to have_no_css('label', text: 'permis de conduire', visible: true)
expect(page).to have_no_css('legend h2', text: 'info voiture', visible: true)
expect(page).to have_no_css('label', text: 'tonnage', visible: true)
- fill_in('age (facultatif)', with: '18')
+ fill_in('age du candidat (facultatif)', with: '18')
expect(page).to have_css('label', text: 'permis de conduire', visible: true)
expect(page).to have_css('legend h2', text: 'info voiture', visible: true)
expect(page).to have_no_css('label', text: 'tonnage', visible: true)
@@ -465,7 +465,7 @@
fill_in('tonnage (facultatif)', with: 'a')
expect(page).to have_no_css('label', text: 'parking', visible: true)
- fill_in('age (facultatif)', with: '2')
+ fill_in('age du candidat (facultatif)', with: '2')
expect(page).to have_no_css('label', text: 'permis de conduire', visible: true)
expect(page).to have_no_css('label', text: 'tonnage', visible: true)
@@ -473,11 +473,11 @@
click_on 'Accéder à votre dossier'
click_on 'Modifier mon dossier'
- expect(page).to have_css('label', text: 'age', visible: true)
+ expect(page).to have_css('label', text: 'age du candidat', visible: true)
expect(page).to have_no_css('label', text: 'permis de conduire', visible: true)
expect(page).to have_no_css('label', text: 'tonnage', visible: true)
- fill_in('age (facultatif)', with: '18')
+ fill_in('age du candidat (facultatif)', with: '18')
wait_for_autosave(false)
# the champ keeps their previous value so they are all displayed