Skip to content

Commit

Permalink
Introduce InduEtrangerMapper + Improve StudentMerger (#1393)
Browse files Browse the repository at this point in the history
  • Loading branch information
pskl authored Feb 18, 2025
1 parent a42da41 commit eaaaf0a
Show file tree
Hide file tree
Showing 13 changed files with 278 additions and 38 deletions.
8 changes: 8 additions & 0 deletions app/models/student.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class Student < ApplicationRecord # rubocop:disable Metrics/ClassLength
:address_line1,
:address_postal_code,
:address_city_insee_code,
:address_city,
:address_country_code,
:birthplace_city_insee_code,
:birthplace_country_insee_code,
Expand Down Expand Up @@ -122,6 +123,13 @@ def index_name
[last_name, first_name].join(" ")
end

def ==(other)
last_name.eql?(other.last_name) &&
first_name.eql?(other.first_name) &&
birthplace_city_insee_code.eql?(other.birthplace_city_insee_code) &&
birthdate.eql?(other.birthdate)
end

def close_current_schooling!(date = Time.zone.today)
current_schooling&.update!(end_date: date)
end
Expand Down
29 changes: 29 additions & 0 deletions app/services/asp/mappers/adresse/indu_etranger_mapper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

module ASP
module Mappers
module Adresse
class InduEtrangerMapper < FranceMapper
def localiteetranger
student.address_city
end

def bureaudistribetranger
student.address_postal_code
end

def voiepointgeoetranger
student.address_line1
end

def districtetranger
student.address_line2
end

def regionetranger
student.address_line2
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module ASP
module Mappers
module Adresse
class InduMapper < FranceMapper
class InduFranceMapper < FranceMapper
def pointremise
student.address_line1
end
Expand Down
2 changes: 2 additions & 0 deletions app/services/student_merger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ class StudentMerger
class StudentMergerError < StandardError; end
class InvalidStudentsArrayError < StudentMergerError; end
class ActiveSchoolingError < StudentMergerError; end
class StudentNotIdenticalError < StudentMergerError; end

attr_reader :students

Expand Down Expand Up @@ -33,6 +34,7 @@ def merge!

def validate_students!
raise InvalidStudentsArrayError unless students.is_a?(Array) && students.length == 2
raise StudentNotIdenticalError unless students[0] == students[1]
end

def determine_target_and_merge_student!
Expand Down
2 changes: 1 addition & 1 deletion config/initializers/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Aplypro
VERSION = "2.2.2"
VERSION = "2.2.3"
end
25 changes: 25 additions & 0 deletions docs/fusion_élèves.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Fusion élèves

## Description

Dans les SI du système éducatif français il n'est pas impossible qu'un élève physique se retrouve avec 2 INE. Lorsque c'est le cas il est possible qu'un retour d'intégration ASP échoue car il existe une contrainte d'unicité sur l'attribut `asp_individu_id`. Pour remédier ces cas et relancer l'intégration il est nécessaire de dédoublonner l'objet `Student` qui pose problème. Il existe à cet effet la classe `StudentMerger`.

## Mode d'emploi

## Etape 1: selectionner l'étudiant

En utilisant l'id qui remonte dans Sentry ou Sidekiq:

`student = Student.find_by!(asp_individu_id: asp_id)`

## Etape 2: Verifier si il y a des doublons

`students = Student.where(last_name: student.last_name, first_name: student.first_name, birthplace_city_inseecode: student.birthplace_city_inseecode, birthdate: student.birthdate)`

## Etape 3: Fusionner les étudiants

`StudentMerger.new(students.to_a).merge!`

## Etape 4: Relancer les fichiers d'intégration

Cliquer "Retry Now" pour le job dans le panneau d'administration de Sidekiq.
53 changes: 53 additions & 0 deletions lib/asp/entities/adresse/indu_etranger.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

module ASP
module Entities
module Adresse
class InduEtranger < Entity
ADRESSE_ATTR_MAX_LENGTH = 38

attribute :localiteetranger, :string
attribute :bureaudistribetranger, :string
attribute :voiepointgeoetranger, :string
attribute :districtetranger, :string
attribute :regionetranger, :string
attribute :codetypeadr, :string
attribute :codeinseepays, :string

validates_presence_of %i[
localiteetranger
bureaudistribetranger
codetypeadr
codeinseepays
]

validates_length_of :localiteetranger, maximum: ADRESSE_ATTR_MAX_LENGTH
validates_length_of :bureaudistribetranger, maximum: ADRESSE_ATTR_MAX_LENGTH

validates_length_of :voiepointgeoetranger, maximum: ADRESSE_ATTR_MAX_LENGTH, allow_nil: true
validates_length_of :districtetranger, maximum: ADRESSE_ATTR_MAX_LENGTH, allow_nil: true
validates_length_of :regionetranger, maximum: ADRESSE_ATTR_MAX_LENGTH, allow_nil: true

def self.payment_mapper_class
Mappers::Adresse::InduEtrangerMapper
end

def root_node_name
"adresse"
end

def fragment(xml) # rubocop:disable Metrics/AbcSize
xml.codetypeadr(codetypeadr)
xml.codeinseepays(codeinseepays)

xml.localiteetranger(localiteetranger)
xml.bureaudistribetranger(bureaudistribetranger)

xml.voiepointgeoetranger(voiepointgeoetranger) if voiepointgeoetranger.present?
xml.districtetranger(districtetranger) if districtetranger.present?
xml.regionetranger(regionetranger) if regionetranger.present?
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
module ASP
module Entities
module Adresse
class Indu < Entity
class InduFrance < Entity
ADRESSE_ATTR_MAX_LENGTH = 38

attribute :pointremise, :string, limit: ADRESSE_ATTR_MAX_LENGTH
attribute :cpltdistribution, :string, limit: ADRESSE_ATTR_MAX_LENGTH
attribute :pointremise, :string
attribute :cpltdistribution, :string
attribute :codetypeadr, :string
attribute :codecominsee, :string
attribute :codeinseepays, :string
Expand All @@ -21,8 +21,11 @@ class Indu < Entity
codecominsee
]

validates_length_of :pointremise, maximum: ADRESSE_ATTR_MAX_LENGTH
validates_length_of :cpltdistribution, maximum: ADRESSE_ATTR_MAX_LENGTH, allow_nil: true

def self.payment_mapper_class
Mappers::Adresse::InduMapper
Mappers::Adresse::InduFranceMapper
end

def root_node_name
Expand Down
2 changes: 1 addition & 1 deletion lib/asp/entities/entity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def root_node_name

def adresse_entity_class
if payment_request.pfmp.rectified?
Adresse::Indu
payment_request.student.lives_in_france? ? Adresse::InduFrance : Adresse::InduEtranger
else
payment_request.student.lives_in_france? ? Adresse::France : Adresse::Etranger
end
Expand Down
46 changes: 46 additions & 0 deletions spec/lib/asp/entities/adresse/indu_etranger_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# frozen_string_literal: true

require "rails_helper"

describe ASP::Entities::Adresse::InduEtranger, type: :model do
describe "fragment" do
let(:pfmp) { create(:pfmp, :rectified) }

before do
pfmp.student.update(
address_line1: "A" * 38,
address_line2: "B" * 38,
address_city: "Cool City",
address_postal_code: 66_666
)
end

describe "validation" do
it { is_expected.to validate_presence_of(:localiteetranger) }
it { is_expected.to validate_presence_of(:bureaudistribetranger) }
it { is_expected.to validate_presence_of(:codetypeadr) }
end

it_behaves_like "an XML-fragment producer" do
let(:entity) { described_class.from_payment_request(pfmp.latest_payment_request) }
let(:probe) { %w[codetypeadr PRINCIPALE] }

it "uses the establishment details for the address" do # rubocop:disable RSpec/MultipleExpectations
expect(document.at("localiteetranger").text).to eq "Cool City"
expect(document.at("bureaudistribetranger").text).to eq 66_666.to_s
end

context "when the addresse is too long" do
before do
pfmp.student.update(
address_city: "A" * 50
)
end

it "errors" do
expect { document.to_s }.to raise_error ActiveModel::ValidationError
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

require "rails_helper"

describe ASP::Entities::Adresse::Indu, type: :model do
describe ASP::Entities::Adresse::InduFrance, type: :model do
describe "fragment" do
let(:pfmp) { create(:pfmp, :rectified) }

before do
pfmp.student.update(
address_line1: "A" * 50,
address_line2: "B" * 50
address_line1: "A" * 38,
address_line2: "B" * 38
)
end

Expand All @@ -29,6 +29,19 @@
expect(document.at("pointremise").text).to eq "A" * 38
expect(document.at("cpltdistribution").text).to eq "B" * 38
end

context "when the addresse is too long" do
before do
pfmp.student.update(
address_line1: "A" * 50,
address_line2: "B" * 50
)
end

it "errors" do
expect { document.to_s }.to raise_error ActiveModel::ValidationError
end
end
end
end
end
37 changes: 37 additions & 0 deletions spec/models/student_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,43 @@
end
end

describe "#==" do
let(:original_student) { build(:student) }
let(:new_student) do
build(
:student,
last_name: original_student.last_name,
first_name: original_student.first_name,
birthplace_city_insee_code: original_student.birthplace_city_insee_code,
birthdate: original_student.birthdate
)
end

it "returns true when all matching attributes are equal" do
expect(original_student == new_student).to be true
end

it "returns false when last_name differs" do
new_student.last_name = "Different"
expect(original_student == new_student).to be false
end

it "returns false when first_name differs" do
new_student.first_name = "Different"
expect(original_student == new_student).to be false
end

it "returns false when birthplace_city_insee_code differs" do
new_student.birthplace_city_insee_code = "99999"
expect(original_student == new_student).to be false
end

it "returns false when birthdate differs" do
new_student.birthdate = 1.day.ago
expect(original_student == new_student).to be false
end
end

describe "biological_sex" do
it "can be unknown" do
expect(build(:student, biological_sex: nil)).to be_valid
Expand Down
Loading

0 comments on commit eaaaf0a

Please sign in to comment.