@@ -4,17 +4,35 @@ class PatientImportRow
4
4
include ActiveModel ::Model
5
5
6
6
MAX_FIELD_LENGTH = 300
7
+ VALID_NAME_REGEX = Regexp . new ( <<~REGEXP , Regexp ::EXTENDED ) . freeze
8
+ ^[
9
+ \\ w # ASCII alphanumeric characters
10
+ \u00C0 -\u00D6 # Latin 1 Supplement letters
11
+ \u00D8 -\u00F6 # Latin 1 Supplement letters
12
+ \u00F8 -\u017F # Latin 1 Supplement & Latin Extended A letters
13
+ \u0020 # Space
14
+ \u0027 # Apostrophe
15
+ \u0060 # Grave accent, will be normalised to apostrophe
16
+ \u2019 # Preferred Unicode apostrophe, will be normalised to apostrophe
17
+ \u02BC # Modifier apostrophe, will be normalised to apostrophe
18
+ \u002E # Full stop
19
+ -]+$ # Hyphen has to come at the very end, even for an extended regexp
20
+ REGEXP
7
21
8
22
validate :validate_date_of_birth ,
9
23
:validate_existing_patients ,
10
24
:validate_first_name ,
25
+ :validate_preferred_first_name ,
11
26
:validate_gender_code ,
12
27
:validate_last_name ,
28
+ :validate_preferred_last_name ,
13
29
:validate_nhs_number ,
14
30
:validate_parent_1_email ,
31
+ :validate_parent_1_name ,
15
32
:validate_parent_1_phone ,
16
33
:validate_parent_1_relationship ,
17
34
:validate_parent_2_email ,
35
+ :validate_parent_2_name ,
18
36
:validate_parent_2_phone ,
19
37
:validate_parent_2_relationship ,
20
38
:validate_year_group
@@ -65,14 +83,14 @@ def to_parents
65
83
if parent_1_exists?
66
84
{
67
85
email : parent_1_email_value ,
68
- full_name : parent_1_name &. to_s ,
86
+ full_name : parent_1_name_value ,
69
87
phone : parent_1_phone_value
70
88
}
71
89
end ,
72
90
if parent_2_exists?
73
91
{
74
92
email : parent_2_email_value ,
75
- full_name : parent_2_name &. to_s ,
93
+ full_name : parent_2_name_value ,
76
94
phone : parent_2_phone_value
77
95
}
78
96
end
@@ -182,20 +200,22 @@ def import_attributes
182
200
address_town : address_town &.to_s ,
183
201
birth_academic_year : birth_academic_year_value ,
184
202
date_of_birth : date_of_birth . to_date ,
185
- family_name : last_name . to_s ,
203
+ family_name : ApostropheNormaliser . call ( last_name . to_s ) ,
186
204
gender_code : gender_code_value ,
187
- given_name : first_name . to_s ,
205
+ given_name : ApostropheNormaliser . call ( first_name . to_s ) ,
188
206
nhs_number : nhs_number_value ,
189
- preferred_family_name : preferred_last_name &.to_s ,
190
- preferred_given_name : preferred_first_name &.to_s ,
207
+ preferred_family_name :
208
+ ApostropheNormaliser . call ( preferred_last_name &.to_s ) ,
209
+ preferred_given_name :
210
+ ApostropheNormaliser . call ( preferred_first_name &.to_s ) ,
191
211
registration : registration &.to_s ,
192
212
registration_academic_year :
193
213
} . compact
194
214
end
195
215
196
216
def parent_1_import_attributes
197
217
{
198
- full_name : parent_1_name &. to_s ,
218
+ full_name : parent_1_name_value ,
199
219
email : parent_1_email_value ,
200
220
phone : parent_1_phone_value ,
201
221
relationship : parent_1_relationship &.to_s
@@ -204,7 +224,7 @@ def parent_1_import_attributes
204
224
205
225
def parent_2_import_attributes
206
226
{
207
- full_name : parent_2_name &. to_s ,
227
+ full_name : parent_2_name_value ,
208
228
email : parent_2_email_value ,
209
229
phone : parent_2_phone_value ,
210
230
relationship : parent_2_relationship &.to_s
@@ -356,10 +376,18 @@ def gender_code_value
356
376
gender_code &.to_s &.downcase &.gsub ( " " , "_" )
357
377
end
358
378
379
+ def parent_1_name_value
380
+ ApostropheNormaliser . call ( parent_1_name &.to_s )
381
+ end
382
+
359
383
def parent_1_email_value
360
384
parent_1_email &.to_s &.downcase
361
385
end
362
386
387
+ def parent_2_name_value
388
+ ApostropheNormaliser . call ( parent_2_name &.to_s )
389
+ end
390
+
363
391
def parent_2_email_value
364
392
parent_2_email &.to_s &.downcase
365
393
end
@@ -405,6 +433,8 @@ def validate_first_name
405
433
first_name . header ,
406
434
"is greater than #{ MAX_FIELD_LENGTH } characters long"
407
435
)
436
+ elsif !first_name . to_s . match? ( VALID_NAME_REGEX )
437
+ errors . add ( first_name . header , "includes invalid character(s)" )
408
438
end
409
439
end
410
440
@@ -415,6 +445,18 @@ def validate_gender_code
415
445
end
416
446
end
417
447
448
+ def validate_preferred_first_name
449
+ return if preferred_first_name . blank?
450
+ if preferred_first_name . to_s . length > MAX_FIELD_LENGTH
451
+ errors . add (
452
+ preferred_first_name . header ,
453
+ "is greater than #{ MAX_FIELD_LENGTH } characters long"
454
+ )
455
+ elsif !preferred_first_name . to_s . match? ( VALID_NAME_REGEX )
456
+ errors . add ( preferred_first_name . header , "includes invalid character(s)" )
457
+ end
458
+ end
459
+
418
460
def validate_last_name
419
461
if last_name . nil?
420
462
errors . add ( :base , "<code>CHILD_LAST_NAME</code> is missing" )
@@ -425,6 +467,20 @@ def validate_last_name
425
467
last_name . header ,
426
468
"is greater than #{ MAX_FIELD_LENGTH } characters long"
427
469
)
470
+ elsif !last_name . to_s . match? ( VALID_NAME_REGEX )
471
+ errors . add ( last_name . header , "includes invalid character(s)" )
472
+ end
473
+ end
474
+
475
+ def validate_preferred_last_name
476
+ return if preferred_last_name . blank?
477
+ if preferred_last_name . to_s . length > MAX_FIELD_LENGTH
478
+ errors . add (
479
+ preferred_last_name . header ,
480
+ "is greater than #{ MAX_FIELD_LENGTH } characters long"
481
+ )
482
+ elsif !preferred_last_name . to_s . match? ( VALID_NAME_REGEX )
483
+ errors . add ( preferred_last_name . header , "includes invalid character(s)" )
428
484
end
429
485
end
430
486
@@ -438,6 +494,19 @@ def validate_nhs_number
438
494
) . validate_each ( self , nhs_number . header , nhs_number_value )
439
495
end
440
496
497
+ def validate_parent_1_name
498
+ return if parent_1_name . blank?
499
+
500
+ if parent_1_name . to_s . length > MAX_FIELD_LENGTH
501
+ errors . add (
502
+ parent_1_name . header ,
503
+ "is greater than #{ MAX_FIELD_LENGTH } characters long"
504
+ )
505
+ elsif !parent_1_name . to_s . match? ( VALID_NAME_REGEX )
506
+ errors . add ( parent_1_name . header , "includes invalid character(s)" )
507
+ end
508
+ end
509
+
441
510
def validate_parent_1_email
442
511
return if parent_1_email . blank?
443
512
@@ -465,6 +534,19 @@ def validate_parent_1_relationship
465
534
end
466
535
end
467
536
537
+ def validate_parent_2_name
538
+ return if parent_2_name . blank?
539
+
540
+ if parent_2_name . to_s . length > MAX_FIELD_LENGTH
541
+ errors . add (
542
+ parent_2_name . header ,
543
+ "is greater than #{ MAX_FIELD_LENGTH } characters long"
544
+ )
545
+ elsif !parent_2_name . to_s . match? ( VALID_NAME_REGEX )
546
+ errors . add ( parent_2_name . header , "includes invalid character(s)" )
547
+ end
548
+ end
549
+
468
550
def validate_parent_2_email
469
551
return if parent_2_email . blank?
470
552
0 commit comments