feat(fusion_claims): service-booking wizard live client search + address autocomplete
The wizard's dynamic fields were non-functional: the "Existing customer" box had
no search (no endpoint, no handler — the typed string was only sent on submit),
and address autocomplete never attached (google_address_autocomplete.js patches
FormController, which a client action is not).
Live client search:
- new jsonrpc endpoint /fusion_claims/service_booking/search_customers — searches
res.partner (name/phone/email) and resolves a typed SO number to its partner.
- JS: debounced (250ms) onCustSearch -> .sb-cust-results dropdown; pickCustomer()
sets state.partnerId + fills the contact, which action_book_from_wizard already
consumes for cust_mode='existing'.
- FIELD-SAFE domain: res.partner has NO `mobile` field in Odoo 19 — referencing it
raises ValueError and the swallowed exception made the search silently return
nothing. Build the OR domain only over fields in Partner._fields. Smoke-tested on
prod data ('25450'->1, '1 905-'->8).
Address autocomplete (wizard-local):
- component loads Google Places (key = ICP fusion_claims.google_maps_api_key, which
IS configured on westin), attaches via useRef('root')+onMounted/onPatched to every
input.sb-addr-input, writes street/city/lat/lng into reactive state. Fully guarded
(per-input _sbAc, _addrStarted/_addrNoKey gate, .catch on both hooks) so a missing
key degrades to manual entry and can never break render.
Verified: pyflakes clean, JS node --check, SCSS compiles, XML well-formed, dropdown
UI rendered against Bootstrap+compiled CSS. Documented in fusion_claims/CLAUDE.md §48.
Bump fusion_claims 19.0.9.6.0 -> 19.0.9.7.0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3141,3 +3141,35 @@ column → 46px navbar + `.o_action_manager{flex:1;min-height:0}` so the wizard'
|
||||
`height:100%;overflow:auto` scrolls) at 320/390/768/1280, and read computed
|
||||
`grid-template-columns` / `margin-left` / `display`. A standalone vanilla-Bootstrap repro is
|
||||
**not** faithful — it rendered fine and falsely cleared the bug.
|
||||
|
||||
## 48. Service Booking wizard — dynamic fields (live client search + address autocomplete), v19.0.9.7.0
|
||||
|
||||
The wizard is a **client action** (registered OWL component), not a form view, so two
|
||||
"type-ahead" features had to be built into the component itself:
|
||||
|
||||
1. **Live client search** ("Existing customer" box). Endpoint
|
||||
`/fusion_claims/service_booking/search_customers` (jsonrpc, auth=user) searches
|
||||
`res.partner` and resolves a typed SO number to its partner; the JS debounces (250 ms),
|
||||
shows a `.sb-cust-results` dropdown, and `pickCustomer()` sets `state.partnerId` + fills the
|
||||
contact fields. The backend (`action_book_from_wizard`) already consumes `partner_id` for
|
||||
`cust_mode='existing'`, so picking links the existing contact.
|
||||
**GOTCHA (cost a near-miss): `res.partner` has NO `mobile` field in Odoo 19** — a domain
|
||||
leaf `('mobile','ilike',q)` raises `ValueError: Invalid field res.partner.mobile`, and
|
||||
because the controller's `except` swallows it the search silently returns nothing (looks
|
||||
exactly like "search not working"). Build the OR domain only over fields present in
|
||||
`Partner._fields` (`name`/`phone`/`email`); same for reading `p.mobile`. Verify any new
|
||||
partner-field reference against `_fields` before shipping.
|
||||
|
||||
2. **Address autocomplete.** `google_address_autocomplete.js` patches `FormController` only,
|
||||
so it does **not** reach this client action. The component loads Google Places itself
|
||||
(key from ICP `fusion_claims.google_maps_api_key`), attaches via `useRef('root')` +
|
||||
`onMounted`/`onPatched` to every `input.sb-addr-input`, and writes
|
||||
`street`/`city`/`lat`/`lng` straight into reactive `state` (no DOM hacks — we're inside the
|
||||
component). Re-attach on patch is guarded by an `_sbAc` flag per input and an `_addrStarted`
|
||||
/`_addrNoKey` gate so a missing key just degrades to manual entry and can never break render
|
||||
(both lifecycle calls are `.catch(()=>{})`).
|
||||
|
||||
**Verifying the search without a browser:** the endpoint logic is plain ORM — smoke it in an
|
||||
`odoo shell` against real data (`Partner.search(<built domain>, limit=8)`); a vanilla repro of
|
||||
the `.sb-cust-results` dropdown markup + compiled CSS confirms the UI. Address autocomplete
|
||||
needs the live key + Google Maps, so it can only be confirmed in a real browser session.
|
||||
|
||||
Reference in New Issue
Block a user