jaz-clio 5.38.0 → 5.38.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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-api
3
- version: 5.38.0
3
+ version: 5.38.1
4
4
  description: >-
5
5
  Use this skill whenever you call, debug, or review code that touches the Jaz
6
6
  REST API. Covers field names, response shapes, 158 production gotchas, error
@@ -205,7 +205,7 @@ The rest of this skill — field names, gotchas, error catalog, dependency order
205
205
  ### Response Shape Gotchas
206
206
  66. **Contact boolean fields are `customer`/`supplier`** — NOT `isCustomer`/`isSupplier`. These are plain booleans on the contact object: `{ "customer": true, "supplier": false }`. Using `isCustomer` or `isSupplier` in code will be `undefined`.
207
207
  67. **Finalized statuses differ by resource type** — NOT `"FINALIZED"`, `"FINAL"`, or `"POSTED"`. Journals → `"APPROVED"`. Invoices/Bills → `"UNPAID"` (progresses to `"PAID"`, `"OVERDUE"`). Customer/Supplier Credit Notes → `"UNAPPLIED"` (progresses to `"APPLIED"`). All types support `"DRAFT"` and `"VOIDED"`. When creating without `saveAsDraft: true`, the response status matches the type's finalized status.
208
- 68. **Create/pay responses are minimal by default** — POST create endpoints (invoices, bills, journals, contacts, payments) return only `{ resourceId: "..." }` (plus a few metadata fields). They do NOT return the full entity. To verify field values after creation, do a subsequent `GET /:type/:resourceId`. **MCP tool shortcut:** `create_invoice` / `create_bill` / `create_journal` / `create_contact` / `create_item` accept `returnFullEntity: true` — the executor performs the GET server-side and returns the full entity inline, saving a turn. The raw REST `POST` is still minimal-only; only the MCP tools collapse the round trip. **If the post-create GET fails** (transient 5xx, network blip), the tool returns the minimal create envelope augmented with `_hydration: { status: 'failed', resourceId, message }` — the write committed; the agent should retry only the `get_*` call, NEVER the create (would duplicate the document).
208
+ 68. **Create/pay responses are minimal by default** — POST create endpoints (invoices, bills, journals, contacts, payments) return only `{ resourceId: "..." }` (plus a few metadata fields). They do NOT return the full entity. To verify field values after creation, do a subsequent `GET /:type/:resourceId`. **MCP tool shortcut:** `create_invoice` / `create_bill` / `create_journal` / `create_contact` / `create_item` accept `returnFullEntity: true` — the executor performs the GET server-side and returns the full entity inline, saving a turn. The raw REST `POST` is still minimal-only; only the MCP tools collapse the round trip. **If the post-create GET fails** (transient 5xx, network blip), the tool returns the minimal create envelope augmented with `_hydration: { status: 'failed', resourceId, message }` — the write committed; the agent should retry only the `get_*` call, NEVER the create (would duplicate the document). **`_fx` on transaction creates:** invoice/bill/credit-note create results may carry a sibling `_fx` field, e.g. `FX: 1 SGD (your base) = 0.74 USD (applied rate for 2026-04-03)` — the exchange rate the record was ACTUALLY created with. Relay that line to the user verbatim; it matters most when the caller supplied no rate (the organization rate was applied silently, and a rate stored the wrong way round reads as an obviously absurd number the user can catch on sight).
209
209
  69. **No `amountDue` field** — Invoices and bills do NOT have an `amountDue` field. To check if a transaction is fully paid, inspect the `paymentRecords` array: if `paymentRecords.length > 0`, payments exist. Compare `totalAmount` with the sum of `paymentRecords[].transactionAmount` to determine remaining balance.
210
210
  70. **Response dates include time component** — Even though request dates are `YYYY-MM-DD`, response dates are epoch milliseconds (see Rule 52). When comparing dates from responses, always convert with `new Date(epochMs).toISOString().slice(0, 10)` — never string-match against the raw epoch value. Remember: business dates are org-timezone (see Rule 52).
211
211
  71. **Items POST requires `saleItemName`/`purchaseItemName`** — When creating items with `appliesToSale: true` or `appliesToPurchase: true`, you MUST include `saleItemName` and/or `purchaseItemName` respectively. These are the display names shown on sale/purchase documents. Omitting them causes 422: "saleItemName is a required field". If not specified, default to the `internalName` value.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-cli
3
- version: 5.38.0
3
+ version: 5.38.1
4
4
  description: >-
5
5
  Use this skill when running Clio CLI commands, building shell scripts with
6
6
  Clio, debugging auth issues, understanding --json output, paginating results,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-conversion
3
- version: 5.38.0
3
+ version: 5.38.1
4
4
  description: >-
5
5
  Use this skill when migrating accounting data into Jaz — importing from Xero,
6
6
  QuickBooks, Sage, MYOB, or Excel exports. Covers the full conversion pipeline:
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-kit
3
- version: 5.38.0
3
+ version: 5.38.1
4
4
  description: >-
5
5
  Use this skill when an accountant, bookkeeper, or owner is running real books
6
6
  in Jaz across one or more organizations from the terminal — setting up a
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-pseudo-sql
3
- version: 5.38.0
3
+ version: 5.38.1
4
4
  description: >-
5
5
  Use this skill when answering ad-hoc data questions that aren't covered by
6
6
  download_export (canonical reports — anomaly, audit, aging, P&L, BS, GL,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-jobs
3
- version: 5.38.0
3
+ version: 5.38.1
4
4
  description: >-
5
5
  Use this skill for recurring accounting workflows — month/quarter/year-end
6
6
  close, bank reconciliation, GST/VAT filing, payment runs, credit control,
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: jaz-recipes
3
- version: 5.38.0
3
+ version: 5.38.1
4
4
  description: >-
5
5
  Use this skill when modeling complex multi-step accounting transactions —
6
6
  anything that spans multiple periods, involves changing amounts, or requires
package/cli.mjs CHANGED
@@ -202,7 +202,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
202
202
  `);return{type:"depreciation",currency:o??null,inputs:{cost:t,salvageValue:e,usefulLifeYears:r,method:"sl",frequency:i},totalDepreciation:n,schedule:d,blueprint:{capsuleType:"Depreciation",capsuleName:`SL Depreciation \u2014 ${r} years`,capsuleDescription:m,tags:["Depreciation"],customFields:{"Asset ID":null},steps:p}}}function VIe(t,e,r,n,i,o,s){let a=[],c=t;for(let m=1;m<=r;m++){let A=re(c),g=r-m+1,y=re(A*n),C=re((A-e)/g),E=re(A-y)<e,v=C>=y||E,I=v?"SL":o==="150db"?"150DB":"DDB",x=v?C:y;re(A-x)<e&&(x=re(A-e)),c=re(A-x);let S={description:`${I} depreciation \u2014 Year ${m} of ${r}`,lines:[{account:"Depreciation Expense",debit:x,credit:0},{account:"Accumulated Depreciation",debit:0,credit:x}]};a.push({period:m,date:null,openingBookValue:A,ddbAmount:y,slAmount:C,methodUsed:I,depreciation:x,closingBookValue:c,journal:S})}let u=a.map((m,A)=>qr(A+1,m.journal.description,m.date,m.journal.lines)),d=s??void 0,f=o==="ddb"?"Double Declining Balance":"150% Declining Balance",p=re(n*100),h=[`${f} Depreciation Workings`,`Cost: ${Ue(t,d)} | Salvage: ${Ue(e,d)} | Depreciable base: ${Ue(i,d)}`,`Useful life: ${r} years | Rate: ${p}% (${o==="ddb"?"2":"1.5"} \xF7 ${r})`,`Total depreciation: ${Ue(i,d)}`,`Method: ${o.toUpperCase()} with auto switch to SL when SL \u2265 declining or floor hit`,"Rounding: 2dp per period, book value never falls below salvage"].join(`
203
203
  `);return{type:"depreciation",currency:s??null,inputs:{cost:t,salvageValue:e,usefulLifeYears:r,method:o,frequency:"annual"},totalDepreciation:i,schedule:a,blueprint:{capsuleType:"Depreciation",capsuleName:`${o.toUpperCase()} Depreciation \u2014 ${r} years`,capsuleDescription:h,tags:["Depreciation"],customFields:{"Asset ID":null},steps:u}}}var U4=X(()=>{"use strict";_s();Wo();Da()});function WO(t){let{amount:e,periods:r,frequency:n="monthly",startDate:i,currency:o}=t;ln(e,"Amount"),Qi(r,"Periods"),Bi(i);let s=WIe(e,r,n,i,"prepaid"),a=null;if(i){let c=[jIe(1,"Create bill from supplier coded to Prepaid Asset, then pay from Cash / Bank Account",i,[{account:"Prepaid Asset",debit:e,credit:0},{account:"Cash / Bank Account",debit:0,credit:e}]),...s.map((f,p)=>qr(p+2,f.journal.description,f.date,f.journal.lines))],u=o??void 0,d=["Prepaid Expense Recognition Workings",`Total prepaid: ${Ue(e,u)} | Periods: ${r} (${n})`,`Per period: ${Ue(re(e/r),u)}`,`Method: Straight-line recognition over ${r} ${n} periods`,"Rounding: 2dp per period, final period absorbs remainder"].join(`
204
204
  `);a={capsuleType:"Prepaid Expenses",capsuleName:`Prepaid Expense \u2014 ${pi(e,o)} \u2014 ${r} periods`,capsuleDescription:d,tags:["Prepaid Expense"],customFields:{"Policy / Contract #":null},steps:c}}return{type:"prepaid-expense",currency:o??null,inputs:{amount:e,periods:r,frequency:n,startDate:i??null},perPeriodAmount:re(e/r),schedule:s,blueprint:a}}function ZO(t){let{amount:e,periods:r,frequency:n="monthly",startDate:i,currency:o}=t;ln(e,"Amount"),Qi(r,"Periods"),Bi(i);let s=WIe(e,r,n,i,"deferred"),a=null;if(i){let c=[YIe(1,"Create invoice to customer coded to Deferred Revenue, record payment to Cash / Bank Account",i,[{account:"Cash / Bank Account",debit:e,credit:0},{account:"Deferred Revenue",debit:0,credit:e}]),...s.map((f,p)=>qr(p+2,f.journal.description,f.date,f.journal.lines))],u=o??void 0,d=["Deferred Revenue Recognition Workings",`Total deferred: ${Ue(e,u)} | Periods: ${r} (${n})`,`Per period: ${Ue(re(e/r),u)}`,`Method: Straight-line recognition over ${r} ${n} periods`,"Rounding: 2dp per period, final period absorbs remainder"].join(`
205
- `);a={capsuleType:"Deferred Revenue",capsuleName:`Deferred Revenue \u2014 ${pi(e,o)} \u2014 ${r} periods`,capsuleDescription:d,tags:["Deferred Revenue"],customFields:{"Contract #":null},steps:c}}return{type:"deferred-revenue",currency:o??null,inputs:{amount:e,periods:r,frequency:n,startDate:i??null},perPeriodAmount:re(e/r),schedule:s,blueprint:a}}function WIe(t,e,r,n,i){let o=re(t/e),s=[],a=t,c=r==="quarterly"?3:1;for(let u=1;u<=e;u++){let f=u===e?re(a):o;a=re(a-f);let p=n?lo(n,u*c):null,h;i==="prepaid"?h={description:`Prepaid expense recognition \u2014 Period ${u} of ${e}`,lines:[{account:"Expense",debit:f,credit:0},{account:"Prepaid Asset",debit:0,credit:f}]}:h={description:`Deferred revenue recognition \u2014 Period ${u} of ${e}`,lines:[{account:"Deferred Revenue",debit:f,credit:0},{account:"Revenue",debit:0,credit:f}]},s.push({period:u,date:p,amortized:f,remainingBalance:a,journal:h})}return s}var $4=X(()=>{"use strict";_s();Wo();Da()});async function Zo(t,e,r,n){return t.post(e,{[r]:n})}function Mn(t,e,r=500,n=e){if(!Array.isArray(t))throw new Error(`${e} must be an array.`);if(t.length===0)throw new Error(`${e} array is empty.`);if(t.length>r)throw new Error(`max ${r} ${n} per call. Split into batches.`)}function dc(t,e){t.forEach((r,n)=>{if(!r||typeof r!="object")return;let i=r;if("dateFormat"in i)throw new Error(`row ${n}: dateFormat field is no longer supported (ISO 8601 YYYY-MM-DD only)`);for(let o of e){let s=i[o];if(s!=null&&(typeof s!="string"||!ZIt.test(s)))throw new Error(`row ${n}: ${o} must be YYYY-MM-DD (got ${JSON.stringify(s)})`)}})}var ZIt,Sa=X(()=>{"use strict";ZIt=/^\d{4}-\d{2}-\d{2}$/});async function ZIe(t,e,r){return t.get(`/api/v1/contacts/${e}/signals`,{btType:r})}async function Gf(t,e){return t.list("/api/v1/contacts",e)}async function fc(t,e){return t.search("/api/v1/contacts/search",e)}async function vE(t,e){return t.post("/api/v1/contacts",e)}async function XO(t,e,r){return t.put(`/api/v1/contacts/${e}`,r)}async function Jf(t,e){return t.get(`/api/v1/contacts/${e}`)}async function KO(t,e){await t.delete(`/api/v1/contacts/${e}`)}async function eF(t,e){return Zo(t,"/api/v1/contacts/bulk-upsert","contacts",e)}var Vf=X(()=>{"use strict";Sa()});async function tF(t,e){return t.list("/api/v1/bills",e)}async function Ds(t,e){return t.get(`/api/v1/bills/${e}`)}async function vd(t,e){return t.search("/api/v1/bills/search",e)}async function cA(t,e){return t.post("/api/v1/bills",{...e,currency:jr(e.currency),taxCurrency:jr(e.taxCurrency),saveAsDraft:e.saveAsDraft??!0})}async function rF(t,e,r){return t.put(`/api/v1/bills/${e}`,r)}async function ww(t,e,r){return t.put(`/api/v1/bills/${e}`,{...r,resourceId:e,saveAsDraft:!1})}async function nF(t,e){await t.delete(`/api/v1/bills/${e}`)}async function iF(t,e){return t.get(`/api/v1/bills/${e}/download`)}async function _w(t,e,r){return t.post(`/api/v1/bills/${e}/payments`,{...r,currency:jr(r.currency),saveAsDraft:r.saveAsDraft??!0})}async function oF(t,e,r){return t.post(`/api/v1/bills/${e}/credits`,{credits:r})}async function Dw(t,e){return t.post("/api/v1/scheduled/bills",{...e,bill:{...e.bill,currency:jr(e.bill?.currency)}})}async function sF(t,e){let r=await t.get(`/api/v1/bills/${e}/payments`);return{data:Array.isArray(r)?r:r.data??[]}}async function aF(t,e){let r=await t.get(`/api/v1/bills/${e}/credits`);return{data:Array.isArray(r)?r:r.data??[]}}async function cF(t,e,r){await t.delete(`/api/v1/bills/${e}/credits/${r}`)}async function lF(t,e){return Zo(t,"/api/v1/bills/bulk-upsert","bills",e)}async function uF(t,e){return Zo(t,"/api/v1/bills/line-items/bulk-upsert","bills",e)}var Id=X(()=>{"use strict";Sa();Pn()});function IE(t){if(typeof t=="number"){let e=new Date(t);return Number.isNaN(e.getTime())?void 0:e.toISOString().slice(0,10)}if(typeof t=="string"){let e=/^(\d{4})-(\d{1,2})-(\d{1,2})(?:[T\s]|$)/.exec(t.trim());return e?`${e[1]}-${e[2].padStart(2,"0")}-${e[3].padStart(2,"0")}`:void 0}}var dF=X(()=>{"use strict"});async function fF(t,e){return t.list("/api/v1/items",e)}async function wE(t,e){return t.get(`/api/v1/items/${e}`)}async function _E(t,e){return t.search("/api/v1/items/search",e)}async function Sw(t,e){let r={...e};return e.appliesToSale&&!r.saleItemName&&(r.saleItemName=e.internalName),e.appliesToPurchase&&!r.purchaseItemName&&(r.purchaseItemName=e.internalName),t.post("/api/v1/items",r)}async function pF(t,e,r){let i=(await wE(t,e)).data,o={itemCode:i.itemCode,internalName:i.internalName,appliesToSale:i.appliesToSale,appliesToPurchase:i.appliesToPurchase};return i.appliesToSale&&(i.saleItemName&&(o.saleItemName=i.saleItemName),i.salePrice!==void 0&&(o.salePrice=i.salePrice),i.saleAccountResourceId&&(o.saleAccountResourceId=i.saleAccountResourceId)),i.appliesToPurchase&&(i.purchaseItemName&&(o.purchaseItemName=i.purchaseItemName),i.purchasePrice!==void 0&&(o.purchaseItemPrice=i.purchasePrice),i.purchaseAccountResourceId&&(o.purchaseAccountResourceId=i.purchaseAccountResourceId)),Object.assign(o,r),t.put(`/api/v1/items/${e}`,o)}async function hF(t,e){await t.delete(`/api/v1/items/${e}`)}async function mF(t,e){return t.post("/api/v1/items/bulk-upsert",{items:e})}var AF=X(()=>{"use strict"});async function wd(t,e){return t.list("/api/v1/chart-of-accounts",e)}async function DE(t,e){return t.search("/api/v1/chart-of-accounts/search",e)}async function XIe(t,e){return t.get(`/api/v1/chart-of-accounts/${e}`)}async function Rw(t,e){return t.post("/api/v1/chart-of-accounts",e)}async function KIe(t,e,r){return t.put(`/api/v1/chart-of-accounts/${e}`,r)}function gF(t){let e={};for(let r of XIt){let n=t[r];n!=null&&(r==="accountType"&&typeof n=="string"?e.accountType=RE(n):e[r]=n)}return e}async function yF(t,e){return t.post("/api/v1/chart-of-accounts/bulk-upsert",{accounts:e})}async function EF(t,e){await t.delete(`/api/v1/chart-of-accounts/${e}`)}async function e0e(t,e){return t.list("/api/v1/account-classifications",e)}var XIt,SE=X(()=>{"use strict";Pn();XIt=["resourceId","code","name","accountType","currencyCode","description","status"]});async function xE(t){return t.get("/api/v1/capsuleTypes")}async function xw(t,e){return t.post("/api/v1/capsuleTypes",e)}async function bF(t,e){return t.list("/api/v1/capsules",e)}async function BE(t,e){return t.search("/api/v1/capsules/search",e)}async function Bw(t,e){return t.get(`/api/v1/capsules/${e}`)}async function lA(t,e){return t.post("/api/v1/capsules",e)}async function CF(t,e,r){let n=await Bw(t,e),i=n.data.capsuleType?.resourceId;if(!i)throw new Error(`Cannot update capsule ${e}: missing capsuleType.resourceId from GET response`);let o={resourceId:e,capsuleTypeResourceId:i,title:n.data.title,description:n.data.description,...r};return t.put(`/api/v1/capsules/${e}`,o)}async function vF(t,e){await t.delete(`/api/v1/capsules/${e}`)}async function IF(t,e){return t.post("/api/v1/moveTransactionCapsules",e)}var Tw=X(()=>{"use strict"});async function TE(t,e){return t.list("/api/v1/tax-profiles",e)}async function wF(t,e){return t.list("/api/v1/tax-types",e)}async function _F(t,e){return t.post("/api/v1/tax-profiles",e)}async function kE(t,e){return t.post("/api/v1/tax-profiles/search",e)}async function DF(t,e){return t.get(`/api/v1/tax-profiles/${e}`)}async function SF(t,e,r){return t.put(`/api/v1/tax-profiles/${e}`,r)}async function RF(t){let e=await t.get("/api/v1/withholding-tax-codes");return{data:Array.isArray(e)?e:e.data??[]}}var kw=X(()=>{"use strict"});async function NE(t,e){return t.list("/api/v1/tags",e)}async function xF(t,e){return t.get(`/api/v1/tags/${e}`)}async function BF(t,e){return t.search("/api/v1/tags/search",e)}async function Nw(t,e){return t.post("/api/v1/tags",e)}async function TF(t,e,r){return t.put(`/api/v1/tags/${e}`,r)}async function kF(t,e){await t.delete(`/api/v1/tags/${e}`)}var NF=X(()=>{"use strict"});async function OF(t,e){return t.list("/api/v1/claim-types",e)}async function FF(t,e){return t.get(`/api/v1/claim-types/${e}`)}async function OE(t,e){return t.search("/api/v1/claim-types/search",e)}async function QF(t,e){return t.post("/api/v1/claim-types",e)}async function LF(t,e,r){return t.put(`/api/v1/claim-types/${e}`,r)}async function MF(t,e){await t.delete(`/api/v1/claim-types/${e}`)}var Ow,PF=X(()=>{"use strict";Ow=["expenseAccountResourceId","taxProfileResourceId","classifierConfig"]});async function UF(t,e){return t.list("/api/v1/claim-profiles",e)}async function $F(t,e){return t.get(`/api/v1/claim-profiles/${e}`)}async function FE(t,e){return t.search("/api/v1/claim-profiles/search",e)}async function qF(t,e){return t.post("/api/v1/claim-profiles",e)}async function jF(t,e,r){return t.put(`/api/v1/claim-profiles/${e}`,r)}async function YF(t,e){await t.delete(`/api/v1/claim-profiles/${e}`)}var Fw,q4,Qw,Lw=X(()=>{"use strict";Fw=["DAILY","WEEKLY","MONTHLY","QUARTERLY","YEARLY"],q4=["NO_TAX","INCLUSIVE"],Qw=["approverUserResourceId","visibleClaimTypeIds","visibleTaxProfileIds","visibleClassifierIds","visibleVendorResourceIds","allowedCurrencies","minClaimAmount","maxClaimAmount","maxPerPeriodAmount","perPeriod","employeeBalanceAccountResourceId","taxMode"]});async function HF(t,e){return t.list("/api/v1/posting-rules",e)}async function zF(t,e){return t.get(`/api/v1/posting-rules/${e}`)}async function QE(t,e){return t.search("/api/v1/posting-rules/search",e)}async function GF(t,e){return t.post("/api/v1/posting-rules",e)}async function JF(t,e,r){return t.put(`/api/v1/posting-rules/${e}`,r)}async function VF(t,e){await t.delete(`/api/v1/posting-rules/${e}`)}var Mw,Pw,Uw=X(()=>{"use strict";Mw=["PER_EMPLOYEE","PER_VENDOR","PER_PAIR","ONE_BATCH","PER_CLAIM"],Pw=["RAW","BY_CT_TP_NC","BY_CT_TP_NC_EMPLOYEE","BY_CT_TP_NC_VENDOR"]});async function LE(t,e){return t.search("/api/v1/employees/search",e)}async function WF(t,e){return t.search("/api/v1/employees/balances/search",e)}async function ZF(t,e){return t.get(`/api/v1/employees/${e}`)}async function XF(t,e){return t.post("/api/v1/employees",e)}async function KF(t,e,r){return t.put(`/api/v1/employees/${e}`,r)}async function e1(t,e){return t.delete(`/api/v1/employees/${e}`)}async function t1(t,e,r){return t.post(`/api/v1/employees/${e}/bind-user`,{userResourceId:r})}async function r1(t,e){return t.post("/api/v1/employees/import/preprocess",e)}async function n1(t,e){if((e.create?.length??0)+(e.update?.length??0)+(e.delete?.length??0)===0)throw new Error("import requires at least one create / update / delete row.");for(let[n,i]of Object.entries(e))if(Array.isArray(i)&&i.length>100)throw new Error(`max 100 ${n} rows per import. Split into batches.`);return t.post("/api/v1/employees/import",e)}var uA,$w=X(()=>{"use strict";uA=["FULL_TIME","PART_TIME","CONTRACTOR","INTERN","TEMPORARY","CONSULTANT"]});async function jw(t,e){return e?((await fc(t,{filter:{name:{eq:e}},limit:5}))?.data??[]).find(n=>n.name===e):void 0}async function i1(t,e){return e?((await _E(t,{filter:{itemCode:{eq:e}},limit:5}))?.data??[]).find(n=>n.itemCode===e):void 0}function RE(t){if(typeof t!="string")return String(t??"");let e=t.trim();return e0t[e.toLowerCase()]??e}function o1(t){if(typeof t!="string")return;let e=t.trim().toUpperCase().replace(/[\s-]+/g,"_");return e==="FUNCTIONAL_TO_SOURCE"||e==="SOURCE_TO_FUNCTIONAL"?e:void 0}function j4(t){if(t!=null){if(t!=="FUNCTIONAL_TO_SOURCE"&&t!=="SOURCE_TO_FUNCTIONAL")throw new qw(`Unknown rateDirection ${JSON.stringify(t)}. Use FUNCTIONAL_TO_SOURCE or SOURCE_TO_FUNCTIONAL (exact, upper-case).`);return t}}function Y4(t,e){if(typeof t!="number"||!Number.isFinite(t)||t<=0)throw new qw(`${e} must be a finite number greater than 0 (got ${JSON.stringify(t)}).`);return t}function jr(t){if(!t||typeof t!="object")return t;let{rateDirection:e,exchangeRate:r,...n}=t;if(j4(e),r===void 0){if(e==="SOURCE_TO_FUNCTIONAL")throw new qw("rateDirection SOURCE_TO_FUNCTIONAL was supplied without exchangeRate \u2014 there is nothing to invert. Provide the rate, or drop rateDirection.");return{...n}}Y4(r,"exchangeRate");let i=e==="SOURCE_TO_FUNCTIONAL"?1/r:r;return{...n,exchangeRate:i}}function Zf(t,e){if(!t?.exchangeRate)return;let{sourceCurrency:r,exchangeRate:n,rateDirection:i}=t,o=i==="SOURCE_TO_FUNCTIONAL"?1/n:n,s=r||"the foreign currency",a=[`FX: 1 base unit = ${Wf(o)} ${s}`];return i==="SOURCE_TO_FUNCTIONAL"&&a.push(`(from 1 ${s} = ${Wf(n)} base, inverted for you)`),typeof e=="number"&&Number.isFinite(e)&&e>0&&a.push(`\u2192 ${s} ${Wf(e)} books as ${Wf(e/o)} base`),a.join(" ")}function H4(t){if(!t)return;let{baseCurrency:e,sourceCurrency:r,exchangeRate:n,date:i}=t;if(!(typeof e!="string"||e.length===0)&&!(typeof r!="string"||r.length===0)&&!(typeof i!="string"||i.length===0)&&!(typeof n!="number"||!Number.isFinite(n)||n<=0))return`FX: 1 ${e} = ${Wf(n)} ${r} (applied rate for ${i})`}function Yw(t,e){return H4(t)??Zf(e)}function Wf(t){return Number.isFinite(t)?new Intl.NumberFormat("en-US",{maximumSignificantDigits:10,maximumFractionDigits:20,useGrouping:!1,notation:"standard"}).format(t):String(t)}async function t0e(t,e){if(!e?.trim())return;let r=e.trim().toLowerCase();return((await BE(t,{filter:{title:{contains:e.trim()}},limit:20}))?.data??[]).find(i=>i.title?.trim().toLowerCase()===r)}async function s1(t,e){return e?((await DE(t,{filter:{name:{eq:e}},limit:5}))?.data??[]).find(n=>n.name===e):void 0}async function a1(t,e){return e?((await kE(t,{filter:{name:{eq:e}},limit:5}))?.data??[]).find(n=>n.name===e):void 0}async function c1(t,e){if(!e)return;let r=e.toLowerCase().trim();return((await NE(t,{limit:500}))?.data??[]).find(i=>i.name.toLowerCase().trim()===r)}async function l1(t,e){if(!e)return;let r=e.toLowerCase().trim();return((await OE(t,{filter:{name:{eq:e}},limit:5}))?.data??[]).find(i=>i.name.toLowerCase().trim()===r)}async function u1(t,e){if(!e)return;let r=e.toLowerCase().trim();return((await FE(t,{filter:{name:{eq:e}},limit:5}))?.data??[]).find(i=>i.name.toLowerCase().trim()===r)}async function d1(t,e){if(!e)return;let r=e.toLowerCase().trim();return((await QE(t,{filter:{name:{eq:e}},limit:5}))?.data??[]).find(i=>i.name.toLowerCase().trim()===r)}async function f1(t,e){if(!e)return;let r=e.toLowerCase().trim();return((await LE(t,{filter:{email:{eq:e}},limit:5}))?.data??[]).find(i=>i.email?.toLowerCase().trim()===r)}function o0t(t){let e=Date.parse(`${t}T00:00:00Z`);return Number.isNaN(e)?t:new Date(e+864e5).toISOString().slice(0,10)}function r0e(t){if(!Array.isArray(t))return;let e=0;for(let r of t){if(!r||typeof r!="object")return;let n=r;if(n.discount!==void 0&&n.discount!==null&&Number(n.discount)!==0)return;let i=Number(n.quantity),o=Number(n.unitPrice);if(!Number.isFinite(i)||!Number.isFinite(o))return;e+=i*o}return e>0?e:void 0}async function n0e(t,e){let{contactResourceId:r,valueDate:n,currencyCode:i,lineSubtotal:o}=e;if(!r||!n)return;let s={contactResourceId:{eq:r},valueDate:{gte:n,lte:o0t(n)},status:{in:[...t0t]}};return i&&(s.currencyCode={eq:i}),o!==void 0&&(s.totalAmount={gte:o*r0t,lte:o*n0t}),((await vd(t,{filter:s,limit:i0t}))?.data??[]).find(c=>c.contactResourceId===r&&IE(c.valueDate)===n&&(!i||c.currencyCode===i)&&String(c.status??"").toUpperCase()!=="VOID")}function i0e(t,e,r){if(!s0t.test(t))throw new Error(`${e} must be a valid UUID (got "${t}"). ${r}`)}function ul(t,e={}){if(!(e.assumeFinalize===!0||t.saveAsDraft===!1))return;let n=t.lineItems;if(!Array.isArray(n)||n.length===0)return;let i=[];for(let a=0;a<n.length;a++){let c=n[a];if(!c||typeof c!="object")continue;let u=c.accountResourceId;(typeof u!="string"||u.trim().length===0)&&i.push(a)}if(i.length===0)return;let o=i.slice(0,5).join(", "),s=i.length>5?` (and ${i.length-5} more)`:"";return{error:`lineItems[${o}]${s}: accountResourceId is required when finalizing.`,status:422,hint:"Pre-flight guard \u2014 request never hit Clio. Search for the right GL account first, then retry with the resourceId on each line item.",repair:{tool:"search_accounts",arguments:{},reason:"Line item missing accountResourceId on a finalize call. Search for the GL account (by name or accountType) and attach the resourceId to each line item."}}}var KIt,pUr,e0t,qw,t0t,r0t,n0t,i0t,s0t,Pn=X(()=>{"use strict";Vf();Id();dF();AF();SE();Tw();kw();NF();PF();Lw();Uw();$w();KIt=["duplicate_skipped","duplicate_suspected"],pUr=new Set(KIt);e0t={"current assets":"Current Asset","current asset":"Current Asset","fixed assets":"Fixed Asset","fixed asset":"Fixed Asset","bank account":"Bank Accounts","bank accounts":"Bank Accounts",bank:"Bank Accounts","current liabilities":"Current Liability","current liability":"Current Liability","non-current liabilities":"Non-current Liability","non-current liability":"Non-current Liability",equity:"Shareholders Equity","shareholders equity":"Shareholders Equity","shareholders' equity":"Shareholders Equity","shareholder's equity":"Shareholders Equity",revenue:"Operating Revenue","operating revenue":"Operating Revenue","other revenue":"Other Revenue","other income":"Other Revenue",expense:"Operating Expense","operating expense":"Operating Expense",expenses:"Operating Expense","direct costs":"Direct Costs","cost of goods sold":"Direct Costs",cogs:"Direct Costs",cash:"Cash",inventory:"Inventory","discontinued expense":"Discontinued Expense","discontinued income":"Discontinued Income","finance cost":"Finance Cost","finance costs":"Finance Cost","financing income":"Financing Income",goodwill:"Goodwill","income tax expense":"Income Tax Expense","income tax":"Income Tax Expense","tax expense":"Income Tax Expense","investing expense":"Investing Expense","investing income":"Investing Income",investment:"Investment",investments:"Investment"};qw=class extends Error{constructor(e){super(e),this.name="ExchangeRateError"}};t0t=["DRAFT","UNPAID","PARTIALLY_PAID","PAID"],r0t=.995,n0t=1.3,i0t=20;s0t=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i});function s0e(t,e,r,n){let i=r==="SOURCE_TO_FUNCTIONAL"?t*e:t/e;if(!Number.isFinite(i)||Math.abs(i)>a0t)throw new Qt(`${n} of ${e} under ${r} translates ${t} into ${i}, outside the representable range. Check the rate direction \u2014 the two conventions are reciprocals, so picking the wrong one moves the result by rate\xB2.`);return i}function g1(t){let{amount:e,bookRate:r,closingRate:n,rateDirection:i,position:o="ASSET",currency:s="USD",baseCurrency:a="SGD"}=t;if(ln(e,"Foreign currency amount"),ln(r,"Book rate"),ln(n,"Closing rate"),o!=="ASSET"&&o!=="LIABILITY")throw new Qt(`position must be ASSET or LIABILITY (got ${JSON.stringify(o)}).`);let c=o1(i);if(!c)throw new Qt('rateDirection is required: FUNCTIONAL_TO_SOURCE (1 base unit = N foreign \u2014 what list_currency_rates returns) or SOURCE_TO_FUNCTIONAL (1 foreign unit = N base \u2014 the everyday "1 USD = 1.35 SGD" quote).');let u=re(s0e(e,r,c,"Book rate")),d=re(s0e(e,n,c,"Closing rate")),f=re(o==="LIABILITY"?u-d:d-u),p=f>=0,h=Math.abs(f),m;p?m={description:`FX revaluation \u2014 ${s} ${e.toLocaleString()} @ ${n} (was ${r}, ${c})`,lines:[{account:`${s} Monetary Item`,debit:h,credit:0},{account:"FX Unrealized Gain",debit:0,credit:h}]}:m={description:`FX revaluation \u2014 ${s} ${e.toLocaleString()} @ ${n} (was ${r}, ${c})`,lines:[{account:"FX Unrealized Loss",debit:h,credit:0},{account:`${s} Monetary Item`,debit:0,credit:h}]};let A={description:`Reversal of FX revaluation \u2014 ${s} ${e.toLocaleString()}`,lines:m.lines.map(C=>({account:C.account,debit:C.credit,credit:C.debit}))},g=["FX Revaluation Workings (IAS 21)",`Foreign currency: ${s} ${e.toLocaleString()} | Base currency: ${a}`,`Rate direction: ${c} | Position: ${o}`,`Book rate: ${r} \u2192 Book value: ${Ue(u,a)}`,`Closing rate: ${n} \u2192 Closing value: ${Ue(d,a)}`,`${p?"Unrealized gain":"Unrealized loss"}: ${Ue(Math.abs(f),a)}`,"Method: IAS 21.23 \u2014 monetary items translated at closing rate","Reversal: Day 1 next period (standard reval/reverse approach)"].join(`
205
+ `);a={capsuleType:"Deferred Revenue",capsuleName:`Deferred Revenue \u2014 ${pi(e,o)} \u2014 ${r} periods`,capsuleDescription:d,tags:["Deferred Revenue"],customFields:{"Contract #":null},steps:c}}return{type:"deferred-revenue",currency:o??null,inputs:{amount:e,periods:r,frequency:n,startDate:i??null},perPeriodAmount:re(e/r),schedule:s,blueprint:a}}function WIe(t,e,r,n,i){let o=re(t/e),s=[],a=t,c=r==="quarterly"?3:1;for(let u=1;u<=e;u++){let f=u===e?re(a):o;a=re(a-f);let p=n?lo(n,u*c):null,h;i==="prepaid"?h={description:`Prepaid expense recognition \u2014 Period ${u} of ${e}`,lines:[{account:"Expense",debit:f,credit:0},{account:"Prepaid Asset",debit:0,credit:f}]}:h={description:`Deferred revenue recognition \u2014 Period ${u} of ${e}`,lines:[{account:"Deferred Revenue",debit:f,credit:0},{account:"Revenue",debit:0,credit:f}]},s.push({period:u,date:p,amortized:f,remainingBalance:a,journal:h})}return s}var $4=X(()=>{"use strict";_s();Wo();Da()});async function Zo(t,e,r,n){return t.post(e,{[r]:n})}function Mn(t,e,r=500,n=e){if(!Array.isArray(t))throw new Error(`${e} must be an array.`);if(t.length===0)throw new Error(`${e} array is empty.`);if(t.length>r)throw new Error(`max ${r} ${n} per call. Split into batches.`)}function dc(t,e){t.forEach((r,n)=>{if(!r||typeof r!="object")return;let i=r;if("dateFormat"in i)throw new Error(`row ${n}: dateFormat field is no longer supported (ISO 8601 YYYY-MM-DD only)`);for(let o of e){let s=i[o];if(s!=null&&(typeof s!="string"||!ZIt.test(s)))throw new Error(`row ${n}: ${o} must be YYYY-MM-DD (got ${JSON.stringify(s)})`)}})}var ZIt,Sa=X(()=>{"use strict";ZIt=/^\d{4}-\d{2}-\d{2}$/});async function ZIe(t,e,r){return t.get(`/api/v1/contacts/${e}/signals`,{btType:r})}async function Gf(t,e){return t.list("/api/v1/contacts",e)}async function fc(t,e){return t.search("/api/v1/contacts/search",e)}async function vE(t,e){return t.post("/api/v1/contacts",e)}async function XO(t,e,r){return t.put(`/api/v1/contacts/${e}`,r)}async function Jf(t,e){return t.get(`/api/v1/contacts/${e}`)}async function KO(t,e){await t.delete(`/api/v1/contacts/${e}`)}async function eF(t,e){return Zo(t,"/api/v1/contacts/bulk-upsert","contacts",e)}var Vf=X(()=>{"use strict";Sa()});async function tF(t,e){return t.list("/api/v1/bills",e)}async function Ds(t,e){return t.get(`/api/v1/bills/${e}`)}async function vd(t,e){return t.search("/api/v1/bills/search",e)}async function cA(t,e){return t.post("/api/v1/bills",{...e,currency:jr(e.currency),taxCurrency:jr(e.taxCurrency),saveAsDraft:e.saveAsDraft??!0})}async function rF(t,e,r){return t.put(`/api/v1/bills/${e}`,r)}async function ww(t,e,r){return t.put(`/api/v1/bills/${e}`,{...r,resourceId:e,saveAsDraft:!1})}async function nF(t,e){await t.delete(`/api/v1/bills/${e}`)}async function iF(t,e){return t.get(`/api/v1/bills/${e}/download`)}async function _w(t,e,r){return t.post(`/api/v1/bills/${e}/payments`,{...r,currency:jr(r.currency),saveAsDraft:r.saveAsDraft??!0})}async function oF(t,e,r){return t.post(`/api/v1/bills/${e}/credits`,{credits:r})}async function Dw(t,e){return t.post("/api/v1/scheduled/bills",{...e,bill:{...e.bill,currency:jr(e.bill?.currency)}})}async function sF(t,e){let r=await t.get(`/api/v1/bills/${e}/payments`);return{data:Array.isArray(r)?r:r.data??[]}}async function aF(t,e){let r=await t.get(`/api/v1/bills/${e}/credits`);return{data:Array.isArray(r)?r:r.data??[]}}async function cF(t,e,r){await t.delete(`/api/v1/bills/${e}/credits/${r}`)}async function lF(t,e){return Zo(t,"/api/v1/bills/bulk-upsert","bills",e)}async function uF(t,e){return Zo(t,"/api/v1/bills/line-items/bulk-upsert","bills",e)}var Id=X(()=>{"use strict";Sa();Pn()});function IE(t){if(typeof t=="number"){let e=new Date(t);return Number.isNaN(e.getTime())?void 0:e.toISOString().slice(0,10)}if(typeof t=="string"){let e=/^(\d{4})-(\d{1,2})-(\d{1,2})(?:[T\s]|$)/.exec(t.trim());return e?`${e[1]}-${e[2].padStart(2,"0")}-${e[3].padStart(2,"0")}`:void 0}}var dF=X(()=>{"use strict"});async function fF(t,e){return t.list("/api/v1/items",e)}async function wE(t,e){return t.get(`/api/v1/items/${e}`)}async function _E(t,e){return t.search("/api/v1/items/search",e)}async function Sw(t,e){let r={...e};return e.appliesToSale&&!r.saleItemName&&(r.saleItemName=e.internalName),e.appliesToPurchase&&!r.purchaseItemName&&(r.purchaseItemName=e.internalName),t.post("/api/v1/items",r)}async function pF(t,e,r){let i=(await wE(t,e)).data,o={itemCode:i.itemCode,internalName:i.internalName,appliesToSale:i.appliesToSale,appliesToPurchase:i.appliesToPurchase};return i.appliesToSale&&(i.saleItemName&&(o.saleItemName=i.saleItemName),i.salePrice!==void 0&&(o.salePrice=i.salePrice),i.saleAccountResourceId&&(o.saleAccountResourceId=i.saleAccountResourceId)),i.appliesToPurchase&&(i.purchaseItemName&&(o.purchaseItemName=i.purchaseItemName),i.purchasePrice!==void 0&&(o.purchaseItemPrice=i.purchasePrice),i.purchaseAccountResourceId&&(o.purchaseAccountResourceId=i.purchaseAccountResourceId)),Object.assign(o,r),t.put(`/api/v1/items/${e}`,o)}async function hF(t,e){await t.delete(`/api/v1/items/${e}`)}async function mF(t,e){return t.post("/api/v1/items/bulk-upsert",{items:e})}var AF=X(()=>{"use strict"});async function wd(t,e){return t.list("/api/v1/chart-of-accounts",e)}async function DE(t,e){return t.search("/api/v1/chart-of-accounts/search",e)}async function XIe(t,e){return t.get(`/api/v1/chart-of-accounts/${e}`)}async function Rw(t,e){return t.post("/api/v1/chart-of-accounts",e)}async function KIe(t,e,r){return t.put(`/api/v1/chart-of-accounts/${e}`,r)}function gF(t){let e={};for(let r of XIt){let n=t[r];n!=null&&(r==="accountType"&&typeof n=="string"?e.accountType=RE(n):e[r]=n)}return e}async function yF(t,e){return t.post("/api/v1/chart-of-accounts/bulk-upsert",{accounts:e})}async function EF(t,e){await t.delete(`/api/v1/chart-of-accounts/${e}`)}async function e0e(t,e){return t.list("/api/v1/account-classifications",e)}var XIt,SE=X(()=>{"use strict";Pn();XIt=["resourceId","code","name","accountType","currencyCode","description","status"]});async function xE(t){return t.get("/api/v1/capsuleTypes")}async function xw(t,e){return t.post("/api/v1/capsuleTypes",e)}async function bF(t,e){return t.list("/api/v1/capsules",e)}async function BE(t,e){return t.search("/api/v1/capsules/search",e)}async function Bw(t,e){return t.get(`/api/v1/capsules/${e}`)}async function lA(t,e){return t.post("/api/v1/capsules",e)}async function CF(t,e,r){let n=await Bw(t,e),i=n.data.capsuleType?.resourceId;if(!i)throw new Error(`Cannot update capsule ${e}: missing capsuleType.resourceId from GET response`);let o={resourceId:e,capsuleTypeResourceId:i,title:n.data.title,description:n.data.description,...r};return t.put(`/api/v1/capsules/${e}`,o)}async function vF(t,e){await t.delete(`/api/v1/capsules/${e}`)}async function IF(t,e){return t.post("/api/v1/moveTransactionCapsules",e)}var Tw=X(()=>{"use strict"});async function TE(t,e){return t.list("/api/v1/tax-profiles",e)}async function wF(t,e){return t.list("/api/v1/tax-types",e)}async function _F(t,e){return t.post("/api/v1/tax-profiles",e)}async function kE(t,e){return t.post("/api/v1/tax-profiles/search",e)}async function DF(t,e){return t.get(`/api/v1/tax-profiles/${e}`)}async function SF(t,e,r){return t.put(`/api/v1/tax-profiles/${e}`,r)}async function RF(t){let e=await t.get("/api/v1/withholding-tax-codes");return{data:Array.isArray(e)?e:e.data??[]}}var kw=X(()=>{"use strict"});async function NE(t,e){return t.list("/api/v1/tags",e)}async function xF(t,e){return t.get(`/api/v1/tags/${e}`)}async function BF(t,e){return t.search("/api/v1/tags/search",e)}async function Nw(t,e){return t.post("/api/v1/tags",e)}async function TF(t,e,r){return t.put(`/api/v1/tags/${e}`,r)}async function kF(t,e){await t.delete(`/api/v1/tags/${e}`)}var NF=X(()=>{"use strict"});async function OF(t,e){return t.list("/api/v1/claim-types",e)}async function FF(t,e){return t.get(`/api/v1/claim-types/${e}`)}async function OE(t,e){return t.search("/api/v1/claim-types/search",e)}async function QF(t,e){return t.post("/api/v1/claim-types",e)}async function LF(t,e,r){return t.put(`/api/v1/claim-types/${e}`,r)}async function MF(t,e){await t.delete(`/api/v1/claim-types/${e}`)}var Ow,PF=X(()=>{"use strict";Ow=["expenseAccountResourceId","taxProfileResourceId","classifierConfig"]});async function UF(t,e){return t.list("/api/v1/claim-profiles",e)}async function $F(t,e){return t.get(`/api/v1/claim-profiles/${e}`)}async function FE(t,e){return t.search("/api/v1/claim-profiles/search",e)}async function qF(t,e){return t.post("/api/v1/claim-profiles",e)}async function jF(t,e,r){return t.put(`/api/v1/claim-profiles/${e}`,r)}async function YF(t,e){await t.delete(`/api/v1/claim-profiles/${e}`)}var Fw,q4,Qw,Lw=X(()=>{"use strict";Fw=["DAILY","WEEKLY","MONTHLY","QUARTERLY","YEARLY"],q4=["NO_TAX","INCLUSIVE"],Qw=["approverUserResourceId","visibleClaimTypeIds","visibleTaxProfileIds","visibleClassifierIds","visibleVendorResourceIds","allowedCurrencies","minClaimAmount","maxClaimAmount","maxPerPeriodAmount","perPeriod","employeeBalanceAccountResourceId","taxMode"]});async function HF(t,e){return t.list("/api/v1/posting-rules",e)}async function zF(t,e){return t.get(`/api/v1/posting-rules/${e}`)}async function QE(t,e){return t.search("/api/v1/posting-rules/search",e)}async function GF(t,e){return t.post("/api/v1/posting-rules",e)}async function JF(t,e,r){return t.put(`/api/v1/posting-rules/${e}`,r)}async function VF(t,e){await t.delete(`/api/v1/posting-rules/${e}`)}var Mw,Pw,Uw=X(()=>{"use strict";Mw=["PER_EMPLOYEE","PER_VENDOR","PER_PAIR","ONE_BATCH","PER_CLAIM"],Pw=["RAW","BY_CT_TP_NC","BY_CT_TP_NC_EMPLOYEE","BY_CT_TP_NC_VENDOR"]});async function LE(t,e){return t.search("/api/v1/employees/search",e)}async function WF(t,e){return t.search("/api/v1/employees/balances/search",e)}async function ZF(t,e){return t.get(`/api/v1/employees/${e}`)}async function XF(t,e){return t.post("/api/v1/employees",e)}async function KF(t,e,r){return t.put(`/api/v1/employees/${e}`,r)}async function e1(t,e){return t.delete(`/api/v1/employees/${e}`)}async function t1(t,e,r){return t.post(`/api/v1/employees/${e}/bind-user`,{userResourceId:r})}async function r1(t,e){return t.post("/api/v1/employees/import/preprocess",e)}async function n1(t,e){if((e.create?.length??0)+(e.update?.length??0)+(e.delete?.length??0)===0)throw new Error("import requires at least one create / update / delete row.");for(let[n,i]of Object.entries(e))if(Array.isArray(i)&&i.length>100)throw new Error(`max 100 ${n} rows per import. Split into batches.`);return t.post("/api/v1/employees/import",e)}var uA,$w=X(()=>{"use strict";uA=["FULL_TIME","PART_TIME","CONTRACTOR","INTERN","TEMPORARY","CONSULTANT"]});async function jw(t,e){return e?((await fc(t,{filter:{name:{eq:e}},limit:5}))?.data??[]).find(n=>n.name===e):void 0}async function i1(t,e){return e?((await _E(t,{filter:{itemCode:{eq:e}},limit:5}))?.data??[]).find(n=>n.itemCode===e):void 0}function RE(t){if(typeof t!="string")return String(t??"");let e=t.trim();return e0t[e.toLowerCase()]??e}function o1(t){if(typeof t!="string")return;let e=t.trim().toUpperCase().replace(/[\s-]+/g,"_");return e==="FUNCTIONAL_TO_SOURCE"||e==="SOURCE_TO_FUNCTIONAL"?e:void 0}function j4(t){if(t!=null){if(t!=="FUNCTIONAL_TO_SOURCE"&&t!=="SOURCE_TO_FUNCTIONAL")throw new qw(`Unknown rateDirection ${JSON.stringify(t)}. Use FUNCTIONAL_TO_SOURCE or SOURCE_TO_FUNCTIONAL (exact, upper-case).`);return t}}function Y4(t,e){if(typeof t!="number"||!Number.isFinite(t)||t<=0)throw new qw(`${e} must be a finite number greater than 0 (got ${JSON.stringify(t)}).`);return t}function jr(t){if(!t||typeof t!="object")return t;let{rateDirection:e,exchangeRate:r,...n}=t;if(j4(e),r===void 0){if(e==="SOURCE_TO_FUNCTIONAL")throw new qw("rateDirection SOURCE_TO_FUNCTIONAL was supplied without exchangeRate \u2014 there is nothing to invert. Provide the rate, or drop rateDirection.");return{...n}}Y4(r,"exchangeRate");let i=e==="SOURCE_TO_FUNCTIONAL"?1/r:r;return{...n,exchangeRate:i}}function Zf(t,e){if(!t?.exchangeRate)return;let{sourceCurrency:r,exchangeRate:n,rateDirection:i}=t,o=i==="SOURCE_TO_FUNCTIONAL"?1/n:n,s=r||"the foreign currency",a=[`FX: 1 base unit = ${Wf(o)} ${s}`];return i==="SOURCE_TO_FUNCTIONAL"&&a.push(`(from 1 ${s} = ${Wf(n)} base, inverted for you)`),typeof e=="number"&&Number.isFinite(e)&&e>0&&a.push(`\u2192 ${s} ${Wf(e)} books as ${Wf(e/o)} base`),a.join(" ")}function H4(t){if(!t)return;let{baseCurrency:e,sourceCurrency:r,exchangeRate:n,date:i}=t;if(!(typeof e!="string"||e.length===0)&&!(typeof r!="string"||r.length===0)&&!(typeof i!="string"||i.length===0)&&!(typeof n!="number"||!Number.isFinite(n)||n<=0))return`FX: 1 ${e} (your base) = ${Wf(n)} ${r} (applied rate for ${i})`}function Yw(t,e){return H4(t)??Zf(e)}function Wf(t){return Number.isFinite(t)?new Intl.NumberFormat("en-US",{maximumSignificantDigits:10,maximumFractionDigits:20,useGrouping:!1,notation:"standard"}).format(t):String(t)}async function t0e(t,e){if(!e?.trim())return;let r=e.trim().toLowerCase();return((await BE(t,{filter:{title:{contains:e.trim()}},limit:20}))?.data??[]).find(i=>i.title?.trim().toLowerCase()===r)}async function s1(t,e){return e?((await DE(t,{filter:{name:{eq:e}},limit:5}))?.data??[]).find(n=>n.name===e):void 0}async function a1(t,e){return e?((await kE(t,{filter:{name:{eq:e}},limit:5}))?.data??[]).find(n=>n.name===e):void 0}async function c1(t,e){if(!e)return;let r=e.toLowerCase().trim();return((await NE(t,{limit:500}))?.data??[]).find(i=>i.name.toLowerCase().trim()===r)}async function l1(t,e){if(!e)return;let r=e.toLowerCase().trim();return((await OE(t,{filter:{name:{eq:e}},limit:5}))?.data??[]).find(i=>i.name.toLowerCase().trim()===r)}async function u1(t,e){if(!e)return;let r=e.toLowerCase().trim();return((await FE(t,{filter:{name:{eq:e}},limit:5}))?.data??[]).find(i=>i.name.toLowerCase().trim()===r)}async function d1(t,e){if(!e)return;let r=e.toLowerCase().trim();return((await QE(t,{filter:{name:{eq:e}},limit:5}))?.data??[]).find(i=>i.name.toLowerCase().trim()===r)}async function f1(t,e){if(!e)return;let r=e.toLowerCase().trim();return((await LE(t,{filter:{email:{eq:e}},limit:5}))?.data??[]).find(i=>i.email?.toLowerCase().trim()===r)}function o0t(t){let e=Date.parse(`${t}T00:00:00Z`);return Number.isNaN(e)?t:new Date(e+864e5).toISOString().slice(0,10)}function r0e(t){if(!Array.isArray(t))return;let e=0;for(let r of t){if(!r||typeof r!="object")return;let n=r;if(n.discount!==void 0&&n.discount!==null&&Number(n.discount)!==0)return;let i=Number(n.quantity),o=Number(n.unitPrice);if(!Number.isFinite(i)||!Number.isFinite(o))return;e+=i*o}return e>0?e:void 0}async function n0e(t,e){let{contactResourceId:r,valueDate:n,currencyCode:i,lineSubtotal:o}=e;if(!r||!n)return;let s={contactResourceId:{eq:r},valueDate:{gte:n,lte:o0t(n)},status:{in:[...t0t]}};return i&&(s.currencyCode={eq:i}),o!==void 0&&(s.totalAmount={gte:o*r0t,lte:o*n0t}),((await vd(t,{filter:s,limit:i0t}))?.data??[]).find(c=>c.contactResourceId===r&&IE(c.valueDate)===n&&(!i||c.currencyCode===i)&&String(c.status??"").toUpperCase()!=="VOID")}function i0e(t,e,r){if(!s0t.test(t))throw new Error(`${e} must be a valid UUID (got "${t}"). ${r}`)}function ul(t,e={}){if(!(e.assumeFinalize===!0||t.saveAsDraft===!1))return;let n=t.lineItems;if(!Array.isArray(n)||n.length===0)return;let i=[];for(let a=0;a<n.length;a++){let c=n[a];if(!c||typeof c!="object")continue;let u=c.accountResourceId;(typeof u!="string"||u.trim().length===0)&&i.push(a)}if(i.length===0)return;let o=i.slice(0,5).join(", "),s=i.length>5?` (and ${i.length-5} more)`:"";return{error:`lineItems[${o}]${s}: accountResourceId is required when finalizing.`,status:422,hint:"Pre-flight guard \u2014 request never hit Clio. Search for the right GL account first, then retry with the resourceId on each line item.",repair:{tool:"search_accounts",arguments:{},reason:"Line item missing accountResourceId on a finalize call. Search for the GL account (by name or accountType) and attach the resourceId to each line item."}}}var KIt,pUr,e0t,qw,t0t,r0t,n0t,i0t,s0t,Pn=X(()=>{"use strict";Vf();Id();dF();AF();SE();Tw();kw();NF();PF();Lw();Uw();$w();KIt=["duplicate_skipped","duplicate_suspected"],pUr=new Set(KIt);e0t={"current assets":"Current Asset","current asset":"Current Asset","fixed assets":"Fixed Asset","fixed asset":"Fixed Asset","bank account":"Bank Accounts","bank accounts":"Bank Accounts",bank:"Bank Accounts","current liabilities":"Current Liability","current liability":"Current Liability","non-current liabilities":"Non-current Liability","non-current liability":"Non-current Liability",equity:"Shareholders Equity","shareholders equity":"Shareholders Equity","shareholders' equity":"Shareholders Equity","shareholder's equity":"Shareholders Equity",revenue:"Operating Revenue","operating revenue":"Operating Revenue","other revenue":"Other Revenue","other income":"Other Revenue",expense:"Operating Expense","operating expense":"Operating Expense",expenses:"Operating Expense","direct costs":"Direct Costs","cost of goods sold":"Direct Costs",cogs:"Direct Costs",cash:"Cash",inventory:"Inventory","discontinued expense":"Discontinued Expense","discontinued income":"Discontinued Income","finance cost":"Finance Cost","finance costs":"Finance Cost","financing income":"Financing Income",goodwill:"Goodwill","income tax expense":"Income Tax Expense","income tax":"Income Tax Expense","tax expense":"Income Tax Expense","investing expense":"Investing Expense","investing income":"Investing Income",investment:"Investment",investments:"Investment"};qw=class extends Error{constructor(e){super(e),this.name="ExchangeRateError"}};t0t=["DRAFT","UNPAID","PARTIALLY_PAID","PAID"],r0t=.995,n0t=1.3,i0t=20;s0t=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i});function s0e(t,e,r,n){let i=r==="SOURCE_TO_FUNCTIONAL"?t*e:t/e;if(!Number.isFinite(i)||Math.abs(i)>a0t)throw new Qt(`${n} of ${e} under ${r} translates ${t} into ${i}, outside the representable range. Check the rate direction \u2014 the two conventions are reciprocals, so picking the wrong one moves the result by rate\xB2.`);return i}function g1(t){let{amount:e,bookRate:r,closingRate:n,rateDirection:i,position:o="ASSET",currency:s="USD",baseCurrency:a="SGD"}=t;if(ln(e,"Foreign currency amount"),ln(r,"Book rate"),ln(n,"Closing rate"),o!=="ASSET"&&o!=="LIABILITY")throw new Qt(`position must be ASSET or LIABILITY (got ${JSON.stringify(o)}).`);let c=o1(i);if(!c)throw new Qt('rateDirection is required: FUNCTIONAL_TO_SOURCE (1 base unit = N foreign \u2014 what list_currency_rates returns) or SOURCE_TO_FUNCTIONAL (1 foreign unit = N base \u2014 the everyday "1 USD = 1.35 SGD" quote).');let u=re(s0e(e,r,c,"Book rate")),d=re(s0e(e,n,c,"Closing rate")),f=re(o==="LIABILITY"?u-d:d-u),p=f>=0,h=Math.abs(f),m;p?m={description:`FX revaluation \u2014 ${s} ${e.toLocaleString()} @ ${n} (was ${r}, ${c})`,lines:[{account:`${s} Monetary Item`,debit:h,credit:0},{account:"FX Unrealized Gain",debit:0,credit:h}]}:m={description:`FX revaluation \u2014 ${s} ${e.toLocaleString()} @ ${n} (was ${r}, ${c})`,lines:[{account:"FX Unrealized Loss",debit:h,credit:0},{account:`${s} Monetary Item`,debit:0,credit:h}]};let A={description:`Reversal of FX revaluation \u2014 ${s} ${e.toLocaleString()}`,lines:m.lines.map(C=>({account:C.account,debit:C.credit,credit:C.debit}))},g=["FX Revaluation Workings (IAS 21)",`Foreign currency: ${s} ${e.toLocaleString()} | Base currency: ${a}`,`Rate direction: ${c} | Position: ${o}`,`Book rate: ${r} \u2192 Book value: ${Ue(u,a)}`,`Closing rate: ${n} \u2192 Closing value: ${Ue(d,a)}`,`${p?"Unrealized gain":"Unrealized loss"}: ${Ue(Math.abs(f),a)}`,"Method: IAS 21.23 \u2014 monetary items translated at closing rate","Reversal: Day 1 next period (standard reval/reverse approach)"].join(`
206
206
  `),y={capsuleType:"FX Revaluation",capsuleName:`FX Reval \u2014 ${s} ${e.toLocaleString()} ${o} \u2014 ${r} \u2192 ${n} (${c})`,capsuleDescription:g,tags:["FX Revaluation",s],customFields:{"Source Account":null,"Period End Date":null},steps:[qr(1,m.description,null,m.lines),qr(2,A.description,null,A.lines)]};return{type:"fx-reval",currency:s,inputs:{amount:e,bookRate:r,closingRate:n,rateDirection:c,position:o,baseCurrency:a},bookValue:u,closingValue:d,gainOrLoss:f,isGain:p,journal:m,reversalJournal:A,blueprint:y}}var a0t,z4=X(()=>{"use strict";_s();Wo();Pn();Da();a0t=Number.MAX_SAFE_INTEGER/100});function y1(t){let{buckets:e,existingProvision:r=0,currency:n}=t;for(let g of e)fu(g.balance,`${g.name} balance`),fu(g.rate,`${g.name} loss rate`);fu(r,"Existing provision");let i=e.map(g=>({bucket:g.name,balance:g.balance,lossRate:g.rate,ecl:re(g.balance*g.rate/100)})),o=re(e.reduce((g,y)=>g+y.balance,0)),s=re(i.reduce((g,y)=>g+y.ecl,0)),a=re(s-r),c=a>=0,u=Math.abs(a),d=o>0?re(s/o*100*100)/100:0,f;c?f={description:"ECL provision increase \u2014 IFRS 9 simplified approach",lines:[{account:"Bad Debt Expense",debit:u,credit:0},{account:"Allowance for Doubtful Debts",debit:0,credit:u}]}:f={description:"ECL provision release \u2014 IFRS 9 simplified approach",lines:[{account:"Allowance for Doubtful Debts",debit:u,credit:0},{account:"Bad Debt Expense",debit:0,credit:u}]};let p=n??void 0,h=i.map(g=>` ${g.bucket}: ${Ue(g.balance,p)} \xD7 ${g.lossRate}% = ${Ue(g.ecl,p)}`).join(`
207
207
  `),m=["ECL Provision Matrix Workings (IFRS 9)",`Total receivables: ${Ue(o,p)} | Weighted avg loss rate: ${d}%`,"Provision matrix:",h,`Total ECL required: ${Ue(s,p)} | Existing provision: ${Ue(r,p)}`,`Adjustment: ${Ue(Math.abs(a),p)} (${c?"increase":"release"})`,"Method: IFRS 9.5.5.15 simplified approach \u2014 lifetime ECL, provision matrix"].join(`
208
208
  `),A={capsuleType:"ECL Provision",capsuleName:`ECL Provision \u2014 ${pi(s,n)} \u2014 ${e.length} buckets`,capsuleDescription:m,tags:["ECL","Bad Debt"],customFields:{"Reporting Period":null,"Aged Receivables Report Date":null},steps:[qr(1,f.description,null,f.lines)]};return{type:"ecl",currency:n??null,inputs:{buckets:e.map(g=>({name:g.name,balance:g.balance,rate:g.rate})),existingProvision:r},totalReceivables:o,totalEcl:s,weightedRate:d,adjustmentRequired:a,isIncrease:c,bucketDetails:i,journal:f,blueprint:A}}var G4=X(()=>{"use strict";_s();Wo();Da()});function E1(t){let{amount:e,annualRate:r,termMonths:n,startDate:i,currency:o}=t;ln(e,"Estimated future outflow"),zf(r,"Discount rate"),Qi(n,"Term (months)"),Bi(i);let s=r/100/12,a=re(-(0,a0e.pv)(s,n,0,e)),c=re(e-a),u={description:"Initial provision recognition at PV (IAS 37)",lines:[{account:"Provision Expense",debit:a,credit:0},{account:"Provision for Obligations",debit:0,credit:a}]},d=[],f=a,p=0;for(let m=1;m<=n;m++){let A=re(f),g=m===n,y;g?y=re(e-A):y=re(A*s),f=re(A+y),p=re(p+y);let C=i?lo(i,m):null,E={description:`Provision unwinding \u2014 Month ${m} of ${n}`,lines:[{account:"Finance Cost \u2014 Unwinding",debit:y,credit:0},{account:"Provision for Obligations",debit:0,credit:y}]};d.push({period:m,date:C,openingBalance:A,payment:0,interest:y,principal:0,closingBalance:f,journal:E})}let h=null;if(i){let m=lo(i,n),A=[qr(1,u.description,i,u.lines),...d.map((C,E)=>qr(E+2,C.journal.description,C.date,C.journal.lines)),aA(n+2,"Settlement \u2014 pay the obligation",m,[{account:"Provision for Obligations",debit:e,credit:0},{account:"Cash / Bank Account",debit:0,credit:e}])],g=o??void 0,y=["IAS 37 Provision Workings",`Nominal obligation: ${Ue(e,g)} | Discount rate: ${r}% p.a. (${re(s*100)}% monthly)`,`Term to settlement: ${n} months | PV at recognition: ${Ue(a,g)}`,`Total unwinding (finance cost): ${Ue(c,g)}`,"Method: PV of single future outflow (IAS 37.45), unwinding via effective interest (IAS 37.60)",`Settlement: ${Ue(e,g)} cash out on ${m}`,"Rounding: 2dp per period, final period closes to nominal amount"].join(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jaz-clio",
3
- "version": "5.38.0",
3
+ "version": "5.38.1",
4
4
  "description": "Clio: Command Line Interface Operator for Jaz AI.",
5
5
  "type": "module",
6
6
  "bin": {