Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ETQ Usager, je peux répondre à une prise de rendez-vous demandée par un instructeur #11033

Draft
wants to merge 28 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d91d598
[#10457] Add RDV card
mmagn Oct 25, 2024
4f3a081
[#10457] Modify RDV enable screen
mmagn Oct 25, 2024
b2d8ee8
[#10457] Feature flip RDV
mmagn Nov 5, 2024
95e923c
[#10457] Init Propose Rdv menu
mmagn Nov 5, 2024
599f566
[#10457] Update Propose Rdv Menu after form submit
mmagn Nov 5, 2024
38b5e5f
[#10457] Prepare Oauth connection for RDV
mmagn Nov 5, 2024
f92207f
[#10457] Mock configure RDV binding
mmagn Nov 7, 2024
b4fe4da
[#10457] Create RDV Connection
mmagn Nov 7, 2024
47beb68
[#10457] Mock RDV oauth callback
mmagn Nov 7, 2024
6420f34
[#10457] Create RDVs
mmagn Nov 8, 2024
4729545
[#10457] Create RDV Webhook
mmagn Nov 8, 2024
6f9b0b0
[#10457] Check plage ouvertures when opening Dropdown
mmagn Nov 8, 2024
2f35524
temp
mmagn Nov 29, 2024
8756938
temp
mmagn Dec 3, 2024
d39a71f
bundle install
mmagn Jan 21, 2025
6e0c387
temp
mmagn Jan 23, 2025
7d7480c
[#10457] Rendez-vous page for instructeur
mmagn Jan 23, 2025
60ba39d
[#10457] Remove plage ouverture check
mmagn Jan 30, 2025
3374661
[#10457] Init rdv card
mmagn Jan 30, 2025
a8b3937
[#10457] Fix connect Rdv from instructeur role
mmagn Feb 4, 2025
38c611f
[#10457] Fix individual names
mmagn Feb 4, 2025
cd2ab6d
[#10457] Fix after first demo
mmagn Feb 6, 2025
866e291
[#10457] Fix after first demo
mmagn Feb 6, 2025
3487351
[#10457] New screen to list all Rdv for a Procedure
mmagn Feb 7, 2025
e787d80
[#10457] Add Rdv alert on dossier list
mmagn Feb 7, 2025
dc3dfb8
[#10457] Add Rdv screen for usager
mmagn Feb 7, 2025
d0990a7
[#10457] Fixes after demo
mmagn Feb 7, 2025
5cbfaec
[#10457] useless file
mmagn Feb 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ gem 'mini_magick'
gem 'net-imap', require: false # See https://github.com/mikel/mail/pull/1439
gem 'net-pop', require: false # same
gem 'net-smtp', require: false # same
gem 'oauth2'
gem 'omniauth'
gem "omniauth-rails_csrf_protection"
gem "omniauth-rdv-service-public", git: "https://github.com/betagouv/rdv-service-public.git", branch: "production", glob: "lib/omniauth-rdv-service-public/omniauth-rdv-service-public.gemspec"
gem 'openid_connect'
gem 'parsby'
gem 'pg'
Expand Down
37 changes: 37 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
GIT
remote: https://github.com/betagouv/rdv-service-public.git
revision: f9de028ccd731c59bf6ca34cd3a13ff0f83e4d42
branch: production
glob: lib/omniauth-rdv-service-public/omniauth-rdv-service-public.gemspec
specs:
omniauth-rdv-service-public (0.1.0)
omniauth (~> 2.0)
omniauth-oauth2 (~> 1.8)

GIT
remote: https://github.com/demarches-simplifiees/reliable-fetch.git
revision: f547a270c402b0180091516d790434e83287fae7
Expand Down Expand Up @@ -461,6 +471,8 @@ GEM
minitest (5.25.4)
msgpack (1.7.5)
multi_json (1.15.0)
multi_xml (0.7.1)
bigdecimal (~> 3.1)
mustermann (3.0.3)
ruby2_keywords (~> 0.0.1)
mutex_m (0.3.0)
Expand Down Expand Up @@ -495,6 +507,23 @@ GEM
racc (~> 1.4)
nokogiri (1.18.1-x86_64-linux-musl)
racc (~> 1.4)
oauth2 (2.0.9)
faraday (>= 0.17.3, < 3.0)
jwt (>= 1.0, < 3.0)
multi_xml (~> 0.5)
rack (>= 1.2, < 4)
snaky_hash (~> 2.0)
version_gem (~> 1.1)
omniauth (2.1.2)
hashie (>= 3.4.6)
rack (>= 2.2.3)
rack-protection
omniauth-oauth2 (1.8.0)
oauth2 (>= 1.4, < 3)
omniauth (~> 2.0)
omniauth-rails_csrf_protection (1.0.2)
actionpack (>= 4.2)
omniauth (~> 2.0)
openid_connect (2.3.1)
activemodel
attr_required (>= 1.0.0)
Expand Down Expand Up @@ -781,6 +810,9 @@ GEM
tilt (~> 2.0)
skylight (6.0.4)
activesupport (>= 5.2.0)
snaky_hash (2.0.1)
hashie
version_gem (~> 1.1, >= 1.1.1)
spreadsheet_architect (5.1.0)
caxlsx (<= 4.0)
csv
Expand Down Expand Up @@ -834,6 +866,7 @@ GEM
public_suffix
vcr (6.3.1)
base64
version_gem (1.1.4)
view_component (3.21.0)
activesupport (>= 5.2.0, < 8.1)
concurrent-ruby (~> 1.0)
Expand Down Expand Up @@ -995,6 +1028,10 @@ DEPENDENCIES
net-imap
net-pop
net-smtp
oauth2
omniauth
omniauth-rails_csrf_protection
omniauth-rdv-service-public!
openid_connect
parsby
pg
Expand Down
12 changes: 12 additions & 0 deletions app/assets/stylesheets/02_utils.scss
Original file line number Diff line number Diff line change
Expand Up @@ -278,3 +278,15 @@ $steps: (0, 1, 2, 3, 4, 5, 6, 7, 8);
}
}
}

.border-grey {
border: 1px solid $border-grey;
}

.bg-light-grey {
background-color: $light-grey;
}

.rounded-4 {
border-radius: 4px;
}
7 changes: 7 additions & 0 deletions app/components/instructeurs/propose_rdv_button_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class Instructeurs::ProposeRdvButtonComponent < ApplicationComponent
def initialize(dossier:)
@dossier = dossier
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
en:
propose_rdv: Propose an appointment
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
fr:
propose_rdv: Proposer un rendez-vous
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
= button_to instructeur_rdvs_path(@dossier.procedure, @dossier), data: { turbo: false }, method: :post, class: 'fr-btn' do
= t('.propose_rdv')
%span.fr-ml-1w.fr-icon-external-link-line{ "aria-hidden": "true" }
14 changes: 14 additions & 0 deletions app/components/instructeurs/rdv_card_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

class Instructeurs::RdvCardComponent < ApplicationComponent
attr_reader :rdv, :with_dossier_infos

def initialize(rdv:, with_dossier_infos: false)
@rdv = rdv
@with_dossier_infos = with_dossier_infos
end

def dossier
@rdv.dossier
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
en:
rdv: Rdv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
fr:
rdv: Rdv
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.card.rounded-4.mb-4.fr-p-0
.flex
- if with_dossier_infos
.p-3.bg-light-grey
.flex.column.flex-gap-1
%h3.card-title
Dossier Nº
= helpers.number_with_html_delimiter(dossier.id)

%p= helpers.status_badge(dossier.state)

%p.fr-icon--sm.fr-icon-user-line
= helpers.demandeur_dossier(dossier)

%p.fr-icon--sm.fr-icon-calendar-line
%span
Déposé le
= l(dossier.depose_at.to_date)

%p.fr-mb-0
= link_to dossier_path(dossier), class: "fr-link" do
Voir le dossier
%span.fr-icon-arrow-right-line.fr-icon--sm{ "aria-hidden": "true" }
.p-3
.flex.column.flex-gap-1
%p
%span.fr-icon-calendar-fill{"aria-hidden": "true"}
%strong
Le
= l(rdv.starts_at, format: :human)
%p.fr-mb-0
Infos et annulation :
= link_to rdv.rdv_plan_url, rdv.rdv_plan_url, class: "fr-link", target: "_blank"
7 changes: 7 additions & 0 deletions app/components/procedure/card/rdv_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class Procedure::Card::RdvComponent < ApplicationComponent
def initialize(procedure:)
@procedure = procedure
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
fr:
title: Prise de rendez-vous
subtitle: Permettre aux instructeurs de prendre des rendez-vous avec les usagers
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.fr-col-6.fr-col-md-4.fr-col-lg-3
= link_to rdv_admin_procedure_path(@procedure), class: 'fr-tile fr-enlarge-link' do
.fr-tile__body.flex.column.align-center.justify-between
- if @procedure.rdv_enabled?
%p.fr-badge.fr-badge--success Activée
- else
%p.fr-badge Désactivée
%div
%h3.fr-h6.fr-mt-10v= t('.title')
%p.fr-tile-subtitle= t('.subtitle')
%p.fr-btn.fr-btn--tertiary= t('views.shared.actions.edit')
20 changes: 19 additions & 1 deletion app/controllers/administrateurs/procedures_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class ProceduresController < AdministrateurController
layout 'all', only: [:all, :administrateurs]
respond_to :html, :xlsx

before_action :retrieve_procedure, only: [:champs, :annotations, :modifications, :edit, :zones, :monavis, :update_monavis, :accuse_lecture, :update_accuse_lecture, :jeton, :update_jeton, :publication, :publish, :transfert, :close, :confirmation, :allow_expert_review, :allow_expert_messaging, :experts_require_administrateur_invitation, :reset_draft, :publish_revision, :check_path, :api_champ_columns, :path, :update_path]
before_action :retrieve_procedure, only: [:champs, :annotations, :modifications, :edit, :zones, :monavis, :update_monavis, :accuse_lecture, :update_accuse_lecture, :jeton, :update_jeton, :publication, :publish, :transfert, :close, :confirmation, :allow_expert_review, :allow_expert_messaging, :experts_require_administrateur_invitation, :reset_draft, :publish_revision, :check_path, :api_champ_columns, :path, :update_path, :rdv, :update_rdv]
before_action :draft_valid?, only: [:apercu]
after_action :reset_procedure, only: [:update]

Expand Down Expand Up @@ -252,6 +252,23 @@ def update_accuse_lecture
def jeton
end

def rdv
end

def update_rdv
rdv_enabled = procedure_params[:rdv_enabled]
result = RdvService.new(rdv_connection: current_administrateur.rdv_connection).configure_rdv_binding(procedure: @procedure, enabled: rdv_enabled)

if result.failure?
flash.now.alert = result.failure[:message]
render 'rdv'
end

@procedure.update!(procedure_params)
flash.notice = @procedure.rdv_enabled? ? "La prise de rendez-vous est activée" : "La prise de rendez-vous est désactivée"
redirect_to rdv_admin_procedure_path(@procedure)
end

def modifications
ProcedureRevisionPreloader.new(@procedure.revisions).all
end
Expand Down Expand Up @@ -585,6 +602,7 @@ def procedure_params
:lien_dpo,
:opendata,
:procedure_expires_when_termine_enabled,
:rdv_enabled,
{ zone_ids: [], procedure_tag_names: [] }
]

Expand Down
10 changes: 8 additions & 2 deletions app/controllers/instructeurs/dossiers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class DossiersController < ProceduresController

before_action :redirect_on_dossier_not_found, only: :show
before_action :redirect_on_dossier_in_batch_operation, only: [:archive, :unarchive, :follow, :unfollow, :passer_en_instruction, :repasser_en_construction, :repasser_en_instruction, :terminer, :restore, :destroy, :extend_conservation]
before_action :set_gallery_attachments, only: [:show, :pieces_jointes, :annotations_privees, :avis, :messagerie, :personnes_impliquees, :reaffectation]
before_action :retrieve_procedure_presentation, only: [:annotations_privees, :avis_new, :avis, :messagerie, :personnes_impliquees, :pieces_jointes, :reaffectation, :show, :dossier_labels, :passer_en_instruction, :repasser_en_construction, :repasser_en_instruction, :terminer, :pending_correction, :create_avis, :create_commentaire]
before_action :set_gallery_attachments, only: [:show, :pieces_jointes, :annotations_privees, :avis, :messagerie, :personnes_impliquees, :reaffectation, :rendez_vous]
before_action :retrieve_procedure_presentation, only: [:annotations_privees, :avis_new, :avis, :messagerie, :personnes_impliquees, :pieces_jointes, :reaffectation, :rendez_vous, :show, :dossier_labels, :passer_en_instruction, :repasser_en_construction, :repasser_en_instruction, :terminer, :pending_correction, :create_avis, :create_commentaire]

after_action :mark_demande_as_read, only: :show
after_action :mark_messagerie_as_read, only: [:messagerie, :create_commentaire, :pending_correction]
Expand Down Expand Up @@ -109,6 +109,12 @@ def personnes_impliquees
@manual_assignments = dossier.dossier_assignments.manual.includes(:groupe_instructeur, :previous_groupe_instructeur)
end

def rendez_vous
RdvService.new(rdv_connection: current_instructeur.rdv_connection).update_pending_rdv_plan!(dossier:)

@rdvs = dossier.rdvs.order(created_at: :desc)
end

def send_to_instructeurs
recipients = params['recipients'].presence || []
# instructeurs are scoped by groupe_instructeur to avoid enumeration
Expand Down
5 changes: 5 additions & 0 deletions app/controllers/instructeurs/procedures_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ def email_usagers
@dossiers_without_groupe_count = procedure.dossiers.state_brouillon.for_groupe_instructeur(nil).count
end

def usagers_rdvs
@procedure = procedure
@rdvs = @procedure.rdvs
end

def create_multiple_commentaire
@procedure = procedure
errors = []
Expand Down
39 changes: 39 additions & 0 deletions app/controllers/instructeurs/rdvs_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

module Instructeurs
class RdvsController < InstructeurController
before_action :set_dossier

def create
pending_rdv = @dossier.rdvs.pending.first

if pending_rdv.present?
return redirect_to pending_rdv.rdv_plan_url, allow_other_host: true
end

rdv_params = params.permit(:first_name, :last_name)
@rdv_plan_result = RdvService.new(rdv_connection: current_instructeur.rdv_connection).create_rdv_plan(
dossier: @dossier,
first_name: rdv_params[:first_name],
last_name: rdv_params[:last_name],
email: @dossier.user_email_for(:notification),
dossier_url: instructeur_dossier_url(@dossier.procedure, @dossier, host: "https://test.gouv.fr"),
return_url: rendez_vous_instructeur_dossier_url(@dossier.procedure, @dossier, host: "https://test.gouv.fr")
)

if @rdv_plan_result.success?
return redirect_to @rdv_plan_result.value!.rdv_plan_url, allow_other_host: true
end

Sentry.capture_message("Rdv creation failed", extra: { rdv_plan_result: @rdv_plan_result })

redirect_to instructeur_dossier_path(@dossier.procedure, @dossier), alert: t('.rdv_creation_failed')
end

private

def set_dossier
@dossier = current_instructeur.dossiers.find(params[:dossier_id])
end
end
end
37 changes: 37 additions & 0 deletions app/controllers/rdv_service_public/oauth_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

class RdvServicePublic::OauthController < ApplicationController
before_action :authenticate_instructeur!

def callback
user_info = request.env['omniauth.auth']

rdv_connection_attributes = {
expires_at: Time.zone.at(user_info.credentials.expires_at),
access_token: user_info.credentials.token,
refresh_token: user_info.credentials.refresh_token
}

if current_instructeur.rdv_connection.present?
current_instructeur.rdv_connection.update!(rdv_connection_attributes)
else
current_instructeur.create_rdv_connection!(rdv_connection_attributes)
end

redirect_path = request.env['omniauth.origin'] || root_path

redirect_to redirect_path, notice: "Votre compte RDV Service Public a été connecté avec succès"
end

private

def authenticate_instructeur!
if current_instructeur.nil?
redirect_to root_path
end
end

def current_instructeur
current_user&.instructeur
end
end
5 changes: 5 additions & 0 deletions app/controllers/users/dossiers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ def messagerie
@commentaire = Commentaire.new
end

def rendez_vous
@dossier = dossier
@rdvs = @dossier.rdvs.booked.by_starts_at
end

def attestation
if dossier.attestation&.pdf&.attached?
redirect_to dossier.attestation.pdf.url, allow_other_host: true
Expand Down
21 changes: 21 additions & 0 deletions app/controllers/webhooks/rdv_service_public_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

class Webhooks::RdvServicePublicController < ApplicationController
before_action :verify_signature

def create
return unless params[:meta][:event].in?(['updated', 'deleted']) && params[:meta][:model] == 'Rdv'

rdv = Rdv.find_by(rdv_service_public_id: params[:data][:id])

rdv.update!(params.require(:data).permit(:status, :starts_at))

render json: { message: 'OK' }
end

private

def verify_signature
# TODO: Implement signature verification
end
end
Loading
Loading