Merge pull request #7585 from betagouv/feat-services-with-siret
feat(services): add siret + geoloc
This commit is contained in:
commit
05dfc93b7e
41 changed files with 634 additions and 128 deletions
|
@ -74,7 +74,7 @@ module Administrateurs
|
|||
private
|
||||
|
||||
def service_params
|
||||
params.require(:service).permit(:nom, :organisme, :type_organisme, :email, :telephone, :horaires, :adresse)
|
||||
params.require(:service).permit(:nom, :organisme, :type_organisme, :email, :telephone, :horaires, :adresse, :siret)
|
||||
end
|
||||
|
||||
def service
|
||||
|
|
|
@ -18,7 +18,10 @@ class ServiceDashboard < Administrate::BaseDashboard
|
|||
email: Field::String,
|
||||
telephone: Field::String,
|
||||
horaires: Field::String,
|
||||
adresse: Field::String
|
||||
adresse: Field::String,
|
||||
siret: Field::String,
|
||||
etablissement_adresse: Field::String.with_options(searchable: false),
|
||||
etablissement_latlng: GeopointField
|
||||
}.freeze
|
||||
|
||||
# COLLECTION_ATTRIBUTES
|
||||
|
@ -44,7 +47,10 @@ class ServiceDashboard < Administrate::BaseDashboard
|
|||
:email,
|
||||
:telephone,
|
||||
:horaires,
|
||||
:adresse
|
||||
:adresse,
|
||||
:siret,
|
||||
:etablissement_adresse,
|
||||
:etablissement_latlng
|
||||
].freeze
|
||||
|
||||
# FORM_ATTRIBUTES
|
||||
|
|
15
app/fields/geopoint_field.rb
Normal file
15
app/fields/geopoint_field.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
require "administrate/field/base"
|
||||
|
||||
class GeopointField < Administrate::Field::Base
|
||||
def lat
|
||||
data.first
|
||||
end
|
||||
|
||||
def lng
|
||||
data.last
|
||||
end
|
||||
|
||||
def present?
|
||||
lat.present? && lng.present?
|
||||
end
|
||||
end
|
|
@ -1990,6 +1990,7 @@ type Service {
|
|||
id: ID!
|
||||
nom: String!
|
||||
organisme: String!
|
||||
siret: String
|
||||
typeOrganisme: TypeOrganisme!
|
||||
}
|
||||
|
||||
|
|
|
@ -11,5 +11,6 @@ module Types
|
|||
field :nom, String, null: false
|
||||
field :type_organisme, TypeOrganisme, null: false
|
||||
field :organisme, String, null: false
|
||||
field :siret, String, null: true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -90,7 +90,7 @@ module DossierHelper
|
|||
l(dossier.expiration_date, format: '%d/%m/%Y')
|
||||
end
|
||||
|
||||
def annuaire_link(siren)
|
||||
def annuaire_link(siren = nil)
|
||||
base_url = "https://annuaire-entreprises.data.gouv.fr"
|
||||
return base_url if siren.blank?
|
||||
"#{base_url}/entreprise/#{siren}"
|
||||
|
|
15
app/jobs/api_entreprise/service_job.rb
Normal file
15
app/jobs/api_entreprise/service_job.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
class APIEntreprise::ServiceJob < APIEntreprise::Job
|
||||
def perform(service_id)
|
||||
service = Service.find(service_id)
|
||||
|
||||
service_params = APIEntreprise::ServiceAdapter.new(service.siret, service_id).to_params
|
||||
service.etablissement_infos = service_params
|
||||
|
||||
point = Geocoder.search(service_params[:adresse]).first
|
||||
|
||||
service.etablissement_lat = point&.latitude
|
||||
service.etablissement_lng = point&.longitude
|
||||
|
||||
service.save!
|
||||
end
|
||||
end
|
|
@ -6,6 +6,10 @@ class APIEntreprise::Adapter
|
|||
@procedure_id = procedure_id
|
||||
end
|
||||
|
||||
def api(procedure_id = nil)
|
||||
APIEntreprise::API.new(procedure_id)
|
||||
end
|
||||
|
||||
def data_source
|
||||
begin
|
||||
@data_source ||= get_resource
|
||||
|
|
|
@ -13,54 +13,77 @@ class APIEntreprise::API
|
|||
TIMEOUT = 20
|
||||
DEFAULT_API_ENTREPRISE_DELAY = 0.0
|
||||
|
||||
def self.entreprise(siren, procedure_id)
|
||||
call_with_siret(ENTREPRISE_RESOURCE_NAME, siren, procedure_id)
|
||||
attr_reader :procedure
|
||||
attr_accessor :token
|
||||
attr_accessor :api_object
|
||||
|
||||
def initialize(procedure_id = nil)
|
||||
return if procedure_id.blank?
|
||||
|
||||
@procedure = Procedure.find(procedure_id)
|
||||
@token = @procedure.api_entreprise_token
|
||||
end
|
||||
|
||||
def self.etablissement(siret, procedure_id)
|
||||
call_with_siret(ETABLISSEMENT_RESOURCE_NAME, siret, procedure_id)
|
||||
def entreprise(siren)
|
||||
call_with_siret(ENTREPRISE_RESOURCE_NAME, siren)
|
||||
end
|
||||
|
||||
def self.exercices(siret, procedure_id)
|
||||
call_with_siret(EXERCICES_RESOURCE_NAME, siret, procedure_id)
|
||||
def etablissement(siret)
|
||||
call_with_siret(ETABLISSEMENT_RESOURCE_NAME, siret)
|
||||
end
|
||||
|
||||
def self.rna(siret, procedure_id)
|
||||
call_with_siret(RNA_RESOURCE_NAME, siret, procedure_id)
|
||||
def exercices(siret)
|
||||
call_with_siret(EXERCICES_RESOURCE_NAME, siret)
|
||||
end
|
||||
|
||||
def self.effectifs(siren, procedure_id, annee, mois)
|
||||
def rna(siret)
|
||||
call_with_siret(RNA_RESOURCE_NAME, siret)
|
||||
end
|
||||
|
||||
def effectifs(siren, annee, mois)
|
||||
endpoint = [EFFECTIFS_RESOURCE_NAME, annee, mois, "entreprise"].join('/')
|
||||
call_with_siret(endpoint, siren, procedure_id)
|
||||
call_with_siret(endpoint, siren)
|
||||
end
|
||||
|
||||
def self.effectifs_annuels(siren, procedure_id)
|
||||
call_with_siret(EFFECTIFS_ANNUELS_RESOURCE_NAME, siren, procedure_id)
|
||||
def effectifs_annuels(siren)
|
||||
call_with_siret(EFFECTIFS_ANNUELS_RESOURCE_NAME, siren)
|
||||
end
|
||||
|
||||
def self.attestation_sociale(siren, procedure_id)
|
||||
procedure = Procedure.find(procedure_id)
|
||||
call_with_siret(ATTESTATION_SOCIALE_RESOURCE_NAME, siren, procedure_id) if procedure.api_entreprise_role?("attestations_sociales")
|
||||
def attestation_sociale(siren)
|
||||
return unless procedure.api_entreprise_role?("attestations_sociales")
|
||||
|
||||
call_with_siret(ATTESTATION_SOCIALE_RESOURCE_NAME, siren)
|
||||
end
|
||||
|
||||
def self.attestation_fiscale(siren, procedure_id, user_id)
|
||||
procedure = Procedure.find(procedure_id)
|
||||
call_with_siret(ATTESTATION_FISCALE_RESOURCE_NAME, siren, procedure_id, user_id) if procedure.api_entreprise_role?("attestations_fiscales")
|
||||
def attestation_fiscale(siren, user_id)
|
||||
return unless procedure.api_entreprise_role?("attestations_fiscales")
|
||||
|
||||
call_with_siret(ATTESTATION_FISCALE_RESOURCE_NAME, siren, user_id: user_id)
|
||||
end
|
||||
|
||||
def self.bilans_bdf(siren, procedure_id)
|
||||
procedure = Procedure.find(procedure_id)
|
||||
call_with_siret(BILANS_BDF_RESOURCE_NAME, siren, procedure_id) if procedure.api_entreprise_role?("bilans_entreprise_bdf")
|
||||
def bilans_bdf(siren)
|
||||
return unless procedure.api_entreprise_role?("bilans_entreprise_bdf")
|
||||
|
||||
call_with_siret(BILANS_BDF_RESOURCE_NAME, siren)
|
||||
end
|
||||
|
||||
def self.privileges(token)
|
||||
call_with_token(PRIVILEGES_RESOURCE_NAME, token)
|
||||
def privileges
|
||||
url = make_url(PRIVILEGES_RESOURCE_NAME)
|
||||
call(url)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.call_with_token(resource_name, token)
|
||||
url = "#{API_ENTREPRISE_URL}/#{resource_name}"
|
||||
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)
|
||||
|
||||
call(url, params)
|
||||
end
|
||||
|
||||
def call(url, params = nil)
|
||||
verify_token!
|
||||
|
||||
# this is a poor man throttling
|
||||
# the idea is to queue api entreprise job on 1 worker
|
||||
|
@ -72,32 +95,13 @@ class APIEntreprise::API
|
|||
|
||||
response = Typhoeus.get(url,
|
||||
headers: { Authorization: "Bearer #{token}" },
|
||||
timeout: TIMEOUT)
|
||||
|
||||
if response.success?
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
else
|
||||
raise RequestFailed.new(response)
|
||||
end
|
||||
end
|
||||
|
||||
def self.call_with_siret(resource_name, siret_or_siren, procedure_id, user_id = nil)
|
||||
if APIEntrepriseToken.new(token_for_procedure(procedure_id)).expired?
|
||||
raise APIEntrepriseToken::TokenError, I18n.t("api_entreprise.errors.token_expired")
|
||||
end
|
||||
|
||||
url = url(resource_name, siret_or_siren)
|
||||
params = params(siret_or_siren, procedure_id, user_id)
|
||||
|
||||
if api_entreprise_delay != 0.0
|
||||
sleep api_entreprise_delay
|
||||
end
|
||||
|
||||
response = Typhoeus.get(url,
|
||||
headers: { Authorization: "Bearer #{token_for_procedure(procedure_id)}" },
|
||||
params: params,
|
||||
timeout: TIMEOUT)
|
||||
|
||||
handle_response(response)
|
||||
end
|
||||
|
||||
def handle_response(response)
|
||||
if response.success?
|
||||
JSON.parse(response.body, symbolize_names: true)
|
||||
elsif response.code&.between?(401, 499)
|
||||
|
@ -115,29 +119,41 @@ class APIEntreprise::API
|
|||
end
|
||||
end
|
||||
|
||||
def self.url(resource_name, siret_or_siren)
|
||||
[API_ENTREPRISE_URL, resource_name, siret_or_siren].join("/")
|
||||
def make_url(resource_name, siret_or_siren = nil)
|
||||
[API_ENTREPRISE_URL, resource_name, siret_or_siren].compact.join("/")
|
||||
end
|
||||
|
||||
def self.params(siret_or_siren, procedure_id, user_id)
|
||||
# rubocop:disable DS/ApplicationName
|
||||
params = {
|
||||
context: "demarches-simplifiees.fr",
|
||||
recipient: ENV.fetch('API_ENTREPRISE_DEFAULT_SIRET'),
|
||||
object: "procedure_id: #{procedure_id}",
|
||||
non_diffusables: true
|
||||
}
|
||||
# rubocop:enable DS/ApplicationName
|
||||
def build_params(user_id)
|
||||
params = base_params
|
||||
|
||||
params[:object] = if api_object.present?
|
||||
api_object
|
||||
elsif procedure.present?
|
||||
"procedure_id: #{procedure.id}"
|
||||
end
|
||||
|
||||
params[:user_id] = user_id if user_id.present?
|
||||
|
||||
params
|
||||
end
|
||||
|
||||
def self.token_for_procedure(procedure_id)
|
||||
procedure = Procedure.find(procedure_id)
|
||||
procedure.api_entreprise_token
|
||||
def base_params
|
||||
# rubocop:disable DS/ApplicationName
|
||||
{
|
||||
context: "demarches-simplifiees.fr",
|
||||
recipient: ENV.fetch('API_ENTREPRISE_DEFAULT_SIRET'),
|
||||
non_diffusables: true
|
||||
}
|
||||
# rubocop:enable DS/ApplicationName
|
||||
end
|
||||
|
||||
def self.api_entreprise_delay
|
||||
def api_entreprise_delay
|
||||
ENV.fetch("API_ENTREPRISE_DELAY", DEFAULT_API_ENTREPRISE_DELAY).to_f
|
||||
end
|
||||
|
||||
def verify_token!
|
||||
return unless APIEntrepriseToken.new(token).expired?
|
||||
|
||||
raise APIEntrepriseToken::TokenError, I18n.t("api_entreprise.errors.token_expired")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ class APIEntreprise::AttestationFiscaleAdapter < APIEntreprise::Adapter
|
|||
private
|
||||
|
||||
def get_resource
|
||||
APIEntreprise::API.attestation_fiscale(siren, @procedure_id, @user_id)
|
||||
api(@procedure_id).attestation_fiscale(siren, @user_id)
|
||||
end
|
||||
|
||||
def process_params
|
||||
|
|
|
@ -7,7 +7,7 @@ class APIEntreprise::AttestationSocialeAdapter < APIEntreprise::Adapter
|
|||
private
|
||||
|
||||
def get_resource
|
||||
APIEntreprise::API.attestation_sociale(siren, @procedure_id)
|
||||
api(@procedure_id).attestation_sociale(siren)
|
||||
end
|
||||
|
||||
def process_params
|
||||
|
|
|
@ -7,7 +7,7 @@ class APIEntreprise::BilansBdfAdapter < APIEntreprise::Adapter
|
|||
private
|
||||
|
||||
def get_resource
|
||||
APIEntreprise::API.bilans_bdf(siren, @procedure_id)
|
||||
api(@procedure_id).bilans_bdf(siren)
|
||||
end
|
||||
|
||||
def process_params
|
||||
|
|
|
@ -9,7 +9,7 @@ class APIEntreprise::EffectifsAdapter < APIEntreprise::Adapter
|
|||
private
|
||||
|
||||
def get_resource
|
||||
APIEntreprise::API.effectifs(siren, @procedure_id, @annee, @mois)
|
||||
api(@procedure_id).effectifs(siren, @annee, @mois)
|
||||
end
|
||||
|
||||
def process_params
|
||||
|
|
|
@ -7,7 +7,7 @@ class APIEntreprise::EffectifsAnnuelsAdapter < APIEntreprise::Adapter
|
|||
private
|
||||
|
||||
def get_resource
|
||||
APIEntreprise::API.effectifs_annuels(siren, @procedure_id)
|
||||
api(@procedure_id).effectifs_annuels(siren)
|
||||
end
|
||||
|
||||
def process_params
|
||||
|
|
|
@ -2,7 +2,7 @@ class APIEntreprise::EntrepriseAdapter < APIEntreprise::Adapter
|
|||
private
|
||||
|
||||
def get_resource
|
||||
APIEntreprise::API.entreprise(siren, @procedure_id)
|
||||
api(@procedure_id).entreprise(siren)
|
||||
end
|
||||
|
||||
def process_params
|
||||
|
|
|
@ -2,7 +2,7 @@ class APIEntreprise::EtablissementAdapter < APIEntreprise::Adapter
|
|||
private
|
||||
|
||||
def get_resource
|
||||
APIEntreprise::API.etablissement(@siret, @procedure_id)
|
||||
api(@procedure_id).etablissement(@siret)
|
||||
end
|
||||
|
||||
def process_params
|
||||
|
|
|
@ -2,7 +2,7 @@ class APIEntreprise::ExercicesAdapter < APIEntreprise::Adapter
|
|||
private
|
||||
|
||||
def get_resource
|
||||
APIEntreprise::API.exercices(@siret, @procedure_id)
|
||||
api(@procedure_id).exercices(@siret)
|
||||
end
|
||||
|
||||
def process_params
|
||||
|
|
|
@ -15,6 +15,8 @@ class APIEntreprise::PrivilegesAdapter < APIEntreprise::Adapter
|
|||
private
|
||||
|
||||
def get_resource
|
||||
APIEntreprise::API.privileges(@token)
|
||||
api.tap do
|
||||
_1.token = @token
|
||||
end.privileges
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@ class APIEntreprise::RNAAdapter < APIEntreprise::Adapter
|
|||
private
|
||||
|
||||
def get_resource
|
||||
APIEntreprise::API.rna(@siret, @procedure_id)
|
||||
api(@procedure_id).rna(@siret)
|
||||
end
|
||||
|
||||
def process_params
|
||||
|
|
23
app/lib/api_entreprise/service_adapter.rb
Normal file
23
app/lib/api_entreprise/service_adapter.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
class APIEntreprise::ServiceAdapter < APIEntreprise::EtablissementAdapter
|
||||
def initialize(siret, service_id)
|
||||
@siret = siret
|
||||
@service_id = service_id
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_resource
|
||||
api_instance = api
|
||||
# TODO: reuse instead a token from an administrateur's procedure?
|
||||
api_instance.token = Rails.application.secrets.api_entreprise[:key]
|
||||
api_instance.api_object = "service_id: #{@service_id}"
|
||||
api_instance.etablissement(@siret)
|
||||
end
|
||||
|
||||
def attr_to_fetch
|
||||
[
|
||||
:adresse,
|
||||
:siret
|
||||
]
|
||||
end
|
||||
end
|
|
@ -2,17 +2,21 @@
|
|||
#
|
||||
# Table name: services
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# adresse :text
|
||||
# email :string
|
||||
# horaires :text
|
||||
# nom :string not null
|
||||
# organisme :string
|
||||
# telephone :string
|
||||
# type_organisme :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# administrateur_id :bigint
|
||||
# id :bigint not null, primary key
|
||||
# adresse :text
|
||||
# email :string
|
||||
# etablissement_infos :jsonb
|
||||
# etablissement_lat :decimal(10, 6)
|
||||
# etablissement_lng :decimal(10, 6)
|
||||
# horaires :text
|
||||
# nom :string not null
|
||||
# organisme :string
|
||||
# siret :string
|
||||
# telephone :string
|
||||
# type_organisme :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# administrateur_id :bigint
|
||||
#
|
||||
class Service < ApplicationRecord
|
||||
has_many :procedures
|
||||
|
@ -33,6 +37,7 @@ class Service < ApplicationRecord
|
|||
validates :nom, presence: { message: 'doit être renseigné' }, allow_nil: false
|
||||
validates :nom, uniqueness: { scope: :administrateur, message: 'existe déjà' }
|
||||
validates :organisme, presence: { message: 'doit être renseigné' }, allow_nil: false
|
||||
validates :siret, siret_format: true
|
||||
validates :type_organisme, presence: { message: 'doit être renseigné' }, allow_nil: false
|
||||
validates :email, presence: { message: 'doit être renseigné' }, allow_nil: false
|
||||
validates :telephone, phone: { possible: true, allow_blank: true }
|
||||
|
@ -40,6 +45,8 @@ class Service < ApplicationRecord
|
|||
validates :adresse, presence: { message: 'doit être renseignée' }, allow_nil: false
|
||||
validates :administrateur, presence: { message: 'doit être renseigné' }, allow_nil: false
|
||||
|
||||
after_commit :enqueue_api_entreprise, if: -> { siret_previously_changed? }
|
||||
|
||||
def clone_and_assign_to_administrateur(administrateur)
|
||||
service_cloned = self.dup
|
||||
service_cloned.administrateur = administrateur
|
||||
|
@ -51,4 +58,18 @@ class Service < ApplicationRecord
|
|||
"tel:#{telephone.gsub(/[[:blank:]]/, '')}"
|
||||
end
|
||||
end
|
||||
|
||||
def etablissement_adresse
|
||||
etablissement_infos.fetch("adresse", nil)
|
||||
end
|
||||
|
||||
def etablissement_latlng
|
||||
[etablissement_lat, etablissement_lng]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def enqueue_api_entreprise
|
||||
APIEntreprise::ServiceJob.perform_later(self.id)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,4 +6,5 @@ class ServiceSerializer < ActiveModel::Serializer
|
|||
attribute :telephone, key: :phone
|
||||
attribute :horaires, key: :schedule
|
||||
attribute :adresse, key: :address
|
||||
attribute :siret, key: :siret
|
||||
end
|
||||
|
|
|
@ -2,9 +2,7 @@ class SiretFormatValidator < ActiveModel::EachValidator
|
|||
def validate_each(record, attribute, value)
|
||||
if !format_is_valid(value)
|
||||
record.errors.add(attribute, :length)
|
||||
end
|
||||
|
||||
if !luhn_passed(value)
|
||||
elsif !luhn_passed(value)
|
||||
record.errors.add(attribute, :checksum)
|
||||
end
|
||||
end
|
||||
|
@ -14,7 +12,7 @@ class SiretFormatValidator < ActiveModel::EachValidator
|
|||
LA_POSTE_SIREN = '356000000'
|
||||
|
||||
def format_is_valid(value)
|
||||
value.match?(/^\d{14}$/)
|
||||
value&.match?(/^\d{14}$/)
|
||||
end
|
||||
|
||||
def luhn_passed(value)
|
||||
|
|
|
@ -20,6 +20,16 @@
|
|||
|
||||
= f.select :type_organisme, Service.type_organismes.keys.map { |key| [ I18n.t("type_organisme.#{key}"), key] }, class: 'width-33-desktop width-100-mobile'
|
||||
|
||||
= f.label :siret do
|
||||
Numéro SIRET
|
||||
%span.mandatory *
|
||||
|
||||
%p.notice
|
||||
Veuillez saisir le numéro de SIRET de l'organisme dont ce service dépend.
|
||||
%br
|
||||
= link_to "➡ Rechercher le numéro SIRET sur « annuaire-entreprises.data.gouv.fr »", annuaire_link, target: "_blank"
|
||||
|
||||
= f.text_field :siret, placeholder: "14 chiffres", required: true
|
||||
|
||||
= render Dsfr::CalloutComponent.new(title: "Informations de contact") do |c|
|
||||
- c.body do
|
||||
|
|
2
app/views/fields/geopoint_field/_show.html.haml
Normal file
2
app/views/fields/geopoint_field/_show.html.haml
Normal file
|
@ -0,0 +1,2 @@
|
|||
- if field.present?
|
||||
= link_to field.data.join(", "), "https://www.geoportail.gouv.fr/carte?c=#{field.lng},#{field.lat}&z=17&permalink=yes", target: '_blank', rel: 'noopener'
|
|
@ -9,3 +9,11 @@ en:
|
|||
adresse: 'Mail address'
|
||||
email: 'Email'
|
||||
telephone: 'Phone'
|
||||
errors:
|
||||
models:
|
||||
service:
|
||||
attributes:
|
||||
siret:
|
||||
format: "SIRET number %{message}"
|
||||
length: "must contain exactly 14 digits"
|
||||
checksum: "is invalid"
|
||||
|
|
|
@ -9,6 +9,14 @@ fr:
|
|||
adresse: 'Adresse postale'
|
||||
email: 'Email de contact'
|
||||
telephone: 'Téléphone'
|
||||
errors:
|
||||
models:
|
||||
service:
|
||||
attributes:
|
||||
siret:
|
||||
format: "Le numéro SIRET %{message}"
|
||||
length: "doit comporter exactement 14 chiffres"
|
||||
checksum: "est invalide"
|
||||
type_organisme:
|
||||
administration_centrale: 'Administration centrale'
|
||||
association: 'Association'
|
||||
|
|
5
db/migrate/20220718134835_add_siret_to_services.rb
Normal file
5
db/migrate/20220718134835_add_siret_to_services.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddSiretToServices < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
add_column :services, :siret, :string
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
class AddEtablissementInfosToServices < ActiveRecord::Migration[6.1]
|
||||
def up
|
||||
add_column :services, :etablissement_infos, :jsonb
|
||||
add_column :services, :etablissement_lat, :decimal, precision: 10, scale: 6
|
||||
add_column :services, :etablissement_lng, :decimal, precision: 10, scale: 6
|
||||
change_column_default :services, :etablissement_infos, {}
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :services, :etablissement_infos
|
||||
remove_column :services, :etablissement_lat
|
||||
remove_column :services, :etablissement_lng
|
||||
end
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
class BackfillAddEtablissementInfosToServices < ActiveRecord::Migration[6.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
Service.unscoped.in_batches do |relation| # rubocop:disable DS/Unscoped
|
||||
relation.update_all etablissement_infos: {}
|
||||
sleep(0.01)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -706,9 +706,13 @@ ActiveRecord::Schema.define(version: 2022_09_02_151920) do
|
|||
t.text "adresse"
|
||||
t.datetime "created_at", null: false
|
||||
t.string "email"
|
||||
t.jsonb "etablissement_infos", default: {}
|
||||
t.decimal "etablissement_lat", precision: 10, scale: 6
|
||||
t.decimal "etablissement_lng", precision: 10, scale: 6
|
||||
t.text "horaires"
|
||||
t.string "nom", null: false
|
||||
t.string "organisme"
|
||||
t.string "siret"
|
||||
t.string "telephone"
|
||||
t.string "type_organisme", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
|
|
|
@ -18,9 +18,10 @@ describe Administrateurs::ServicesController, type: :controller do
|
|||
email: 'email@toto.com',
|
||||
telephone: '1234',
|
||||
horaires: 'horaires',
|
||||
adresse: 'adresse'
|
||||
adresse: 'adresse',
|
||||
siret: "35600082800018"
|
||||
},
|
||||
procedure_id: 12
|
||||
procedure_id: procedure.id
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -33,7 +34,8 @@ describe Administrateurs::ServicesController, type: :controller do
|
|||
it { expect(Service.last.telephone).to eq('1234') }
|
||||
it { expect(Service.last.horaires).to eq('horaires') }
|
||||
it { expect(Service.last.adresse).to eq('adresse') }
|
||||
it { expect(response).to redirect_to(admin_services_path(procedure_id: 12)) }
|
||||
it { expect(Service.last.siret).to eq('35600082800018') }
|
||||
it { expect(response).to redirect_to(admin_services_path(procedure_id: procedure.id)) }
|
||||
end
|
||||
|
||||
context 'when submitting an invalid service' do
|
||||
|
@ -113,13 +115,13 @@ describe Administrateurs::ServicesController, type: :controller do
|
|||
context 'when a service has no related procedure' do
|
||||
before do
|
||||
sign_in(admin.user)
|
||||
delete :destroy, params: { id: service.id, procedure_id: 12 }
|
||||
delete :destroy, params: { id: service.id, procedure_id: procedure.id }
|
||||
end
|
||||
|
||||
it { expect { service.reload }.to raise_error(ActiveRecord::RecordNotFound) }
|
||||
it { expect(flash.alert).to be_nil }
|
||||
it { expect(flash.notice).to eq("#{service.nom} est supprimé") }
|
||||
it { expect(response).to redirect_to(admin_services_path(procedure_id: 12)) }
|
||||
it { expect(response).to redirect_to(admin_services_path(procedure_id: procedure.id)) }
|
||||
end
|
||||
|
||||
context 'when a service still has some related procedures' do
|
||||
|
@ -127,13 +129,13 @@ describe Administrateurs::ServicesController, type: :controller do
|
|||
|
||||
before do
|
||||
sign_in(admin.user)
|
||||
delete :destroy, params: { id: service.id, procedure_id: 12 }
|
||||
delete :destroy, params: { id: service.id, procedure_id: procedure.id }
|
||||
end
|
||||
|
||||
it { expect(service.reload).not_to be_nil }
|
||||
it { expect(flash.alert).to eq("la démarche #{procedure.libelle} utilise encore le service #{service.nom}. Veuillez l'affecter à un autre service avant de pouvoir le supprimer") }
|
||||
it { expect(flash.notice).to be_nil }
|
||||
it { expect(response).to redirect_to(admin_services_path(procedure_id: 12)) }
|
||||
it { expect(response).to redirect_to(admin_services_path(procedure_id: procedure.id)) }
|
||||
end
|
||||
|
||||
context "when a service has some related discarded procedures" do
|
||||
|
|
|
@ -949,7 +949,7 @@ describe API::V2::GraphqlController do
|
|||
errors: nil
|
||||
})
|
||||
|
||||
perform_enqueued_jobs
|
||||
perform_enqueued_jobs except: [APIEntreprise::ServiceJob]
|
||||
expect(ActionMailer::Base.deliveries.size).to eq(4)
|
||||
end
|
||||
end
|
||||
|
@ -992,7 +992,7 @@ describe API::V2::GraphqlController do
|
|||
errors: nil
|
||||
})
|
||||
|
||||
perform_enqueued_jobs
|
||||
perform_enqueued_jobs except: [APIEntreprise::ServiceJob]
|
||||
expect(ActionMailer::Base.deliveries.size).to eq(3)
|
||||
end
|
||||
end
|
||||
|
@ -1035,7 +1035,7 @@ describe API::V2::GraphqlController do
|
|||
errors: nil
|
||||
})
|
||||
|
||||
perform_enqueued_jobs
|
||||
perform_enqueued_jobs except: [APIEntreprise::ServiceJob]
|
||||
expect(ActionMailer::Base.deliveries.size).to eq(4)
|
||||
end
|
||||
end
|
||||
|
@ -1078,7 +1078,7 @@ describe API::V2::GraphqlController do
|
|||
errors: nil
|
||||
})
|
||||
|
||||
perform_enqueued_jobs
|
||||
perform_enqueued_jobs except: [APIEntreprise::ServiceJob]
|
||||
expect(ActionMailer::Base.deliveries.size).to eq(3)
|
||||
end
|
||||
end
|
||||
|
|
31
spec/controllers/manager/services_controller_spec.rb
Normal file
31
spec/controllers/manager/services_controller_spec.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
describe Manager::ServicesController, type: :controller do
|
||||
let(:super_admin) { create(:super_admin) }
|
||||
before do
|
||||
sign_in super_admin
|
||||
@service = create(:service)
|
||||
end
|
||||
|
||||
render_views
|
||||
|
||||
describe 'GET #index' do
|
||||
it "should list services" do
|
||||
get :index
|
||||
expect(response.body).to include(@service.nom)
|
||||
end
|
||||
|
||||
it "should search by nom" do
|
||||
get :index, params: { search: @service.nom.first(3) }
|
||||
expect(response.body).to include(@service.nom)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET #show" do
|
||||
before do
|
||||
get :show, params: { id: @service.id }
|
||||
end
|
||||
|
||||
it { expect(response.body).to include(@service.nom) }
|
||||
it { expect(response.body).to include("75 rue du Louvre") }
|
||||
it { expect(response.body).to have_link(href: "https://www.geoportail.gouv.fr/carte?c=2.34,48.87&z=17&permalink=yes") }
|
||||
end
|
||||
end
|
|
@ -7,6 +7,10 @@ FactoryBot.define do
|
|||
telephone { '1234' }
|
||||
horaires { 'de 9 h à 18 h' }
|
||||
adresse { 'adresse' }
|
||||
siret { '35600082800018' }
|
||||
etablissement_infos { { adresse: "75 rue du Louvre\n75002\nPARIS\nFRANCE" } }
|
||||
etablissement_lat { 48.87 }
|
||||
etablissement_lng { 2.34 }
|
||||
|
||||
association :administrateur
|
||||
end
|
||||
|
|
29
spec/fixtures/files/api_entreprise/privileges.json
vendored
Normal file
29
spec/fixtures/files/api_entreprise/privileges.json
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"privileges": [
|
||||
"attestations_agefiph",
|
||||
"attestations_fiscales",
|
||||
"attestations_sociales",
|
||||
"certificat_cnetp",
|
||||
"associations",
|
||||
"certificat_opqibi",
|
||||
"documents_association",
|
||||
"etablissements",
|
||||
"entreprises",
|
||||
"extrait_court_inpi",
|
||||
"extraits_rcs",
|
||||
"exercices",
|
||||
"fntp_carte_pro",
|
||||
"qualibat",
|
||||
"probtp",
|
||||
"msa_cotisations",
|
||||
"bilans_entreprise_bdf",
|
||||
"certificat_rge_ademe",
|
||||
"conventions_collectives",
|
||||
"actes_inpi",
|
||||
"bilans_inpi",
|
||||
"effectifs_acoss",
|
||||
"entreprises_artisanales",
|
||||
"eori_douanes",
|
||||
"certificat_agence_bio"
|
||||
]
|
||||
}
|
72
spec/jobs/api_entreprise/service_job_spec.rb
Normal file
72
spec/jobs/api_entreprise/service_job_spec.rb
Normal file
|
@ -0,0 +1,72 @@
|
|||
RSpec.describe APIEntreprise::ServiceJob, type: :job do
|
||||
let(:siret) { '41816609600051' }
|
||||
let(:service) { create(:service, siret: siret) }
|
||||
let(:entreprise_body) { File.read('spec/fixtures/files/api_entreprise/etablissements.json') }
|
||||
let(:geocoder_body) { File.read('spec/fixtures/files/api_address/address.json') }
|
||||
let(:status) { 200 }
|
||||
|
||||
let (:adresse) { "OCTO TECHNOLOGY\r\n50 AVENUE DES CHAMPS ELYSEES\r\n75008 PARIS\r\nFRANCE" }
|
||||
|
||||
before do
|
||||
stub_request(:get, %r{https://entreprise.api.gouv.fr/v2/etablissements/})
|
||||
.to_return(body: entreprise_body, status: status)
|
||||
allow_any_instance_of(APIEntrepriseToken).to receive(:expired?).and_return(false)
|
||||
|
||||
Geocoder.configure(lookup: :ban_data_gouv_fr, use_https: true)
|
||||
|
||||
stub_request(:get, "https://api-adresse.data.gouv.fr/search/?q=#{adresse}")
|
||||
.to_return(body: geocoder_body, status: status)
|
||||
end
|
||||
|
||||
after do
|
||||
Geocoder.configure(lookup: :test)
|
||||
end
|
||||
|
||||
subject { described_class.new.perform(service.id) }
|
||||
|
||||
it "update service with address" do
|
||||
subject
|
||||
infos = service.reload.etablissement_infos
|
||||
|
||||
expect(infos).not_to be_empty
|
||||
expect(infos["adresse"]).to eq(adresse)
|
||||
expect(infos["numero_voie"]).to eq("50")
|
||||
expect(infos["code_postal"]).to eq("75008")
|
||||
expect(infos["localite"]).to eq("PARIS 8")
|
||||
end
|
||||
|
||||
it "geocode address" do
|
||||
subject
|
||||
service.reload
|
||||
|
||||
expect(service.etablissement_lat).to eq(48.859)
|
||||
expect(service.etablissement_lng).to eq(2.347)
|
||||
end
|
||||
|
||||
context "errors responses" do
|
||||
it "clear attributes when no address match" do
|
||||
stub_request(:get, %r{https://entreprise.api.gouv.fr/v2/etablissements/})
|
||||
.to_return(body: "{}", status: 404)
|
||||
subject
|
||||
service.reload
|
||||
|
||||
expect(service.etablissement_infos).to be_empty
|
||||
expect(service.etablissement_lat).to be_nil
|
||||
expect(service.etablissement_lng).to be_nil
|
||||
end
|
||||
|
||||
it "supports empty geocode result" do
|
||||
geocoder_response = JSON.parse(geocoder_body)
|
||||
geocoder_response["features"] = []
|
||||
|
||||
stub_request(:get, "https://api-adresse.data.gouv.fr/search/?q=#{adresse}")
|
||||
.to_return(body: JSON.generate(geocoder_response), status: status)
|
||||
|
||||
subject
|
||||
service.reload
|
||||
|
||||
expect(service.etablissement_lat).to be_nil
|
||||
expect(service.etablissement_lng).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,7 +4,7 @@ describe APIEntreprise::API do
|
|||
let(:token) { Rails.application.secrets.api_entreprise[:key] }
|
||||
|
||||
describe '.entreprise' do
|
||||
subject { described_class.entreprise(siren, procedure_id) }
|
||||
subject { described_class.new(procedure_id).entreprise(siren) }
|
||||
|
||||
before do
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/)
|
||||
|
@ -85,7 +85,7 @@ describe APIEntreprise::API do
|
|||
end
|
||||
|
||||
describe '.etablissement' do
|
||||
subject { described_class.etablissement(siret, procedure_id) }
|
||||
subject { described_class.new(procedure_id).etablissement(siret) }
|
||||
before do
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*non_diffusables=true/)
|
||||
.to_return(status: status, body: body)
|
||||
|
@ -121,7 +121,7 @@ describe APIEntreprise::API do
|
|||
end
|
||||
|
||||
context 'when siret does not exist' do
|
||||
subject { described_class.exercices(siret, procedure_id) }
|
||||
subject { described_class.new(procedure_id).exercices(siret) }
|
||||
|
||||
let(:siret) { '11111111111111' }
|
||||
let(:status) { 404 }
|
||||
|
@ -133,7 +133,7 @@ describe APIEntreprise::API do
|
|||
end
|
||||
|
||||
context 'when siret exists' do
|
||||
subject { described_class.exercices(siret, procedure_id) }
|
||||
subject { described_class.new(procedure_id).exercices(siret) }
|
||||
|
||||
let(:siret) { '41816609600051' }
|
||||
let(:status) { 200 }
|
||||
|
@ -152,7 +152,7 @@ describe APIEntreprise::API do
|
|||
allow_any_instance_of(APIEntrepriseToken).to receive(:expired?).and_return(false)
|
||||
end
|
||||
|
||||
subject { described_class.rna(siren, procedure_id) }
|
||||
subject { described_class.new(procedure_id).rna(siren) }
|
||||
|
||||
context 'when siren does not exist' do
|
||||
let(:siren) { '111111111' }
|
||||
|
@ -186,7 +186,7 @@ describe APIEntreprise::API do
|
|||
.to_return(body: body, status: status)
|
||||
end
|
||||
|
||||
subject { described_class.attestation_sociale(siren, procedure.id) }
|
||||
subject { described_class.new(procedure.id).attestation_sociale(siren) }
|
||||
|
||||
context 'when token not authorized' do
|
||||
let(:roles) { ["entreprises"] }
|
||||
|
@ -215,7 +215,7 @@ describe APIEntreprise::API do
|
|||
.to_return(body: body, status: status)
|
||||
end
|
||||
|
||||
subject { described_class.attestation_fiscale(siren, procedure.id, user_id) }
|
||||
subject { described_class.new(procedure.id).attestation_fiscale(siren, user_id) }
|
||||
|
||||
context 'when token not authorized' do
|
||||
let(:roles) { ["entreprises"] }
|
||||
|
@ -243,7 +243,7 @@ describe APIEntreprise::API do
|
|||
.to_return(body: body, status: status)
|
||||
end
|
||||
|
||||
subject { described_class.bilans_bdf(siren, procedure.id) }
|
||||
subject { described_class.new(procedure.id).bilans_bdf(siren) }
|
||||
|
||||
context 'when token not authorized' do
|
||||
let(:roles) { ["entreprises"] }
|
||||
|
@ -258,9 +258,27 @@ describe APIEntreprise::API do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.privileges' do
|
||||
let(:api) { described_class.new }
|
||||
let(:status) { 200 }
|
||||
let(:body) { File.read('spec/fixtures/files/api_entreprise/privileges.json') }
|
||||
subject { api.privileges }
|
||||
|
||||
before do
|
||||
api.token = token
|
||||
|
||||
stub_request(:get, "https://entreprise.api.gouv.fr/v2/privileges")
|
||||
.to_return(body: body, status: status)
|
||||
end
|
||||
|
||||
context 'when token is authorized' do
|
||||
it { expect(subject).to eq(JSON.parse(body, symbolize_names: true)) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with expired token' do
|
||||
let(:siren) { '111111111' }
|
||||
subject { described_class.entreprise(siren, procedure_id) }
|
||||
subject { described_class.new(procedure_id).entreprise(siren) }
|
||||
|
||||
before do
|
||||
allow_any_instance_of(APIEntrepriseToken).to receive(:expired?).and_return(true)
|
||||
|
|
24
spec/lib/api_entreprise/privileges_adapter_spec.rb
Normal file
24
spec/lib/api_entreprise/privileges_adapter_spec.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
describe APIEntreprise::PrivilegesAdapter do
|
||||
let(:body) { File.read('spec/fixtures/files/api_entreprise/privileges.json') }
|
||||
let(:status) { 200 }
|
||||
let(:token) { "secret-token" }
|
||||
let(:adapter) { described_class.new(token) }
|
||||
|
||||
subject { adapter }
|
||||
|
||||
before do
|
||||
stub_request(:get, "https://entreprise.api.gouv.fr/v2/privileges")
|
||||
.to_return(body: body, status: status)
|
||||
allow_any_instance_of(APIEntrepriseToken).to receive(:expired?).and_return(false)
|
||||
end
|
||||
|
||||
it { is_expected.to be_valid }
|
||||
|
||||
context 'when token is not valid or missing' do
|
||||
let(:token) { nil }
|
||||
let(:status) { 403 }
|
||||
let(:body) { '' }
|
||||
|
||||
it { is_expected.not_to be_valid }
|
||||
end
|
||||
end
|
89
spec/lib/api_entreprise/service_adapter_spec.rb
Normal file
89
spec/lib/api_entreprise/service_adapter_spec.rb
Normal file
|
@ -0,0 +1,89 @@
|
|||
describe APIEntreprise::ServiceAdapter do
|
||||
before do
|
||||
allow_any_instance_of(APIEntrepriseToken).to receive(:expired?).and_return(false)
|
||||
end
|
||||
|
||||
let(:siret) { '41816609600051' }
|
||||
let(:service) { create(:service, siret: siret) }
|
||||
|
||||
context 'SIRET valide avec infos diffusables' do
|
||||
let(:fixture) { 'spec/fixtures/files/api_entreprise/etablissements.json' }
|
||||
subject { described_class.new(siret, service.id).to_params }
|
||||
|
||||
before do
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
|
||||
.with(query: hash_including({ 'object' => "service_id: #{service.id}" }))
|
||||
.to_return(body: File.read(fixture, status: 200))
|
||||
end
|
||||
|
||||
it '#to_params class est une Hash ?' do
|
||||
expect(subject).to be_a_instance_of(Hash)
|
||||
end
|
||||
|
||||
context 'Attributs Etablissements' do
|
||||
it 'should contains a SIRET' do
|
||||
expect(subject[:siret]).to eq(siret)
|
||||
end
|
||||
|
||||
it 'should not return siege_social information' do
|
||||
expect(subject[:siege_social]).to be_nil
|
||||
end
|
||||
|
||||
context 'Concaténation lignes adresse' do
|
||||
it 'service contains a multi lines adress' do
|
||||
expect(subject[:adresse]).to eq("OCTO TECHNOLOGY\r\n50 AVENUE DES CHAMPS ELYSEES\r\n75008 PARIS\r\nFRANCE")
|
||||
end
|
||||
end
|
||||
|
||||
context 'adress details' do
|
||||
it 'service contains a numero_voie' do
|
||||
expect(subject[:numero_voie]).to eq('50')
|
||||
end
|
||||
|
||||
it 'service contains a type_voie' do
|
||||
expect(subject[:type_voie]).to eq('AV')
|
||||
end
|
||||
|
||||
it 'service contains a nom_voie' do
|
||||
expect(subject[:nom_voie]).to eq('DES CHAMPS ELYSEES')
|
||||
end
|
||||
it 'service contains a complement_adresse' do
|
||||
expect(subject[:complement_adresse]).to eq('complement_adresse')
|
||||
end
|
||||
|
||||
it 'service contains a code_postal' do
|
||||
expect(subject[:code_postal]).to eq('75008')
|
||||
end
|
||||
|
||||
it 'service contains a localite' do
|
||||
expect(subject[:localite]).to eq('PARIS 8')
|
||||
end
|
||||
|
||||
it 'service contains a code_insee_localite' do
|
||||
expect(subject[:code_insee_localite]).to eq('75108')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'Attributs Etablissements pour etablissement non siege' do
|
||||
let(:siret) { '17310120500719' }
|
||||
let(:fixture) { 'spec/fixtures/files/api_entreprise/etablissements-non-siege.json' }
|
||||
it 'service contains a siret' do
|
||||
expect(subject[:siret]).to eq(siret)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when siret is not found' do
|
||||
let(:bad_siret) { 11_111_111_111_111 }
|
||||
subject { described_class.new(bad_siret, service.id).to_params }
|
||||
|
||||
before do
|
||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{bad_siret}/)
|
||||
.with(query: hash_including({ 'object' => "service_id: #{service.id}" }))
|
||||
.to_return(body: 'Fake body', status: 404)
|
||||
end
|
||||
|
||||
it { expect(subject).to eq({}) }
|
||||
end
|
||||
end
|
|
@ -10,36 +10,47 @@ describe Service, type: :model do
|
|||
telephone: '012345678',
|
||||
horaires: 'du lundi au vendredi',
|
||||
adresse: '12 rue des schtroumpfs',
|
||||
administrateur_id: administrateur.id
|
||||
administrateur_id: administrateur.id,
|
||||
siret: "35600082800018"
|
||||
}
|
||||
end
|
||||
|
||||
it { expect(Service.new(params).valid?).to be_truthy }
|
||||
subject { Service.new(params) }
|
||||
|
||||
it { expect(Service.new(params)).to be_valid }
|
||||
|
||||
it 'should forbid invalid phone numbers' do
|
||||
service = Service.create(params)
|
||||
invalid_phone_numbers = ["1", "Néant", "01 60 50 40 30 20"]
|
||||
|
||||
invalid_phone_numbers.each do |tel|
|
||||
service.telephone = tel
|
||||
expect(service.valid?).to be_falsey
|
||||
subject.telephone = tel
|
||||
expect(subject).not_to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
it 'should accept no phone numbers' do
|
||||
service = Service.create(params)
|
||||
service.telephone = nil
|
||||
|
||||
expect(service.valid?).to be_truthy
|
||||
subject.telephone = nil
|
||||
expect(subject).to be_valid
|
||||
end
|
||||
|
||||
it 'should accept valid phone numbers' do
|
||||
service = Service.create(params)
|
||||
valid_phone_numbers = ["3646", "273115", "0160376983", "01 60 50 40 30 ", "+33160504030"]
|
||||
|
||||
valid_phone_numbers.each do |tel|
|
||||
service.telephone = tel
|
||||
expect(service.valid?).to be_truthy
|
||||
subject.telephone = tel
|
||||
expect(subject).to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
describe "siret" do
|
||||
it 'should not be invalid' do
|
||||
subject.siret = "012345678901234"
|
||||
expect(subject).not_to be_valid
|
||||
end
|
||||
|
||||
it 'should be required' do
|
||||
subject.siret = nil
|
||||
expect(subject).not_to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -47,25 +58,25 @@ describe Service, type: :model do
|
|||
before { Service.create(params) }
|
||||
|
||||
context 'checks uniqueness of administrateur, name couple' do
|
||||
it { expect(Service.create(params).valid?).to be_falsey }
|
||||
it { expect(Service.create(params)).not_to be_valid }
|
||||
end
|
||||
end
|
||||
|
||||
context 'of type_organisme' do
|
||||
it 'should be set' do
|
||||
expect(Service.new(params.except(:type_organisme)).valid?).to be_falsey
|
||||
expect(Service.new(params.except(:type_organisme))).not_to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
context 'of nom' do
|
||||
it 'should be set' do
|
||||
expect(Service.new(params.except(:nom)).valid?).to be_falsey
|
||||
expect(Service.new(params.except(:nom))).not_to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
context 'of administrateur' do
|
||||
it 'should be set' do
|
||||
expect(Service.new(params.except(:administrateur_id)).valid?).to be_falsey
|
||||
expect(Service.new(params.except(:administrateur_id))).not_to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -75,4 +86,66 @@ describe Service, type: :model do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "API Entreprise job" do
|
||||
subject { create(:service) }
|
||||
it "should enqueue a job when created" do
|
||||
expect(APIEntreprise::ServiceJob).to have_been_enqueued.with(subject.id)
|
||||
end
|
||||
|
||||
it "should enqueue a job when siret changed" do
|
||||
subject.update(siret: "35600082800018")
|
||||
expect(APIEntreprise::ServiceJob).to have_been_enqueued.with(subject.id)
|
||||
end
|
||||
|
||||
it "should not enqueue a job when siret is unchanged" do
|
||||
subject
|
||||
clear_enqueued_jobs
|
||||
subject.update(telephone: "09879789")
|
||||
expect(APIEntreprise::ServiceJob).not_to have_been_enqueued
|
||||
end
|
||||
end
|
||||
|
||||
describe "etablissement adresse & geo coordinates" do
|
||||
subject { create(:service, etablissement_lat: latitude, etablissement_lng: longitude, etablissement_infos: etablissement_infos) }
|
||||
|
||||
context "when the service has no geo coordinates" do
|
||||
let(:latitude) { nil }
|
||||
let(:longitude) { nil }
|
||||
let(:etablissement_infos) { {} }
|
||||
it "should return nil" do
|
||||
expect(subject.etablissement_lat).to be_nil
|
||||
expect(subject.etablissement_lng).to be_nil
|
||||
expect(subject.etablissement_adresse).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context "when the service has geo coordinates" do
|
||||
let(:latitude) { 43.5 }
|
||||
let(:longitude) { 4.7 }
|
||||
let(:adresse) { "174 Chemin du Beurre\n13200\nARLES\nFRANCE" }
|
||||
let(:etablissement_infos) { { adresse: adresse } }
|
||||
|
||||
it "should return nil" do
|
||||
expect(subject.etablissement_lat).to eq(43.5)
|
||||
expect(subject.etablissement_lng).to eq(4.7)
|
||||
end
|
||||
|
||||
it "should return etablissement adresse" do
|
||||
expect(subject.etablissement_adresse).to eq(adresse)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'etablissement_latlng' do
|
||||
it 'without coordinates' do
|
||||
service = build(:service, etablissement_lat: nil, etablissement_lng: nil)
|
||||
expect(service.etablissement_latlng).to eq([nil, nil])
|
||||
end
|
||||
|
||||
it 'with coordinates' do
|
||||
service = build(:service)
|
||||
expect(service.etablissement_latlng).to eq([48.87, 2.34])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue