Skip to content

fix(spp_registry): registry UX polish (#942)#174

Open
emjay0921 wants to merge 3 commits into19.0from
fix/942-registry-ux-polish
Open

fix(spp_registry): registry UX polish (#942)#174
emjay0921 wants to merge 3 commits into19.0from
fix/942-registry-ux-polish

Conversation

@emjay0921
Copy link
Copy Markdown
Contributor

Why is this change needed?

OpenProject #942 — three small registry UX issues observed while reviewing the group + member overview:

  1. Tab orderLocation was rendering before Financial Information on the Profile tab, contradicting the intended bottom-of-page placement.
  2. Membership Types label — column header read Membership Types; the agreed wording (already used in the Philippines demo override) is Group Role.
  3. Empty vocabularies still rendered — when an admin archives all codes in urn:openspp:vocab:group-type or urn:openspp:vocab:group-membership-type, the corresponding form field (Group Type) and list column (Group Role) were still rendered as empty selectors / blank tag cells.

The original ticket also included a registry role-based menu audit; that was split out into #951 so it can ship independently.

How was the change implemented?

Three commits, one per item:

  • ad51f8d8spp_registrant_gis/views/res_partner_views.xml — change the xpath insertion target from phone_section / group_phone_section to financial_section / group_financial_section so Location renders after Financial Information on both the individual and group profile tabs.
  • 09ed95ddspp_registry/models/group_membership.py (master string=) plus 4 view files where the column was explicitly relabeled. Also bumped the inconsistent string="Role:" in spp_registry_group_hierarchy/views/group_views.xml to Group Role: for consistency. Field name membership_type_ids unchanged — only the user-visible label.
  • 0a708fba — two narrow computed booleans on res.partner (has_group_type_codes, has_group_membership_type_codes) plus a mirror compute on spp.group.membership for the standalone tree view. Each compute is a single sudo'd search_count against its vocabulary's namespace, returning a boolean (no vocab content leaks). Views gate group_type_id with invisible="not has_group_type_codes" and the membership_type_ids column with column_invisible="not parent.has_group_membership_type_codes" (or column_invisible="not has_group_membership_type_codes" on the standalone tree).

New unit tests

None — the changes are pure label edits and view conditionals, no new logic worth testing in isolation. Existing spp_registry test suite still passes (no regressions).

Unit tests executed by the author

docker compose run … -i spp_registry --test-tags /spp_registry
docker compose run … -i spp_registrant_gis --test-tags /spp_registrant_gis

Both runs return 0 failed, 0 error(s) (spp_registry currently has no tagged tests; spp_registrant_gis has 4 — all pass).

CI-local pre-commit (./ci-local/run.sh OpenSPP2 --files …) passes on every modified file.

How to test manually

QA guides for each item are posted as comments on #942:

  • Item 1 — view-only round, just Apps → upgrade spp_registrant_gis and check tab order on a registrant's Profile.
  • Item 2 — restart + upgrade, then confirm Group Role label everywhere Membership Types used to appear.
  • Item 3 — archive all codes in urn:openspp:vocab:group-type / urn:openspp:vocab:group-membership-type via Settings → Vocabularies → Manage Vocabularies → Codes smart button, and verify both the Group Type field and the Group Role column disappear; re-activate one code and they reappear.

Related links

…mpty (#942 item 3)

Two narrow computes on res.partner (has_group_type_codes,
has_group_membership_type_codes) plus a mirror compute on
spp.group.membership for the standalone tree view.

Group Type form field on the Group form is now invisible when the
urn:openspp:vocab:group-type vocabulary has no active codes.

Group Role column on the Members and Group Membership lists is now
column_invisible when urn:openspp:vocab:group-membership-type has no
active codes — the embedded lists read parent.has_group_membership_type_codes
from res.partner; the standalone tree reads the field directly off the
membership record.

Both fields reappear automatically as soon as a code is added or
re-activated.
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 reorders fields in the registrant profile, renames 'Membership Types' to 'Group Role', and introduces logic to conditionally hide group-related fields and columns when their respective vocabularies are empty. Feedback is provided regarding the use of the limit argument in search_count calls within the group.py and group_membership.py models, as this argument is not supported by the method and will result in a TypeError at runtime.

Comment on lines +72 to +79
has_codes = bool(
self.env["spp.vocabulary.code"] # nosemgrep: odoo-sudo-without-context
.sudo()
.search_count(
[("vocabulary_id.namespace_uri", "=", "urn:openspp:vocab:group-membership-type")],
limit=1,
)
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The search_count method in Odoo does not accept a limit argument. Passing limit=1 will result in a TypeError at runtime. To efficiently check for the existence of at least one record, use search() with limit=1 instead. Note: This non-deterministic search (using limit=1 without order) is acceptable here but should be acknowledged as technical debt to be addressed if the context changes.

Suggested change
has_codes = bool(
self.env["spp.vocabulary.code"] # nosemgrep: odoo-sudo-without-context
.sudo()
.search_count(
[("vocabulary_id.namespace_uri", "=", "urn:openspp:vocab:group-membership-type")],
limit=1,
)
)
has_codes = bool(
self.env["spp.vocabulary.code"] # nosemgrep: odoo-sudo-without-context
.sudo()
.search(
[("vocabulary_id.namespace_uri", "=", "urn:openspp:vocab:group-membership-type")],
limit=1,
)
)
References
  1. A non-deterministic database search (using search with limit=1 but no order) can be acceptable if the practical context makes it functionally deterministic, but it should be acknowledged as technical debt.

Comment on lines +85 to +92
has_codes = bool(
self.env["spp.vocabulary.code"] # nosemgrep: odoo-sudo-without-context
.sudo()
.search_count(
[("vocabulary_id.namespace_uri", "=", "urn:openspp:vocab:group-type")],
limit=1,
)
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The search_count method does not support the limit parameter. This will cause a TypeError. Use search() with limit=1 to perform an efficient existence check. This non-deterministic search is acceptable but should be acknowledged as technical debt to be addressed if the context changes.

Suggested change
has_codes = bool(
self.env["spp.vocabulary.code"] # nosemgrep: odoo-sudo-without-context
.sudo()
.search_count(
[("vocabulary_id.namespace_uri", "=", "urn:openspp:vocab:group-type")],
limit=1,
)
)
has_codes = bool(
self.env["spp.vocabulary.code"] # nosemgrep: odoo-sudo-without-context
.sudo()
.search(
[("vocabulary_id.namespace_uri", "=", "urn:openspp:vocab:group-type")],
limit=1,
)
)
References
  1. A non-deterministic database search (using search with limit=1 but no order) can be acceptable if the practical context makes it functionally deterministic, but it should be acknowledged as technical debt.

Comment on lines +42 to +49
has_codes = bool(
self.env["spp.vocabulary.code"] # nosemgrep: odoo-sudo-without-context
.sudo()
.search_count(
[("vocabulary_id.namespace_uri", "=", "urn:openspp:vocab:group-membership-type")],
limit=1,
)
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

In Odoo, search_count does not accept a limit argument. This implementation will fail with a TypeError. Please use search() with limit=1 for an optimized existence check. This approach is non-deterministic without an explicit order and should be acknowledged as technical debt to be addressed if the context changes.

Suggested change
has_codes = bool(
self.env["spp.vocabulary.code"] # nosemgrep: odoo-sudo-without-context
.sudo()
.search_count(
[("vocabulary_id.namespace_uri", "=", "urn:openspp:vocab:group-membership-type")],
limit=1,
)
)
has_codes = bool(
self.env["spp.vocabulary.code"] # nosemgrep: odoo-sudo-without-context
.sudo()
.search(
[("vocabulary_id.namespace_uri", "=", "urn:openspp:vocab:group-membership-type")],
limit=1,
)
)
References
  1. A non-deterministic database search (using search with limit=1 but no order) can be acceptable if the practical context makes it functionally deterministic, but it should be acknowledged as technical debt.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.48%. Comparing base (98a45a9) to head (0a708fb).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             19.0     #174   +/-   ##
=======================================
  Coverage   71.48%   71.48%           
=======================================
  Files         932      932           
  Lines       54840    54840           
=======================================
  Hits        39201    39201           
  Misses      15639    15639           
Flag Coverage Δ
spp_analytics 93.13% <ø> (ø)
spp_api_v2 80.10% <ø> (ø)
spp_api_v2_change_request 66.85% <ø> (ø)
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_approval 50.29% <ø> (ø)
spp_area 80.07% <ø> (ø)
spp_area_hdx 81.43% <ø> (ø)
spp_audit 72.60% <ø> (ø)
spp_banking 80.00% <ø> (ø)
spp_base_common 90.26% <ø> (ø)
spp_base_setting 50.00% <ø> (ø)
spp_programs 64.51% <ø> (ø)
spp_security 66.66% <ø> (ø)

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

🚀 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.

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.

1 participant