Update BuildEase demo skill (session 2026-09-21 edits)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DywdYrFTrWa4h1T3ZykPBX
This commit is contained in:
glenn
2026-09-21 14:30:07 +02:00
co-authored by Claude Opus 5
parent 5aee1c61b5
commit f7e43d7210
3 changed files with 46 additions and 30 deletions
+13 -11
View File
@@ -146,8 +146,8 @@ and each statement gets its own copy carrying **that period's** index. This is w
Three traps, each of which cost a debugging round:
- **The rows are generated by an `@api.onchange`.** The list is `create="0" delete="0"` in
the form, so there is no button and no create path — and `write()` over XML-RPC does not
fire onchanges, so nothing appears. Every field on `formula.input` is a plain **stored**
the form, so there is no button and no create path — and `write()` over the external API
does not fire onchanges, so nothing appears. Every field on `formula.input` is a plain **stored**
field (readonly in the UI only), so write them directly, `weight_parameter` included.
- **Set `is_revision = True` on the take-off first.** `revision_scheme_id` is
`invisible="not is_revision"`, and `revision_formula_ids` computes off the *inputs*, not
@@ -210,12 +210,12 @@ need to delete the order separately, only to have cancelled it.
**A take-off with no sale order *can* be cancelled and deleted.** `cancel()` writes
`state = "cancel"` directly and then calls `action_cancel()` on `sale_order_id` — an empty
recordset when there is no order, and in Odoo 19 `sale.order.action_cancel` is
`self.write({'state': 'cancel'})` with no `ensure_one()`, so it is a clean no-op. Over
XML-RPC:
`self.write({'state': 'cancel'})` with no `ensure_one()`, so it is a clean no-op. Through
the substrate's `x()` helper:
```python
x("quantity.take.off", "cancel", [qto_id]) # works with or without a sale order
x("quantity.take.off", "unlink", [qto_id]) # now passes the state == 'cancel' check
x("quantity.take.off", "cancel", qto_ids) # works with or without a sale order
x("quantity.take.off", "unlink", qto_ids) # now passes the state == 'cancel' check
```
This supersedes the older "convert it to a quotation first, then cancel that" workaround,
@@ -239,11 +239,13 @@ already-draft invoice, and the `unlink` beneath it never runs. Then run the whol
loop until a pass keeps nothing — cascades free records that the previous pass could not
touch.
**Button methods return an action dict Odoo cannot marshal over XML-RPC.**
`action_cancel`, `action_approved`, `action_price_revision`, `create_invoices` and friends
all raise a `Fault` whose text mentions `Marshal`/`dumps`. **The method already ran and
committed** — only the response failed. Catch that specific fault and continue; retrying
re-runs the transition and will fail the second time on a state guard.
**Button methods return an action dict, not `True`.** `action_cancel`, `action_approved`,
`action_price_revision`, `create_invoices` and friends all hand back a window action. Over
JSON-2 that serialises fine, so the dict is neither an error nor proof the transition
landed — read the state back. On a legacy XML-RPC connection the same dict raises a `Fault`
whose text mentions `Marshal`/`dumps`: **the method already ran and committed**, only the
response failed, so catch that specific fault and continue. Never retry — the second run
hits a state guard and reads like a real error.
---