jaz-clio 5.63.0 → 5.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/skills/api/SKILL.md +1 -1
- package/assets/skills/api/references/claims.md +18 -11
- package/assets/skills/api/references/errors.md +2 -2
- package/assets/skills/cli/SKILL.md +1 -1
- package/assets/skills/cli/references/command-catalog.md +3 -3
- 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/jobs/SKILL.md +1 -1
- package/assets/skills/jobs/references/month-end-close.md +2 -2
- package/assets/skills/jobs/references/year-end-close.md +1 -1
- package/assets/skills/transaction-recipes/SKILL.md +1 -1
- package/assets/skills/transaction-recipes/references/bad-debt-provision.md +11 -12
- package/assets/skills/transaction-recipes/references/bank-loan.md +1 -1
- package/assets/skills/transaction-recipes/references/dividend.md +7 -5
- package/assets/skills/transaction-recipes/references/fixed-deposit.md +2 -2
- package/assets/skills/transaction-recipes/references/fx-revaluation.md +3 -3
- package/assets/skills/transaction-recipes/references/provisions.md +2 -2
- package/cli.mjs +443 -442
- package/package.json +1 -1
|
@@ -149,22 +149,28 @@ Turn APPROVED claims into journal entries, and record books-only employee payout
|
|
|
149
149
|
The expense-claim members. CLI: `clio employees …`. `list = search_employees` (no
|
|
150
150
|
bare list endpoint).
|
|
151
151
|
|
|
152
|
-
- **`add_employee`** — `
|
|
153
|
-
|
|
154
|
-
|
|
152
|
+
- **`add_employee`** — **`name` and `claimProfileResourceId` are required** (without a
|
|
153
|
+
profile: `422 EMPLOYEE_CLAIM_PROFILE_REQUIRED`). `userResourceId` is optional: omit it
|
|
154
|
+
for an offline employee with no login. **`userResourceId` is the user's resourceId —
|
|
155
155
|
read it as the `userResourceId` FIELD on an org-user (`search_org_users`), NOT the
|
|
156
156
|
org-user record's own `resourceId`; passing the membership id returns
|
|
157
|
-
`422 EMPLOYEE_USER_NOT_FOUND`.** Each user
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
`422 EMPLOYEE_USER_NOT_FOUND`.** Each user links to at most one employee per org. The link
|
|
158
|
+
can be changed later: `update_employee` `userResourceId` relinks, `clearFields: ["userResourceId"]`
|
|
159
|
+
unlinks. An **offline employee** (no user bound yet) can also arise via import; bind it with
|
|
160
|
+
`bind_employee_user` or `update_employee` `userResourceId`. Dedups by email (per-org unique).
|
|
160
161
|
- **The approver comes from the claim profile, not the employee.** An employee's approver
|
|
161
162
|
is `claimProfile.approverUserResourceId` (set on the Claim Profile) — the employee record
|
|
162
163
|
has no own approver field. To change who approves, edit the profile or move the employee
|
|
163
164
|
to another profile. `claimProfileResourceId` is locked while the employee has unsettled claims.
|
|
164
|
-
- **`update_employee`** — partial
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
- **`update_employee`** — partial: an omitted, `null` or `""` param is left unchanged (the
|
|
166
|
+
tool drops them, because the raw API treats an explicit `null` on email, phone,
|
|
167
|
+
managerEmployeeResourceId, employmentType or userResourceId, and `phone: ""`, as a clear).
|
|
168
|
+
To clear, list the fields in **`clearFields`** (`email`, `phone`, `managerEmployeeResourceId`,
|
|
169
|
+
`employmentType`, `userResourceId`); a field both set and cleared in one call is refused.
|
|
170
|
+
One exception: `email: ""` is passed through and clears email, same as `clearFields: ["email"]`.
|
|
171
|
+
`userResourceId` links or relinks the login user; `clearFields: ["userResourceId"]`
|
|
172
|
+
unlinks it. **Archive with `active: false`** (reversible, prefer over `delete_employee`).
|
|
173
|
+
`bind_employee_user` only binds an employee that has no user yet.
|
|
168
174
|
- **`delete_employee`** — server validates the employee is settled (else error). Prefer archive.
|
|
169
175
|
- **`search_employees`** / **`search_employee_balances`** — the second is the balance
|
|
170
176
|
directory (per-currency reimbursement owed). `search_employee_payouts` lives in `claim_processing`.
|
|
@@ -176,7 +182,8 @@ bare list endpoint).
|
|
|
176
182
|
- **Import**: `preprocess_employees_file` (sync — pass a sheet `fileUrl`, returns a row
|
|
177
183
|
preview) → `import_employees` (`create`/`update`/`delete` arrays, **max 100 each**;
|
|
178
184
|
sync-validates rows with row-level 422s, then queues an async job — poll
|
|
179
|
-
`search_background_jobs`). Create rows need
|
|
185
|
+
`search_background_jobs`). Create rows need `name` + `claimProfileResourceId`;
|
|
186
|
+
`userResourceId` is optional (omit for an offline employee).
|
|
180
187
|
|
|
181
188
|
---
|
|
182
189
|
|
|
@@ -930,8 +930,8 @@ Two of the seven never reach you through this path: a zero `adjustmentValue` and
|
|
|
930
930
|
**Fix**: Find an expense GL account via `search_accounts` — `accountType` is a **display label** (`"Operating Expense"`, `"Direct Costs"`), NOT an enum like `"EXPENSE"` (which returns zero rows) — then pass its `resourceId` as `expenseAccountResourceId`.
|
|
931
931
|
|
|
932
932
|
### "EMPLOYEE_USER_NOT_FOUND" (422)
|
|
933
|
-
**Cause**: `add_employee` / `bind_employee_user` was given a `userResourceId` that isn't a user ("User not found for userResourceId …"). The usual mistake: passing an org-user record's own `resourceId` instead of its `userResourceId`.
|
|
934
|
-
**Fix**: Use `search_org_users` and read the member's **`userResourceId`** field (not the org-user record's `resourceId`), then retry. Each user
|
|
933
|
+
**Cause**: `add_employee` / `update_employee` / `bind_employee_user` was given a `userResourceId` that isn't a user ("User not found for userResourceId …"). The usual mistake: passing an org-user record's own `resourceId` instead of its `userResourceId`.
|
|
934
|
+
**Fix**: Use `search_org_users` and read the member's **`userResourceId`** field (not the org-user record's `resourceId`), then retry. Each user links to at most one employee per org. To move a link, relink with `update_employee` `userResourceId` or unlink with `clearFields: ["userResourceId"]`.
|
|
935
935
|
|
|
936
936
|
### "EMPLOYEE_CLAIM_PROFILE_REQUIRED" (422)
|
|
937
937
|
**Cause**: `add_employee` was called without `claimProfileResourceId` ("A claim profile is required for an employee — it carries the employee balance account used to convert and pay claims"). The claim profile is **server-required** — the org default is NOT auto-applied for employees (unlike claims), even when a default profile exists.
|
|
@@ -268,9 +268,9 @@ Same subcommands and flags as `cash-in`.
|
|
|
268
268
|
| `search` | `--name`, `--email`, `--active`, `--claim-profile-resource-id`, `--sort`, `--order` |
|
|
269
269
|
| `balances` (alias `search-balances`) | per-employee, per-currency reimbursement owed |
|
|
270
270
|
| `get <id>` | `--json` |
|
|
271
|
-
| `create` | `--name
|
|
272
|
-
| `update <id>` | `--name`, `--claim-profile`, `--employment-type`, `--archive` / `--activate`, `--clear-employment-type` |
|
|
273
|
-
| `bind-user <id> <userId>` | bind a login user to an offline employee (no user yet)
|
|
271
|
+
| `create` | `--name`*, `--claim-profile`*, `--user` (link login, optional), `--employment-type`, `--email`, `--manager` |
|
|
272
|
+
| `update <id>` | `--name`, `--email`, `--phone`, `--manager`, `--claim-profile`, `--employment-type`, `--user` (link/relink), `--archive` / `--activate`, `--clear-email`, `--clear-phone`, `--clear-manager`, `--clear-employment-type`, `--unlink-user` |
|
|
273
|
+
| `bind-user <id> <userId>` | bind a login user to an offline employee (no user yet); relink or unlink via `update` |
|
|
274
274
|
| `delete <id>` | only if settled (no outstanding balance) |
|
|
275
275
|
| `preprocess <fileUrl>` | `--file-type` (CSV / XLS / XLSX) — preview rows before import |
|
|
276
276
|
| `import` | `--create` / `--update` / `--delete` (JSON arrays) — async, returns jobId |
|
|
@@ -110,7 +110,7 @@ Cross-check: `generate_trial_balance(period_end: '2025-01-31')`. Sum credit move
|
|
|
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: `JournalFilter` declares no `capsuleResourceId`,
|
|
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.
|
|
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
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 is then in the bulk_finalize_drafts queue above.
|
|
@@ -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: `JournalFilter` declares no `capsuleResourceId`,
|
|
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.
|
|
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.
|
|
@@ -118,7 +118,7 @@ plan_recipe(
|
|
|
118
118
|
)
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
-
Then `execute_recipe(...)`. Engine emits
|
|
121
|
+
Then `execute_recipe(...)`. Engine emits a declaration journal (Dr Retained Earnings / Cr Dividends Payable) and a payment cash-out, plus a withholding cash-out when `withholdingRate > 0`. Only the declaration journal follows the `finalize` flag (DRAFT or ACTIVE). The cash-outs post ACTIVE immediately, dated `paymentDate`: cash entries have no draft state. So run `execute_recipe` on the actual payment date, not at FY-end when the dividend is only declared. If the declaration must be booked in the FY-end close, post it alone with `create_journal` and record the payment with `create_cash_out` when the money leaves the account.
|
|
122
122
|
|
|
123
123
|
For interim dividends declared during the year: those should already be posted in their respective monthly closes. Y3 covers FY-end final dividend only.
|
|
124
124
|
|
|
@@ -77,22 +77,17 @@ If `topUpRequired` is below the entity's materiality threshold: skip the recipe
|
|
|
77
77
|
|
|
78
78
|
```
|
|
79
79
|
plan_recipe(
|
|
80
|
-
// Note: gl*, capsuleType, capsuleName, bankAccountResourceId, vendor, customer below are illustrative — auto-resolved at execute time from CoA, not real plan_recipe params.
|
|
81
80
|
recipe: 'ecl',
|
|
82
|
-
|
|
83
|
-
{
|
|
84
|
-
{
|
|
85
|
-
{
|
|
86
|
-
{
|
|
87
|
-
{
|
|
81
|
+
buckets: [
|
|
82
|
+
{name: 'Current', balance: 100000, rate: 0.5},
|
|
83
|
+
{name: '1-30 days', balance: 50000, rate: 2},
|
|
84
|
+
{name: '31-60 days', balance: 20000, rate: 5},
|
|
85
|
+
{name: '61-90 days', balance: 10000, rate: 10},
|
|
86
|
+
{name: '91+ days', balance: 5000, rate: 50}
|
|
88
87
|
],
|
|
89
88
|
existingProvision: 5000,
|
|
90
89
|
currency: 'SGD',
|
|
91
|
-
|
|
92
|
-
glBadDebtExpense: <resourceId of 'Bad Debt Expense' account>,
|
|
93
|
-
valueDate: '2025-12-31',
|
|
94
|
-
capsuleType: 'ECL Provision',
|
|
95
|
-
capsuleName: 'FY2025 Year-End ECL True-Up'
|
|
90
|
+
startDate: '2025-12-31' // provision date: the aged AR report date. The ECL journal is dated on it.
|
|
96
91
|
)
|
|
97
92
|
```
|
|
98
93
|
|
|
@@ -113,6 +108,10 @@ If `Allowance for Doubtful Debts` doesn't exist in the CoA: `create_account(name
|
|
|
113
108
|
execute_recipe(recipe: 'ecl', ...same args...) // accounts auto-resolved from CoA; pass `bankAccountName` / `contactName` for fuzzy resolve
|
|
114
109
|
```
|
|
115
110
|
|
|
111
|
+
`startDate` is required: it dates the ECL journal, so pass the aged AR report date (`2025-12-31` here).
|
|
112
|
+
|
|
113
|
+
When the calculated ECL equals `existingProvision` there is no adjustment: the plan has no steps and `execute_recipe` refuses with "Nothing to post" before creating anything.
|
|
114
|
+
|
|
116
115
|
Returns: `{ capsule: {resourceId, type, title}, steps: [{step: 1, action: 'journal', status: 'created', resourceId: <journal id>}], summary: {total: 1, created: 1} }`. The single journal is DRAFT — finalize via `update_journal(resourceId: <id>, saveAsDraft: false)` once the practitioner confirms the inputs.
|
|
117
116
|
|
|
118
117
|
### Step 5 — Verify
|
|
@@ -83,7 +83,7 @@ execute_recipe(recipe: 'loan', ...same args...) // accounts auto-resolved from
|
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
Returns: `{ capsule: {resourceId, type, title}, steps: [{step, action, status, resourceId}, ...], summary: {total, created, ...} }`. The recipe creates **termMonths + 1 entries upfront**:
|
|
86
|
-
- Step 1: 1 cash-in for the loan disbursement (per `jaz-api/SKILL.md` rule 26: `accountResourceId` at top level for the bank account, `lines: [{accountResourceId: <Loan Payable>, amount: 100000}]` for the offset). Posted ACTIVE
|
|
86
|
+
- Step 1: 1 cash-in for the loan disbursement (per `jaz-api/SKILL.md` rule 26: `accountResourceId` at top level for the bank account, `lines: [{accountResourceId: <Loan Payable>, amount: 100000}]` for the offset). Posted ACTIVE immediately, whatever `finalize` says: cash entries have no draft state.
|
|
87
87
|
- Steps 2..termMonths+1: **N future-dated DRAFT journals** (one per repayment period, dated end-of-month for each month from `<startDate>+1 month` through `<startDate>+termMonths`). Each is a 3-line entry: debit Loan Payable (principal portion per amortization schedule), debit Interest Expense (interest portion), credit Cash.
|
|
88
88
|
|
|
89
89
|
All N journals attach to the same capsule. They sit DRAFT until you finalize them — typically one per month during monthly-close after the actual bank payment posts.
|
|
@@ -95,17 +95,19 @@ execute_recipe(recipe: 'dividend', ...same args...) // accounts auto-resolved f
|
|
|
95
95
|
|
|
96
96
|
Returns: `{ capsule: {resourceId, type, title}, steps: [{step, action, status, resourceId}, ...], summary: {total: 2 or 3, created: 2 or 3} }`. The recipe creates 2 entries (or 3 with withholding), all attached to the same capsule:
|
|
97
97
|
- Declaration journal (DRAFT or ACTIVE per `finalize` flag)
|
|
98
|
-
- Payment cash-out
|
|
99
|
-
- Withholding cash-out
|
|
98
|
+
- Payment cash-out: posted ACTIVE immediately, dated `paymentDate`. Cash entries have no draft state, so `finalize` does not apply and there is nothing to finalize later.
|
|
99
|
+
- Withholding cash-out: same, posted ACTIVE immediately, dated `paymentDate`.
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
**Run the recipe on the actual payment date**, once the money has left the bank account. The declaration journal still carries `declarationDate`, so booking it late puts it in the right period. Running at declaration time instead posts a live bank payment that has not happened yet, which the bank reconciliation will not match until the real payment arrives. If the declaration must be booked before the payment (for example at FY-end), post the declaration alone with `create_journal` (Dr Retained Earnings / Cr Dividends Payable) and record the payment with `create_cash_out` when the money leaves the account.
|
|
102
|
+
|
|
103
|
+
### Step 5 — Verify (after the declaration is finalized and the payment is posted)
|
|
102
104
|
|
|
103
105
|
After declaration finalized (Dec 31, 2025):
|
|
104
106
|
- `generate_balance_sheet(period_end: '2025-12-31')`.
|
|
105
107
|
- Assert: `balance['Retained Earnings']` reduced by 200,000.
|
|
106
108
|
- Assert: `balance['Dividends Payable']` increased by 200,000.
|
|
107
109
|
|
|
108
|
-
After payment
|
|
110
|
+
After payment posted (Mar 15, 2026):
|
|
109
111
|
- `generate_balance_sheet(period_end: '2026-03-15')`.
|
|
110
112
|
- Assert: `balance['Dividends Payable']` is now 0.
|
|
111
113
|
- Assert: `balance['Cash']` reduced by 200,000 (or 180,000 if withholding).
|
|
@@ -148,6 +150,6 @@ After payment AND WHT remittance:
|
|
|
148
150
|
## Cross-references
|
|
149
151
|
|
|
150
152
|
- Year-end close (Y3 in year-end-close) — final FY dividend declaration AFTER the FY's audited net profit is determined. The declared amount and withholding rate drive the recipe inputs.
|
|
151
|
-
- Month-end close — interim dividends declared mid-year are posted in the month they were declared.
|
|
153
|
+
- Month-end close — interim dividends declared mid-year are posted in the month they were declared. The payment cash-outs post ACTIVE the moment the recipe runs, so run it once the bank disbursement has happened (typically next month), or book the declaration alone with `create_journal` in the declaration month and record the payment with `create_cash_out` when it is made.
|
|
152
154
|
- `audit-prep.md` step 8 — auditor reviews `generate_equity_movement` to verify dividends are correctly classified as equity reduction (not P&L expense).
|
|
153
155
|
- `statutory-filing.md` — SG Form C-S Box 12 (dividends paid during YA) reads from this capsule's payment cash-out entries.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
### Recipe engine entry point
|
|
8
8
|
- **`plan_recipe(recipe: 'fixed-deposit', ...)`** — used in step 2: returns RecipePlan with placement + N accrual + maturity steps.
|
|
9
|
-
- **`execute_recipe(recipe: 'fixed-deposit', ...)`** — used in step 4: posts the placement cash-out (today), N future-dated DRAFT accrual journals (one per period), and maturity cash-in (dated termMonths later,
|
|
9
|
+
- **`execute_recipe(recipe: 'fixed-deposit', ...)`** — used in step 4: posts the placement cash-out (today), N future-dated DRAFT accrual journals (one per period), and maturity cash-in (dated termMonths later, posted ACTIVE immediately: cash entries have no draft state).
|
|
10
10
|
|
|
11
11
|
### Calculator (cross-check, no API key needed)
|
|
12
12
|
- **`clio calc fixed-deposit --principal <p> --rate <annual %> --term <months> --start-date <YYYY-MM-DD> --currency <code> [--compound monthly|annually] --json`** — used in step 1: compute monthly accrual amounts. Default simple interest; `--compound` for compound interest. Returns `{ totalInterest, schedule[n] }` where each row carries `period`, `accrualDate`, `accrualAmount`, `accruedToDate`, `journal`.
|
|
@@ -83,7 +83,7 @@ Bank account: resolve `bankAccountResourceId` for the disbursement bank (where t
|
|
|
83
83
|
execute_recipe(recipe: 'fixed-deposit', ...same args...) // accounts auto-resolved from CoA; pass `bankAccountName` / `contactName` for fuzzy resolve
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
Returns: `{ capsule: {resourceId, type, title}, steps: [{step, action, status, resourceId}, ...14], summary: {total: 14, created: 14} }`. The recipe creates 14 entries upfront: 1 placement cash-out (immediately
|
|
86
|
+
Returns: `{ capsule: {resourceId, type, title}, steps: [{step, action, status, resourceId}, ...14], summary: {total: 14, created: 14} }`. The recipe creates 14 entries upfront: 1 placement cash-out (ACTIVE immediately, whatever `finalize` says), 12 future-dated DRAFT accrual journals, 1 future-dated maturity cash-in (dated `startDate + termMonths`, also ACTIVE immediately: cash entries have no draft state).
|
|
87
87
|
|
|
88
88
|
### Step 5 — Monthly action (during monthly-close)
|
|
89
89
|
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
### Engine entry points (DO NOT INVOKE in normal operation)
|
|
33
33
|
- ~~`plan_recipe(recipe: 'fx-reval', ...)`~~ — engine still accepts this for legacy reasons; output is for inspection only.
|
|
34
|
-
- ~~`execute_recipe(recipe: 'fx-reval', ...)`~~
|
|
34
|
+
- ~~`execute_recipe(recipe: 'fx-reval', ...)`~~ (and `clio ct fx-reval` without `--plan`): **refused.** Executing would double-post, so the engine rejects the call before it creates anything.
|
|
35
35
|
|
|
36
36
|
### Cross-references
|
|
37
37
|
- Operational context: invoked during month-end close only as a VERIFICATION step (cross-check Jaz's auto-posted reval against an independent calculation; surface any variance). Same during the GST/VAT filing cycle and year-end close.
|
|
@@ -130,9 +130,9 @@ This file feeds `audit-prep.md` step 8 supporting schedules. Auditors love indep
|
|
|
130
130
|
|
|
131
131
|
---
|
|
132
132
|
|
|
133
|
-
## Why the engine still
|
|
133
|
+
## Why the engine still plans the recipe
|
|
134
134
|
|
|
135
|
-
Historical: pre-platform-auto-FX-reval orgs needed this. Some orgs may still run on a configuration where auto-FX is disabled (rare, legacy).
|
|
135
|
+
Historical: pre-platform-auto-FX-reval orgs needed this. Some orgs may still run on a configuration where auto-FX is disabled (rare, legacy). `execute_recipe(recipe: 'fx-reval', ...)` is refused for every org, so for those orgs take the period-end journal and Day 1 reversal from `plan_recipe(recipe: 'fx-reval', ...)` and post them as two manual journals with `create_journal` (the reversal dated the first day of the next period). DO NOT do this in any modern org.
|
|
136
136
|
|
|
137
137
|
If you genuinely need to know whether auto-FX is enabled for a specific org: check organization settings via `get_organization()`. If the auto-FX flag is on (default and typical), this recipe is verification-only as documented above.
|
|
138
138
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
### Recipe engine entry point
|
|
8
8
|
- **`plan_recipe(recipe: 'provision', ...)`** — used in step 2: returns RecipePlan with PV-recognition journal + N period unwinding journals + settlement cash-out.
|
|
9
|
-
- **`execute_recipe(recipe: 'provision', ...)`** — used in step 4: posts initial PV journal (today), N future-dated DRAFT discount-unwinding journals (one per month), and settlement cash-out (dated `settlementDate`,
|
|
9
|
+
- **`execute_recipe(recipe: 'provision', ...)`** — used in step 4: posts initial PV journal (today), N future-dated DRAFT discount-unwinding journals (one per month), and settlement cash-out (dated `settlementDate`, posted ACTIVE immediately: cash entries have no draft state).
|
|
10
10
|
|
|
11
11
|
### Calculator (cross-check, no API key needed)
|
|
12
12
|
- **`clio calc provision --amount <undiscounted total> --rate <annual %> --term <months> --start-date <YYYY-MM-DD> --currency <code> --json`** — used in step 1: compute PV at recognition + per-period unwinding charge. Returns `{ presentValue, totalUnwindingCharge, schedule[n] }` where each row has `period`, `openingProvision`, `unwindingCharge`, `closingProvision`.
|
|
@@ -83,7 +83,7 @@ Bank account: only needed for the settlement cash-out at the end of the term.
|
|
|
83
83
|
execute_recipe(recipe: 'provision', ...same args...) // accounts auto-resolved from CoA; pass `bankAccountName` / `contactName` for fuzzy resolve
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
-
Returns: `{ capsule: {resourceId, type, title}, steps: [{step, action, status, resourceId}, ...62], summary: {total: 62, created: 62} }`. Initial recognition journal (today, ACTIVE if `finalize: true`); 60 future-dated DRAFT unwinding journals; 1 future-dated
|
|
86
|
+
Returns: `{ capsule: {resourceId, type, title}, steps: [{step, action, status, resourceId}, ...62], summary: {total: 62, created: 62} }`. Initial recognition journal (today, ACTIVE if `finalize: true`); 60 future-dated DRAFT unwinding journals; 1 future-dated settlement cash-out, posted ACTIVE immediately (cash entries have no draft state).
|
|
87
87
|
|
|
88
88
|
### Step 5 — Monthly action (during monthly-close)
|
|
89
89
|
|