From d4d94f2cefe4b4baecae2cf1aa3bfd0923ed35c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Ferrandis?= Date: Wed, 29 Jan 2025 12:01:12 +0100 Subject: [PATCH 1/9] =?UTF-8?q?V=C3=A9rifier=20les=20agents=20pass=C3=A9s?= =?UTF-8?q?=20=C3=A0=20l'update=20de=20RDV=20(#5026)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Supprime du code inutilisé * Renomme une méthode pour être plus explicite * Filtre les IDs d'agents passés --- app/controllers/admin/rdvs_controller.rb | 14 +++++++++----- spec/controllers/admin/rdvs_controller_spec.rb | 12 ++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/app/controllers/admin/rdvs_controller.rb b/app/controllers/admin/rdvs_controller.rb index fffe06b7b7..c01f735a8a 100644 --- a/app/controllers/admin/rdvs_controller.rb +++ b/app/controllers/admin/rdvs_controller.rb @@ -72,7 +72,6 @@ def participations_export end def show - @uncollapsed_section = params[:uncollapsed_section] authorize(@rdv, policy_class: Agent::RdvPolicy) end @@ -89,7 +88,7 @@ def update authorize(@rdv, policy_class: Agent::RdvPolicy) @rdv_form = Admin::EditRdvForm.new(@rdv, pundit_user) - @success = @rdv_form.submit(rdv_params) + @success = @rdv_form.submit(rdv_update_params) respond_to do |format| format.js do @@ -161,9 +160,8 @@ def set_rdv @rdv = policy_scope(Rdv, policy_scope_class: Agent::RdvPolicy::Scope).find(params[:id]) end - def rdv_params + def rdv_update_params allowed_params = params.require(:rdv).permit(:motif_id, :status, :lieu_id, :duration_in_min, :starts_at, :context, :ignore_benign_errors, :max_participants_count, :name, - agent_ids: [], participations_attributes: %i[user_id send_lifecycle_notifications send_reminder_notification id _destroy], lieu_attributes: %i[name address latitude longitude id]) @@ -174,6 +172,12 @@ def rdv_params allowed_params[:lieu_attributes][:availability] = :single_use end + if params[:rdv][:agent_ids].present? + # La méthode Motif#authorized_agents est aussi utilisée pour lister les agents du select + # de l'edit, c'est donc cohérent de l'utiliser ici pour sanitizer les IDs d'agent. + allowed_params[:agent_ids] = @rdv.motif.authorized_agents.where(id: params[:rdv][:agent_ids]).pluck(:id) + end + allowed_params end @@ -191,7 +195,7 @@ def parsed_params def rdv_success_flash { - notice: if rdv_params[:status].in?(Rdv::CANCELLED_STATUSES) + notice: if rdv_update_params[:status].in?(Rdv::CANCELLED_STATUSES) I18n.t("admin.rdvs.message.success.cancel") else I18n.t("admin.rdvs.message.success.update") diff --git a/spec/controllers/admin/rdvs_controller_spec.rb b/spec/controllers/admin/rdvs_controller_spec.rb index 433ef43a58..33d33df781 100644 --- a/spec/controllers/admin/rdvs_controller_spec.rb +++ b/spec/controllers/admin/rdvs_controller_spec.rb @@ -129,6 +129,18 @@ end.not_to change { rdv.reload.user_ids } end end + + context "when injecting the ID of an agent that is outside of the organisation (same territory)" do + it "doesn't allow updating the RDV with this agent" do + other_org_of_territory = create(:organisation, territory: organisation.territory) + agent_from_other_org_of_my_territory = create(:agent, :with_territory_access_rights, basic_role_in_organisations: [other_org_of_territory]) + rdv = create(:rdv, motif: motif, agents: [agent], users: [user], organisation: organisation) + new_attributes = { agent_ids: [agent.id, agent_from_other_org_of_my_territory.id] } + expect do + put :update, params: { organisation_id: organisation.id, id: rdv.to_param, rdv: new_attributes } + end.not_to change { rdv.reload.agent_ids } + end + end end describe "GET #show" do From 9b50cdae7759824a448a24e892b6648252142ceb Mon Sep 17 00:00:00 2001 From: Adrien Di Pasquale Date: Wed, 29 Jan 2025 12:14:21 +0100 Subject: [PATCH 2/9] application de la policy scope Motif sur admin/rdvs#index (#5027) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ajout d’une spec qui échoue pour les motifs d’autres services sur admin/rdvs#index * filtrer les motifs avec le policy scope sur admin/rdvs#index * correction pour les motifs d’autres services de RDV en binôme --- app/controllers/admin/rdvs_controller.rb | 5 ++++- app/policies/agent/motif_policy.rb | 22 +++++++++++++++++++ .../controllers/admin/rdvs_controller_spec.rb | 18 ++++++++++++--- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/app/controllers/admin/rdvs_controller.rb b/app/controllers/admin/rdvs_controller.rb index c01f735a8a..662594bb5d 100644 --- a/app/controllers/admin/rdvs_controller.rb +++ b/app/controllers/admin/rdvs_controller.rb @@ -36,7 +36,10 @@ def index @form = Admin::RdvSearchForm.new(parsed_params.merge(pundit_user:)) @lieux = Lieu.joins(:organisation).where(organisations: { id: @scoped_organisations.select(:id) }).enabled.ordered_by_name - @motifs = Motif.joins(:organisation).where(organisations: { id: @scoped_organisations.select(:id) }).ordered_by_name + @motifs = Agent::MotifPolicy::ScopeForRdvsList.new( + current_agent, + Motif.joins(:organisation).where(organisations: { id: @scoped_organisations.select(:id) }).ordered_by_name + ).resolve end def a_renseigner diff --git a/app/policies/agent/motif_policy.rb b/app/policies/agent/motif_policy.rb index 1f13956266..45a4116606 100644 --- a/app/policies/agent/motif_policy.rb +++ b/app/policies/agent/motif_policy.rb @@ -56,4 +56,26 @@ def resolve alias current_agent pundit_user end + + class ScopeForRdvsList < Scope + # on veut permettre aux agents de filtrer sur les motifs d’autres services pour lesquels ils ont des RDV en binôme + def resolve + super.or( + scope.where( + organisation: current_agent.basic_orgs + current_agent.admin_orgs, + id: motif_ids_from_other_services + ) + ) + end + + private + + def motif_ids_from_other_services + # L’exclusion des services de l’agent ci-dessous n’est pas nécessaire mais évite de retourner de nombreux motif ids dans cette sous-requête + AgentsRdv.joins(rdv: [:motif]) + .where(agent: current_agent) + .where.not(motifs: { service_id: current_agent.service_ids }) + .select("rdvs.motif_id") + end + end end diff --git a/spec/controllers/admin/rdvs_controller_spec.rb b/spec/controllers/admin/rdvs_controller_spec.rb index 33d33df781..9637431ec6 100644 --- a/spec/controllers/admin/rdvs_controller_spec.rb +++ b/spec/controllers/admin/rdvs_controller_spec.rb @@ -1,11 +1,17 @@ RSpec.describe Admin::RdvsController, type: :controller do let(:now) { Time.zone.parse("19/07/2019 15:00") } - let!(:organisation) { create(:organisation) } - let!(:territory) { organisation.territory } + let!(:territory) { create(:territory) } + let!(:organisation) { create(:organisation, territory:) } let!(:service) { create(:service) } let!(:agent) { create(:agent, basic_role_in_organisations: [organisation], service: service) } let!(:user) { create(:user, first_name: "Marie", last_name: "Denis") } let!(:motif) { create(:motif, name: "Suivi", organisation: organisation, service: service, color: "#1010FF") } + let!(:motif_from_other_orga) { create(:motif, name: "Suivi", organisation: create(:organisation, territory:), service: service, color: "#1010FF") } + let!(:other_service) { create(:service) } + let!(:motif_from_other_service_without_rdv) { create(:motif, name: "Rencontre", organisation: organisation, service: other_service, color: "#1010FF") } + let!(:motif_from_other_service_with_rdv_binome) { create(:motif, name: "Parcours", organisation: organisation, service: other_service, color: "#1010FF") } + let!(:agent2) { create(:agent, basic_role_in_organisations: [organisation], service: other_service) } + let!(:rdv_binome) { create(:rdv, motif: motif_from_other_service_with_rdv_binome, agents: [agent2, agent], users: [user], organisation: organisation) } before do travel_to(now) @@ -25,7 +31,7 @@ rdv = create(:rdv, agents: [agent], organisation: organisation, motif: motif) get(:index, params: { organisation_id: organisation.id }) - expect(assigns(:rdvs)).to eq([rdv]) + expect(assigns(:rdvs)).to contain_exactly(rdv, rdv_binome) end it "assign form" do @@ -34,6 +40,12 @@ expect(assigns(:form)).not_to be_nil end + it "assigns motifs" do + get(:index, params: { organisation_id: organisation.id }) + + expect(assigns(:motifs)).to contain_exactly(motif, motif_from_other_service_with_rdv_binome) + end + context "with invalid dates" do it "respond success" do get(:index, params: { organisation_id: organisation.id, agent_id: agent.id, start: "invalid_date", end: "__/__/____" }) From b4751b8d270053bf901ebd8e8cab49202c166adc Mon Sep 17 00:00:00 2001 From: Adrien Di Pasquale Date: Wed, 29 Jan 2025 12:57:38 +0100 Subject: [PATCH 3/9] =?UTF-8?q?Correction=20mise=20=C3=A0=20jour=20des=20a?= =?UTF-8?q?gents=20d=E2=80=99un=20RDV=20(#5029)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit correction mise à jour des agents sur un RDV --- app/controllers/admin/rdvs_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/admin/rdvs_controller.rb b/app/controllers/admin/rdvs_controller.rb index 662594bb5d..4abb37f704 100644 --- a/app/controllers/admin/rdvs_controller.rb +++ b/app/controllers/admin/rdvs_controller.rb @@ -178,7 +178,7 @@ def rdv_update_params if params[:rdv][:agent_ids].present? # La méthode Motif#authorized_agents est aussi utilisée pour lister les agents du select # de l'edit, c'est donc cohérent de l'utiliser ici pour sanitizer les IDs d'agent. - allowed_params[:agent_ids] = @rdv.motif.authorized_agents.where(id: params[:rdv][:agent_ids]).pluck(:id) + allowed_params[:agent_ids] = @rdv.motif.authorized_agents.where(id: params[:rdv][:agent_ids]).pluck(:id).uniq end allowed_params From b978726fdcd051f8f9540639cc32da2d8ca87942 Mon Sep 17 00:00:00 2001 From: Victor Mours Date: Wed, 29 Jan 2025 22:47:30 +0100 Subject: [PATCH 4/9] =?UTF-8?q?Premi=C3=A8re=20version=20de=20la=20prise?= =?UTF-8?q?=20de=20rdv=20par=20int=C3=A9gration=20(#5006)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * wip: trying to add radio buttons * wip * fix * nicer radio buttons, still need proper field name * wip * Add location type * wip * wip * wip * wip * fix * Extend integration spec for rdv_plan * fix user update * wip * anonymizer fix * update brakeman ignore * fix * remove unused css * Add policy call for lieux * fix * wip * Vérifie dans les specs qu'on envoie les bons mails --------- Co-authored-by: François Ferrandis --- .../agents/rdv_plans_controller.rb | 73 ++++++++++++++++++- app/helpers/application_helper.rb | 16 ++-- app/models/rdv_plan.rb | 41 +++++++++++ app/models/service.rb | 2 +- app/policies/agent/rdv_plan_policy.rb | 11 ++- .../rdv_plans/_modalites_field.html.slim | 48 ++++++++++++ .../agents/rdv_plans/edit_modalites.html.slim | 18 +++++ .../agents/rdv_plans/edit_motif.html.slim | 23 ++++++ .../agents/rdv_plans/edit_user.html.slim | 31 ++++++++ app/views/agents/rdv_plans/rdv.html.slim | 33 +++++++++ .../summary/_location_type.html.slim | 12 +++ .../agents/rdv_plans/summary/_motif.html.slim | 5 ++ .../rdv_plans/summary/_starts_at.html.slim | 4 + config/anonymizer.yml | 1 + config/brakeman.ignore | 36 ++++++++- config/locales/models/rdv_plan.yml | 5 ++ config/routes.rb | 11 ++- ...121133641_add_location_type_to_rdv_plan.rb | 5 ++ db/schema.rb | 3 +- db/seeds.rb | 1 + db/seeds/ccas.rb | 51 +++++++++++++ spec/factories/user.rb | 3 + .../agents/create_rdv_with_rdv_plan_spec.rb | 42 ++++++++++- 23 files changed, 458 insertions(+), 17 deletions(-) create mode 100644 app/views/agents/rdv_plans/_modalites_field.html.slim create mode 100644 app/views/agents/rdv_plans/edit_modalites.html.slim create mode 100644 app/views/agents/rdv_plans/edit_motif.html.slim create mode 100644 app/views/agents/rdv_plans/edit_user.html.slim create mode 100644 app/views/agents/rdv_plans/rdv.html.slim create mode 100644 app/views/agents/rdv_plans/summary/_location_type.html.slim create mode 100644 app/views/agents/rdv_plans/summary/_motif.html.slim create mode 100644 app/views/agents/rdv_plans/summary/_starts_at.html.slim create mode 100644 config/locales/models/rdv_plan.yml create mode 100644 db/migrate/20250121133641_add_location_type_to_rdv_plan.rb create mode 100644 db/seeds/ccas.rb diff --git a/app/controllers/agents/rdv_plans_controller.rb b/app/controllers/agents/rdv_plans_controller.rb index 7beace0fa9..9338d119af 100644 --- a/app/controllers/agents/rdv_plans_controller.rb +++ b/app/controllers/agents/rdv_plans_controller.rb @@ -1,6 +1,7 @@ class Agents::RdvPlansController < AgentAuthController layout "application" before_action :find_rdv_plan + before_action :redirect_to_rdv, if: -> { @rdv_plan.rdv.present? }, except: [:rdv] def show redirect_to edit_starts_at_agents_rdv_plan_path(@rdv_plan) @@ -12,10 +13,73 @@ def edit_starts_at def update_starts_at @rdv_plan.update!(params.require(:rdv_plan).permit(:starts_at).merge(rdv_agent: current_agent)) - redirect_to show_starts_at_agents_rdv_plan_path(@rdv_plan) + redirect_to edit_modalites_agents_rdv_plan_path(@rdv_plan) end - def show_starts_at; end + def edit_modalites; end + + def update_modalites + rdv_plan_params = params.require(:rdv_plan).permit(:starts_at, :modalite) + + if @rdv_plan.update(rdv_plan_params) + redirect_to edit_motif_agents_rdv_plan_path(@rdv_plan) + else + render "edit_modalites" + end + end + + def edit_motif + @motifs = current_agent.motifs.individuel.where( + organisation_id: current_agent.roles.select(:organisation_id), + location_type: @rdv_plan.location_type, + service: @rdv_plan.rdv_agent.services + ) + if @motifs.count == 1 + @rdv_plan.motif_id ||= @motifs.first.id + end + @rdv_plan.duration_in_minutes ||= @motifs.first.default_duration_in_min + end + + def update_motif + rdv_plan_params = params.require(:rdv_plan).permit(:motif_id, :duration_in_minutes) + + if @rdv_plan.update(rdv_plan_params) + redirect_to edit_user_agents_rdv_plan_path(@rdv_plan) + else + render "edit_motif_from_calendar" + end + end + + def edit_user; end + + def create_rdv + rdv_plan_params = params.require(:rdv_plan) + + user_attributes = rdv_plan_params.require(:user).permit(:email, :phone_number) + + # TODO: possible à mettre en commun ? + participation_attributes = if @rdv_plan.motif.visible_and_notified? + rdv_plan_params.require(:participation).permit( + :send_lifecycle_notifications, :send_reminder_notification + ) + else + { send_lifecycle_notifications: false, send_reminder_notification: false } + end + + rdv = @rdv_plan.create_rdv(user_attributes:, participation_attributes:) + + if rdv.valid? + flash[:success] = "Le rendez-vous a été créé." + redirect_to rdv_agents_rdv_plan_path(@rdv_plan) + else + flash[:error] = rdv.errors.full_messages.to_sentence + redirect_to edit_user_agents_rdv_plan_path(@rdv_plan) + end + end + + def rdv + @rdv = @rdv_plan.rdv + end private @@ -24,6 +88,11 @@ def find_rdv_plan authorize @rdv_plan, :edit?, policy_class: Agent::RdvPlanPolicy end + def redirect_to_rdv + # TODO: ajouter un flash ici? + redirect_to rdv_agents_rdv_plan_path(@rdv_plan) + end + def pundit_user current_agent end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 225bfd3e3c..8b58b27377 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -29,15 +29,17 @@ def alert_dsfr_class_for(alert) end end - def datetime_input(form, field, input_html: {}) + def datetime_input(form, field, input_html: {}, options: {}) form.input( field, - as: :string, - input_html: { - value: form.object.send(field)&.strftime("%d/%m/%Y %H:%M"), - data: { behaviour: "datetimepicker" }, - autocomplete: "off", - }.deep_merge(input_html) + { + as: :string, + input_html: { + value: form.object.send(field)&.strftime("%d/%m/%Y %H:%M"), + data: { behaviour: "datetimepicker" }, + autocomplete: "off", + }.deep_merge(input_html), + }.deep_merge(options) ) end diff --git a/app/models/rdv_plan.rb b/app/models/rdv_plan.rb index 160616aa6f..71f0383b4f 100644 --- a/app/models/rdv_plan.rb +++ b/app/models/rdv_plan.rb @@ -11,6 +11,47 @@ class RdvPlan < ApplicationRecord validate :return_url_is_authorized + # TODO: mettre en commun avec les motifs et ajouter une validation de synchro + enum :location_type, { public_office: "public_office", phone: "phone", home: "home", visio: "visio" } + + def modalite + if location_type == "public_office" + "#{location_type}-#{lieu&.id}" + else + location_type + end + end + + def modalite=(modalite) + self.location_type, self.lieu_id = modalite.split("-") + end + + def create_rdv(user_attributes:, participation_attributes:) + if user.encrypted_password.blank? # Pour mettre à jour l'email sans renvoyer de mail de confirmation + user.skip_confirmation_notification! + user.skip_reconfirmation! + end + user.update!(user_attributes) + + rdv = Rdv.create( + agents: [rdv_agent], + participations: [Participation.new(participation_attributes.merge(user_id: user.id))], + motif: motif, + organisation: organisation, + lieu: lieu, + starts_at: starts_at, + created_by: planning_agent, + ends_at: starts_at + (duration_in_minutes || motif.default_duration_in_min).minutes + ) + + if rdv.persisted? + update(rdv: rdv) + Notifiers::RdvCreated.perform_with(rdv, planning_agent) + end + + rdv + end + private def return_url_is_authorized diff --git a/app/models/service.rb b/app/models/service.rb index bc4e81f5c2..04071c98e9 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -22,7 +22,7 @@ class Service < ApplicationRecord validates :name, :short_name, presence: true, uniqueness: { case_sensitive: false } # Scopes - default_scope { order(Arel.sql("unaccent(LOWER(name))")) } + default_scope { order(Arel.sql("unaccent(LOWER(services.name))")) } ## - diff --git a/app/policies/agent/rdv_plan_policy.rb b/app/policies/agent/rdv_plan_policy.rb index 01e9d62a3a..88d3ed6613 100644 --- a/app/policies/agent/rdv_plan_policy.rb +++ b/app/policies/agent/rdv_plan_policy.rb @@ -1,6 +1,6 @@ class Agent::RdvPlanPolicy < ApplicationPolicy def create? - pundit_user == record.planning_agent + authorized_lieu && pundit_user == record.planning_agent end alias edit? create? @@ -9,4 +9,13 @@ def resolve scope.where(planning_agent: pundit_user) end end + + private + + # TODO: ajouter une spec pour ce cas + def authorized_lieu + return true unless record.lieu_id + + Agent::LieuPolicy::Scope.new(pundit_user, Lieu.enabled).resolve.find_by(id: record.lieu_id).present? + end end diff --git a/app/views/agents/rdv_plans/_modalites_field.html.slim b/app/views/agents/rdv_plans/_modalites_field.html.slim new file mode 100644 index 0000000000..dd81685d24 --- /dev/null +++ b/app/views/agents/rdv_plans/_modalites_field.html.slim @@ -0,0 +1,48 @@ +- available_location_types = rdv_plan.rdv_agent.motifs.individuel.active.where(organisation_id: rdv_plan.rdv_agent.roles.select(:organisation_id)).pluck(:location_type) + +fieldset[class="fr-fieldset" id="rdv_plan[modalite]" aria-labelledby="radio-rich-no-pictogram-inline-legend radio-rich-no-pictogram-inline-messages"] + legend[class="fr-fieldset__legend--regular fr-fieldset__legend" id="radio-rich-no-pictogram-inline-legend"] + | Comment souhaitez-vous faire le rendez-vous ? + + - if available_location_types.include?("public_office") + - lieux = policy_scope(Lieu.enabled, policy_scope_class: Agent::LieuPolicy::Scope) + - lieux.each do |lieu| + .fr-fieldset__element + .fr-radio-group.fr-radio-rich + input[value="public_office-#{lieu.id}" type="radio" id="public_office-#{lieu.id}" name="rdv_plan[modalite]" required] + label.fr-label[for="public_office-#{lieu.id}"] + span + = lieu_icon + = " Sur place à #{lieu.name}" + span.fr-hint-text = lieu.address + + - if available_location_types.include?("phone") + .fr-fieldset__element + .fr-radio-group.fr-radio-rich + input[value="phone" type="radio" id="rdv_plan_modalite_phone" name="rdv_plan[modalite]" required] + label.fr-label[for="rdv_plan_modalite_phone"] + span + = phone_icon + = " Par téléphone" + + - if available_location_types.include?("visio") + .fr-fieldset__element + .fr-radio-group.fr-radio-rich + input[value="visio" type="radio" id="rdv_plan_modalite_visio" name="rdv_plan[modalite]" required] + label.fr-label[for="rdv_plan_modalite_visio"] + span + = visio_icon + = " Par visioconférence" + span.fr-hint-text + | Nous vous fournirons un lien de visio + + - if available_location_types.include?("home") + .fr-fieldset__element + .fr-radio-group.fr-radio-rich + input[value="home" type="radio" id="rdv_plan_modalite_home" name="rdv_plan[modalite]" required] + label.fr-label[for="rdv_plan_modalite_home"] + span + = home_icon + | Au domicile de l'usager + + div[class="fr-messages-group" id="radio-rich-no-pictogram-inline-messages" aria-live="polite"] diff --git a/app/views/agents/rdv_plans/edit_modalites.html.slim b/app/views/agents/rdv_plans/edit_modalites.html.slim new file mode 100644 index 0000000000..90a29d2367 --- /dev/null +++ b/app/views/agents/rdv_plans/edit_modalites.html.slim @@ -0,0 +1,18 @@ +.fr-row + .fr-col-12 + = render "agents/rdv_plans/header", rdv_plan: @rdv_plan, current_step: 1, step_title: "Créneau", next_step_title: "Motif" +.row.fr-mb-16w + .col-12.col-md-4 + = render "agents/rdv_plans/calendar", rdv_plan: @rdv_plan, single_day: true + = link_to edit_starts_at_agents_rdv_plan_path(@rdv_plan) do + = "retour" + + .col-12.col-md-4 + = simple_form_for @rdv_plan, url: update_modalites_agents_rdv_plan_path(@rdv_plan) do |f| + .fr-mb-4w + .input-group + = datetime_input(f, :starts_at, options: { label_html: { style: "flex-shrink: 0;", class: "fr-mr-2w" }, wrapper_html: { class: "d-flex", style: "align-items: baseline;" }}) + + = render "agents/rdv_plans/modalites_field", rdv_plan: @rdv_plan + + = f.submit "Continuer", class: "fr-btn float-right" diff --git a/app/views/agents/rdv_plans/edit_motif.html.slim b/app/views/agents/rdv_plans/edit_motif.html.slim new file mode 100644 index 0000000000..00e82c46f4 --- /dev/null +++ b/app/views/agents/rdv_plans/edit_motif.html.slim @@ -0,0 +1,23 @@ +.fr-row + .fr-col-12 + = render "agents/rdv_plans/header", rdv_plan: @rdv_plan, current_step: 2, step_title: "Motif", next_step_title: "Usager" +.row.fr-mb-16w + .col-4 + = render "agents/rdv_plans/calendar", rdv_plan: @rdv_plan, single_day: true + = link_to edit_modalites_agents_rdv_plan_path(@rdv_plan) do + = back_icon(class: "fr-mr-1w") + = "retour" + + .col-12.col-md-6 + = render "agents/rdv_plans/summary/starts_at", rdv_plan: @rdv_plan + = render "agents/rdv_plans/summary/location_type", rdv_plan: @rdv_plan + hr.fr-mt-2w.fr-mb-4w + + = simple_form_for @rdv_plan, url: update_motif_agents_rdv_plan_path(@rdv_plan) do |f| + = render "model_errors", model: @rdv_plan + + .input-group.fr-mb-3w + = f.input :motif_id, label: "Motif du rendez-vous", required: true, collection: @motifs, label_method: :name, label_html: { class: "fr-mr-2w" }, include_blank: true + + = f.input :duration_in_minutes, label: "Durée en minutes" + = f.submit "Continuer", class: "fr-btn float-right" diff --git a/app/views/agents/rdv_plans/edit_user.html.slim b/app/views/agents/rdv_plans/edit_user.html.slim new file mode 100644 index 0000000000..49a6d72351 --- /dev/null +++ b/app/views/agents/rdv_plans/edit_user.html.slim @@ -0,0 +1,31 @@ +.row.justify-content-md-center + .col-12 + = render "agents/rdv_plans/header", rdv_plan: @rdv_plan, current_step: 3, step_title: "Usager", next_step_title: "" +.row.fr-mb-16w + .col-12.col-md-4 + = render "agents/rdv_plans/calendar", rdv_plan: @rdv_plan, single_day: true + = link_to edit_motif_agents_rdv_plan_path(@rdv_plan) do + = back_icon(class: "fr-mr-1w") + = "retour" + .col-12.col-md-8 + = render "agents/rdv_plans/summary/starts_at", rdv_plan: @rdv_plan + = render "agents/rdv_plans/summary/location_type", rdv_plan: @rdv_plan + = render "agents/rdv_plans/summary/motif", rdv_plan: @rdv_plan + + hr.fr-mt-2w + h3= @rdv_plan.user.full_name + = simple_form_for @rdv_plan, url: create_rdv_agents_rdv_plan_path(@rdv_plan), method: :post do |f| + = f.fields_for :user, @rdv_plan.user do |ff| + .row + .col-6 + / TODO: gérer le cas des users confirmed (et gérer ce cas dans l'interface principale aussi) : leur nouvelle adresse mail ne sera pas prise en compte tant qu'ils ne la confirment pas + = ff.input :email + .col-6 + = ff.input :phone_number + - if @rdv_plan.motif.visible_and_notified? + = f.fields_for :participation, (Participation.new(send_lifecycle_notifications: true, send_reminder_notification: true)) do |ff| + = ff.input :send_lifecycle_notifications, label: "Envoyer une notification de confirmation" + = ff.input :send_reminder_notification, label: "Envoyer une notification de rappel 48h avant le rendez-vous" + - else + | Les notifications ne sont pas envoyées pour ce motif de rendez-vous. + = f.submit "Confirmer le rendez-vous", class: "fr-btn float-right fr-btn--lg" diff --git a/app/views/agents/rdv_plans/rdv.html.slim b/app/views/agents/rdv_plans/rdv.html.slim new file mode 100644 index 0000000000..fc8ee0adf8 --- /dev/null +++ b/app/views/agents/rdv_plans/rdv.html.slim @@ -0,0 +1,33 @@ +.fr-grid-row.justify-content-md-center.fr-mb-16w + .fr-col-8 + h1.fr-h2 Rendez-vous confirmé + .card + .card-body + div + span.fr-icon-calendar-fill.fr-mr-1w[aria-hidden="true"] + = "#{l(@rdv.starts_at, format: :human)} (#{@rdv.duration_in_min} minutes)" + = " " + = dsfr_link_to "voir dans l'agenda", admin_organisation_agent_agenda_path(@rdv.organisation, @rdv.agents.first, selected_event_id: @rdv.id, date: @rdv.starts_at.to_date), target: :blank + + .fr-mt-2w + - if @rdv.lieu + = lieu_icon(class: "fr-mr-1w") + = @rdv.lieu.name + br + .fr-ml-4w= @rdv.lieu.address + / TODO: gérer les autres location types + + .fr-mt-2w + = motif_icon(class: "fr-mr-1w") + = "Motif : #{@rdv.motif.name}" + + .fr-mt-2w + span.fr-icon-user-fill.fr-mr-1w[aria-hidden="true"] + = @rdv_plan.user.full_name + .fr-ml-4w= @rdv_plan.user.email + .fr-ml-4w= @rdv_plan.user.phone_number + + .fr-mt-4w + = link_to "Modifier", edit_admin_organisation_rdv_path(@rdv.organisation, @rdv), class: "fr-btn fr-btn--secondary", target: :blank + - if @rdv_plan.return_url + = link_to "Retour sur Mon Suivi Social", @rdv_plan.return_url, class: "float-right" diff --git a/app/views/agents/rdv_plans/summary/_location_type.html.slim b/app/views/agents/rdv_plans/summary/_location_type.html.slim new file mode 100644 index 0000000000..67d84540b0 --- /dev/null +++ b/app/views/agents/rdv_plans/summary/_location_type.html.slim @@ -0,0 +1,12 @@ +/ locals(rdv_plan:) +br +- if rdv_plan.public_office? + = lieu_icon(class: "fr-mr-1w") + = rdv_plan.lieu.name +- elsif rdv_plan.phone? + = phone_icon(class: "fr-mr-1w") + = "Par téléphone" +- elsif rdv_plan.visio? + = visio_icon(class: "fr-mr-1w") + = "Par visio" += link_to "modifier", edit_modalites_agents_rdv_plan_path(rdv_plan), class: "fr-ml-2w" diff --git a/app/views/agents/rdv_plans/summary/_motif.html.slim b/app/views/agents/rdv_plans/summary/_motif.html.slim new file mode 100644 index 0000000000..3f71a72a19 --- /dev/null +++ b/app/views/agents/rdv_plans/summary/_motif.html.slim @@ -0,0 +1,5 @@ +/ locals(rdv_plan:) +br += motif_icon(class: "fr-mr-1w") += rdv_plan.motif.name += link_to "modifier", edit_motif_agents_rdv_plan_path(rdv_plan), class: "fr-ml-2w" diff --git a/app/views/agents/rdv_plans/summary/_starts_at.html.slim b/app/views/agents/rdv_plans/summary/_starts_at.html.slim new file mode 100644 index 0000000000..30a006e27e --- /dev/null +++ b/app/views/agents/rdv_plans/summary/_starts_at.html.slim @@ -0,0 +1,4 @@ +/ locals(rdv_plan:) +span.fr-icon-calendar-fill.fr-mr-1w[aria-hidden="true"] += "#{l(rdv_plan.starts_at, format: :human)} (#{rdv_plan.duration_in_minutes} minutes)" += link_to "modifier", edit_starts_at_agents_rdv_plan_path(rdv_plan), class: "fr-ml-2w" diff --git a/config/anonymizer.yml b/config/anonymizer.yml index 8f36105262..8a0ad22ef0 100644 --- a/config/anonymizer.yml +++ b/config/anonymizer.yml @@ -457,3 +457,4 @@ tables: - starts_at - created_at - updated_at + - location_type diff --git a/config/brakeman.ignore b/config/brakeman.ignore index 0a479ce550..c860a07798 100644 --- a/config/brakeman.ignore +++ b/config/brakeman.ignore @@ -1,5 +1,39 @@ { "ignored_warnings": [ + { + "warning_type": "Cross-Site Scripting", + "warning_code": 4, + "fingerprint": "2747f988c20b0979bf7fe9339e5ba78a0f118f9f87ba443060f1ee2bd0cd52c6", + "check_name": "LinkToHref", + "message": "Potentially unsafe model attribute in `link_to` href", + "file": "app/views/agents/rdv_plans/rdv.html.slim", + "line": 33, + "link": "https://brakemanscanner.org/docs/warning_types/link_to_href", + "code": "link_to(\"Retour sur Mon Suivi Social\", RdvPlan.find(params[:id]).return_url, :class => \"float-right\")", + "render_path": [ + { + "type": "controller", + "class": "Agents::RdvPlansController", + "method": "rdv", + "line": 82, + "file": "app/controllers/agents/rdv_plans_controller.rb", + "rendered": { + "name": "agents/rdv_plans/rdv", + "file": "app/views/agents/rdv_plans/rdv.html.slim" + } + } + ], + "location": { + "type": "template", + "template": "agents/rdv_plans/rdv" + }, + "user_input": "RdvPlan.find(params[:id]).return_url", + "confidence": "Weak", + "cwe_id": [ + 79 + ], + "note": "" + }, { "warning_type": "Cross-Site Scripting", "warning_code": 4, @@ -15,7 +49,7 @@ "type": "controller", "class": "Agents::RdvPlansController", "method": "edit_starts_at", - "line": 10, + "line": 12, "file": "app/controllers/agents/rdv_plans_controller.rb", "rendered": { "name": "agents/rdv_plans/edit_starts_at", diff --git a/config/locales/models/rdv_plan.yml b/config/locales/models/rdv_plan.yml new file mode 100644 index 0000000000..92fd520574 --- /dev/null +++ b/config/locales/models/rdv_plan.yml @@ -0,0 +1,5 @@ +fr: + activerecord: + attributes: + rdv_plan: + starts_at: "Date et heure" diff --git a/config/routes.rb b/config/routes.rb index 318a92a530..1316d28662 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -121,7 +121,16 @@ get :edit_starts_at patch :update_starts_at - get :show_starts_at # Route temporaire qui sera supprimée quand on implémentera la suite du parcours + get :edit_modalites + patch :update_modalites + + get :edit_motif + patch :update_motif + + get :edit_user + post :create_rdv + + get :rdv end end resources :users, only: [] do diff --git a/db/migrate/20250121133641_add_location_type_to_rdv_plan.rb b/db/migrate/20250121133641_add_location_type_to_rdv_plan.rb new file mode 100644 index 0000000000..565054e45a --- /dev/null +++ b/db/migrate/20250121133641_add_location_type_to_rdv_plan.rb @@ -0,0 +1,5 @@ +class AddLocationTypeToRdvPlan < ActiveRecord::Migration[7.1] + def change + add_column :rdv_plans, :location_type, :enum, enum_type: :location_type + end +end diff --git a/db/schema.rb b/db/schema.rb index 960143a7ca..228c89630e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2025_01_08_115309) do +ActiveRecord::Schema[7.1].define(version: 2025_01_21_133641) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" enable_extension "pgcrypto" @@ -594,6 +594,7 @@ t.text "return_url" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.enum "location_type", enum_type: "location_type" t.index ["lieu_id"], name: "index_rdv_plans_on_lieu_id" t.index ["motif_id"], name: "index_rdv_plans_on_motif_id" t.index ["planning_agent_id"], name: "index_rdv_plans_on_planning_agent_id" diff --git a/db/seeds.rb b/db/seeds.rb index 8f065c3f7d..1843e28373 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -6,3 +6,4 @@ load Rails.root.join("db/seeds/rdv_mairie.rb") load Rails.root.join("db/seeds/cdad.rb") load Rails.root.join("db/seeds/visioplainte.rb") +load Rails.root.join("db/seeds/ccas.rb") diff --git a/db/seeds/ccas.rb b/db/seeds/ccas.rb new file mode 100644 index 0000000000..c4e193abdb --- /dev/null +++ b/db/seeds/ccas.rb @@ -0,0 +1,51 @@ +service = Service.create!(name: "Action Sociale", short_name: "AS CCAS") + +Compte.new( + { + territory: { + name: "Montélimar", + departement_number: "26", + }, + organisation: { + name: "CCAS de Montélimar", + }, + lieu: { + address: "10 Rue Cuiraterie, 26200 Montélimar", + latitude: "44.5569244", + longitude: "4.7521632", + }, + agent: { + first_name: "Cécile", + last_name: "Astier", + email: "cecile.astier@demo-rdv-service-public.fr", + service_ids: [service.id], + }, + }, Domain::RDV_MAIRIE +).save! + +agent = Agent.find_by(email: "cecile.astier@demo-rdv-service-public.fr") + +agent.update!( + invitation_token: nil, + invitation_accepted_at: 10.days.ago, + invitation_created_at: nil, + invitation_sent_at: nil, + confirmed_at: 10.days.ago, + password: "Rdvservicepublictest1!" +) + +orga_ccas = agent.organisations.first + +user = User.new( + first_name: "Patricia", + last_name: "Duroy", + email: "patricia@demo.rdv-solidarites.fr", + birth_date: Date.parse("20/06/1975"), + password: "Rdvservicepublictest1!", + phone_number: "0101010101", + organisation_ids: [orga_ccas.id], + created_through: "user_sign_up" +) + +user.skip_confirmation! +user.save! diff --git a/spec/factories/user.rb b/spec/factories/user.rb index 484089eab2..6f80210cd7 100644 --- a/spec/factories/user.rb +++ b/spec/factories/user.rb @@ -38,6 +38,9 @@ confirmed_at { nil } password { nil } password_confirmation { nil } + before(:create) do |user, _| + user.skip_confirmation_notification! + end end trait :relative do responsible { association(:user) } diff --git a/spec/features/agents/create_rdv_with_rdv_plan_spec.rb b/spec/features/agents/create_rdv_with_rdv_plan_spec.rb index 18f0bf17ee..23bdc0e257 100644 --- a/spec/features/agents/create_rdv_with_rdv_plan_spec.rb +++ b/spec/features/agents/create_rdv_with_rdv_plan_spec.rb @@ -1,22 +1,58 @@ RSpec.describe "Les agents peuvent prendre un rendez-vous en passant par l'interface de rdv_plan" do let!(:organisation) { create(:organisation) } - let!(:agent) { create(:agent, basic_role_in_organisations: [organisation]) } + let!(:agent) do + create(:agent, basic_role_in_organisations: [organisation], rdv_notifications_level: :all) + end let!(:motif) { create(:motif, service: agent.services.first, organisation: organisation, location_type: :public_office) } let!(:lieu) { create(:lieu, organisation: organisation) } let!(:user) do - create(:user, organisations: [organisation]) # créé par appel d'api par l'appli qui s'intègre avec nous + create(:user, :unregistered, organisations: [organisation]) # créé par appel d'api par l'appli qui s'intègre avec nous end let(:rdv_plan) do create(:rdv_plan, user: user, planning_agent: agent) end - before { login_as(agent, scope: :agent) } + before do + stub_netsize_ok + login_as(agent, scope: :agent) + end it "permet de prendre un rendez-vous", js: true do visit agents_rdv_plan_path(rdv_plan.id) find(".fc-widget-content", match: :first).click expect(page).to have_content "Nouveau" expect(rdv_plan.reload.starts_at).to be_present + + find("label", text: "Sur place").click + click_on "Continuer" + expect(page).to have_content "Motif du rendez-vous " + click_on "Continuer" + + # On a sélectionné le premier créneau visible du calendrier, qui est donc dans le passé + # Hack : on modifie à la main le starts_at + rdv_plan.update!(starts_at: 2.weeks.from_now) + + fill_in("Email", with: "newaddress@exemple.com") + + expect(page).to have_content "Envoyer une notification de confirmation" + click_on "Confirmer le rendez-vous" + + expect(page).to have_content "Rendez-vous confirmé" + rdv = Rdv.last + expect(rdv).to have_attributes( + users: [user], + agents: [agent], + motif: motif, + lieu: lieu, + organisation: organisation + ) + expect(user.reload.email).to eq "newaddress@exemple.com" + + perform_enqueued_jobs + emails = ActionMailer::Base.deliveries + expect(emails.size).to eq(2) + expect(emails.map { [_1.to, _1.subject] }).to include([["newaddress@exemple.com"], a_string_matching(/RDV confirmé le/)]) + expect(emails.map { [_1.to, _1.subject] }).to include([[agent.email], a_string_matching(/Nouveau RDV ajouté sur votre agenda/)]) end end From a60e679170f6583d08e5b0cdbbee4a0402e351d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Ferrandis?= Date: Thu, 30 Jan 2025 07:45:27 +0100 Subject: [PATCH 5/9] =?UTF-8?q?Mise=20en=20place=20d'une=20scope=20de=20to?= =?UTF-8?q?us=20les=20territoires=20que=20je=20peux=20g=C3=A9rer=20(#5030)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Mise en place d'une scope de tous les territoires que je peux gérer * Corrige les offenses Rubocop * Emploie les suggestions d'Adrien ;) --- app/models/agent_territorial_access_right.rb | 9 +++ app/policies/agent/territory_policy.rb | 13 ++-- app/views/admin/organisations/new.html.slim | 3 +- spec/policies/agent/territory_policy_spec.rb | 72 +++++++++++++++++--- 4 files changed, 81 insertions(+), 16 deletions(-) diff --git a/app/models/agent_territorial_access_right.rb b/app/models/agent_territorial_access_right.rb index adb738f4c4..38de0b645f 100644 --- a/app/models/agent_territorial_access_right.rb +++ b/app/models/agent_territorial_access_right.rb @@ -5,4 +5,13 @@ class AgentTerritorialAccessRight < ApplicationRecord # Relations belongs_to :agent belongs_to :territory + + scope :without_any_rights_allowed, lambda { + where( + allow_to_manage_teams: false, + allow_to_manage_access_rights: false, + allow_to_invite_agents: false + ) + } + scope :with_some_rights_allowed, -> { without_any_rights_allowed.invert_where } end diff --git a/app/policies/agent/territory_policy.rb b/app/policies/agent/territory_policy.rb index b063bd2101..87aeb973a5 100644 --- a/app/policies/agent/territory_policy.rb +++ b/app/policies/agent/territory_policy.rb @@ -38,13 +38,14 @@ def initialize(current_agent, scope) end def resolve - @scope.joins(:roles).where(roles: { agent: @current_agent }) - end - end + territories_with_roles = @scope.joins(:roles) + .where(agent_territorial_roles: { agent: @current_agent }) - private + territories_with_rights = @scope.joins(:agent_territorial_access_rights) + .where(agent_territorial_access_rights: { agent: @current_agent }) + .merge(AgentTerritorialAccessRight.with_some_rights_allowed) - def access_rights - @access_rights ||= @current_agent.agent_territorial_access_rights.find_by(territory: @territory) + @scope.where_id_in_subqueries([territories_with_roles, territories_with_rights]) + end end end diff --git a/app/views/admin/organisations/new.html.slim b/app/views/admin/organisations/new.html.slim index 99f09a5b2e..0550391dcf 100644 --- a/app/views/admin/organisations/new.html.slim +++ b/app/views/admin/organisations/new.html.slim @@ -9,7 +9,8 @@ = f.input :name, label: "Nom de votre organisation", placeholder: "Maison départementale des solidarités de Beaupréau-en-Mauges" = f.association :territory, \ label: "Territoire", \ - collection: Agent::TerritoryPolicy::Scope.new(current_agent, current_agent.territories).resolve, \ + collection: [@organisation.territory], \ include_blank: false, \ + readonly: true, \ label_method: -> { _1.to_s } = f.submit value: "Enregistrer", class: "btn btn-primary" diff --git a/spec/policies/agent/territory_policy_spec.rb b/spec/policies/agent/territory_policy_spec.rb index 1d273ec05d..f81f9785c3 100644 --- a/spec/policies/agent/territory_policy_spec.rb +++ b/spec/policies/agent/territory_policy_spec.rb @@ -71,15 +71,69 @@ described_class.new(agent, Territory).resolve end - context "misc state" do - let!(:territory1) { create(:territory) } - let!(:territory2) { create(:territory) } - let!(:territory3) { create(:territory) } - let!(:agent) { create(:agent, role_in_territories: [territory1, territory2]) } - - it { is_expected.to include(territory1) } - it { is_expected.to include(territory2) } - it { is_expected.not_to include(territory3) } + context "many possible cases" do + let!(:agent) { create(:agent) } + + let!(:territory_no_rights_in_db) do + create(:territory, name: "Territoire où je n'ai aucun droit") + end + + let!(:territory_allow_nothing) do + create(:territory, name: "Territoire ou j'ai un AgentTerritorialAccessRight avec tout à false").tap do |territory| + agent.agent_territorial_access_rights.create!(territory:) + end + end + + let!(:territory_with_role) do + create(:territory, name: "Territoire ou j'ai un AgentTerritorialRole").tap do |territory| + agent.territorial_roles.create!(territory:) + end + end + + let!(:territory_manage_teams) do + create(:territory, name: "Territoire ou j'ai un AgentTerritorialAccessRight avec allow_to_manage_teams: true").tap do |territory| + agent.agent_territorial_access_rights.create!(territory:, allow_to_manage_teams: true) + end + end + let!(:territory_invite_agents) do + create(:territory, name: "Territoire ou j'ai un AgentTerritorialAccessRight avec allow_to_invite_agents: true").tap do |territory| + agent.agent_territorial_access_rights.create!(territory:, allow_to_invite_agents: true) + end + end + let!(:territory_manage_access_rights) do + create(:territory, name: "Territoire ou j'ai un AgentTerritorialAccessRight avec allow_to_manage_access_rights: true").tap do |territory| + agent.agent_territorial_access_rights.create!(territory:, allow_to_invite_agents: true) + end + end + + let!(:territory_with_role_and_rights) do + create(:territory, name: "Territoire ou j'ai un à la fois un role et des rights").tap do |territory| + agent.territorial_roles.create!(territory:) + agent.agent_territorial_access_rights.create!(territory:, allow_to_manage_access_rights: true) + end + end + + let!(:territory_with_role_for_another_agent) do + create(:territory, name: "Territoire où quelqu'un d'autre a un AgentTerritorialRole").tap do |territory| + create(:agent).territorial_roles.create!(territory:) + end + end + + let!(:territory_with_rights_for_another_agent) do + create(:territory, name: "Territoire où quelqu'un d'autre a un AgentTerritorialAccessRight avec allow_to_manage_teams: true").tap do |territory| + create(:agent).agent_territorial_access_rights.create!(territory:, allow_to_manage_teams: true) + end + end + + it "includes any territory where I either have a role or any right" do + expect(subject).to contain_exactly( + territory_with_role, + territory_manage_teams, + territory_invite_agents, + territory_manage_access_rights, + territory_with_role_and_rights + ) + end end end end From 594cfc461af8c9566006fef860ffea790f2c56ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Ferrandis?= Date: Thu, 30 Jan 2025 12:10:34 +0100 Subject: [PATCH 6/9] =?UTF-8?q?Rediriger=20vers=20la=20page=20pr=C3=A9c?= =?UTF-8?q?=C3=A9dente=20en=20cas=20d'action=20non=20autoris=C3=A9e=20(#50?= =?UTF-8?q?07)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Rediriger vers la page précédente en cas d'action non autorisée * Ajoute une condition pour éviter les boucles infinies --- .../concerns/admin/authenticated_controller_concern.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/controllers/concerns/admin/authenticated_controller_concern.rb b/app/controllers/concerns/admin/authenticated_controller_concern.rb index 7d232f2986..bbaec1e221 100644 --- a/app/controllers/concerns/admin/authenticated_controller_concern.rb +++ b/app/controllers/concerns/admin/authenticated_controller_concern.rb @@ -21,6 +21,13 @@ def user_for_paper_trail def agent_not_authorized(exception) policy_name = exception.policy.class.to_s.underscore flash[:error] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default - redirect_to authenticated_agent_root_path + + if request.referer.present? && + request.original_url != request.referer && # évite les boucles infinies + URI.parse(request.referer).host == current_domain.host_name # évite de rediriger vers l'extérieur + redirect_to request.referer + else + redirect_to authenticated_agent_root_url + end end end From cfa71fda082094f5975d9162a16d22ba74f8f6bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Ferrandis?= Date: Thu, 30 Jan 2025 12:17:51 +0100 Subject: [PATCH 7/9] Remonter l'agent dans Sentry en cas d'erreur de sync Outlook (#5032) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remonter l'agent dans Sentry en cas d'erreur de sync Outlook * Allez, on reste cohérents --- app/jobs/outlook/mass_create_event_job.rb | 2 ++ app/jobs/outlook/mass_destroy_event_job.rb | 2 ++ app/jobs/outlook/sync_event_job.rb | 2 ++ 3 files changed, 6 insertions(+) diff --git a/app/jobs/outlook/mass_create_event_job.rb b/app/jobs/outlook/mass_create_event_job.rb index fde9771a3e..2b1efd1e5d 100644 --- a/app/jobs/outlook/mass_create_event_job.rb +++ b/app/jobs/outlook/mass_create_event_job.rb @@ -3,6 +3,8 @@ class MassCreateEventJob < ApplicationJob queue_as :outlook_sync def perform(agent) + Sentry.set_user({ id: agent.id, role: "Agent", email: agent.email }) + agent.agents_rdvs.joins(:rdv).where(rdv: { starts_at: 1.month.ago.. }).find_each do |agents_rdv| Outlook::SyncEventJob.perform_later_for(agents_rdv) end diff --git a/app/jobs/outlook/mass_destroy_event_job.rb b/app/jobs/outlook/mass_destroy_event_job.rb index 64147fad73..ec4948e71e 100644 --- a/app/jobs/outlook/mass_destroy_event_job.rb +++ b/app/jobs/outlook/mass_destroy_event_job.rb @@ -3,6 +3,8 @@ class MassDestroyEventJob < ApplicationJob queue_as :outlook_sync def perform(agent) + Sentry.set_user({ id: agent.id, role: "Agent", email: agent.email }) + client = Outlook::ApiClient.new(agent) agent.agents_rdvs.where.not(outlook_id: nil).each do |agents_rdv| diff --git a/app/jobs/outlook/sync_event_job.rb b/app/jobs/outlook/sync_event_job.rb index 2e22dc702c..7db987c89c 100644 --- a/app/jobs/outlook/sync_event_job.rb +++ b/app/jobs/outlook/sync_event_job.rb @@ -20,6 +20,8 @@ def self.perform_later_for(agents_rdv) end def perform(agents_rdv_id, outlook_id, agent) + Sentry.set_user({ id: agent.id, role: "Agent", email: agent.email }) + @agents_rdv_id = agents_rdv_id @outlook_id = outlook_id @agent = agent From 9f682a5f33dbcd5a88842b2bfd3260e114fedf25 Mon Sep 17 00:00:00 2001 From: Adrien Di Pasquale Date: Thu, 30 Jan 2025 12:24:32 +0100 Subject: [PATCH 8/9] =?UTF-8?q?Ajout=20de=20validation=20de=20la=20coh?= =?UTF-8?q?=C3=A9rence=20entre=20l=E2=80=99orga=20du=20RDV=20et=20de=20son?= =?UTF-8?q?=20motif=20(#5025)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ajout de validation de la cohérence entre l’orga du RDV et de son motif * correction des specs pour la nouvelle validation --- app/models/rdv.rb | 7 +++ .../admin/api/agenda/rdvs_controller_spec.rb | 2 +- .../controllers/users/rdvs_controller_spec.rb | 32 +++++------ ...agent_can_configure_online_booking_spec.rb | 2 +- .../agents/agent_can_list_rdvs_spec.rb | 2 +- spec/features/agents/calendar_export_spec.rb | 2 +- spec/features/agents/rdv_details_spec.rb | 6 +-- .../rdvs_collectifs/duplicating_spec.rb | 5 +- spec/features/agents/renseigner_rdv_spec.rb | 2 +- .../anybody/anybody_can_see_stats_spec.rb | 5 +- .../can_add_a_user_to_a_rdv_collectif_spec.rb | 2 +- .../can_create_rdv_for_a_user_spec.rb | 2 +- .../super_admin/migrating_an_agent_spec.rb | 4 +- .../online_booking/with_invitation_spec.rb | 2 +- .../users/user_can_manage_rdv_spec.rb | 2 +- .../user_can_see_rdv_instruction_spec.rb | 5 +- .../prescripteur_rdv_wizard_spec.rb | 2 +- spec/helpers/rdvs_helper_spec.rb | 13 ++--- spec/jobs/ants/sync_appointment_job_spec.rb | 4 +- .../outlook/mass_destroy_event_job_spec.rb | 2 +- ...ppointment_serializer_and_listener_spec.rb | 20 +++---- ...erializer_and_listener_integration_spec.rb | 2 +- .../concerns/participation/creatable_spec.rb | 6 +-- .../participation/status_changeable_spec.rb | 3 +- spec/models/concerns/rdv/updatable_spec.rb | 13 ++--- spec/models/lieu_spec.rb | 10 ++-- spec/models/motif_spec.rb | 4 +- spec/models/outlook/api_client_spec.rb | 2 +- spec/models/participation_spec.rb | 5 +- spec/models/rdv_spec.rb | 6 +-- spec/models/stat_spec.rb | 53 +++++++++++-------- spec/requests/admin/rdv_collectifs_spec.rb | 2 +- .../swagger_doc/public_links_request_spec.rb | 2 +- .../api/v1/swagger_doc/rdvs_request_spec.rb | 26 ++++----- .../creneaux_search/calculator_spec.rb | 18 +++---- .../services/creneaux_search/for_user_spec.rb | 22 ++++---- spec/services/notifiers/rdv_base_spec.rb | 10 ++-- spec/services/notifiers/rdv_created_spec.rb | 2 +- spec/services/participation_exporter_spec.rb | 9 ++-- spec/sms/users/rdv_sms_spec.rb | 7 +-- spec/support/shared_context/search_context.rb | 7 +-- 41 files changed, 181 insertions(+), 151 deletions(-) diff --git a/app/models/rdv.rb b/app/models/rdv.rb index 0f27b1501d..eee31ad22a 100644 --- a/app/models/rdv.rb +++ b/app/models/rdv.rb @@ -67,6 +67,7 @@ def nested_lieu_attributes validates :participations, presence: true, unless: :collectif? validates :status, inclusion: { in: COLLECTIVE_RDV_STATUSES }, if: :collectif? + validate :validate_motif_organisation # Hooks after_save :associate_users_with_organisation @@ -426,4 +427,10 @@ def update_agents_unknown_past_rdv_count def set_created_by_for_participations participations.each { |participation| participation.created_by = created_by } end + + def validate_motif_organisation + if organisation_id != motif.organisation_id + errors.add(:motif_id, "n’appartient pas à l’organisation du RDV") + end + end end diff --git a/spec/controllers/admin/api/agenda/rdvs_controller_spec.rb b/spec/controllers/admin/api/agenda/rdvs_controller_spec.rb index 42c668fe6d..631a4d634f 100644 --- a/spec/controllers/admin/api/agenda/rdvs_controller_spec.rb +++ b/spec/controllers/admin/api/agenda/rdvs_controller_spec.rb @@ -64,7 +64,7 @@ it "does not show any info about the RDV and does not provide a link" do other_service = create(:service) given_agent = create(:agent, basic_role_in_organisations: [organisation], service: current_agent.services.first) - rdv_of_another_service = create(:rdv, agents: [given_agent], organisation: organisation, starts_at: mercredi_15h, motif: create(:motif, service: other_service)) + rdv_of_another_service = create(:rdv, agents: [given_agent], organisation: organisation, starts_at: mercredi_15h, motif: create(:motif, service: other_service, organisation:)) get :index, params: fullcalendar_time_range_params.merge(agent_id: given_agent.id, organisation_id: organisation.id, format: :json) expect(response.parsed_body.size).to eq(1) expect(response.parsed_body[0].keys).to eq(%w[start end title textColor backgroundColor extendedProps]) diff --git a/spec/controllers/users/rdvs_controller_spec.rb b/spec/controllers/users/rdvs_controller_spec.rb index 3f329c57ad..ad8c8eb1a8 100644 --- a/spec/controllers/users/rdvs_controller_spec.rb +++ b/spec/controllers/users/rdvs_controller_spec.rb @@ -90,7 +90,8 @@ describe "PUT #cancel" do context "when user belongs to rdv" do let(:token) { "12345" } - let(:rdv) { create(:rdv, starts_at: 5.hours.from_now) } + let(:organisation) { create(:organisation) } + let(:rdv) { create(:rdv, starts_at: 5.hours.from_now, organisation:) } before { allow_any_instance_of(Participation).to receive(:new_raw_invitation_token).and_return(token) } @@ -107,7 +108,7 @@ end context "when the motif is by phone and lieu is missing" do - let(:rdv) { create(:rdv, motif: create(:motif, :by_phone), lieu: nil, starts_at: 5.hours.from_now) } + let(:rdv) { create(:rdv, motif: create(:motif, :by_phone, organisation:), lieu: nil, starts_at: 5.hours.from_now, organisation:) } before { sign_in rdv.users.first } @@ -123,7 +124,7 @@ end context "when rdv is not cancellable" do - let(:rdv) { create(:rdv, starts_at: 3.hours.from_now) } + let(:rdv) { create(:rdv, starts_at: 3.hours.from_now, organisation:) } it "is not authorized" do sign_in rdv.users.first @@ -155,10 +156,10 @@ let(:user2) { create(:user) } let(:organisation) { create(:organisation) } let!(:agent) { create(:agent, basic_role_in_organisations: [organisation]) } - let(:rdv) { create(:rdv, users: [user], motif: motif, starts_at: starts_at, created_by: user) } - let(:rdv2) { create(:rdv, users: [user2], motif: create(:motif, :by_phone), lieu: nil, starts_at: starts_at, created_by: user) } + let(:rdv) { create(:rdv, users: [user], motif:, starts_at: starts_at, created_by: user, organisation:) } + let(:rdv2) { create(:rdv, users: [user2], motif: create(:motif, :by_phone, organisation:), lieu: nil, starts_at: starts_at, created_by: user, organisation:) } let(:starts_at) { Time.zone.parse("2020-10-20 10h30") } - let(:motif) { build(:motif, rdvs_editable_by_user: true, rdvs_cancellable_by_user: true) } + let(:motif) { build(:motif, rdvs_editable_by_user: true, rdvs_cancellable_by_user: true, organisation:) } def prevents_access_to_others_rdvs get :show, params: { id: rdv2.id } @@ -182,7 +183,7 @@ def prevents_access_to_others_rdvs end context "when the motif is by phone and lieu is missing" do - let(:rdv) { create(:rdv, users: [user], motif: create(:motif, :by_phone), lieu: nil, starts_at: starts_at, created_by: user) } + let(:rdv) { create(:rdv, users: [user], motif: create(:motif, :by_phone, organisation:), lieu: nil, starts_at: starts_at, created_by: user, organisation:) } it "shows the rdv" do get :show, params: { id: rdv.id } @@ -217,7 +218,7 @@ def prevents_access_to_others_rdvs end context "when the rdv is created by an agent" do - let(:rdv) { create(:rdv, users: [user], motif: motif, starts_at: starts_at, created_by: agent) } + let(:rdv) { create(:rdv, users: [user], motif: motif, starts_at: starts_at, created_by: agent, organisation:) } it "does show link to edit" do get :show, params: { id: rdv.id } @@ -234,7 +235,7 @@ def prevents_access_to_others_rdvs end context "when the rdv motif is not bookable_by_everone" do - let(:motif) { build(:motif, bookable_by: :agents, rdvs_editable_by_user: true, rdvs_cancellable_by_user: true) } + let(:motif) { build(:motif, bookable_by: :agents, rdvs_editable_by_user: true, rdvs_cancellable_by_user: true, organisation:) } it "does show link to edit" do get :show, params: { id: rdv.id } @@ -251,7 +252,7 @@ def prevents_access_to_others_rdvs end context "when the rdv is set as not editable" do - let(:motif) { build(:motif, rdvs_editable_by_user: false, rdvs_cancellable_by_user: true) } + let(:motif) { build(:motif, rdvs_editable_by_user: false, rdvs_cancellable_by_user: true, organisation:) } it "does show link to edit" do get :show, params: { id: rdv.id } @@ -268,7 +269,7 @@ def prevents_access_to_others_rdvs end context "when the rdv is set as not cancellable" do - let(:motif) { build(:motif, rdvs_editable_by_user: true, rdvs_cancellable_by_user: false) } + let(:motif) { build(:motif, rdvs_editable_by_user: true, rdvs_cancellable_by_user: false, organisation:) } it "does show link to edit" do get :show, params: { id: rdv.id } @@ -315,12 +316,13 @@ def prevents_access_to_others_rdvs describe "GET #index" do subject { get :index } + let(:organisation) { create(:organisation) } let!(:user) { create(:user) } let!(:user2) { create(:user) } - let!(:rdv1) { create(:rdv, users: [user], starts_at: 5.days.from_now) } - let!(:rdv2) { create(:rdv, users: [user], starts_at: 4.days.from_now) } - let!(:rdv3) { create(:rdv, motif: create(:motif, :by_phone), lieu: nil, users: [user], starts_at: 3.days.from_now) } - let!(:rdv_co) { create(:rdv, :collectif, users: [user], starts_at: 6.days.from_now) } + let!(:rdv1) { create(:rdv, users: [user], starts_at: 5.days.from_now, organisation:) } + let!(:rdv2) { create(:rdv, users: [user], starts_at: 4.days.from_now, organisation:) } + let!(:rdv3) { create(:rdv, motif: create(:motif, :by_phone, organisation:), lieu: nil, users: [user], starts_at: 3.days.from_now, organisation:) } + let!(:rdv_co) { create(:rdv, :collectif, users: [user], starts_at: 6.days.from_now, organisation:) } let!(:rdv_co_other_user) { create(:rdv, :collectif, users: [user2], starts_at: 8.days.from_now) } let!(:rdv_co_without_users) { create(:rdv, :collectif, :without_users, starts_at: 9.days.from_now) } diff --git a/spec/features/agents/agent_can_configure_online_booking_spec.rb b/spec/features/agents/agent_can_configure_online_booking_spec.rb index ef004585f4..4c5738e7b4 100644 --- a/spec/features/agents/agent_can_configure_online_booking_spec.rb +++ b/spec/features/agents/agent_can_configure_online_booking_spec.rb @@ -65,7 +65,7 @@ expect(page).to have_content("Réservable en ligne") expect(page).to have_content("Aucun rendez-vous avec des places disponibles") - create(:rdv, motif: motif, max_participants_count: 5) + create(:rdv, motif: motif, max_participants_count: 5, organisation:) visit admin_organisation_online_booking_path(organisation) expect(page).to have_css("i.fa-solid.fa-circle-check.color-scheme-green", count: 3) diff --git a/spec/features/agents/agent_can_list_rdvs_spec.rb b/spec/features/agents/agent_can_list_rdvs_spec.rb index 270d1793cc..7b9e61ec9a 100644 --- a/spec/features/agents/agent_can_list_rdvs_spec.rb +++ b/spec/features/agents/agent_can_list_rdvs_spec.rb @@ -17,7 +17,7 @@ def user_profile_path(user) before do [current_agent, agent_from_same_service, agent_from_other_service].each do |agent| - create(:rdv, organisation: organisation, agents: [agent], motif: create(:motif, service: agent.services.first)) + create(:rdv, organisation: organisation, agents: [agent], motif: create(:motif, service: agent.services.first, organisation:)) end end diff --git a/spec/features/agents/calendar_export_spec.rb b/spec/features/agents/calendar_export_spec.rb index 966ae9c708..217d9cb6ff 100644 --- a/spec/features/agents/calendar_export_spec.rb +++ b/spec/features/agents/calendar_export_spec.rb @@ -38,7 +38,7 @@ travel_to(Time.zone.local(2022, 7, 8)) org = create(:organisation, id: 123_000) agent = create(:agent, calendar_uid: SecureRandom.uuid, first_name: "Marceau", last_name: "COLIN") - motif = create(:motif, name: "Accompagnement individuel") + motif = create(:motif, name: "Accompagnement individuel", organisation: org) create(:rdv, motif: motif, agents: [agent], status: "unknown", starts_at: 1.day.from_now, uuid: "e0a8dbac-d06c-4d18-98c6-a48f47fddd4c", organisation: org, id: 456_000) create(:rdv, motif: motif, agents: [agent], status: "revoked", starts_at: 2.days.from_now, uuid: "749336ce-eaca-40a3-8c28-246ed8d18849", organisation: org, id: 789_000) motif_collectif = create(:motif, :collectif, name: "Atelier collectif", organisation: org) diff --git a/spec/features/agents/rdv_details_spec.rb b/spec/features/agents/rdv_details_spec.rb index 66c4b30b35..495d56f928 100644 --- a/spec/features/agents/rdv_details_spec.rb +++ b/spec/features/agents/rdv_details_spec.rb @@ -11,7 +11,7 @@ context "Motif is not collective" do let(:user) { create(:user, organisations: [organisation]) } - let(:motif) { create(:motif, service: service, name: "Renseignements") } + let(:motif) { create(:motif, service: service, name: "Renseignements", organisation:) } let(:rdv) { create(:rdv, agents: [agent], users: [user], motif: motif, organisation: organisation, starts_at: starts_at) } let!(:receipt) { create(:receipt, rdv: rdv, result: :sent, content: "Vous avez rendez-vous!") } let(:prescripteur) { create(:prescripteur, first_name: "Jean", last_name: "Valjean") } @@ -112,7 +112,7 @@ let(:user) { create(:user, organisations: [organisation]) } let(:user2) { create(:user, organisations: [organisation]) } let(:user3) { create(:user, organisations: [organisation]) } - let(:motif) { create(:motif, :collectif, service: service, name: "Atelier Colectif") } + let(:motif) { create(:motif, :collectif, service: service, name: "Atelier Colectif", organisation:) } let(:rdv) { create(:rdv, agents: [agent], users: [user, user2, user3], motif: motif, organisation: organisation, starts_at: starts_at, max_participants_count: 3) } let!(:receipt) { create(:receipt, rdv: rdv, result: :sent, content: "Vous avez rendez-vous!") } @@ -140,7 +140,7 @@ end context "when the rdv is by visio" do - let(:motif) { create(:motif, service: service, location_type: :visio) } + let(:motif) { create(:motif, service: service, location_type: :visio, organisation:) } let(:user) { create(:user, organisations: [organisation]) } context "when the agent participates in the rdv" do diff --git a/spec/features/agents/rdvs_collectifs/duplicating_spec.rb b/spec/features/agents/rdvs_collectifs/duplicating_spec.rb index 28fc3c0e6a..f0c80aaf21 100644 --- a/spec/features/agents/rdvs_collectifs/duplicating_spec.rb +++ b/spec/features/agents/rdvs_collectifs/duplicating_spec.rb @@ -33,10 +33,11 @@ end describe "when trying to duplicate a RDV the agent doesn't have access to" do + let(:other_organisation) { create(:organisation) } + let!(:motif_other_organisation) { create(:motif, :collectif, service: service, organisation: other_organisation, name: "Atelier Collectif") } let(:rdv_for_other_organisation) do - create(:rdv, motif: motif, organisation: other_organisation, name: "Traitement de texte") + create(:rdv, motif: motif_other_organisation, organisation: other_organisation, name: "Traitement de texte") end - let(:other_organisation) { create(:organisation) } it "doesn't prefill anything" do login_as(agent, scope: :agent) diff --git a/spec/features/agents/renseigner_rdv_spec.rb b/spec/features/agents/renseigner_rdv_spec.rb index e5e11bd71a..5ed6361480 100644 --- a/spec/features/agents/renseigner_rdv_spec.rb +++ b/spec/features/agents/renseigner_rdv_spec.rb @@ -3,7 +3,7 @@ let(:organisation) { create(:organisation) } let(:service) { create(:service) } let!(:rdv) do - create(:rdv, :past, status: :unknown, agents: [agent], motif: create(:motif, service: service), organisation: organisation) + create(:rdv, :past, status: :unknown, agents: [agent], motif: create(:motif, service: service, organisation:), organisation: organisation) end before { login_as(agent, scope: :agent) } diff --git a/spec/features/anybody/anybody_can_see_stats_spec.rb b/spec/features/anybody/anybody_can_see_stats_spec.rb index 29da6aee23..edf3974238 100644 --- a/spec/features/anybody/anybody_can_see_stats_spec.rb +++ b/spec/features/anybody/anybody_can_see_stats_spec.rb @@ -1,4 +1,7 @@ RSpec.describe "Anybody can see stats" do + let(:organisation) { create(:organisation) } + let(:motif) { create(:motif, :collectif, organisation:) } + it "displays all the stats" do visit root_path click_link "Statistiques" @@ -12,7 +15,7 @@ expect(page).to have_content("0 ont des créneaux ouverts au public") create(:plage_ouverture, motifs: [create(:motif)]) # reservable online plage - create(:rdv, motif: create(:motif, :collectif)) # reservable online RDV collectif + create(:rdv, motif:, organisation:) # reservable online RDV collectif visit stats_path expect(page).to have_content("2 ont des créneaux ouverts au public") diff --git a/spec/features/prescripteurs/can_add_a_user_to_a_rdv_collectif_spec.rb b/spec/features/prescripteurs/can_add_a_user_to_a_rdv_collectif_spec.rb index f46a204894..514353e055 100644 --- a/spec/features/prescripteurs/can_add_a_user_to_a_rdv_collectif_spec.rb +++ b/spec/features/prescripteurs/can_add_a_user_to_a_rdv_collectif_spec.rb @@ -84,7 +84,7 @@ context "when creneau is taken by someone else during booking process" do let!(:fallback_rdv_collectif_2_hours_later) do - create(:rdv, :without_users, motif: motif_collectif, agents: [agent], lieu: lieu, starts_at: rdv_collectif.starts_at + 2.hours) + create(:rdv, :without_users, motif: motif_collectif, agents: [agent], lieu: lieu, starts_at: rdv_collectif.starts_at + 2.hours, organisation:) end it "redirects to creneau search with error message" do diff --git a/spec/features/prescripteurs/can_create_rdv_for_a_user_spec.rb b/spec/features/prescripteurs/can_create_rdv_for_a_user_spec.rb index c89f985969..e621801e66 100644 --- a/spec/features/prescripteurs/can_create_rdv_for_a_user_spec.rb +++ b/spec/features/prescripteurs/can_create_rdv_for_a_user_spec.rb @@ -33,7 +33,7 @@ fill_in "Téléphone", with: "0611223344" # On simule que le créneau choisi est simultanément pris par quelqu'un d'autre - create(:rdv, starts_at: Time.zone.local(2022, 11, 15, 8, 0, 0), motif: motif, agents: [agent], lieu: lieu) + create(:rdv, starts_at: Time.zone.local(2022, 11, 15, 8, 0, 0), motif: motif, agents: [agent], lieu: lieu, organisation:) click_on "Confirmer le rendez-vous" expect(page).to have_content("Ce créneau n'est plus disponible. Veuillez en choisir un autre.") # Dans ce cas, retour à l'étape de choix du lieu diff --git a/spec/features/super_admin/migrating_an_agent_spec.rb b/spec/features/super_admin/migrating_an_agent_spec.rb index 03d65ee559..958cbfd4e6 100644 --- a/spec/features/super_admin/migrating_an_agent_spec.rb +++ b/spec/features/super_admin/migrating_an_agent_spec.rb @@ -4,8 +4,8 @@ let!(:new_organisation) { create :organisation, territory: old_organisation.territory } let(:agent) { create :agent, admin_role_in_organisations: [old_organisation] } - let!(:motif1) { create :motif } - let!(:motif2) { create :motif } + let!(:motif1) { create :motif, organisation: old_organisation } + let!(:motif2) { create :motif, organisation: old_organisation } let!(:rdv1) { create :rdv, organisation: old_organisation, agents: [agent], motif: motif1 } let!(:rdv2) { create :rdv, organisation: old_organisation, agents: [agent], motif: motif1 } let!(:rdv3) { create :rdv, organisation: old_organisation, agents: [agent], motif: motif2 } diff --git a/spec/features/users/online_booking/with_invitation_spec.rb b/spec/features/users/online_booking/with_invitation_spec.rb index e217d34106..d9d96a8611 100644 --- a/spec/features/users/online_booking/with_invitation_spec.rb +++ b/spec/features/users/online_booking/with_invitation_spec.rb @@ -276,7 +276,7 @@ create(:motif, name: "RSA orientation collectif", collectif: true, bookable_by: "agents_and_prescripteurs_and_invited_users", organisation: organisation, service: agent.services.first, motif_category:) end - let!(:collectif_rdv) { create(:rdv, motif: collectif_motif, starts_at: 1.week.from_now, max_participants_count: 10) } + let!(:collectif_rdv) { create(:rdv, motif: collectif_motif, starts_at: 1.week.from_now, max_participants_count: 10, organisation:) } before do travel_to(now) diff --git a/spec/features/users/user_can_manage_rdv_spec.rb b/spec/features/users/user_can_manage_rdv_spec.rb index 1cb001a8a4..5211876569 100644 --- a/spec/features/users/user_can_manage_rdv_spec.rb +++ b/spec/features/users/user_can_manage_rdv_spec.rb @@ -58,7 +58,7 @@ let!(:agent2) { create(:agent, organisations: [organisation]) } let!(:user) { create(:user, organisations: [organisation]) } let!(:motif) { create(:motif, organisation: organisation) } - let!(:rdv) { create(:rdv, users: [user], agents: [agent1], starts_at: 10.days.from_now, created_by: user, motif: motif, lieu: lieu) } + let!(:rdv) { create(:rdv, users: [user], agents: [agent1], starts_at: 10.days.from_now, created_by: user, motif: motif, lieu: lieu, organisation:) } let!(:plage_ouverture) { create(:plage_ouverture, :weekdays, motifs: [motif], lieu: lieu, organisation: organisation, agent: agent2) } before do diff --git a/spec/features/users/user_can_see_rdv_instruction_spec.rb b/spec/features/users/user_can_see_rdv_instruction_spec.rb index abfda8f45b..178752198e 100644 --- a/spec/features/users/user_can_see_rdv_instruction_spec.rb +++ b/spec/features/users/user_can_see_rdv_instruction_spec.rb @@ -1,7 +1,8 @@ RSpec.describe "User can see RDV instructions" do it "can see RDV inscrution on RDV page" do - motif = create(:motif, restriction_for_rdv: "Pensez à prendre votre carnet de santé") - rdv = create(:rdv, motif: motif) + organisation = create(:organisation) + motif = create(:motif, restriction_for_rdv: "Pensez à prendre votre carnet de santé", organisation:) + rdv = create(:rdv, motif:, organisation:) user = rdv.users.first login_as(user, scope: :user) visit users_rdv_path(rdv) diff --git a/spec/form_models/prescripteur_rdv_wizard_spec.rb b/spec/form_models/prescripteur_rdv_wizard_spec.rb index 2437aff52c..2321cc2d26 100644 --- a/spec/form_models/prescripteur_rdv_wizard_spec.rb +++ b/spec/form_models/prescripteur_rdv_wizard_spec.rb @@ -32,7 +32,7 @@ before do motif.update!(collectif: true) - rdv = create(:rdv, motif: motif, agents: [agent]) + rdv = create(:rdv, motif: motif, agents: [agent], organisation:) attributes["rdv_collectif_id"] = rdv.id stub_netsize_ok diff --git a/spec/helpers/rdvs_helper_spec.rb b/spec/helpers/rdvs_helper_spec.rb index 0c74905508..2bd2c370d4 100644 --- a/spec/helpers/rdvs_helper_spec.rb +++ b/spec/helpers/rdvs_helper_spec.rb @@ -1,9 +1,10 @@ RSpec.describe RdvsHelper do include ActionView::Helpers::DateHelper - let(:motif) { build(:motif, name: "Consultation normale") } + let(:organisation) { create(:organisation) } + let(:motif) { build(:motif, name: "Consultation normale", organisation:) } let(:user) { build(:user, first_name: "Marie", last_name: "DENIS") } - let(:rdv) { build(:rdv, users: [user], motif: motif) } + let(:rdv) { build(:rdv, users: [user], motif: motif, organisation:) } describe "#rdv_title_for_agent" do subject { helper.rdv_title_for_agent(rdv) } @@ -143,15 +144,15 @@ end it "return simple confirm message for a revoked future RDV with invisible motif" do - motif = create(:motif, visibility_type: Motif::INVISIBLE) - rdv = create(:rdv, motif: motif) + motif = create(:motif, visibility_type: Motif::INVISIBLE, organisation:) + rdv = create(:rdv, motif: motif, organisation:) expected = I18n.t("admin.rdvs.message.confirm.simple_cancel") expect(change_status_confirmation_message(rdv, "revoked")).to eq(expected) end it "return simple confirm message for a revoked future RDV with visible and notified motif" do - motif = create(:motif, visibility_type: Motif::VISIBLE_AND_NOTIFIED) - rdv = create(:rdv, motif: motif) + motif = create(:motif, visibility_type: Motif::VISIBLE_AND_NOTIFIED, organisation:) + rdv = create(:rdv, motif: motif, organisation:) expected = I18n.t("admin.rdvs.message.confirm.cancel_with_notification") expect(change_status_confirmation_message(rdv, "revoked")).to eq(expected) end diff --git a/spec/jobs/ants/sync_appointment_job_spec.rb b/spec/jobs/ants/sync_appointment_job_spec.rb index 0543aef9ff..34e34a1fee 100644 --- a/spec/jobs/ants/sync_appointment_job_spec.rb +++ b/spec/jobs/ants/sync_appointment_job_spec.rb @@ -2,7 +2,7 @@ context "Nouveau RDV ANTS" do let!(:organisation) { create(:organisation, verticale: :rdv_mairie) } let!(:lieu) { create(:lieu, organisation:, name: "Mairie de Saumur") } - let!(:motif) { create(:motif, motif_category: create(:motif_category, :passeport)) } + let!(:motif) { create(:motif, motif_category: create(:motif_category, :passeport), organisation:) } let!(:user) { create(:user, ants_pre_demande_number: "A123456789", organisations: [organisation]) } let!(:rdv) { create(:rdv, motif:, users: [user], lieu:, organisation:, starts_at: Time.zone.parse("2020-04-20 08:00:00")) } @@ -21,7 +21,7 @@ context "Synchro pour un RDV ANTS dans le passé" do let!(:organisation) { create(:organisation, verticale: :rdv_mairie) } let!(:lieu) { create(:lieu, organisation:, name: "Mairie de Saumur") } - let!(:motif) { create(:motif, motif_category: create(:motif_category, :passeport)) } + let!(:motif) { create(:motif, motif_category: create(:motif_category, :passeport), organisation:) } let!(:user) { create(:user, ants_pre_demande_number: "A123456789", organisations: [organisation]) } let!(:rdv) { create(:rdv, motif:, users: [user], lieu:, organisation:, starts_at: Time.zone.parse("2020-04-20 08:00:00")) } diff --git a/spec/jobs/outlook/mass_destroy_event_job_spec.rb b/spec/jobs/outlook/mass_destroy_event_job_spec.rb index 2a8ca93761..f15487aec5 100644 --- a/spec/jobs/outlook/mass_destroy_event_job_spec.rb +++ b/spec/jobs/outlook/mass_destroy_event_job_spec.rb @@ -2,7 +2,7 @@ RSpec.describe Outlook::MassDestroyEventJob, type: :job do let(:organisation) { create(:organisation) } - let(:motif) { create(:motif, name: "Super Motif", location_type: :phone) } + let(:motif) { create(:motif, name: "Super Motif", location_type: :phone, organisation:) } # We need to create a fake agent to initialize a RDV as they have a validation on agents which prevents us to control the data in its AgentsRdv let(:fake_agent) { create(:agent) } let(:agent) { create(:agent, microsoft_graph_token: "token", refresh_microsoft_graph_token: "refresh_token") } diff --git a/spec/models/concerns/ants/appointment_serializer_and_listener_spec.rb b/spec/models/concerns/ants/appointment_serializer_and_listener_spec.rb index 0d2263193d..ce02828d25 100644 --- a/spec/models/concerns/ants/appointment_serializer_and_listener_spec.rb +++ b/spec/models/concerns/ants/appointment_serializer_and_listener_spec.rb @@ -30,7 +30,7 @@ describe "Création de RDV, l’usager a un numéro de pré-demande ANTS" do let(:organisation) { create(:organisation, verticale: :rdv_mairie) } let(:lieu) { create(:lieu, organisation:, name: "Mairie de Saumur") } - let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport)) } + let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport), organisation:) } let(:user) { create(:user, ants_pre_demande_number: "A123456789", organisations: [organisation]) } let!(:rdv) { build(:rdv, motif:, users: [user], lieu:, organisation:, starts_at: Time.zone.parse("2020-04-20 08:00:00")) } @@ -68,7 +68,7 @@ describe "Création de RDV, l’usager n’a pas de numéro de pré-demande ANTS" do let(:organisation) { create(:organisation, verticale: :rdv_mairie) } let(:lieu) { create(:lieu, organisation:, name: "Mairie de Saumur") } - let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport)) } + let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport), organisation:) } let(:user) { create(:user, ants_pre_demande_number: "", organisations: [organisation]) } let(:rdv) { build(:rdv, motif:, users: [user], lieu:, organisation:, starts_at: Time.zone.parse("2020-04-20 08:00:00")) } @@ -96,7 +96,7 @@ describe "Suppression de RDV" do let(:organisation) { create(:organisation, verticale: :rdv_mairie) } let(:lieu) { create(:lieu, organisation:, name: "Mairie de Saumur") } - let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport)) } + let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport), organisation:) } let(:user) { create(:user, ants_pre_demande_number: "A123456789", organisations: [organisation]) } let!(:rdv) { create(:rdv, motif:, users: [user], lieu:, organisation:, starts_at: Time.zone.parse("2020-04-20 08:00:00")) } @@ -146,7 +146,7 @@ describe "Annulation de RDV" do let(:organisation) { create(:organisation, verticale: :rdv_mairie) } let(:lieu) { create(:lieu, organisation:, name: "Mairie de Saumur") } - let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport)) } + let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport), organisation:) } let(:user) { create(:user, ants_pre_demande_number: "A123456789", organisations: [organisation]) } let!(:rdv) { create(:rdv, motif:, users: [user], lieu:, organisation:, starts_at: Time.zone.parse("2020-04-20 08:00:00")) } @@ -197,7 +197,7 @@ describe "Annulation de RDV, l’API de l’ANTS renvoie un statut consumed" do let(:organisation) { create(:organisation, verticale: :rdv_mairie) } let(:lieu) { create(:lieu, organisation:, name: "Mairie de Saumur") } - let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport)) } + let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport), organisation:) } let!(:user) { create(:user, ants_pre_demande_number: "A123456789", organisations: [organisation]) } let!(:rdv) { create(:rdv, motif:, users: [user], lieu:, organisation:, starts_at: Time.zone.parse("2020-04-20 08:00:00")) } @@ -223,7 +223,7 @@ describe "le RDV est marqué comme vu alors qu’il avait été annulé" do let(:organisation) { create(:organisation, verticale: :rdv_mairie) } let(:lieu) { create(:lieu, organisation:, name: "Mairie de Saumur") } - let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport)) } + let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport), organisation:) } let(:user) { create(:user, ants_pre_demande_number: "A123456789", organisations: [organisation]) } let!(:rdv) { create(:rdv, motif:, users: [user], lieu:, organisation:, starts_at: Time.zone.parse("2020-04-20 08:00:00")) } @@ -290,7 +290,7 @@ describe "l’usager change de numéro de pré-demande ANTS après avoir pris RDV avec un précédent numéro" do let(:organisation) { create(:organisation, verticale: :rdv_mairie) } let(:lieu) { create(:lieu, organisation:, name: "Mairie de Saumur") } - let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport)) } + let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport), organisation:) } let!(:user) { create(:user, ants_pre_demande_number: "A123456789", organisations: [organisation]) } let!(:rdv) { create(:rdv, motif:, users: [user], lieu:, organisation:, starts_at: Time.zone.parse("2020-04-20 08:00:00")) } @@ -329,7 +329,7 @@ describe "Le lieu change de nom" do let(:organisation) { create(:organisation, verticale: :rdv_mairie) } let(:lieu) { create(:lieu, organisation:, name: "Mairie de Saumur") } - let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport)) } + let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport), organisation:) } let!(:user) { create(:user, ants_pre_demande_number: "A123456789", organisations: [organisation]) } let!(:rdv) { create(:rdv, motif:, users: [user], lieu:, organisation:, starts_at: Time.zone.parse("2020-04-20 08:00:00")) } @@ -368,7 +368,7 @@ describe "Le lieu change de nom mais le RDV ANTS de l’usager est dans le passé" do let(:organisation) { create(:organisation, verticale: :rdv_mairie) } let(:lieu) { create(:lieu, organisation:, name: "Mairie de Saumur") } - let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport)) } + let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport), organisation:) } let!(:user) { create(:user, ants_pre_demande_number: "A123456789", organisations: [organisation]) } let!(:rdv) { create(:rdv, motif:, users: [user], lieu:, organisation:, starts_at: Time.zone.parse("2020-04-20 08:00:00")) } @@ -407,7 +407,7 @@ describe "un usager est retiré du RDV" do let(:organisation) { create(:organisation, verticale: :rdv_mairie) } let(:lieu) { create(:lieu, organisation:, name: "Mairie de Saumur") } - let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport)) } + let(:motif) { create(:motif, motif_category: create(:motif_category, :passeport), organisation:) } let!(:user) { create(:user, ants_pre_demande_number: "A123456789", organisations: [organisation]) } let!(:rdv) { create(:rdv, motif:, users: [user], lieu:, organisation:, starts_at: Time.zone.parse("2020-04-20 08:00:00")) } diff --git a/spec/models/concerns/outlook/event_serializer_and_listener_integration_spec.rb b/spec/models/concerns/outlook/event_serializer_and_listener_integration_spec.rb index 43cf962a0c..b753193b89 100644 --- a/spec/models/concerns/outlook/event_serializer_and_listener_integration_spec.rb +++ b/spec/models/concerns/outlook/event_serializer_and_listener_integration_spec.rb @@ -6,8 +6,8 @@ end let(:agent) { create(:agent, microsoft_graph_token: "token") } - let(:motif) { create(:motif, name: "Super Motif", location_type: :phone) } let(:organisation) { create(:organisation) } + let(:motif) { create(:motif, name: "Super Motif", location_type: :phone, organisation:) } let(:user) { create(:user, email: "user@example.fr", first_name: "First", last_name: "Last", organisations: [organisation]) } let(:expected_headers) do diff --git a/spec/models/concerns/participation/creatable_spec.rb b/spec/models/concerns/participation/creatable_spec.rb index 5dda4beefc..87f7c1bb1f 100644 --- a/spec/models/concerns/participation/creatable_spec.rb +++ b/spec/models/concerns/participation/creatable_spec.rb @@ -8,14 +8,14 @@ let(:agent) { create :agent } let(:user) { create :user } let(:user3) { create :user } + let!(:organisation) { create(:organisation) } let(:relative) do create(:user, :relative, :with_no_email, responsible: user, first_name: "Petit", last_name: "Bébé") end - let(:rdv) { create :rdv, :collectif, :without_users, starts_at: Time.zone.tomorrow, agents: [agent] } + let(:rdv) { create :rdv, :collectif, :without_users, starts_at: Time.zone.tomorrow, agents: [agent], organisation: } describe "triggers webhook" do let!(:webhook_endpoint) { create(:webhook_endpoint, organisation: organisation, subscriptions: ["rdv"]) } - let!(:organisation) { create(:organisation, rdvs: [rdv]) } let(:participation1) { build(:participation, rdv: rdv, user: user) } it "sends a webhook" do @@ -68,7 +68,6 @@ end describe "l’usager ajouté n’appartient pas encore à l’organisation" do - let!(:organisation) { create(:organisation, rdvs: [rdv]) } let(:participation) { build(:participation, rdv:, user:) } it "ajoute l’orga à l’usager" do @@ -79,7 +78,6 @@ end describe "l’usager ajouté appartient déjà à l’organisation" do - let!(:organisation) { create(:organisation, rdvs: [rdv]) } let!(:user) { create(:user, organisations: [organisation]) } let(:participation) { build(:participation, rdv:, user:) } diff --git a/spec/models/concerns/participation/status_changeable_spec.rb b/spec/models/concerns/participation/status_changeable_spec.rb index 884703b24b..ebca41106b 100644 --- a/spec/models/concerns/participation/status_changeable_spec.rb +++ b/spec/models/concerns/participation/status_changeable_spec.rb @@ -4,8 +4,7 @@ describe "Participation change status" do let(:agent) { create :agent } let(:rdv) { create :rdv, :collectif, starts_at: Time.zone.tomorrow, agents: [agent] } - let!(:organisation) { create(:organisation, rdvs: [rdv]) } - let!(:webhook_endpoint) { create(:webhook_endpoint, organisation: organisation, subscriptions: ["rdv"]) } + let!(:webhook_endpoint) { create(:webhook_endpoint, organisation: rdv.organisation, subscriptions: ["rdv"]) } let(:participation1) { create(:participation, rdv: rdv) } let(:participation_with_excused_status) { create(:participation, rdv: rdv) } let(:participation_with_lifecycle_disabled) { create(:participation, rdv: rdv, send_lifecycle_notifications: false) } diff --git a/spec/models/concerns/rdv/updatable_spec.rb b/spec/models/concerns/rdv/updatable_spec.rb index 5a2d2376ef..8692d62a67 100644 --- a/spec/models/concerns/rdv/updatable_spec.rb +++ b/spec/models/concerns/rdv/updatable_spec.rb @@ -4,9 +4,11 @@ allow(Devise.token_generator).to receive(:generate).and_return("12345678") end + let(:organisation) { create(:organisation) } let(:agent) { create(:agent, rdv_notifications_level: "all") } - let(:rdv) { create(:rdv, agents: [agent]) } - let(:rdv_co) { create(:rdv, :collectif, users: [user_co1, user_co2], agents: [agent]) } + let(:rdv) { create(:rdv, agents: [agent], organisation:) } + let(:motif) { create(:motif, :collectif, organisation:) } + let(:rdv_co) { create(:rdv, motif:, users: [user_co1, user_co2], agents: [agent], organisation:) } let(:user_co1) { create(:user) } let(:user_co2) { create(:user) } let(:user) { rdv.users.first } @@ -138,7 +140,6 @@ describe "triggers webhook" do let!(:webhook_endpoint) { create(:webhook_endpoint, organisation: organisation, subscriptions: ["rdv"]) } - let!(:organisation) { create(:organisation, rdvs: [rdv]) } it "sends a webhook" do rdv.reload @@ -158,8 +159,8 @@ } end # The reload makes sure we have the proper .previous_changes - let(:rdv) { create(:rdv, agents: [agent], motif: motif, users: [user_staying, user_removed]).reload } - let(:motif) { create(:motif, :collectif) } + let(:rdv) { create(:rdv, agents: [agent], motif: motif, users: [user_staying, user_removed], organisation:).reload } + let(:motif) { create(:motif, :collectif, organisation:) } let(:user_staying) { create(:user, first_name: "Stay") } let(:user_added) { create(:user, first_name: "Add") } let(:user_removed) { create(:user, first_name: "Remove") } @@ -171,7 +172,7 @@ end context "quand un des usager qu'on ajoute est déjà inscrit comme participant au rdv" do - let(:rdv) { create(:rdv, agents: [agent], motif: motif, users: [user_staying, user_added]).reload } + let(:rdv) { create(:rdv, agents: [agent], motif: motif, users: [user_staying, user_added], organisation:).reload } let(:attributes) do { diff --git a/spec/models/lieu_spec.rb b/spec/models/lieu_spec.rb index 6d49793bd9..3fe5d9be09 100644 --- a/spec/models/lieu_spec.rb +++ b/spec/models/lieu_spec.rb @@ -133,15 +133,15 @@ end context "for a motif collectif" do - let!(:motif) { create(:motif, collectif: true) } + let!(:motif) { create(:motif, collectif: true, organisation:) } before do - create(:rdv, :collectif, motif: motif, lieu: lieu) # valid rdv - create(:rdv, :collectif, motif: motif, status: :revoked) - create(:rdv, :collectif, motif: motif, max_participants_count: 3).tap do |rdv| # fully booked + create(:rdv, :collectif, motif: motif, lieu: lieu, organisation:) # valid rdv + create(:rdv, :collectif, motif: motif, status: :revoked, organisation:) + create(:rdv, :collectif, motif: motif, max_participants_count: 3, organisation:).tap do |rdv| # fully booked rdv.update_columns(users_count: 3) # rubocop:disable Rails/SkipsModelValidations end - create(:rdv, :collectif, motif: motif, starts_at: 3.days.ago) # in the past + create(:rdv, :collectif, motif: motif, starts_at: 3.days.ago, organisation:) # in the past end it "only returns lieux with a rdv that is available for reservation" do diff --git a/spec/models/motif_spec.rb b/spec/models/motif_spec.rb index 6a627b2c06..b5903197b6 100644 --- a/spec/models/motif_spec.rb +++ b/spec/models/motif_spec.rb @@ -272,14 +272,14 @@ context "when motif is used by any RDV" do it "is forbidden from changing location_type" do - motif = create(:motif, location_type: "public_office").tap { create(:rdv, motif: _1) } + motif = create(:motif, location_type: "public_office", organisation:).tap { create(:rdv, motif: _1, organisation:) } motif.update(location_type: "phone") expect(motif.errors[:location_type]).to include("ne peut être modifié car le motif est utilisé pour un RDV") expect(motif.reload.location_type).to eq("public_office") end it "is allowed to change :collectif" do - motif = create(:motif, collectif: false).tap { create(:rdv, motif: _1) } + motif = create(:motif, collectif: false, organisation:).tap { create(:rdv, motif: _1, organisation:) } motif.update(collectif: true) expect(motif.errors[:collectif]).to include("ne peut être modifié car le motif est utilisé pour un RDV") expect(motif.reload.collectif).to be(false) diff --git a/spec/models/outlook/api_client_spec.rb b/spec/models/outlook/api_client_spec.rb index 09c28e3bd3..120b37fa25 100644 --- a/spec/models/outlook/api_client_spec.rb +++ b/spec/models/outlook/api_client_spec.rb @@ -32,7 +32,7 @@ transactionId: "agents_rdv-#{agents_rdv.id}", } end - let(:motif) { create(:motif, name: "Super Motif", location_type: :phone) } + let(:motif) { create(:motif, name: "Super Motif", location_type: :phone, organisation:) } let(:agent) { create(:agent, microsoft_graph_token: "token", refresh_microsoft_graph_token: "refresh_token") } let(:user) { create(:user, email: "user@example.fr", first_name: "First", last_name: "Last", organisations: [organisation]) } let(:rdv) { create(:rdv, users: [user], motif: motif, organisation: organisation, starts_at: Time.zone.parse("2023-01-01 11h00"), duration_in_min: 30, agents: [agent]) } diff --git a/spec/models/participation_spec.rb b/spec/models/participation_spec.rb index 934adf812b..47c2ecf1c5 100644 --- a/spec/models/participation_spec.rb +++ b/spec/models/participation_spec.rb @@ -2,11 +2,12 @@ describe "Participation is getting Rdv parent status" do %w[collectif individuel].each do |rdv_type| describe "For #{rdv_type} rdv" do - rdv_type == "collectif" ? let(:motif) { create(:motif, :collectif) } : let(:motif) { create(:motif) } + rdv_type == "collectif" ? let(:motif) { create(:motif, :collectif, organisation:) } : let(:motif) { create(:motif, organisation:) } + let(:organisation) { create(:organisation) } let(:agent) { create(:agent) } let(:user) { create(:user) } let(:user2) { create(:user) } - let(:rdv) { create(:rdv, starts_at: Time.zone.tomorrow, users: [user, user2], motif: motif, agents: [agent]) } + let(:rdv) { create(:rdv, starts_at: Time.zone.tomorrow, users: [user, user2], motif: motif, agents: [agent], organisation:) } describe "when rdv is created with user" do it do diff --git a/spec/models/rdv_spec.rb b/spec/models/rdv_spec.rb index d9b7e050c9..e065bffdcd 100644 --- a/spec/models/rdv_spec.rb +++ b/spec/models/rdv_spec.rb @@ -260,19 +260,19 @@ describe "#visible" do it "don't return rdv with invisible motif" do motif = create(:motif, :invisible) - create(:rdv, motif: motif) + create(:rdv, motif: motif, organisation: motif.organisation) expect(described_class.visible).to be_empty end it "return rdv with visible and notified motif" do motif = create(:motif, :visible_and_notified) - rdv = create(:rdv, motif: motif) + rdv = create(:rdv, motif: motif, organisation: motif.organisation) expect(described_class.visible).to contain_exactly(rdv) end it "return rdv with visible and not notified motif" do motif = create(:motif, :visible_and_not_notified) - rdv = create(:rdv, motif: motif) + rdv = create(:rdv, motif: motif, organisation: motif.organisation) expect(described_class.visible).to contain_exactly(rdv) end end diff --git a/spec/models/stat_spec.rb b/spec/models/stat_spec.rb index 532243b037..0d6bddcf49 100644 --- a/spec/models/stat_spec.rb +++ b/spec/models/stat_spec.rb @@ -1,50 +1,52 @@ RSpec.describe Stat, type: :model do describe "#rdvs_group_by_type" do + let(:organisation) { create(:organisation) } + it "return empty hash without rdv" do stats = described_class.new(rdvs: Rdv.all) expect(stats.rdvs_group_by_type).to eq({}) end it "return 2=>1 with one home rdv" do - home_motif = create(:motif, location_type: :home) - create(:rdv, motif: home_motif, created_at: Time.zone.parse("2020-04-07 10:00")) + home_motif = create(:motif, location_type: :home, organisation:) + create(:rdv, motif: home_motif, created_at: Time.zone.parse("2020-04-07 10:00"), organisation:) stats = described_class.new(rdvs: Rdv.all) expect(stats.rdvs_group_by_type[["à domicile", "05/04/2020"]]).to eq(1) end it "return 2=>2 with two home rdv" do - home_motif = create(:motif, location_type: :home) - create_list(:rdv, 2, motif: home_motif, created_at: Time.zone.parse("2020-04-07 10:00")) + home_motif = create(:motif, location_type: :home, organisation:) + create_list(:rdv, 2, motif: home_motif, created_at: Time.zone.parse("2020-04-07 10:00"), organisation:) stats = described_class.new(rdvs: Rdv.all) expect(stats.rdvs_group_by_type[["à domicile", "05/04/2020"]]).to eq(2) end it "return 2=>2 with two different motif of home rdv" do - home_motif = create(:motif, location_type: :home) - other_home_motif = create(:motif, location_type: :home) - create(:rdv, motif: home_motif, created_at: Time.zone.parse("2020-04-07 10:00")) - create(:rdv, motif: other_home_motif, created_at: Time.zone.parse("2020-04-07 10:00")) + home_motif = create(:motif, location_type: :home, organisation:) + other_home_motif = create(:motif, location_type: :home, organisation:) + create(:rdv, motif: home_motif, created_at: Time.zone.parse("2020-04-07 10:00"), organisation:) + create(:rdv, motif: other_home_motif, created_at: Time.zone.parse("2020-04-07 10:00"), organisation:) stats = described_class.new(rdvs: Rdv.all) expect(stats.rdvs_group_by_type[["à domicile", "05/04/2020"]]).to eq(2) end it "return {2=>1, 1=>1} with one home rdv and one phone" do - home_motif = create(:motif, location_type: :home) - phone_motif = create(:motif, location_type: :phone) - create(:rdv, motif: home_motif, created_at: Time.zone.parse("2020-04-07 10:00")) - create(:rdv, motif: phone_motif, created_at: Time.zone.parse("2020-04-07 11:00")) + home_motif = create(:motif, location_type: :home, organisation:) + phone_motif = create(:motif, location_type: :phone, organisation:) + create(:rdv, motif: home_motif, created_at: Time.zone.parse("2020-04-07 10:00"), organisation:) + create(:rdv, motif: phone_motif, created_at: Time.zone.parse("2020-04-07 11:00"), organisation:) stats = described_class.new(rdvs: Rdv.all) expect(stats.rdvs_group_by_type[["à domicile", "05/04/2020"]]).to eq(1) expect(stats.rdvs_group_by_type[["par téléphone", "05/04/2020"]]).to eq(1) end it "return {2=>1, 1=>1, 0=>1 with each available motif" do - home_motif = create(:motif, location_type: :home) - phone_motif = create(:motif, location_type: :phone) - public_office_motif = create(:motif, location_type: :public_office) - create(:rdv, motif: home_motif, created_at: Time.zone.parse("2020-04-07 10:00")) - create(:rdv, motif: phone_motif, created_at: Time.zone.parse("2020-04-07 11:00")) - create(:rdv, motif: public_office_motif, created_at: Time.zone.parse("2020-04-07 09:40")) + home_motif = create(:motif, location_type: :home, organisation:) + phone_motif = create(:motif, location_type: :phone, organisation:) + public_office_motif = create(:motif, location_type: :public_office, organisation:) + create(:rdv, motif: home_motif, created_at: Time.zone.parse("2020-04-07 10:00"), organisation:) + create(:rdv, motif: phone_motif, created_at: Time.zone.parse("2020-04-07 11:00"), organisation:) + create(:rdv, motif: public_office_motif, created_at: Time.zone.parse("2020-04-07 09:40"), organisation:) stats = described_class.new(rdvs: Rdv.all) expect(stats.rdvs_group_by_type[["à domicile", "05/04/2020"]]).to eq(1) expect(stats.rdvs_group_by_type[["par téléphone", "05/04/2020"]]).to eq(1) @@ -64,23 +66,28 @@ end describe "#rdvs_group_by_territory_name" do + let(:territory) { create(:territory, name: "Bretagne") } + let(:organisation) { create(:organisation, territory:) } + it "returns rdv group by département" do now = Time.zone.parse("20220123 13:00") travel_to(now) - home_motif = create(:motif, location_type: :home) - create(:rdv, motif: home_motif, created_at: now) + home_motif = create(:motif, location_type: :home, organisation:) + create(:rdv, motif: home_motif, created_at: now, organisation:) stats = described_class.new(rdvs: Rdv.all) - expect(stats.rdvs_group_by_territory_name).to eq({ ["Territoire n°2", "23/01/2022"] => 1 }) + expect(stats.rdvs_group_by_territory_name).to eq({ ["Bretagne", "23/01/2022"] => 1 }) end end describe "#rdvs_group_by_service" do + let(:organisation) { create(:organisation) } + it "returns rdv group by service" do now = Time.zone.parse("20220123 13:00") travel_to(now) service = create(:service, name: "PMI") - home_motif = create(:motif, location_type: :home, service: service) - create(:rdv, motif: home_motif, created_at: now) + home_motif = create(:motif, location_type: :home, service: service, organisation:) + create(:rdv, motif: home_motif, created_at: now, organisation:) stats = described_class.new(rdvs: Rdv.all) expect(stats.rdvs_group_by_service).to eq({ ["PMI", "23/01/2022"] => 1 }) end diff --git a/spec/requests/admin/rdv_collectifs_spec.rb b/spec/requests/admin/rdv_collectifs_spec.rb index e1714519bc..d2a666523d 100644 --- a/spec/requests/admin/rdv_collectifs_spec.rb +++ b/spec/requests/admin/rdv_collectifs_spec.rb @@ -2,7 +2,7 @@ include Rails.application.routes.url_helpers let(:organisation) { create(:organisation) } - let(:motif) { create(:motif, :collectif) } + let(:motif) { create(:motif, :collectif, organisation:) } describe "GET /admin/organisations/:organisation_id/rdv_collectifs" do it "is successful" do diff --git a/spec/requests/api/v1/swagger_doc/public_links_request_spec.rb b/spec/requests/api/v1/swagger_doc/public_links_request_spec.rb index 45cc8c57fc..65c9a4f123 100644 --- a/spec/requests/api/v1/swagger_doc/public_links_request_spec.rb +++ b/spec/requests/api/v1/swagger_doc/public_links_request_spec.rb @@ -50,7 +50,7 @@ create(:plage_ouverture, :expired, organisation: organisation_d) create(:plage_ouverture, organisation: organisation_g) - create(:rdv, :future, motif: create(:motif, :collectif), organisation: organisation_c) + create(:rdv, :future, motif: create(:motif, :collectif, organisation: organisation_c), organisation: organisation_c) # Organisation A has two recurring plages # Organisation B has a plage in 5 days diff --git a/spec/requests/api/v1/swagger_doc/rdvs_request_spec.rb b/spec/requests/api/v1/swagger_doc/rdvs_request_spec.rb index 45ae9abcc4..0813e1eb90 100644 --- a/spec/requests/api/v1/swagger_doc/rdvs_request_spec.rb +++ b/spec/requests/api/v1/swagger_doc/rdvs_request_spec.rb @@ -26,21 +26,23 @@ let(:uid) { access_basic_agent["uid"].to_s } let(:client) { access_basic_agent["client"].to_s } - let!(:organisation) { create(:organisation) } - let!(:organisation2) { create(:organisation) } + let!(:organisationA) { create(:organisation) } + let!(:organisationB) { create(:organisation) } let!(:service) { create(:service) } let!(:service2) { create(:service) } - let!(:motif) { create(:motif, service: service) } - let!(:motif2) { create(:motif, service: service2) } + let!(:motifA1) { create(:motif, service: service, organisation: organisationA) } + let!(:motifA2) { create(:motif, service: service2, organisation: organisationA) } + let!(:motifB1) { create(:motif, service: service, organisation: organisationB) } + let!(:motifB2) { create(:motif, service: service2, organisation: organisationB) } - let!(:rdv) { create(:rdv, organisation: organisation, motif: motif, starts_at: "2022-01-01 09:00:00 +0200") } - let!(:rdv2) { create(:rdv, organisation: organisation2, motif: motif, starts_at: "2023-01-01 09:00:00 +0200") } - let!(:rdv3) { create(:rdv, organisation: organisation, motif: motif2, starts_at: "2024-01-01 09:00:00 +0200") } + let!(:rdv) { create(:rdv, organisation: organisationA, motif: motifA1, starts_at: "2022-01-01 09:00:00 +0200") } + let!(:rdv2) { create(:rdv, organisation: organisationB, motif: motifB1, starts_at: "2023-01-01 09:00:00 +0200") } + let!(:rdv3) { create(:rdv, organisation: organisationA, motif: motifA2, starts_at: "2024-01-01 09:00:00 +0200") } - let!(:basic_agent) { create(:agent, basic_role_in_organisations: [organisation], service: service) } - let(:organisation_id) { organisation.id } + let!(:basic_agent) { create(:agent, basic_role_in_organisations: [organisationA], service: service) } + let(:organisation_id) { organisationA.id } after do Rack::Attack.enabled = false @@ -74,8 +76,8 @@ end context "with starts_after and starts_before params" do - let!(:rdv2020) { create(:rdv, organisation: organisation, motif: motif, starts_at: "2020-01-01 09:00:00 +0200") } - let!(:rdv2021) { create(:rdv, organisation: organisation, motif: motif, starts_at: "2021-01-01 09:00:00 +0200") } + let!(:rdv2020) { create(:rdv, organisation: organisationA, motif: motifA1, starts_at: "2020-01-01 09:00:00 +0200") } + let!(:rdv2021) { create(:rdv, organisation: organisationA, motif: motifA1, starts_at: "2021-01-01 09:00:00 +0200") } response 200, "returns policy scoped RDVs filtered with starts_after and starts_before", document: false do let(:starts_after) { "2020-01-01" } @@ -120,7 +122,7 @@ end response 200, "returns policy scoped RDVs when agent is admin", document: false do - let!(:admin_agent) { create(:agent, admin_role_in_organisations: [organisation], service: service) } + let!(:admin_agent) { create(:agent, admin_role_in_organisations: [organisationA], service: service) } let(:access_admin_agent) { api_auth_headers_for_agent(admin_agent) } let(:"access-token") { access_admin_agent["access-token"].to_s } let(:uid) { access_admin_agent["uid"].to_s } diff --git a/spec/services/creneaux_search/calculator_spec.rb b/spec/services/creneaux_search/calculator_spec.rb index 388f08a87f..0c1f04b0e0 100644 --- a/spec/services/creneaux_search/calculator_spec.rb +++ b/spec/services/creneaux_search/calculator_spec.rb @@ -101,7 +101,7 @@ # Une absence de 9h15 à 9h45 (par exemple une absence récurrente créée après le rdv, où on suppose que l'agent accepte de faire une exception) before do plage_ouverture = create(:plage_ouverture, motifs: [motif], first_day: first_day, start_time: Tod::TimeOfDay.new(9), end_time: Tod::TimeOfDay.new(11), lieu: lieu) - create(:rdv, agents: [plage_ouverture.agent], motif: motif, starts_at: Time.zone.local(2021, 5, 3, 9, 0, 0), duration_in_min: 60) + create(:rdv, agents: [plage_ouverture.agent], motif: motif, starts_at: Time.zone.local(2021, 5, 3, 9, 0, 0), duration_in_min: 60, organisation:) create(:absence, agent: plage_ouverture.agent, first_day: first_day, end_day: first_day, start_time: Tod::TimeOfDay.new(9, 15), end_time: Tod::TimeOfDay.new(9, 45)) end @@ -245,7 +245,7 @@ it "return plage ouverture slot minus rdv duration" do starts_at = Time.zone.parse("20211027 9:00") ends_at = Time.zone.parse("20211027 11:00") - rdv = create(:rdv, motif: motif, starts_at: starts_at, agents: [agent]) + rdv = create(:rdv, motif: motif, starts_at: starts_at, agents: [agent], organisation:) plage_ouverture = build(:plage_ouverture, first_day: starts_at.to_date, start_time: Tod::TimeOfDay.new(9), end_time: Tod::TimeOfDay.new(11), agent: agent, motifs: [motif]) range = Date.new(2021, 10, 26)..Date.new(2021, 10, 29) @@ -256,7 +256,7 @@ it "return plage ouverture slot minus RDV duration that overlap po when RDV starts before PO" do starts_at = Time.zone.parse("20211027 9:00") ends_at = Time.zone.parse("20211027 11:00") - rdv = create(:rdv, motif: motif, starts_at: starts_at - 30.minutes, agents: [agent]) + rdv = create(:rdv, motif: motif, starts_at: starts_at - 30.minutes, agents: [agent], organisation:) plage_ouverture = build(:plage_ouverture, first_day: starts_at.to_date, start_time: Tod::TimeOfDay.new(9), end_time: Tod::TimeOfDay.new(11), agent: agent) range = Date.new(2021, 10, 26)..Date.new(2021, 10, 29) @@ -267,8 +267,8 @@ it "return plage ouverture slots minus 2 RDV duration that overlap po" do starts_at = Time.zone.parse("20211027 9:00") ends_at = Time.zone.parse("20211027 11:00") - rdv = create(:rdv, motif: motif, starts_at: starts_at - 30.minutes, agents: [agent]) - other_rdv = create(:rdv, motif: motif, starts_at: starts_at + 45.minutes, agents: [agent]) + rdv = create(:rdv, motif: motif, starts_at: starts_at - 30.minutes, agents: [agent], organisation:) + other_rdv = create(:rdv, motif: motif, starts_at: starts_at + 45.minutes, agents: [agent], organisation:) plage_ouverture = build(:plage_ouverture, first_day: starts_at.to_date, start_time: Tod::TimeOfDay.new(9), end_time: Tod::TimeOfDay.new(11), agent: agent) range = Date.new(2021, 10, 26)..Date.new(2021, 10, 29) @@ -326,7 +326,7 @@ starts_at = friday - 1.week plage_ouverture = build(:plage_ouverture, first_day: starts_at.to_date, start_time: Tod::TimeOfDay.new(9), end_time: Tod::TimeOfDay.new(11), agent: agent, recurrence: Montrose.every(:week, starts: starts_at.to_date - 1.day, day: [5], interval: 1)) - create(:rdv, :excused, motif: motif, starts_at: Time.zone.parse("20211112 10:00"), agents: [agent]) + create(:rdv, :excused, motif: motif, starts_at: Time.zone.parse("20211112 10:00"), agents: [agent], organisation:) range = Date.new(2021, 11, 12)..Date.new(2021, 11, 19) expected_ranges = [(Time.zone.parse("2021-11-19 9:00")..Time.zone.parse("2021-11-19 11:00"))] @@ -349,9 +349,9 @@ it "return range without only range of longer overlapped RDV on same range with same duration" do starts_at = Time.zone.parse("20211027 9:00") ends_at = Time.zone.parse("20211027 11:00") - create(:rdv, motif: create(:motif, organisation: organisation, default_duration_in_min: 30), starts_at: starts_at + 45.minutes, agents: [agent]) - prev_rdv = create(:rdv, starts_at: starts_at - 30.minutes, agents: [agent]) - rdv = create(:rdv, motif: create(:motif, organisation: organisation, default_duration_in_min: 30), starts_at: starts_at + 45.minutes, agents: [agent]) + create(:rdv, motif: create(:motif, organisation: organisation, default_duration_in_min: 30), starts_at: starts_at + 45.minutes, agents: [agent], organisation:) + prev_rdv = create(:rdv, starts_at: starts_at - 30.minutes, agents: [agent], organisation:) + rdv = create(:rdv, motif: create(:motif, organisation: organisation, default_duration_in_min: 30), starts_at: starts_at + 45.minutes, agents: [agent], organisation:) plage_ouverture = build(:plage_ouverture, first_day: starts_at.to_date, start_time: Tod::TimeOfDay.new(9), end_time: Tod::TimeOfDay.new(11), agent: agent) range = Date.new(2021, 10, 26)..Date.new(2021, 10, 29) diff --git a/spec/services/creneaux_search/for_user_spec.rb b/spec/services/creneaux_search/for_user_spec.rb index e625a075b2..b194df4314 100644 --- a/spec/services/creneaux_search/for_user_spec.rb +++ b/spec/services/creneaux_search/for_user_spec.rb @@ -83,13 +83,13 @@ subject { described_class.new(user: user, motif: motif, lieu: lieu) } let!(:motif) { create(:motif, collectif: true) } - let!(:rdv) { create(:rdv, :future, motif: motif, lieu: lieu, starts_at: 3.days.from_now) } - let!(:passed_rdv) { create(:rdv, motif: motif, lieu: lieu, starts_at: 2.days.ago) } - let!(:rdv_with_user) { create(:rdv, :future, motif: motif, lieu: lieu, users: [user], starts_at: 4.days.from_now) } - let!(:rdv_in_different_lieu) { create(:rdv, :future, motif: motif, lieu: create(:lieu)) } - let!(:rdv_with_no_remaining_seat) { create(:rdv, :future, motif: motif, lieu: lieu, max_participants_count: 1) } - let!(:rdv_after_max_public_booking_delay) { create(:rdv, :future, motif: motif, lieu: lieu, starts_at: motif.end_booking_delay + 1.hour) } - let!(:rdv_before_min_public_booking_delay) { create(:rdv, :future, motif: motif, lieu: lieu, starts_at: motif.start_booking_delay - 1.hour) } + let!(:rdv) { create(:rdv, :future, motif: motif, lieu: lieu, starts_at: 3.days.from_now, organisation: motif.organisation) } + let!(:passed_rdv) { create(:rdv, motif: motif, lieu: lieu, starts_at: 2.days.ago, organisation: motif.organisation) } + let!(:rdv_with_user) { create(:rdv, :future, motif: motif, lieu: lieu, users: [user], starts_at: 4.days.from_now, organisation: motif.organisation) } + let!(:rdv_in_different_lieu) { create(:rdv, :future, motif: motif, lieu: create(:lieu), organisation: motif.organisation) } + let!(:rdv_with_no_remaining_seat) { create(:rdv, :future, motif: motif, lieu: lieu, max_participants_count: 1, organisation: motif.organisation) } + let!(:rdv_after_max_public_booking_delay) { create(:rdv, :future, motif: motif, lieu: lieu, starts_at: motif.end_booking_delay + 1.hour, organisation: motif.organisation) } + let!(:rdv_before_min_public_booking_delay) { create(:rdv, :future, motif: motif, lieu: lieu, starts_at: motif.start_booking_delay - 1.hour, organisation: motif.organisation) } let!(:user) { create(:user) } it "returns the subscribable collective rdvs (rdv and rdv_with_user)" do @@ -102,8 +102,8 @@ let!(:agent) { create(:agent) } let!(:motif) { create(:motif, collectif: true, organisation: organisation, sectorisation_level: "agent") } - let!(:rdv) { create(:rdv, :future, motif: motif, lieu: lieu, agents: [agent]) } - let!(:rdv2) { create(:rdv, :future, motif: motif, lieu: lieu, agents: [build(:agent)]) } + let!(:rdv) { create(:rdv, :future, motif: motif, lieu: lieu, agents: [agent], organisation: motif.organisation) } + let!(:rdv2) { create(:rdv, :future, motif: motif, lieu: lieu, agents: [build(:agent)], organisation: motif.organisation) } let!(:geo_search) { instance_double(Users::GeoSearch, attributed_agents_by_organisation: { organisation => [agent] }) } it "returns the rdv linked to the geo attributed agents" do @@ -118,8 +118,8 @@ let!(:agent) { create(:agent) } let!(:user) { create(:user, referent_agents: [agent]) } let!(:motif) { create(:motif, collectif: true, organisation: organisation, follow_up: true) } - let!(:rdv) { create(:rdv, :future, motif: motif, lieu: lieu, agents: [agent]) } - let!(:rdv2) { create(:rdv, :future, motif: motif, lieu: lieu, agents: [build(:agent)]) } + let!(:rdv) { create(:rdv, :future, motif: motif, lieu: lieu, agents: [agent], organisation: motif.organisation) } + let!(:rdv2) { create(:rdv, :future, motif: motif, lieu: lieu, agents: [build(:agent)], organisation: motif.organisation) } it "returns the rdv linked to referents" do expect(subject.next_availability).to eq(rdv) diff --git a/spec/services/notifiers/rdv_base_spec.rb b/spec/services/notifiers/rdv_base_spec.rb index 3e6e7e9ec0..e9357a111a 100644 --- a/spec/services/notifiers/rdv_base_spec.rb +++ b/spec/services/notifiers/rdv_base_spec.rb @@ -28,8 +28,9 @@ def participations_to_notify context "rdv has one user with email notifications, but motif is not notified" do let(:user1) { build(:user, notify_by_email: true) } - let(:motif) { build(:motif, :visible_and_not_notified) } - let(:rdv) { create(:rdv, starts_at: 1.day.from_now, users: [user1], motif: motif) } + let(:organisation) { build(:organisation) } + let(:motif) { build(:motif, :visible_and_not_notified, organisation:) } + let(:rdv) { create(:rdv, starts_at: 1.day.from_now, users: [user1], motif: motif, organisation:) } it "sends email to user" do expect(service).not_to receive(:notify_user_by_mail).with(user1) @@ -104,8 +105,9 @@ def participations_to_notify context "motif is not_notified" do let(:author) { build(:agent) } let(:agent) { build(:agent) } - let(:motif) { build(:motif, :visible_and_not_notified) } - let(:rdv) { create(:rdv, starts_at: 1.day.from_now, agents: [agent], motif: motif) } + let(:organisation) { build(:organisation) } + let(:motif) { build(:motif, :visible_and_not_notified, organisation:) } + let(:rdv) { create(:rdv, starts_at: 1.day.from_now, agents: [agent], motif: motif, organisation:) } it "agent is notified anyway" do expect(service).to receive(:notify_agent).with(agent) diff --git a/spec/services/notifiers/rdv_created_spec.rb b/spec/services/notifiers/rdv_created_spec.rb index 8b1ac42f33..d2297e9a4e 100644 --- a/spec/services/notifiers/rdv_created_spec.rb +++ b/spec/services/notifiers/rdv_created_spec.rb @@ -5,7 +5,7 @@ let(:user2) { create(:user) } let(:agent1) { create(:agent) } let(:agent2) { create(:agent) } - let(:rdv) { create(:rdv, starts_at: starts_at, motif: motif, agents: [agent1, agent2], users: [user1, user2]) } + let(:rdv) { create(:rdv, starts_at: starts_at, motif: motif, agents: [agent1, agent2], users: [user1, user2], organisation: motif.organisation) } let(:token1) { "123456" } let(:token2) { "56789" } diff --git a/spec/services/participation_exporter_spec.rb b/spec/services/participation_exporter_spec.rb index a8a1108045..64fae53c27 100644 --- a/spec/services/participation_exporter_spec.rb +++ b/spec/services/participation_exporter_spec.rb @@ -1,15 +1,18 @@ RSpec.describe ParticipationExporter, type: :service do describe "#xls_string_from_rdvs_rows" do it "return export with header" do + organisation = create(:organisation, name: "MDS Paris") + lieu = create(:lieu, name: "MDS Paris Nord", address: "21 rue des Ardennes, Paris, 75019", organisation:) + motif = build(:motif, name: "Consultation", service: build(:service, name: "PMI"), organisation:) rdv = create( :rdv, created_at: Time.zone.parse("2023-01-01 12h50"), starts_at: Time.zone.parse("2023-04-07 14h30"), status: :unknown, context: "des infos sur le rdv", - lieu: create(:lieu, name: "MDS Paris Nord", address: "21 rue des Ardennes, Paris, 75019"), - motif: build(:motif, name: "Consultation", service: build(:service, name: "PMI")), - organisation: create(:organisation, name: "MDS Paris"), + lieu:, + motif:, + organisation:, agents: [create(:agent, email: "agent@mail.com", first_name: "Francis", last_name: "Factice")], users: [create(:user, first_name: "Gaston", last_name: "Bidon", birth_date: Date.new(2000, 1, 1), address: nil)] ) diff --git a/spec/sms/users/rdv_sms_spec.rb b/spec/sms/users/rdv_sms_spec.rb index 5baf0c34a6..3980efceee 100644 --- a/spec/sms/users/rdv_sms_spec.rb +++ b/spec/sms/users/rdv_sms_spec.rb @@ -5,7 +5,7 @@ let(:organisation) { build(:organisation) } let(:pmi) { build(:service, short_name: "PMI") } - let(:motif) { build(:motif, service: pmi) } + let(:motif) { build(:motif, service: pmi, organisation:) } let(:lieu) { build(:lieu, name: "MDS Centre", address: "10 rue d'ici, Paris, 75016") } let(:rdv) { build(:rdv, motif: motif, organisation: organisation, lieu: lieu, starts_at: Time.zone.local(2021, 12, 10, 13, 10), id: 123, name: "Ne Doit pas s'afficher") } let(:user) { build(:user) } @@ -51,10 +51,11 @@ context "with a follow_up rdv" do it "contains referent name" do + organisation = create(:organisation) agent = create(:agent, first_name: "James", last_name: "Bond") user = create(:user, referent_agents: [agent]) - motif = create(:motif, follow_up: true) - rdv = create(:rdv, motif: motif, users: [user], agents: [agent]) + motif = create(:motif, follow_up: true, organisation:) + rdv = create(:rdv, motif: motif, users: [user], agents: [agent], organisation:) token = "12345" content = described_class.rdv_created(rdv, user, token).content diff --git a/spec/support/shared_context/search_context.rb b/spec/support/shared_context/search_context.rb index 114b2bacb2..171c98455a 100644 --- a/spec/support/shared_context/search_context.rb +++ b/spec/support/shared_context/search_context.rb @@ -188,10 +188,11 @@ end it "returns collective motif with lieu_id" do - lieu = create(:lieu) + organisation = create(:organisation) + lieu = create(:lieu, organisation:) search_context = described_class.new(user: nil, query_params: { lieu_id: lieu.id }) - motif = create(:motif, collectif: true) - create(:rdv, motif: motif, lieu: lieu) + motif = create(:motif, collectif: true, organisation:) + create(:rdv, motif: motif, lieu: lieu, organisation:) expect(search_context.filter_motifs(Motif.where(id: motif.id))).to eq([motif]) end From 4d7c1934df0dc8b1584b9cac91affb89f621d832 Mon Sep 17 00:00:00 2001 From: Adrien Di Pasquale Date: Thu, 30 Jan 2025 12:44:07 +0100 Subject: [PATCH 9/9] =?UTF-8?q?Ajout=20de=20lien=20vers=20Letter=20Opener?= =?UTF-8?q?=20en=20d=C3=A9veloppement=20+=20correction=20port=20(#5020)=20?= =?UTF-8?q?[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Ajout de lien vers Letter Opener en développement * fix specs * fix specs --- app/views/users/registrations/pending.html.slim | 3 +++ config/initializers/letter_opener.rb | 10 ++++++++++ 2 files changed, 13 insertions(+) create mode 100644 config/initializers/letter_opener.rb diff --git a/app/views/users/registrations/pending.html.slim b/app/views/users/registrations/pending.html.slim index d4e5f8a1eb..7c62286281 100644 --- a/app/views/users/registrations/pending.html.slim +++ b/app/views/users/registrations/pending.html.slim @@ -12,3 +12,6 @@ - if email_tld_infos(@email_tld).present? .fr-hr-or.fr-mb-2w ou = link_to t("devise.invitations.invitation.open_app_mail"), "message://", target: "_blank", class: "fr-icon" + + - if Rails.env.development? + = link_to "Letter Opener", "/letter_opener", class: "fr-btn fr-btn--icon-left fr-icon-mail-line" diff --git a/config/initializers/letter_opener.rb b/config/initializers/letter_opener.rb new file mode 100644 index 0000000000..82307c1281 --- /dev/null +++ b/config/initializers/letter_opener.rb @@ -0,0 +1,10 @@ +Rails.application.config.after_initialize do + next if !Rails.env.development? || !defined?(LetterOpenerWeb) + + LetterOpenerWeb::Letter.class_eval do + alias_method :original_adjust_link_targets, :adjust_link_targets + def adjust_link_targets(contents) + original_adjust_link_targets(contents).gsub(".localhost/", ".localhost:3000/") + end + end +end