🎯 Core Issue:
Soft delete based on detected value change assumes continuity, but some cases involve disappearance, movement, or transformation that wouldn’t trigger expiration.
- Project earned value: Measures can shift across time or phases but still belong to the same concept.
- Invoice accounting: Amounts may be amended, reallocated, or withdrawn entirely (e.g. credit notes, reversals).
- Activity sequencing: If a value “moves”, it’s not necessarily a change — it’s a context shift.
🔍 Risks of the Current Approach
| Scenario | Problem |
|---|---|
| Value disappears entirely | You keep the last-seen value forever unless a new version overwrites |
| Value moves to another key | The old one is retained, and the new one appears as duplicate context |
| Periodic reporting gaps | Reporting shows a “stale” value that’s no longer present |
| Multi-row summaries (earned value) | Partial values may cause duplication, under/over-reporting |
✅ Recommended Pattern: Row Presence Verification (RPV)
Introduce a process step that verifies expected presence for certain value types. Instead of only watching for changes, you ask: “Should this value still exist in this context?”
🔄 How it Works
- During your ingestion or transformation phase:
- Build a set of expected active keys based on the latest source snapshot.
- Compare with current
ACTIVE_FLAG = 1rows.
- For any active row where the key no longer exists, and there’s no matching replacement:
- Expire it deliberately (with a reason =
'missing_from_source') - Or flag it for review (
AUDIT_FLAG = 1,EXPIRY_REASON = 'unexpected_absence')
- Expire it deliberately (with a reason =
🧩 Technical Implementation Suggestions
1. Presence Check Table
A temp table holding object_seq, attribute, expected_this_period = 1
Then join against *_values or *_meta to find orphaned active rows.
2. Add an EXPIRY_REASON Field
Extend your templates to track why a row was expired:
value_changedsource_disappearedmanual_overridearchived_due_to_period_end
3. Run Periodic Reconciliation
Schedule a job (or make part of pipeline post-step) that checks:
ACTIVE_FLAG = 1rows not found in current snapshot- Log/report the anomalies before automatically expiring
🛡️ Why This Matters
Without this safeguard, your model assumes “absence = unchanged”, which is brittle for:
- Currency-based values that consolidate over time
- Earned value measures that change source frequency
- Reconciliations that back-date or remove items from systems like ERP or timesheet engines