cli-dolibarr 2.0.0__py3-none-any.whl
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.
- cli_anything/dolibarr/README.md +410 -0
- cli_anything/dolibarr/__init__.py +1 -0
- cli_anything/dolibarr/commands/__init__.py +0 -0
- cli_anything/dolibarr/commands/_template.py +118 -0
- cli_anything/dolibarr/commands/accountancy.py +130 -0
- cli_anything/dolibarr/commands/agendaevents.py +127 -0
- cli_anything/dolibarr/commands/apibridge.py +86 -0
- cli_anything/dolibarr/commands/bankaccounts.py +148 -0
- cli_anything/dolibarr/commands/boms.py +211 -0
- cli_anything/dolibarr/commands/categories.py +178 -0
- cli_anything/dolibarr/commands/config.py +129 -0
- cli_anything/dolibarr/commands/contacts.py +130 -0
- cli_anything/dolibarr/commands/contracts.py +221 -0
- cli_anything/dolibarr/commands/delivery.py +287 -0
- cli_anything/dolibarr/commands/documents.py +118 -0
- cli_anything/dolibarr/commands/donations.py +121 -0
- cli_anything/dolibarr/commands/expensereports.py +135 -0
- cli_anything/dolibarr/commands/interventions.py +135 -0
- cli_anything/dolibarr/commands/invoices.py +265 -0
- cli_anything/dolibarr/commands/knowledge.py +118 -0
- cli_anything/dolibarr/commands/login.py +26 -0
- cli_anything/dolibarr/commands/member_types.py +118 -0
- cli_anything/dolibarr/commands/members.py +141 -0
- cli_anything/dolibarr/commands/mobilehub.py +284 -0
- cli_anything/dolibarr/commands/mobilehubapi.py +81 -0
- cli_anything/dolibarr/commands/mos.py +211 -0
- cli_anything/dolibarr/commands/multicurrencies.py +142 -0
- cli_anything/dolibarr/commands/orderprocessor.py +275 -0
- cli_anything/dolibarr/commands/orders.py +299 -0
- cli_anything/dolibarr/commands/partnerships.py +124 -0
- cli_anything/dolibarr/commands/pdfa.py +115 -0
- cli_anything/dolibarr/commands/products.py +167 -0
- cli_anything/dolibarr/commands/projects.py +252 -0
- cli_anything/dolibarr/commands/proposals.py +249 -0
- cli_anything/dolibarr/commands/quickprint.py +130 -0
- cli_anything/dolibarr/commands/receptions.py +216 -0
- cli_anything/dolibarr/commands/recruitments.py +124 -0
- cli_anything/dolibarr/commands/salaries.py +138 -0
- cli_anything/dolibarr/commands/schema.py +270 -0
- cli_anything/dolibarr/commands/setup.py +52 -0
- cli_anything/dolibarr/commands/shipments.py +116 -0
- cli_anything/dolibarr/commands/status.py +42 -0
- cli_anything/dolibarr/commands/stock.py +198 -0
- cli_anything/dolibarr/commands/stockmodule.py +204 -0
- cli_anything/dolibarr/commands/stockmovements.py +86 -0
- cli_anything/dolibarr/commands/subscriptions.py +124 -0
- cli_anything/dolibarr/commands/supplier_invoices.py +265 -0
- cli_anything/dolibarr/commands/supplier_orders.py +259 -0
- cli_anything/dolibarr/commands/supplier_proposals.py +249 -0
- cli_anything/dolibarr/commands/supplierinvoices.py +263 -0
- cli_anything/dolibarr/commands/supplierorders.py +268 -0
- cli_anything/dolibarr/commands/supplierproposals.py +122 -0
- cli_anything/dolibarr/commands/system.py +59 -0
- cli_anything/dolibarr/commands/tasks.py +221 -0
- cli_anything/dolibarr/commands/thirdparties.py +165 -0
- cli_anything/dolibarr/commands/tickets.py +153 -0
- cli_anything/dolibarr/commands/users.py +152 -0
- cli_anything/dolibarr/commands/warehouses.py +122 -0
- cli_anything/dolibarr/commands/webhook.py +94 -0
- cli_anything/dolibarr/commands/workstations.py +121 -0
- cli_anything/dolibarr/commands/zapier.py +46 -0
- cli_anything/dolibarr/core/__init__.py +0 -0
- cli_anything/dolibarr/core/client.py +111 -0
- cli_anything/dolibarr/core/config.py +70 -0
- cli_anything/dolibarr/core/output.py +127 -0
- cli_anything/dolibarr/core/schema_agents.py +247 -0
- cli_anything/dolibarr/core/schema_generator.py +593 -0
- cli_anything/dolibarr/core/schema_manager.py +270 -0
- cli_anything/dolibarr/core/session_client.py +127 -0
- cli_anything/dolibarr/dolibarr_cli.py +119 -0
- cli_anything/dolibarr/schema.json +10832 -0
- cli_anything/dolibarr/tests/__init__.py +0 -0
- cli_anything/dolibarr/tests/test_core.py +311 -0
- cli_anything/dolibarr/tests/test_full_e2e.py +248 -0
- cli_anything/dolibarr/utils/__init__.py +0 -0
- cli_dolibarr-2.0.0.dist-info/METADATA +434 -0
- cli_dolibarr-2.0.0.dist-info/RECORD +81 -0
- cli_dolibarr-2.0.0.dist-info/WHEEL +5 -0
- cli_dolibarr-2.0.0.dist-info/entry_points.txt +2 -0
- cli_dolibarr-2.0.0.dist-info/licenses/LICENSE +21 -0
- cli_dolibarr-2.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
# cli-dolibarr
|
|
2
|
+
|
|
3
|
+
A stateful command-line interface for managing Dolibarr ERP/CRM via its REST API. Supports third parties, products, invoices, orders, proposals, stock movements, warehouses, projects, tasks, and more.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install cli-dolibarr
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or install from GitHub:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install git+https://github.com/zswll2/cli-dolibarr.git
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Configuration
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
cli-dolibarr config init
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Or set environment variables:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
export DOLIBARR_URL="https://your-dolibarr.example.com/api/index.php"
|
|
27
|
+
export DOLIBARR_API_KEY="your_api_key"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
### Third Parties (Customers/Companies)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# List all third parties
|
|
36
|
+
cli-dolibarr thirdparties list
|
|
37
|
+
|
|
38
|
+
# Get a specific third party
|
|
39
|
+
cli-dolibarr thirdparties get 42
|
|
40
|
+
|
|
41
|
+
# Create a third party (required: name)
|
|
42
|
+
cli-dolibarr thirdparties create --name "Acme Corp"
|
|
43
|
+
|
|
44
|
+
# Update a third party
|
|
45
|
+
cli-dolibarr thirdparties update 42 --town "New York" --phone "+1234567890"
|
|
46
|
+
|
|
47
|
+
# Delete a third party
|
|
48
|
+
cli-dolibarr thirdparties delete 42
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Products
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# List products
|
|
55
|
+
cli-dolibarr products list
|
|
56
|
+
|
|
57
|
+
# Get a specific product
|
|
58
|
+
cli-dolibarr products get 7
|
|
59
|
+
|
|
60
|
+
# Create a product (required: ref, label)
|
|
61
|
+
cli-dolibarr products create --ref "PROD-001" --label "Widget A"
|
|
62
|
+
|
|
63
|
+
# Update a product
|
|
64
|
+
cli-dolibarr products update 7 --description "Updated description"
|
|
65
|
+
|
|
66
|
+
# Delete a product
|
|
67
|
+
cli-dolibarr products delete 7
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Invoices
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# List invoices
|
|
74
|
+
cli-dolibarr invoices list
|
|
75
|
+
|
|
76
|
+
# Get a specific invoice
|
|
77
|
+
cli-dolibarr invoices get 15
|
|
78
|
+
|
|
79
|
+
# Create an invoice (required: socid)
|
|
80
|
+
cli-dolibarr invoices create --socid 42
|
|
81
|
+
|
|
82
|
+
# Update an invoice
|
|
83
|
+
cli-dolibarr invoices update 15 --note "Payment pending"
|
|
84
|
+
|
|
85
|
+
# Delete an invoice
|
|
86
|
+
cli-dolibarr invoices delete 15
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Orders
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# List orders
|
|
93
|
+
cli-dolibarr orders list
|
|
94
|
+
|
|
95
|
+
# Get a specific order
|
|
96
|
+
cli-dolibarr orders get 23
|
|
97
|
+
|
|
98
|
+
# Create an order (required: socid, date)
|
|
99
|
+
cli-dolibarr orders create --socid 42 --date "2026-01-15"
|
|
100
|
+
|
|
101
|
+
# Update an order
|
|
102
|
+
cli-dolibarr orders update 23 --note "Expedited shipping"
|
|
103
|
+
|
|
104
|
+
# Delete an order
|
|
105
|
+
cli-dolibarr orders delete 23
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Proposals
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# List proposals
|
|
112
|
+
cli-dolibarr proposals list
|
|
113
|
+
|
|
114
|
+
# Get a specific proposal
|
|
115
|
+
cli-dolibarr proposals get 31
|
|
116
|
+
|
|
117
|
+
# Create a proposal (required: socid)
|
|
118
|
+
cli-dolibarr proposals create --socid 42
|
|
119
|
+
|
|
120
|
+
# Update a proposal
|
|
121
|
+
cli-dolibarr proposals update 31 --note "Revised terms"
|
|
122
|
+
|
|
123
|
+
# Delete a proposal
|
|
124
|
+
cli-dolibarr proposals delete 31
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Stock Movements
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# List stock movements
|
|
131
|
+
cli-dolibarr stockmovements list
|
|
132
|
+
|
|
133
|
+
# Stock in (type=3, positive qty)
|
|
134
|
+
cli-dolibarr stockmovements create --product-id 7 --warehouse-id 1 --qty 50
|
|
135
|
+
|
|
136
|
+
# Stock out (type=2, negative qty)
|
|
137
|
+
cli-dolibarr stockmovements create --product-id 7 --warehouse-id 1 --qty -10
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Warehouses
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# List warehouses
|
|
144
|
+
cli-dolibarr warehouses list
|
|
145
|
+
|
|
146
|
+
# Get a specific warehouse
|
|
147
|
+
cli-dolibarr warehouses get 1
|
|
148
|
+
|
|
149
|
+
# Create a warehouse (required: label)
|
|
150
|
+
cli-dolibarr warehouses create --label "Main Warehouse"
|
|
151
|
+
|
|
152
|
+
# Update a warehouse
|
|
153
|
+
cli-dolibarr warehouses update 1 --town "Shanghai"
|
|
154
|
+
|
|
155
|
+
# Delete a warehouse
|
|
156
|
+
cli-dolibarr warehouses delete 1
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Projects
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# List projects
|
|
163
|
+
cli-dolibarr projects list
|
|
164
|
+
|
|
165
|
+
# Get a specific project
|
|
166
|
+
cli-dolibarr projects get 5
|
|
167
|
+
|
|
168
|
+
# Create a project (required: title)
|
|
169
|
+
cli-dolibarr projects create --title "Website Redesign"
|
|
170
|
+
|
|
171
|
+
# Update a project
|
|
172
|
+
cli-dolibarr projects update 5 --description "Phase 2 started"
|
|
173
|
+
|
|
174
|
+
# Delete a project
|
|
175
|
+
cli-dolibarr projects delete 5
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Tasks
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# List tasks
|
|
182
|
+
cli-dolibarr tasks list
|
|
183
|
+
|
|
184
|
+
# Get a specific task
|
|
185
|
+
cli-dolibarr tasks get 12
|
|
186
|
+
|
|
187
|
+
# Create a task (requires project context)
|
|
188
|
+
cli-dolibarr tasks create --title "Design mockups" --project-id 5
|
|
189
|
+
|
|
190
|
+
# Update a task
|
|
191
|
+
cli-dolibarr tasks update 12 --progress 75
|
|
192
|
+
|
|
193
|
+
# Delete a task
|
|
194
|
+
cli-dolibarr tasks delete 12
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Global Options
|
|
198
|
+
|
|
199
|
+
| Option | Description |
|
|
200
|
+
|-----------------|------------------------------------|
|
|
201
|
+
| `--json` | Output in JSON format |
|
|
202
|
+
| `--csv` | Output in CSV format |
|
|
203
|
+
| `--url` | Override Dolibarr API URL |
|
|
204
|
+
| `--api-key` | Override API key |
|
|
205
|
+
| `--limit N` | Limit results to N items |
|
|
206
|
+
| `--verify` | Enable SSL certificate verification|
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Example: JSON output with limit
|
|
210
|
+
cli-dolibarr products list --json --limit 5
|
|
211
|
+
|
|
212
|
+
# Example: CSV output
|
|
213
|
+
cli-dolibarr invoices list --csv
|
|
214
|
+
|
|
215
|
+
# Example: Override URL and API key
|
|
216
|
+
cli-dolibarr thirdparties list --url "https://your-dolibarr.example.com/api/index.php" --api-key "your_api_key"
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## REPL Mode
|
|
220
|
+
|
|
221
|
+
Start an interactive session for repeated commands without re-authenticating:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
cli-dolibarr repl
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Inside the REPL, use commands directly:
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
dolibarr> thirdparties list
|
|
231
|
+
dolibarr> products get 7
|
|
232
|
+
dolibarr> exit
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Environment Variables
|
|
236
|
+
|
|
237
|
+
| Variable | Description |
|
|
238
|
+
|---------------------|--------------------------------------|
|
|
239
|
+
| `DOLIBARR_URL` | Full API URL (e.g., `https://your-dolibarr.example.com/api/index.php`) |
|
|
240
|
+
| `DOLIBARR_API_KEY` | API key from Dolibarr user settings |
|
|
241
|
+
| `DOLIBARR_VERIFY_SSL`| Set to `1` or `true` to verify SSL |
|
|
242
|
+
|
|
243
|
+
## SQL Filters
|
|
244
|
+
|
|
245
|
+
Use the `--sql-filter` option to apply advanced filters on list commands:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
# Filter by name pattern
|
|
249
|
+
cli-dolibarr thirdparties list --sql-filter "(t.name:like:'Acme%')"
|
|
250
|
+
|
|
251
|
+
# Filter by date range
|
|
252
|
+
cli-dolibarr invoices list --sql-filter "(t.datec:>=:'2026-01-01')"
|
|
253
|
+
|
|
254
|
+
# Combined filters
|
|
255
|
+
cli-dolibarr products list --sql-filter "(t.toselect:=:1) and (t.status:=:1)"
|
|
256
|
+
|
|
257
|
+
# IN operator
|
|
258
|
+
cli-dolibarr orders list --sql-filter "(t.status:IN:1,2,3)"
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Operators: `:=`, `:like:`, `:<`, `:>`, `:<=`, `:>=`, `:!=`, `:IN:`, `:NOTIN:`
|
|
262
|
+
|
|
263
|
+
## SSL Verification
|
|
264
|
+
|
|
265
|
+
By default, SSL verification is **disabled** (`--no-verify`) to support self-signed certificates common in self-hosted Dolibarr installations. To enable verification:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
cli-dolibarr --verify thirdparties list
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Or set the environment variable:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
export DOLIBARR_VERIFY_SSL="true"
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Schema Management
|
|
278
|
+
|
|
279
|
+
Built-in schema-driven API discovery system for keeping CLI commands in sync with Dolibarr API changes.
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
# Fetch latest API spec from Dolibarr
|
|
283
|
+
cli-dolibarr schema sync
|
|
284
|
+
|
|
285
|
+
# Check coverage (which endpoints have CLI commands)
|
|
286
|
+
cli-dolibarr schema diff
|
|
287
|
+
|
|
288
|
+
# Auto-generate CLI commands for uncovered endpoints
|
|
289
|
+
cli-dolibarr schema generate --all
|
|
290
|
+
|
|
291
|
+
# Preview without writing files
|
|
292
|
+
cli-dolibarr schema generate --all --dry-run
|
|
293
|
+
|
|
294
|
+
# Generate AI code map (AGENTS.md)
|
|
295
|
+
cli-dolibarr schema agents
|
|
296
|
+
|
|
297
|
+
# Export endpoint data for AI fine-tuning
|
|
298
|
+
cli-dolibarr schema export --format jsonl --output data.jsonl
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Available Commands
|
|
302
|
+
|
|
303
|
+
49 command groups covering all Dolibarr REST API resources: thirdparties, products, invoices, orders, proposals, shipments, projects, tasks, warehouses, stockmovements, contacts, bankaccounts, categories, users, tickets, webhooks, and more. Run `cli-dolibarr --help` for the full list.
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## 中文说明
|
|
308
|
+
|
|
309
|
+
Dolibarr ERP/CRM REST API 的命令行管理工具。支持客户、产品、发票、订单、报价、库存、仓库、项目、任务等 49 个模块。
|
|
310
|
+
|
|
311
|
+
### 安装
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
pip install cli-dolibarr
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
或从 GitHub 安装:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
pip install git+https://github.com/zswll2/cli-dolibarr.git
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### 配置
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
# 交互式配置(输入 URL 和 API Key)
|
|
327
|
+
cli-dolibarr config init
|
|
328
|
+
|
|
329
|
+
# 或使用环境变量
|
|
330
|
+
export DOLIBARR_URL="https://your-dolibarr.example.com/api/index.php"
|
|
331
|
+
export DOLIBARR_API_KEY="your_api_key"
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### 常用命令
|
|
335
|
+
|
|
336
|
+
```bash
|
|
337
|
+
# 客户管理
|
|
338
|
+
cli-dolibarr thirdparties list # 列出所有客户
|
|
339
|
+
cli-dolibarr thirdparties get 42 # 查看客户详情
|
|
340
|
+
cli-dolibarr thirdparties create --name "Acme Corp" # 创建客户
|
|
341
|
+
|
|
342
|
+
# 产品管理
|
|
343
|
+
cli-dolibarr products list # 列出产品
|
|
344
|
+
cli-dolibarr products create --ref "P001" --label "产品A" # 创建产品
|
|
345
|
+
|
|
346
|
+
# 发票管理
|
|
347
|
+
cli-dolibarr invoices list # 列出发票
|
|
348
|
+
cli-dolibarr invoices create --socid 42 # 创建发票
|
|
349
|
+
|
|
350
|
+
# 订单管理
|
|
351
|
+
cli-dolibarr orders list # 列出订单
|
|
352
|
+
cli-dolibarr orders create --socid 42 --date "2026-01-15" # 创建订单
|
|
353
|
+
|
|
354
|
+
# 库存管理
|
|
355
|
+
cli-dolibarr stockmovements create --product-id 7 --warehouse-id 1 --qty 50 # 入库
|
|
356
|
+
cli-dolibarr stockmovements create --product-id 7 --warehouse-id 1 --qty -10 # 出库
|
|
357
|
+
|
|
358
|
+
# 项目与任务
|
|
359
|
+
cli-dolibarr projects list # 列出项目
|
|
360
|
+
cli-dolibarr tasks list # 列出任务
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Schema 管理系统
|
|
364
|
+
|
|
365
|
+
内置 API 自动发现系统,Dolibarr 升级后可自动同步新端点:
|
|
366
|
+
|
|
367
|
+
```bash
|
|
368
|
+
cli-dolibarr schema sync # 从 Dolibarr 拉取最新 API 定义
|
|
369
|
+
cli-dolibarr schema diff # 查看覆盖情况(哪些有命令、哪些没有)
|
|
370
|
+
cli-dolibarr schema generate --all # 自动生成缺失的 CLI 命令
|
|
371
|
+
cli-dolibarr schema agents # 生成 AI 代码地图 (AGENTS.md)
|
|
372
|
+
cli-dolibarr schema export --format jsonl --output data.jsonl # 导出微调数据
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### 输出格式
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
cli-dolibarr --json products list # JSON 格式
|
|
379
|
+
cli-dolibarr --csv invoices list # CSV 格式(可导入 Excel)
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### 全局选项
|
|
383
|
+
|
|
384
|
+
| 选项 | 说明 |
|
|
385
|
+
|------|------|
|
|
386
|
+
| `--json` | JSON 格式输出 |
|
|
387
|
+
| `--csv` | CSV 格式输出 |
|
|
388
|
+
| `--url` | 覆盖 API URL |
|
|
389
|
+
| `--api-key` | 覆盖 API Key |
|
|
390
|
+
| `--limit N` | 限制返回条数 |
|
|
391
|
+
| `--verify` | 启用 SSL 证书验证 |
|
|
392
|
+
|
|
393
|
+
### 交互模式
|
|
394
|
+
|
|
395
|
+
```bash
|
|
396
|
+
cli-dolibarr repl
|
|
397
|
+
# 进入后可直接输入命令:
|
|
398
|
+
# doli> thirdparties list
|
|
399
|
+
# doli> products get 7
|
|
400
|
+
# doli> exit
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### SQL 过滤器
|
|
404
|
+
|
|
405
|
+
```bash
|
|
406
|
+
cli-dolibarr thirdparties list --sql-filter "(t.name:like:'Acme%')" # 按名称筛选
|
|
407
|
+
cli-dolibarr invoices list --sql-filter "(t.datec:>=:'2026-01-01')" # 按日期筛选
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
支持的操作符:`:=`, `:like:`, `:<`, `:>`, `:<=`, `:>=`, `:!=`, `:IN:`, `:NOTIN:`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.0.0"
|
|
File without changes
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command template for Dolibarr CLI.
|
|
3
|
+
|
|
4
|
+
Copy this file to create a new command. Name it after your resource
|
|
5
|
+
(e.g. warehouses.py) and rename the group function to match.
|
|
6
|
+
|
|
7
|
+
Registration is automatic — any .py file in this directory (not starting
|
|
8
|
+
with _) that exposes a click.Group or click.Command matching the filename
|
|
9
|
+
will be discovered at startup.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import sys
|
|
13
|
+
import click
|
|
14
|
+
import json
|
|
15
|
+
from cli_anything.dolibarr.core.client import DolibarrClient, DolibarrAPIError
|
|
16
|
+
from cli_anything.dolibarr.core.output import OutputFormatter
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _get_client(ctx) -> DolibarrClient:
|
|
20
|
+
return ctx.obj['client']
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _get_formatter(ctx) -> OutputFormatter:
|
|
24
|
+
return ctx.obj['formatter']
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# The function name MUST match the filename (without .py).
|
|
28
|
+
# e.g. file "warehouses.py" → function "warehouses".
|
|
29
|
+
@click.group()
|
|
30
|
+
def template(): # ← rename to match your filename
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@template.command('list')
|
|
35
|
+
@click.option('--sortfield', default='t.rowid', help='Sort field')
|
|
36
|
+
@click.option('--sortorder', default='ASC', type=click.Choice(['ASC', 'DESC']))
|
|
37
|
+
@click.option('--limit', default=100, type=int, help='Items per page')
|
|
38
|
+
@click.option('--page', default=0, type=int, help='Page number')
|
|
39
|
+
@click.option('--filter', 'sqlfilters', default=None, help='SQL filter')
|
|
40
|
+
@click.pass_context
|
|
41
|
+
def list_items(ctx, sortfield, sortorder, limit, page, sqlfilters):
|
|
42
|
+
client = _get_client(ctx)
|
|
43
|
+
formatter = _get_formatter(ctx)
|
|
44
|
+
try:
|
|
45
|
+
result = client.list('template', sortfield=sortfield, sortorder=sortorder,
|
|
46
|
+
limit=limit, page=page, sqlfilters=sqlfilters)
|
|
47
|
+
formatter.output(result)
|
|
48
|
+
except DolibarrAPIError as e:
|
|
49
|
+
click.echo(f"Error: {e.message}", err=True)
|
|
50
|
+
sys.exit(1)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@template.command('get')
|
|
54
|
+
@click.argument('id', type=int)
|
|
55
|
+
@click.pass_context
|
|
56
|
+
def get_item(ctx, id):
|
|
57
|
+
client = _get_client(ctx)
|
|
58
|
+
formatter = _get_formatter(ctx)
|
|
59
|
+
try:
|
|
60
|
+
result = client.get('template', resource_id=id)
|
|
61
|
+
formatter.output(result)
|
|
62
|
+
except DolibarrAPIError as e:
|
|
63
|
+
click.echo(f"Error: {e.message}", err=True)
|
|
64
|
+
sys.exit(1)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@template.command('create')
|
|
68
|
+
@click.option('--data', default=None, help='JSON string with all fields')
|
|
69
|
+
@click.pass_context
|
|
70
|
+
def create_item(ctx, data):
|
|
71
|
+
client = _get_client(ctx)
|
|
72
|
+
formatter = _get_formatter(ctx)
|
|
73
|
+
try:
|
|
74
|
+
payload = json.loads(data) if data else {}
|
|
75
|
+
result = client.post('template', data=payload)
|
|
76
|
+
formatter.output(result)
|
|
77
|
+
except DolibarrAPIError as e:
|
|
78
|
+
click.echo(f"Error: {e.message}", err=True)
|
|
79
|
+
sys.exit(1)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@template.command('update')
|
|
83
|
+
@click.argument('id', type=int)
|
|
84
|
+
@click.option('--data', default=None, help='JSON string with all fields')
|
|
85
|
+
@click.option('--set', 'set_fields', multiple=True, help='Key=value pairs')
|
|
86
|
+
@click.pass_context
|
|
87
|
+
def update_item(ctx, id, data, set_fields):
|
|
88
|
+
client = _get_client(ctx)
|
|
89
|
+
formatter = _get_formatter(ctx)
|
|
90
|
+
try:
|
|
91
|
+
if data:
|
|
92
|
+
payload = json.loads(data)
|
|
93
|
+
else:
|
|
94
|
+
existing = client.get('template', resource_id=id)
|
|
95
|
+
payload = existing if isinstance(existing, dict) else {}
|
|
96
|
+
for sf in set_fields:
|
|
97
|
+
if '=' in sf:
|
|
98
|
+
k, v = sf.split('=', 1)
|
|
99
|
+
payload[k] = v
|
|
100
|
+
result = client.put('template', resource_id=id, data=payload)
|
|
101
|
+
formatter.output(result)
|
|
102
|
+
except DolibarrAPIError as e:
|
|
103
|
+
click.echo(f"Error: {e.message}", err=True)
|
|
104
|
+
sys.exit(1)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@template.command('delete')
|
|
108
|
+
@click.argument('id', type=int)
|
|
109
|
+
@click.pass_context
|
|
110
|
+
def delete_item(ctx, id):
|
|
111
|
+
client = _get_client(ctx)
|
|
112
|
+
formatter = _get_formatter(ctx)
|
|
113
|
+
try:
|
|
114
|
+
result = client.delete('template', resource_id=id)
|
|
115
|
+
formatter.output(result)
|
|
116
|
+
except DolibarrAPIError as e:
|
|
117
|
+
click.echo(f"Error: {e.message}", err=True)
|
|
118
|
+
sys.exit(1)
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import click
|
|
3
|
+
import json
|
|
4
|
+
from cli_anything.dolibarr.core.client import DolibarrClient, DolibarrAPIError
|
|
5
|
+
from cli_anything.dolibarr.core.output import OutputFormatter
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _get_client(ctx) -> DolibarrClient:
|
|
9
|
+
return ctx.obj['client']
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _get_formatter(ctx) -> OutputFormatter:
|
|
13
|
+
return ctx.obj['formatter']
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@click.group()
|
|
17
|
+
def accountancy():
|
|
18
|
+
"""Manage Dolibarr accountancy (会计) entries."""
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@accountancy.command('list')
|
|
23
|
+
@click.option('--sortfield', default='t.rowid', help='Sort field')
|
|
24
|
+
@click.option('--sortorder', default='ASC', type=click.Choice(['ASC', 'DESC']))
|
|
25
|
+
@click.option('--limit', default=100, type=int, help='Items per page')
|
|
26
|
+
@click.option('--page', default=0, type=int, help='Page number')
|
|
27
|
+
@click.option('--filter', 'sqlfilters', default=None, help='SQL filter')
|
|
28
|
+
@click.option('--properties', default=None, help='Fields to return')
|
|
29
|
+
@click.pass_context
|
|
30
|
+
def list_accountancy(ctx, sortfield, sortorder, limit, page, sqlfilters, properties):
|
|
31
|
+
"""List accountancy entries."""
|
|
32
|
+
client = _get_client(ctx)
|
|
33
|
+
formatter = _get_formatter(ctx)
|
|
34
|
+
try:
|
|
35
|
+
result = client.list('accountancy', sortfield=sortfield, sortorder=sortorder,
|
|
36
|
+
limit=limit, page=page, sqlfilters=sqlfilters,
|
|
37
|
+
properties=properties)
|
|
38
|
+
formatter.output(result)
|
|
39
|
+
except DolibarrAPIError as e:
|
|
40
|
+
click.echo(f"Error: {e.message}", err=True)
|
|
41
|
+
sys.exit(1)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@accountancy.command('get')
|
|
45
|
+
@click.argument('id', type=int)
|
|
46
|
+
@click.pass_context
|
|
47
|
+
def get_accountancy(ctx, id):
|
|
48
|
+
"""Get a single accountancy entry by ID."""
|
|
49
|
+
client = _get_client(ctx)
|
|
50
|
+
formatter = _get_formatter(ctx)
|
|
51
|
+
try:
|
|
52
|
+
result = client.get('accountancy', resource_id=id)
|
|
53
|
+
formatter.output(result)
|
|
54
|
+
except DolibarrAPIError as e:
|
|
55
|
+
click.echo(f"Error: {e.message}", err=True)
|
|
56
|
+
sys.exit(1)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@accountancy.command('create')
|
|
60
|
+
@click.option('--data', default=None, help='JSON string with all fields')
|
|
61
|
+
@click.option('--doc_type', default=None, help='Document type')
|
|
62
|
+
@click.option('--doc_ref', default=None, help='Document reference')
|
|
63
|
+
@click.option('--numero_compte', default=None, help='Account number')
|
|
64
|
+
@click.option('--label_operation', default=None, help='Label of the operation')
|
|
65
|
+
@click.pass_context
|
|
66
|
+
def create_accountancy(ctx, data, doc_type, doc_ref, numero_compte, label_operation):
|
|
67
|
+
"""Create a new accountancy entry."""
|
|
68
|
+
client = _get_client(ctx)
|
|
69
|
+
formatter = _get_formatter(ctx)
|
|
70
|
+
try:
|
|
71
|
+
if data:
|
|
72
|
+
payload = json.loads(data)
|
|
73
|
+
else:
|
|
74
|
+
payload = {}
|
|
75
|
+
if doc_type is not None:
|
|
76
|
+
payload['doc_type'] = doc_type
|
|
77
|
+
if doc_ref is not None:
|
|
78
|
+
payload['doc_ref'] = doc_ref
|
|
79
|
+
if numero_compte is not None:
|
|
80
|
+
payload['numero_compte'] = numero_compte
|
|
81
|
+
if label_operation is not None:
|
|
82
|
+
payload['label_operation'] = label_operation
|
|
83
|
+
result = client.post('accountancy', data=payload)
|
|
84
|
+
formatter.output(result)
|
|
85
|
+
except DolibarrAPIError as e:
|
|
86
|
+
click.echo(f"Error: {e.message}", err=True)
|
|
87
|
+
sys.exit(1)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@accountancy.command('update')
|
|
91
|
+
@click.argument('id', type=int)
|
|
92
|
+
@click.option('--data', default=None, help='JSON string with all fields')
|
|
93
|
+
@click.option('--set', 'set_fields', multiple=True, help='Key=value pairs')
|
|
94
|
+
@click.pass_context
|
|
95
|
+
def update_accountancy(ctx, id, data, set_fields):
|
|
96
|
+
"""Update an existing accountancy entry."""
|
|
97
|
+
client = _get_client(ctx)
|
|
98
|
+
formatter = _get_formatter(ctx)
|
|
99
|
+
try:
|
|
100
|
+
if data:
|
|
101
|
+
payload = json.loads(data)
|
|
102
|
+
else:
|
|
103
|
+
existing = client.get('accountancy', resource_id=id)
|
|
104
|
+
payload = {}
|
|
105
|
+
if isinstance(existing, dict):
|
|
106
|
+
payload = existing
|
|
107
|
+
for sf in set_fields:
|
|
108
|
+
if '=' in sf:
|
|
109
|
+
k, v = sf.split('=', 1)
|
|
110
|
+
payload[k] = v
|
|
111
|
+
result = client.put('accountancy', resource_id=id, data=payload)
|
|
112
|
+
formatter.output(result)
|
|
113
|
+
except DolibarrAPIError as e:
|
|
114
|
+
click.echo(f"Error: {e.message}", err=True)
|
|
115
|
+
sys.exit(1)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@accountancy.command('delete')
|
|
119
|
+
@click.argument('id', type=int)
|
|
120
|
+
@click.pass_context
|
|
121
|
+
def delete_accountancy(ctx, id):
|
|
122
|
+
"""Delete an accountancy entry by ID."""
|
|
123
|
+
client = _get_client(ctx)
|
|
124
|
+
formatter = _get_formatter(ctx)
|
|
125
|
+
try:
|
|
126
|
+
result = client.delete('accountancy', resource_id=id)
|
|
127
|
+
formatter.output(result)
|
|
128
|
+
except DolibarrAPIError as e:
|
|
129
|
+
click.echo(f"Error: {e.message}", err=True)
|
|
130
|
+
sys.exit(1)
|