Merged PR 2653: fix: preserve LPA questionnaire PDF metadata during submission
fix: preserve LPA questionnaire PDF metadata during submission Related work items: #25435
This commit is contained in:
@@ -297,7 +297,7 @@ let MakeRepresentation = (props) => {
|
||||
});
|
||||
|
||||
let resultsObj = findResultsObjForCurrentReference({
|
||||
"currentReference": currentView.caseReference.currentReference,
|
||||
"currentReference": currentView.caseReference.ticketnumber,
|
||||
"caseResultsSource": caseResultsSource
|
||||
});
|
||||
|
||||
|
||||
@@ -33,6 +33,14 @@ export const buildSubmitEnrichedValues = ({
|
||||
representationCapacity,
|
||||
locale
|
||||
}) => {
|
||||
const isPopulatedText = (value) =>
|
||||
value !== null &&
|
||||
value !== undefined &&
|
||||
(typeof value !== "string" || value.trim() !== "");
|
||||
|
||||
const preserveExistingWhenMissing = (canonicalValue, existingValue) =>
|
||||
isPopulatedText(canonicalValue) ? canonicalValue : existingValue;
|
||||
|
||||
const buildSiteAddress = () => {
|
||||
const {
|
||||
pinswg_siteaddressline1,
|
||||
@@ -47,10 +55,12 @@ export const buildSubmitEnrichedValues = ({
|
||||
pinswg_siteaddresstown,
|
||||
pinswg_siteaddresspostcode
|
||||
]
|
||||
.filter(Boolean)
|
||||
.filter(isPopulatedText)
|
||||
.join(" ");
|
||||
};
|
||||
|
||||
const siteAddress = buildSiteAddress();
|
||||
|
||||
return {
|
||||
...formValues,
|
||||
containerID: accountDetails.containerID,
|
||||
@@ -58,7 +68,10 @@ export const buildSubmitEnrichedValues = ({
|
||||
incidentID:
|
||||
caseReferenceObj.incidentid ||
|
||||
caseReferenceObj.repDetails.incidentid,
|
||||
caseRef: caseReferenceObj.ticketnumber,
|
||||
caseRef: preserveExistingWhenMissing(
|
||||
caseReferenceObj.ticketnumber,
|
||||
formValues.caseRef
|
||||
),
|
||||
casereference: caseReferenceObj.currentReference,
|
||||
pinswg_questionnaireduedate: detailsObj.pinswg_questionnaireduedate,
|
||||
pinswg_endofrepresentationperiod:
|
||||
@@ -72,12 +85,18 @@ export const buildSubmitEnrichedValues = ({
|
||||
firstname: accountDetails.firstname,
|
||||
lastname: accountDetails.lastname,
|
||||
emailAddress: accountDetails.emailaddress1,
|
||||
siteAddress: buildSiteAddress(),
|
||||
siteAddress: preserveExistingWhenMissing(
|
||||
siteAddress,
|
||||
formValues.siteAddress
|
||||
),
|
||||
pinswg_siteaddressline1: detailsObj.pinswg_siteaddressline1,
|
||||
pinswg_siteaddressline2: detailsObj.pinswg_siteaddressline2,
|
||||
pinswg_siteaddresstown: detailsObj.pinswg_siteaddresstown,
|
||||
pinswg_siteaddresspostcode: detailsObj.pinswg_siteaddresspostcode,
|
||||
pinswg_lpareference: resultsObj?.pinswg_lpareference,
|
||||
pinswg_lpareference: preserveExistingWhenMissing(
|
||||
resultsObj?.pinswg_lpareference,
|
||||
formValues.pinswg_lpareference
|
||||
),
|
||||
_pinswg_appellant_value: detailsObj._pinswg_appellant_value,
|
||||
"_pinswg_appellant_value@OData.Community.Display.V1.FormattedValue":
|
||||
detailsObj[
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
const assert = require("assert");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const vm = require("vm");
|
||||
|
||||
const rootDir = path.resolve(__dirname, "..", "..");
|
||||
const tests = [];
|
||||
const test = (name, fn) => tests.push({ name, fn });
|
||||
|
||||
const loadModule = (relativePath, exportNames, contextOverrides = {}) => {
|
||||
const filePath = path.join(rootDir, ...relativePath);
|
||||
let source = fs.readFileSync(filePath, "utf8");
|
||||
|
||||
source = source.replace(/import[\s\S]*?from\s+"[^"]+";\n?/g, "");
|
||||
source = source.replace(/export\s+const\s+/g, "const ");
|
||||
source += `\nmodule.exports = { ${exportNames.join(", ")} };\n`;
|
||||
|
||||
const context = {
|
||||
module: { exports: {} },
|
||||
exports: {},
|
||||
...contextOverrides
|
||||
};
|
||||
|
||||
vm.runInNewContext(source, context, { filename: filePath });
|
||||
return context.module.exports;
|
||||
};
|
||||
|
||||
const { buildSubmitEnrichedValues } = loadModule(
|
||||
[
|
||||
"components",
|
||||
"case",
|
||||
"representation",
|
||||
"utils",
|
||||
"finalisationBoundary.js"
|
||||
],
|
||||
["buildSubmitEnrichedValues"]
|
||||
);
|
||||
|
||||
const findTicketnumberMatch = ({ path: jsonPath, json }) => {
|
||||
const ticketnumber = jsonPath.match(/ticketnumber=="([^"]+)"/)?.[1];
|
||||
const queue = [json];
|
||||
|
||||
while (queue.length > 0) {
|
||||
const value = queue.shift();
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
queue.push(...value);
|
||||
} else if (value && typeof value === "object") {
|
||||
if (value.ticketnumber === ticketnumber) {
|
||||
return [value];
|
||||
}
|
||||
queue.push(...Object.values(value));
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
const { findResultsObjForCurrentReference } = loadModule(
|
||||
[
|
||||
"components",
|
||||
"case",
|
||||
"representation",
|
||||
"utils",
|
||||
"dataResolution.js"
|
||||
],
|
||||
["findResultsObjForCurrentReference"],
|
||||
{ jsonpath: findTicketnumberMatch }
|
||||
);
|
||||
|
||||
const buildInput = (overrides = {}) => ({
|
||||
formValues: {
|
||||
caseRef: "FORM-CASE",
|
||||
pinswg_lpareference: "FORM-LPA",
|
||||
siteAddress: "Form address",
|
||||
questionnaireAnswer: "Preserved",
|
||||
...overrides.formValues
|
||||
},
|
||||
accountDetails: {
|
||||
containerID: "container-1",
|
||||
firstname: "Test",
|
||||
lastname: "User",
|
||||
emailaddress1: "test@example.com"
|
||||
},
|
||||
appealType: "S78",
|
||||
caseReferenceObj: {
|
||||
ticketnumber: "CANONICAL-CASE",
|
||||
currentReference: "Display reference",
|
||||
incidentid: "incident-1",
|
||||
repDetails: {},
|
||||
...overrides.caseReferenceObj
|
||||
},
|
||||
detailsObj: {
|
||||
pinswg_siteaddressline1: "1 Canonical Street",
|
||||
pinswg_siteaddressline2: "Canonical Area",
|
||||
pinswg_siteaddresstown: "Canonical Town",
|
||||
pinswg_siteaddresspostcode: "CF10 1AA",
|
||||
...overrides.detailsObj
|
||||
},
|
||||
resultsObj: {
|
||||
pinswg_lpareference: "CANONICAL-LPA",
|
||||
...overrides.resultsObj
|
||||
},
|
||||
representationCapacity: "LPA",
|
||||
locale: "en"
|
||||
});
|
||||
|
||||
test("populated canonical metadata overrides conflicting form metadata", () => {
|
||||
const result = buildSubmitEnrichedValues(buildInput());
|
||||
|
||||
assert.strictEqual(result.caseRef, "CANONICAL-CASE");
|
||||
assert.strictEqual(result.pinswg_lpareference, "CANONICAL-LPA");
|
||||
assert.strictEqual(
|
||||
result.siteAddress,
|
||||
"1 Canonical Street Canonical Area Canonical Town CF10 1AA"
|
||||
);
|
||||
assert.strictEqual(result.questionnaireAnswer, "Preserved");
|
||||
});
|
||||
|
||||
test("missing canonical case reference preserves the submitted case reference", () => {
|
||||
const input = buildInput({ caseReferenceObj: { ticketnumber: undefined } });
|
||||
const result = buildSubmitEnrichedValues(input);
|
||||
|
||||
assert.strictEqual(result.caseRef, "FORM-CASE");
|
||||
assert.strictEqual(input.formValues.caseRef, "FORM-CASE");
|
||||
});
|
||||
|
||||
test("missing result metadata preserves the submitted LPA reference", () => {
|
||||
const input = buildInput();
|
||||
input.resultsObj = undefined;
|
||||
|
||||
const result = buildSubmitEnrichedValues(input);
|
||||
|
||||
assert.strictEqual(result.pinswg_lpareference, "FORM-LPA");
|
||||
});
|
||||
|
||||
test("empty canonical address preserves the submitted site address", () => {
|
||||
const result = buildSubmitEnrichedValues(
|
||||
buildInput({
|
||||
detailsObj: {
|
||||
pinswg_siteaddressline1: "",
|
||||
pinswg_siteaddressline2: null,
|
||||
pinswg_siteaddresstown: undefined,
|
||||
pinswg_siteaddresspostcode: ""
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
assert.strictEqual(result.siteAddress, "Form address");
|
||||
});
|
||||
|
||||
test("whitespace-only canonical metadata cannot erase submitted metadata", () => {
|
||||
const result = buildSubmitEnrichedValues(
|
||||
buildInput({
|
||||
caseReferenceObj: { ticketnumber: " " },
|
||||
resultsObj: { pinswg_lpareference: "\t" },
|
||||
detailsObj: {
|
||||
pinswg_siteaddressline1: " ",
|
||||
pinswg_siteaddressline2: "\t",
|
||||
pinswg_siteaddresstown: " ",
|
||||
pinswg_siteaddresspostcode: "\n"
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
assert.strictEqual(result.caseRef, "FORM-CASE");
|
||||
assert.strictEqual(result.pinswg_lpareference, "FORM-LPA");
|
||||
assert.strictEqual(result.siteAddress, "Form address");
|
||||
});
|
||||
|
||||
test("case-results lookup resolves the record by ticket number", () => {
|
||||
const selected = findResultsObjForCurrentReference({
|
||||
currentReference: "CAS-EXAMPLE-001",
|
||||
caseResultsSource: {
|
||||
value: [
|
||||
{
|
||||
ticketnumber: "CAS-OTHER-001",
|
||||
title: "CAS-EXAMPLE-001"
|
||||
},
|
||||
{
|
||||
ticketnumber: "CAS-EXAMPLE-001",
|
||||
title: "Different Display Reference"
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
assert.strictEqual(selected.ticketnumber, "CAS-EXAMPLE-001");
|
||||
assert.strictEqual(selected.title, "Different Display Reference");
|
||||
});
|
||||
|
||||
test("parent lookup supplies the case ticket number", () => {
|
||||
const source = fs.readFileSync(
|
||||
path.join(rootDir, "components", "case", "representation", "index.js"),
|
||||
"utf8"
|
||||
);
|
||||
|
||||
assert.match(
|
||||
source,
|
||||
/findResultsObjForCurrentReference\(\{\s*"currentReference": currentView\.caseReference\.ticketnumber,\s*"caseResultsSource": caseResultsSource\s*\}\)/
|
||||
);
|
||||
});
|
||||
|
||||
test("existing and edit representations remain outside submit enrichment", () => {
|
||||
const source = fs.readFileSync(
|
||||
path.join(rootDir, "components", "case", "representation", "index.js"),
|
||||
"utf8"
|
||||
);
|
||||
|
||||
assert.match(
|
||||
source,
|
||||
/formObj\?\.representationForm\?\.values\s*&&\s*!router\.query\.hasOwnProperty\("state"\)/
|
||||
);
|
||||
});
|
||||
|
||||
const run = async () => {
|
||||
let passed = 0;
|
||||
|
||||
for (const currentTest of tests) {
|
||||
await currentTest.fn();
|
||||
passed += 1;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Phase 22 representation PDF metadata tests passed (${passed}/${tests.length}).`
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = run;
|
||||
|
||||
if (require.main === module) {
|
||||
run().catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user