Skip to content

feat(spp_api_v2): auto-assign system_id to registrants for API addressability#162

Draft
pmigueld wants to merge 15 commits into19.0from
fix/api-v2-skip-records-without-identifiers
Draft

feat(spp_api_v2): auto-assign system_id to registrants for API addressability#162
pmigueld wants to merge 15 commits into19.0from
fix/api-v2-skip-records-without-identifiers

Conversation

@pmigueld
Copy link
Copy Markdown

@pmigueld pmigueld commented Apr 15, 2026

Summary

The web UI allows creating registrants without identity documents, but the V2 API requires at least one identifier to address records. Records without identifiers were invisible to the API — they couldn't be searched, referenced in memberships, or synced to external systems like DataCollect.

This PR auto-generates a system-level registry ID (UUID) for every registrant at creation time. This is not an identity document — it's an internal addressability key, similar to a partner ID but exposed safely through the API without leaking sequential database IDs.

Changes

  • New vocabulary code system_id under urn:openspp:vocab:id-type — distinguishes system IDs from real identity documents (national_id, passport, etc.)
  • Auto-assignment on createres.partner.create override generates a UUID registry ID for new registrants
  • Backfill on install — post-init hook assigns system_id to all existing registrants that lack one
  • Membership referencesmembership_utils.py uses id_type_id.uri (full code URI) instead of namespace_uri for identifier lookup
  • Graceful handlingto_api_schema returns None with a warning for records that somehow still lack identifiers (safety net)

Context

Confirmed with OpenSPP team: identity documents being required in the API but not in the web UI is a bug. The NO database IDs exposed design constraint in to_api_schema means we cannot use partner.id as a fallback — hence the UUID-based approach using the existing vocabulary/registry system.

Test plan

  • Create a registrant via web UI without any ID documents → verify system_id auto-assigned in registry
  • Search via API → verify registrant appears with system_id identifier
  • Existing registrants without IDs → verify backfill assigns system_id on module upgrade
  • Create registrant with national_id → verify both national_id and system_id present
  • DataCollect external sync → verify all registrants now pullable

🤖 Generated with Claude Code

@pmigueld pmigueld requested a review from jeremi April 15, 2026 06:33
@cursor
Copy link
Copy Markdown

cursor bot commented Apr 15, 2026

You have used all of your free Bugbot PR reviews.

To receive reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the to_api_schema and membership_to_response methods to return None and log a warning instead of raising a ValidationError when external identifiers are missing. Corresponding null checks have been added to the search routers and the get_groups service. Review feedback highlights the need for more robust identifier selection to prevent malformed API references and warns of potential crashes in single-resource endpoints that have not yet been updated to handle the new None return value.

Comment thread spp_api_v2/services/membership_utils.py Outdated
Comment thread spp_api_v2/services/membership_utils.py Outdated
Comment thread spp_api_v2/services/group_service.py
Comment thread spp_api_v2/services/individual_service.py
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 15, 2026

Codecov Report

❌ Patch coverage is 81.90476% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.63%. Comparing base (1f4203c) to head (385a127).
⚠️ Report is 4 commits behind head on 19.0.

Files with missing lines Patch % Lines
spp_api_v2/__init__.py 73.68% 5 Missing ⚠️
spp_api_v2/models/res_partner_system_id.py 82.75% 5 Missing ⚠️
spp_api_v2/services/membership_utils.py 63.63% 4 Missing ⚠️
spp_api_v2/models/spp_registry_id_system.py 57.14% 3 Missing ⚠️
spp_api_v2/routers/program_membership.py 50.00% 1 Missing ⚠️
..._change_request/services/change_request_service.py 75.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             19.0     #162      +/-   ##
==========================================
+ Coverage   71.36%   71.63%   +0.26%     
==========================================
  Files         932      935       +3     
  Lines       54792    55413     +621     
==========================================
+ Hits        39101    39693     +592     
- Misses      15691    15720      +29     
Flag Coverage Δ
spp_api_v2 80.23% <82.17%> (+0.13%) ⬆️
spp_api_v2_change_request 66.29% <75.00%> (-0.57%) ⬇️
spp_api_v2_cycles 71.12% <ø> (ø)
spp_api_v2_data 64.41% <ø> (ø)
spp_api_v2_entitlements 70.19% <ø> (ø)
spp_api_v2_gis 71.52% <ø> (ø)
spp_api_v2_products 66.27% <ø> (ø)
spp_api_v2_service_points 70.94% <ø> (ø)
spp_api_v2_simulation 71.12% <ø> (ø)
spp_api_v2_vocabulary 57.26% <ø> (ø)
spp_base_common 90.26% <ø> (ø)
spp_dci_client_dr 55.66% <ø> (-0.21%) ⬇️
spp_dci_client_ibr 60.17% <ø> (ø)
spp_dci_demo 69.23% <ø> (ø)
spp_dci_server 35.68% <ø> (ø)
spp_farmer_registry_demo 54.01% <ø> (+0.62%) ⬆️
spp_mis_demo_v2 74.07% <ø> (+4.05%) ⬆️
spp_programs 64.33% <ø> (+0.73%) ⬆️
spp_security 66.66% <ø> (ø)
spp_starter_social_registry 0.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
spp_api_v2/__manifest__.py 0.00% <ø> (ø)
spp_api_v2/models/__init__.py 100.00% <100.00%> (ø)
spp_api_v2/routers/bulk.py 100.00% <ø> (ø)
spp_api_v2/routers/filter.py 29.91% <ø> (ø)
spp_api_v2/routers/group.py 74.36% <100.00%> (+0.42%) ⬆️
spp_api_v2/routers/individual.py 77.54% <100.00%> (+0.24%) ⬆️
spp_api_v2/services/group_service.py 85.04% <100.00%> (+0.26%) ⬆️
spp_api_v2/services/individual_service.py 72.46% <100.00%> (+0.71%) ⬆️
spp_api_v2/services/program_membership_service.py 93.37% <100.00%> (+1.37%) ⬆️
spp_api_v2/routers/program_membership.py 74.30% <50.00%> (+1.06%) ⬆️
... and 5 more

... and 14 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pmigueld pmigueld marked this pull request as draft April 15, 2026 06:42
@pmigueld pmigueld marked this pull request as ready for review April 15, 2026 09:01
@pmigueld pmigueld marked this pull request as draft April 17, 2026 03:47
@pmigueld pmigueld changed the title fix(spp_api_v2): skip records without identifiers instead of crashing feat(spp_api_v2): auto-assign system_id to registrants for API addressability Apr 17, 2026
@pmigueld pmigueld force-pushed the fix/api-v2-skip-records-without-identifiers branch from f3177c2 to e4fc7bc Compare April 17, 2026 07:11
@pmigueld pmigueld marked this pull request as ready for review April 17, 2026 07:20
@pmigueld pmigueld marked this pull request as draft April 17, 2026 07:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants