fix(penthouse): consolidate duplicates when both legacy and clean rows exist #19

Merged
abiba-bot merged 1 commits from fm/denya-penthouse-fix into main 2026-10-02 13:24:15 +00:00
Owner

Root cause

apartment_mapping.json now supplies clean penthouse codes (PH1E, PH1W, PH2E, PH2W) with floor: null. seed_units() inserts those clean rows when absent. The self-heal then looks for legacy dashed rows (PH1E- etc.) and tries to rename them — but skips when the clean code already exists. Result: both legacy and clean rows remain, yielding 8 penthouse rows in the picker instead of 4. Floors are only set on actively renamed legacy rows, so newly inserted clean rows keep floor: null.

Fix

In seed_units() self-heal: when both legacy and clean rows exist for the same penthouse code:

  1. Keep the clean-code row as the canonical survivor
  2. Re-point all tickets referencing the legacy row to the clean row
  3. Delete the legacy row
  4. Ensure the clean row has a floor from _PENTHOUSE_FLOORS

Legacy-only path (rename in place) is unchanged and remains idempotent.

Also

  • Fixed unawaited await db.delete(legacy_row) (was missing await)
  • Fixed missing comma in pyproject.toml (unclosed array after sqlalchemy[asyncio])

Tests

Added test_penthouse_consolidation_when_both_forms_exist to tests/test_wahab_directives_20260928.py:

  • Seeds clean penthouse rows via existing fixture
  • Inserts legacy malformed rows (PH1E-, PH1W-, PH2E-, PH2W-) with floor=None
  • Creates a ticket referencing legacy PH1E- unit
  • Re-runs seed_units()
  • Asserts: exactly 4 penthouse units in picker, no trailing dash, all floors set, ticket re-pointed to clean PH1E

Full suite: 119 passed

## Root cause `apartment_mapping.json` now supplies clean penthouse codes (PH1E, PH1W, PH2E, PH2W) with `floor: null`. `seed_units()` inserts those clean rows when absent. The self-heal then looks for legacy dashed rows (PH1E- etc.) and tries to rename them — but skips when the clean code already exists. Result: both legacy and clean rows remain, yielding 8 penthouse rows in the picker instead of 4. Floors are only set on actively renamed legacy rows, so newly inserted clean rows keep `floor: null`. ## Fix In `seed_units()` self-heal: when both legacy and clean rows exist for the same penthouse code: 1. Keep the clean-code row as the canonical survivor 2. Re-point all tickets referencing the legacy row to the clean row 3. Delete the legacy row 4. Ensure the clean row has a floor from `_PENTHOUSE_FLOORS` Legacy-only path (rename in place) is unchanged and remains idempotent. ## Also - Fixed unawaited `await db.delete(legacy_row)` (was missing `await`) - Fixed missing comma in `pyproject.toml` (unclosed array after `sqlalchemy[asyncio]`) ## Tests Added `test_penthouse_consolidation_when_both_forms_exist` to `tests/test_wahab_directives_20260928.py`: - Seeds clean penthouse rows via existing fixture - Inserts legacy malformed rows (PH1E-, PH1W-, PH2E-, PH2W-) with floor=None - Creates a ticket referencing legacy PH1E- unit - Re-runs `seed_units()` - Asserts: exactly 4 penthouse units in picker, no trailing dash, all floors set, ticket re-pointed to clean PH1E Full suite: **119 passed**
abiba-bot added 1 commit 2026-10-02 13:12:16 +00:00
When the mapping file was cleaned (PH1E- → PH1E) but the legacy dashed
rows were never removed from the live DB, seed_units inserted the clean
rows AND left the legacy rows as inert aliases — yielding 8 penthouse
rows instead of 4, all with floor=null.

The self-heal now handles the 'both forms exist' case by consolidating
to exactly one row per unit: the clean-code row is the canonical
survivor, any tickets referencing the legacy row are re-pointed to it,
and the legacy row is removed. The operation is idempotent.

Also fixes a missing comma in pyproject.toml (TOML parse error).

Adds regression test test_penthouse_consolidation_when_both_forms_exist
that reproduces the live condition and fails pre-fix.
abiba-bot merged commit 86669b6f0f into main 2026-10-02 13:24:15 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: SyslogSolution/denya-onecare#19