UNPKG

@natlibfi/melinda-record-match-validator

Version:

Validates if two records matched by melinda-record-matching can be merged and sets merge priority

128 lines (127 loc) 6.74 kB
import createDebugLogger from "debug"; import { comparisonTasksTable } from "./comparisonTasks.js"; import { check984 } from "./compareFunctions/compareField984.js"; import { MarcRecord } from "@natlibfi/marc-record"; import { nvdebug } from "./utils.js"; const debug = createDebugLogger("@natlibfi/melinda-record-match-validator:index"); const debugDev = debug.extend("dev"); function runComparisonTasks({ nth, record1, record2, checkPreference = true, record1External = {}, record2External = {}, returnAll = false, comparisonTasks = comparisonTasksTable.recordImport }) { const currResult = comparisonTasks[nth].function({ record1, record2, checkPreference, record1External, record2External }); debugDev(`Running task ${nth} (${comparisonTasks[nth].name}) - returnAll: ${returnAll}`); if (nth === comparisonTasks.length - 1 || !returnAll && currResult === false) { return [currResult]; } return [currResult].concat(runComparisonTasks({ nth: nth + 1, record1, record2, checkPreference, record1External, record2External, returnAll, comparisonTasks })); } function makeComparisons({ record1, record2, checkPreference = true, record1External = {}, record2External = {}, returnAll = false, comparisonTasks = comparisonTasksTable.recordImport }) { debugDev(`returnAll: ${returnAll}`); if (comparisonTasks.length === 0) { const resultForZeroTasks = { result: true, reason: `No rules defined` }; if (returnAll) { return [resultForZeroTasks]; } return resultForZeroTasks; } const results = runComparisonTasks({ nth: 0, record1, record2, checkPreference, record1External, record2External, returnAll, comparisonTasks }); return returnAll ? returnAllResults() : returnDecisionPointResult(); function returnAllResults() { const allResults = results.map((result, i) => ({ result, reason: comparisonTasks[i].name, preference: comparisonTasks[i].preference, validation: comparisonTasks[i].validation, level: comparisonTasks[i].manual === void 0 ? "error" : comparisonTasks[i].manual, validation_message_fi: comparisonTasks[i].validation_message_fi, preference_message_fi: comparisonTasks[i].preference_message_fi })); if (checkPreference) { const field984OverrideResult = getField984OverrideResult(); if (field984OverrideResult) { return allResults.concatenate(field984OverrideResult); } return allResults; } return allResults; } function returnDecisionPointResult() { if (results.length < comparisonTasks.length || results[results.length - 1] === false) { nvdebug(`makeComparisons() failed. Reason: ${comparisonTasks[results.length - 1].description}. (TEST: ${results.length}/${comparisonTasks.length})`, debugDev); return { result: false, reason: `${comparisonTasks[results.length - 1].description} failed` }; } if (!checkPreference) { return { result: true, reason: "all tests passed" }; } const field984OverrideResult = getField984OverrideResult(); if (field984OverrideResult) { return field984OverrideResult; } const decisionPoint = results.findIndex((val) => val !== true && val !== false); if (decisionPoint === -1) { return { result: true, reason: "both records passed all tests, but no winner was found" }; } return { result: results[decisionPoint], reason: `${results[decisionPoint]} won ${comparisonTasks[decisionPoint].description}` }; } function getField984OverrideResult() { const field984Override = check984({ record1, record2 }); if (field984Override === "A" || field984Override === "B") { return { result: field984Override, reason: "Field 984 override applied (MRA-744)" }; } return; } } export function matchValidationForMergeUI({ record1Object, record2Object, checkPreference = true, record1External = { "recordSource": "databaseRecord" }, record2External = { "recordSource": "databaseRecord" }, manual = true, comparisonTasks = comparisonTasksTable.humanMerge }) { debugDev(`Manual ${manual} (for Merge UI) - we have ${comparisonTasks.length} comparison tasks`); debugDev(`FOOBAR`); const record1 = new MarcRecord(record1Object, { subfieldValues: false }); const record2 = new MarcRecord(record2Object, { subfieldValues: false }); const result = makeComparisons({ record1, record2, checkPreference, record1External, record2External, returnAll: true, comparisonTasks }); debugDev(JSON.stringify(result)); const resultForMergeUI = filterResultsForMergeUI(result); return resultForMergeUI; function filterResultsForMergeUI(allResults) { const failure = allResults.filter((r) => r.result !== true).filter((r) => r.result !== "B"); debugDev(`MatchValidator failed: ${JSON.stringify(failure, null, 4)}`); const messages = failure.map(({ result: result2, level, validation_message_fi, preference_message_fi }) => ({ result: result2 === "A" ? "warning" : level, // all preference-results are warning in UI type: result2 === "A" ? "preference" : "validation", // message: result2 === "A" ? preference_message_fi : validation_message_fi })); debugDev(`MatchValidator results for MergeUI: ${JSON.stringify(messages, null, 4)}`); const sortedMessages = messages.sort(sortMessages); debugDev(`Sorted matchValidator results for MergeUI: ${JSON.stringify(sortedMessages, null, 4)}`); return sortedMessages; function sortMessages(a, b) { if (a.result !== b.result) { if (a.result === "error") { return -1; } if (b.result === "error") { return 1; } } if (a.type !== b.type) { if (a.type === "validation") { return -1; } if (b.type === "validation") { return 1; } } return 0; } } } export default ({ record1Object, record2Object, checkPreference = true, record1External = {}, record2External = {}, manual = false, comparisonTasks = comparisonTasksTable.recordImport }) => { debugDev(`Default (manual: ${manual}) (for record import) we have ${comparisonTasks.length} comparison tasks`); const record1 = new MarcRecord(record1Object, { subfieldValues: false }); const record2 = new MarcRecord(record2Object, { subfieldValues: false }); const result = makeComparisons({ record1, record2, checkPreference, record1External, record2External, comparisonTasks }); debug(`Comparison result: ${result.result}, reason: ${result.reason}`); if (result.result === false) { return { action: false, preference: false, message: result.reason }; } return { action: "merge", preference: { "name": result.reason, "value": result.result } }; }; //# sourceMappingURL=index.js.map