fix(registry): let a removed ID type be used again - #437
Open
emjay0921 wants to merge 2 commits into
Open
Conversation
Removing an ID through a change request keeps the record and marks it Invalid rather than deleting it. Two separate checks counted that dead row, so once an ID had been removed the registrant was left with an Invalid ID and no way to add a valid one of the same type — which defeats the point of the Remove action. Both had to change; fixing either alone still leaves the user stuck. UNIQUE(partner_id, id_type_id) on spp.registry.id becomes a partial unique index over rows WHERE status IS DISTINCT FROM 'invalid'. A table constraint cannot express the condition. IS DISTINCT FROM rather than != is what keeps a NULL status blocking: those are IDs added straight through the registry, which are live records, not removed ones. The change request add path searched for any ID of the type regardless of status and refused on the strength of it. It now looks for a live one, so the Remove-then-Add sequence the ticket describes completes. Uniqueness is asserted before the write rather than through @api.constrains. Constraints run on flush, by which point the INSERT has already hit the index and the user sees a raw psycopg UniqueViolation instead of a sentence naming the ID type. The index stays as the race-safe guarantee. Covers the spec exactly: a live ID still reserves its type, an ID with no status still reserves its type, successive removals leave several Invalid rows behind without blocking, and flipping an Invalid row back to valid while a live one exists is refused. Note for upgrades: init() drops the old constraint explicitly rather than relying on the ORM noticing it is no longer declared, so an existing database needs spp_registry upgraded, not merely restarted. OP#1136
…-after-cr-removal
emjay0921
marked this pull request as ready for review
August 18, 2026 08:01
Comment on lines
+102
to
+108
| self.env.cr.execute( | ||
| f""" | ||
| CREATE UNIQUE INDEX IF NOT EXISTS {self._UNIQUE_ACTIVE_INDEX} | ||
| ON spp_registry_id (partner_id, id_type_id) | ||
| WHERE status IS DISTINCT FROM 'invalid' | ||
| """ | ||
| ) |
| ] | ||
| if exclude_id: | ||
| domain.append(("id", "!=", exclude_id)) | ||
| clash = self.sudo().search(domain, limit=1) |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## 19.0 #437 +/- ##
==========================================
+ Coverage 72.24% 72.69% +0.45%
==========================================
Files 419 560 +141
Lines 29813 38397 +8584
==========================================
+ Hits 21539 27914 +6375
- Misses 8274 10483 +2209
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why is this change needed?
Removing an ID through a change request keeps the record and marks it Invalid rather than deleting it. Two separate checks counted that dead row, so once an ID had been removed the registrant was left with an Invalid ID and no way to add a valid one of the same type — which defeats the point of the Remove action (OP#1136).
Both checks had to change; fixing either alone still leaves the user stuck.
How was the change implemented?
UNIQUE(partner_id, id_type_id)onspp.registry.idbecomes a partial unique index over rowsWHERE status IS DISTINCT FROM 'invalid'. A table constraint cannot express the condition.IS DISTINCT FROMrather than!=is what keeps a NULL status blocking: those are IDs added straight through the registry, which are live records, not removed ones.@api.constrains. Constraints run on flush, by which point the INSERT has already hit the index and the user sees a raw psycopgUniqueViolationinstead of a sentence naming the ID type. The index stays as the race-safe guarantee.Note for upgrades:
init()drops the old constraint explicitly rather than relying on the ORM noticing it is no longer declared, so an existing database needsspp_registryupgraded, not merely restarted.New unit tests
spp_registry/tests/test_reg_id.py— a live ID still reserves its type, an ID with no status still reserves its type, successive removals leave several Invalid rows behind without blocking, and flipping an Invalid row back to valid while a live one exists is refused.spp_change_request_v2/tests/test_update_id_strategy.py— the add path accepts a type whose only existing row is Invalid, and still refuses one with a live row.Unit tests executed by the author
Run per module, the way CI's matrix does, on this branch after merging
19.0in:spp_registry— 250 tests, 0 failed, 0 errorsspp_change_request_v2— 331 tests, 0 failed, 0 errorsHow to test manually
Related links