@openhealth/oht-custom-parser-lib 0.3.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -1
- package/dist/index.js +17 -2
- package/dist/index.js.map +1 -1
- package/dist/service/auxiliaryFunctions.service.d.ts +2 -0
- package/dist/service/auxiliaryFunctions.service.js +4 -3
- package/dist/service/auxiliaryFunctions.service.js.map +1 -1
- package/dist/service/fileUploadErrorHandler.service.d.ts +26 -0
- package/dist/service/fileUploadErrorHandler.service.js +264 -0
- package/dist/service/fileUploadErrorHandler.service.js.map +1 -0
- package/dist/service/ohtMeasurementsExtractor.service.js +23 -25
- package/dist/service/ohtMeasurementsExtractor.service.js.map +1 -1
- package/dist/service/ohtReportMeasurementsExtractor.service.d.ts +1 -0
- package/dist/service/ohtReportMeasurementsExtractor.service.js +34 -48
- package/dist/service/ohtReportMeasurementsExtractor.service.js.map +1 -1
- package/dist/service/processingLogger.service.d.ts +122 -0
- package/dist/service/processingLogger.service.js +331 -0
- package/dist/service/processingLogger.service.js.map +1 -0
- package/dist/service/reportCreator.service.js +48 -56
- package/dist/service/reportCreator.service.js.map +1 -1
- package/dist/service/slackMessages.service.js +4 -5
- package/dist/service/slackMessages.service.js.map +1 -1
- package/dist/service/transformationRules.service.js +3 -10
- package/dist/service/transformationRules.service.js.map +1 -1
- package/dist/types/error.types.d.ts +82 -0
- package/dist/types/error.types.js +195 -0
- package/dist/types/error.types.js.map +1 -1
- package/dist/types/oht.types.d.ts +5 -1
- package/dist/types/oht.types.js +4 -0
- package/dist/types/oht.types.js.map +1 -1
- package/dist/util-ts/apiUtils.js +2 -3
- package/dist/util-ts/apiUtils.js.map +1 -1
- package/dist/util-ts/dataUtils.js +24 -16
- package/dist/util-ts/dataUtils.js.map +1 -1
- package/dist/util-ts/extractionUtils.js +4 -8
- package/dist/util-ts/extractionUtils.js.map +1 -1
- package/package.json +34 -34
- package/readme.md +99 -99
- package/dist/service/ohtAgnosticMeasurementsExtractor.service.d.ts +0 -59
- package/dist/service/ohtAgnosticMeasurementsExtractor.service.js +0 -603
- package/dist/service/ohtAgnosticMeasurementsExtractor.service.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -7,8 +7,10 @@ export { aggregateMessages, aggregateBiMessages, publishToTopic, generateBIMessa
|
|
|
7
7
|
export { applyRules as applyTransformationRules, validateJsonataExpression as validateTransformationRuleExpression, } from './service/transformationRules.service';
|
|
8
8
|
export { LabToOhtContract, LabToOhtMapper, UnknownMeasurementExtraction, ReferenceAsAnnotation, UnitExtraction, RangeExtraction, RangeExtractionResponse, ValueExtraction, unitSynonyms, ValueExtractionResponse, SynonymUnit, UnknownUnits, } from './types/custom-parser.types';
|
|
9
9
|
export { AcfBiomarkerRangeAnnotationCheck, AcfBiomarkerGenericDisclaimerLogic, ManualCheck, BiomarkerCompatibility, ReferenceRangeType, AcfReferenceRange, VisualRange, NameAlias, AlternativeUnit, BiomarkerAcf, Biomarker, PipelineStep, DigitizationStatus, MeasurementValueComparator, BiomarkerValueType, DataImportFileUploadStatus, Sex, Digitization, PatientInfo, UnknownMeasurement, UnmappedLabKey, Measurement, DataImportFileUpload, MessagePayload, SignedUpload, ReportStyleConfig, LanguageCode, BiomarkerCustomisation, PartnerCustomPanel, ReportDisplaySettings, ReportCustomisation, OHTPartner, UploadType, RejectReason, AnnotationLabKey, ExtractionPath, AnnotationConfig, } from './types/oht.types';
|
|
10
|
-
export { ErrorMessage } from './types/error.types';
|
|
10
|
+
export { ErrorMessage, ErrorCode, ERROR_CATALOG, ERROR_MESSAGES, getErrorMessage, getRejectReason, } from './types/error.types';
|
|
11
|
+
export { handleError, ValidationError, shouldSendSlackNotification, extractFormattedRejectReason, mapErrorToRejectReason, } from './service/fileUploadErrorHandler.service';
|
|
11
12
|
export type { TransformationRule, TransformationContext, ApplyRulesResult as TransformationApplyRulesResult, ApplyRulesOptions as TransformationApplyRulesOptions, ValidationResult as TransformationValidationResult, } from './types/transformationRules.types';
|
|
13
|
+
export { processingLogger, ProcessingContext, StageDuration, } from './service/processingLogger.service';
|
|
12
14
|
export { makeApiCallWithRetry, parseErrorObj } from './util-ts/apiUtils';
|
|
13
15
|
export { extractValue, isBiomarkerValueNumerical, isBiomarkerExternalNoVisualRange, processAppendedMappings, fetchSynonymUnits, resolveUnitFromSynonyms, extractFromPath, applyFormat } from './util-ts/dataUtils';
|
|
14
16
|
export { readFileFromBucket, uploadFileBufferToGCS } from './util-ts/googleStorageUtils';
|
package/dist/index.js
CHANGED
|
@@ -3,8 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
exports.parseRange = exports.getMappedBiomarkersLatest = exports.getMappedBiomarkers = exports.getLowerThanPatterns = exports.getGreaterThanPatterns = exports.pinoLogger = exports.uploadFileBufferToGCS = void 0;
|
|
6
|
+
exports.processingLogger = exports.mapErrorToRejectReason = exports.extractFormattedRejectReason = exports.shouldSendSlackNotification = exports.ValidationError = exports.handleError = exports.getRejectReason = exports.getErrorMessage = exports.ERROR_MESSAGES = exports.ERROR_CATALOG = exports.ErrorCode = exports.RejectReason = exports.UploadType = exports.Sex = exports.DataImportFileUploadStatus = exports.BiomarkerValueType = exports.MeasurementValueComparator = exports.DigitizationStatus = exports.PipelineStep = exports.ReferenceRangeType = exports.BiomarkerCompatibility = exports.ManualCheck = exports.AcfBiomarkerGenericDisclaimerLogic = exports.AcfBiomarkerRangeAnnotationCheck = exports.unitSynonyms = exports.validateTransformationRuleExpression = exports.applyTransformationRules = exports.generateBIMessages = exports.publishToTopic = exports.aggregateBiMessages = exports.aggregateMessages = exports.sendMessageToSlack = exports.getSlackFileIssueNotificationMessage = exports.extractValueFromGreaterLowerThan = exports.extractUnit = exports.getRangeFromPositionAndRegex = exports.parseExamValue = exports.extractReferenceAnnotation = exports.extractReferenceRanges = exports.checkValueForPlausibleValues = exports.ohtMeasurementsExtractor = exports.ohtReportMeasurementsExtractor = exports.postFileUploadSetStatus = exports.queryFileUploadsWithFilters = exports.handleRejection = exports.isPatientAgeValid = exports.parseGender = exports.parseExternalPatientId = exports.postReportPreviewToCore = exports.postDataImportFileUploadToCore = void 0;
|
|
7
|
+
exports.parseRange = exports.getMappedBiomarkersLatest = exports.getMappedBiomarkers = exports.getLowerThanPatterns = exports.getGreaterThanPatterns = exports.pinoLogger = exports.uploadFileBufferToGCS = exports.readFileFromBucket = exports.applyFormat = exports.extractFromPath = exports.resolveUnitFromSynonyms = exports.fetchSynonymUnits = exports.processAppendedMappings = exports.isBiomarkerExternalNoVisualRange = exports.isBiomarkerValueNumerical = exports.extractValue = exports.parseErrorObj = exports.makeApiCallWithRetry = void 0;
|
|
8
8
|
// ### SERVICES ###
|
|
9
9
|
var reportCreator_service_1 = require("./service/reportCreator.service");
|
|
10
10
|
Object.defineProperty(exports, "postDataImportFileUploadToCore", { enumerable: true, get: function () { return reportCreator_service_1.postDataImportFileUploadToCore; } });
|
|
@@ -55,6 +55,21 @@ Object.defineProperty(exports, "DataImportFileUploadStatus", { enumerable: true,
|
|
|
55
55
|
Object.defineProperty(exports, "Sex", { enumerable: true, get: function () { return oht_types_1.Sex; } });
|
|
56
56
|
Object.defineProperty(exports, "UploadType", { enumerable: true, get: function () { return oht_types_1.UploadType; } });
|
|
57
57
|
Object.defineProperty(exports, "RejectReason", { enumerable: true, get: function () { return oht_types_1.RejectReason; } });
|
|
58
|
+
var error_types_1 = require("./types/error.types");
|
|
59
|
+
Object.defineProperty(exports, "ErrorCode", { enumerable: true, get: function () { return error_types_1.ErrorCode; } });
|
|
60
|
+
Object.defineProperty(exports, "ERROR_CATALOG", { enumerable: true, get: function () { return error_types_1.ERROR_CATALOG; } });
|
|
61
|
+
Object.defineProperty(exports, "ERROR_MESSAGES", { enumerable: true, get: function () { return error_types_1.ERROR_MESSAGES; } });
|
|
62
|
+
Object.defineProperty(exports, "getErrorMessage", { enumerable: true, get: function () { return error_types_1.getErrorMessage; } });
|
|
63
|
+
Object.defineProperty(exports, "getRejectReason", { enumerable: true, get: function () { return error_types_1.getRejectReason; } });
|
|
64
|
+
var fileUploadErrorHandler_service_1 = require("./service/fileUploadErrorHandler.service");
|
|
65
|
+
Object.defineProperty(exports, "handleError", { enumerable: true, get: function () { return fileUploadErrorHandler_service_1.handleError; } });
|
|
66
|
+
Object.defineProperty(exports, "ValidationError", { enumerable: true, get: function () { return fileUploadErrorHandler_service_1.ValidationError; } });
|
|
67
|
+
Object.defineProperty(exports, "shouldSendSlackNotification", { enumerable: true, get: function () { return fileUploadErrorHandler_service_1.shouldSendSlackNotification; } });
|
|
68
|
+
Object.defineProperty(exports, "extractFormattedRejectReason", { enumerable: true, get: function () { return fileUploadErrorHandler_service_1.extractFormattedRejectReason; } });
|
|
69
|
+
Object.defineProperty(exports, "mapErrorToRejectReason", { enumerable: true, get: function () { return fileUploadErrorHandler_service_1.mapErrorToRejectReason; } });
|
|
70
|
+
// ### PROCESSING LOGGER ###
|
|
71
|
+
var processingLogger_service_1 = require("./service/processingLogger.service");
|
|
72
|
+
Object.defineProperty(exports, "processingLogger", { enumerable: true, get: function () { return processingLogger_service_1.processingLogger; } });
|
|
58
73
|
// ### UTIL-TS ###
|
|
59
74
|
var apiUtils_1 = require("./util-ts/apiUtils");
|
|
60
75
|
Object.defineProperty(exports, "makeApiCallWithRetry", { enumerable: true, get: function () { return apiUtils_1.makeApiCallWithRetry; } });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;AAAA,mBAAmB;AACnB,yEAGyC;AAFvC,uIAAA,8BAA8B,OAAA;AAC9B,gIAAA,uBAAuB,OAAA;AAEzB,mFAQ8C;AAP5C,oIAAA,sBAAsB,OAAA;AACtB,yHAAA,WAAW,OAAA;AACX,+HAAA,iBAAiB,OAAA;AACjB,6HAAA,eAAe,OAAA;AACf,yIAAA,2BAA2B,OAAA;AAC3B,qIAAA,uBAAuB,OAAA;AAIzB,2GAE0D;AADxD,wJAAA,8BAA8B,OAAA;AAGhC,+FASoD;AARlD,4IAAA,wBAAwB,OAAA;AACxB,gJAAA,4BAA4B,OAAA;AAC5B,0IAAA,sBAAsB,OAAA;AACtB,8IAAA,0BAA0B,OAAA;AAC1B,kIAAA,cAAc,OAAA;AACd,gJAAA,4BAA4B,OAAA;AAC5B,+HAAA,WAAW,OAAA;AACX,oJAAA,gCAAgC,OAAA;AAGlC,yEAEyC;AADvC,6IAAA,oCAAoC,OAAA;AAAE,2HAAA,kBAAkB,OAAA;AAE1D,yEAKyC;AAJvC,0HAAA,iBAAiB,OAAA;AACjB,4HAAA,mBAAmB,OAAA;AACnB,uHAAA,cAAc,OAAA;AACd,2HAAA,kBAAkB,OAAA;AAEpB,qFAG+C;AAF7C,uIAAA,UAAU,OAA4B;AACtC,mJAAA,yBAAyB,OAAwC;AAGnE,gBAAgB;AAChB,mEAaqC;AAJnC,mHAAA,YAAY,OAAA;AAKd,+CAsC2B;AArCzB,6HAAA,gCAAgC,OAAA;AAChC,+HAAA,kCAAkC,OAAA;AAClC,wGAAA,WAAW,OAAA;AACX,mHAAA,sBAAsB,OAAA;AACtB,+GAAA,kBAAkB,OAAA;AAOlB,yGAAA,YAAY,OAAA;AACZ,+GAAA,kBAAkB,OAAA;AAClB,uHAAA,0BAA0B,OAAA;AAC1B,+GAAA,kBAAkB,OAAA;AAClB,uHAAA,0BAA0B,OAAA;AAC1B,gGAAA,GAAG,OAAA;AAgBH,uGAAA,UAAU,OAAA;AACV,yGAAA,YAAY,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":";;;;;;;AAAA,mBAAmB;AACnB,yEAGyC;AAFvC,uIAAA,8BAA8B,OAAA;AAC9B,gIAAA,uBAAuB,OAAA;AAEzB,mFAQ8C;AAP5C,oIAAA,sBAAsB,OAAA;AACtB,yHAAA,WAAW,OAAA;AACX,+HAAA,iBAAiB,OAAA;AACjB,6HAAA,eAAe,OAAA;AACf,yIAAA,2BAA2B,OAAA;AAC3B,qIAAA,uBAAuB,OAAA;AAIzB,2GAE0D;AADxD,wJAAA,8BAA8B,OAAA;AAGhC,+FASoD;AARlD,4IAAA,wBAAwB,OAAA;AACxB,gJAAA,4BAA4B,OAAA;AAC5B,0IAAA,sBAAsB,OAAA;AACtB,8IAAA,0BAA0B,OAAA;AAC1B,kIAAA,cAAc,OAAA;AACd,gJAAA,4BAA4B,OAAA;AAC5B,+HAAA,WAAW,OAAA;AACX,oJAAA,gCAAgC,OAAA;AAGlC,yEAEyC;AADvC,6IAAA,oCAAoC,OAAA;AAAE,2HAAA,kBAAkB,OAAA;AAE1D,yEAKyC;AAJvC,0HAAA,iBAAiB,OAAA;AACjB,4HAAA,mBAAmB,OAAA;AACnB,uHAAA,cAAc,OAAA;AACd,2HAAA,kBAAkB,OAAA;AAEpB,qFAG+C;AAF7C,uIAAA,UAAU,OAA4B;AACtC,mJAAA,yBAAyB,OAAwC;AAGnE,gBAAgB;AAChB,mEAaqC;AAJnC,mHAAA,YAAY,OAAA;AAKd,+CAsC2B;AArCzB,6HAAA,gCAAgC,OAAA;AAChC,+HAAA,kCAAkC,OAAA;AAClC,wGAAA,WAAW,OAAA;AACX,mHAAA,sBAAsB,OAAA;AACtB,+GAAA,kBAAkB,OAAA;AAOlB,yGAAA,YAAY,OAAA;AACZ,+GAAA,kBAAkB,OAAA;AAClB,uHAAA,0BAA0B,OAAA;AAC1B,+GAAA,kBAAkB,OAAA;AAClB,uHAAA,0BAA0B,OAAA;AAC1B,gGAAA,GAAG,OAAA;AAgBH,uGAAA,UAAU,OAAA;AACV,yGAAA,YAAY,OAAA;AAKd,mDAO6B;AAL3B,wGAAA,SAAS,OAAA;AACT,4GAAA,aAAa,OAAA;AACb,6GAAA,cAAc,OAAA;AACd,8GAAA,eAAe,OAAA;AACf,8GAAA,eAAe,OAAA;AAEjB,2FAMkD;AALhD,6HAAA,WAAW,OAAA;AACX,iIAAA,eAAe,OAAA;AACf,6IAAA,2BAA2B,OAAA;AAC3B,8IAAA,4BAA4B,OAAA;AAC5B,wIAAA,sBAAsB,OAAA;AAUxB,4BAA4B;AAC5B,+EAI4C;AAH1C,4HAAA,gBAAgB,OAAA;AAKlB,kBAAkB;AAClB,+CAAuE;AAA/D,gHAAA,oBAAoB,OAAA;AAAE,yGAAA,aAAa,OAAA;AAC3C,iDAAiN;AAAzM,yGAAA,YAAY,OAAA;AAAE,sHAAA,yBAAyB,OAAA;AAAE,6HAAA,gCAAgC,OAAA;AAAE,oHAAA,uBAAuB,OAAA;AAAE,8GAAA,iBAAiB,OAAA;AAAE,oHAAA,uBAAuB,OAAA;AAAE,4GAAA,eAAe,OAAA;AAAE,wGAAA,WAAW,OAAA;AACpL,mEAAuF;AAA/E,wHAAA,kBAAkB,OAAA;AAAE,2HAAA,qBAAqB,OAAA;AACjD,mDAA2D;AAAnD,yHAAA,OAAO,OAAc;AAC7B,mDAAkF;AAA1E,oHAAA,sBAAsB,OAAA;AAAE,kHAAA,oBAAoB,OAAA;AACpD,iDAAmF;AAA3E,gHAAA,mBAAmB,OAAA;AAAE,sHAAA,yBAAyB,OAAA;AACtD,6DAAqD;AAA7C,6GAAA,UAAU,OAAA"}
|
|
@@ -15,6 +15,8 @@ declare function parseGender(patientGender?: string): {
|
|
|
15
15
|
*
|
|
16
16
|
* @param parseType - The type of parsing that failed (e.g., "age", "exam date", "units")
|
|
17
17
|
* @param errorMessages - Array to append error messages to
|
|
18
|
+
* @param notifySlack - notifySlack
|
|
19
|
+
* @param notifyNotes - notifyNotes
|
|
18
20
|
* @returns Object containing rejectedStatus and rejectReason
|
|
19
21
|
*/
|
|
20
22
|
declare function handleRejection(parseType: string, errorMessages: ErrorMessage[], notifySlack?: boolean, notifyNotes?: boolean, notifyBi?: boolean): {
|
|
@@ -13,14 +13,13 @@ exports.postFileUploadSetStatus = postFileUploadSetStatus;
|
|
|
13
13
|
exports.getPartnerTransformationRules = getPartnerTransformationRules;
|
|
14
14
|
const moment_1 = __importDefault(require("moment/moment"));
|
|
15
15
|
const apiUtils_1 = require("../util-ts/apiUtils");
|
|
16
|
-
const
|
|
16
|
+
const processingLogger_service_1 = require("./processingLogger.service");
|
|
17
17
|
const oht_types_1 = require("../types/oht.types");
|
|
18
18
|
const dayjs_1 = __importDefault(require("dayjs"));
|
|
19
19
|
const customParseFormat_1 = __importDefault(require("dayjs/plugin/customParseFormat"));
|
|
20
20
|
const utc_1 = __importDefault(require("dayjs/plugin/utc"));
|
|
21
21
|
dayjs_1.default.extend(customParseFormat_1.default);
|
|
22
22
|
dayjs_1.default.extend(utc_1.default);
|
|
23
|
-
const logger = (0, pinoLogger_1.default)();
|
|
24
23
|
const OHT_CORE_URL = process.env.OHT_CORE_URL;
|
|
25
24
|
function getPatientAge(documentDate, patientBirthdate) {
|
|
26
25
|
if (!patientBirthdate || !documentDate)
|
|
@@ -61,6 +60,8 @@ function parseGender(patientGender) {
|
|
|
61
60
|
*
|
|
62
61
|
* @param parseType - The type of parsing that failed (e.g., "age", "exam date", "units")
|
|
63
62
|
* @param errorMessages - Array to append error messages to
|
|
63
|
+
* @param notifySlack - notifySlack
|
|
64
|
+
* @param notifyNotes - notifyNotes
|
|
64
65
|
* @returns Object containing rejectedStatus and rejectReason
|
|
65
66
|
*/
|
|
66
67
|
function handleRejection(parseType, errorMessages, notifySlack = true, notifyNotes = false, notifyBi = false) {
|
|
@@ -188,7 +189,7 @@ async function postFileUploadSetStatus(payload, fileUploadId, filename, ohtCoreA
|
|
|
188
189
|
formattedPayload.digitalization = digitalization;
|
|
189
190
|
}
|
|
190
191
|
const processingResponse = await (0, apiUtils_1.makeApiCallWithRetry)('post', ohtCoreFileUploadSetStatusUrl, formattedPayload, ohtCoreApiKey);
|
|
191
|
-
|
|
192
|
+
processingLogger_service_1.processingLogger.logInfo(`Resp: POST status: ${payload.status} /file-uploads/${fileUploadId}, filename: ${filename}`, { resp: processingResponse?.data });
|
|
192
193
|
return processingResponse?.data;
|
|
193
194
|
}
|
|
194
195
|
// getPartnerTransformationRules fetches all the available partner transformation rules
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auxiliaryFunctions.service.js","sourceRoot":"","sources":["../../service/auxiliaryFunctions.service.ts"],"names":[],"mappings":";;;;;AAiTE,wDAAsB;AACtB,kCAAW;AACX,8CAAiB;AACjB,sCAAa;AACb,0CAAe;AACf,kEAA2B;AAC3B,0DAAuB;AACvB,sEAA6B;AAxT/B,2DAAmC;AAEnC,kDAAyD;AACzD,
|
|
1
|
+
{"version":3,"file":"auxiliaryFunctions.service.js","sourceRoot":"","sources":["../../service/auxiliaryFunctions.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { RejectReason } from '../types/oht.types';
|
|
2
|
+
/**
|
|
3
|
+
* Validation error for parser/report validation (rejectReason + optional field).
|
|
4
|
+
* Used by mapErrorToRejectReason and handleError.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ValidationError extends Error {
|
|
7
|
+
rejectReason: RejectReason;
|
|
8
|
+
fieldName?: string;
|
|
9
|
+
constructor(message: string, rejectReason: RejectReason, fieldName?: string);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Whether to send Slack notification for this reject reason (not in silent list).
|
|
13
|
+
*/
|
|
14
|
+
export declare function shouldSendSlackNotification(rejectReason: RejectReason | undefined, silentRejectReasons: RejectReason[]): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Formats reject reason with field name and context for better client messages.
|
|
17
|
+
*/
|
|
18
|
+
export declare function extractFormattedRejectReason(rejectReason: RejectReason, fieldName?: string, errorMessage?: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Maps error to an appropriate RejectReason.
|
|
21
|
+
*/
|
|
22
|
+
export declare function mapErrorToRejectReason(error: Error, errorMessage: string, statusCode?: number, responseData?: any): RejectReason;
|
|
23
|
+
/**
|
|
24
|
+
* Handles file-upload processing errors: updates status, notifies Slack, logs with error_code.
|
|
25
|
+
*/
|
|
26
|
+
export declare function handleError(error: Error, fileName: string, signedUploadId: string | undefined, apiKey: string, ohapiUrl: string, cloudEventId?: string, partnerName?: string, silentRejectReasons?: RejectReason[]): Promise<void>;
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ValidationError = void 0;
|
|
7
|
+
exports.shouldSendSlackNotification = shouldSendSlackNotification;
|
|
8
|
+
exports.extractFormattedRejectReason = extractFormattedRejectReason;
|
|
9
|
+
exports.mapErrorToRejectReason = mapErrorToRejectReason;
|
|
10
|
+
exports.handleError = handleError;
|
|
11
|
+
const oht_types_1 = require("../types/oht.types");
|
|
12
|
+
const slackMessages_service_1 = require("./slackMessages.service");
|
|
13
|
+
const auxiliaryFunctions_service_1 = require("./auxiliaryFunctions.service");
|
|
14
|
+
const apiUtils_1 = require("../util-ts/apiUtils");
|
|
15
|
+
const processingLogger_service_1 = require("./processingLogger.service");
|
|
16
|
+
const error_types_1 = require("../types/error.types");
|
|
17
|
+
const dayjs_1 = __importDefault(require("dayjs"));
|
|
18
|
+
const utc_1 = __importDefault(require("dayjs/plugin/utc"));
|
|
19
|
+
dayjs_1.default.extend(utc_1.default);
|
|
20
|
+
/**
|
|
21
|
+
* Validation error for parser/report validation (rejectReason + optional field).
|
|
22
|
+
* Used by mapErrorToRejectReason and handleError.
|
|
23
|
+
*/
|
|
24
|
+
class ValidationError extends Error {
|
|
25
|
+
constructor(message, rejectReason, fieldName) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = 'ValidationError';
|
|
28
|
+
this.rejectReason = rejectReason;
|
|
29
|
+
this.fieldName = fieldName;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.ValidationError = ValidationError;
|
|
33
|
+
/**
|
|
34
|
+
* Whether to send Slack notification for this reject reason (not in silent list).
|
|
35
|
+
*/
|
|
36
|
+
function shouldSendSlackNotification(rejectReason, silentRejectReasons) {
|
|
37
|
+
if (!rejectReason || silentRejectReasons.length === 0) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
return !silentRejectReasons.includes(rejectReason);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Formats reject reason with field name and context for better client messages.
|
|
44
|
+
*/
|
|
45
|
+
function extractFormattedRejectReason(rejectReason, fieldName, errorMessage) {
|
|
46
|
+
const baseRejectReason = String(rejectReason);
|
|
47
|
+
if (rejectReason === oht_types_1.RejectReason.INVALID_DATA_FORMAT && errorMessage) {
|
|
48
|
+
const formattedMatch = errorMessage.match(/Invalid Data Format \[expected: ([^\]]+), received: ([^\]]+)\]/);
|
|
49
|
+
if (formattedMatch) {
|
|
50
|
+
const expectedFormat = formattedMatch[1];
|
|
51
|
+
const receivedFormat = formattedMatch[2];
|
|
52
|
+
const fieldPart = fieldName ? ` for '${fieldName}'` : '';
|
|
53
|
+
return `Invalid Data Format${fieldPart} [expected: ${expectedFormat}, received: ${receivedFormat}]`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (fieldName) {
|
|
57
|
+
switch (rejectReason) {
|
|
58
|
+
case oht_types_1.RejectReason.INCOMPLETE_DATA:
|
|
59
|
+
if (fieldName === 'patient.id') {
|
|
60
|
+
return `Patient external ID conflict: '${fieldName}' does not match user's external reference`;
|
|
61
|
+
}
|
|
62
|
+
return `${baseRejectReason} - Missing or invalid '${fieldName}'`;
|
|
63
|
+
case oht_types_1.RejectReason.MISSING_EXAM_DATE:
|
|
64
|
+
return `${baseRejectReason} - Missing '${fieldName}'`;
|
|
65
|
+
case oht_types_1.RejectReason.MISSING_LAB_ORDER_ID:
|
|
66
|
+
return `${baseRejectReason} - Missing '${fieldName}'`;
|
|
67
|
+
case oht_types_1.RejectReason.MISSING_EXTERNAL_PATIENT_ID:
|
|
68
|
+
return `${baseRejectReason} - Missing '${fieldName}'`;
|
|
69
|
+
case oht_types_1.RejectReason.MISSING_PATIENT_SEX:
|
|
70
|
+
return `${baseRejectReason} - Missing '${fieldName}'`;
|
|
71
|
+
case oht_types_1.RejectReason.INVALID_DATA_NO_BIOMARKER_DATA:
|
|
72
|
+
return `${baseRejectReason} - Invalid '${fieldName}'`;
|
|
73
|
+
default:
|
|
74
|
+
return `${baseRejectReason} - Issue with '${fieldName}'`;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return baseRejectReason;
|
|
78
|
+
}
|
|
79
|
+
function isPatientExternalIdConflict(statusCode, errorMessage, responseData) {
|
|
80
|
+
const lowerMessage = errorMessage.toLowerCase();
|
|
81
|
+
const is409Error = statusCode === 409 ||
|
|
82
|
+
lowerMessage.includes('status code 409') ||
|
|
83
|
+
lowerMessage.includes('409');
|
|
84
|
+
if (!is409Error)
|
|
85
|
+
return false;
|
|
86
|
+
const isExplicitlyNotPatientConflict = lowerMessage.includes('duplicate') &&
|
|
87
|
+
!lowerMessage.includes('patient') &&
|
|
88
|
+
!lowerMessage.includes('external');
|
|
89
|
+
return !isExplicitlyNotPatientConflict;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Maps error to an appropriate RejectReason.
|
|
93
|
+
*/
|
|
94
|
+
function mapErrorToRejectReason(error, errorMessage, statusCode, responseData) {
|
|
95
|
+
if (isPatientExternalIdConflict(statusCode, errorMessage, responseData)) {
|
|
96
|
+
return oht_types_1.RejectReason.INCOMPLETE_DATA;
|
|
97
|
+
}
|
|
98
|
+
const hasRejectReason = error instanceof ValidationError || 'rejectReason' in error;
|
|
99
|
+
if (hasRejectReason) {
|
|
100
|
+
const rejectReason = error.rejectReason;
|
|
101
|
+
if (rejectReason !== undefined && rejectReason !== null && rejectReason !== '') {
|
|
102
|
+
return rejectReason;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const lowerMessage = errorMessage.toLowerCase();
|
|
106
|
+
if (lowerMessage.includes('invalid data format') || lowerMessage.includes('invalid format') || lowerMessage.includes('iso 8601 format')) {
|
|
107
|
+
return oht_types_1.RejectReason.INVALID_DATA_FORMAT;
|
|
108
|
+
}
|
|
109
|
+
if (lowerMessage.includes('no biomarker') || lowerMessage.includes('invalid input') || lowerMessage.includes('no measurements')) {
|
|
110
|
+
return oht_types_1.RejectReason.INVALID_DATA_NO_BIOMARKER_DATA;
|
|
111
|
+
}
|
|
112
|
+
if (lowerMessage.includes('image quality') || lowerMessage.includes('low quality')) {
|
|
113
|
+
return oht_types_1.RejectReason.LOW_IMAGE_QUALITY;
|
|
114
|
+
}
|
|
115
|
+
if (lowerMessage.includes('underage') || (lowerMessage.includes('age') && lowerMessage.includes('invalid'))) {
|
|
116
|
+
return oht_types_1.RejectReason.UNDERAGE_PERSON;
|
|
117
|
+
}
|
|
118
|
+
if (lowerMessage.includes('language') || lowerMessage.includes('unsupported language')) {
|
|
119
|
+
return oht_types_1.RejectReason.LANGUAGE_NOT_SUPPORTED;
|
|
120
|
+
}
|
|
121
|
+
if (lowerMessage.includes('implausible') || lowerMessage.includes('invalid value')) {
|
|
122
|
+
return oht_types_1.RejectReason.IMPLAUSIBLE_DATA;
|
|
123
|
+
}
|
|
124
|
+
if (lowerMessage.includes('missing exam date') || lowerMessage.includes('no date') || lowerMessage.includes('date')) {
|
|
125
|
+
return oht_types_1.RejectReason.MISSING_EXAM_DATE;
|
|
126
|
+
}
|
|
127
|
+
if (lowerMessage.includes('missing unit') || lowerMessage.includes('incomplete') || lowerMessage.includes('missing data')) {
|
|
128
|
+
return oht_types_1.RejectReason.INCOMPLETE_DATA;
|
|
129
|
+
}
|
|
130
|
+
if (lowerMessage.includes('not an official') || lowerMessage.includes('not official')) {
|
|
131
|
+
return oht_types_1.RejectReason.NOT_AN_OFFICIAL_REPORT;
|
|
132
|
+
}
|
|
133
|
+
if (lowerMessage.includes('missing external patient') || lowerMessage.includes('missing patient id')) {
|
|
134
|
+
return oht_types_1.RejectReason.MISSING_EXTERNAL_PATIENT_ID;
|
|
135
|
+
}
|
|
136
|
+
if (lowerMessage.includes('unsupported') || lowerMessage.includes('not supported')) {
|
|
137
|
+
return oht_types_1.RejectReason.UNSUPPORTED_UPLOAD;
|
|
138
|
+
}
|
|
139
|
+
return oht_types_1.RejectReason.UNSUPPORTED_UPLOAD;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Handles file-upload processing errors: updates status, notifies Slack, logs with error_code.
|
|
143
|
+
*/
|
|
144
|
+
async function handleError(error, fileName, signedUploadId, apiKey, ohapiUrl, cloudEventId, partnerName, silentRejectReasons = []) {
|
|
145
|
+
const errorDetails = (0, apiUtils_1.parseErrorObj)(error);
|
|
146
|
+
const responseData = errorDetails.responseData;
|
|
147
|
+
const statusCode = errorDetails.status;
|
|
148
|
+
const axiosStatusCode = error.response?.status;
|
|
149
|
+
const finalStatusCode = statusCode || axiosStatusCode;
|
|
150
|
+
const errorMessage = responseData
|
|
151
|
+
? `${error.message} - Response: ${JSON.stringify(responseData)}`
|
|
152
|
+
: error.message || 'Unknown error occurred';
|
|
153
|
+
const isIngestionError = finalStatusCode === 409 ||
|
|
154
|
+
errorMessage.toLowerCase().includes('ingestion') ||
|
|
155
|
+
errorDetails.config?.url?.includes('/ingestion');
|
|
156
|
+
const pipelineStep = isIngestionError
|
|
157
|
+
? oht_types_1.PipelineStep.SENDING_RESULTS
|
|
158
|
+
: oht_types_1.PipelineStep.EXTRACTING_METADATA;
|
|
159
|
+
const errorType = error.constructor.name;
|
|
160
|
+
const rejectReason = mapErrorToRejectReason(error, errorMessage, finalStatusCode, responseData);
|
|
161
|
+
let fieldName;
|
|
162
|
+
if (error instanceof ValidationError) {
|
|
163
|
+
fieldName = error.fieldName;
|
|
164
|
+
}
|
|
165
|
+
else if (finalStatusCode === 409 && rejectReason === oht_types_1.RejectReason.INCOMPLETE_DATA) {
|
|
166
|
+
fieldName = 'patient.id';
|
|
167
|
+
}
|
|
168
|
+
const formattedRejectReason = extractFormattedRejectReason(rejectReason, fieldName, errorMessage);
|
|
169
|
+
if (!signedUploadId) {
|
|
170
|
+
const noUploadError = new Error((0, error_types_1.getErrorMessage)(error_types_1.ErrorCode.UPLOAD_MISSING_SIGNED_UPLOAD_ID));
|
|
171
|
+
processingLogger_service_1.processingLogger.addError(noUploadError, 'error_handling');
|
|
172
|
+
processingLogger_service_1.processingLogger.logError('Processing failed: Missing signed upload ID', noUploadError, {
|
|
173
|
+
error_code: error_types_1.ErrorCode.UPLOAD_MISSING_SIGNED_UPLOAD_ID,
|
|
174
|
+
cloud_event_id: cloudEventId,
|
|
175
|
+
partner_name: partnerName,
|
|
176
|
+
});
|
|
177
|
+
processingLogger_service_1.processingLogger.logEnd(false);
|
|
178
|
+
throw noUploadError;
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
181
|
+
processingLogger_service_1.processingLogger.addError(error, 'error_handling');
|
|
182
|
+
const fileUploads = await (0, auxiliaryFunctions_service_1.queryFileUploadsWithFilters)([{ field: 'signedUploadId', search: signedUploadId }], apiKey);
|
|
183
|
+
const fileUploadId = fileUploads[0]?.id;
|
|
184
|
+
if (!fileUploadId) {
|
|
185
|
+
processingLogger_service_1.processingLogger.logError('Processing failed: File upload not found', undefined, {
|
|
186
|
+
error_code: error_types_1.ErrorCode.UPLOAD_FILE_NOT_FOUND,
|
|
187
|
+
signed_upload_id: signedUploadId,
|
|
188
|
+
partner_name: partnerName,
|
|
189
|
+
});
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const fileUrl = `${ohapiUrl}/data-import/file-uploads/${fileUploadId}`;
|
|
193
|
+
const sendSlack = shouldSendSlackNotification(rejectReason, silentRejectReasons);
|
|
194
|
+
const fieldInfo = fieldName ? `\n*Field:* \`${fieldName}\`` : '';
|
|
195
|
+
const slackMessage = (0, slackMessages_service_1.getSlackFileIssueNotificationMessage)(`🚨 *AgnosticParser Processing Error*\n\n` +
|
|
196
|
+
`*Error:* ${errorType}: ${errorMessage}\n` +
|
|
197
|
+
`*Reject Reason:* ${formattedRejectReason}${fieldInfo}\n` +
|
|
198
|
+
`*File:* \`${fileName}\`\n` +
|
|
199
|
+
`*Partner:* ${partnerName || 'Unknown'}\n` +
|
|
200
|
+
`*File Upload ID:* \`${fileUploadId}\`\n` +
|
|
201
|
+
(cloudEventId ? `*Event ID:* \`${cloudEventId}\`\n` : ''), `AgnosticParser - ${partnerName || 'Unknown Partner'}`, fileUrl);
|
|
202
|
+
const [slackResult, statusResult] = await Promise.allSettled([
|
|
203
|
+
sendSlack ? (0, slackMessages_service_1.sendMessageToSlack)(slackMessage) : Promise.resolve(),
|
|
204
|
+
(0, auxiliaryFunctions_service_1.postFileUploadSetStatus)({
|
|
205
|
+
status: oht_types_1.DataImportFileUploadStatus.REJECTED,
|
|
206
|
+
digitalization: {
|
|
207
|
+
status: oht_types_1.DigitizationStatus.ERROR,
|
|
208
|
+
pipelineStep: pipelineStep,
|
|
209
|
+
pipelineStepData: formattedRejectReason,
|
|
210
|
+
timestamp: dayjs_1.default.utc().toISOString(),
|
|
211
|
+
},
|
|
212
|
+
...(formattedRejectReason && { rejectReason: formattedRejectReason }),
|
|
213
|
+
}, fileUploadId, fileName, apiKey),
|
|
214
|
+
]);
|
|
215
|
+
if (slackResult.status === 'rejected') {
|
|
216
|
+
processingLogger_service_1.processingLogger.logWarn('Slack notification failed', {
|
|
217
|
+
error_code: error_types_1.ErrorCode.UPLOAD_SLACK_FAILED,
|
|
218
|
+
file_upload_id: fileUploadId,
|
|
219
|
+
slack_error: (0, apiUtils_1.parseErrorObj)(slackResult.reason),
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
if (statusResult.status === 'rejected') {
|
|
223
|
+
const statusErrorDetails = (0, apiUtils_1.parseErrorObj)(statusResult.reason);
|
|
224
|
+
const statusResponseData = statusErrorDetails.responseData;
|
|
225
|
+
processingLogger_service_1.processingLogger.logError(`Failed to update file upload status: ${statusErrorDetails.message}${statusResponseData ? ` - ${JSON.stringify(statusResponseData)}` : ''}`, undefined, {
|
|
226
|
+
error_code: error_types_1.ErrorCode.UPLOAD_STATUS_UPDATE_FAILED,
|
|
227
|
+
file_upload_id: fileUploadId,
|
|
228
|
+
status_error: statusErrorDetails,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
processingLogger_service_1.processingLogger.logError(`Processing failed: ${errorType} - ${formattedRejectReason}${fieldName ? ` (field: ${fieldName})` : ''}`, error, {
|
|
232
|
+
error_code: error_types_1.ErrorCode.UPLOAD_PROCESSING_FAILED,
|
|
233
|
+
file_upload_id: fileUploadId,
|
|
234
|
+
signed_upload_id: signedUploadId,
|
|
235
|
+
partner_name: partnerName,
|
|
236
|
+
error_type: errorType,
|
|
237
|
+
error_details: errorDetails,
|
|
238
|
+
reject_reason: formattedRejectReason,
|
|
239
|
+
field_name: fieldName,
|
|
240
|
+
cloud_event_id: cloudEventId,
|
|
241
|
+
});
|
|
242
|
+
processingLogger_service_1.processingLogger.logEnd(false);
|
|
243
|
+
}
|
|
244
|
+
catch (handleErrorException) {
|
|
245
|
+
const exceptionMessage = handleErrorException instanceof Error
|
|
246
|
+
? handleErrorException.message
|
|
247
|
+
: String(handleErrorException);
|
|
248
|
+
const handlingError = handleErrorException instanceof Error
|
|
249
|
+
? handleErrorException
|
|
250
|
+
: new Error(String(handleErrorException));
|
|
251
|
+
processingLogger_service_1.processingLogger.addError(handlingError, 'error_handling_failure');
|
|
252
|
+
processingLogger_service_1.processingLogger.logError(`Error handling failed: ${exceptionMessage}`, handlingError, {
|
|
253
|
+
error_code: error_types_1.ErrorCode.UPLOAD_HANDLING_FAILED,
|
|
254
|
+
signed_upload_id: signedUploadId,
|
|
255
|
+
partner_name: partnerName,
|
|
256
|
+
original_error: errorMessage,
|
|
257
|
+
original_error_type: errorType,
|
|
258
|
+
handling_error: exceptionMessage,
|
|
259
|
+
});
|
|
260
|
+
processingLogger_service_1.processingLogger.logEnd(false);
|
|
261
|
+
throw error;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=fileUploadErrorHandler.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileUploadErrorHandler.service.js","sourceRoot":"","sources":["../../service/fileUploadErrorHandler.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.getRangeFromPositionAndRegex = void 0;
|
|
7
4
|
exports.ohtMeasurementsExtractor = ohtMeasurementsExtractor;
|
|
@@ -13,12 +10,11 @@ exports.extractUnit = extractUnit;
|
|
|
13
10
|
exports.extractValueFromGreaterLowerThan = extractValueFromGreaterLowerThan;
|
|
14
11
|
const dataUtils_1 = require("../util-ts/dataUtils");
|
|
15
12
|
const regexUtils_1 = require("../util-ts/regexUtils");
|
|
16
|
-
const
|
|
13
|
+
const processingLogger_service_1 = require("./processingLogger.service");
|
|
17
14
|
const apiUtils_1 = require("../util-ts/apiUtils");
|
|
18
15
|
const oht_types_1 = require("../types/oht.types");
|
|
19
16
|
const transformationRules_service_1 = require("./transformationRules.service");
|
|
20
17
|
const auxiliaryFunctions_service_1 = require("./auxiliaryFunctions.service");
|
|
21
|
-
const logger = (0, pinoLogger_1.default)();
|
|
22
18
|
const OHT_CORE_URL = process.env.OHT_CORE_URL;
|
|
23
19
|
let filename = '';
|
|
24
20
|
function extractUnit(unitExtraction, rawData, ohtBiomarker, synonymUnits = null, partnerId = null) {
|
|
@@ -296,7 +292,7 @@ function checkValueForPlausibleValues(labToOhtMapper, ohtBiomarker, unit, value,
|
|
|
296
292
|
const isPlausibleValue = value >= plausibleLowerValue && value <= plausibleUpperValue;
|
|
297
293
|
// Log if the value is not plausible
|
|
298
294
|
if (!isPlausibleValue) {
|
|
299
|
-
|
|
295
|
+
processingLogger_service_1.processingLogger.logWarn(`Value "${value} ${standardUnit}" not plausible "${plausibleLowerValue} to ${plausibleUpperValue}" for "${labToOhtMapper.ohtBmId}" | "${labToOhtMapper.labKey}", filename: ${filename}`, { labToOhtMapper, value, standardUnit, plausibleLowerValue, plausibleUpperValue, filename });
|
|
300
296
|
}
|
|
301
297
|
return isPlausibleValue;
|
|
302
298
|
}
|
|
@@ -306,8 +302,10 @@ function checkValueForPlausibleValues(labToOhtMapper, ohtBiomarker, unit, value,
|
|
|
306
302
|
*
|
|
307
303
|
* @param exams - Array of original exam objects
|
|
308
304
|
* @param transformationRules - Mapping of labKey to transformation rule chains
|
|
309
|
-
* @param
|
|
310
|
-
* @
|
|
305
|
+
* @param patientInfo - PatientInfo
|
|
306
|
+
* @param documentDate - Source DocumentDate
|
|
307
|
+
*
|
|
308
|
+
* @returns Promise<ApplyTransformationRulesResult[]> - Array of transformed exams
|
|
311
309
|
*/
|
|
312
310
|
async function applyTransformationRulesToExams(exams, transformationRules, patientInfo, documentDate) {
|
|
313
311
|
if (transformationRules.size === 0) {
|
|
@@ -329,7 +327,7 @@ async function applyTransformationRulesToExams(exams, transformationRules, patie
|
|
|
329
327
|
const ohtReport = {
|
|
330
328
|
exams: exams.map(e => e.ohtExam),
|
|
331
329
|
};
|
|
332
|
-
|
|
330
|
+
processingLogger_service_1.processingLogger.logInfo('Applying transformation rules to exams...', { exams_count: exams.length, chains_count: transformationRules.size, filename });
|
|
333
331
|
let labKeysWithRulesCount = 0;
|
|
334
332
|
let transformedLabKeysCount = 0;
|
|
335
333
|
const applicationErrorMessages = [];
|
|
@@ -347,14 +345,14 @@ async function applyTransformationRulesToExams(exams, transformationRules, patie
|
|
|
347
345
|
contextJson: reportContext,
|
|
348
346
|
});
|
|
349
347
|
if (result.errors.length > 0) {
|
|
350
|
-
|
|
348
|
+
processingLogger_service_1.processingLogger.logWarn('Errors applying transformation rule(s) for labKey.', { labKey, errors: result.errors, filename });
|
|
351
349
|
applicationErrorMessages.push(`${labKey}: ${result.errors.map(e => `(rule ID ${e.ruleId}) ${e.error}`).join('; ')}`);
|
|
352
350
|
}
|
|
353
351
|
else {
|
|
354
352
|
if (result.appliedRules.length > 0) {
|
|
355
353
|
transformedLabKeysCount++;
|
|
356
354
|
}
|
|
357
|
-
|
|
355
|
+
processingLogger_service_1.processingLogger.logInfo('Done applying transformation rule(s) for labKey.', { labKey, applied_rules: result.appliedRules.length, filename });
|
|
358
356
|
// Add the transformed exam to the result array only if there are no errors in the chain
|
|
359
357
|
transformedExams.push({
|
|
360
358
|
ohtExam: result.data,
|
|
@@ -363,17 +361,17 @@ async function applyTransformationRulesToExams(exams, transformationRules, patie
|
|
|
363
361
|
}
|
|
364
362
|
}
|
|
365
363
|
catch (error) {
|
|
366
|
-
|
|
364
|
+
processingLogger_service_1.processingLogger.logError('Failed to apply transformation rules for labKey.', error instanceof Error ? error : undefined, { labKey, filename });
|
|
367
365
|
applicationErrorMessages.push(`${labKey}: Unhandled error occurred.`);
|
|
368
366
|
}
|
|
369
367
|
}
|
|
370
|
-
|
|
368
|
+
processingLogger_service_1.processingLogger.logInfo('Done applying the transformation rules to exams.', {
|
|
371
369
|
filename,
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
transformedLabKeysCount,
|
|
375
|
-
labKeysWithRulesCount,
|
|
376
|
-
}
|
|
370
|
+
exams_count: exams.length,
|
|
371
|
+
chains_count: transformationRules.size,
|
|
372
|
+
transformed_lab_keys_count: transformedLabKeysCount,
|
|
373
|
+
lab_keys_with_rules_count: labKeysWithRulesCount,
|
|
374
|
+
});
|
|
377
375
|
return {
|
|
378
376
|
transformedExams,
|
|
379
377
|
applicationErrorMessages
|
|
@@ -392,7 +390,7 @@ async function ohtMeasurementsExtractor(labToOhtContract, exams, transformationR
|
|
|
392
390
|
transformedExamsResult = await applyTransformationRulesToExams(exams, transformationRules, labToOhtContract.patientInfo, labToOhtContract.documentDate);
|
|
393
391
|
}
|
|
394
392
|
catch (error) {
|
|
395
|
-
|
|
393
|
+
processingLogger_service_1.processingLogger.logError('Unhandled error while applying transformation rules to exams.', error instanceof Error ? error : undefined, { filename });
|
|
396
394
|
labToOhtContract.errorMessages.push({
|
|
397
395
|
destination: { slack: true, notes: true, bi: false },
|
|
398
396
|
message: `Failed applying the transformation rules for filename ${filename}. ${error instanceof Error ? error.message : error}`,
|
|
@@ -450,7 +448,7 @@ async function ohtMeasurementsExtractor(labToOhtContract, exams, transformationR
|
|
|
450
448
|
if (labToOhtMapper?.ohtBmId && labToOhtMapper?.ohtBmId !== -1) {
|
|
451
449
|
// if BM is already in measurements, continue to the next one
|
|
452
450
|
if (measurements.some(measurement => measurement.biomarkerId === labToOhtMapper.ohtBmId)) {
|
|
453
|
-
|
|
451
|
+
processingLogger_service_1.processingLogger.logWarn(`Biomarker already in measurements array, should investigate, filename: ${filename}`, { labToOhtMapper });
|
|
454
452
|
labToOhtContract.errorMessages.push({
|
|
455
453
|
destination: { slack: false, notes: false, bi: true },
|
|
456
454
|
message: `Biomarkers Duplicated keys:[PLACEHOLDER]`,
|
|
@@ -477,7 +475,7 @@ async function ohtMeasurementsExtractor(labToOhtContract, exams, transformationR
|
|
|
477
475
|
});
|
|
478
476
|
}
|
|
479
477
|
if (!isUnitParsedCorrectly) {
|
|
480
|
-
|
|
478
|
+
processingLogger_service_1.processingLogger.logWarn(`Unit not extracted correctly for "${labToOhtMapper.ohtBmId}|${labToOhtMapper.labKey}", filename: ${filename}`, { labToOhtMapper });
|
|
481
479
|
labToOhtContract.errorMessages.push({
|
|
482
480
|
destination: { slack: true, notes: true, bi: true },
|
|
483
481
|
message: `Unit not extracted correctly for:[PLACEHOLDER]`,
|
|
@@ -487,7 +485,7 @@ async function ohtMeasurementsExtractor(labToOhtContract, exams, transformationR
|
|
|
487
485
|
}
|
|
488
486
|
let { valueType, alphanumericalValue, numberValue, valueComparator, isValueParsedCorrectly } = parseExamValue(examObj, labToOhtMapper.valueExtraction, ohtBiomarker);
|
|
489
487
|
if (!isValueParsedCorrectly) {
|
|
490
|
-
|
|
488
|
+
processingLogger_service_1.processingLogger.logWarn(`Value not extracted correctly for "${labToOhtMapper.ohtBmId}|${labToOhtMapper.labKey}", filename: ${filename}`, { labToOhtMapper });
|
|
491
489
|
labToOhtContract.errorMessages.push({
|
|
492
490
|
destination: { slack: true, notes: true, bi: true },
|
|
493
491
|
message: `Value not extracted correctly for:[PLACEHOLDER]`,
|
|
@@ -523,7 +521,7 @@ async function ohtMeasurementsExtractor(labToOhtContract, exams, transformationR
|
|
|
523
521
|
if (isValueParsedCorrectly && valueType === 'NUMERICAL') {
|
|
524
522
|
const isPlausibleValue = numberValue !== null && checkValueForPlausibleValues(labToOhtMapper, ohtBiomarker, unit, numberValue, isUnitParsedCorrectly);
|
|
525
523
|
if (!isPlausibleValue) {
|
|
526
|
-
|
|
524
|
+
processingLogger_service_1.processingLogger.logWarn(`Value [${numberValue} ${unit}] is not plausible for "${labToOhtMapper.ohtBmId}|${labToOhtMapper.labKey}", filename: ${filename}`, { labToOhtMapper });
|
|
527
525
|
labToOhtContract.errorMessages.push({
|
|
528
526
|
destination: { slack: true, notes: true, bi: true },
|
|
529
527
|
message: `Value is not plausible for:[PLACEHOLDER]`,
|
|
@@ -541,7 +539,7 @@ async function ohtMeasurementsExtractor(labToOhtContract, exams, transformationR
|
|
|
541
539
|
to = extractedRange.to ?? null;
|
|
542
540
|
isRangeParsedCorrectly = extractedRange.isRangeParsedCorrectly;
|
|
543
541
|
if (!isRangeParsedCorrectly) {
|
|
544
|
-
|
|
542
|
+
processingLogger_service_1.processingLogger.logWarn(`Range not extracted correctly for "${labToOhtMapper.ohtBmId}|${labToOhtMapper.labKey}", filename: ${filename}`, { labToOhtMapper });
|
|
545
543
|
labToOhtContract.errorMessages.push({
|
|
546
544
|
destination: { slack: true, notes: true, bi: true },
|
|
547
545
|
message: `Range not extracted correctly for:[PLACEHOLDER]`,
|
|
@@ -598,7 +596,7 @@ async function ohtMeasurementsExtractor(labToOhtContract, exams, transformationR
|
|
|
598
596
|
measurements.push(measurement);
|
|
599
597
|
}
|
|
600
598
|
else {
|
|
601
|
-
|
|
599
|
+
processingLogger_service_1.processingLogger.logWarn(`Created an ungroupedBiomarker for id: ${labToOhtMapper.labKey}, filename: ${filename}`);
|
|
602
600
|
labToOhtContract.errorMessages.push({
|
|
603
601
|
destination: { slack: false, notes: false, bi: true },
|
|
604
602
|
message: `Created ungroupedBiomarkers for:[PLACEHOLDER]`,
|