jaz-clio 5.65.0 → 5.65.1
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/assets/skills/api/SKILL.md +4 -4
- package/assets/skills/api/references/search-enums.md +2 -2
- package/assets/skills/cli/SKILL.md +1 -1
- package/assets/skills/cli/references/error-recovery.md +1 -1
- package/assets/skills/conversion/SKILL.md +1 -1
- package/assets/skills/jaz-kit/SKILL.md +1 -1
- package/assets/skills/jaz-pseudo-sql/SKILL.md +1 -1
- package/assets/skills/jaz-pseudo-sql/references/error-catalog.md +1 -1
- package/assets/skills/jobs/SKILL.md +1 -1
- package/assets/skills/jobs/references/audit-prep.md +30 -30
- package/assets/skills/jobs/references/bank-recon.md +18 -21
- package/assets/skills/jobs/references/building-blocks.md +7 -7
- package/assets/skills/jobs/references/credit-control.md +21 -22
- package/assets/skills/jobs/references/document-collection.md +9 -11
- package/assets/skills/jobs/references/fa-review.md +18 -19
- package/assets/skills/jobs/references/gst-vat-filing.md +5 -5
- package/assets/skills/jobs/references/month-end-close.md +23 -23
- package/assets/skills/jobs/references/payment-run.md +22 -24
- package/assets/skills/jobs/references/quarter-end-close.md +14 -14
- package/assets/skills/jobs/references/supplier-recon.md +7 -7
- package/assets/skills/jobs/references/year-end-close.md +13 -18
- package/assets/skills/transaction-recipes/SKILL.md +3 -3
- package/assets/skills/transaction-recipes/references/accrued-expenses.md +8 -13
- package/assets/skills/transaction-recipes/references/asset-disposal.md +14 -21
- package/assets/skills/transaction-recipes/references/bad-debt-provision.md +22 -23
- package/assets/skills/transaction-recipes/references/bank-loan.md +7 -13
- package/assets/skills/transaction-recipes/references/building-blocks.md +16 -15
- package/assets/skills/transaction-recipes/references/capital-wip.md +30 -25
- package/assets/skills/transaction-recipes/references/declining-balance.md +4 -8
- package/assets/skills/transaction-recipes/references/deferred-revenue.md +6 -11
- package/assets/skills/transaction-recipes/references/dividend.md +9 -16
- package/assets/skills/transaction-recipes/references/employee-accruals.md +10 -19
- package/assets/skills/transaction-recipes/references/fixed-deposit.md +5 -11
- package/assets/skills/transaction-recipes/references/fx-revaluation.md +10 -9
- package/assets/skills/transaction-recipes/references/hire-purchase.md +15 -10
- package/assets/skills/transaction-recipes/references/ifrs16-lease.md +25 -27
- package/assets/skills/transaction-recipes/references/intercompany.md +30 -34
- package/assets/skills/transaction-recipes/references/prepaid-amortization.md +6 -11
- package/assets/skills/transaction-recipes/references/provisions.md +5 -12
- package/cli.mjs +3 -3
- package/package.json +1 -1
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
### Platform tools
|
|
8
8
|
- **`search_fixed_assets(filter: {status: {in: ['ACTIVE', 'DISPOSED', 'DISCARDED']}}, limit: 200)`** — step 1: enumerate FAs. Paginate.
|
|
9
|
-
- **`get_fixed_asset(resourceId: <id>)`** — step 2: per-asset detail (
|
|
10
|
-
- **`generate_fa_summary(
|
|
11
|
-
- **`generate_fa_recon_summary(
|
|
12
|
-
- **`generate_general_ledger(
|
|
13
|
-
- **`mark_fixed_asset_sold(resourceId: <id>, disposalDate,
|
|
9
|
+
- **`get_fixed_asset(resourceId: <id>)`** — step 2: per-asset detail (purchaseAmount, purchaseDate, depreciationStartDate, effectiveLife in months, depreciationMethod, depreciableValueResidualAmount, NBV).
|
|
10
|
+
- **`generate_fa_summary(primarySnapshotStartDate: <period-start>, primarySnapshotEndDate: <period-end>, groupBy: 'CATEGORY')`** — step 3: aggregate FA register at period end.
|
|
11
|
+
- **`generate_fa_recon_summary(primarySnapshotStartDate: <year-start>, primarySnapshotEndDate: <year-end>)`** — step 3: reconcile movement (opening + additions − disposals − depreciation = closing).
|
|
12
|
+
- **`generate_general_ledger(accountResourceIds: [<FA category GL>], startDate, endDate)`** — step 4: per-FA-category GL movement vs FA register.
|
|
13
|
+
- **`mark_fixed_asset_sold(resourceId: <id>, depreciationEndDate, assetDisposalGainLossAccountResourceId, saleBusinessTransactionType, saleItemResourceId)` / `discard_fixed_asset(resourceId: <id>, disposalDate, depreciationEndDate)`** — step 5: status updates for disposals. Mirror endpoints `POST /api/v1/mark-as-sold/fixed-assets` (sale) / `POST /api/v1/discard-fixed-assets/{id}` (scrap).
|
|
14
14
|
- **`plan_recipe(recipe: 'asset-disposal', ...)` + `execute_recipe(...)`** — step 5: invoke per disposal identified during review (see the `asset-disposal` recipe).
|
|
15
15
|
- **`bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`** — step 5 / 6: finalize disposal journals + any pending DDB / 150DB depreciation DRAFTs from the `depreciation` recipe.
|
|
16
16
|
|
|
@@ -42,7 +42,7 @@ Paginate via offset. For year-end review: include DISPOSED and DISCARDED (dispos
|
|
|
42
42
|
|
|
43
43
|
For each ACTIVE asset, flag for practitioner attention:
|
|
44
44
|
- **Fully depreciated** (`NBV == salvageValue` per FA summary): consider disposal if no longer in use; consider impairment review per IAS 36 if NBV > recoverable amount.
|
|
45
|
-
- **Recently acquired without `
|
|
45
|
+
- **Recently acquired without `effectiveLife`**: depreciation can't run; halt and surface.
|
|
46
46
|
- **Pre-flagged by the user as a disposal candidate**: act on it.
|
|
47
47
|
- **Damaged / no longer in use** (per practitioner inspection): write off.
|
|
48
48
|
- **Mid-life disposals** (sold or traded in during the period): per asset-disposal recipe.
|
|
@@ -50,21 +50,21 @@ For each ACTIVE asset, flag for practitioner attention:
|
|
|
50
50
|
## Step 3 — FA register reconciliation
|
|
51
51
|
|
|
52
52
|
```
|
|
53
|
-
generate_fa_summary(
|
|
54
|
-
generate_fa_recon_summary(
|
|
53
|
+
generate_fa_summary(primarySnapshotStartDate: '2025-01-01', primarySnapshotEndDate: '2025-12-31', groupBy: 'CATEGORY')
|
|
54
|
+
generate_fa_recon_summary(primarySnapshotStartDate: '2025-01-01', primarySnapshotEndDate: '2025-12-31')
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
Keep both the FA summary and the recon summary. Assert per FA category:
|
|
58
58
|
- `closingNbv == openingNbv + additions - disposals - depreciation` (the recon formula).
|
|
59
59
|
- Sum of per-asset NBV in the register equals TB `<FA cost> - <Accumulated Depreciation>` line for that category.
|
|
60
60
|
|
|
61
|
-
If mismatch beyond the materiality threshold: investigate via `generate_general_ledger(
|
|
61
|
+
If mismatch beyond the materiality threshold: investigate via `generate_general_ledger(accountResourceIds: [<FA category cost GL>], startDate, endDate)`. Common: a disposal posted via the `asset-disposal` recipe but the step 5 `mark_fixed_asset_sold` / `discard_fixed_asset` was missed — Jaz continues auto-depreciating.
|
|
62
62
|
|
|
63
63
|
## Step 4 — Depreciation cross-check
|
|
64
64
|
|
|
65
65
|
For each ACTIVE SL asset (Jaz auto-depreciates):
|
|
66
|
-
- Pull FA's expected annual depreciation: `(
|
|
67
|
-
- Compare to actual `generate_general_ledger(
|
|
66
|
+
- Pull FA's expected annual depreciation: `(purchaseAmount - depreciableValueResidualAmount) / (effectiveLife / 12)`.
|
|
67
|
+
- Compare to actual `generate_general_ledger(accountResourceIds: [<Depreciation Expense for this category>], startDate: <year-start>, endDate: <year-end>)` movement.
|
|
68
68
|
- Should match within rounding ($0.12 tolerance for full-year SL).
|
|
69
69
|
|
|
70
70
|
For each ACTIVE DDB / 150DB asset (recipe-managed, see the `depreciation` recipe):
|
|
@@ -79,13 +79,10 @@ For each disposal identified in step 2:
|
|
|
79
79
|
|
|
80
80
|
```
|
|
81
81
|
plan_recipe(
|
|
82
|
-
//
|
|
82
|
+
// Accounts, capsule and counterparty are not plan_recipe params: execute_recipe resolves accounts from the CoA and takes bankAccountName / contactName.
|
|
83
83
|
recipe: 'asset-disposal',
|
|
84
84
|
cost, salvageValue, usefulLifeYears, acquisitionDate, disposalDate, proceeds, method,
|
|
85
|
-
|
|
86
|
-
fixedAssetResourceId: <asset id>,
|
|
87
|
-
capsuleType: 'Asset Disposal',
|
|
88
|
-
capsuleName: 'Disposal — <asset name> — <disposal date>'
|
|
85
|
+
...
|
|
89
86
|
)
|
|
90
87
|
execute_recipe(...)
|
|
91
88
|
update_journal(resourceId: <disposal journal id>, saveAsDraft: false)
|
|
@@ -93,7 +90,9 @@ update_journal(resourceId: <disposal journal id>, saveAsDraft: false)
|
|
|
93
90
|
|
|
94
91
|
Then the manual FA-register status update (engine-skipped — see the `asset-disposal` recipe):
|
|
95
92
|
```
|
|
96
|
-
|
|
93
|
+
mark_fixed_asset_sold(resourceId: <asset id>, depreciationEndDate, assetDisposalGainLossAccountResourceId, saleBusinessTransactionType, saleItemResourceId)
|
|
94
|
+
// or, for a write-off with no sale:
|
|
95
|
+
discard_fixed_asset(resourceId: <asset id>, disposalDate, depreciationEndDate)
|
|
97
96
|
```
|
|
98
97
|
|
|
99
98
|
For scrap / write-off (no proceeds): `discard_fixed_asset(...)` — its own description is "Discard (write off) a fixed asset". There is no `WRITTEN_OFF` status; the declared set is ACTIVE, ONGOING, COMPLETED, DRAFT, DISPOSED, SOLD, DISCARDED, CLOSED_OUT.
|
|
@@ -109,7 +108,7 @@ For assets at salvage value AND no longer in use:
|
|
|
109
108
|
|
|
110
109
|
For each FA category (e.g., Vehicles, Office Equipment, Computers, Buildings):
|
|
111
110
|
```
|
|
112
|
-
generate_general_ledger(
|
|
111
|
+
generate_general_ledger(accountResourceIds: [<FA cost GL>], startDate: '2025-01-01', endDate: '2025-12-31', groupBy: 'ACCOUNT')
|
|
113
112
|
```
|
|
114
113
|
|
|
115
114
|
Group by capsule shows per-asset / per-disposal trail. Auditor sample-test will pick 2-3 assets per category and trace GL → original purchase bill → FA registration → depreciation history → disposal (if any).
|
|
@@ -133,7 +132,7 @@ These feed `audit-prep.md` step 8 supporting schedules.
|
|
|
133
132
|
| Step 1 | `search_fixed_assets` returns more than the page limit | Paginate via `offset`. Most SMBs have <100 FAs. |
|
|
134
133
|
| Step 3 | Recon doesn't tie | Disposed asset still ACTIVE in register (the `asset-disposal` recipe leaves the FA-register status update to you). Audit each disposal's status. |
|
|
135
134
|
| Step 4 | DDB / 150DB DRAFTs unfinalized | Likely a missed monthly close. Finalize the current ones and surface to the user — the auditor will otherwise see 12 months' depreciation in one period. |
|
|
136
|
-
| Step 4 | SL depreciation off by > $0.12 | A monthly depreciation period was skipped (asset created mid-month with mis-aligned `
|
|
135
|
+
| Step 4 | SL depreciation off by > $0.12 | A monthly depreciation period was skipped (asset created mid-month with mis-aligned `depreciationStartDate`). Reconcile per asset. |
|
|
137
136
|
| Step 5 | `update_fixed_asset` to DISPOSED | 422 `pending_depreciation_journals` | DRAFT depreciation journals exist for periods after disposal date. **Do not select these with a filter** — journals cannot be narrowed to one fixed asset (`JournalFilter` has no `fixedAssetResourceId`, and a journal row carries no asset link), so a date+status search returns every DRAFT in the org and `delete_journal` over it would destroy unrelated work. Surface the asset and the blocking periods to the practitioner and let them identify the journals, then retry. |
|
|
138
137
|
| Step 6 | Trying to dispose an FA at NBV = 0 with no proceeds | Recipe still works but creates a no-effect journal. May be skippable; surface to practitioner. |
|
|
139
138
|
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
## Tools, recipes, calculators this job uses
|
|
6
6
|
|
|
7
7
|
### Platform tools
|
|
8
|
-
- **`generate_vat_ledger(
|
|
8
|
+
- **`generate_vat_ledger(startDate: <period-start>, endDate: <period-end>)`** — step 1: the canonical tax ledger. Returns input + output tax totals + per-tax-profile breakdown.
|
|
9
9
|
- **`search_tax_profiles(filter: {})`** — step 2 setup verification: confirm all expected tax profiles exist (`SR`, `ZR`, `ES`, `IES`, `OS`, `TX`, `BL`, `OP`, `EP`, `RC` for SG; `VAT-RC`, `VAT-EXP`, `VAT-ZR`, `VAT-EXM`, `VAT-EXC` for PH).
|
|
10
10
|
- **`search_invoices(filter: {valueDate: {between: [<period-start>, <period-end>]}}, limit: 200)`** — step 3 output-tax detail: per-invoice GST cross-check against tax ledger.
|
|
11
11
|
- **`search_bills(filter: {valueDate: {between: [<period-start>, <period-end>]}, status: {neq: 'DRAFT'}}, limit: 200)`** — step 4 input-tax detail: per-bill GST cross-check, with blocked-input filter.
|
|
12
12
|
- **`quick_fix_line_items(entity: 'invoices' | 'bills', lineItemResourceIds, attributes)`** — step 5 corrections: re-assign the tax profile on the affected lines if errors are found. The tax profile sits on each line, so the fix is at line level.
|
|
13
13
|
- **`download_export(exportType: 'analysis-exchange-rate-audit', startDate, endDate)`** — step 6 pre-filing check: FX rates outside expected band can shift GST on FX invoices.
|
|
14
|
-
- **`generate_trial_balance(
|
|
14
|
+
- **`generate_trial_balance(endDate: <period-end>)`** — step 7 GST account reconciliation: `GST Control` / `Input Tax Recoverable` / `Output Tax Payable` accounts.
|
|
15
15
|
|
|
16
16
|
### Cross-references
|
|
17
17
|
- Org inputs this job needs (confirm with the user when not already on file): the GST scheme, the GST registration number, and the country code (`SG` | `PH`).
|
|
@@ -27,7 +27,7 @@ Walk steps 1-8 below. (Local CLI: `clio jobs gst-vat --period 2025-Q1` prints th
|
|
|
27
27
|
## Step 1 — Pull the tax ledger
|
|
28
28
|
|
|
29
29
|
```
|
|
30
|
-
generate_vat_ledger(
|
|
30
|
+
generate_vat_ledger(startDate: '2025-01-01', endDate: '2025-03-31')
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
Save the quarter's VAT ledger. Returns:
|
|
@@ -126,14 +126,14 @@ For PH (country code `PH`): also run `download_export(exportType: 'analysis-anom
|
|
|
126
126
|
## Step 7 — GST account reconciliation
|
|
127
127
|
|
|
128
128
|
```
|
|
129
|
-
generate_trial_balance(
|
|
129
|
+
generate_trial_balance(endDate: '2025-03-31')
|
|
130
130
|
```
|
|
131
131
|
|
|
132
132
|
For SG: balance['GST Control'] should equal tax-ledger's `netPayable` for the quarter. Pre-existing balance from prior quarter (carried forward) must be netted.
|
|
133
133
|
|
|
134
134
|
For PH: separate accounts for Input VAT Recoverable + Output VAT Payable; verify each independently.
|
|
135
135
|
|
|
136
|
-
If TB doesn't tie to tax ledger: likely a manual journal posted directly to GST accounts (bypassing the per-transaction tax-profile). Audit via `generate_general_ledger(
|
|
136
|
+
If TB doesn't tie to tax ledger: likely a manual journal posted directly to GST accounts (bypassing the per-transaction tax-profile). Audit via `generate_general_ledger(accountResourceIds: [<GST Control>], startDate, endDate)` — surface any non-source-system entries.
|
|
137
137
|
|
|
138
138
|
## Step 8 — Filing summary
|
|
139
139
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
- **`search_invoices(filter: {valueDate: {between: [<period-start>, <period-end>]}}, sortBy: 'valueDate', sortOrder: 'ASC', limit: 200)`** — step 1: confirm sales invoices entered. Paginate via `offset`.
|
|
9
9
|
- **`search_bills(filter: {valueDate: {between: [<period-start>, <period-end>]}}, ...)`** — step 2: confirm purchase bills entered.
|
|
10
10
|
- **`search_bank_records(accountResourceId: <id>, status: 'UNRECONCILED', startDate: <from>, endDate: <to>)`** — step 3: pull unreconciled bank statement entries per account.
|
|
11
|
-
- **`generate_aged_ar(
|
|
11
|
+
- **`generate_aged_ar(endDate: <date>)` / `generate_aged_ap(endDate: <date>)`** — steps 4-5: aging reports tied to TB AR / AP balances.
|
|
12
12
|
|
|
13
13
|
### Platform tools — accruals + valuations
|
|
14
14
|
- **`plan_recipe(recipe: 'accrued-expense', ...)` / `execute_recipe(...)`** — step 6: per recurring accrual whose last posting predates the period end.
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
- **`quick_reconcile(...)` / `reconcile_direct_cash_entry(...)` / `reconcile_cash_journal(...)` / `reconcile_manual_journal(...)` / `reconcile_cash_transfer(...)` / `reconcile_invoice_receipt(...)` / `reconcile_bill_receipt(...)`** — step 3: per matched pair from the cascade.
|
|
26
26
|
|
|
27
27
|
### Platform tools — verification + close
|
|
28
|
-
- **`generate_trial_balance(
|
|
29
|
-
- **`generate_profit_and_loss(
|
|
30
|
-
- **`generate_balance_sheet(
|
|
28
|
+
- **`generate_trial_balance(endDate: <date>)`** — step 14: master reconciliation.
|
|
29
|
+
- **`generate_profit_and_loss(startDate, endDate)`** — step 15.
|
|
30
|
+
- **`generate_balance_sheet(snapshotDate)`** — step 16.
|
|
31
31
|
- **`search_journals(filter: {status: {eq: 'DRAFT'}, valueDate: {between: [<period-start>, <period-end>]}})`** — step 17: gate on zero drafts.
|
|
32
32
|
- **`bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`** — step 17: clear residual drafts before lock.
|
|
33
33
|
- **`update_account(resourceId: <CoA root>, lockDate: <period-end>)`** — step 18: lock the period.
|
|
@@ -77,15 +77,15 @@ For each bank account:
|
|
|
77
77
|
2. `search_bank_records(accountResourceId: <bank account resourceId>, status: 'UNRECONCILED', startDate: '2025-01-01', endDate: '2025-01-31', limit: 200, sortBy: 'valueDate', sortOrder: 'ASC')`.
|
|
78
78
|
3. If results: drive the 5-phase cascade matcher (Step 4 in `bank-recon.md`; local CLI: `clio jobs bank-recon match --input <records> --tolerance 0.01 --date-window 14 --json`). For each match, invoke the matching `reconcile_*` tool.
|
|
79
79
|
4. `view_auto_reconciliation(bankStatementEntryResourceIds: [<id>, ...], recommendationType: 'MAGIC_MATCH')` — READ-ONLY suggestions for residuals (per-entry; get ids from `search_bank_records`, status `UNRECONCILED`); commit via `quick_reconcile` / `apply_bank_rule` / per-entry `reconcile_*`.
|
|
80
|
-
5. `generate_bank_recon_summary(
|
|
80
|
+
5. `generate_bank_recon_summary(bankAccountResourceId: <id>, primarySnapshotStartDate: '2025-01-01', primarySnapshotEndDate: '2025-01-31')`. Confirm `unreconciledCount == 0` OR document the residuals for the period and surface to the user.
|
|
81
81
|
|
|
82
82
|
Full detail in `bank-recon.md`. NOT idempotent — see error table.
|
|
83
83
|
|
|
84
84
|
### Steps 4-5 — AR / AP aging
|
|
85
85
|
|
|
86
86
|
```
|
|
87
|
-
generate_aged_ar(
|
|
88
|
-
generate_aged_ap(
|
|
87
|
+
generate_aged_ar(endDate: '2025-01-31')
|
|
88
|
+
generate_aged_ap(endDate: '2025-01-31')
|
|
89
89
|
```
|
|
90
90
|
|
|
91
91
|
Use `endDate` (rule 36 — point-in-time, not period-range). Assert: aging totals match `generate_trial_balance` AR/AP lines within the org's materiality threshold. Flag > 60d for credit-control / payment-priority. Disputed bills exit the active aging — annotate for the user.
|
|
@@ -98,26 +98,26 @@ For each recurring accrual the org runs whose last posting predates `2025-01-31`
|
|
|
98
98
|
|
|
99
99
|
1. Compute amount per the accrual's estimation method (`prior_month` via `search_journals`, `trailing_3m_avg`, `budget`, `fixed_amount`).
|
|
100
100
|
2. Cross-check: `clio calc accrued-expense --amount <computed> --periods 1 --json`.
|
|
101
|
-
3. `plan_recipe(recipe: 'accrued-expense', amount: <computed>,
|
|
101
|
+
3. `plan_recipe(recipe: 'accrued-expense', amount: <computed>, periods: 1, startDate: '2025-01-31')` (the engine dates the reversal itself; the accrual accounts resolve from the CoA and the vendor goes to `execute_recipe` as `contactName`).
|
|
102
102
|
4. Resolve `requiredAccounts` + `needsContact` (search/create as needed).
|
|
103
103
|
5. `execute_recipe(...)`. Engine emits dual-entry accrual + reversal scheduler.
|
|
104
104
|
6. `validate_journal_draft(resourceId: <id>)` for each draft journal.
|
|
105
105
|
7. After all accruals processed: `bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`.
|
|
106
106
|
|
|
107
|
-
Cross-check: `generate_trial_balance(
|
|
107
|
+
Cross-check: `generate_trial_balance(endDate: '2025-01-31')`. Sum credit movements against accrual liability accounts. Verify `|sum - expected| ≤ materiality threshold`.
|
|
108
108
|
|
|
109
109
|
### Step 7 — Prepaid expense recognition (finalize this period's pre-emitted journal)
|
|
110
110
|
|
|
111
111
|
For each existing `Prepaid Expenses` capsule (via `search_capsules(filter: {status: {eq: 'ACTIVE'}})` (capsule type is not filterable — see `building-blocks.md` § Filter limits)):
|
|
112
112
|
|
|
113
|
-
1. **STOP — do not select these with a filter.** Journals cannot be narrowed to one capsule by a filter: `JournalFilter` declares no `capsuleResourceId`, and `GET /capsules/{id}` returns only `totalTransactions`, a count (measured 2026-09-07). A date+status search returns EVERY matching DRAFT in the org, including drafts a practitioner deliberately parked, so passing it to `bulk_update_journals(saveAsDraft: false)` finalizes unrelated work. `get_journal` (`GET /journals/{id}`) does return the link as `capsule: {resourceId, type, title}` (measured 2026-09-23), so check each candidate journal's `capsule.resourceId` against this capsule, keep only the matches, and confirm the count with the practitioner before finalizing.
|
|
113
|
+
1. **STOP — do not select these with a filter.** Journals cannot be narrowed to one capsule by a filter: `JournalFilter` declares no `capsuleResourceId`, and `GET /capsules/{id}` returns only `totalTransactions`, a count (measured 2026-09-07). A date+status search returns EVERY matching DRAFT in the org, including drafts a practitioner deliberately parked, so passing it to `bulk_update_journals(items: [{resourceId, saveAsDraft: false}])` finalizes unrelated work. `get_journal` (`GET /journals/{id}`) does return the link as `capsule: {resourceId, type, title}` (measured 2026-09-23), so check each candidate journal's `capsule.resourceId` against this capsule, keep only the matches, and confirm the count with the practitioner before finalizing.
|
|
114
114
|
2. If empty: either the recipe was set up wrong (no journal for this period — investigate via `search_journals` without status filter to see if it's already ACTIVE, then skip), OR the practitioner went off-recipe. Surface to practitioner.
|
|
115
115
|
3. If found: collect resourceIds, then `bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`.
|
|
116
|
-
4. New prepaid setups during this period (a new prepaid started this month): invoke `plan_recipe(recipe: 'prepaid-expense', ...)` (see the `prepaid-expense` recipe in the transaction-recipes skill) — this creates the bill + N future-dated DRAFT journals; the current period's journal
|
|
116
|
+
4. New prepaid setups during this period (a new prepaid started this month): invoke `plan_recipe(recipe: 'prepaid-expense', ...)` (see the `prepaid-expense` recipe in the transaction-recipes skill) — this creates the bill + N future-dated DRAFT journals; the current period's journal joins the `bulk_update_journals` set above (`bulk_finalize_drafts` takes invoices, bills and credit notes only, never journals).
|
|
117
117
|
|
|
118
118
|
### Step 8 — Deferred revenue recognition
|
|
119
119
|
|
|
120
|
-
Mirror of step 7. Existing `Deferred Revenue` capsules:
|
|
120
|
+
Mirror of step 7. Existing `Deferred Revenue` capsules: find this period's DRAFT journal in each, then `bulk_update_journals(items: [{resourceId, saveAsDraft: false}])`. New deferred setups: `plan_recipe(recipe: 'deferred-revenue', ...)` then finalize the current period's journal in the same `bulk_update_journals` call.
|
|
121
121
|
|
|
122
122
|
### Step 9 — Depreciation
|
|
123
123
|
|
|
@@ -125,14 +125,14 @@ Mirror of step 7. Existing `Deferred Revenue` capsules: search for this period's
|
|
|
125
125
|
search_fixed_assets(filter: {status: {eq: 'ACTIVE'}, depreciationMethod: {in: ['ddb', '150db']}})
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
-
For Jaz-native SL assets: depreciation auto-posts; verify via `generate_fa_summary(
|
|
128
|
+
For Jaz-native SL assets: depreciation auto-posts; verify via `generate_fa_summary(primarySnapshotStartDate: '2025-01-01', primarySnapshotEndDate: '2025-01-31', groupBy: 'CATEGORY')` showing month's depreciation movement. For non-SL methods returned above: `plan_recipe(recipe: 'depreciation', method: 'ddb' | '150db', cost, salvageValue, usefulLifeYears, ...)` per asset, then `execute_recipe`.
|
|
129
129
|
|
|
130
130
|
### Step 10 — Employee benefit accruals
|
|
131
131
|
|
|
132
132
|
If the org has headcount and tracks leave balances:
|
|
133
133
|
|
|
134
134
|
```
|
|
135
|
-
plan_recipe(recipe: 'leave-accrual',
|
|
135
|
+
plan_recipe(recipe: 'leave-accrual', employees: <headcount>, daysPerYear: <leave days per year>, dailyRate: <avg-daily-rate>, startDate: '2025-01-01', periods: 12)
|
|
136
136
|
```
|
|
137
137
|
|
|
138
138
|
On first month of FY only — engine creates the scheduler and posts the first accrual. Subsequent months: scheduler emits automatically. Cross-check via `clio calc leave-accrual`.
|
|
@@ -141,7 +141,7 @@ On first month of FY only — engine creates the scheduler and posts the first a
|
|
|
141
141
|
|
|
142
142
|
For each active loan capsule (via `search_capsules(filter: {status: {eq: 'ACTIVE'}})` (capsule type is not filterable — see `building-blocks.md` § Filter limits)):
|
|
143
143
|
|
|
144
|
-
1. **STOP — do not select these with a filter.** Journals cannot be narrowed to one capsule by a filter: `JournalFilter` declares no `capsuleResourceId`, and `GET /capsules/{id}` returns only `totalTransactions`, a count (measured 2026-09-07). A date+status search returns EVERY matching DRAFT in the org, including drafts a practitioner deliberately parked, so passing it to `bulk_update_journals(saveAsDraft: false)` finalizes unrelated work. `get_journal` (`GET /journals/{id}`) does return the link as `capsule: {resourceId, type, title}` (measured 2026-09-23), so check each candidate journal's `capsule.resourceId` against this capsule, keep only the matches, and confirm the count with the practitioner before finalizing.
|
|
144
|
+
1. **STOP — do not select these with a filter.** Journals cannot be narrowed to one capsule by a filter: `JournalFilter` declares no `capsuleResourceId`, and `GET /capsules/{id}` returns only `totalTransactions`, a count (measured 2026-09-07). A date+status search returns EVERY matching DRAFT in the org, including drafts a practitioner deliberately parked, so passing it to `bulk_update_journals(items: [{resourceId, saveAsDraft: false}])` finalizes unrelated work. `get_journal` (`GET /journals/{id}`) does return the link as `capsule: {resourceId, type, title}` (measured 2026-09-23), so check each candidate journal's `capsule.resourceId` against this capsule, keep only the matches, and confirm the count with the practitioner before finalizing.
|
|
145
145
|
2. Should return exactly one DRAFT journal per active loan. Each is a 3-line entry (debit Loan Payable, debit Interest Expense, credit Cash) with the correct amortization split for the period.
|
|
146
146
|
3. Collect resourceIds, then `bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`.
|
|
147
147
|
4. Do NOT post manual loan-interest accruals — the recipe already emitted the journal with the correct split per `clio calc loan` schedule.
|
|
@@ -159,7 +159,7 @@ This step is a verification cross-check. If the org is multi-currency:
|
|
|
159
159
|
1. Pull what Jaz auto-posted to FX accounts during the period:
|
|
160
160
|
```
|
|
161
161
|
search_accounts(filter: {name: {in: ['FX Unrealized Gain', 'FX Unrealized Loss', 'FX Bank Revaluation']}})
|
|
162
|
-
generate_general_ledger(
|
|
162
|
+
generate_general_ledger(startDate: '2025-01-01', endDate: '2025-01-31', accountResourceIds: [<FX account ids>], groupBy: 'ACCOUNT')
|
|
163
163
|
```
|
|
164
164
|
|
|
165
165
|
2. For each foreign-currency monetary balance at period end (from a separate `generate_general_ledger` filtered to non-base-currency accounts), independently compute:
|
|
@@ -180,7 +180,7 @@ Per memory rule [Bank FX is Revaluation, not Realized]: bank/cash FX uses `FX Ba
|
|
|
180
180
|
Mental check on AR aging > 90d bucket changes. If material change vs prior month: invoke ECL recipe.
|
|
181
181
|
|
|
182
182
|
```
|
|
183
|
-
plan_recipe(recipe: 'ecl',
|
|
183
|
+
plan_recipe(recipe: 'ecl', buckets: <generate_aged_ar buckets, each {name, balance, rate} with rate from the org ECL loss-rate matrix>, existingProvision, startDate)
|
|
184
184
|
```
|
|
185
185
|
|
|
186
186
|
For most SMBs, formal ECL adjustment runs in `quarter-end-close.md`. Skip in routine monthly close unless a major customer default / dispute occurred.
|
|
@@ -190,7 +190,7 @@ For most SMBs, formal ECL adjustment runs in `quarter-end-close.md`. Skip in rou
|
|
|
190
190
|
### Step 14 — Trial balance
|
|
191
191
|
|
|
192
192
|
```
|
|
193
|
-
generate_trial_balance(
|
|
193
|
+
generate_trial_balance(endDate: '2025-01-31')
|
|
194
194
|
```
|
|
195
195
|
|
|
196
196
|
Save the close trial balance for the period (you'll diff next month against it). Assert:
|
|
@@ -203,8 +203,8 @@ Save the close trial balance for the period (you'll diff next month against it).
|
|
|
203
203
|
### Steps 15-16 — P&L + Balance Sheet
|
|
204
204
|
|
|
205
205
|
```
|
|
206
|
-
generate_profit_and_loss(
|
|
207
|
-
generate_balance_sheet(
|
|
206
|
+
generate_profit_and_loss(startDate: '2025-01-01', endDate: '2025-01-31')
|
|
207
|
+
generate_balance_sheet(snapshotDate: '2025-01-31')
|
|
208
208
|
```
|
|
209
209
|
|
|
210
210
|
Save both. Assert: BS Total Assets == Total Liabilities + Total Equity. P&L net profit ties to BS Equity Movement.
|
|
@@ -219,7 +219,7 @@ search_invoices(filter: {status: {eq: 'DRAFT'}, valueDate: {between: ['2025-01-0
|
|
|
219
219
|
search_bills(filter: {status: {eq: 'DRAFT'}, valueDate: {between: ['2025-01-01', '2025-01-31']}})
|
|
220
220
|
```
|
|
221
221
|
|
|
222
|
-
All three must return zero. If any rows: classify per practitioner judgment, then `bulk_finalize_drafts` for
|
|
222
|
+
All three must return zero. If any rows: classify per practitioner judgment, then finalize the keep-set (`bulk_update_journals` for journals, `bulk_finalize_drafts` for invoices and bills) OR delete via `delete_journal` / `delete_invoice` / `delete_bill`. Record the judgment: `jot(kind: SCOPE)` naming which drafts were finalized, which were deleted, and the rule applied.
|
|
223
223
|
|
|
224
224
|
## Phase 5 — Lock
|
|
225
225
|
|
|
@@ -244,10 +244,10 @@ If residuals were documented at steps 3 or 17, record the judgment after the loc
|
|
|
244
244
|
| `reconcile_invoice_receipt` | 422 `invoice_status_invalid` | Matched invoice still DRAFT. `finalize_invoice(resourceId: <id>)` first. |
|
|
245
245
|
| `reconcile_*` | (any) — NOT idempotent | Per `jaz-api/SKILL.md` rule 125. On 500 / network error, do NOT retry. Confirm reconciled state via `view_auto_reconciliation` or `search_bank_records(status: 'RECONCILED')` first. |
|
|
246
246
|
| `plan_recipe` | 422 `account_not_found` / `contact_not_found` | Step resolution incomplete. `search_accounts` / `search_contacts`; create if missing. Halt and surface to the user. |
|
|
247
|
-
| `
|
|
247
|
+
| `bulk_update_journals` | 422 `journal_unbalanced` | Recipe regression. Halt; do not retry without manual review. |
|
|
248
248
|
| `update_account` lockDate | 422 `lock_date_violated` | Open drafts in the period. Re-run step 17 gates. |
|
|
249
249
|
| `update_account` lockDate | 422 `period_already_locked` | Period already closed. Confirm with the user before re-opening. |
|
|
250
|
-
| FA `depreciation` posting | 0 movement when expected | Asset not `status: ACTIVE` in FA register. `update_fixed_asset(resourceId: <id>,
|
|
250
|
+
| FA `depreciation` posting | 0 movement when expected | Asset not `status: ACTIVE` in FA register. `update_fixed_asset(resourceId: <id>, isDraftToActive: true)` first. |
|
|
251
251
|
|
|
252
252
|
---
|
|
253
253
|
|
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
### Platform tools (jaz-api)
|
|
8
8
|
- **`search_bills(filter: {status: {eq: 'UNPAID'}, balanceAmount: {gt: 0}, dueDate: {lte: <cutoff>}}, sortBy: 'dueDate', sortOrder: 'ASC', limit: 200)`** — used in step 2: pull due bills (paginate via `offset` if `>200`).
|
|
9
|
-
- **`generate_aged_ap(
|
|
10
|
-
- **`generate_bank_balance_summary(
|
|
9
|
+
- **`generate_aged_ap(endDate: <cutoff>)`** — used in step 3: total-AP cross-check; flag bills in 60d+ aging buckets.
|
|
10
|
+
- **`generate_bank_balance_summary(primarySnapshotDate: <cutoff>)`** — used in step 5: confirm cash availability before approving the batch.
|
|
11
11
|
- **`get_contact(resourceId: <contactResourceId>)`** — used in step 4 (per supplier): pull payment terms / preferred payment method / bank details (especially `taxId`, `bankAccountNumber`, `bicSwift` for GIRO file generation).
|
|
12
|
-
- **`
|
|
12
|
+
- **`pay_bill(resourceId: <id>, paymentAmount, transactionAmount, accountResourceId, valueDate, ...)`** — used in step 6: post the payment per bill. NO BATCH PAYMENT ENDPOINT yet — one POST per bill.
|
|
13
13
|
- **`search_payments(filter: {businessTransactionReference: {startWith: <run-prefix>}, valueDate: {eq: <run-date>}})`** — used in step 8: idempotency / verification check (re-running the run won't duplicate-pay if all references match).
|
|
14
14
|
|
|
15
15
|
> **The field and the operator are both exact.** `search_payments` hits `POST /cashflow-transactions/search` → `TransactionsFilter`, which declares no `additionalProperties`, so an undeclared field is rejected outright rather than ignored. It has **no `reference`** (that is `businessTransactionReference`) and `StringExpression` has **no `startsWith`** — the prefix operator is spelled **`startWith`**, no "s". Until 5.55.3 this line asked for both wrong names, so the idempotency check — the step standing between a re-run and paying every supplier twice — could not return anything. Use `startWith`, not `contains`: measured on the sandbox 2026-09-07, `contains: 'PR-'` matched 3 rows that do **not** start with that prefix, and a looser match here silently widens what the run treats as already-paid.
|
|
@@ -61,7 +61,7 @@ For each bill, also collect: `contactResourceId`, `currency`, `originalAmount`,
|
|
|
61
61
|
## Step 3 — AP aging cross-check
|
|
62
62
|
|
|
63
63
|
```
|
|
64
|
-
generate_aged_ap(
|
|
64
|
+
generate_aged_ap(endDate: '2025-02-28')
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
Verify: `sum(derived outstanding) ≈ generate_aged_ap.totalOutstanding` (within the materiality threshold). Mismatch indicates pending bills in non-`UNPAID` status (e.g., `PARTIALLY_PAID`) that need separate handling — surface to the user.
|
|
@@ -79,12 +79,12 @@ Suppliers prefer one consolidated payment per run. Multi-currency suppliers need
|
|
|
79
79
|
## Step 5 — Cash availability gate
|
|
80
80
|
|
|
81
81
|
```
|
|
82
|
-
generate_bank_balance_summary(
|
|
82
|
+
generate_bank_balance_summary(primarySnapshotDate: '2025-02-28')
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
For each `bankAccountResourceId` you'll pay from: confirm `availableBalance >= sum of payments to be drawn from it`. If insufficient: defer the bottom of the priority stack to the next run; surface the deferred list to practitioner with explanation.
|
|
86
86
|
|
|
87
|
-
Apply the org's cash-buffer policy (default: 14 days operating expenses) — never drain to zero. Compute buffer-required from last 30 days' opex via `generate_profit_and_loss(
|
|
87
|
+
Apply the org's cash-buffer policy (default: 14 days operating expenses) — never drain to zero. Compute buffer-required from last 30 days' opex via `generate_profit_and_loss(startDate: <-30d>, endDate: <today>)`.
|
|
88
88
|
|
|
89
89
|
Record the judgment: `jot(kind: SCOPE)` naming the deferred bills and the cash-buffer rule applied.
|
|
90
90
|
|
|
@@ -93,16 +93,14 @@ Record the judgment: `jot(kind: SCOPE)` naming the deferred bills and the cash-b
|
|
|
93
93
|
For each approved bill (one POST per bill — no batch endpoint):
|
|
94
94
|
|
|
95
95
|
```
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
valueDate: '2025-02-28'
|
|
105
|
-
}]
|
|
96
|
+
pay_bill(
|
|
97
|
+
resourceId: <id>,
|
|
98
|
+
paymentAmount: 5350.00,
|
|
99
|
+
transactionAmount: 5350.00,
|
|
100
|
+
accountResourceId: <bank-account-resourceId>,
|
|
101
|
+
paymentMethod: 'BANK_TRANSFER',
|
|
102
|
+
reference: 'PAYRUN-2025-02-28-001',
|
|
103
|
+
valueDate: '2025-02-28'
|
|
106
104
|
)
|
|
107
105
|
```
|
|
108
106
|
|
|
@@ -116,10 +114,10 @@ create_bill_payment(
|
|
|
116
114
|
|
|
117
115
|
## Step 7 — Verify
|
|
118
116
|
|
|
119
|
-
After all `
|
|
117
|
+
After all `pay_bill` calls succeed:
|
|
120
118
|
|
|
121
119
|
```
|
|
122
|
-
generate_aged_ap(
|
|
120
|
+
generate_aged_ap(endDate: '2025-02-28')
|
|
123
121
|
search_payments(filter: {businessTransactionReference: {startWith: 'PAYRUN-2025-02-28-'}, valueDate: {eq: '2025-02-28'}})
|
|
124
122
|
```
|
|
125
123
|
|
|
@@ -129,7 +127,7 @@ Assert:
|
|
|
129
127
|
- `search_payments` returns N rows where N = bills paid in step 6.
|
|
130
128
|
|
|
131
129
|
```
|
|
132
|
-
generate_bank_balance_summary(
|
|
130
|
+
generate_bank_balance_summary(primarySnapshotDate: '2025-02-28')
|
|
133
131
|
```
|
|
134
132
|
|
|
135
133
|
Assert: per-account balance reduced by `sum(paymentAmount per accountResourceId)`. Cross-reference to actual bank statement when it arrives — this is the next-day bank-recon job.
|
|
@@ -140,11 +138,11 @@ Assert: per-account balance reduced by `sum(paymentAmount per accountResourceId)
|
|
|
140
138
|
|
|
141
139
|
| Source | Error | Recovery |
|
|
142
140
|
|--------|-------|----------|
|
|
143
|
-
| `
|
|
144
|
-
| `
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
141
|
+
| `pay_bill` | 422 `bill_not_approved` | Bill is `DRAFT`. `finalize_bill(resourceId: <id>)` first, then retry. Do NOT pay drafts. |
|
|
142
|
+
| `pay_bill` | 422 `currency_mismatch` | `paymentAmount` currency ≠ bank account currency. Either pay from the matching-currency bank account, or model as FX (different `paymentAmount` and `transactionAmount`). |
|
|
143
|
+
| `pay_bill` | 422 `bill_already_paid` | Bill went `PAID` since step 2. Re-run `search_bills` for fresh state; remove from batch. |
|
|
144
|
+
| `pay_bill` | 422 `lock_date_violated` | `valueDate` is in a locked period. Either lift the lock via `update_account` lock_date OR adjust `valueDate` to the next open period. |
|
|
145
|
+
| `pay_bill` | 500 mid-run | Some payments succeeded; others didn't. NOT idempotent — re-running the loop creates duplicates. Use `search_payments` with the run prefix to identify what succeeded; resume from the next unprocessed bill. Record the judgment: `jot(kind: RECOVERY)` naming the resume point and the bills already paid. |
|
|
148
146
|
| `generate_aged_ap` | Total mismatch with `search_bills` | Likely `PARTIALLY_PAID` bills excluded from `search_bills` filter. Add `status: {in: ['UNPAID', 'PARTIALLY_PAID']}` and retry. |
|
|
149
147
|
|
|
150
148
|
---
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
- **`month-end-close.md`** — invoked 3× in standalone mode (months 1, 2, 3 of the quarter) before quarterly extras.
|
|
9
9
|
|
|
10
10
|
### Platform tools — quarterly extras
|
|
11
|
-
- **`generate_vat_ledger(
|
|
12
|
-
- **`generate_aged_ar(
|
|
11
|
+
- **`generate_vat_ledger(startDate: <Q-start>, endDate: <Q-end>)`** — Q1 GST/VAT filing prep: full quarterly tax ledger.
|
|
12
|
+
- **`generate_aged_ar(endDate: <Q-end>)`** — Q2 ECL formal review input.
|
|
13
13
|
- **`plan_recipe(recipe: 'ecl', ...)` + `execute_recipe(...)`** — Q2 ECL top-up if material.
|
|
14
14
|
- **`search_journals(filter: {tags: {eq: 'bonus-accrual'}, valueDate: {between: [<Q-start>, <Q-end>]}})`** — Q3 bonus YTD pull.
|
|
15
15
|
- **`create_journal(...)`** — Q3 bonus true-up adjustment (manual one-off).
|
|
16
16
|
- **`search_capsules(filter: {status: {eq: 'ACTIVE'}})` (capsule type is not filterable — see `building-blocks.md` § Filter limits)** — Q4 IC reconciliation per pair of entities (multi-org coordination — see the `intercompany` recipe).
|
|
17
17
|
- **`search_capsules(filter: {status: {eq: 'ACTIVE'}})` (capsule type is not filterable — see `building-blocks.md` § Filter limits) + `bulk_update_journals(items: [{resourceId: <id>, saveAsDraft: false}, ...])`** — Q5 finalize each provision capsule's quarter-end DRAFT unwinding journals.
|
|
18
|
-
- **`generate_trial_balance(
|
|
18
|
+
- **`generate_trial_balance(endDate: <Q-end>)`** — verification.
|
|
19
19
|
- **`update_account(resourceId: <CoA root>, lockDate: <Q-end>)`** — final lock.
|
|
20
20
|
|
|
21
21
|
### Calculators (cross-check, no API key needed)
|
|
@@ -49,7 +49,7 @@ Invoke `month-end-close.md` job for each of months 1, 2, 3 of the quarter. By en
|
|
|
49
49
|
### Q1 — GST/VAT filing preparation
|
|
50
50
|
|
|
51
51
|
```
|
|
52
|
-
generate_vat_ledger(
|
|
52
|
+
generate_vat_ledger(startDate: '2025-01-01', endDate: '2025-03-31')
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
Save the quarter's VAT ledger. Verify:
|
|
@@ -68,14 +68,14 @@ Full step-by-step in `gst-vat-filing.md`.
|
|
|
68
68
|
### Q2 — ECL formal review
|
|
69
69
|
|
|
70
70
|
```
|
|
71
|
-
generate_aged_ar(
|
|
71
|
+
generate_aged_ar(endDate: '2025-03-31')
|
|
72
72
|
clio calc ecl --current 100000 --30d 50000 --60d 20000 --90d 10000 --120d 5000 --rates 0.5,2,5,10,50 --existing-provision <TB Allowance balance> --currency <base currency> --json
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
If `topUpRequired > materiality threshold`:
|
|
76
76
|
|
|
77
77
|
```
|
|
78
|
-
plan_recipe(recipe: 'ecl',
|
|
78
|
+
plan_recipe(recipe: 'ecl', buckets: <[{name, balance, rate}], rate from the org ECL loss-rate matrix>, ...)
|
|
79
79
|
execute_recipe(...)
|
|
80
80
|
update_journal(resourceId: <ecl journal>, saveAsDraft: false)
|
|
81
81
|
```
|
|
@@ -97,10 +97,10 @@ Sum YTD accruals. Re-estimate full-year bonus per current performance data. If r
|
|
|
97
97
|
If the org has intercompany arrangements:
|
|
98
98
|
|
|
99
99
|
For each arrangement (per pair of entities):
|
|
100
|
-
1. Per-entity TB pull: `generate_trial_balance(
|
|
100
|
+
1. Per-entity TB pull: `generate_trial_balance(endDate: '2025-03-31')` under EACH entity's org credentials (multi-org work — see the `intercompany` recipe).
|
|
101
101
|
2. Verify `Entity A's IC Receivable balance == Entity B's IC Payable balance` (sign flipped).
|
|
102
102
|
3. Investigate discrepancies (timing, FX, missing posting).
|
|
103
|
-
4. If settling balances: post `
|
|
103
|
+
4. If settling balances: post `create_cash_out` in payer org + `create_cash_in` (or invoice payment) in payee org.
|
|
104
104
|
|
|
105
105
|
Full pattern in the `intercompany` recipe.
|
|
106
106
|
|
|
@@ -119,7 +119,7 @@ Per capsule: this period's quarter-end unwinding DRAFT journals (3 monthly DRAFT
|
|
|
119
119
|
> capsule link even at `view: 'full'` or on `GET /journals/{id}`, and `GET /capsules/{id}` returns
|
|
120
120
|
> only `totalTransactions` — a count (all measured 2026-09-07). A search by date and status alone
|
|
121
121
|
> returns **every** matching DRAFT in the org, including drafts a practitioner deliberately parked,
|
|
122
|
-
> so feeding it to `bulk_update_journals(saveAsDraft: false)` or `delete_journal` would finalize or
|
|
122
|
+
> so feeding it to `bulk_update_journals(items: [{resourceId, saveAsDraft: false}])` or `delete_journal` would finalize or
|
|
123
123
|
> destroy unrelated work. Surface the capsule and its expected journal count to the practitioner and
|
|
124
124
|
> let them identify the journals; do not select them with a filter.
|
|
125
125
|
|
|
@@ -128,9 +128,9 @@ If the user determines remeasurement is needed (cash-flow estimate changed, disc
|
|
|
128
128
|
## Phase 7 — Quarterly verification
|
|
129
129
|
|
|
130
130
|
```
|
|
131
|
-
generate_trial_balance(
|
|
132
|
-
generate_profit_and_loss(
|
|
133
|
-
generate_balance_sheet(
|
|
131
|
+
generate_trial_balance(endDate: '2025-03-31')
|
|
132
|
+
generate_profit_and_loss(startDate: '2025-01-01', endDate: '2025-03-31')
|
|
133
|
+
generate_balance_sheet(snapshotDate: '2025-03-31')
|
|
134
134
|
```
|
|
135
135
|
|
|
136
136
|
Save the quarter's reports. Quarterly-specific assertions:
|
|
@@ -156,8 +156,8 @@ update_account(resourceId: <CoA root>, lockDate: '2025-03-31')
|
|
|
156
156
|
|--------|-------|----------|
|
|
157
157
|
| Phase 1-5 (standalone) | Months not all closed | Months incomplete. Route to missing `month-end-close.md`. Run quarterly extras only once all 3 months are locked. |
|
|
158
158
|
| Q1 verification | Tax ledger ≠ sum of GST per invoice/bill | Likely tax-profile assignment errors. Audit each invoice / bill for correct tax profile. Quick Fix: `quick_fix_line_items(entity: 'invoices' \| 'bills', ...)` on the affected lines, since the tax profile sits on each line. |
|
|
159
|
-
| Q2 ECL recipe | 422 `account_not_found` | `Allowance for Doubtful Debts` missing. Create via `create_account(accountType: 'Current Asset')`. |
|
|
160
|
-
| Q3 | YTD accrual mismatches monthly recipe expectations | Likely a manual journal posted directly to Bonus Liability (not via recipe). Audit `generate_general_ledger(
|
|
159
|
+
| Q2 ECL recipe | 422 `account_not_found` | `Allowance for Doubtful Debts` missing. Create via `create_account(name: 'Allowance for Doubtful Debts', code: <unused account code>, accountType: 'Current Asset')`. |
|
|
160
|
+
| Q3 | YTD accrual mismatches monthly recipe expectations | Likely a manual journal posted directly to Bonus Liability (not via recipe). Audit `generate_general_ledger(accountResourceIds: [<Bonus Liability>], startDate: <FY-start>, endDate: <today>)`. |
|
|
161
161
|
| Q4 IC recon | Entity A IC Receivable ≠ Entity B IC Payable (sign-flipped) | See the `intercompany` recipe error table. Common causes: timing, FX confusion, posting skipped in one entity. |
|
|
162
162
|
| Q5 | Provision DRAFTs missing for the quarter | Recipe wasn't executed at provision setup. Re-run the `provision` recipe with current inputs; the engine emits the unwinding schedule for the remaining periods. |
|
|
163
163
|
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
> The amount filter differs by endpoint: `totalAmount` is accepted on bills and on
|
|
24
24
|
> cashflow-transactions but **rejected on supplier credit notes**, and no `paymentAmount` filter
|
|
25
25
|
> exists anywhere — it is a response field on a payment, not a filter key.
|
|
26
|
-
- **`generate_aged_ap(
|
|
27
|
-
- **`create_bill(...)`** / **`
|
|
26
|
+
- **`generate_aged_ap(endDate: <date>)`** — step 5: per-supplier outstanding balance.
|
|
27
|
+
- **`create_bill(...)`** / **`apply_credits_to_bill(...)`** / **`create_supplier_credit_note(...)`** — step 6: post any missing items identified during recon.
|
|
28
28
|
|
|
29
29
|
### Cross-references
|
|
30
30
|
- Run ad-hoc per major supplier, and at year-end as a mandatory recon for major suppliers (feeds `audit-prep.md` AP confirmations).
|
|
@@ -62,7 +62,7 @@ search_bills(
|
|
|
62
62
|
|
|
63
63
|
Per bill: `{resourceId, reference, valueDate, currency, originalAmount, paymentRecords, status, dueDate}`. `balanceAmount` is a FILTER key only — the API accepts it in a filter but never returns it on a bill or invoice. Reading it back yields undefined. Derive outstanding instead: `totalAmount - sum(paymentRecords[].transactionAmount) - sum(creditsApplied[].amountApplied)`, and fetch with `view: 'full'` because a lean row omits `paymentRecords` entirely. Keep the Jaz-side bill list for the recon pack.
|
|
64
64
|
|
|
65
|
-
For an opening-balance recon: also pull the supplier's pre-period balance via `generate_aged_ap(
|
|
65
|
+
For an opening-balance recon: also pull the supplier's pre-period balance via `generate_aged_ap(endDate: <period-start - 1 day>)` and filter to this supplier.
|
|
66
66
|
|
|
67
67
|
## Step 3 — Pull payments
|
|
68
68
|
|
|
@@ -83,7 +83,7 @@ Save. Each credit note may have been applied to one or more bills; the applicati
|
|
|
83
83
|
## Step 5 — Compute Jaz-side closing balance
|
|
84
84
|
|
|
85
85
|
```
|
|
86
|
-
generate_aged_ap(
|
|
86
|
+
generate_aged_ap(endDate: '2025-01-31')
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
Filter to this supplier. Compute: opening balance + new bills (step 2) - payments (step 3) - applied credit notes (step 4) = closing balance per Jaz.
|
|
@@ -99,7 +99,7 @@ Practitioner provides the supplier's statement (PDF, email, paper). Per-line-ite
|
|
|
99
99
|
| Different amounts on same reference | Pricing dispute | Practitioner contacts supplier for clarification. Possible adjustment journal post-resolution. |
|
|
100
100
|
| Bill paid per Jaz, supplier says unpaid | Bank reconciliation gap | Pull bank statement for the payment date; verify the wire/cheque cleared. If cleared, send remittance proof to supplier. |
|
|
101
101
|
| Bill unpaid per Jaz, supplier says paid | Payment recorded against wrong supplier OR bill | Audit `search_payments(filter: {valueDate: {eq: <date>}, totalAmount: {eq: <amount>}})`; identify mis-routing; post correcting journal OR re-issue payment. |
|
|
102
|
-
| Supplier credit note not in Jaz | Missed credit | `create_supplier_credit_note(...)` per supplier statement. Then `
|
|
102
|
+
| Supplier credit note not in Jaz | Missed credit | `create_supplier_credit_note(...)` per supplier statement. Then `apply_credits_to_bill(...)` to the offsetting bill. |
|
|
103
103
|
| Currency mismatch | FX bills with different rates | Confirm Jaz used the right rate per `jaz-api/SKILL.md` rule 25; the supplier statement may use spot rate, Jaz uses recorded rate. Document the FX gap. |
|
|
104
104
|
|
|
105
105
|
## Step 7 — Post corrections + verify
|
|
@@ -108,7 +108,7 @@ For each missing bill / credit note: post via `create_bill` / `create_supplier_c
|
|
|
108
108
|
|
|
109
109
|
After corrections:
|
|
110
110
|
```
|
|
111
|
-
generate_aged_ap(
|
|
111
|
+
generate_aged_ap(endDate: '2025-01-31')
|
|
112
112
|
```
|
|
113
113
|
|
|
114
114
|
Filter to supplier. New closing balance should match the supplier statement closing balance within tolerance (typically zero — pricing rounding on long-running accounts can leave cents).
|
|
@@ -131,7 +131,7 @@ Keep, per supplier:
|
|
|
131
131
|
| Step 2 | Bill count > page limit | Paginate via `offset`. |
|
|
132
132
|
| Step 6 | Currency mismatch on supplier statement | Standard FX handling — supplier records in the supplier's base currency, Jaz records in the org's base currency. Compare in the supplier's currency for the parity check; FX gap goes to FX gain/loss separately. |
|
|
133
133
|
| Step 7 | `create_bill` 422 `valueDate_in_locked_period` | The missing bill belongs to a locked period. Lift lock via `update_account` lockDate, post, re-lock. Surface to practitioner — auditor will see late posting. |
|
|
134
|
-
| Step 7 | `
|
|
134
|
+
| Step 7 | `apply_credits_to_bill` 422 `credit_exceeds_balance` | Trying to apply more credit than the bill has remaining. Practitioner judgment — split the credit across multiple bills OR carry forward. |
|
|
135
135
|
|
|
136
136
|
---
|
|
137
137
|
|