T3276 relational mapping ambiguity - #2128
Conversation
…grades The recurring.invoicer model was removed from compassion-accounting, but its cleanup companion (T3284) never landed on 18.0, leaving a stale ACL row and menu item in sponsorship_compassion that crash any full module load. Mirrors the already-authored fix sitting unmerged on T3284-Remove-recurring-invoicer-object.
…mappings Generic JSON-to-Odoo mapping picks the first matching record for a Many2one relational field, with no way to narrow the search or react when several records match (e.g. two users named the same). Adds two fields on compassion.field.to.json: - relational_domain_restrict: optional domain to narrow the search for an existing relational record. - many2one_multiple_match_policy: take the first match (default, current behavior) or raise an error when several records match. Also adds a "Check for duplicates" action that scans the real target model/field for existing duplicate values, and a dedicated "Many2one Fields to Review" list (Message Center > Configuration) flattening every Many2one relational lookup across all mappings for review. Impact verification of the ~97 existing Many2one lookups and any resulting mapping changes are tracked separately.
Confidence Score: 4/5
What T-Rex did
|
| duplicate_groups = self.env[target_model]._read_group( | ||
| domain=[(search_field, "!=", False)], | ||
| groupby=[search_field], | ||
| aggregates=["__count"], | ||
| having=[("__count", ">", 1)], | ||
| ) |
There was a problem hiding this comment.
Duplicate check does not match runtime lookup
The duplicate-check action groups exact target values and only filters out falsy values. Runtime resolution also uses a case-insensitive =ilike fallback and applies relational_domain_restrict. As a result, values such as ABC and abc are not shown as duplicates even though one runtime lookup matches both records, while an exact duplicate that the configured restriction narrows to one record is still reported. Apply the same effective domain and case-insensitive matching semantics in the diagnostic so its review results reflect the records conversion can actually resolve.
Artifacts
Focused executable source-pinned check for the diagnostic and runtime lookup mismatch
- The authored minimal Python check asserts the reviewed source contains both query shapes and executes case-only and domain-restriction reproductions, confirming the mismatch.
Output from the focused PR 2128 diagnostic and runtime check
- Running the focused check exited 0 and shows the diagnostic disagrees with runtime for both case-only values and a domain-excluded duplicate, confirming the defect.
T3276 — Improve odoo message center json to odoo conversion
Problem
When GMC Connect sends a JSON message, textual values that map to a
Many2one field are resolved by a generic search on the target model. If more than one record
matches, the code silently takes the first one found — there was no way to
narrow the search or to be warned when the match is ambiguous.
What changed
models/field_to_json.py: two new fields oncompassion.field.to.json:relational_domain_restrict(Char, domain expression) — AND-ed intothe search whenever a relational lookup is performed, regardless of
field type.
many2one_multiple_match_policy(Selectionfirst_match/raise,default
first_match) — only meaningful for Many2one fields; when setto
raise,_search_for_relational_valuesnow raises aUserErrorif the search returns more than one record instead of silently taking
records[:1].action_check_duplicate_matches(): a self-service diagnostic thatscans the real current data of the target model/field for existing
duplicate values (
_read_group+having __count > 1), so anyone cancheck whether a given lookup is actually ambiguous today without DB
access.
relational_comodel_name/relational_ttype: technicalrelatedfields (not
compute+store) exposing the target model/type for theview and the diagnostic — deliberately not stored
computefields,see "Bugs found" below.
views/compassion_mapping_view.xml: exposes the two new fields (Many2onepolicy only shown for Many2one fields) and a "Check for duplicates"
button on the field-to-json form; adds a dedicated flattened list +
menu, Message Center → Configuration → Many2one Fields to Review,
showing all Many2one relational lookups across every mapping in one
screen (previously only reachable by opening each mapping individually).
Default policy is
first_matchfor all existing rows — no behaviorchange for any existing mapping until someone explicitly reviews and
changes a specific field.
Unrelated fix bundled in (separate commit)
[T3284] Remove stale recurring.invoicer references blocking module upgrades—sponsorship_compassion/security/ir.model.access.csvandviews/sponsorship_contract_view.xml. Discovered thatorigin/18.0itself currently crashes on any full module load:
recurring.invoicerwasremoved from
compassion-accounting, but its cleanup companion (ticketT3284) never got merged — it's sitting on its own unmerged branch,
T3284-Remove-recurring-invoicer-object. This commit mirrors thatalready-authored fix exactly, scoped to unblock this branch.
T3284's own PR still needs to be merged so this isn't needed again on
the next fresh branch off
18.0.Impact verification — deferred, not done in this PR
The ticket's own acceptance criteria calls for reviewing all existing
Many2one relational mappings and deciding, field by field, whether they
need a domain restriction and/or the
raisepolicy, decisions are being made separately.Once decisions are made, the actual mapping change needs to go into the
relevant module's
static/mappings/*.jsonfile (the real source oftruth —
compassion.mapping.load_from_json()deletes and recreates allof a mapping's
compassion.field.to.jsonrows from that file on everyreload), then reloaded via
-u <module>or the "Import GMC MappingWizard" (Message Center → Configuration). Editing the field directly in
the UI is useful for testing but does not persist across a reload.
How to test manually
PrimaryOwneron "Hold Creation") → Check forduplicates. With no duplicates, get a green "No ambiguity found"
notification. With duplicates (tested live against
CompassNeedKeyand`PrimaryHoldOwner), get a list of the actual
matching records.
Domain RestrictandMatch Policyonly show for Many2one fields with
search_relational_recordenabled;non-relational rows (e.g.
HoldID) show neither.