diff --git a/app/controllers/api/v1/market_applications_controller.rb b/app/controllers/api/v1/market_applications_controller.rb
index 5f2369adc..9bfa5f285 100644
--- a/app/controllers/api/v1/market_applications_controller.rb
+++ b/app/controllers/api/v1/market_applications_controller.rb
@@ -75,11 +75,8 @@ def success_response(market_application)
end
def application_url_for(market_application)
- if market_application.application_mode_choice_required?
- return Rails.application.routes.url_helpers.application_mode_candidate_market_application_url(
- market_application.identifier
- )
- end
+ target, step = market_application.next_required_wizard_step
+ return wizard_step_url(target, step) if target
Rails.application.routes.url_helpers.step_candidate_market_application_url(
market_application.identifier,
@@ -87,6 +84,15 @@ def application_url_for(market_application)
)
end
+ def wizard_step_url(market_application, step)
+ case step
+ when :application_mode
+ Rails.application.routes.url_helpers.application_mode_candidate_market_application_url(market_application.identifier)
+ when :grouping_legal_type
+ Rails.application.routes.url_helpers.grouping_legal_type_candidate_market_application_url(market_application.identifier)
+ end
+ end
+
def validate_application_completed
return if @market_application.completed?
diff --git a/app/controllers/candidate/application_modes_controller.rb b/app/controllers/candidate/application_modes_controller.rb
index f5322d010..d7858a7ed 100644
--- a/app/controllers/candidate/application_modes_controller.rb
+++ b/app/controllers/candidate/application_modes_controller.rb
@@ -4,14 +4,15 @@ module Candidate
class ApplicationModesController < Candidate::ApplicationController
include Candidate::GroupementFeatureGuard
include Candidate::MarketApplicationGuard
+ include Candidate::WizardRoutable
prepend_before_action :find_market_application
before_action :redirect_if_mode_already_chosen
def show
- @already_mandataire = already_mandataire_elsewhere?
- @readonly = @market_application.application_mode.present?
- @readonly_continue_path = next_step_path(@market_application) if @readonly
+ @already_mandataire = presenter.already_mandataire?
+ @readonly = presenter.readonly?
+ @readonly_continue_path = next_required_wizard_step_path(@market_application) if @readonly
end
def update
@@ -22,7 +23,7 @@ def update
return handle_success(result) if result.success?
- @already_mandataire = already_mandataire_elsewhere?
+ @already_mandataire = presenter.already_mandataire?
@errors = result.errors
render :show, status: :unprocessable_content
end
@@ -39,27 +40,15 @@ def redirect_if_mode_already_chosen
return if @market_application.application_mode.nil?
return if action_name == 'show' && params[:readonly].present?
- redirect_to next_step_path(@market_application)
+ redirect_to next_required_wizard_step_path(@market_application)
end
- def next_step_path(market_application)
- if market_application.grouping_legal_type_choice_required?
- grouping_legal_type_candidate_market_application_path(market_application.identifier)
- else
- company_identification_candidate_market_application_path(market_application.identifier)
- end
- end
-
- def already_mandataire_elsewhere?
- Grouping
- .joins(:mandataire_market_application)
- .where(public_market: @market_application.public_market, market_applications: { siret: @market_application.siret })
- .where.not(market_applications: { id: @market_application.id })
- .exists?
+ def presenter
+ @presenter ||= Candidate::ApplicationModePresenter.new(@market_application)
end
def handle_success(result)
- redirect_to next_step_path(result.market_application)
+ redirect_to next_required_wizard_step_path(result.market_application)
end
end
end
diff --git a/app/controllers/candidate/grouping_legal_types_controller.rb b/app/controllers/candidate/grouping_legal_types_controller.rb
index 03da97a33..7e4bccc24 100644
--- a/app/controllers/candidate/grouping_legal_types_controller.rb
+++ b/app/controllers/candidate/grouping_legal_types_controller.rb
@@ -8,7 +8,9 @@ class GroupingLegalTypesController < Candidate::ApplicationController
prepend_before_action :find_market_application
before_action :redirect_unless_mandataire
- def show; end
+ def show
+ @grouping = presenter.grouping
+ end
def update
result = Candidate::SetGroupingLegalType.call(
@@ -18,6 +20,7 @@ def update
return handle_success if result.success?
+ @grouping = presenter.grouping
@errors = result.errors
render :show, status: :unprocessable_content
end
@@ -31,12 +34,15 @@ def find_market_application
end
def redirect_unless_mandataire
- @grouping = Grouping.joins(:mandataire_market_application).find_by(market_applications: { id: @market_application.id })
- return if @grouping
+ return if presenter.grouping
redirect_to application_mode_candidate_market_application_path(@market_application.identifier)
end
+ def presenter
+ @presenter ||= Candidate::GroupingLegalTypePresenter.new(@market_application)
+ end
+
def handle_success
redirect_to company_identification_candidate_market_application_path(@market_application.identifier)
end
diff --git a/app/controllers/candidate/sessions_controller.rb b/app/controllers/candidate/sessions_controller.rb
index cd84b3b17..c93c25713 100644
--- a/app/controllers/candidate/sessions_controller.rb
+++ b/app/controllers/candidate/sessions_controller.rb
@@ -2,6 +2,8 @@
module Candidate
class SessionsController < Candidate::ApplicationController
+ include Candidate::WizardRoutable
+
skip_before_action :require_candidate_authentication
def new
@@ -38,23 +40,28 @@ def destroy
def sign_in_candidate(user, market_application)
reconnection = market_application.user_id.present?
- market_application.update!(user:) unless reconnection
+ link_candidate_to_application(user, market_application) unless reconnection
session[:user_id] = user.id
session[:market_application_identifier] = market_application.identifier
redirect_to first_step_path(market_application)
end
+ def link_candidate_to_application(user, market_application)
+ counterpart = market_application.groupement_counterpart || market_application.solo_counterpart
+ market_application.update!(user:)
+ counterpart&.update!(user:)
+ end
+
def first_step_path(market_application)
- if market_application.completed?
- return deadline_passed_candidate_market_application_path(market_application.identifier) unless market_application.public_market.open?
+ return completed_application_path(market_application) if market_application.completed?
- return candidate_sync_status_path(market_application.identifier)
- end
+ next_required_wizard_step_path(market_application)
+ end
- return application_mode_candidate_market_application_path(market_application.identifier) if market_application.application_mode_choice_required?
- return grouping_legal_type_candidate_market_application_path(market_application.identifier) if market_application.grouping_legal_type_choice_required?
+ def completed_application_path(market_application)
+ return deadline_passed_candidate_market_application_path(market_application.identifier) unless market_application.public_market.open?
- company_identification_candidate_market_application_path(market_application.identifier)
+ candidate_sync_status_path(market_application.identifier)
end
def handle_magic_link_sent(result)
diff --git a/app/controllers/concerns/candidate/application_mode_guard.rb b/app/controllers/concerns/candidate/application_mode_guard.rb
index 848431f76..d48198590 100644
--- a/app/controllers/concerns/candidate/application_mode_guard.rb
+++ b/app/controllers/concerns/candidate/application_mode_guard.rb
@@ -3,6 +3,7 @@
module Candidate
module ApplicationModeGuard
extend ActiveSupport::Concern
+ include Candidate::WizardRoutable
included do
before_action :redirect_to_application_mode_choice
@@ -11,9 +12,9 @@ module ApplicationModeGuard
private
def redirect_to_application_mode_choice
- return unless @market_application&.application_mode_choice_required?
+ return unless @market_application
- redirect_to application_mode_candidate_market_application_path(@market_application.identifier)
+ redirect_to next_required_wizard_step_path(@market_application) if @market_application.next_required_wizard_step
end
end
end
diff --git a/app/controllers/concerns/candidate/wizard_routable.rb b/app/controllers/concerns/candidate/wizard_routable.rb
new file mode 100644
index 000000000..d1e750e7a
--- /dev/null
+++ b/app/controllers/concerns/candidate/wizard_routable.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Candidate
+ module WizardRoutable
+ extend ActiveSupport::Concern
+
+ private
+
+ def wizard_step_path(market_application, step)
+ case step
+ when :application_mode
+ application_mode_candidate_market_application_path(market_application.identifier)
+ when :grouping_legal_type
+ grouping_legal_type_candidate_market_application_path(market_application.identifier)
+ end
+ end
+
+ def next_required_wizard_step_path(market_application)
+ target, step = market_application.next_required_wizard_step
+ return company_identification_candidate_market_application_path(market_application.identifier) unless target
+
+ wizard_step_path(target, step)
+ end
+ end
+end
diff --git a/app/models/market_application.rb b/app/models/market_application.rb
index 36ee72eaf..6e29312d2 100644
--- a/app/models/market_application.rb
+++ b/app/models/market_application.rb
@@ -53,10 +53,34 @@ def application_mode_choice_required?
end
def grouping_legal_type_choice_required?
+ return false if completed?
+
FeatureFlags::Groupement.enabled? && groupement? &&
Grouping.joins(:mandataire_market_application).exists?(legal_type: nil, market_applications: { id: })
end
+ def groupement_counterpart
+ return nil if groupement?
+
+ MarketApplication.where(public_market:, siret:, application_mode: :groupement, user_id:).where.not(id:).first
+ end
+
+ def solo_counterpart
+ return nil if solo?
+
+ MarketApplication.where(public_market:, siret:, application_mode: :solo, user_id:).where.not(id:).first
+ end
+
+ def next_required_wizard_step
+ return nil unless FeatureFlags::Groupement.enabled?
+ return [self, :application_mode] if application_mode_choice_required?
+
+ target = groupement_counterpart || self
+ return [target, :grouping_legal_type] if target.grouping_legal_type_choice_required?
+
+ nil
+ end
+
def update_api_status(api_name, status:, fields_filled: 0)
with_lock do
updated_status = (api_fetch_status || {}).dup
diff --git a/app/presenters/candidate/application_mode_presenter.rb b/app/presenters/candidate/application_mode_presenter.rb
new file mode 100644
index 000000000..6812621f4
--- /dev/null
+++ b/app/presenters/candidate/application_mode_presenter.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Candidate
+ class ApplicationModePresenter
+ def initialize(market_application)
+ @market_application = market_application
+ end
+
+ def already_mandataire?
+ Grouping
+ .joins(:mandataire_market_application)
+ .where(public_market: market_application.public_market, market_applications: { siret: market_application.siret })
+ .where.not(market_applications: { id: market_application.id })
+ .exists?
+ end
+
+ def readonly?
+ market_application.application_mode.present?
+ end
+
+ private
+
+ attr_reader :market_application
+ end
+end
diff --git a/app/presenters/candidate/grouping_legal_type_presenter.rb b/app/presenters/candidate/grouping_legal_type_presenter.rb
new file mode 100644
index 000000000..549239d21
--- /dev/null
+++ b/app/presenters/candidate/grouping_legal_type_presenter.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Candidate
+ class GroupingLegalTypePresenter
+ def initialize(market_application)
+ @market_application = market_application
+ end
+
+ def grouping
+ return @grouping if defined?(@grouping)
+
+ @grouping = Grouping.joins(:mandataire_market_application)
+ .find_by(market_applications: { id: market_application.id })
+ end
+
+ private
+
+ attr_reader :market_application
+ end
+end
diff --git a/app/views/candidate/grouping_legal_types/show.html.erb b/app/views/candidate/grouping_legal_types/show.html.erb
index 632a4385d..429402a60 100644
--- a/app/views/candidate/grouping_legal_types/show.html.erb
+++ b/app/views/candidate/grouping_legal_types/show.html.erb
@@ -2,7 +2,7 @@
<%= t('candidate.grouping_legal_types.step_current') %>
-
<%= t('candidate.grouping_legal_types.title') %>
+
<%= t('candidate.grouping_legal_types.title') %>
@@ -15,7 +15,7 @@
<%= t('candidate.grouping_legal_types.step_next_label') %>
-
<%= t('candidate.grouping_legal_types.question') %>
+
<%= t('candidate.grouping_legal_types.question') %>
<% if @errors.present? %>
@@ -34,9 +34,7 @@
<%= t('candidate.grouping_legal_types.alert') %>
- <%= form_with url: grouping_legal_type_candidate_market_application_path(@market_application.identifier),
- method: :patch,
- data: { controller: "enable-on-choice" } do |form| %>
+ <%= form_with url: grouping_legal_type_candidate_market_application_path(@market_application.identifier), method: :patch, data: { controller: "enable-on-choice" } do |form| %>