Skip to content

Commit

Permalink
Merge branch 'main' into feat/dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
pskl committed Nov 12, 2024
2 parents 31b8f42 + a1a4a55 commit 8085234
Show file tree
Hide file tree
Showing 22 changed files with 299 additions and 280 deletions.
2 changes: 1 addition & 1 deletion app/controllers/classes_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def bulk_pfmp_completion
def update_bulk_pfmp
@pfmps = bulk_pfmp_completion_params[:pfmps].map do |pfmp_params|
@classe.pfmps.find(pfmp_params[:id]).tap do |pfmp|
pfmp.day_count = pfmp_params[:day_count]
PfmpManager.new(pfmp).update(day_count: pfmp_params[:day_count])
end
end

Expand Down
6 changes: 3 additions & 3 deletions app/controllers/pfmps_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ def new
def edit; end

def create
@pfmp = Pfmp.new(pfmp_params.merge(schooling: @schooling))
@pfmp = Pfmp.new

if @pfmp.save
if PfmpManager.new(@pfmp).update(pfmp_params.merge(schooling: @schooling))
redirect_to student_path(@schooling.student),
notice: t("pfmps.new.success")
else
Expand All @@ -31,7 +31,7 @@ def create
end

def update
if @pfmp.update(pfmp_params)
if PfmpManager.new(@pfmp).update(pfmp_params)
redirect_to school_year_class_schooling_pfmp_path(selected_school_year, @classe, @schooling, @pfmp),
notice: t("pfmps.edit.success")
else
Expand Down
2 changes: 0 additions & 2 deletions app/jobs/generate_attributive_decisions_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

class GenerateAttributiveDecisionsJob < ApplicationJob
def perform(schoolings)
Schooling.transaction { schoolings.each { |s| s.update!(generating_attributive_decision: true) } }

jobs = schoolings.map { |schooling| GenerateAttributiveDecisionJob.new(schooling) }

ActiveJob.perform_all_later(jobs)
Expand Down
11 changes: 9 additions & 2 deletions app/jobs/janitor_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,25 @@ class JanitorJob < ApplicationJob
sidekiq_options retry: false

def perform
reset_attributive_decision_version_overflow
reset_attributive_decision_version_attribute
reset_generating_attributive_decision_attribute
end

private

def reset_attributive_decision_version_overflow
def reset_attributive_decision_version_attribute
Schooling.where("attributive_decision_version > ?", 9).find_each do |schooling|
schooling.update!(attributive_decision_version: 9)
end
true
end

def reset_generating_attributive_decision_attribute
Schooling.generating_attributive_decision.each do |schooling|
schooling.update(generating_attributive_decision: false)
end
end

def squish_codes_above_five
%i[address_city_insee_code address_postal_code].each do |code|
Student.where("LENGTH(#{code}) > 5").find_each do |s|
Expand Down
42 changes: 0 additions & 42 deletions app/models/concerns/pfmp_amount_calculator.rb

This file was deleted.

36 changes: 13 additions & 23 deletions app/models/pfmp.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
# frozen_string_literal: true

class Pfmp < ApplicationRecord # rubocop:disable Metrics/ClassLength
include PfmpAmountCalculator

TRANSITION_CLASS = PfmpTransition
STATE_MACHINE_CLASS = PfmpStateMachine
TRANSITION_RELATION_NAME = :transitions
Expand Down Expand Up @@ -50,6 +48,8 @@ class Pfmp < ApplicationRecord # rubocop:disable Metrics/ClassLength
comparison: { greater_than_or_equal_to: :start_date },
if: -> { start_date && end_date }

validates :amount, numericality: { only_integer: true, allow_nil: true, greater_than_or_equal_to: 0 }

validates :day_count,
numericality: {
only_integer: true,
Expand All @@ -66,25 +66,6 @@ class Pfmp < ApplicationRecord # rubocop:disable Metrics/ClassLength

before_destroy :ensure_destroyable?, prepend: true

after_save do
if day_count.present?
transition_to!(:completed) if in_state?(:pending)
elsif in_state?(:completed, :validated)
transition_to!(:pending)
end
end

after_save :recalculate_amounts_if_needed

# Recalculate amounts for the current PFMP and all follow up PFMPs that are still modifiable
def recalculate_amounts_if_needed
changed_day_count = day_count_before_last_save != day_count

return if !changed_day_count

PfmpManager.new(self).recalculate_amounts!
end

def validate!
transition_to!(:validated)
end
Expand Down Expand Up @@ -156,15 +137,24 @@ def can_retrigger_payment?
latest_payment_request.failed?
end

def all_pfmps_for_mef
student.pfmps
.joins(schooling: :classe)
.where("classes.mef_id": mef.id, "classes.school_year_id": school_year.id)
end

private

def amounts_yearly_cap
return unless mef

pfmps = all_pfmps_for_mef
cap = mef.wage.yearly_cap
total = all_pfmps_for_mef.sum(:amount)
total = pfmps.sum(:amount)
return unless total > cap

errors.add(:amount, "Yearly cap of #{cap} not respected for Mef code: #{mef.code}")
errors.add(:amount,
"Yearly cap of #{cap} not respected for Mef code: #{mef.code} \\
-> #{total}/#{cap} with #{pfmps.count} PFMPs")
end
end
5 changes: 0 additions & 5 deletions app/models/pfmp_state_machine.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,10 @@ class PfmpStateMachine
end

after_transition(to: :rectified) do |pfmp|
PfmpManager.new(pfmp).recalculate_amounts!
new_payment_request = PfmpManager.new(pfmp).create_new_payment_request!
new_payment_request.mark_ready!
end

after_transition(to: :completed) do |pfmp|
PfmpManager.new(pfmp).recalculate_amounts!
end

after_transition(to: :validated) do |pfmp|
PfmpManager.new(pfmp).create_new_payment_request!
end
Expand Down
2 changes: 1 addition & 1 deletion app/models/student/mappers/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def parse!

Sentry.capture_exception(
SchoolingParsingError.new(
"Schooling parsing failed for #{uai}: #{e.message}"
"Schooling parsing failed for entry: #{entry} , for UAI: #{uai} with message: #{e.message}"
)
)
end
Expand Down
4 changes: 1 addition & 3 deletions app/models/student/mappers/sygne.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@ def map_schooling!(classe, student, entry)
.find_or_initialize_by(classe: classe, student: student)
.tap { |sc| sc.assign_attributes(attributes) }

student.close_current_schooling! if schooling != student.current_schooling
student.close_current_schooling! if schooling.open? && student.current_schooling != schooling

schooling.save!
end

def map_schooling_attributes(entry)
schooling_mapper.new.call(entry).slice(:status, :start_date, :end_date)
rescue StandardError => e
raise SchoolingParsingError.new, "Schooling parsing failure for #{uai}: #{e.message}"
end
end
end
Expand Down
21 changes: 3 additions & 18 deletions app/services/asp/mappers/coord_paie_mapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@ class CoordPaieMapper
PRINCIPAL_ADDRESS_TYPE = "PRINCIPALE"
ASSIMILATED_FRENCH_COUNTRY_CODES = %w[FR GF GP MC MQ NC PF PM RE WF YT].freeze

PARTICULAR_BICS = {
CREDIT_MUTUEL_ARKEA: "CMBRFR2BARK",
BNP_PARIBAS_METZ: "BNPAFRPPMTZ",
BNP_PARIBAS_LYON: "BNPAFRPPTAS"
}.freeze
PARTICULAR_BICS = %w[CMBRFR2BARK BNPAFRPPMTZ BNPAFRPPTAS BNPAFRPPETI].freeze

MAPPING = {
bic: :bic
Expand Down Expand Up @@ -60,7 +56,7 @@ def bic
bic = rib.bic

if particular_bic?
particular_rib_treatment(bic)
bic[0..-4]
elsif french_rib?
bic.delete_suffix("XXX")
elsif bic.length == 8
Expand All @@ -77,18 +73,7 @@ def french_rib?
end

def particular_bic?
PARTICULAR_BICS.values.include?(rib.bic)
end

def particular_rib_treatment(bic)
case PARTICULAR_BICS.key(bic)
when :CREDIT_MUTUEL_ARKEA
bic.gsub("ARK", "")
when :BNP_PARIBAS_METZ
bic.gsub("MTZ", "")
when :BNP_PARIBAS_LYON
bic.gsub("TAS", "")
end
PARTICULAR_BICS.include?(rib.bic)
end
end
end
Expand Down
79 changes: 66 additions & 13 deletions app/services/pfmp_manager.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# frozen_string_literal: true

# Simple Ruby service to Handle complex actions on PFMPs
# TODO: refactor PfmpAmountCalculator to be part of this class (requires a lot of spec changes)

class PfmpManager
class PfmpManagerError < StandardError; end
Expand All @@ -15,12 +14,20 @@ def initialize(pfmp)
@pfmp = pfmp
end

def recalculate_amounts!
raise PfmpNotModifiableError unless pfmp.can_be_modified?
def update(params)
update!(params)
true
rescue ActiveRecord::RecordInvalid
false
end

ApplicationRecord.transaction do
pfmp.update!(amount: pfmp.calculate_amount)
rebalance_following_pfmps!
def update!(params)
params = params.to_h.with_indifferent_access

Pfmp.transaction do
pfmp.update!(params)
recalculate_amounts! if params[:day_count].present?
transition!
end
end

Expand All @@ -41,13 +48,20 @@ def retry_incomplete_payment_request!
end

def rectify_and_update_attributes!(confirmed_pfmp_params, confirmed_address_params)
ApplicationRecord.transaction do
@pfmp.update!(confirmed_pfmp_params)
@pfmp.student.update!(confirmed_address_params)
@pfmp.rectify!
Pfmp.transaction do
update!(confirmed_pfmp_params)
pfmp.student.update!(confirmed_address_params)
pfmp.rectify!
end
end

def previously_locked_amount(pfmp)
other_priced_pfmps(pfmp)
.map(&:amount)
.compact
.sum
end

def retry_payment_request!(reasons)
return unless @pfmp.latest_payment_request&.eligible_for_rejected_or_unpaid_auto_retry?(reasons)

Expand All @@ -57,9 +71,48 @@ def retry_payment_request!(reasons)

private

def rebalance_following_pfmps!
pfmp.rebalancable_pfmps.each do |pfmp|
pfmp.update!(amount: pfmp.calculate_amount)
def calculate_amount(target_pfmp)
return 0 if target_pfmp.day_count.nil?

[
target_pfmp.day_count * target_pfmp.wage.daily_rate,
target_pfmp.wage.yearly_cap - previously_locked_amount(target_pfmp)
].min
end

def recalculate_amounts!
raise PfmpNotModifiableError unless pfmp.can_be_modified?

pfmp.all_pfmps_for_mef.lock!
pfmp.update!(amount: calculate_amount(pfmp))
rebalance_other_pfmps!
end

def other_pfmps_for_mef(excluded_pfmp)
pfmp.all_pfmps_for_mef.excluding(excluded_pfmp)
end

def other_priced_pfmps(pfmp)
other_pfmps_for_mef(pfmp)
.where.not(amount: nil)
end

def rebalancable_pfmps
@rebalancable_pfmps ||= other_pfmps_for_mef(pfmp)
.select(&:can_be_rebalanced?)
end

def rebalance_other_pfmps!
rebalancable_pfmps.each do |rebalancable_pfmp|
rebalancable_pfmp.update!(amount: calculate_amount(rebalancable_pfmp))
end
end

def transition!
if pfmp.day_count.present?
pfmp.transition_to!(:completed) if pfmp.in_state?(:pending)
elsif pfmp.in_state?(:completed, :validated)
pfmp.transition_to!(:pending)
end
end
end
4 changes: 2 additions & 2 deletions app/views/pfmps/_payment_panel.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
= number_to_currency pfmp.wage.yearly_cap
de plafond maximum par an
%div.fr-mb-1w
= number_to_currency pfmp.previously_locked_amount
engagés par les PFMPs précédemment déclarées et validées.
= number_to_currency PfmpManager.new(pfmp).previously_locked_amount(pfmp)
déjà engagés par d'autres PFMPs sur cette scolarité.
8 changes: 8 additions & 0 deletions db/migrate/20241106195543_add_more_indexes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class AddMoreIndexes < ActiveRecord::Migration[7.2]
disable_ddl_transaction!

def change
add_index :asp_payment_request_transitions, :to_state, algorithm: :concurrently
add_index :pfmp_transitions, :to_state, algorithm: :concurrently
end
end
Loading

0 comments on commit 8085234

Please sign in to comment.