@elisra-devops/docgen-data-provider 1.79.0 → 1.80.0
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.
|
@@ -118,6 +118,8 @@ export default class ResultDataProvider {
|
|
|
118
118
|
private fetchMewpL2Requirements;
|
|
119
119
|
private isMewpL2AreaPath;
|
|
120
120
|
private collapseMewpRequirementFamilies;
|
|
121
|
+
private buildMewpL2ToLinkedL1BaseKeys;
|
|
122
|
+
private buildMewpExternalJoinKeysByL2Requirement;
|
|
121
123
|
private buildRequirementFamilyMap;
|
|
122
124
|
private buildLinkedRequirementsByTestCase;
|
|
123
125
|
private resolveMewpRequirementScopeKeysFromQuery;
|
|
@@ -304,6 +304,7 @@ class ResultDataProvider {
|
|
|
304
304
|
const linkedRequirementsByTestCase = await this.buildLinkedRequirementsByTestCase(allRequirements, testData, projectName);
|
|
305
305
|
const scopedRequirementKeys = await this.resolveMewpRequirementScopeKeysFromQuery(linkedQueryRequest, allRequirements, linkedRequirementsByTestCase);
|
|
306
306
|
const requirements = this.collapseMewpRequirementFamilies(allRequirements, (scopedRequirementKeys === null || scopedRequirementKeys === void 0 ? void 0 : scopedRequirementKeys.size) ? scopedRequirementKeys : undefined);
|
|
307
|
+
const l2ToLinkedL1BaseKeys = await this.buildMewpL2ToLinkedL1BaseKeys(allRequirements, projectName, testData);
|
|
307
308
|
const requirementSapWbsByBaseKey = this.buildRequirementSapWbsByBaseKey(allRequirements);
|
|
308
309
|
const externalBugsByTestCase = await this.loadExternalBugsByTestCase(options === null || options === void 0 ? void 0 : options.externalBugsFile);
|
|
309
310
|
const externalL3L4ByBaseKey = await this.loadExternalL3L4ByBaseKey(options === null || options === void 0 ? void 0 : options.externalL3L4File, requirementSapWbsByBaseKey);
|
|
@@ -333,6 +334,7 @@ class ResultDataProvider {
|
|
|
333
334
|
if (requirements.length === 0) {
|
|
334
335
|
return Object.assign(Object.assign({}, defaultPayload), { sheetName: this.buildMewpCoverageSheetName(planName, testPlanId) });
|
|
335
336
|
}
|
|
337
|
+
const externalJoinKeysByL2 = this.buildMewpExternalJoinKeysByL2Requirement(requirements, l2ToLinkedL1BaseKeys);
|
|
336
338
|
const requirementIndex = new Map();
|
|
337
339
|
const observedTestCaseIdsByRequirement = new Map();
|
|
338
340
|
const requirementKeys = new Set();
|
|
@@ -382,8 +384,15 @@ class ResultDataProvider {
|
|
|
382
384
|
this.accumulateRequirementCountsFromActionResults(fallbackActionResults, testCaseId, requirementKeys, requirementIndex, observedTestCaseIdsByRequirement);
|
|
383
385
|
}
|
|
384
386
|
const requirementBaseKeys = new Set(requirements.map((item) => String((item === null || item === void 0 ? void 0 : item.baseKey) || '').trim()).filter((item) => !!item));
|
|
387
|
+
const externalJoinKeyUniverse = new Set();
|
|
388
|
+
for (const keySet of externalJoinKeysByL2.values()) {
|
|
389
|
+
for (const key of keySet) {
|
|
390
|
+
if (key)
|
|
391
|
+
externalJoinKeyUniverse.add(key);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
385
394
|
const externalL3L4BaseKeys = new Set([...externalL3L4ByBaseKey.keys()]);
|
|
386
|
-
const externalL3L4OverlapKeys = [...externalL3L4BaseKeys].filter((key) =>
|
|
395
|
+
const externalL3L4OverlapKeys = [...externalL3L4BaseKeys].filter((key) => externalJoinKeyUniverse.has(key));
|
|
387
396
|
const failedRequirementBaseKeys = new Set();
|
|
388
397
|
const failedTestCaseIds = new Set();
|
|
389
398
|
for (const [requirementBaseKey, byTestCase] of requirementIndex.entries()) {
|
|
@@ -404,9 +413,10 @@ class ResultDataProvider {
|
|
|
404
413
|
externalBugBaseKeys.add(key);
|
|
405
414
|
}
|
|
406
415
|
}
|
|
407
|
-
const externalBugRequirementOverlap = [...externalBugBaseKeys].filter((key) =>
|
|
408
|
-
const externalBugFailedRequirementOverlap = [...externalBugBaseKeys].filter((key) =>
|
|
416
|
+
const externalBugRequirementOverlap = [...externalBugBaseKeys].filter((key) => externalJoinKeyUniverse.has(key));
|
|
417
|
+
const externalBugFailedRequirementOverlap = [...externalBugBaseKeys].filter((key) => externalJoinKeyUniverse.has(key));
|
|
409
418
|
logger_1.default.info(`MEWP coverage join diagnostics: requirementBaseKeys=${requirementBaseKeys.size} ` +
|
|
419
|
+
`externalJoinKeys=${externalJoinKeyUniverse.size} ` +
|
|
410
420
|
`failedRequirementBaseKeys=${failedRequirementBaseKeys.size} failedTestCases=${failedTestCaseIds.size}; ` +
|
|
411
421
|
`externalL3L4BaseKeys=${externalL3L4BaseKeys.size} externalL3L4Overlap=${externalL3L4OverlapKeys.length}; ` +
|
|
412
422
|
`externalBugTestCases=${externalBugTestCaseIds.size} externalBugFailedTestCaseOverlap=${externalBugFailedTestCaseOverlap.length}; ` +
|
|
@@ -414,21 +424,25 @@ class ResultDataProvider {
|
|
|
414
424
|
`externalBugFailedRequirementOverlap=${externalBugFailedRequirementOverlap.length}`);
|
|
415
425
|
if (externalL3L4BaseKeys.size > 0 && externalL3L4OverlapKeys.length === 0) {
|
|
416
426
|
const sampleReq = [...requirementBaseKeys].slice(0, 5);
|
|
427
|
+
const sampleJoin = [...externalJoinKeyUniverse].slice(0, 5);
|
|
417
428
|
const sampleExt = [...externalL3L4BaseKeys].slice(0, 5);
|
|
418
429
|
logger_1.default.warn(`MEWP coverage join diagnostics: no L3/L4 key overlap found. ` +
|
|
419
|
-
`sampleRequirementKeys=${sampleReq.join(', ')}
|
|
430
|
+
`sampleRequirementKeys=${sampleReq.join(', ')} sampleJoinKeys=${sampleJoin.join(', ')} ` +
|
|
431
|
+
`sampleExternalL3L4Keys=${sampleExt.join(', ')}`);
|
|
420
432
|
}
|
|
421
433
|
if (externalBugBaseKeys.size > 0 && externalBugRequirementOverlap.length === 0) {
|
|
422
434
|
const sampleReq = [...requirementBaseKeys].slice(0, 5);
|
|
435
|
+
const sampleJoin = [...externalJoinKeyUniverse].slice(0, 5);
|
|
423
436
|
const sampleExt = [...externalBugBaseKeys].slice(0, 5);
|
|
424
437
|
logger_1.default.warn(`MEWP coverage join diagnostics: no bug requirement-key overlap found. ` +
|
|
425
|
-
`sampleRequirementKeys=${sampleReq.join(', ')}
|
|
438
|
+
`sampleRequirementKeys=${sampleReq.join(', ')} sampleJoinKeys=${sampleJoin.join(', ')} ` +
|
|
439
|
+
`sampleExternalBugKeys=${sampleExt.join(', ')}`);
|
|
426
440
|
}
|
|
427
441
|
if (externalBugTestCaseIds.size > 0 && externalBugFailedTestCaseOverlap.length === 0) {
|
|
428
442
|
logger_1.default.warn(`MEWP coverage join diagnostics: no overlap between external bug test cases and failed test cases. ` +
|
|
429
443
|
`Bug rows remain empty because bugs are shown only for failed L2s.`);
|
|
430
444
|
}
|
|
431
|
-
const rows = this.buildMewpCoverageRows(requirements, requirementIndex, observedTestCaseIdsByRequirement, linkedRequirementsByTestCase, externalL3L4ByBaseKey, externalBugsByTestCase);
|
|
445
|
+
const rows = this.buildMewpCoverageRows(requirements, requirementIndex, observedTestCaseIdsByRequirement, linkedRequirementsByTestCase, externalL3L4ByBaseKey, externalBugsByTestCase, externalJoinKeysByL2);
|
|
432
446
|
const coverageRowStats = rows.reduce((acc, row) => {
|
|
433
447
|
const hasBug = Number((row === null || row === void 0 ? void 0 : row['Bug ID']) || 0) > 0;
|
|
434
448
|
const hasL3 = String((row === null || row === void 0 ? void 0 : row['L3 REQ ID']) || '').trim() !== '';
|
|
@@ -493,12 +507,24 @@ class ResultDataProvider {
|
|
|
493
507
|
}
|
|
494
508
|
}
|
|
495
509
|
const validL2BaseKeys = new Set([...requirementFamilies.keys()]);
|
|
510
|
+
const diagnostics = {
|
|
511
|
+
totalTestCases: 0,
|
|
512
|
+
totalParsedSteps: 0,
|
|
513
|
+
totalStepsWithMentions: 0,
|
|
514
|
+
totalMentionedCustomerIds: 0,
|
|
515
|
+
testCasesWithoutMentionedCustomerIds: 0,
|
|
516
|
+
failingRows: 0,
|
|
517
|
+
};
|
|
496
518
|
for (const testCaseId of [...allTestCaseIds].sort((a, b) => a - b)) {
|
|
519
|
+
diagnostics.totalTestCases += 1;
|
|
497
520
|
const stepsXml = stepsXmlByTestCase.get(testCaseId) || '';
|
|
498
521
|
const parsedSteps = stepsXml && String(stepsXml).trim() !== ''
|
|
499
522
|
? await this.testStepParserHelper.parseTestSteps(stepsXml, new Map())
|
|
500
523
|
: [];
|
|
524
|
+
const executableSteps = parsedSteps.filter((step) => !(step === null || step === void 0 ? void 0 : step.isSharedStepTitle));
|
|
525
|
+
diagnostics.totalParsedSteps += executableSteps.length;
|
|
501
526
|
const mentionEntries = this.extractRequirementMentionsFromExpectedSteps(parsedSteps, true);
|
|
527
|
+
diagnostics.totalStepsWithMentions += mentionEntries.length;
|
|
502
528
|
const mentionedL2Only = new Set();
|
|
503
529
|
const mentionedCodeFirstStep = new Map();
|
|
504
530
|
const mentionedBaseFirstStep = new Map();
|
|
@@ -521,6 +547,10 @@ class ResultDataProvider {
|
|
|
521
547
|
}
|
|
522
548
|
}
|
|
523
549
|
}
|
|
550
|
+
diagnostics.totalMentionedCustomerIds += mentionedL2Only.size;
|
|
551
|
+
if (mentionedL2Only.size === 0) {
|
|
552
|
+
diagnostics.testCasesWithoutMentionedCustomerIds += 1;
|
|
553
|
+
}
|
|
524
554
|
const mentionedBaseKeys = new Set([...mentionedL2Only].map((code) => this.toRequirementKey(code)).filter((code) => !!code));
|
|
525
555
|
const expectedFamilyCodes = new Set();
|
|
526
556
|
for (const baseKey of mentionedBaseKeys) {
|
|
@@ -597,6 +627,14 @@ class ResultDataProvider {
|
|
|
597
627
|
.join('; ');
|
|
598
628
|
const linkedButNotMentioned = sortedExtraLinked.join('; ');
|
|
599
629
|
const validationStatus = mentionedButNotLinked || linkedButNotMentioned ? 'Fail' : 'Pass';
|
|
630
|
+
if (validationStatus === 'Fail')
|
|
631
|
+
diagnostics.failingRows += 1;
|
|
632
|
+
logger_1.default.debug(`MEWP internal validation parse diagnostics: ` +
|
|
633
|
+
`testCaseId=${testCaseId} parsedSteps=${executableSteps.length} ` +
|
|
634
|
+
`stepsWithMentions=${mentionEntries.length} customerIdsFound=${mentionedL2Only.size} ` +
|
|
635
|
+
`linkedRequirements=${linkedFullCodes.size} mentionedButNotLinked=${sortedMissingMentioned.length + sortedMissingFamily.length} ` +
|
|
636
|
+
`linkedButNotMentioned=${sortedExtraLinked.length} status=${validationStatus} ` +
|
|
637
|
+
`customerIdSample='${[...mentionedL2Only].slice(0, 5).join(', ')}'`);
|
|
600
638
|
rows.push({
|
|
601
639
|
'Test Case ID': testCaseId,
|
|
602
640
|
'Test Case Title': String(testCaseTitleMap.get(testCaseId) || '').trim(),
|
|
@@ -605,6 +643,11 @@ class ResultDataProvider {
|
|
|
605
643
|
'Validation Status': validationStatus,
|
|
606
644
|
});
|
|
607
645
|
}
|
|
646
|
+
logger_1.default.info(`MEWP internal validation summary: testCases=${diagnostics.totalTestCases} ` +
|
|
647
|
+
`parsedSteps=${diagnostics.totalParsedSteps} stepsWithMentions=${diagnostics.totalStepsWithMentions} ` +
|
|
648
|
+
`totalCustomerIdsFound=${diagnostics.totalMentionedCustomerIds} ` +
|
|
649
|
+
`testCasesWithoutCustomerIds=${diagnostics.testCasesWithoutMentionedCustomerIds} ` +
|
|
650
|
+
`failingRows=${diagnostics.failingRows}`);
|
|
608
651
|
return {
|
|
609
652
|
sheetName: this.buildInternalValidationSheetName(planName, testPlanId),
|
|
610
653
|
columnOrder: [...ResultDataProvider.INTERNAL_VALIDATION_COLUMNS],
|
|
@@ -719,7 +762,22 @@ class ResultDataProvider {
|
|
|
719
762
|
return { l3Id: '', l3Title: '', l4Id: '', l4Title: '' };
|
|
720
763
|
}
|
|
721
764
|
buildMewpCoverageL3L4Rows(links) {
|
|
722
|
-
const
|
|
765
|
+
const deduped = new Map();
|
|
766
|
+
for (const item of links || []) {
|
|
767
|
+
const level = (item === null || item === void 0 ? void 0 : item.level) === 'L4' ? 'L4' : 'L3';
|
|
768
|
+
const id = String((item === null || item === void 0 ? void 0 : item.id) || '').trim();
|
|
769
|
+
if (!id)
|
|
770
|
+
continue;
|
|
771
|
+
const key = `${level}:${id}`;
|
|
772
|
+
if (!deduped.has(key)) {
|
|
773
|
+
deduped.set(key, {
|
|
774
|
+
id,
|
|
775
|
+
level,
|
|
776
|
+
title: String((item === null || item === void 0 ? void 0 : item.title) || '').trim(),
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
const sorted = [...deduped.values()].sort((a, b) => {
|
|
723
781
|
if (a.level !== b.level)
|
|
724
782
|
return a.level === 'L3' ? -1 : 1;
|
|
725
783
|
return String(a.id || '').localeCompare(String(b.id || ''));
|
|
@@ -736,12 +794,14 @@ class ResultDataProvider {
|
|
|
736
794
|
}
|
|
737
795
|
return rows;
|
|
738
796
|
}
|
|
739
|
-
buildMewpCoverageRows(requirements, requirementIndex, observedTestCaseIdsByRequirement, linkedRequirementsByTestCase, l3l4ByBaseKey, externalBugsByTestCase) {
|
|
797
|
+
buildMewpCoverageRows(requirements, requirementIndex, observedTestCaseIdsByRequirement, linkedRequirementsByTestCase, l3l4ByBaseKey, externalBugsByTestCase, externalJoinKeysByL2) {
|
|
740
798
|
var _a;
|
|
741
799
|
const rows = [];
|
|
742
800
|
const linkedByRequirement = this.invertBaseRequirementLinks(linkedRequirementsByTestCase);
|
|
801
|
+
const joinKeysByRequirement = externalJoinKeysByL2 || new Map();
|
|
743
802
|
for (const requirement of requirements) {
|
|
744
803
|
const key = String((requirement === null || requirement === void 0 ? void 0 : requirement.baseKey) || this.toRequirementKey(requirement.requirementId) || '').trim();
|
|
804
|
+
const externalJoinKeys = joinKeysByRequirement.get(key) || new Set([key]);
|
|
745
805
|
const linkedTestCaseIds = ((requirement === null || requirement === void 0 ? void 0 : requirement.linkedTestCaseIds) || []).filter((id) => Number.isFinite(id) && Number(id) > 0);
|
|
746
806
|
const linkedByTestCase = key ? Array.from(linkedByRequirement.get(key) || []) : [];
|
|
747
807
|
const observedTestCaseIds = key
|
|
@@ -763,7 +823,7 @@ class ResultDataProvider {
|
|
|
763
823
|
const externalBugs = externalBugsByTestCase.get(testCaseId) || [];
|
|
764
824
|
for (const bug of externalBugs) {
|
|
765
825
|
const bugBaseKey = String((bug === null || bug === void 0 ? void 0 : bug.requirementBaseKey) || '').trim();
|
|
766
|
-
if (bugBaseKey && bugBaseKey
|
|
826
|
+
if (bugBaseKey && !externalJoinKeys.has(bugBaseKey))
|
|
767
827
|
continue;
|
|
768
828
|
const bugId = Number((bug === null || bug === void 0 ? void 0 : bug.id) || 0);
|
|
769
829
|
if (!Number.isFinite(bugId) || bugId <= 0)
|
|
@@ -781,7 +841,7 @@ class ResultDataProvider {
|
|
|
781
841
|
const bugsForRows = runStatus === 'Fail'
|
|
782
842
|
? Array.from(aggregatedBugs.values()).sort((a, b) => a.id - b.id)
|
|
783
843
|
: [];
|
|
784
|
-
const l3l4ForRows = [...(l3l4ByBaseKey.get(
|
|
844
|
+
const l3l4ForRows = [...externalJoinKeys].flatMap((joinKey) => l3l4ByBaseKey.get(joinKey) || []);
|
|
785
845
|
const bugRows = bugsForRows.length > 0
|
|
786
846
|
? bugsForRows
|
|
787
847
|
: [];
|
|
@@ -1456,6 +1516,119 @@ class ResultDataProvider {
|
|
|
1456
1516
|
})
|
|
1457
1517
|
.sort((a, b) => String(a.requirementId).localeCompare(String(b.requirementId)));
|
|
1458
1518
|
}
|
|
1519
|
+
async buildMewpL2ToLinkedL1BaseKeys(requirements, projectName, testData) {
|
|
1520
|
+
const out = new Map();
|
|
1521
|
+
const relatedIds = new Set();
|
|
1522
|
+
const linkedTestCaseIdsByL2 = new Map();
|
|
1523
|
+
const testCaseTitleMap = this.buildMewpTestCaseTitleMap(testData);
|
|
1524
|
+
for (const requirement of requirements || []) {
|
|
1525
|
+
const l2BaseKey = String((requirement === null || requirement === void 0 ? void 0 : requirement.baseKey) || '').trim();
|
|
1526
|
+
if (!l2BaseKey)
|
|
1527
|
+
continue;
|
|
1528
|
+
if (!out.has(l2BaseKey))
|
|
1529
|
+
out.set(l2BaseKey, new Set());
|
|
1530
|
+
if (!linkedTestCaseIdsByL2.has(l2BaseKey))
|
|
1531
|
+
linkedTestCaseIdsByL2.set(l2BaseKey, new Set());
|
|
1532
|
+
for (const testCaseId of (requirement === null || requirement === void 0 ? void 0 : requirement.linkedTestCaseIds) || []) {
|
|
1533
|
+
const numeric = Number(testCaseId);
|
|
1534
|
+
if (Number.isFinite(numeric) && numeric > 0) {
|
|
1535
|
+
linkedTestCaseIdsByL2.get(l2BaseKey).add(numeric);
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
for (const relatedId of (requirement === null || requirement === void 0 ? void 0 : requirement.relatedWorkItemIds) || []) {
|
|
1539
|
+
const id = Number(relatedId);
|
|
1540
|
+
if (Number.isFinite(id) && id > 0)
|
|
1541
|
+
relatedIds.add(id);
|
|
1542
|
+
}
|
|
1543
|
+
}
|
|
1544
|
+
let titleDerivedCount = 0;
|
|
1545
|
+
for (const [l2BaseKey, testCaseIds] of linkedTestCaseIdsByL2.entries()) {
|
|
1546
|
+
const targetSet = out.get(l2BaseKey) || new Set();
|
|
1547
|
+
for (const testCaseId of testCaseIds) {
|
|
1548
|
+
const title = String(testCaseTitleMap.get(testCaseId) || '').trim();
|
|
1549
|
+
if (!title)
|
|
1550
|
+
continue;
|
|
1551
|
+
const fromTitleCodes = this.extractRequirementCodesFromExpectedText(title, false);
|
|
1552
|
+
if (fromTitleCodes.size > 0) {
|
|
1553
|
+
for (const code of fromTitleCodes) {
|
|
1554
|
+
const normalized = this.toRequirementKey(code);
|
|
1555
|
+
if (normalized)
|
|
1556
|
+
targetSet.add(normalized);
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
else {
|
|
1560
|
+
const normalized = this.toRequirementKey(title);
|
|
1561
|
+
if (normalized)
|
|
1562
|
+
targetSet.add(normalized);
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
if (targetSet.size > 0) {
|
|
1566
|
+
titleDerivedCount += 1;
|
|
1567
|
+
}
|
|
1568
|
+
out.set(l2BaseKey, targetSet);
|
|
1569
|
+
}
|
|
1570
|
+
if (relatedIds.size === 0) {
|
|
1571
|
+
const linkedL1Count = [...out.values()].reduce((sum, set) => sum + set.size, 0);
|
|
1572
|
+
logger_1.default.info(`MEWP L2->L1 mapping summary: l2Families=${out.size} ` +
|
|
1573
|
+
`fromTitle=${titleDerivedCount} fallbackFromLinkedL1=0 linkedL1Keys=${linkedL1Count}`);
|
|
1574
|
+
return out;
|
|
1575
|
+
}
|
|
1576
|
+
const relatedWorkItems = await this.fetchWorkItemsByIds(projectName, [...relatedIds], false);
|
|
1577
|
+
const l1BaseByWorkItemId = new Map();
|
|
1578
|
+
for (const workItem of relatedWorkItems || []) {
|
|
1579
|
+
const workItemId = Number((workItem === null || workItem === void 0 ? void 0 : workItem.id) || 0);
|
|
1580
|
+
if (!Number.isFinite(workItemId) || workItemId <= 0)
|
|
1581
|
+
continue;
|
|
1582
|
+
const fields = (workItem === null || workItem === void 0 ? void 0 : workItem.fields) || {};
|
|
1583
|
+
const customerId = this.extractMewpRequirementIdentifier(fields);
|
|
1584
|
+
const baseKey = this.toRequirementKey(customerId);
|
|
1585
|
+
if (!baseKey)
|
|
1586
|
+
continue;
|
|
1587
|
+
l1BaseByWorkItemId.set(workItemId, baseKey);
|
|
1588
|
+
}
|
|
1589
|
+
let linkedFallbackCount = 0;
|
|
1590
|
+
for (const requirement of requirements || []) {
|
|
1591
|
+
const l2BaseKey = String((requirement === null || requirement === void 0 ? void 0 : requirement.baseKey) || '').trim();
|
|
1592
|
+
if (!l2BaseKey)
|
|
1593
|
+
continue;
|
|
1594
|
+
if (!out.has(l2BaseKey))
|
|
1595
|
+
out.set(l2BaseKey, new Set());
|
|
1596
|
+
const targetSet = out.get(l2BaseKey);
|
|
1597
|
+
if (targetSet.size > 0) {
|
|
1598
|
+
continue;
|
|
1599
|
+
}
|
|
1600
|
+
for (const relatedId of (requirement === null || requirement === void 0 ? void 0 : requirement.relatedWorkItemIds) || []) {
|
|
1601
|
+
const baseKey = l1BaseByWorkItemId.get(Number(relatedId));
|
|
1602
|
+
if (baseKey)
|
|
1603
|
+
targetSet.add(baseKey);
|
|
1604
|
+
}
|
|
1605
|
+
if (targetSet.size > 0) {
|
|
1606
|
+
linkedFallbackCount += 1;
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
const l2Families = out.size;
|
|
1610
|
+
const withLinkedL1 = [...out.values()].filter((set) => set.size > 0).length;
|
|
1611
|
+
const linkedL1Count = [...out.values()].reduce((sum, set) => sum + set.size, 0);
|
|
1612
|
+
logger_1.default.info(`MEWP L2->L1 mapping summary: l2Families=${l2Families} withLinkedL1=${withLinkedL1} ` +
|
|
1613
|
+
`fromTitle=${titleDerivedCount} fallbackFromLinkedL1=${linkedFallbackCount} linkedL1Keys=${linkedL1Count}`);
|
|
1614
|
+
return out;
|
|
1615
|
+
}
|
|
1616
|
+
buildMewpExternalJoinKeysByL2Requirement(requirements, l2ToLinkedL1BaseKeys) {
|
|
1617
|
+
const out = new Map();
|
|
1618
|
+
for (const requirement of requirements || []) {
|
|
1619
|
+
const l2BaseKey = String((requirement === null || requirement === void 0 ? void 0 : requirement.baseKey) || '').trim();
|
|
1620
|
+
if (!l2BaseKey)
|
|
1621
|
+
continue;
|
|
1622
|
+
const joinKeys = new Set([l2BaseKey]);
|
|
1623
|
+
for (const l1Key of l2ToLinkedL1BaseKeys.get(l2BaseKey) || []) {
|
|
1624
|
+
const normalized = String(l1Key || '').trim();
|
|
1625
|
+
if (normalized)
|
|
1626
|
+
joinKeys.add(normalized);
|
|
1627
|
+
}
|
|
1628
|
+
out.set(l2BaseKey, joinKeys);
|
|
1629
|
+
}
|
|
1630
|
+
return out;
|
|
1631
|
+
}
|
|
1459
1632
|
buildRequirementFamilyMap(requirements, scopedRequirementKeys) {
|
|
1460
1633
|
const familyMap = new Map();
|
|
1461
1634
|
for (const requirement of requirements || []) {
|