Verify the skill against Odoo 20.0 and note what changed
Odoo 20.0 (FINAL) is on GitHub. Every v19 field the skill relies on (group_ids, privilege_id, is_storable, credit-limit fields, stock_fleet dispatch fields) is unchanged; the JSON-2 connector already speaks the v20 API. Real deltas: the RPC db service is gone, custom-module security is a single ir.access.csv, binary fields have a new RPC shape. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
adb6ebe25f
commit
9876f6ba10
@@ -57,9 +57,9 @@ same-named fork silently shadows upstream depending on install order.
|
||||
|
||||
`scripts/creds.json` and `scripts/demo_config.json` are gitignored — they hold client API keys. Keep it that way.
|
||||
|
||||
## Read this before touching Odoo 19
|
||||
## Read this before touching Odoo 19/20
|
||||
|
||||
Several core fields were renamed in v19 (`res.users.group_ids`, `res.groups` lost `category_id`, etc.), credit limit is **warning-only** natively, and fleet load-by-weight needs `stock_fleet`. All the footguns are in [`reference/odoo19-field-gotchas.md`](reference/odoo19-field-gotchas.md) so you don't relearn them the hard way.
|
||||
Several core fields were renamed in v19 (`res.users.group_ids`, `res.groups` lost `category_id`, etc. — still true on v20, which additionally replaces `ir.model.access.csv` with `ir.access.csv` in custom modules), credit limit is **warning-only** natively, and fleet load-by-weight needs `stock_fleet`. All the footguns are in [`reference/odoo19-field-gotchas.md`](reference/odoo19-field-gotchas.md) so you don't relearn them the hard way.
|
||||
|
||||
## Files
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: callista-odoo-demo
|
||||
description: Build a complete, client-tailored Odoo demo end to end — assembles the discovery brief from any source (transcript, notes, email, Knowcap, or a live interview), researches native-vs-custom per hero feature, stands up a LIVE Odoo database over the Odoo 19 JSON-2 API (modules + realistic data + working heroes), tests it, and generates the sales docs and the post-demo follow-through set (objection sheet, scoped quote, timeline, SOW). Use when prepping an Odoo sales demo, POC, or proof-of-value, or when writing the follow-up after one. Triggers: "build an Odoo demo", "demo DB for <client>", "Odoo proof of concept", "stand up a demo before the meeting", "write the follow-up after the demo".
|
||||
description: Build a complete, client-tailored Odoo demo end to end — assembles the discovery brief from any source (transcript, notes, email, Knowcap, or a live interview), researches native-vs-custom per hero feature, stands up a LIVE Odoo database over the Odoo 19/20 JSON-2 API (modules + realistic data + working heroes), tests it, and generates the sales docs and the post-demo follow-through set (objection sheet, scoped quote, timeline, SOW). Use when prepping an Odoo sales demo, POC, or proof-of-value, or when writing the follow-up after one. Triggers: "build an Odoo demo", "demo DB for <client>", "Odoo proof of concept", "stand up a demo before the meeting", "write the follow-up after the demo".
|
||||
---
|
||||
|
||||
# Callista Odoo Demo
|
||||
@@ -130,7 +130,7 @@ An extending skill may insert its own tier ahead of native — see [Extension po
|
||||
### Connect
|
||||
|
||||
Use `scripts/odoo_connect.py`. It speaks **JSON-2** (`POST /json/2/<model>/<method>`, API key
|
||||
as a bearer token) — Odoo 19's external API. `/xmlrpc`, `/xmlrpc/2` and `/jsonrpc` are all
|
||||
as a bearer token) — the Odoo 19/20 external API. `/xmlrpc`, `/xmlrpc/2` and `/jsonrpc` are all
|
||||
deprecated and disappear in Odoo 22; do not write execute_kw calls.
|
||||
|
||||
Print `version()["version"]` to confirm the major version (field names differ across versions
|
||||
@@ -244,7 +244,8 @@ Rules:
|
||||
Portable to any Odoo, no deploy.
|
||||
- **Custom module only if needed:** generate a minimal module, push to the instance's git
|
||||
(Odoo.sh) or hand it to the user to deploy, then install + test. Keep modules tiny and
|
||||
version-correct.
|
||||
version-correct: on v20 security is one `security/ir.access.csv` (no `ir.model.access.csv`,
|
||||
no `ir.rule`); on v19 it is still `ir.model.access.csv`. Check `version()` first.
|
||||
- Example hero (credit hard-block + manager override): override `sale.order.action_confirm`
|
||||
to raise `UserError` when `partner.credit + amount_total > credit_limit` unless the user
|
||||
is in an approver group; add an "Override" button gated to that group.
|
||||
@@ -406,7 +407,7 @@ Rules for the boundary:
|
||||
- Never hand over an environment holding test records. Purge them and read back the counts;
|
||||
do not settle for "cancelled and archived" and do not write leftovers off as a note.
|
||||
- Never send anything client-facing without the user reading it first.
|
||||
- Read `reference/odoo19-field-gotchas.md` before touching Odoo 19 — several core fields
|
||||
- Read `reference/odoo19-field-gotchas.md` before touching Odoo 19/20 — several core fields
|
||||
were renamed.
|
||||
- `discovery_brief.md`, `demo_config.json` and the follow-through docs hold client data and
|
||||
API keys — keep them in the project directory, never in a scratchpad you'd forget.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Odoo 19 (Enterprise) — field names & footguns
|
||||
# Odoo 19 / 20 (Enterprise) — field names & footguns
|
||||
|
||||
Hard-won notes from a real v19 demo build. Check these before you waste a build cycle. Always confirm the major version first: `version()["version"]`.
|
||||
Hard-won notes from a real v19 demo build, re-verified against the Odoo 20.0 source (released 2026-09-17). Everything below holds on v20 unless a **v20** note says otherwise. Check these before you waste a build cycle. Always confirm the major version first: `version()["version"]`.
|
||||
|
||||
## Renamed core fields (these break v17/v18 code)
|
||||
| Concept | v17/18 | **v19** |
|
||||
@@ -11,6 +11,12 @@ Hard-won notes from a real v19 demo build. Check these before you waste a build
|
||||
|
||||
A custom module that sets `category_id` on `res.groups` or `groups_id` on `res.users` will fail to install on v19 with `Invalid field ... / Cannot ...`. Drop the category or use `privilege_id`.
|
||||
|
||||
## v20-only changes (verified on the 20.0 branch)
|
||||
- **Custom-module security:** `security/ir.model.access.csv` + `ir.rule` records are replaced by ONE `security/ir.access.csv` (model `ir.access`, merges ACLs and record rules). Columns: `id,name,model_id,group_id/id,operation,domain` — `operation` is a subset of `crud`, `domain` is optional. A v19 module shipping `ir.model.access.csv` will not install on v20.
|
||||
- **Binary fields over RPC:** `write` accepts `{"file_name": ..., "content": ...}` on binary fields and `web_read` no longer returns base64 blobs; `bin_size` context is gone. Only matters if you upload logos/images — this skill doesn't.
|
||||
- **RPC `db` service removed** (`/xmlrpc/db`, `/jsonrpc` service `db`). Use `/web/database/*` or JSON-2 (`res.lang`, `res.country`). The connector never used it.
|
||||
- Field renames from v19 (`group_ids`, `privilege_id`, `is_storable`, credit-limit fields, `stock_fleet` dispatch fields) are unchanged in v20.
|
||||
|
||||
## fields_get returns null attributes over RPC (some v19 builds)
|
||||
`fields_get([], {"attributes": ["string","type"]})` may return each field with `string=None`. The **keys (technical names) are still correct** — match on keys, not labels. (`fields_named()` in `odoo_connect.py` does this.)
|
||||
|
||||
@@ -43,7 +49,7 @@ A custom module that sets `category_id` on `res.groups` or `groups_id` on `res.u
|
||||
- `stock.picking.button_validate` can return a wizard dict (`stock.backorder.confirmation`, immediate transfer) instead of `True` — create the wizard from `res_model`/`context` and call its `process` button.
|
||||
|
||||
## RPC helper footgun
|
||||
- v19's API is **JSON-2** (`POST /json/2/<model>/<method>`, `Authorization: bearer <api key>`). `/xmlrpc`, `/xmlrpc/2` and `/jsonrpc` still work but are deprecated and go away in Odoo 22.
|
||||
- v19's API is **JSON-2** (`POST /json/2/<model>/<method>`, `Authorization: bearer <api key>`). `/xmlrpc`, `/xmlrpc/2` and `/jsonrpc` still work but are deprecated: `db` service gone in Odoo 20, the rest in Odoo 22.
|
||||
- **No positional arguments exist.** ids go in the `ids` body key, everything else under the ORM parameter's own name: `domain`, `fields`, `vals` (write), `vals_list` (create), `context`, `limit`. Wrong name = `TypeError` from the server, not a silent misread — but guessing still costs a round trip. Every model+method signature for YOUR database is published at `<ODOO_URL>/doc`.
|
||||
- The old execute_kw footgun (a context dict passed positionally landing in `offset` → `psycopg2 can't adapt type 'dict'`) is gone with the endpoint. If you see it, you are on legacy code.
|
||||
- **One call, one transaction.** Committed on success, discarded on error, and nothing chains across calls. Prefer a single method that does the whole job (`search_read`, `action_confirm`) over a sequence you orchestrate client-side.
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
"""Generic Odoo JSON-2 connector for callista-odoo-demo.
|
||||
|
||||
Odoo 19's external API is **JSON-2**: `POST /json/2/<model>/<method>`, authenticated
|
||||
with an API key as a bearer token. The old `/xmlrpc`, `/xmlrpc/2` and `/jsonrpc`
|
||||
endpoints (services common / db / object) are all deprecated and scheduled for removal
|
||||
in Odoo 22. https://www.odoo.com/documentation/19.0/developer/reference/external_api.html
|
||||
Odoo 19+ (incl. 20) external API is **JSON-2**: `POST /json/2/<model>/<method>`,
|
||||
authenticated with an API key as a bearer token. The old `/xmlrpc`, `/xmlrpc/2` and
|
||||
`/jsonrpc` endpoints are deprecated: the `db` service is already gone in Odoo 20,
|
||||
`common`/`object` go in Odoo 22.
|
||||
https://www.odoo.com/documentation/master/developer/reference/external_api.html
|
||||
|
||||
Three things differ from execute_kw, and they bite:
|
||||
1. No uid, no password. The API key alone identifies the user.
|
||||
@@ -93,7 +94,7 @@ def x(model, method, ids=None, timeout=600, **kwargs):
|
||||
|
||||
|
||||
def version():
|
||||
"""Server version — {"version_info": [19, 0, ...], "version": "19.0"}."""
|
||||
"""Server version — {"version_info": [20, 0, ...], "version": "20.0"} (or 19.0)."""
|
||||
req = urllib.request.Request(f"{URL}/web/version")
|
||||
with urllib.request.urlopen(req, timeout=30) as r:
|
||||
return json.load(r)
|
||||
|
||||
Reference in New Issue
Block a user