feat(sva): calculcate decision date with corrections delays & resume methods

This commit is contained in:
Colin Darie 2023-06-05 18:53:03 +02:00
parent 5db80ee6de
commit 4bdd4310ab
No known key found for this signature in database
GPG key ID: 4FB865FDBCA4BCC4
5 changed files with 175 additions and 58 deletions

View file

@ -1070,7 +1070,7 @@ class Dossier < ApplicationRecord
return unless procedure.sva_svr_enabled?
return if sva_svr_decision_triggered_at.present?
self.sva_svr_decision_on = SVASVRDateCalculatorService.new(self, procedure).calculate
self.sva_svr_decision_on = SVASVRDecisionDateCalculatorService.new(self, procedure).decision_date
if en_construction? && may_passer_automatiquement_en_instruction?
passer_automatiquement_en_instruction!

View file

@ -1,23 +0,0 @@
class SVASVRDateCalculatorService
attr_reader :dossier, :procedure
def initialize(dossier, procedure)
@dossier = dossier
@procedure = procedure
end
def calculate
config = procedure.sva_svr_configuration
unit = config.unit.to_sym
period = config.period.to_i
case unit
when :days
dossier.depose_at.to_date + period.days
when :weeks
dossier.depose_at.to_date + period.weeks
when :months
dossier.depose_at.to_date + period.months
end
end
end

View file

@ -0,0 +1,56 @@
class SVASVRDecisionDateCalculatorService
attr_reader :dossier, :procedure, :unit, :period, :resume_method
def initialize(dossier, procedure)
@dossier = dossier
@procedure = procedure
config = procedure.sva_svr_configuration
@unit = config.unit.to_sym
@period = config.period.to_i
@resume_method = config.resume.to_sym
end
def decision_date
base_date = determine_base_date
duration = case unit
when :days
period.days
when :weeks
period.weeks
when :months
period.months
end
base_date + duration
end
private
def determine_base_date
return dossier.depose_at.to_date + total_correction_delay if resume_method == :continue
if dossier.corrections.any?
most_recent_correction_date
else
dossier.depose_at.to_date
end
end
def total_correction_delay
dossier.corrections.sum do |correction|
# If the correction is not resolved, we use the current date
# so interfaces could calculate how many remaining days
resolved_date = correction.resolved_at&.to_date || Date.current
(resolved_date - correction.created_at.to_date).days
end
end
def most_recent_correction_date
return Date.current if dossier.pending_correction?
dossier.corrections.max_by(&:resolved_at).resolved_at.to_date
end
end

View file

@ -1,34 +0,0 @@
require 'rails_helper'
describe SVASVRDateCalculatorService do
let(:procedure) { create(:procedure, sva_svr: config) }
let(:dossier) { create(:dossier, :en_instruction, procedure:, depose_at: DateTime.new(2023, 5, 15, 12)) }
subject { described_class.new(dossier, procedure).calculate }
describe '#calculate' do
context 'when sva has a months period' do
let(:config) { { decision: :sva, period: 2, unit: :months, resume: :continue } }
it 'calculates the date based on SVA rules' do
expect(subject).to eq(Date.new(2023, 7, 15))
end
end
context 'when sva has a days period' do
let(:config) { { decision: :sva, period: 30, unit: :days, resume: :continue } }
it 'calculates the date based on SVA rules' do
expect(subject).to eq(Date.new(2023, 6, 14))
end
end
context 'when sva has a weeks period' do
let(:config) { { decision: :sva, period: 8, unit: :weeks, resume: :continue } }
it 'calculates the date based on SVA rules' do
expect(subject).to eq(Date.new(2023, 7, 10))
end
end
end
end

View file

@ -0,0 +1,118 @@
require 'rails_helper'
describe SVASVRDecisionDateCalculatorService do
include ActiveSupport::Testing::TimeHelpers
let(:procedure) { create(:procedure, sva_svr: config) }
let(:dossier) { create(:dossier, :en_instruction, procedure:, depose_at: DateTime.new(2023, 5, 15, 12)) }
subject { described_class.new(dossier, procedure).decision_date }
describe '#decision_date' do
context 'when sva has a months period' do
let(:config) { { decision: :sva, period: 2, unit: :months, resume: :continue } }
it 'calculates the date based on SVA rules' do
expect(subject).to eq(Date.new(2023, 7, 15))
end
end
context 'when sva has a days period' do
let(:config) { { decision: :sva, period: 30, unit: :days, resume: :continue } }
it 'calculates the date based on SVA rules' do
expect(subject).to eq(Date.new(2023, 6, 14))
end
end
context 'when sva has a weeks period' do
let(:config) { { decision: :sva, period: 8, unit: :weeks, resume: :continue } }
it 'calculates the date based on SVA rules' do
expect(subject).to eq(Date.new(2023, 7, 10))
end
end
context 'when sva resume setting is continue' do
let(:config) { { decision: :sva, period: 2, unit: :months, resume: :continue } }
context 'when a dossier is corrected and resolved' do
let!(:correction) do
created_at = DateTime.new(2023, 5, 20, 15)
resolved_at = DateTime.new(2023, 5, 25, 12)
create(:dossier_correction, dossier:, created_at:, resolved_at:)
end
it 'calculates the date based on SVA rules with correction delay' do
expect(subject).to eq(Date.new(2023, 7, 20))
end
context 'when there are multiple corrections' do
let!(:correction2) do
created_at = DateTime.new(2023, 5, 30, 18)
resolved_at = DateTime.new(2023, 6, 3, 8)
create(:dossier_correction, dossier:, created_at:, resolved_at:)
end
it 'calculates the date based on SVA rules with all correction delays' do
expect(subject).to eq(Date.new(2023, 7, 24))
end
end
context 'there is a pending correction' do
before do
travel_to DateTime.new(2023, 5, 30, 18) do
dossier.flag_as_pending_correction!(build(:commentaire, dossier:))
end
travel_to DateTime.new(2023, 6, 5, 8) # 6 days elapsed
end
it 'calculates the date, like if resolution will be today' do
expect(subject).to eq(Date.new(2023, 7, 26))
end
end
end
end
context 'when sva resume setting is reset' do
let(:config) { { decision: :sva, period: 2, unit: :months, resume: :reset } }
context 'there is no correction' do
it 'calculates the date based on deposed_at' do
expect(subject).to eq(Date.new(2023, 7, 15))
end
end
context 'there are multiple resolved correction' do
before do
created_at = DateTime.new(2023, 5, 16, 15)
resolved_at = DateTime.new(2023, 5, 17, 12)
create(:dossier_correction, dossier:, created_at:, resolved_at:)
created_at = DateTime.new(2023, 5, 20, 15)
resolved_at = DateTime.new(2023, 5, 25, 12)
create(:dossier_correction, dossier:, created_at:, resolved_at:)
end
it 'calculates the date based on SVA rules from the last resolved date' do
expect(subject).to eq(Date.new(2023, 7, 25))
end
end
context 'there is a pending correction' do
before do
travel_to DateTime.new(2023, 5, 30, 18) do
dossier.flag_as_pending_correction!(build(:commentaire, dossier:))
end
travel_to DateTime.new(2023, 6, 5, 8)
end
it 'calculates the date, like if resolution will be today and delay restarted' do
expect(subject).to eq(Date.new(2023, 8, 5))
end
end
end
end
end