diff --git a/app/controllers/dashboard/internship_offers_controller.rb b/app/controllers/dashboard/internship_offers_controller.rb index d82932b2b..fb689ec68 100644 --- a/app/controllers/dashboard/internship_offers_controller.rb +++ b/app/controllers/dashboard/internship_offers_controller.rb @@ -215,7 +215,7 @@ def internship_offer_builder def internship_offer_params params.require(:internship_offer) - .permit(:academy, :aasm_state, :city, + .permit(:academy, :aasm_state, :city, :contact_phone, :department, :description, :employer_chosen_name, :employer_id, :employer_name, :employer_type, :entreprise_chosen_full_address, :entreprise_city, diff --git a/app/controllers/dashboard/stepper/entreprises_controller.rb b/app/controllers/dashboard/stepper/entreprises_controller.rb index 365b45e21..0a0dec6bc 100644 --- a/app/controllers/dashboard/stepper/entreprises_controller.rb +++ b/app/controllers/dashboard/stepper/entreprises_controller.rb @@ -71,6 +71,7 @@ def entreprise_params :entreprise_chosen_full_address, :entreprise_coordinates_longitude, :entreprise_coordinates_latitude, + :contact_phone, :entreprise_coordinates, :internship_occupation_id, :internship_address_manual_enter, diff --git a/app/controllers/dashboard/stepper/plannings_controller.rb b/app/controllers/dashboard/stepper/plannings_controller.rb index d4e61e01b..1ee7881e9 100644 --- a/app/controllers/dashboard/stepper/plannings_controller.rb +++ b/app/controllers/dashboard/stepper/plannings_controller.rb @@ -61,6 +61,7 @@ def edit end # process update following a back to step 2 + # should never be used def update raise 'expected to be never used ' authorize! :update, @planning diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 960a1dceb..045598a2d 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -26,6 +26,10 @@ def phone_pattern '^\+?(\d{2,3}\s?)?(\d{2}\s?){3,4}\d{2}$' end + def field_phone_pattern + '\A\+?(\d{2,3}\s?)?(\d{2}\s?){3,4}\d{2}\z' + end + def mail_pattern '^[a-z0-9._%+\\-]+@[a-z0-9.\\-]+\.[a-z]{2,}$' end diff --git a/app/libs/builders/internship_offer_builder.rb b/app/libs/builders/internship_offer_builder.rb index bae36adb3..a15d944e2 100644 --- a/app/libs/builders/internship_offer_builder.rb +++ b/app/libs/builders/internship_offer_builder.rb @@ -161,6 +161,7 @@ def preprocess_entreprise_to_params(entreprise) entreprise_full_address: entreprise.entreprise_full_address, entreprise_chosen_full_address: entreprise.entreprise_chosen_full_address, entreprise_coordinates: entreprise.entreprise_coordinates, + contact_phone: entreprise.contact_phone, workspace_conditions: entreprise.workspace_conditions, workspace_accessibility: entreprise.workspace_accessibility, internship_address_manual_enter: entreprise.internship_address_manual_enter diff --git a/app/models/ability.rb b/app/models/ability.rb index 73d947bdf..b54ecdde9 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -209,12 +209,6 @@ def as_employers_like(user:) end can %i[create see_tutor], InternshipOffer can %i[read update discard publish], InternshipOffer, employer_id: user.team_members_ids - # legacy_abilities for stepper - # can %i[create], InternshipOfferInfo - # can %i[create], HostingInfo - # can %i[create], PracticalInfo - # can %i[create], Organisation - # new_abilities for stepper can %i[create], InternshipOccupation can %i[create], Entreprise do |entreprise| entreprise.internship_occupation.employer_id == user.id @@ -222,12 +216,6 @@ def as_employers_like(user:) can %i[create], Planning do |planning| planning.entreprise.internship_occupation.employer_id == user.id end - # legacy_abilities for stepper - # can %i[update edit renew], InternshipOfferInfo, employer_id: user.team_members_ids - # can %i[update edit renew], HostingInfo, employer_id: user.team_members_ids - # can %i[update edit renew], PracticalInfo, employer_id: user.team_members_ids - # can %i[update edit], Organisation, employer_id: user.team_members_ids - # new_abilities for stepper can %i[update edit renew], InternshipOccupation, employer_id: user.team_members_ids can %i[update edit renew], Entreprise do |entreprise| entreprise.internship_occupation.employer_id.in?(user.team_members_ids) diff --git a/app/models/entreprise.rb b/app/models/entreprise.rb index b730ba397..f3c42b820 100644 --- a/app/models/entreprise.rb +++ b/app/models/entreprise.rb @@ -16,6 +16,9 @@ class Entreprise < ApplicationRecord validates :entreprise_full_address, length: { minimum: 8, maximum: 200 }, presence: true + validates :contact_phone, + format: { with: Regexp.new(ApplicationController.helpers.field_phone_pattern), + message: 'Le numéro de téléphone doit être composé de 10 chiffres' } def entreprise_coordinates=(geolocation) case geolocation diff --git a/app/models/internship_offer.rb b/app/models/internship_offer.rb index 2ea05d629..75fad5eec 100644 --- a/app/models/internship_offer.rb +++ b/app/models/internship_offer.rb @@ -12,7 +12,7 @@ class InternshipOffer < ApplicationRecord DUPLICATE_WHITE_LIST = %w[type title sector_id max_candidates description employer_name street zipcode city department entreprise_coordinates employer_chosen_name all_year_long period grade_ids week_ids - entreprise_full_address internship_offer_area_id + entreprise_full_address internship_offer_area_id contact_phone is_public group school_id coordinates first_date last_date siret internship_address_manual_enter lunch_break daily_hours weekly_hours rep qpv].freeze diff --git a/app/models/internship_offers/weekly_framed.rb b/app/models/internship_offers/weekly_framed.rb index 4114edd2c..6e150c2b9 100644 --- a/app/models/internship_offers/weekly_framed.rb +++ b/app/models/internship_offers/weekly_framed.rb @@ -13,6 +13,10 @@ class WeeklyFramed < InternshipOffer validates :street, :city, presence: true + validates :contact_phone, + format: { with: Regexp.new(ApplicationController.helpers.field_phone_pattern), + message: 'Le numéro de téléphone doit être composé de 10 chiffres' }, + unless: :from_api? validates :max_candidates, numericality: { only_integer: true, diff --git a/app/views/dashboard/stepper/entreprises/_form_fields.html.slim b/app/views/dashboard/stepper/entreprises/_form_fields.html.slim index 22cf68a11..7d611f945 100644 --- a/app/views/dashboard/stepper/entreprises/_form_fields.html.slim +++ b/app/views/dashboard/stepper/entreprises/_form_fields.html.slim @@ -145,14 +145,29 @@ span.fr-icon-info-fill.text-blue-info aria-hidden="true" small.text-blue-info.fr-mx-1w | L’adresse du siège peut être différente de l’adresse où se déroulera le stage. - + div class="row fr-mt-3w bloc-tooggle #{form.object.persisted? ? '' : 'd-none'}" + .col-12 + - label = "Numéro de téléphone du dépositaire *" + - hint = "Ce numéro ne sera pas communiqué aux candidats." + = render 'inputs/dsfr_input_field', + field: :contact_phone, + f: form, + label: label, + required: true, + title: label, + object: form.object, + hint: hint, + pattern: phone_pattern, + maxlength: 20, + value: resource&.contact_phone + .row class="fr-mt-3w bloc-tooggle #{form.object.persisted? ? '' : 'd-none'}" .col-12 .fr-h6 | Les informations liées à votre environnement de travail .small | Afin de mieux informer les élèves, nous vous proposons de préciser brièvement et si vous le souhaitez les conditions d’accueil dans vos locaux en répondant à ces deux questions - div data-controller="character-count" data-character-count-max-value="1000" class="row fr-mt-3w bloc-tooggle #{form.object.persisted? ? '' : 'd-none'}" + div data-controller="character-count" data-character-count-max-value="1000" class="row fr-mt-3w bloc-tooggle #{form.object.persisted? ? '' : 'd-none'}" .col-12 = form.label :workspace_conditions, class: 'fr-label' do = "Décrivez l'environnement de travail dans lequel l'élève va évoluer (open space, niveau sonore, luminosité…)" @@ -166,13 +181,13 @@ | 0/1000 caractères .fr-message.fr-message--error.d-none data-character-count-target="error" | Le texte ne doit pas dépasser 1000 caractères - div data-controller="character-count" data-character-count-max-value="1000" class="row fr-mt-3w bloc-tooggle #{form.object.persisted? ? '' : 'd-none'}" + div data-controller="character-count" data-character-count-max-value="1000" class="row fr-mt-3w bloc-tooggle #{form.object.persisted? ? '' : 'd-none'}" .col-12 = form.label :workspace_accessibility, class: 'fr-label' do = "Parlez-nous de l’accessibilité du poste (déplacement dans les locaux, informations sonores et/ou visuelles, présence d’un ascenseur…)" - = form.text_area :workspace_accessibility, - class: 'fr-input', - rows: 3, + = form.text_area :workspace_accessibility, + class: 'fr-input', + rows: 3, maxlength: 1000, data: {:'character_count_target' => "input", :'action' => "input->character-count#updateCounter"} .fr-messages-group aria-live="polite" diff --git a/app/views/dashboard/stepper/plannings/edit.html.slim b/app/views/dashboard/stepper/plannings/edit.html.slim index 90290e4be..dfada994a 100644 --- a/app/views/dashboard/stepper/plannings/edit.html.slim +++ b/app/views/dashboard/stepper/plannings/edit.html.slim @@ -16,4 +16,5 @@ submit_button: true , model: model, method: method, - url: url + url: url, + duplication: false diff --git a/db/migrate/20241204173244_add_employer_phone_to_entreprise.rb b/db/migrate/20241204173244_add_employer_phone_to_entreprise.rb new file mode 100644 index 000000000..4d4726fa5 --- /dev/null +++ b/db/migrate/20241204173244_add_employer_phone_to_entreprise.rb @@ -0,0 +1,5 @@ +class AddEmployerPhoneToEntreprise < ActiveRecord::Migration[7.1] + def change + add_column :entreprises, :contact_phone, :string, limit: 20 + end +end diff --git a/test/controllers/dashboard/stepper/entreprises_controller_test.rb b/test/controllers/dashboard/stepper/entreprises_controller_test.rb index 7064b617f..3dac6ebe2 100644 --- a/test/controllers/dashboard/stepper/entreprises_controller_test.rb +++ b/test/controllers/dashboard/stepper/entreprises_controller_test.rb @@ -37,6 +37,7 @@ class EntreprisesControllerTest < ActionDispatch::IntegrationTest entreprise_chosen_full_address: 'Testo in Paris', entreprise_coordinates_longitude: '2.35', entreprise_coordinates_latitude: '48.85', + contact_phone: '0123456789', is_public: false, sector_id: sector.id, workspace_conditions: 'Environnement de travail', diff --git a/test/factories/entreprises.rb b/test/factories/entreprises.rb index e61ed447a..926bd4323 100644 --- a/test/factories/entreprises.rb +++ b/test/factories/entreprises.rb @@ -10,6 +10,7 @@ entreprise_full_address { FFaker::AddressFR.full_address } entreprise_chosen_full_address { FFaker::AddressFR.full_address } entreprise_coordinates { Coordinates.paris } + contact_phone { FFaker::PhoneNumberFR.phone_number } workspace_conditions { FFaker::Lorem.paragraph } workspace_accessibility { FFaker::Lorem.paragraph } diff --git a/test/factories/internship_offers.rb b/test/factories/internship_offers.rb index c08330252..21fa2957e 100644 --- a/test/factories/internship_offers.rb +++ b/test/factories/internship_offers.rb @@ -8,7 +8,7 @@ planning { create(:planning, entreprise: entreprise) } sequence(:title) { |n| "Stage de 2de - #{n}" } description { 'Lorem ipsum dolor' } - # contact_phone { '+330612345678' } + contact_phone { '+330612345678' } max_candidates { 1 } blocked_weeks_count { 0 } sector { create(:sector) } diff --git a/test/models/entreprise_test.rb b/test/models/entreprise_test.rb index 80a363217..0cfa9bebb 100644 --- a/test/models/entreprise_test.rb +++ b/test/models/entreprise_test.rb @@ -21,6 +21,7 @@ class EntrepriseTest < ActiveSupport::TestCase entreprise.entreprise_coordinates = { latitude: 48.8566, longitude: 2.3522 } assert_equal 2.3522, entreprise.entreprise_coordinates.longitude assert_equal 48.8566, entreprise.entreprise_coordinates.latitude + assert entreprise.contact_phone.gsub(' ', '').match?(/0\d{9}/) end test 'tutor partially filled form fails gracefully' do diff --git a/test/support/entreprise_form_filler.rb b/test/support/entreprise_form_filler.rb index c6d57bbe9..1bb580481 100644 --- a/test/support/entreprise_form_filler.rb +++ b/test/support/entreprise_form_filler.rb @@ -47,6 +47,7 @@ def fill_in_entreprise_form(group: nil, sector: nil) assert_equal 'COMMUNE DE SAINT OUEN L AUMONE', find('input#entreprise_employer_name', visible: true).value.strip fill_in "Indiquez le nom de l'enseigne de l'établissement d'accueil, si elle diffère de la raison sociale", with: 'Mairie de Saint-Ouen-l’Aumône' + fill_in 'Numéro de téléphone du dépositaire *', with: '0130131313' end def fill_in_entreprise_manual_form(group: nil, sector: nil) diff --git a/test/support/third_party_test_helpers.rb b/test/support/third_party_test_helpers.rb index d6e16c2cd..c1966e6e9 100644 --- a/test/support/third_party_test_helpers.rb +++ b/test/support/third_party_test_helpers.rb @@ -166,4 +166,21 @@ def fim_teacher_without_school_userinfo_stub 'rne' => '0590121X' }.to_json, headers: {}) end + + def prismic_stub(body_content) + headers = { + 'Accept': 'application/json', + 'Accept-Encoding': 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', + 'User-Agent': 'Ruby' + } + stub_request(:get, "#{ENV.fetch('PRISMIC_URL')}?access_token=#{ENV.fetch('PRISMIC_API_KEY')}") + .with(headers: headers) + .to_return(status: 200, body: body_content, headers: {}) + end + + def prismic_straight_stub(&block) + PagesController.stub_any_instance(:get_resources, []) do + PagesController.stub_any_instance(:get_faqs, [], &block) + end + end end diff --git a/test/system/dashboard/stepper/manage_entreprises_test.rb b/test/system/dashboard/stepper/manage_entreprises_test.rb index 608612169..8cc66df70 100644 --- a/test/system/dashboard/stepper/manage_entreprises_test.rb +++ b/test/system/dashboard/stepper/manage_entreprises_test.rb @@ -45,6 +45,7 @@ class ManageEntreprisesTest < ApplicationSystemTestCase visit new_dashboard_stepper_entreprise_path(internship_occupation_id: internship_occupation.id) fill_in_entreprise_manual_form(group:, sector:) find('p.fr-card__desc[data-write-summary-card-target="employerNameOutput"]', text: 'Mairie de Saint-Ouen-l’Aumône') + fill_in('Numéro de téléphone du dépositaire *', with: '0130131313') find("button[type='submit']").click find('#alert-success', text: "Les informations de l'entreprise ont bien été enregistrées") diff --git a/test/system/internship_application_student_flow_test.rb b/test/system/internship_application_student_flow_test.rb index b8e008c23..f277ce172 100644 --- a/test/system/internship_application_student_flow_test.rb +++ b/test/system/internship_application_student_flow_test.rb @@ -89,25 +89,27 @@ class InternshipApplicationStudentFlowTest < ApplicationSystemTestCase test 'student with approved application can see employer\'s address' do skip 'failing test on CI but passing locally' if ENV.fetch('CI') == 'true' - school = create(:school, :with_school_manager) - student = create(:student, - school:, - class_room: create(:class_room, school:)) - internship_application = create( - :weekly_internship_application, - :approved, - student: - ) - sign_in(student) - visit '/' - visit dashboard_students_internship_applications_path(student, internship_application.internship_offer) - url = dashboard_students_internship_application_path( - student_id: student.id, - uuid: internship_application.uuid - ) - assert page.has_selector?("a[href='#{url}']", count: 1) - visit url - find('.row .col-12 .fr-pl-1w.blue-france', text: '1 rue du poulet 75001 Paris') + prismic_straight_stub do + school = create(:school, :with_school_manager) + student = create(:student, + school:, + class_room: create(:class_room, school:)) + internship_application = create( + :weekly_internship_application, + :approved, + student: + ) + sign_in(student) + visit '/' + visit dashboard_students_internship_applications_path(student, internship_application.internship_offer) + url = dashboard_students_internship_application_path( + student_id: student.id, + id: internship_application.id + ) + assert page.has_selector?("a[href='#{url}']", count: 1) + visit url + find('.row .col-12 .fr-pl-1w.blue-france', text: '1 rue du poulet 75001 Paris') + end end test 'student with submittted application can not see employer\'s address' do @@ -127,13 +129,15 @@ class InternshipApplicationStudentFlowTest < ApplicationSystemTestCase end test 'when an employer tries to access application forms, she fails' do - employer = create(:employer) - internship_offer = create(:weekly_internship_offer_2nde) - visit internship_offer_path(internship_offer.id) - first(:link, 'Postuler').click - fill_in('Adresse électronique', with: employer.email) - fill_in('Mot de passe', with: employer.password) - click_button('Se connecter') - assert page.has_selector?('span#alert-text', text: "Vous n'êtes pas autorisé à effectuer cette action.") + prismic_straight_stub do + employer = create(:employer) + internship_offer = create(:weekly_internship_offer_2nde) + visit internship_offer_path(internship_offer.id) + first(:link, 'Postuler').click + fill_in('Adresse électronique', with: employer.email) + fill_in('Mot de passe', with: employer.password) + click_button('Se connecter') + assert page.has_selector?('span#alert-text', text: "Vous n'êtes pas autorisé à effectuer cette action.") + end end end