diff --git a/app/assets/javascripts/new_design/champs/siret.js b/app/assets/javascripts/new_design/champs/siret.js new file mode 100644 index 000000000..8904b05a6 --- /dev/null +++ b/app/assets/javascripts/new_design/champs/siret.js @@ -0,0 +1,27 @@ +document.addEventListener('turbolinks:load', function() { + $('[data-siret]').on('input', function(evt) { + var input = $(evt.target); + var value = input.val(); + var url = input.attr('data-siret'); + switch (value.length) { + case 0: + $.get(url+'?siret=blank'); + break; + case 14: + input.attr('disabled', 'disabled'); + $.get(url+'?siret='+value).then(function() { + input.removeAttr('data-invalid'); + input.removeAttr('disabled'); + }, function() { + input.removeAttr('disabled'); + input.attr('data-invalid', true); + }); + break; + default: + if (!input.attr('data-invalid')) { + input.attr('data-invalid', true); + $.get(url+'?siret=invalid'); + } + } + }); +}); diff --git a/app/assets/stylesheets/new_design/forms.scss b/app/assets/stylesheets/new_design/forms.scss index 17ef315f6..8c5191313 100644 --- a/app/assets/stylesheets/new_design/forms.scss +++ b/app/assets/stylesheets/new_design/forms.scss @@ -48,6 +48,10 @@ .updated-at.highlighted { visibility: visible; } + + .etablissement-titre { + margin-bottom: 2 * $default-padding; + } } .radios { @@ -82,6 +86,10 @@ &.small { padding: $default-padding / 2; } + + &.small-margin { + margin-bottom: $default-padding / 2; + } } input[type=text], diff --git a/app/controllers/champs/siret_controller.rb b/app/controllers/champs/siret_controller.rb new file mode 100644 index 000000000..b1fb41b55 --- /dev/null +++ b/app/controllers/champs/siret_controller.rb @@ -0,0 +1,29 @@ +class Champs::SiretController < ApplicationController + def index + siret, champ_id = params.required([:siret, :champ_id]) + @champ = Champs::SiretChamp.find(champ_id) + @etablissement = @champ.etablissement + if siret == 'blank' + if @etablissement + @etablissement.mark_for_destruction + end + @blank = true + elsif siret == 'invalid' + if @etablissement + @etablissement.mark_for_destruction + end + @error = "SIRET invalide" + else + etablissement_attributes = SIRETService.fetch(siret, @champ.dossier.procedure_id) + if etablissement_attributes.present? + @etablissement = @champ.build_etablissement(etablissement_attributes) + @etablissement.champ = @champ + else + @error = "SIRET invalide" + end + end + respond_to do |format| + format.js + end + end +end diff --git a/app/controllers/new_gestionnaire/dossiers_controller.rb b/app/controllers/new_gestionnaire/dossiers_controller.rb index e978a348c..2cfb23257 100644 --- a/app/controllers/new_gestionnaire/dossiers_controller.rb +++ b/app/controllers/new_gestionnaire/dossiers_controller.rb @@ -198,7 +198,10 @@ module NewGestionnaire end def champs_private_params - params.require(:dossier).permit(champs_private_attributes: [:id, :piece_justificative_file, :value, value: []]) + params.require(:dossier).permit(champs_private_attributes: [ + :id, :piece_justificative_file, :value, value: [], + etablissement_attributes: Champs::SiretChamp::ETABLISSEMENT_ATTRIBUTES + ]) end def check_attestation_emailable diff --git a/app/controllers/new_user/dossiers_controller.rb b/app/controllers/new_user/dossiers_controller.rb index b4501c8e6..b0a63fb8a 100644 --- a/app/controllers/new_user/dossiers_controller.rb +++ b/app/controllers/new_user/dossiers_controller.rb @@ -116,7 +116,12 @@ module NewUser # FIXME: require(:dossier) when all the champs are united def champs_params - params.permit(dossier: { champs_attributes: [:id, :value, :piece_justificative_file, value: []] }) + params.permit(dossier: { + champs_attributes: [ + :id, :value, :piece_justificative_file, value: [], + etablissement_attributes: Champs::SiretChamp::ETABLISSEMENT_ATTRIBUTES + ] + }) end def dossier diff --git a/app/helpers/type_de_champ_helper.rb b/app/helpers/type_de_champ_helper.rb index f91158bf6..12bb3674a 100644 --- a/app/helpers/type_de_champ_helper.rb +++ b/app/helpers/type_de_champ_helper.rb @@ -6,6 +6,10 @@ module TypeDeChampHelper tdcs.reject! { |tdc| tdc.last == "piece_justificative" } end + if !current_administrateur.feature_enabled?(:champ_siret_allowed) + tdcs.reject! { |tdc| tdc.last == "siret" } + end + tdcs end end diff --git a/app/models/champs/siret_champ.rb b/app/models/champs/siret_champ.rb index 91e237032..0a55edb32 100644 --- a/app/models/champs/siret_champ.rb +++ b/app/models/champs/siret_champ.rb @@ -1,4 +1,42 @@ class Champs::SiretChamp < Champ + ETABLISSEMENT_ATTRIBUTES = [ + :id, + :_destroy, + :signature, + :siret, + :siege_social, + :naf, + :libelle_naf, + :adresse, + :numero_voie, + :type_voie, + :nom_voie, + :code_postal, + :localite, + :code_insee_localite, + :entreprise_siren, + :entreprise_capital_social, + :entreprise_numero_tva_intracommunautaire, + :entreprise_forme_juridique, + :entreprise_forme_juridique_code, + :entreprise_nom_commercial, + :entreprise_raison_sociale, + :entreprise_siret_siege_social, + :entreprise_code_effectif_entreprise, + :entreprise_date_creation, + :entreprise_nom, + :entreprise_prenom, + :association_rna, + :association_titre, + :association_objet, + :association_date_creation, + :association_date_declaration, + :association_date_publication, + exercices_attributes: [ + [:id, :ca, :date_fin_exercice, :date_fin_exercice_timestamp] + ] + ] + belongs_to :etablissement, dependent: :destroy accepts_nested_attributes_for :etablissement, allow_destroy: true, update_only: true end diff --git a/app/models/etablissement.rb b/app/models/etablissement.rb index af9c0a2a4..840e1aed5 100644 --- a/app/models/etablissement.rb +++ b/app/models/etablissement.rb @@ -8,7 +8,10 @@ class Etablissement < ApplicationRecord accepts_nested_attributes_for :exercices accepts_nested_attributes_for :entreprise, update_only: true - validates :dossier_id, uniqueness: true + validates :siret, presence: true + validates :dossier_id, uniqueness: { allow_nil: true } + + validate :validate_signature def geo_adresse [numero_voie, type_voie, nom_voie, complement_adresse, code_postal, localite].join(' ') @@ -18,6 +21,11 @@ class Etablissement < ApplicationRecord # squeeze needed because of space in excess in the data "#{numero_voie} #{type_voie} #{nom_voie}, #{complement_adresse}, #{code_postal} #{localite}".squeeze(' ') end + + def titre + entreprise_raison_sociale || association_titre + end + def verify SignatureService.verify(signature, message_for_signature) end @@ -28,6 +36,14 @@ class Etablissement < ApplicationRecord attr_accessor :signature + private + + def validate_signature + if champ && !verify + errors.add(:base, 'Numéro SIRET introuvable.') + end + end + def message_for_signature JSON.pretty_generate(as_json(include: { exercices: { only: [:ca, :date_fin_exercice, :date_fin_exercice_timestamp] } diff --git a/app/models/type_de_champ.rb b/app/models/type_de_champ.rb index a10e445a7..ca90df71c 100644 --- a/app/models/type_de_champ.rb +++ b/app/models/type_de_champ.rb @@ -20,7 +20,8 @@ class TypeDeChamp < ApplicationRecord header_section: 'header_section', explication: 'explication', dossier_link: 'dossier_link', - piece_justificative: 'piece_justificative' + piece_justificative: 'piece_justificative', + siret: 'siret' } belongs_to :procedure diff --git a/app/views/champs/siret/index.js.erb b/app/views/champs/siret/index.js.erb new file mode 100644 index 000000000..899f52440 --- /dev/null +++ b/app/views/champs/siret/index.js.erb @@ -0,0 +1,8 @@ +(function() { + <% if @blank || @error %> + var html = "<%= escape_javascript(render partial: 'shared/champs/siret/delete_etablissement', locals: { message: @error, position: @champ.order_place, etablissement: @etablissement }) %>"; + <% else %> + var html = "<%= escape_javascript(render partial: 'shared/champs/siret/etablissement', locals: { position: @champ.order_place, etablissement: @etablissement }) %>"; + <% end %> + $("#etablissement-for-<%= @champ.id %>").html(html); +})(); diff --git a/app/views/shared/champs/siret/_delete_etablissement.html.haml b/app/views/shared/champs/siret/_delete_etablissement.html.haml new file mode 100644 index 000000000..279c69c2c --- /dev/null +++ b/app/views/shared/champs/siret/_delete_etablissement.html.haml @@ -0,0 +1,6 @@ += message +- if etablissement.present? + - champ_attributes = etablissement.champ.private? ? 'champs_private_attributes' : 'champs_attributes' + = fields_for "dossier[#{champ_attributes}][#{position}][etablissement_attributes]", etablissement do |form| + = form.hidden_field :_destroy + diff --git a/app/views/shared/champs/siret/_etablissement.html.haml b/app/views/shared/champs/siret/_etablissement.html.haml new file mode 100644 index 000000000..893a5ef2a --- /dev/null +++ b/app/views/shared/champs/siret/_etablissement.html.haml @@ -0,0 +1,4 @@ += render partial: 'shared/dossiers/editable_champs/etablissement_titre', locals: { etablissement: etablissement } +- champ_attributes = etablissement.champ.private? ? 'champs_private_attributes' : 'champs_attributes' += fields_for "dossier[#{champ_attributes}][#{position}][etablissement_attributes]", etablissement do |form| + = render partial: 'shared/dossiers/editable_champs/etablissement', locals: { form: form, signature: etablissement.sign } diff --git a/app/views/shared/dossiers/editable_champs/_etablissement.html.haml b/app/views/shared/dossiers/editable_champs/_etablissement.html.haml new file mode 100644 index 000000000..81d5baac9 --- /dev/null +++ b/app/views/shared/dossiers/editable_champs/_etablissement.html.haml @@ -0,0 +1,34 @@ += form.hidden_field :signature, value: signature += form.hidden_field :siret += form.hidden_field :siege_social += form.hidden_field :naf += form.hidden_field :libelle_naf += form.hidden_field :adresse += form.hidden_field :numero_voie += form.hidden_field :type_voie += form.hidden_field :nom_voie += form.hidden_field :code_postal += form.hidden_field :localite += form.hidden_field :code_insee_localite += form.hidden_field :entreprise_siren += form.hidden_field :entreprise_capital_social += form.hidden_field :entreprise_numero_tva_intracommunautaire += form.hidden_field :entreprise_forme_juridique += form.hidden_field :entreprise_forme_juridique_code += form.hidden_field :entreprise_nom_commercial += form.hidden_field :entreprise_raison_sociale += form.hidden_field :entreprise_siret_siege_social += form.hidden_field :entreprise_code_effectif_entreprise += form.hidden_field :entreprise_date_creation += form.hidden_field :entreprise_nom += form.hidden_field :entreprise_prenom += form.hidden_field :association_rna += form.hidden_field :association_titre += form.hidden_field :association_objet += form.hidden_field :association_date_creation += form.hidden_field :association_date_declaration += form.hidden_field :association_date_publication += form.fields_for :exercices do |form| + = form.hidden_field :ca + = form.hidden_field :date_fin_exercice + = form.hidden_field :date_fin_exercice_timestamp diff --git a/app/views/shared/dossiers/editable_champs/_etablissement_titre.html.haml b/app/views/shared/dossiers/editable_champs/_etablissement_titre.html.haml new file mode 100644 index 000000000..b63734321 --- /dev/null +++ b/app/views/shared/dossiers/editable_champs/_etablissement_titre.html.haml @@ -0,0 +1,6 @@ +.etablissement-titre + = etablissement.titre + = etablissement.entreprise_forme_juridique + - if etablissement.entreprise_capital_social.present? + au capital social de + = number_to_currency(etablissement.entreprise_capital_social) diff --git a/app/views/shared/dossiers/editable_champs/_siret.html.haml b/app/views/shared/dossiers/editable_champs/_siret.html.haml new file mode 100644 index 000000000..2135b274f --- /dev/null +++ b/app/views/shared/dossiers/editable_champs/_siret.html.haml @@ -0,0 +1,10 @@ += form.text_field :value, + placeholder: champ.libelle, + class: 'small-margin', + data: { siret: champs_siret_path(format: :js, champ_id: champ) }, + required: champ.mandatory? +%div{ id: "etablissement-for-#{champ.id}" } + - if champ.etablissement.present? + = render partial: 'shared/dossiers/editable_champs/etablissement_titre', locals: { etablissement: champ.etablissement } + = form.fields_for :etablissement do |form| + = render partial: 'shared/dossiers/editable_champs/etablissement', locals: { form: form, signature: champ.etablissement.sign } diff --git a/config/initializers/features.yml b/config/initializers/features.yml index b0210bbe9..a7b150256 100644 --- a/config/initializers/features.yml +++ b/config/initializers/features.yml @@ -2,3 +2,5 @@ remote_storage: false weekly_overview: false champ_pj_allowed_for_admin_ids: - 0 +champ_siret_allowed_for_admin_ids: + - 0 diff --git a/config/routes.rb b/config/routes.rb index b2cb6bea7..901dd75cb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -72,6 +72,10 @@ Rails.application.routes.draw do get 'particulier/callback' => 'particulier#callback' end + namespace :champs do + get ':champ_id/siret' => 'siret#index', as: 'siret' + end + namespace :users do namespace :dossiers do resources :invites, only: [:index, :show] diff --git a/spec/controllers/new_user/dossiers_controller_spec.rb b/spec/controllers/new_user/dossiers_controller_spec.rb index 0b4645124..af8dfd898 100644 --- a/spec/controllers/new_user/dossiers_controller_spec.rb +++ b/spec/controllers/new_user/dossiers_controller_spec.rb @@ -235,7 +235,7 @@ describe NewUser::DossiersController, type: :controller do context 'when the update fails' do before do - expect_any_instance_of(Dossier).to receive(:update).and_return(false) + expect_any_instance_of(Dossier).to receive(:save).and_return(false) expect_any_instance_of(Dossier).to receive(:errors) .and_return(double(full_messages: ['nop']))