generated from DFE-Digital/govuk-rails-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CPDLP-3586] Migrated over DQTRecordCheck logic to NPQ
- Loading branch information
Showing
12 changed files
with
628 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# frozen_string_literal: true | ||
|
||
module Dqt | ||
class RecordCheck | ||
TITLES = %w[mr mrs miss ms dr prof rev].freeze | ||
|
||
CheckResult = Struct.new( | ||
:dqt_record, | ||
:trn_matches, | ||
:name_matches, | ||
:dob_matches, | ||
:nino_matches, | ||
:total_matched, | ||
:failure_reason, | ||
) | ||
|
||
def call | ||
check_record | ||
end | ||
|
||
private | ||
|
||
attr_reader :trn, :nino, :full_name, :date_of_birth, :check_first_name_only | ||
|
||
def initialize(trn:, full_name:, date_of_birth:, nino: nil, check_first_name_only: true) | ||
@trn = trn | ||
@full_name = full_name&.strip | ||
@date_of_birth = date_of_birth | ||
@nino = nino | ||
@check_first_name_only = check_first_name_only | ||
end | ||
|
||
def dqt_record(padded_trn) | ||
V1::Teacher.find(trn: padded_trn, nino:, birthdate: date_of_birth) | ||
end | ||
|
||
def check_record | ||
return check_failure(:trn_and_nino_blank) if trn.blank? && nino.blank? | ||
|
||
@trn = "0000001" if trn.blank? | ||
|
||
padded_trn = TeacherReferenceNumber.new(trn).formatted_trn | ||
dqt_record = TeacherRecord.new(dqt_record(padded_trn)) | ||
|
||
return check_failure(:no_match_found) if dqt_record.blank? | ||
return check_failure(:found_but_not_active) unless dqt_record.active? | ||
|
||
trn_matches = dqt_record.trn == padded_trn | ||
name_matches = name_matches?(dqt_name: dqt_record.name) | ||
dob_matches = dqt_record.dob == date_of_birth | ||
nino_matches = nino.present? && nino.downcase == dqt_record.ni_number&.downcase | ||
|
||
matches = [trn_matches, name_matches, dob_matches, nino_matches].count(true) | ||
|
||
if matches >= 3 | ||
CheckResult.new(dqt_record, trn_matches, name_matches, dob_matches, nino_matches, matches) | ||
elsif matches < 3 && (trn_matches && trn != "1") | ||
if matches == 2 && !name_matches && check_first_name_only | ||
CheckResult.new(dqt_record, trn_matches, name_matches, dob_matches, nino_matches, matches) | ||
else | ||
# If a participant mistypes their TRN and enters someone else's, we should search by NINO instead | ||
# The API first matches by (mandatory) TRN, then by NINO if it finds no results. This works around that. | ||
@trn = "0000001" | ||
check_record | ||
end | ||
else | ||
# we found a record but not enough matched | ||
check_failure(:no_match_found) | ||
end | ||
end | ||
|
||
def name_matches?(dqt_name:) | ||
return false if full_name.blank? | ||
return false if full_name.in?(TITLES) | ||
return false if dqt_name.blank? | ||
|
||
NameMatcher.new(full_name, dqt_name, check_first_name_only:).matches? | ||
end | ||
|
||
def check_failure(reason) | ||
CheckResult.new(nil, false, false, false, false, 0, reason) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# frozen_string_literal: true | ||
|
||
module Dqt | ||
class TeacherRecord | ||
include ActiveModel::Model | ||
|
||
attr_accessor :trn, | ||
:state_name, | ||
:name, | ||
:dob, | ||
:ni_number, | ||
:active_alert | ||
|
||
def active? | ||
state_name == "Active" | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
# frozen_string_literal: true | ||
|
||
class NameMatcher | ||
attr_reader :name1, :name2, :check_first_name_only | ||
|
||
TITLES = /\A((mr|mrs|miss|ms|dr|prof|rev)\.?)/ | ||
|
||
def initialize(name1, name2, check_first_name_only: true) | ||
@name1 = name1 | ||
@name2 = name2 | ||
@check_first_name_only = check_first_name_only | ||
end | ||
|
||
def matches? | ||
if check_first_name_only? | ||
first_name(name1).downcase == first_name(name2).downcase | ||
else | ||
strip_title(name1).downcase == strip_title(name2).downcase | ||
end | ||
end | ||
|
||
private | ||
|
||
alias_method :check_first_name_only?, :check_first_name_only | ||
|
||
def first_name(name) | ||
strip_title(name).split(" ").first | ||
end | ||
|
||
def strip_title(str) | ||
parts = str.split(" ") | ||
parts.first.downcase =~ TITLES ? parts.drop(1).join(" ") : str | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# frozen_string_literal: true | ||
|
||
class TeacherReferenceNumber | ||
MIN_UNPADDED_TRN_LENGTH = 5 | ||
PADDED_TRN_LENGTH = 7 | ||
|
||
attr_reader :trn, :format_error | ||
|
||
def initialize(trn) | ||
@trn = trn | ||
@format_error = nil | ||
end | ||
|
||
def formatted_trn | ||
@formatted_trn ||= extract_trn_value | ||
end | ||
|
||
def valid? | ||
formatted_trn.present? | ||
end | ||
|
||
private | ||
|
||
def extract_trn_value | ||
@format_error = :blank and return if trn.blank? | ||
|
||
# remove any characters that are not digits | ||
only_digits = trn.to_s.gsub(/[^\d]/, "") | ||
|
||
@format_error = :invalid and return if only_digits.blank? | ||
@format_error = :too_short and return if only_digits.length < MIN_UNPADDED_TRN_LENGTH | ||
@format_error = :too_long and return if only_digits.length > PADDED_TRN_LENGTH | ||
|
||
only_digits.rjust(PADDED_TRN_LENGTH, "0") | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.