diff --git a/spp_registry/README.rst b/spp_registry/README.rst
index 4eb0e993..8c2a20e0 100644
--- a/spp_registry/README.rst
+++ b/spp_registry/README.rst
@@ -139,6 +139,19 @@ Dependencies
Changelog
=========
+19.0.2.2.7
+~~~~~~~~~~
+
+- test(registry): make two tests hold when other modules are installed
+ alongside spp_registry, as on every full stack. The unparseable-phone
+ fallback test builds its record with ``new()`` instead of
+ ``create()``, because ``spp_base_common`` overrides ``create()`` to
+ refuse a number containing letters before the registry compute is
+ reached; the unlink-permission tests pin the starter bundles'
+ admin-only registry switch off for their transaction, because it is
+ shipped on and enforced server-side and would refuse the manager the
+ registry rule allows. No behaviour change (#443)
+
19.0.2.2.4
~~~~~~~~~~
diff --git a/spp_registry/__manifest__.py b/spp_registry/__manifest__.py
index 2ed500e3..4c17061b 100644
--- a/spp_registry/__manifest__.py
+++ b/spp_registry/__manifest__.py
@@ -3,7 +3,7 @@
{
"name": "OpenSPP Registry",
"category": "OpenSPP/Core",
- "version": "19.0.2.2.4",
+ "version": "19.0.2.2.7",
"sequence": 1,
"author": "OpenSPP.org",
"website": "https://github.com/OpenSPP/OpenSPP2",
diff --git a/spp_registry/readme/HISTORY.md b/spp_registry/readme/HISTORY.md
index d2f80ecd..c48e1815 100644
--- a/spp_registry/readme/HISTORY.md
+++ b/spp_registry/readme/HISTORY.md
@@ -1,3 +1,7 @@
+### 19.0.2.2.7
+
+- test(registry): make two tests hold when other modules are installed alongside spp_registry, as on every full stack. The unparseable-phone fallback test builds its record with `new()` instead of `create()`, because `spp_base_common` overrides `create()` to refuse a number containing letters before the registry compute is reached; the unlink-permission tests pin the starter bundles' admin-only registry switch off for their transaction, because it is shipped on and enforced server-side and would refuse the manager the registry rule allows. No behaviour change (#443)
+
### 19.0.2.2.4
- fix(registry): refuse a date of birth in the future on every write path. `_birthdate_onchange` only runs in the form UI, so ORM `create`/`write`, CSV/Excel import and API writes (XML-RPC, API v2, DCI) all persisted a future `birthdate` — which the non-stored `age` compute then rendered as a negative number in views, exports and API reads. A stored-field constraint now enforces it server-side, comparing against the user's own today so a registrar east of UTC is not refused a birth recorded earlier that local day, and naming the record and the offending value so a bad row in a bulk import can be found. The onchange is kept as the friendlier silent-reset UX in the form (#362)
diff --git a/spp_registry/static/description/index.html b/spp_registry/static/description/index.html
index 48cfcf7c..68b3bca4 100644
--- a/spp_registry/static/description/index.html
+++ b/spp_registry/static/description/index.html
@@ -518,6 +518,20 @@
+
19.0.2.2.7
+
+- test(registry): make two tests hold when other modules are installed
+alongside spp_registry, as on every full stack. The unparseable-phone
+fallback test builds its record with new() instead of
+create(), because spp_base_common overrides create() to
+refuse a number containing letters before the registry compute is
+reached; the unlink-permission tests pin the starter bundles’
+admin-only registry switch off for their transaction, because it is
+shipped on and enforced server-side and would refuse the manager the
+registry rule allows. No behaviour change (#443)
+
+
+
19.0.2.2.4
- fix(registry): refuse a date of birth in the future on every write
@@ -538,7 +552,7 @@
19.0.2.2.4
SELECT id, display_name, birthdate FROM res_partner WHERE birthdate > CURRENT_DATE;
-
+
19.0.2.2.3
- fix(registry): repair the stored status/is_ended computes on
@@ -562,7 +576,7 @@
19.0.2.2.3
CREATE INDEX CONCURRENTLY IF NOT EXISTS spp_group_membership__ended_date_index ON spp_group_membership (ended_date) WHERE ended_date IS NOT NULL;
-
+
19.0.2.2.2
- fix(registry): let an ID type be used again after its ID was removed.
@@ -574,7 +588,7 @@
19.0.2.2.2
surfacing a database error (#1136)
-
+
19.0.2.2.1
- feat(registry): registry configuration is consolidated into one
@@ -585,7 +599,7 @@
19.0.2.2.1
framework refuses a settings save from anyone else (#1009)
-
+
19.0.2.1.4
- fix(registry): remove the dead @api.constrains("age")
@@ -597,7 +611,7 @@
19.0.2.1.4
dropped
-
+
19.0.2.1.3
- fix(registry): show an ID Status column on the group form
@@ -608,7 +622,7 @@
19.0.2.1.3
(#1110)
-
+
19.0.2.1.1
- fix(views): add reusable x2many_no_padding JS widget that
@@ -618,7 +632,7 @@
19.0.2.1.1
don’t bloat the layout (#943).
-
+
19.0.2.0.0
- Initial migration to OpenSPP2
diff --git a/spp_registry/tests/test_phone_number.py b/spp_registry/tests/test_phone_number.py
index 580ca661..d8325729 100644
--- a/spp_registry/tests/test_phone_number.py
+++ b/spp_registry/tests/test_phone_number.py
@@ -115,8 +115,13 @@ def test_unparseable_phone_falls_back_to_original(self):
Worth flagging: this means ``phone_sanitized`` can hold an
un-E164'd value when parsing fails. If you'd rather it be empty,
the compute needs to filter the fallback explicitly.
+
+ The record is built with ``new()`` rather than ``create()``: this
+ pins the compute of the registry layer alone, and ``spp_base_common``
+ (installed on every full stack) overrides ``create()`` to refuse a
+ number containing letters before the compute is ever reached.
"""
- rec = self.PhoneNumber.create({"partner_id": self.individual_a.id, "phone_no": "abcxyz"})
+ rec = self.PhoneNumber.new({"partner_id": self.individual_a.id, "phone_no": "abcxyz"})
self.assertEqual(rec.phone_sanitized, "abcxyz")
def test_phone_validation_unavailable_returns_original(self):
diff --git a/spp_registry/tests/test_unlink_permissions.py b/spp_registry/tests/test_unlink_permissions.py
index 4e75ab7d..45964cf3 100644
--- a/spp_registry/tests/test_unlink_permissions.py
+++ b/spp_registry/tests/test_unlink_permissions.py
@@ -13,6 +13,7 @@
from odoo.exceptions import AccessError
from odoo.tests import tagged
+from ..models.res_config_settings import _LEGACY_KEYS
from .common import RegistryCommon
@@ -21,6 +22,16 @@ class TestRegistrantUnlinkPermissions(RegistryCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
+ # These tests pin spp_registry's own rule (officer blocked, manager
+ # allowed). The starter bundles layer a stricter switch on top —
+ # registrant create/write/unlink for admins only, shipped ON and
+ # enforced server-side since #411 — which would refuse the manager
+ # here whenever such a bundle is installed in the same database. Pin
+ # it off for this transaction; the guard reads the parameter live and
+ # the change rolls back with the test (precedent: spp_mis_demo_v2's
+ # access-control tests, OP#1142).
+ for key in _LEGACY_KEYS:
+ cls.env["ir.config_parameter"].sudo().set_param(key, "False")
cls.target = cls.Partner.create({"name": "Deletable Partner", "is_registrant": True, "is_group": False})
def _target_for(self, user):