jaz-clio 4.30.10 → 4.30.12
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 +1 -1
- package/assets/skills/api/SKILL.md +4 -1
- package/assets/skills/api/references/endpoints.md +90 -1
- package/assets/skills/api/references/errors.md +15 -1
- package/assets/skills/api/references/feature-glossary.md +6 -0
- package/assets/skills/api/references/field-map.md +12 -1
- package/assets/skills/api/references/full-api-surface.md +12 -1
- package/assets/skills/conversion/SKILL.md +1 -1
- package/assets/skills/jobs/SKILL.md +1 -1
- package/assets/skills/transaction-recipes/SKILL.md +1 -1
- package/dist/commands/quick-fix.js +139 -0
- package/dist/core/api/index.js +1 -0
- package/dist/core/api/quick-fix.js +16 -0
- package/dist/core/registry/namespaces.js +6 -0
- package/dist/core/registry/tools.js +81 -17
- package/dist/index.js +2 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -235,7 +235,7 @@ Every command supports `--json` for structured output — ideal for piping to ot
|
|
|
235
235
|
|
|
236
236
|
## MCP Server
|
|
237
237
|
|
|
238
|
-
Expose all
|
|
238
|
+
Expose all 207 CLI tools to AI coding and coworking agents via the Model Context Protocol (MCP). The server runs locally on your machine — no cloud, no ports. API calls go directly from your machine to the Jaz API.
|
|
239
239
|
|
|
240
240
|
**Claude Code:**
|
|
241
241
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-api
|
|
3
|
-
version: 4.30.
|
|
3
|
+
version: 4.30.12
|
|
4
4
|
description: Complete reference for the Jaz REST API — the accounting platform backend. Use this skill whenever building, modifying, debugging, or extending any code that calls the API — including API clients, integrations, data seeding, test data, or new endpoint work. Contains every field name, response shape, error, gotcha, and edge case discovered through live production testing.
|
|
5
5
|
license: MIT
|
|
6
6
|
compatibility: Requires Jaz API key (x-jk-api-key header). Works with Claude Code, Google Antigravity, OpenAI Codex, GitHub Copilot, Cursor, and any agent that reads markdown.
|
|
@@ -278,6 +278,9 @@ Bills, invoices, and credit notes share identical mandatory field specs. Adding
|
|
|
278
278
|
105. **`add_currency_rate` for new rates, `update_currency_rate` only for editing existing records** — When a user says "update the rate" or "set the rate", use `add_currency_rate` (POST — creates a new rate entry for a date). Only use `update_currency_rate` (PUT) when explicitly modifying an existing rate record by its resourceId.
|
|
279
279
|
106. **Contact PUT uses `email` (string), not `emails` (array)** — GET returns `emails: [{email, label}]` (array) but PUT accepts `email: "user@example.com"` (string). Sending the `emails` array in PUT body causes 400 "Invalid request body". The CLI and tool executor handle this automatically via read-modify-write with the correct field.
|
|
280
280
|
|
|
281
|
+
### Quick Fix (Bulk Update)
|
|
282
|
+
107. **20 Quick Fix endpoints for bulk-updating transactions and line items** — `POST /api/v1/quick-fix/{entity}` with `{ resourceIds: [...], attributes: {...} }`. Response: `{ updated: [...], failed: [{ resourceId, error, errorCode }] }`. Entities grouped by domain: **ARAP**: invoices, bills, customer-credit-notes, supplier-credit-notes. **Accounting**: journals, cash-entries. **Schedulers**: sale-schedules, purchase-schedules, subscription-schedules, journal-schedules. Line-item endpoints add `/line-items` suffix. ARAP line items use `{ lineItemResourceIds, attributes }`. Scheduler line items use `{ schedulerUpdates: [{ schedulerResourceId, lineItemUpdates }] }`. **Known gotcha**: `valueDate` (and `dueDate` for ARAP) must currently be included in `attributes` even when unchanged — absent fields are treated as "remove" rather than "keep existing". This will be fixed server-side.
|
|
283
|
+
|
|
281
284
|
## Supporting Files
|
|
282
285
|
|
|
283
286
|
For detailed reference, read these files in this skill directory:
|
|
@@ -1814,4 +1814,93 @@ Middleware on payment, credit, and refund endpoints automatically wraps a flat J
|
|
|
1814
1814
|
|
|
1815
1815
|
---
|
|
1816
1816
|
|
|
1817
|
-
|
|
1817
|
+
---
|
|
1818
|
+
|
|
1819
|
+
## 17. Quick Fix (Bulk Update)
|
|
1820
|
+
|
|
1821
|
+
20 endpoints for bulk-updating transactions and line items in a single API call.
|
|
1822
|
+
|
|
1823
|
+
### Pattern
|
|
1824
|
+
|
|
1825
|
+
```
|
|
1826
|
+
POST /api/v1/quick-fix/{entity}
|
|
1827
|
+
POST /api/v1/quick-fix/{entity}/line-items
|
|
1828
|
+
```
|
|
1829
|
+
|
|
1830
|
+
### Entities (grouped by domain)
|
|
1831
|
+
|
|
1832
|
+
**ARAP**: `invoices`, `bills`, `customer-credit-notes`, `supplier-credit-notes`
|
|
1833
|
+
**Accounting**: `journals`, `cash-entries`
|
|
1834
|
+
**Schedulers**: `sale-schedules`, `purchase-schedules`, `subscription-schedules`, `journal-schedules`
|
|
1835
|
+
|
|
1836
|
+
### Transaction-Level Request
|
|
1837
|
+
|
|
1838
|
+
```json
|
|
1839
|
+
POST /api/v1/quick-fix/bills
|
|
1840
|
+
{
|
|
1841
|
+
"resourceIds": ["uuid1", "uuid2"],
|
|
1842
|
+
"attributes": {
|
|
1843
|
+
"valueDate": "2026-03-01",
|
|
1844
|
+
"dueDate": "2026-03-31",
|
|
1845
|
+
"tags": ["Q1-2026"],
|
|
1846
|
+
"contactResourceId": "uuid"
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
```
|
|
1850
|
+
|
|
1851
|
+
### Line-Item-Level Request (ARAP + Accounting)
|
|
1852
|
+
|
|
1853
|
+
```json
|
|
1854
|
+
POST /api/v1/quick-fix/invoices/line-items
|
|
1855
|
+
{
|
|
1856
|
+
"lineItemResourceIds": ["li-uuid1", "li-uuid2"],
|
|
1857
|
+
"attributes": {
|
|
1858
|
+
"name": "Updated Item",
|
|
1859
|
+
"quantity": 2,
|
|
1860
|
+
"unitPrice": 150,
|
|
1861
|
+
"organizationAccountResourceId": "acct-uuid",
|
|
1862
|
+
"taxProfileResourceId": "tax-uuid"
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
```
|
|
1866
|
+
|
|
1867
|
+
### Line-Item-Level Request (Schedulers)
|
|
1868
|
+
|
|
1869
|
+
```json
|
|
1870
|
+
POST /api/v1/quick-fix/sale-schedules/line-items
|
|
1871
|
+
{
|
|
1872
|
+
"schedulerUpdates": [
|
|
1873
|
+
{
|
|
1874
|
+
"schedulerResourceId": "sched-uuid",
|
|
1875
|
+
"lineItemUpdates": [
|
|
1876
|
+
{ "arrayIndex": 0, "unitPrice": 200 }
|
|
1877
|
+
]
|
|
1878
|
+
}
|
|
1879
|
+
]
|
|
1880
|
+
}
|
|
1881
|
+
```
|
|
1882
|
+
|
|
1883
|
+
### Response (all 20 endpoints)
|
|
1884
|
+
|
|
1885
|
+
```json
|
|
1886
|
+
{
|
|
1887
|
+
"updated": ["uuid1", "uuid2"],
|
|
1888
|
+
"failed": [
|
|
1889
|
+
{ "resourceId": "uuid3", "error": "Transaction is locked", "errorCode": "TRANSACTION_LOCKED" }
|
|
1890
|
+
]
|
|
1891
|
+
}
|
|
1892
|
+
```
|
|
1893
|
+
|
|
1894
|
+
### Updatable Fields
|
|
1895
|
+
|
|
1896
|
+
**Transaction-level**: valueDate, dueDate (ARAP), contactResourceId, tags, capsuleResourceId, customFields, currencySettings, taxCurrencySettings, invoiceNotes (invoices/CNs), templateResourceId (invoices/CNs), billFrom/billTo (invoices/CNs), endDate/interval (schedulers).
|
|
1897
|
+
|
|
1898
|
+
**ARAP line items**: name, quantity, unit, unitPrice, discount, itemResourceId, organizationAccountResourceId, taxProfileResourceId, classifierConfig, withholdingTax (bills/supplier-CNs only).
|
|
1899
|
+
|
|
1900
|
+
**Journal/cash-entry line items**: organizationAccountResourceId, amount, description, taxProfileResourceId, classifierConfig.
|
|
1901
|
+
|
|
1902
|
+
**Known gotcha**: `valueDate` (and `dueDate` for ARAP) must currently be included in `attributes` even when unchanged — absent fields are treated as "remove". Server-side fix pending.
|
|
1903
|
+
|
|
1904
|
+
---
|
|
1905
|
+
|
|
1906
|
+
*Last updated: 2026-03-09 — Added: Quick Fix (20 bulk-update endpoints), subscription CRUD (proratedConfig, PUT cancel).*
|
|
@@ -819,4 +819,18 @@ Journals support a top-level `currency` object to create entries in a foreign cu
|
|
|
819
819
|
|
|
820
820
|
---
|
|
821
821
|
|
|
822
|
-
|
|
822
|
+
### Quick Fix Errors
|
|
823
|
+
|
|
824
|
+
**"Not allowed to remove valueDate of a sale/purchase/journal"** — `valueDate` absent from `attributes`. Currently must be included even if unchanged. Server-side fix pending.
|
|
825
|
+
|
|
826
|
+
**"Not allowed to remove dueDate of a sale"** — Same pattern for `dueDate` on invoices.
|
|
827
|
+
|
|
828
|
+
**"Not allowed to remove pdfTemplate of a sale"** — Same pattern for `templateResourceId` on invoices that have a template.
|
|
829
|
+
|
|
830
|
+
**"Item name is required to bulk update purchase item details"** — Line-item quick-fix requires `name` in attributes. Same "absent = remove" pattern.
|
|
831
|
+
|
|
832
|
+
**"TRANSACTION_LOCKED"** — Transaction is in a locked period. Cannot update.
|
|
833
|
+
|
|
834
|
+
---
|
|
835
|
+
|
|
836
|
+
*Last updated: 2026-03-09 — Added Quick Fix errors (absent = remove gotcha), cash entry PUT 500 (missing accountResourceId), contact PUT email/emails asymmetry.*
|
|
@@ -237,6 +237,12 @@ Bank statement import supports CSV and PDF with configurable column mapping. Sta
|
|
|
237
237
|
|
|
238
238
|
**API**: `POST /magic/importBankStatementFromAttachment` (multipart: `sourceFile`, `accountResourceId`, `businessTransactionType: "BANK_STATEMENT"`, `sourceType: "FILE"`)
|
|
239
239
|
|
|
240
|
+
### Quick Fix (Bulk Update)
|
|
241
|
+
|
|
242
|
+
Mass-edit transactions and line items in a single operation. Replaces the need to open and update each transaction individually. Supports all transaction types (invoices, bills, credit notes, journals, cash entries) and their scheduled/subscription variants. Common use cases: batch date corrections, reassigning contacts, bulk-tagging for reporting, changing accounts/tax profiles across multiple line items.
|
|
243
|
+
|
|
244
|
+
**API**: `POST /api/v1/quick-fix/{entity}` (transaction-level) + `POST /api/v1/quick-fix/{entity}/line-items` (line-item-level). 20 endpoints total.
|
|
245
|
+
|
|
240
246
|
---
|
|
241
247
|
|
|
242
248
|
*Maintained alongside [help.jaz.ai](https://help.jaz.ai).*
|
|
@@ -565,4 +565,15 @@ Battle-tested patterns from production Jaz API clients:
|
|
|
565
565
|
|
|
566
566
|
---
|
|
567
567
|
|
|
568
|
-
|
|
568
|
+
### Quick Fix (Bulk Update) Field Mapping
|
|
569
|
+
|
|
570
|
+
| What you'd guess | Actual field | Notes |
|
|
571
|
+
|-------------------|-------------|-------|
|
|
572
|
+
| `accountResourceId` (line items) | `organizationAccountResourceId` | Quick-fix line items use GET-side field name, NOT the POST alias |
|
|
573
|
+
| `repeat` (schedulers) | `interval` | Quick-fix scheduler attributes use `interval`, NOT `repeat` |
|
|
574
|
+
| `lineItems` | `lineItemResourceIds` | Pass individual line item IDs, not the transaction resourceId |
|
|
575
|
+
| `schedulerResourceId` | `schedulerResourceId` | For scheduler line-item updates (in `schedulerUpdates` array) |
|
|
576
|
+
|
|
577
|
+
---
|
|
578
|
+
|
|
579
|
+
*Last updated: 2026-03-09 — Added Quick Fix field mapping. Previous: Currency response fields, account create fields.*
|
|
@@ -694,6 +694,17 @@ These features exist in the Jaz platform and may affect API responses or cause u
|
|
|
694
694
|
- Move transactions between capsules via `POST /api/v1/moveTransactionCapsules`
|
|
695
695
|
- Search transactions within capsules
|
|
696
696
|
|
|
697
|
+
### Quick Fix (Bulk Update) — 20 Endpoints
|
|
698
|
+
|
|
699
|
+
Bulk-update transactions or line items in a single call. Pattern: `POST /api/v1/quick-fix/{entity}` + `POST /api/v1/quick-fix/{entity}/line-items`.
|
|
700
|
+
|
|
701
|
+
**ARAP**: `invoices`, `bills`, `customer-credit-notes`, `supplier-credit-notes` (× 2 = 8)
|
|
702
|
+
**Accounting**: `journals`, `cash-entries` (× 2 = 4)
|
|
703
|
+
**Schedulers**: `sale-schedules`, `purchase-schedules`, `subscription-schedules`, `journal-schedules` (× 2 = 8)
|
|
704
|
+
|
|
705
|
+
Request: `{ resourceIds: [...], attributes: {...} }` (transactions) or `{ lineItemResourceIds: [...], attributes: {...} }` (line items) or `{ schedulerUpdates: [...] }` (scheduler line items).
|
|
706
|
+
Response: `{ updated: [...], failed: [{ resourceId, error, errorCode }] }`.
|
|
707
|
+
|
|
697
708
|
---
|
|
698
709
|
|
|
699
|
-
*Last updated: 2026-
|
|
710
|
+
*Last updated: 2026-03-09 — Added 20 Quick Fix endpoints (bulk update). Previous: All search/list responses standardized to flat shape, kebab-case aliases, sort array on all endpoints.*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-conversion
|
|
3
|
-
version: 4.30.
|
|
3
|
+
version: 4.30.12
|
|
4
4
|
description: Accounting data conversion skill — migrates customer data from Xero, QuickBooks, Sage, MYOB, and Excel exports to Jaz. Covers config, quick, and full conversion workflows, Excel parsing, CoA/contact/tax/items mapping, clearing accounts, TTB, and TB verification.
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-jobs
|
|
3
|
-
version: 4.30.
|
|
3
|
+
version: 4.30.12
|
|
4
4
|
description: 12 accounting jobs for SMB bookkeepers and accountants — month-end, quarter-end, and year-end close playbooks plus 9 ad-hoc operational jobs (bank recon, document collection, GST/VAT filing, payment runs, credit control, supplier recon, audit prep, fixed asset review, statutory filing). Jobs can have paired tools as nested subcommands (e.g., `clio jobs bank-recon match`, `clio jobs document-collection ingest`, `clio jobs statutory-filing sg-cs`). Paired with an interactive CLI blueprint generator (clio jobs).
|
|
5
5
|
license: MIT
|
|
6
6
|
compatibility: Works with Claude Code, Claude Cowork, Claude.ai, and any agent that reads markdown. For API payloads, load the jaz-api skill. For individual transaction patterns, load the jaz-recipes skill.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: jaz-recipes
|
|
3
|
-
version: 4.30.
|
|
3
|
+
version: 4.30.12
|
|
4
4
|
description: 16 IFRS-compliant recipes for complex multi-step accounting in Jaz — prepaid amortization, deferred revenue, loan schedules, IFRS 16 leases, hire purchase, fixed deposits, asset disposal, FX revaluation, ECL provisioning, IAS 37 provisions, dividends, intercompany, and capital WIP. Each recipe includes journal entries, capsule structure, and verification steps. Paired with 13 financial calculators that produce execution-ready blueprints with workings.
|
|
5
5
|
license: MIT
|
|
6
6
|
compatibility: Works with Claude Code, Claude Cowork, Claude.ai, and any agent that reads markdown. For API payloads, load the jaz-api skill alongside this one.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { quickFix, quickFixLineItems, QUICK_FIX_ENTITIES } from '../core/api/quick-fix.js';
|
|
4
|
+
import { QUICK_FIX_ARAP } from '../core/api/quick-fix.js';
|
|
5
|
+
import { apiAction } from './api-action.js';
|
|
6
|
+
function parseJson(source, label) {
|
|
7
|
+
try {
|
|
8
|
+
return JSON.parse(source);
|
|
9
|
+
}
|
|
10
|
+
catch (err) {
|
|
11
|
+
console.error(chalk.red(`Invalid JSON in ${label}: ${err.message}`));
|
|
12
|
+
process.exitCode = 1;
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function registerQuickFixCommand(program) {
|
|
17
|
+
const cmd = program
|
|
18
|
+
.command('quick-fix <entity>')
|
|
19
|
+
.description('Bulk-update transactions or line items in one call')
|
|
20
|
+
.addHelpText('after', `
|
|
21
|
+
Entities (grouped by domain):
|
|
22
|
+
ARAP: invoices, bills, customer-credit-notes, supplier-credit-notes
|
|
23
|
+
Accounting: journals, cash-entries
|
|
24
|
+
Schedulers: sale-schedules, purchase-schedules, subscription-schedules, journal-schedules
|
|
25
|
+
|
|
26
|
+
Examples:
|
|
27
|
+
clio quick-fix invoices --ids id1,id2 --attributes '{"valueDate":"2026-01-15","tags":["Q1"]}'
|
|
28
|
+
clio quick-fix bills --ids id1 --date 2026-02-01 --due 2026-03-01 --tag Marketing
|
|
29
|
+
clio quick-fix journals --line-items --ids li1,li2 --attributes '{"organizationAccountResourceId":"<uuid>"}'
|
|
30
|
+
clio quick-fix sale-schedules --line-items --input scheduler-updates.json`)
|
|
31
|
+
.option('--ids <csv>', 'Comma-separated resourceIds (transaction or line item)')
|
|
32
|
+
.option('--line-items', 'Target line items instead of transactions')
|
|
33
|
+
.option('--attributes <json>', 'Attributes JSON object')
|
|
34
|
+
.option('--input <file>', 'Read attributes/body from JSON file')
|
|
35
|
+
.option('--date <date>', 'Shorthand: set valueDate (YYYY-MM-DD)')
|
|
36
|
+
.option('--due <date>', 'Shorthand: set dueDate (YYYY-MM-DD)')
|
|
37
|
+
.option('--tag <name>', 'Shorthand: set tags to [name]')
|
|
38
|
+
.option('--contact <id>', 'Shorthand: set contactResourceId')
|
|
39
|
+
.option('--account <id>', 'Shorthand: set organizationAccountResourceId (line items)')
|
|
40
|
+
.option('--tax-profile <id>', 'Shorthand: set taxProfileResourceId (line items)')
|
|
41
|
+
.option('--api-key <key>', 'API key')
|
|
42
|
+
.option('--json', 'JSON output')
|
|
43
|
+
.action((entity, opts) => apiAction(async (client) => {
|
|
44
|
+
// ── Validate entity ──────────────────────────────────────
|
|
45
|
+
if (!QUICK_FIX_ENTITIES.includes(entity)) {
|
|
46
|
+
console.error(chalk.red(`Unknown entity: ${entity}`));
|
|
47
|
+
console.error(`Valid entities: ${QUICK_FIX_ENTITIES.join(', ')}`);
|
|
48
|
+
process.exitCode = 1;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// ── Build body ───────────────────────────────────────────
|
|
52
|
+
if (opts.input) {
|
|
53
|
+
const raw = parseJson(readFileSync(opts.input, 'utf-8'), '--input');
|
|
54
|
+
if (!raw)
|
|
55
|
+
return;
|
|
56
|
+
const result = opts.lineItems
|
|
57
|
+
? await quickFixLineItems(client, entity, raw)
|
|
58
|
+
: await quickFix(client, entity, raw);
|
|
59
|
+
formatResult(result, opts.json);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const ids = opts.ids ? opts.ids.split(',').map((s) => s.trim()).filter(Boolean) : [];
|
|
63
|
+
if (ids.length === 0) {
|
|
64
|
+
console.error(chalk.red('--ids is required (comma-separated resourceIds)'));
|
|
65
|
+
process.exitCode = 1;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
// Merge --attributes JSON with shorthand flags
|
|
69
|
+
let attrs = {};
|
|
70
|
+
if (opts.attributes) {
|
|
71
|
+
const parsed = parseJson(opts.attributes, '--attributes');
|
|
72
|
+
if (!parsed)
|
|
73
|
+
return;
|
|
74
|
+
attrs = parsed;
|
|
75
|
+
}
|
|
76
|
+
if (opts.date)
|
|
77
|
+
attrs.valueDate = opts.date;
|
|
78
|
+
if (opts.due)
|
|
79
|
+
attrs.dueDate = opts.due;
|
|
80
|
+
if (opts.tag)
|
|
81
|
+
attrs.tags = [opts.tag];
|
|
82
|
+
if (opts.contact)
|
|
83
|
+
attrs.contactResourceId = opts.contact;
|
|
84
|
+
if (opts.account)
|
|
85
|
+
attrs.organizationAccountResourceId = opts.account;
|
|
86
|
+
if (opts.taxProfile)
|
|
87
|
+
attrs.taxProfileResourceId = opts.taxProfile;
|
|
88
|
+
// ── Pre-flight: require valueDate/dueDate (API treats absent as remove) ──
|
|
89
|
+
if (!opts.lineItems) {
|
|
90
|
+
if (!('valueDate' in attrs)) {
|
|
91
|
+
console.error(chalk.red('valueDate is required in attributes (use --date or include in --attributes)'));
|
|
92
|
+
console.error(chalk.dim('The API currently treats absent fields as "remove". Server-side fix pending.'));
|
|
93
|
+
process.exitCode = 1;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (QUICK_FIX_ARAP.includes(entity) && !('dueDate' in attrs)) {
|
|
97
|
+
console.error(chalk.red('dueDate is required for ARAP entities (use --due or include in --attributes)'));
|
|
98
|
+
console.error(chalk.dim('The API currently treats absent fields as "remove". Server-side fix pending.'));
|
|
99
|
+
process.exitCode = 1;
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (opts.lineItems) {
|
|
104
|
+
const result = await quickFixLineItems(client, entity, {
|
|
105
|
+
lineItemResourceIds: ids,
|
|
106
|
+
attributes: attrs,
|
|
107
|
+
});
|
|
108
|
+
formatResult(result, opts.json);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
const result = await quickFix(client, entity, {
|
|
112
|
+
resourceIds: ids,
|
|
113
|
+
attributes: attrs,
|
|
114
|
+
});
|
|
115
|
+
formatResult(result, opts.json);
|
|
116
|
+
}
|
|
117
|
+
})(opts));
|
|
118
|
+
}
|
|
119
|
+
function formatResult(result, json) {
|
|
120
|
+
if (json) {
|
|
121
|
+
console.log(JSON.stringify(result, null, 2));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (result.updated.length > 0) {
|
|
125
|
+
console.log(chalk.green(`Updated ${result.updated.length} item(s):`));
|
|
126
|
+
for (const id of result.updated)
|
|
127
|
+
console.log(` ${chalk.cyan(id)}`);
|
|
128
|
+
}
|
|
129
|
+
if (result.failed.length > 0) {
|
|
130
|
+
console.log(chalk.red(`Failed ${result.failed.length} item(s):`));
|
|
131
|
+
for (const f of result.failed) {
|
|
132
|
+
console.log(` ${chalk.cyan(f.resourceId)} ${chalk.red(f.error)}${f.errorCode ? ` (${f.errorCode})` : ''}`);
|
|
133
|
+
}
|
|
134
|
+
process.exitCode = 1;
|
|
135
|
+
}
|
|
136
|
+
if (result.updated.length === 0 && result.failed.length === 0) {
|
|
137
|
+
console.log('No items processed.');
|
|
138
|
+
}
|
|
139
|
+
}
|
package/dist/core/api/index.js
CHANGED
|
@@ -33,5 +33,6 @@ export * as subscriptions from './subscriptions.js';
|
|
|
33
33
|
export * as contactGroups from './contact-groups.js';
|
|
34
34
|
export * as inventory from './inventory.js';
|
|
35
35
|
export * as search from './search.js';
|
|
36
|
+
export * as quickFix from './quick-fix.js';
|
|
36
37
|
// ── Guards (pre-flight checks for create operations) ────────────
|
|
37
38
|
export * from './guards.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// ── Entity Groups ────────────────────────────────────────────────
|
|
2
|
+
// Grouped by domain — values are API path segments for /api/v1/quick-fix/{entity}
|
|
3
|
+
export const QUICK_FIX_ARAP = ['invoices', 'bills', 'customer-credit-notes', 'supplier-credit-notes'];
|
|
4
|
+
const QUICK_FIX_ACCOUNTING = ['journals', 'cash-entries'];
|
|
5
|
+
const QUICK_FIX_SCHEDULERS = ['sale-schedules', 'purchase-schedules', 'subscription-schedules', 'journal-schedules'];
|
|
6
|
+
export const QUICK_FIX_ENTITIES = [...QUICK_FIX_ARAP, ...QUICK_FIX_ACCOUNTING, ...QUICK_FIX_SCHEDULERS];
|
|
7
|
+
// ── Transaction-Level Quick Fix ──────────────────────────────────
|
|
8
|
+
export async function quickFix(client, entity, body) {
|
|
9
|
+
return client.post(`/api/v1/quick-fix/${entity}`, body);
|
|
10
|
+
}
|
|
11
|
+
// ── Line-Item-Level Quick Fix ────────────────────────────────────
|
|
12
|
+
// ARAP: { lineItemResourceIds: string[], attributes: {...} }
|
|
13
|
+
// Schedulers: { schedulerUpdates: [{ schedulerResourceId, lineItemUpdates: [...] }] }
|
|
14
|
+
export async function quickFixLineItems(client, entity, body) {
|
|
15
|
+
return client.post(`/api/v1/quick-fix/${entity}/line-items`, body);
|
|
16
|
+
}
|
|
@@ -125,6 +125,12 @@ export const TOOL_NAMESPACES = [
|
|
|
125
125
|
description: 'Payments search/list across all transaction types. Cashflow transaction ledger. Universal cross-entity search. Transaction summary (fetch any transaction + attachments + payment history in one call).',
|
|
126
126
|
groups: ['payments', 'cashflow', 'search'],
|
|
127
127
|
},
|
|
128
|
+
// ── Quick Fix (Bulk Update) ────────────────────────────────
|
|
129
|
+
{
|
|
130
|
+
name: 'quick_fix',
|
|
131
|
+
description: 'Quick Fix: bulk-update multiple transactions or line items in one call. Change dates, contacts, tags, accounts, tax profiles, custom fields across many invoices/bills/journals/credit-notes/cash-entries/schedulers at once. Also: batch update, mass edit.',
|
|
132
|
+
groups: ['quick_fix'],
|
|
133
|
+
},
|
|
128
134
|
// ── Drafts ──────────────────────────────────────────────────
|
|
129
135
|
{
|
|
130
136
|
name: 'drafts',
|
|
@@ -39,6 +39,7 @@ import { listContactGroups, getContactGroup, searchContactGroups, createContactG
|
|
|
39
39
|
import { listInventoryItems, getInventoryBalance } from '../api/inventory.js';
|
|
40
40
|
import { universalSearch } from '../api/search.js';
|
|
41
41
|
import { listCustomFields, getCustomField, searchCustomFields, createCustomField, updateCustomField, deleteCustomField } from '../api/custom-fields.js';
|
|
42
|
+
import { quickFix, quickFixLineItems, QUICK_FIX_ENTITIES } from '../api/quick-fix.js';
|
|
42
43
|
// Job blueprints (offline — no API calls)
|
|
43
44
|
import { generateMonthEndBlueprint } from '../jobs/month-end/blueprint.js';
|
|
44
45
|
import { generateQuarterEndBlueprint } from '../jobs/quarter-end/blueprint.js';
|
|
@@ -652,6 +653,18 @@ export const TOOL_DEFINITIONS = [
|
|
|
652
653
|
execute: async (ctx, input) => {
|
|
653
654
|
const { resourceId: rid, ...overrides } = input;
|
|
654
655
|
const merged = await fetchAndMerge(ctx.client, 'invoice', rid, overrides);
|
|
656
|
+
// Dedup guard: if reference already exists on another invoice, auto-suffix to avoid 422
|
|
657
|
+
if (merged.reference) {
|
|
658
|
+
const ref = merged.reference;
|
|
659
|
+
const existing = await searchInvoices(ctx.client, {
|
|
660
|
+
filter: { reference: { eq: ref } }, limit: 1, offset: 0,
|
|
661
|
+
sort: { sortBy: ['valueDate'], order: 'DESC' },
|
|
662
|
+
});
|
|
663
|
+
const dupes = (existing.data ?? []).filter((inv) => inv.resourceId !== rid);
|
|
664
|
+
if (dupes.length > 0) {
|
|
665
|
+
merged.reference = `${ref}-${Date.now() % 10000}`;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
655
668
|
return finalizeInvoice(ctx.client, rid, merged);
|
|
656
669
|
},
|
|
657
670
|
},
|
|
@@ -1792,8 +1805,8 @@ Steps: 1) search_customer_credit_notes with status UNAPPLIED for the same contac
|
|
|
1792
1805
|
WHEN TO USE: customer payments received, refunds from suppliers, insurance payouts, external deposits.
|
|
1793
1806
|
WHEN NOT TO USE: moving money between your own bank/cash accounts — use create_cash_transfer instead.
|
|
1794
1807
|
- accountResourceId MUST be a Bank Accounts type account — use list_bank_accounts or search_accounts with accountType "Bank Accounts" to find the correct one. Non-bank accounts are rejected.
|
|
1795
|
-
- journalEntries are the offsetting entries
|
|
1796
|
-
- The API enforces account separation: cash-in
|
|
1808
|
+
- journalEntries are the offsetting entries. Each needs accountResourceId, type (DEBIT/CREDIT), and amount. IMPORTANT: offset accounts must be regular P&L or balance sheet accounts (expense, revenue, asset, liability) — NOT bank/cash accounts or controlled accounts (AR/AP). Example: Service Revenue, Interest Income, Other Income.
|
|
1809
|
+
- The API enforces account separation: cash-in bank account cannot appear in journalEntries.`,
|
|
1797
1810
|
params: {
|
|
1798
1811
|
reference: { type: 'string', description: 'Reference number' },
|
|
1799
1812
|
valueDate: { type: 'string', description: 'Date (YYYY-MM-DD)' },
|
|
@@ -1821,8 +1834,8 @@ WHEN NOT TO USE: moving money between your own bank/cash accounts — use create
|
|
|
1821
1834
|
WHEN TO USE: expenses paid, supplier payments, reimbursements, withdrawals to external parties.
|
|
1822
1835
|
WHEN NOT TO USE: moving money between your own bank/cash accounts — use create_cash_transfer instead.
|
|
1823
1836
|
- accountResourceId MUST be a Bank Accounts type account — use list_bank_accounts or search_accounts with accountType "Bank Accounts" to find the correct one. Non-bank accounts are rejected.
|
|
1824
|
-
- journalEntries are the offsetting entries
|
|
1825
|
-
- The API enforces account separation: cash-out
|
|
1837
|
+
- journalEntries are the offsetting entries. Each needs accountResourceId, type (DEBIT/CREDIT), and amount. IMPORTANT: offset accounts must be regular P&L or balance sheet accounts (expense, revenue, asset, liability) — NOT bank/cash accounts or controlled accounts (AR/AP). Example: Utilities Expense, Office Supplies, Service Revenue.
|
|
1838
|
+
- The API enforces account separation: cash-out bank account cannot appear in journalEntries.`,
|
|
1826
1839
|
params: {
|
|
1827
1840
|
reference: { type: 'string', description: 'Reference number' },
|
|
1828
1841
|
valueDate: { type: 'string', description: 'Date (YYYY-MM-DD)' },
|
|
@@ -1871,7 +1884,7 @@ WHEN NOT TO USE: moving money between your own bank/cash accounts — use create
|
|
|
1871
1884
|
readOnly: false,
|
|
1872
1885
|
execute: async (ctx, input) => {
|
|
1873
1886
|
const { resourceId: rid, ...data } = input;
|
|
1874
|
-
return updateCashIn(ctx.client, rid,
|
|
1887
|
+
return updateCashIn(ctx.client, rid, data);
|
|
1875
1888
|
},
|
|
1876
1889
|
},
|
|
1877
1890
|
{
|
|
@@ -1902,7 +1915,7 @@ WHEN NOT TO USE: moving money between your own bank/cash accounts — use create
|
|
|
1902
1915
|
readOnly: false,
|
|
1903
1916
|
execute: async (ctx, input) => {
|
|
1904
1917
|
const { resourceId: rid, ...data } = input;
|
|
1905
|
-
return updateCashOut(ctx.client, rid,
|
|
1918
|
+
return updateCashOut(ctx.client, rid, data);
|
|
1906
1919
|
},
|
|
1907
1920
|
},
|
|
1908
1921
|
// ── Cash Transfers ─────────────────────────────────────────────
|
|
@@ -2236,7 +2249,8 @@ Available export types: trial-balance, balance-sheet, profit-and-loss, general-l
|
|
|
2236
2249
|
// ── Recipes ───────────────────────────────────────────────────
|
|
2237
2250
|
{
|
|
2238
2251
|
name: 'plan_recipe',
|
|
2239
|
-
description: `Plan a transaction recipe — run a financial calculator and show what accounts, contacts, and bank accounts are needed. This is READ-ONLY (no API calls, no transactions created).
|
|
2252
|
+
description: `Plan a transaction recipe — run a financial calculator and show what accounts, contacts, and bank accounts are needed. This is READ-ONLY (no API calls, no transactions created).
|
|
2253
|
+
After planning, ALWAYS use execute_recipe to create all transactions in one call — do NOT manually create journals/invoices/bills.
|
|
2240
2254
|
Supported recipes: ${RECIPE_TYPES.join(', ')}
|
|
2241
2255
|
Returns: capsule type/name, required accounts, step breakdown (journal/bill/invoice/cash-in/cash-out), and full calculator results.
|
|
2242
2256
|
Use this BEFORE execute_recipe to verify requirements. Parameters vary by recipe — see recipe skill docs for per-recipe params.
|
|
@@ -2294,8 +2308,8 @@ CRITICAL: ALWAYS call this tool for ANY calculation involving: depreciation, amo
|
|
|
2294
2308
|
},
|
|
2295
2309
|
{
|
|
2296
2310
|
name: 'execute_recipe',
|
|
2297
|
-
description: `Execute a transaction recipe end-to-end — run calculator, create capsule, post all entries.
|
|
2298
|
-
|
|
2311
|
+
description: `Execute a transaction recipe end-to-end — run calculator, create capsule, post all entries in one call.
|
|
2312
|
+
PREFERRED over manual transaction creation — replaces ~20 manual tool calls. After plan_recipe, ALWAYS use this tool (not create_journal/create_invoice/create_cash_out).
|
|
2299
2313
|
Supported recipes: ${RECIPE_TYPES.join(', ')}
|
|
2300
2314
|
Requires startDate (to generate blueprint with dated steps).
|
|
2301
2315
|
Auto-resolves accounts from chart of accounts. Provide bankAccountName for recipes with cash-in/cash-out steps, contactName for recipes with invoice/bill steps.`,
|
|
@@ -3064,14 +3078,15 @@ CRITICAL:
|
|
|
3064
3078
|
{
|
|
3065
3079
|
name: 'create_bank_rule',
|
|
3066
3080
|
description: `Create a bank reconciliation rule. Rules auto-match bank records to transactions during reconciliation.
|
|
3067
|
-
- actionType: "RECONCILE_WITH_DIRECT_CASH_ENTRY" (most common)
|
|
3081
|
+
- actionType: "RECONCILE_WITH_DIRECT_CASH_ENTRY" (most common — creates cash-in/cash-out on match)
|
|
3068
3082
|
- appliesToReconciliationAccountResourceId: the bank account this rule applies to
|
|
3069
|
-
- configuration:
|
|
3083
|
+
- configuration MUST include: allocationType ("PERCENTAGE" or "FIXED"), allocationDetails array with organizationAccountResourceId + percentage (or fixedAmount) + optional taxProfileResourceId
|
|
3084
|
+
Example configuration: { "allocationType": "PERCENTAGE", "allocationDetails": [{ "organizationAccountResourceId": "<revenue-account-id>", "percentage": 100 }] }`,
|
|
3070
3085
|
params: {
|
|
3071
|
-
name: { type: 'string', description: 'Rule name (e.g., "PayNow Sales")' },
|
|
3072
|
-
actionType: { type: 'string', description: 'Action type
|
|
3086
|
+
name: { type: 'string', description: 'Rule name (e.g., "PayNow Sales", "STRIPE Payouts")' },
|
|
3087
|
+
actionType: { type: 'string', description: 'Action type: "RECONCILE_WITH_DIRECT_CASH_ENTRY" (creates cash entry on match)' },
|
|
3073
3088
|
appliesToReconciliationAccountResourceId: { type: 'string', description: 'Bank account resourceId this rule applies to' },
|
|
3074
|
-
configuration: { type: 'object', description: '
|
|
3089
|
+
configuration: { type: 'object', description: 'Required structure: { allocationType: "PERCENTAGE"|"FIXED", allocationDetails: [{ organizationAccountResourceId: "<account-id>", percentage: 100, taxProfileResourceId?: "<tax-id>" }] }' },
|
|
3075
3090
|
},
|
|
3076
3091
|
required: ['name', 'actionType', 'appliesToReconciliationAccountResourceId', 'configuration'],
|
|
3077
3092
|
group: 'bank_rules',
|
|
@@ -3319,7 +3334,7 @@ Use for: software licenses, retainer services, recurring SaaS billing. Invoices
|
|
|
3319
3334
|
description: 'Line items (name, unitPrice, quantity only — account/tax set at top level)',
|
|
3320
3335
|
},
|
|
3321
3336
|
},
|
|
3322
|
-
required: ['interval', 'startDate', 'contactResourceId', 'lineItems', 'accountResourceId'],
|
|
3337
|
+
required: ['interval', 'startDate', 'contactResourceId', 'lineItems', 'accountResourceId', 'valueDate', 'dueDate'],
|
|
3323
3338
|
group: 'subscriptions',
|
|
3324
3339
|
readOnly: false,
|
|
3325
3340
|
execute: async (ctx, input) => {
|
|
@@ -3483,11 +3498,11 @@ Use for: software licenses, retainer services, recurring SaaS billing. Invoices
|
|
|
3483
3498
|
},
|
|
3484
3499
|
{
|
|
3485
3500
|
name: 'generate_fa_summary',
|
|
3486
|
-
description: 'Generate fixed assets summary report grouped by type,
|
|
3501
|
+
description: 'Generate fixed assets summary report grouped by account, type, category, or status.',
|
|
3487
3502
|
params: {
|
|
3488
3503
|
primarySnapshotStartDate: { type: 'string', description: 'Period start date (YYYY-MM-DD)' },
|
|
3489
3504
|
primarySnapshotEndDate: { type: 'string', description: 'Period end date (YYYY-MM-DD)' },
|
|
3490
|
-
groupBy: { type: 'string', enum: ['
|
|
3505
|
+
groupBy: { type: 'string', enum: ['ACCOUNT', 'TYPE', 'CATEGORY', 'STATUS'], description: 'Grouping dimension' },
|
|
3491
3506
|
currencyCode: { type: 'string', description: 'Currency code' },
|
|
3492
3507
|
},
|
|
3493
3508
|
required: ['primarySnapshotStartDate', 'primarySnapshotEndDate', 'groupBy'],
|
|
@@ -3966,4 +3981,53 @@ Returns per-contact result: created, skipped (duplicate), or failed.`,
|
|
|
3966
3981
|
};
|
|
3967
3982
|
},
|
|
3968
3983
|
},
|
|
3984
|
+
// ══════════════════════════════════════════════════════════════
|
|
3985
|
+
// ── Quick Fix (Bulk Update) ─────────────────────────────────
|
|
3986
|
+
// ══════════════════════════════════════════════════════════════
|
|
3987
|
+
{
|
|
3988
|
+
name: 'quick_fix_transactions',
|
|
3989
|
+
description: 'Bulk-update multiple transactions of the same type in one call. Pass resourceIds + attributes — only present fields are changed. ARAP: invoices, bills, customer-credit-notes, supplier-credit-notes. Accounting: journals, cash-entries. Schedulers: sale-schedules, purchase-schedules, subscription-schedules, journal-schedules. Common attributes: valueDate, contactResourceId, tags, capsuleResourceId. Entity-specific: dueDate (invoices/bills/CNs), invoiceNotes, templateResourceId, currencySettings, taxCurrencySettings, customFields. NOTE: valueDate (and dueDate for invoices/bills) must currently be included even if unchanged.',
|
|
3990
|
+
params: {
|
|
3991
|
+
entity: { type: 'string', enum: [...QUICK_FIX_ENTITIES], description: 'Transaction type to update' },
|
|
3992
|
+
resourceIds: { type: 'array', items: { type: 'string' }, description: 'Array of transaction resourceIds to update' },
|
|
3993
|
+
attributes: { type: 'object', description: 'Fields to update — only present fields are changed. Common: valueDate, contactResourceId, tags, capsuleResourceId. Invoices/bills: dueDate, currencySettings, taxCurrencySettings, customFields. Invoices/CNs: invoiceNotes, templateResourceId, billFrom, billTo. Schedulers: endDate, interval.' },
|
|
3994
|
+
},
|
|
3995
|
+
required: ['entity', 'resourceIds', 'attributes'],
|
|
3996
|
+
group: 'quick_fix',
|
|
3997
|
+
readOnly: false,
|
|
3998
|
+
execute: async (ctx, input) => quickFix(ctx.client, input.entity, {
|
|
3999
|
+
resourceIds: input.resourceIds,
|
|
4000
|
+
attributes: input.attributes,
|
|
4001
|
+
}),
|
|
4002
|
+
},
|
|
4003
|
+
{
|
|
4004
|
+
name: 'quick_fix_line_items',
|
|
4005
|
+
description: 'Bulk-update line items across multiple transactions. For ARAP (invoices, bills, credit notes) and accounting (journals, cash-entries): pass lineItemResourceIds + attributes. For schedulers: pass schedulerUpdates array with per-scheduler lineItemUpdates. ARAP line item attributes: name, quantity, unit, unitPrice, discount, itemResourceId, organizationAccountResourceId, taxProfileResourceId, classifierConfig. Bill/supplier-CN also: withholdingTax. Journal/cash-entry line items: organizationAccountResourceId, amount, description, taxProfileResourceId, classifierConfig.',
|
|
4006
|
+
params: {
|
|
4007
|
+
entity: { type: 'string', enum: [...QUICK_FIX_ENTITIES], description: 'Transaction type' },
|
|
4008
|
+
lineItemResourceIds: { type: 'array', items: { type: 'string' }, description: 'Line item resourceIds to update (ARAP + accounting entities)' },
|
|
4009
|
+
attributes: { type: 'object', description: 'Fields to update on all specified line items' },
|
|
4010
|
+
schedulerUpdates: { type: 'array', items: { type: 'object' }, description: 'Per-scheduler updates (scheduler entities only): [{ schedulerResourceId, lineItemUpdates: [{ arrayIndex, ...fields }] }]' },
|
|
4011
|
+
},
|
|
4012
|
+
required: ['entity'],
|
|
4013
|
+
group: 'quick_fix',
|
|
4014
|
+
readOnly: false,
|
|
4015
|
+
execute: async (ctx, input) => {
|
|
4016
|
+
const entity = input.entity;
|
|
4017
|
+
const isScheduler = ['sale-schedules', 'purchase-schedules', 'subscription-schedules', 'journal-schedules'].includes(entity);
|
|
4018
|
+
const body = {};
|
|
4019
|
+
if (isScheduler) {
|
|
4020
|
+
if (!input.schedulerUpdates)
|
|
4021
|
+
throw new Error('schedulerUpdates is required for scheduler entities (sale-schedules, purchase-schedules, subscription-schedules, journal-schedules)');
|
|
4022
|
+
body.schedulerUpdates = input.schedulerUpdates;
|
|
4023
|
+
}
|
|
4024
|
+
else {
|
|
4025
|
+
if (!input.lineItemResourceIds)
|
|
4026
|
+
throw new Error('lineItemResourceIds is required for non-scheduler entities');
|
|
4027
|
+
body.lineItemResourceIds = input.lineItemResourceIds;
|
|
4028
|
+
body.attributes = input.attributes ?? {};
|
|
4029
|
+
}
|
|
4030
|
+
return quickFixLineItems(ctx.client, entity, body);
|
|
4031
|
+
},
|
|
4032
|
+
},
|
|
3969
4033
|
];
|
package/dist/index.js
CHANGED
|
@@ -49,6 +49,7 @@ import { registerContactGroupsCommand } from './commands/contact-groups.js';
|
|
|
49
49
|
import { registerInventoryCommand } from './commands/inventory.js';
|
|
50
50
|
import { registerSearchCommand } from './commands/search.js';
|
|
51
51
|
import { registerCustomFieldsCommand } from './commands/custom-fields.js';
|
|
52
|
+
import { registerQuickFixCommand } from './commands/quick-fix.js';
|
|
52
53
|
import { registerSchemaCommand } from './commands/schema.js';
|
|
53
54
|
import { applyAllExamples } from './commands/help-examples.js';
|
|
54
55
|
import { shouldShowPicker, showCommandPicker, attachSubcommandPickers } from './commands/picker.js';
|
|
@@ -161,6 +162,7 @@ registerContactGroupsCommand(program);
|
|
|
161
162
|
registerInventoryCommand(program);
|
|
162
163
|
registerSearchCommand(program);
|
|
163
164
|
registerCustomFieldsCommand(program);
|
|
165
|
+
registerQuickFixCommand(program);
|
|
164
166
|
registerSchemaCommand(program);
|
|
165
167
|
applyAllExamples(program);
|
|
166
168
|
// Add --org to every command that has --api-key (DRY: zero changes to command files)
|