@marcfargas/odoo-cli 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +354 -0
- package/package.json +53 -53
package/README.md
ADDED
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
# `@marcfargas/odoo-cli`
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@marcfargas/odoo-cli)
|
|
4
|
+
[](https://www.gnu.org/licenses/lgpl-3.0)
|
|
5
|
+
|
|
6
|
+
Command-line interface for Odoo ERP — query records, post chatter messages, manage modules, track time, inspect schema, and more. Built on [`@marcfargas/odoo-client`](../odoo-client).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install -g @marcfargas/odoo-cli
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Installs the `odoo` binary (also available as `odoo-cli`).
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Configuration
|
|
21
|
+
|
|
22
|
+
All commands read credentials from environment variables. Set them once in your shell profile:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
export ODOO_URL=https://mycompany.odoo.com
|
|
26
|
+
export ODOO_DB=mycompany
|
|
27
|
+
export ODOO_USERNAME=admin@example.com
|
|
28
|
+
export ODOO_PASSWORD=secret
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
| Variable | Description | CLI flag override |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `ODOO_URL` | Odoo base URL | `--url` |
|
|
34
|
+
| `ODOO_DB` | Database name | `--db` |
|
|
35
|
+
| `ODOO_USERNAME` | Login username | `--user` |
|
|
36
|
+
| `ODOO_PASSWORD` | Password | `--password` |
|
|
37
|
+
|
|
38
|
+
Verify your connection:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
odoo config check
|
|
42
|
+
odoo config show # shows resolved config (password redacted)
|
|
43
|
+
odoo config show --format json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
> **Note:** Prefer environment variables over CLI flags — flags appear in shell history.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Search records with filters
|
|
54
|
+
odoo records search crm.lead --fields id,name,stage_id --limit 20
|
|
55
|
+
odoo records search res.partner --filter active=true --format csv > partners.csv
|
|
56
|
+
|
|
57
|
+
# Post an internal note on a record
|
|
58
|
+
odoo mail note crm.lead 42 "Called customer, following up next week" --confirm
|
|
59
|
+
|
|
60
|
+
# Stream all invoices as newline-delimited JSON
|
|
61
|
+
odoo records search account.move --domain '[("state","=","posted")]' --all --format ndjson \
|
|
62
|
+
> invoices.ndjson
|
|
63
|
+
|
|
64
|
+
# Generate a TypeScript interface for a model
|
|
65
|
+
odoo schema codegen sale.order --out ./types/sale-order.ts
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Commands Reference
|
|
71
|
+
|
|
72
|
+
### `odoo config` — Connection management
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
odoo config check Verify connection and show current user [READ]
|
|
76
|
+
odoo config show Show resolved config (password redacted) [READ]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### `odoo records` — Generic CRUD on any Odoo model
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
odoo records search <model> Filter and list records [READ]
|
|
83
|
+
odoo records get <model> <id> Fetch a single record [READ]
|
|
84
|
+
odoo records count <model> Count matching records [READ]
|
|
85
|
+
odoo records create <model> Create a record [WRITE]
|
|
86
|
+
odoo records write <model> <ids> Update records — batch by comma-separated IDs [WRITE]
|
|
87
|
+
odoo records delete <model> <ids> Delete records [DESTRUCTIVE]
|
|
88
|
+
odoo records call <model> <method> Call an arbitrary model method [WRITE]
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`search` supports rich filtering:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# Odoo domain syntax
|
|
95
|
+
odoo records search sale.order --domain '[("state","=","sale")]'
|
|
96
|
+
|
|
97
|
+
# JSON domain
|
|
98
|
+
odoo records search sale.order --domain-json '[["state","=","sale"]]'
|
|
99
|
+
|
|
100
|
+
# Simple K=V shorthand (ANDed, repeatable)
|
|
101
|
+
odoo records search res.partner --filter active=true --filter country_id.code=ES
|
|
102
|
+
|
|
103
|
+
# Domain from file or stdin
|
|
104
|
+
odoo records search crm.lead --domain-file filter.json
|
|
105
|
+
|
|
106
|
+
# Pagination
|
|
107
|
+
odoo records search res.partner --limit 200 --offset 0 --order "name asc"
|
|
108
|
+
odoo records search account.move --all --page-size 500 # fetches everything, paged
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`call` invokes arbitrary ORM methods:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
odoo records call sale.order action_confirm --ids 42 --confirm
|
|
115
|
+
odoo records call sale.order get_delivery_count --ids 42 --read-only # no --confirm needed
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### `odoo mail` — Chatter messages
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
odoo mail note <model> <id> [message] Post internal note — staff only [WRITE]
|
|
122
|
+
odoo mail post <model> <id> [message] Post public message — notifies followers [WRITE]
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
odoo mail note crm.lead 42 "Meeting rescheduled" --confirm
|
|
127
|
+
odoo mail post sale.order 88 "Your order has shipped" --confirm
|
|
128
|
+
|
|
129
|
+
# HTML body
|
|
130
|
+
odoo mail note project.task 17 "<p>Build <strong>passed</strong></p>" --html --confirm
|
|
131
|
+
|
|
132
|
+
# Read message from file or stdin
|
|
133
|
+
git log --oneline -5 | odoo mail note project.task 17 --message-file - --confirm
|
|
134
|
+
|
|
135
|
+
# With subject and explicit partner notifications
|
|
136
|
+
odoo mail post crm.lead 42 --subject "Contract ready" --partner-ids 7,15 "See attached." --confirm
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### `odoo modules` — Module management
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
odoo modules list List modules [READ]
|
|
143
|
+
odoo modules info <name> Show module metadata [READ]
|
|
144
|
+
odoo modules status <name> Print single-word state — for scripting [READ]
|
|
145
|
+
odoo modules install <name> Install a module [WRITE]
|
|
146
|
+
odoo modules upgrade <name> Upgrade a module [WRITE]
|
|
147
|
+
odoo modules uninstall <name> Uninstall — may remove data [DESTRUCTIVE]
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
odoo modules list --filter installed
|
|
152
|
+
odoo modules list --search sale --format json | jq '.[].technical_name'
|
|
153
|
+
odoo modules status hr_timesheet # prints: installed
|
|
154
|
+
|
|
155
|
+
if [ "$(odoo modules status my_addon)" = "installed" ]; then echo ready; fi
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### `odoo attendance` — Clock in/out *(requires `hr_attendance`)*
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
odoo attendance clock-in Record clock-in [WRITE]
|
|
162
|
+
odoo attendance clock-out Record clock-out [WRITE]
|
|
163
|
+
odoo attendance status Show current attendance status [READ]
|
|
164
|
+
odoo attendance list List records by date range [READ]
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
odoo attendance clock-in --confirm
|
|
169
|
+
odoo attendance status
|
|
170
|
+
odoo attendance list --from 2024-03-11 --to 2024-03-15 --format csv
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Use `--employee-id <n>` or `--employee <name>` to act on behalf of another employee (default: current user).
|
|
174
|
+
|
|
175
|
+
### `odoo timesheets` — Time tracking *(requires `hr_timesheet`)*
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
odoo timesheets start Start a timer [WRITE]
|
|
179
|
+
odoo timesheets stop Stop running timer [WRITE]
|
|
180
|
+
odoo timesheets running Show running timer [READ]
|
|
181
|
+
odoo timesheets log Log time retroactively [WRITE]
|
|
182
|
+
odoo timesheets list List timesheet entries [READ]
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Timer workflow
|
|
187
|
+
odoo timesheets start --task-id 42 --description "Feature work" --confirm
|
|
188
|
+
odoo timesheets running
|
|
189
|
+
odoo timesheets stop --confirm
|
|
190
|
+
|
|
191
|
+
# Manual entry
|
|
192
|
+
odoo timesheets log --task-id 42 --hours 1.5 --description "Review PR" --confirm
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### `odoo accounting` — Read-only accounting queries *(requires `account`)*
|
|
196
|
+
|
|
197
|
+
All commands are READ-only — no `--confirm` required.
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
odoo accounting cash-accounts Discover cash/bank journal accounts
|
|
201
|
+
odoo accounting cash-balance Show balance as-of a date
|
|
202
|
+
odoo accounting posted-moves List posted journal entries
|
|
203
|
+
odoo accounting trace-recon <id> Show reconciliation for a move
|
|
204
|
+
odoo accounting days-to-pay <id> Payment term analysis for an invoice
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
odoo accounting cash-balance --as-of 2024-03-31
|
|
209
|
+
odoo accounting posted-moves --from 2024-01-01 --to 2024-03-31 --format csv
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### `odoo url` — Generate record URLs
|
|
213
|
+
|
|
214
|
+
```
|
|
215
|
+
odoo url record <model> <id> Backend URL [READ]
|
|
216
|
+
odoo url portal <model> <id> Portal URL [READ]
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
URL=$(odoo url record project.task 17)
|
|
221
|
+
odoo mail note project.task 17 "Deployed: $URL" --confirm
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### `odoo schema` — Runtime schema introspection
|
|
225
|
+
|
|
226
|
+
Wraps [`@marcfargas/odoo-introspection`](../odoo-introspection). All commands are READ.
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
odoo schema models List all models
|
|
230
|
+
odoo schema fields <model> List fields for a model
|
|
231
|
+
odoo schema describe <model> Human-readable model summary
|
|
232
|
+
odoo schema codegen <model> Generate TypeScript interface
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
odoo schema models --search sale
|
|
237
|
+
odoo schema fields crm.lead --type many2one
|
|
238
|
+
odoo schema describe res.partner
|
|
239
|
+
odoo schema codegen sale.order --out ./types/sale-order.ts
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### `odoo state` — ⚠ Experimental state management
|
|
243
|
+
|
|
244
|
+
Declare desired Odoo configuration, plan drift, and apply — similar to Terraform. All commands require `--experimental`.
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
odoo state plan <file> Show drift between desired and current [READ]
|
|
248
|
+
odoo state diff <model> Show current state of a model's records [READ]
|
|
249
|
+
odoo state apply <file> Apply desired state [WRITE]
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
odoo state plan ./config.json --experimental
|
|
254
|
+
odoo state apply ./config.json --experimental --confirm
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## Output Formats
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
odoo records search crm.lead --format json # JSON array
|
|
263
|
+
odoo records search crm.lead --format table # ASCII table (default in TTY)
|
|
264
|
+
odoo records search crm.lead --format csv # CSV with header row
|
|
265
|
+
odoo records search crm.lead --format ndjson # Newline-delimited JSON (streaming)
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Auto-detection:** when stdout is a TTY, defaults to `table`; when piped, defaults to `json`.
|
|
269
|
+
|
|
270
|
+
**stdout / stderr split:**
|
|
271
|
+
|
|
272
|
+
- `stdout` — data only (always parseable, safe to pipe)
|
|
273
|
+
- `stderr` — errors, progress messages, warnings
|
|
274
|
+
|
|
275
|
+
This means `odoo records search crm.lead | jq '.[0].name'` always works even in `table` mode, because table output also goes to stdout only when a TTY is detected.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Safety Model
|
|
280
|
+
|
|
281
|
+
Every command has a safety level shown in its description:
|
|
282
|
+
|
|
283
|
+
| Level | What it means | Requirements |
|
|
284
|
+
|---|---|---|
|
|
285
|
+
| **READ** | No data mutation | None — safe to run anywhere |
|
|
286
|
+
| **WRITE** | Creates or updates Odoo records | `--confirm` required |
|
|
287
|
+
| **DESTRUCTIVE** | May permanently delete data | `--confirm` required, warning printed |
|
|
288
|
+
|
|
289
|
+
```bash
|
|
290
|
+
# This will error: --confirm is required
|
|
291
|
+
odoo records create res.partner --data '{"name":"Acme"}'
|
|
292
|
+
|
|
293
|
+
# Correct
|
|
294
|
+
odoo records create res.partner --data '{"name":"Acme"}' --confirm
|
|
295
|
+
|
|
296
|
+
# Preview without executing (no --confirm needed)
|
|
297
|
+
odoo records create res.partner --data '{"name":"Acme"}' --dry-run
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
`--dry-run` prints the RPC call that *would* be executed to stderr and exits without contacting Odoo. Use it to verify commands before committing to mutations.
|
|
301
|
+
|
|
302
|
+
`--read-only` is accepted by `records call` to declare that a method is safe (skips the `--confirm` check).
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Global Flags
|
|
307
|
+
|
|
308
|
+
These flags work on every command:
|
|
309
|
+
|
|
310
|
+
| Flag | Description |
|
|
311
|
+
|---|---|
|
|
312
|
+
| `--format json\|table\|csv\|ndjson` | Output format |
|
|
313
|
+
| `--no-color` | Disable ANSI colors (also: `NO_COLOR` env var) |
|
|
314
|
+
| `-q, --quiet` | Suppress stderr progress and warnings |
|
|
315
|
+
| `-v, --version` | Show version |
|
|
316
|
+
| `-h, --help` | Show help |
|
|
317
|
+
| `--help-extra` | Show extended documentation for a command group |
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Exit Codes
|
|
322
|
+
|
|
323
|
+
| Code | Meaning |
|
|
324
|
+
|---|---|
|
|
325
|
+
| 0 | Success |
|
|
326
|
+
| 1 | Usage error |
|
|
327
|
+
| 2 | Auth / network error |
|
|
328
|
+
| 3 | Not found |
|
|
329
|
+
| 4 | Permission denied |
|
|
330
|
+
| 5 | Validation error |
|
|
331
|
+
| 6 | Conflict |
|
|
332
|
+
| 10 | Partial success |
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## As a Library
|
|
337
|
+
|
|
338
|
+
`odoo-cli` is built on `@marcfargas/odoo-client` for all Odoo communication. If you want to automate Odoo programmatically instead of shelling out:
|
|
339
|
+
|
|
340
|
+
```typescript
|
|
341
|
+
import { createClient } from '@marcfargas/odoo-client';
|
|
342
|
+
|
|
343
|
+
const client = await createClient(); // reads ODOO_* env vars
|
|
344
|
+
const leads = await client.searchRead('crm.lead', [['stage_id.name', '=', 'Won']]);
|
|
345
|
+
await client.mail.postInternalNote('crm.lead', leads[0].id, '<p>Processed by CI</p>');
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
See the [odoo-toolbox monorepo](../../README.md) for the full ecosystem: RPC client, schema introspection, and Odoo knowledge modules.
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## License
|
|
353
|
+
|
|
354
|
+
[LGPL-3.0](./LICENSE) — Marc Fargas
|
package/package.json
CHANGED
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@marcfargas/odoo-cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "CLI for Odoo ERP — records, mail, modules, attendance, timesheets, accounting",
|
|
5
|
-
"main": "dist/cli.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"odoo": "./dist/cli.js",
|
|
8
|
-
"odoo-cli": "./dist/cli.js"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"dist",
|
|
12
|
-
"LICENSE",
|
|
13
|
-
"README.md"
|
|
14
|
-
],
|
|
15
|
-
"scripts": {
|
|
16
|
-
"build": "tsc -b",
|
|
17
|
-
"dev": "tsc -b --watch",
|
|
18
|
-
"test": "vitest run --config vitest.config.ts",
|
|
19
|
-
"test:unit": "vitest run --config vitest.config.ts tests/unit",
|
|
20
|
-
"test:e2e": "vitest run tests/e2e",
|
|
21
|
-
"test:packaging": "vitest run --config vitest.packaging.config.ts"
|
|
22
|
-
},
|
|
23
|
-
"keywords": [
|
|
24
|
-
"odoo",
|
|
25
|
-
"cli",
|
|
26
|
-
"erp",
|
|
27
|
-
"commander",
|
|
28
|
-
"typescript"
|
|
29
|
-
],
|
|
30
|
-
"author": "Marc Fargas <marc@marcfargas.com>",
|
|
31
|
-
"license": "LGPL-3.0",
|
|
32
|
-
"repository": {
|
|
33
|
-
"type": "git",
|
|
34
|
-
"url": "https://github.com/marcfargas/odoo-toolbox.git",
|
|
35
|
-
"directory": "packages/odoo-cli"
|
|
36
|
-
},
|
|
37
|
-
"dependencies": {
|
|
38
|
-
"@marcfargas/odoo-client": "^0.4.
|
|
39
|
-
"@marcfargas/odoo-introspection": "^0.1.3",
|
|
40
|
-
"cli-table3": "^0.6.3",
|
|
41
|
-
"commander": "^12.0.0",
|
|
42
|
-
"debug": "^4.3.4"
|
|
43
|
-
},
|
|
44
|
-
"devDependencies": {
|
|
45
|
-
"@types/debug": "^4.1.12",
|
|
46
|
-
"@types/node": "^20.0.0",
|
|
47
|
-
"typescript": "^5.0.0",
|
|
48
|
-
"vitest": "^4.0.0"
|
|
49
|
-
},
|
|
50
|
-
"publishConfig": {
|
|
51
|
-
"access": "public"
|
|
52
|
-
}
|
|
53
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@marcfargas/odoo-cli",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "CLI for Odoo ERP — records, mail, modules, attendance, timesheets, accounting",
|
|
5
|
+
"main": "dist/cli.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"odoo": "./dist/cli.js",
|
|
8
|
+
"odoo-cli": "./dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"LICENSE",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc -b",
|
|
17
|
+
"dev": "tsc -b --watch",
|
|
18
|
+
"test": "vitest run --config vitest.config.ts",
|
|
19
|
+
"test:unit": "vitest run --config vitest.config.ts tests/unit",
|
|
20
|
+
"test:e2e": "vitest run tests/e2e",
|
|
21
|
+
"test:packaging": "vitest run --config vitest.packaging.config.ts"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"odoo",
|
|
25
|
+
"cli",
|
|
26
|
+
"erp",
|
|
27
|
+
"commander",
|
|
28
|
+
"typescript"
|
|
29
|
+
],
|
|
30
|
+
"author": "Marc Fargas <marc@marcfargas.com>",
|
|
31
|
+
"license": "LGPL-3.0",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/marcfargas/odoo-toolbox.git",
|
|
35
|
+
"directory": "packages/odoo-cli"
|
|
36
|
+
},
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@marcfargas/odoo-client": "^0.4.2",
|
|
39
|
+
"@marcfargas/odoo-introspection": "^0.1.3",
|
|
40
|
+
"cli-table3": "^0.6.3",
|
|
41
|
+
"commander": "^12.0.0",
|
|
42
|
+
"debug": "^4.3.4"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/debug": "^4.1.12",
|
|
46
|
+
"@types/node": "^20.0.0",
|
|
47
|
+
"typescript": "^5.0.0",
|
|
48
|
+
"vitest": "^4.0.0"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
}
|
|
53
|
+
}
|