Skip to content

Commit 9792643

Browse files
thomasleesebenilovj
authored andcommitted
Try matching against all four values first
This should improve the reliability of repeated cohort uploads by ensuring twins and other scenarios where three of the four datapoints match and don't result in a validation error for multiple matches.
1 parent dd015c4 commit 9792643

File tree

2 files changed

+54
-32
lines changed

2 files changed

+54
-32
lines changed

app/models/patient.rb

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -172,41 +172,61 @@ def self.match_existing(
172172
end
173173

174174
scope =
175-
Patient
176-
.where(
177-
"given_name ILIKE ? AND family_name ILIKE ?",
178-
given_name,
179-
family_name
180-
)
181-
.where(date_of_birth:)
182-
.or(
183-
Patient.where(
184-
"given_name ILIKE ? AND family_name ILIKE ?",
185-
given_name,
186-
family_name
187-
).where(address_postcode:)
188-
)
189-
.or(
190-
Patient.where("given_name ILIKE ?", given_name).where(
191-
date_of_birth:,
192-
address_postcode:
175+
Patient.where(
176+
"given_name ILIKE ? AND family_name ILIKE ?",
177+
given_name,
178+
family_name
179+
).where(date_of_birth:)
180+
181+
if address_postcode.present?
182+
scope =
183+
scope
184+
.or(
185+
Patient.where(
186+
"given_name ILIKE ? AND family_name ILIKE ?",
187+
given_name,
188+
family_name
189+
).where(address_postcode:)
193190
)
194-
)
195-
.or(
196-
Patient.where("family_name ILIKE ?", family_name).where(
197-
date_of_birth:,
198-
address_postcode:
191+
.or(
192+
Patient.where("given_name ILIKE ?", given_name).where(
193+
date_of_birth:,
194+
address_postcode:
195+
)
196+
)
197+
.or(
198+
Patient.where("family_name ILIKE ?", family_name).where(
199+
date_of_birth:,
200+
address_postcode:
201+
)
199202
)
200-
)
203+
end
201204

202-
if nhs_number.blank?
203-
scope.to_a
204-
else
205-
# This prevents us from finding a patient that happens to have at least
206-
# three of the other fields the same, but with a different NHS number,
207-
# and therefore cannot be a match.
208-
Patient.where(nhs_number: nil).merge(scope).to_a
205+
results =
206+
if nhs_number.blank?
207+
scope.to_a
208+
else
209+
# This prevents us from finding a patient that happens to have at least
210+
# three of the other fields the same, but with a different NHS number,
211+
# and therefore cannot be a match.
212+
Patient.where(nhs_number: nil).merge(scope).to_a
213+
end
214+
215+
if address_postcode.present?
216+
# Check for an exact match of all four datapoints, we do this in memory
217+
# to avoid an extra query to the database for each record.
218+
exact_results =
219+
results.select do
220+
_1.given_name.downcase == given_name.downcase &&
221+
_1.family_name.downcase == family_name.downcase &&
222+
_1.date_of_birth == date_of_birth &&
223+
_1.address_postcode == UKPostcode.parse(address_postcode).to_s
224+
end
225+
226+
return exact_results if exact_results.length == 1
209227
end
228+
229+
results
210230
end
211231

212232
def relationship_to(parent:)

spec/models/patient_spec.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,9 @@
160160
context "with matching first name, last name and postcode not provided" do
161161
let(:nhs_number) { nil }
162162
let(:address_postcode) { nil }
163-
let(:patient) { create(:patient, given_name:, family_name:) }
163+
let(:patient) do
164+
create(:patient, given_name:, family_name:, address_postcode: nil)
165+
end
164166

165167
it { should_not include(patient) }
166168
end

0 commit comments

Comments
 (0)