Skip to content

Fix: RTR sets INVESTIGATION.INV_STATE_CASE_ID fallback - #985

Closed
ericnagel wants to merge 4 commits into
mainfrom
en/APP-803-STATE_CASE_ID
Closed

Fix: RTR sets INVESTIGATION.INV_STATE_CASE_ID fallback#985
ericnagel wants to merge 4 commits into
mainfrom
en/APP-803-STATE_CASE_ID

Conversation

@ericnagel

@ericnagel ericnagel commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Fix: Restore NULL behavior for missing investigation identifiers (STATE_CASE_ID bug)

Problem

PR #910 (June 22, 2026) inadvertently introduced a bug where contact investigations without real ODSE act_id rows were being assigned synthetic state case IDs derived from the investigation's local ID. This broke the expected MasterETL behavior where investigations without a real state case ID should have INV_STATE_CASE_ID = NULL.

Root Cause of PR #910 Bug

PR #910 added fallback logic to handle variable act_id_seq positions. While the Java transformer was improved to match identifiers by type_cd (not fixed positions), the SQL stored procedure injected a synthetic STATE act_id row:

UNION ALL
SELECT phc_fallback.public_health_case_uid AS [id],
       0 AS [act_id_seq],
       phc_fallback.record_status_cd AS [record_status],
       phc_fallback.local_id AS [root_extension_txt],  -- ← BUG: uses local_id as state case ID
       'STATE' AS [type_cd],
       'Local Public Health Case Identifier' AS [type_desc_txt],
       ...
FROM nbs_odse.dbo.public_health_case phc_fallback
WHERE phc_fallback.public_health_case_uid = phc.public_health_case_uid
  AND phc_fallback.local_id IS NOT NULL
  AND NOT EXISTS (SELECT 1 FROM nbs_odse.dbo.act_id ... WHERE ... type_cd = 'STATE')

This fallback was intended to handle edge cases but created fake identifiers for investigations like contacts that legitimately have no state case ID.

Solution

This PR removes the synthetic fallback behavior and restores the expected NULL handling through two complementary changes:

1. SQL Layer Fix (Stored Procedure)

Removed:

  • The synthetic STATE fallback UNION ALL block
  • The COALESCE that filled NULL root_extension_txt with phc.local_id for STATE rows

Result: Only real ODSE act_id rows are included in the JSON payload. Investigations without a real state case ID now correctly get NULL instead of a synthetic value.

2. Java Layer Defensive Filter

Added a safety check to ignore any synthetic or non-meaningful rows (those with act_id_seq <= 0):

// Ignore synthetic or non-meaningful rows such as fallback rows with act_id_seq = 0.
// Only real act_id rows should be considered for downstream case-id fields.
if (actIdSeq <= 0) {
  continue;
}

Testing

Added 8 new comprehensive unit tests covering missing scenarios, bringing total act_id transformation test coverage to 12 tests. Tests validate behavior for all combinations of identifier presence/absence and edge cases.

Test Coverage Matrix

Test Case STATE CITY LEGACY Description
testTransformActIdsExtractsByTypeCdRegardlessOfSequence ✅ seq 7 ✅ seq 9 ✅ seq 11 All present, non-standard sequences
testTransformActIdsIgnoresSyntheticFallbackStateRows ❌ seq 0 ✅ seq 2 ❌ absent Synthetic rows (seq ≤ 0) filtered
testTransformActIdsLegacyCaseIdNullWhenNoLegacyRow ✅ seq 1 ✅ seq 2 ❌ absent LEGACY missing → NULL
testTransformActIdsUsesLatestSequenceWhenMultipleLegacyRowsExist ❌ absent ❌ absent ✅ seq 30 (max) Multiple rows → uses highest seq
testTransformActIdsEmptyArrayAllFieldsNull ❌ absent ❌ absent ❌ absent CRITICAL: Contact investigations (0 rows)
testTransformActIdsStateNullWhenNoStateRow ❌ absent ✅ seq 1 ✅ seq 2 STATE missing → NULL
testTransformActIdsCityNullWhenNoCityRow ✅ seq 1 ❌ absent ✅ seq 3 CITY missing → NULL
testTransformActIdsMultipleStateRowsUsesHighestSequence ✅ seq 15 (max) ❌ absent ❌ absent Multiple STATE rows → uses highest
testTransformActIdsMultipleCityRowsUsesHighestSequence ❌ absent ✅ seq 12 (max) ❌ absent Multiple CITY rows → uses highest
testTransformActIdsBlankRootExtensionTxtIgnored ❌ blank ✅ "GA-CITY-001" ❌ blank Whitespace/blank values skipped
testTransformActIdsAllTypesAbsentAllFieldsNull ❌ other ❌ other ❌ other Unknown types only → all NULL
testTransformActIdsMixedPresenceAndAbsence ✅ seq 1 ✅ seq 2 ❌ absent Mixed scenario validation

Bold rows = newly added tests

Impact

  • ✅ Contact investigations now correctly have NULL identifiers instead of synthetic local_id values
  • ✅ Restores MasterETL behavior and backward compatibility
  • ✅ Fully tested with 100% coverage for all identifier type combinations
  • ✅ Defensive filtering prevents any future synthetic row regressions

Related Issues

Additional Notes

N/A

Checklist

  • I have ensured that the pull request is of a manageable size, allowing it to be reviewed within a single session.
  • I have reviewed my changes to ensure they are clear, concise, and well-documented.
  • I have updated the documentation, if applicable.
  • I have added or updated test cases to cover my changes, if applicable.

@ericnagel
ericnagel marked this pull request as ready for review August 10, 2026 16:22
@ericnagel
ericnagel requested a review from a team as a code owner August 10, 2026 16:22
@ericbuckley

Copy link
Copy Markdown
Contributor

any reason to not merge this fix into rel-7.13?

@ericnagel

Copy link
Copy Markdown
Contributor Author

any reason to not merge this fix into rel-7.13?

@ericbuckley not that I can think of. I'll retarget it.

@ericnagel
ericnagel changed the base branch from main to rel-7.13 August 10, 2026 19:20
@ericnagel
ericnagel changed the base branch from rel-7.13 to main August 10, 2026 19:22
@ericnagel
ericnagel marked this pull request as draft August 10, 2026 19:22
@ericnagel ericnagel closed this Aug 10, 2026
@ericnagel
ericnagel deleted the en/APP-803-STATE_CASE_ID branch August 10, 2026 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants