Skip to content

Commit 1afa621

Browse files
Merge branch 'main' into feat/rfr-transformRules
2 parents 440f2f1 + 05923c6 commit 1afa621

File tree

10 files changed

+153
-107
lines changed

10 files changed

+153
-107
lines changed

application/CohortManager/src/Functions/ScreeningValidationService/LookupValidation/Breast_Screening_lookupRules.json

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,25 @@
22
{
33
"WorkflowName": "Common",
44
"GlobalParams": [
5-
{
6-
"Name": "ValidCurrentPosting",
7-
"Expression": "string.IsNullOrEmpty(newParticipant.CurrentPosting) OR dbLookup.CheckIfCurrentPostingExists(newParticipant.CurrentPosting)"
8-
},
95
{
106
"Name": "ValidPrimaryCareProvider",
117
"Expression": "string.IsNullOrEmpty(newParticipant.PrimaryCareProvider) || dbLookup.CheckIfPrimaryCareProviderExists(newParticipant.PrimaryCareProvider)"
128
}
139
],
1410
"Rules": [
1511
{
16-
"RuleName": "45.GPPracticeCodeDoesNotExist.BSSelect.NonFatal",
12+
"RuleName": "45.GPPracticeCodeDoesNotExist.NBO.NonFatal",
1713
"LocalParams": [
1814
{
19-
"Name": "EnglishPostingCategory",
20-
"Expression": "string.Equals(dbLookup.RetrievePostingCategory(newParticipant.CurrentPosting), \"ENGLAND\", StringComparison.OrdinalIgnoreCase)"
21-
},
22-
{
23-
"Name": "InvalidPostingCategory",
24-
"Expression": "!(EnglishPostingCategory || string.Equals(newParticipant.CurrentPosting, \"ENG\", StringComparison.OrdinalIgnoreCase) || string.Equals(newParticipant.CurrentPosting, \"IM\", StringComparison.OrdinalIgnoreCase) || string.Equals(newParticipant.CurrentPosting, \"DMS\", StringComparison.OrdinalIgnoreCase))"
15+
"Name": "WelshPostingCategory",
16+
"Expression": "string.Equals(dbLookup.RetrievePostingCategory(newParticipant.CurrentPosting), \"WALES\", StringComparison.OrdinalIgnoreCase)"
2517
},
2618
{
2719
"Name": "IsExcluded",
2820
"Expression": "dbLookup.CheckIfPrimaryCareProviderInExcludedSmuList(newParticipant.PrimaryCareProvider)"
2921
}
3022
],
31-
"Expression": "(InvalidPostingCategory || ValidPrimaryCareProvider || IsExcluded)",
23+
"Expression": "(WelshPostingCategory || ValidPrimaryCareProvider || IsExcluded)",
3224
"Actions": {
3325
"OnFailure": {
3426
"Name": "OutputExpression",
@@ -62,7 +54,7 @@
6254
"Expression": "!(reasonForRemoval AND postcode AND primaryCareProvider)"
6355
},
6456
{
65-
"RuleName": "17.AddressLinesNullAndPostcodeDoesNotMatchExisting.NBO.NonFatal",
57+
"RuleName": "71.AddressLinesNullAndPostcodeDoesNotMatchExisting.NBO.NonFatal",
6658
"LocalParams": [
6759
{
6860
"Name": "addressLines",

application/CohortManager/src/Web/app/components/search-nhs-number.tsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ export function SearchNhsNumber() {
77
const [nhsNumber, setNhsNumber] = useState("");
88

99
const isValidNhsNumber = (value: string): boolean => {
10-
const cleaned = value.replaceAll(" ", "");
10+
const cleaned = value.trim().replaceAll(" ", "");
1111
return cleaned.length === 10 && /^\d+$/.test(cleaned);
1212
};
1313

1414
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
1515
e.preventDefault();
16-
const cleanedNhsNumber = nhsNumber.replaceAll(" ", "");
16+
const cleanedNhsNumber = nhsNumber.trim().replaceAll(" ", "");
1717

1818
if (!isValidNhsNumber(nhsNumber)) {
1919
router.push(`/exceptions/noResults`);
@@ -39,12 +39,11 @@ export function SearchNhsNumber() {
3939
};
4040

4141
return (
42-
<search className="nhsuk-header__search">
43-
<form
44-
className="nhsuk-header__search-form"
45-
id="search"
46-
onSubmit={handleSubmit}
47-
>
42+
<form
43+
className="nhsuk-header__search-form"
44+
id="search"
45+
onSubmit={handleSubmit}
46+
>
4847
<label className="nhsuk-u-visually-hidden" htmlFor="search-field">
4948
Search by NHS number
5049
</label>
@@ -74,6 +73,5 @@ export function SearchNhsNumber() {
7473
</svg>
7574
</button>
7675
</form>
77-
</search>
7876
);
7977
}

application/CohortManager/src/Web/app/globals.scss

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,9 @@
165165
.nhsuk-header__content {
166166
display: flex;
167167
align-items: center;
168+
gap: clamp(8px, 2vw, 24px);
169+
flex-wrap: wrap;
168170
justify-content: space-between;
169-
flex-wrap: nowrap;
170171
}
171172

172173
.nhsuk-header__service {
@@ -176,16 +177,12 @@
176177

177178
.nhsuk-header__search {
178179
flex: 1;
179-
min-width: 250px;
180-
}
181-
182-
.nhsuk-header .nhsuk-header__search {
183-
margin: 0 100px;
180+
min-width: min(240px, 40vw);
181+
max-width: 420px;
184182
}
185183

186184
.nhsuk-header__search-form {
187185
display: flex;
188-
fill: currentColor;
189186
}
190187

191188
.nhsuk-header__account {

application/CohortManager/src/Web/app/lib/ruleMapping.test.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ describe("ruleMapping", () => {
44
describe("ruleIdMappings", () => {
55
it("should contain all expected rule IDs", () => {
66
const expectedRuleIds = [
7-
3, 8, 10, 17, 18, 21, 22, 30, 35, 39, 40, 54, 66, 69, 71,
7+
3, 8, 17, 18, 30, 35, 39, 40, 54, 66, 71
88
];
99
const actualRuleIds = Object.keys(ruleIdMappings).map(Number);
1010

@@ -153,15 +153,5 @@ describe("ruleMapping", () => {
153153
expect(mapping.ruleDescription.trim()).not.toBe("");
154154
});
155155
});
156-
157-
it("should handle rules with empty moreDetails", () => {
158-
// Rule 21 has empty moreDetails in the mapping
159-
const result = getRuleMapping(21);
160-
expect(result.moreDetails).toBe("");
161-
expect(result.ruleDescription).toBe(
162-
"The 'Superseded by NHS number' field has been populated with an NHS number by NBO."
163-
);
164-
expect(result.reportingId).toBe("CMR33");
165-
});
166156
});
167157
});

application/CohortManager/src/Web/app/lib/ruleMapping.ts

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,6 @@ export const ruleIdMappings: Record<number, RuleMapping> = {
1515
reportingId: "CMR4",
1616
portalFormTitle: "Raise with Cohorting as a Service (CaaS)",
1717
},
18-
10: {
19-
ruleDescription:
20-
"Update received for NHS number with reason for removal of ‘DEA’.",
21-
moreDetails: "An update has been received for a record marked as deceased.",
22-
reportingId: "CMR36",
23-
},
2418
17: {
2519
ruleDescription:
2620
"Date of birth is either missing, in the wrong format, or is in the future.",
@@ -35,20 +29,6 @@ export const ruleIdMappings: Record<number, RuleMapping> = {
3529
"Enter the date of death in the correct format. The date cannot be in the future.",
3630
reportingId: "CMR22",
3731
},
38-
21: {
39-
ruleDescription:
40-
"The 'Superseded by NHS number' field has been populated with an NHS number by NBO.",
41-
moreDetails: "",
42-
reportingId: "CMR33",
43-
},
44-
22: {
45-
ruleDescription:
46-
"Amendment received for an NHS number that is not in this cohort.",
47-
moreDetails:
48-
"Raise with Cohorting as a Service (CaaS). An amendment cannot be applied as the record has not yet been added to the cohort. There may have been a delay in adding the new record to Cohort Manager. ",
49-
reportingId: "CMR39",
50-
portalFormTitle: "Raise with Cohorting as a Service (CaaS)",
51-
},
5232
30: {
5333
ruleDescription: "Postcode is in the wrong format.",
5434
moreDetails: "Enter a valid UK postcode.",
@@ -104,12 +84,6 @@ export const ruleIdMappings: Record<number, RuleMapping> = {
10484
reportingId: "CMR20",
10585
portalFormTitle: "Confused NHS numbers",
10686
},
107-
69: {
108-
ruleDescription: "NHS number’s invalid flag is set to true.",
109-
moreDetails:
110-
"An update has been received for the record with the NHS Number now flagged as invalid.",
111-
reportingId: "CMR29",
112-
},
11387
71: {
11488
ruleDescription: "Address is blank (postcode may be blank too).",
11589
moreDetails: "Enter the patient's full address and postcode.",

infrastructure/tf-core/environments/development.tfvars

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ features = {
1111
private_service_connection_is_manual = false
1212
public_network_access_enabled = false
1313
frontdoor_endpoint_enabled = true
14-
alerts_enabled = true
14+
alerts_enabled = false
1515
}
1616

1717
# these will be merged with compliance tags in locals.tf

infrastructure/tf-core/environments/sandbox.tfvars

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ features = {
1010
private_service_connection_is_manual = false
1111
public_network_access_enabled = false
1212
frontdoor_endpoint_enabled = false
13-
alerts_enabled = true
13+
alerts_enabled = false
1414
}
1515

1616
# these will be merged with compliance tags in locals.tf

tests/UnitTests/ScreeningValidationServiceTests/LookupValidation/LookupValidationTests.cs

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ public class LookupValidationTests
2828
private readonly Mock<ILogger<LookupValidation>> _mockLogger = new();
2929
private readonly Mock<IDataLookupFacadeBreastScreening> _lookupValidation = new();
3030

31+
private readonly List<string> welshPostingCategories = new List<string>{"CLD","CYM","DYF","GWE","SGA","WGA"};
32+
3133
[TestInitialize]
3234
public void IntialiseTests()
3335
{
@@ -189,29 +191,64 @@ public async Task Run_CurrentPosting_ReturnNoContent(string currentPosting)
189191
}
190192

191193
[TestMethod]
192-
[DataRow("InvalidCurrentPosting", "InvalidPCP")]
193-
[DataRow("ValidCurrentPosting", "ValidPCP")]
194-
[DataRow("InvalidCurrentPosting", "ValidPCP")]
195-
[DataRow("ValidCurrentPosting", null)]
196-
[DataRow("InvalidCurrentPosting", null)]
197-
public async Task Run_CurrentPostingAndPrimaryProvider_ReturnNoContent(string currentPosting, string primaryCareProvider)
194+
[DataRow("BAA", "InvalidPCP", true)]
195+
[DataRow(null, "InvalidPCP", true)]
196+
[DataRow("BAA", "ValidPCP", true)]
197+
[DataRow(null, "ValidPCP", true)]
198+
[DataRow("BAA", "ValidPCP", false)]
199+
[DataRow(null, "ValidPCP", false)]
200+
[DataRow("BAA", null, false)]
201+
[DataRow("BAA", null, true)]
202+
[DataRow(null, null, false)]
203+
[DataRow("CYM", "InvalidPCP", false)]
204+
[DataRow("CYM", "ValidPCP", false)]
205+
[DataRow("CYM", "InvalidPCP", true)]
206+
[DataRow("CYM", "ValidPCP", true)]
207+
public async Task Run_CurrentPostingAndPrimaryProvider_ReturnNoContent(string currentPosting, string primaryCareProvider, bool PCPIsExcluded)
198208
{
199209
// Arrange
200210
_requestBody.NewParticipant.CurrentPosting = currentPosting;
201211
_requestBody.NewParticipant.PrimaryCareProvider = primaryCareProvider;
212+
202213
var json = JsonSerializer.Serialize(_requestBody);
203214
SetUpRequestBody(json);
204215

205-
_lookupValidation.Setup(x => x.ValidatePostingCategories(It.IsAny<string>())).Returns(currentPosting == "ValidCurrentPosting");
206216
_lookupValidation.Setup(x => x.CheckIfPrimaryCareProviderExists(It.IsAny<string>())).Returns(primaryCareProvider == "ValidPCP");
217+
_lookupValidation.Setup(x => x.CheckIfPrimaryCareProviderInExcludedSmuList(It.IsAny<string>())).Returns(PCPIsExcluded);
218+
_lookupValidation.Setup(x => x.RetrievePostingCategory(It.IsIn<string>(welshPostingCategories))).Returns("WALES");
219+
_lookupValidation.Setup(x => x.RetrievePostingCategory(It.IsNotIn<string>(welshPostingCategories))).Returns("ENGLAND");
207220

208221
// Act
209222
var response = await _sut.RunAsync(_request.Object);
210223
string body = await AssertionHelper.ReadResponseBodyAsync(response);
211224

212225
// Assert
213-
Assert.IsFalse(body.Contains("45.GPPracticeCodeDoesNotExist.BSSelect.NonFatal"));
226+
Assert.IsFalse(body.Contains("45.GPPracticeCodeDoesNotExist.BSSelect.NonFatal")); // Rule Not Triggered
214227
}
228+
[TestMethod]
229+
[DataRow("BAA", "InvalidPCP",false)]
230+
[DataRow("HJ", "InvalidPCP",false)]
231+
[DataRow("DMS", "InvalidPCP",false)]
232+
public async Task Run_CurrentPostingAndPrimaryProvider_ReturnsException(string currentPosting, string primaryCareProvider, bool PCPIsExcluded)
233+
{
234+
// Arrange
235+
_requestBody.NewParticipant.CurrentPosting = currentPosting;
236+
_requestBody.NewParticipant.PrimaryCareProvider = primaryCareProvider;
237+
var json = JsonSerializer.Serialize(_requestBody);
238+
SetUpRequestBody(json);
239+
240+
_lookupValidation.Setup(x => x.CheckIfPrimaryCareProviderExists(It.IsAny<string>())).Returns(primaryCareProvider == "ValidPCP");
241+
_lookupValidation.Setup(x => x.CheckIfPrimaryCareProviderInExcludedSmuList(It.IsAny<string>())).Returns(PCPIsExcluded);
242+
_lookupValidation.Setup(x => x.RetrievePostingCategory(It.IsIn<string>(welshPostingCategories))).Returns("WALES");
243+
_lookupValidation.Setup(x => x.RetrievePostingCategory(It.IsNotIn<string>(welshPostingCategories))).Returns("ENGLAND");
244+
// Act
245+
var response = await _sut.RunAsync(_request.Object);
246+
string body = await AssertionHelper.ReadResponseBodyAsync(response);
247+
248+
// Assert
249+
Assert.IsTrue(body.Contains("45.GPPracticeCodeDoesNotExist.NBO.NonFatal"));
250+
}
251+
215252

216253
#region Validate BSO Code (Rule 54)
217254
[TestMethod]
@@ -267,35 +304,6 @@ public async Task Run_AmendedParticipantHasValidBSO_ReturnNoContent(string reaso
267304
#endregion
268305

269306
[TestMethod]
270-
[DataRow("DMS", "Z00000")]
271-
[DataRow("ENG", "Z00000")]
272-
[DataRow("IM", "Z00000")]
273-
274-
public async Task Run_ParticipantLocationRemainingOutsideOfCohortAndNotInExcludedSMU_ReturnValidationException(string newCurrentPosting, string newPrimaryCareProvider)
275-
{
276-
// Arrange
277-
_requestBody.NewParticipant.RecordType = Actions.New;
278-
_requestBody.NewParticipant.CurrentPosting = newCurrentPosting;
279-
_requestBody.NewParticipant.PrimaryCareProvider = newPrimaryCareProvider;
280-
281-
var json = JsonSerializer.Serialize(_requestBody);
282-
SetUpRequestBody(json);
283-
_lookupValidation.Setup(x => x.RetrievePostingCategory(newCurrentPosting)).Returns(newCurrentPosting);
284-
_lookupValidation.Setup(x => x.CheckIfCurrentPostingExists(newCurrentPosting)).Returns(true);
285-
_lookupValidation.Setup(x => x.CheckIfPrimaryCareProviderInExcludedSmuList(newPrimaryCareProvider)).Returns(false);
286-
_lookupValidation.Setup(x => x.CheckIfPrimaryCareProviderExists(newPrimaryCareProvider)).Returns(false);
287-
288-
// Act
289-
var response = await _sut.RunAsync(_request.Object);
290-
string body = await AssertionHelper.ReadResponseBodyAsync(response);
291-
292-
// Assert
293-
StringAssert.Contains(body, "45.GPPracticeCodeDoesNotExist.BSSelect.NonFatal");
294-
}
295-
296-
297-
[TestMethod]
298-
299307
[DataRow(null, null, null, null, null, null, "Existing Address 1", "Existing Address 2", "Existing Address 3", "Existing Address 4", "Existing Address 5", "RG2 5TX")] // All New Address Fields null, New Postcode null, Existing Address fields full.
300308
[DataRow("", "", "", "", "", "", "Existing Address 1", "Existing Address 2", "Existing Address 3", "Existing Address 4", "Existing Address 5", "RG2 5TX")] // All New Address Fields empty, New Postcode empty, Existing Address fields full.
301309
[DataRow(null, null, null, null, null, "RG2 5TX", "Existing Address 1", "Existing Address 2", "Existing Address 3", "Existing Address 4", "Existing Address 5", "ZZ99 6TF")] // All New Address Fields null, All existing address field full, Postcode does not match.
@@ -327,7 +335,7 @@ public async Task Run_AddressLinesNullAndPostcodeDoesNotMatchExisting_ReturnVali
327335
string body = await AssertionHelper.ReadResponseBodyAsync(response);
328336

329337
// Assert
330-
StringAssert.Contains(body, "17.AddressLinesNullAndPostcodeDoesNotMatchExisting.NBO.NonFatal");
338+
StringAssert.Contains(body, "71.AddressLinesNullAndPostcodeDoesNotMatchExisting.NBO.NonFatal");
331339
}
332340

333341
[DataRow(null, null, null, null, null, "RG2 5TX", "Existing Address 1", "Existing Address 2", "Existing Address 3", "Existing Address 4", "Existing Address 5", "RG2 5TX")] // All New Address Fields Blank, Postcode exists, Existing Address fields full

tests/playwright-tests/src/tests/e2e/epic4d-validation-tests/epic4d-6045-validation-testsuite-migrated.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@
2424
// This equates to "@epic4d-" tags, configured in the package.json at the playwright-tests root location.
2525

2626

27-
export const runnerBasedEpic4dTestScenariosAdd = "@DTOSS-9496-01|@DTOSS-9498-01|@DTOSS-A456-01|@DTOSS-A457-01|@DTOSS-A459-01";
27+
export const runnerBasedEpic4dTestScenariosAdd = "@DTOSS-11715-01|@DTOSS-9496-01|@DTOSS-9498-01|@DTOSS-A456-01|@DTOSS-A457-01|@DTOSS-A459-01";
2828
export const runnerBasedEpic4dTestScenariosAmend = "@DTOSS-9497-01|@DTOSS-9499-01|@DTOSS-A451-01|@DTOSS-A452-01|@DTOSS-A453-01|@DTOSS-A454-01|@DTOSS-A455-01|@DTOSS-A458-01";

0 commit comments

Comments
 (0)