jaz-cli 2.0.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 +162 -0
- package/assets/skills/api/references/dependencies.md +139 -0
- package/assets/skills/api/references/endpoints.md +1299 -0
- package/assets/skills/api/references/errors.md +751 -0
- package/assets/skills/api/references/feature-glossary.md +216 -0
- package/assets/skills/api/references/field-map.md +428 -0
- package/assets/skills/api/references/full-api-surface.md +699 -0
- package/assets/skills/api/references/search-reference.md +714 -0
- package/assets/skills/conversion/SKILL.md +130 -0
- package/assets/skills/conversion/references/edge-cases.md +174 -0
- package/assets/skills/conversion/references/file-analysis.md +120 -0
- package/assets/skills/conversion/references/file-types.md +501 -0
- package/assets/skills/conversion/references/mapping-rules.md +166 -0
- package/assets/skills/conversion/references/option1-full.md +145 -0
- package/assets/skills/conversion/references/option2-quick.md +197 -0
- package/assets/skills/conversion/references/verification.md +142 -0
- package/dist/commands/init.js +76 -0
- package/dist/commands/update.js +28 -0
- package/dist/commands/versions.js +33 -0
- package/dist/index.js +52 -0
- package/dist/types/index.js +5 -0
- package/dist/utils/github.js +81 -0
- package/dist/utils/logger.js +21 -0
- package/dist/utils/template.js +49 -0
- package/package.json +44 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Full Conversion (Option 1) — Complete Transaction History
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Full Conversion transfers **all transaction details** for FY and FY-1 (typically 2 financial years). This preserves the complete audit trail including individual invoices, bills, payments, journals, and more.
|
|
6
|
+
|
|
7
|
+
**Result:** On Jaz, the ledger shows every transaction from the source system. The Trial Balance at any date within the conversion period matches the source.
|
|
8
|
+
|
|
9
|
+
## Required Input Files
|
|
10
|
+
|
|
11
|
+
**No date range (reference data):**
|
|
12
|
+
1. Chart of Accounts — full CoA list
|
|
13
|
+
2. Contact list (customers + suppliers) with details
|
|
14
|
+
3. Item list (products/services)
|
|
15
|
+
4. Tax profile list
|
|
16
|
+
5. Exchange rate table (rates for the conversion period)
|
|
17
|
+
|
|
18
|
+
**As-on date (FYE or start date):**
|
|
19
|
+
6. Trial Balance — opening balances at conversion start
|
|
20
|
+
7. AR Aging — outstanding receivables at conversion start
|
|
21
|
+
8. AP Aging — outstanding payables at conversion start
|
|
22
|
+
9. Fixed Asset Register — assets with accumulated depreciation
|
|
23
|
+
|
|
24
|
+
**Conversion period range:**
|
|
25
|
+
10. Detailed invoice listing (with line items)
|
|
26
|
+
11. Detailed bill listing (with line items)
|
|
27
|
+
12. Payment details (invoice payments + bill payments)
|
|
28
|
+
13. General Ledger report (all journal entries)
|
|
29
|
+
14. Credit note listing (customer + supplier)
|
|
30
|
+
15. Bank statement / bank records
|
|
31
|
+
16. Cash-in / cash-out entries
|
|
32
|
+
17. Cash transfer records
|
|
33
|
+
|
|
34
|
+
## Execution Order
|
|
35
|
+
|
|
36
|
+
### Phase 1: Foundation (same as Quick)
|
|
37
|
+
1. Currencies + exchange rates
|
|
38
|
+
2. Chart of Accounts (full match or replace)
|
|
39
|
+
3. Tax profile discovery + mapping
|
|
40
|
+
4. Contacts (customers + suppliers)
|
|
41
|
+
5. Items (products/services with pricing)
|
|
42
|
+
|
|
43
|
+
### Phase 2: Opening Balances
|
|
44
|
+
If converting mid-FY (not from the very start of the ledger):
|
|
45
|
+
- Create a TTB journal for opening balances at the conversion start date
|
|
46
|
+
- This is the same pattern as Quick Conversion Phase 3
|
|
47
|
+
|
|
48
|
+
### Phase 3: Transactions (chronological order within the period)
|
|
49
|
+
|
|
50
|
+
#### 3.1 Invoices
|
|
51
|
+
Create each source invoice with its original:
|
|
52
|
+
- Date (`valueDate`)
|
|
53
|
+
- Reference number
|
|
54
|
+
- Contact
|
|
55
|
+
- Line items (account, description, quantity, unit price, tax)
|
|
56
|
+
- Currency + exchange rate (for FX invoices)
|
|
57
|
+
|
|
58
|
+
#### 3.2 Bills
|
|
59
|
+
Same pattern as invoices but via `POST /api/v1/bills`.
|
|
60
|
+
|
|
61
|
+
#### 3.3 Journal Entries
|
|
62
|
+
Source GL entries that aren't invoices/bills/payments → create as journal entries.
|
|
63
|
+
- Map each line to the correct CoA account
|
|
64
|
+
- Preserve debit/credit direction
|
|
65
|
+
- Note: Journals have NO top-level currency field
|
|
66
|
+
|
|
67
|
+
#### 3.4 Credit Notes
|
|
68
|
+
- Customer credit notes via `POST /api/v1/customer-credit-notes`
|
|
69
|
+
- Supplier credit notes via `POST /api/v1/supplier-credit-notes`
|
|
70
|
+
|
|
71
|
+
#### 3.5 Cash Entries
|
|
72
|
+
- Cash-in entries (deposits received)
|
|
73
|
+
- Cash-out entries (payments made directly from bank)
|
|
74
|
+
- Cash transfers between bank accounts
|
|
75
|
+
|
|
76
|
+
### Phase 4: Settlements
|
|
77
|
+
|
|
78
|
+
#### 4.1 Invoice Payments
|
|
79
|
+
For each payment in the source:
|
|
80
|
+
```
|
|
81
|
+
POST /api/v1/invoices/<invoiceResourceId>/payments
|
|
82
|
+
{
|
|
83
|
+
"payments": [{
|
|
84
|
+
"paymentAmount": <bank currency amount>,
|
|
85
|
+
"transactionAmount": <invoice currency amount>,
|
|
86
|
+
"accountResourceId": "<bank account ID>",
|
|
87
|
+
"paymentMethod": "BANK_TRANSFER",
|
|
88
|
+
"reference": "<payment ref>",
|
|
89
|
+
"valueDate": "<payment date>"
|
|
90
|
+
}]
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
#### 4.2 Bill Payments
|
|
95
|
+
Same pattern via `POST /api/v1/bills/<billResourceId>/payments`.
|
|
96
|
+
|
|
97
|
+
#### 4.3 Credit Note Applications
|
|
98
|
+
Apply credit notes to invoices/bills if the source shows them as applied.
|
|
99
|
+
|
|
100
|
+
### Phase 5: Post-Transaction Data
|
|
101
|
+
|
|
102
|
+
#### 5.1 Bank Records
|
|
103
|
+
Import bank statements for reconciliation:
|
|
104
|
+
- Via `POST /api/v1/bank-records/import` (multipart form)
|
|
105
|
+
- Or via individual `POST /api/v1/bank-records`
|
|
106
|
+
|
|
107
|
+
#### 5.2 Fixed Assets
|
|
108
|
+
Transfer existing assets with accumulated depreciation:
|
|
109
|
+
```
|
|
110
|
+
POST /api/v1/transfer-fixed-assets
|
|
111
|
+
```
|
|
112
|
+
This preserves the asset's cost basis and accumulated depreciation — do NOT use the "new asset" endpoint which would reset depreciation.
|
|
113
|
+
|
|
114
|
+
### Phase 6: Verify
|
|
115
|
+
Pull TB from Jaz at multiple dates (conversion start, mid-period, period end) and compare against source.
|
|
116
|
+
|
|
117
|
+
## Key Differences from Quick Conversion
|
|
118
|
+
|
|
119
|
+
| Aspect | Quick | Full |
|
|
120
|
+
|--------|-------|------|
|
|
121
|
+
| Transactions created | Conversion invoices/bills only | All original transactions |
|
|
122
|
+
| Date on documents | Original dates (FYE fallback) | Original dates |
|
|
123
|
+
| Exchange rates | Explicit FYE rate (zero UGL) | Original rates per transaction |
|
|
124
|
+
| Payments | None (just open balances) | All payments linked to documents |
|
|
125
|
+
| Journals | TTB only | TTB + all source journals |
|
|
126
|
+
| Verification points | TB at FYE only | TB at multiple dates |
|
|
127
|
+
| Complexity | Low-medium | High |
|
|
128
|
+
| Time to execute | Hours | Days |
|
|
129
|
+
|
|
130
|
+
## Edge Cases
|
|
131
|
+
|
|
132
|
+
### Payments That Cross Invoices
|
|
133
|
+
A single payment may cover multiple invoices. Create separate payment records for each invoice, splitting the amount.
|
|
134
|
+
|
|
135
|
+
### Void/Deleted Transactions
|
|
136
|
+
Skip voided transactions — they don't affect balances. If the source shows a void + reversal, only the reversal matters.
|
|
137
|
+
|
|
138
|
+
### Inter-Company Transactions
|
|
139
|
+
If the source has inter-company entries, these must map to the correct contact + accounts on each side.
|
|
140
|
+
|
|
141
|
+
### Unrealized FX Gains/Losses
|
|
142
|
+
Unlike Quick Conversion (where prior UGL is captured in the TTB and conversion invoices use explicit FYE rate for zero UGL), Full Conversion replicates **all transactions at their original rates**. Any unrealized FX revaluation journals from the source system should be replicated as manual journals in Jaz if they fall within the conversion period. This preserves the full historical UGL trail.
|
|
143
|
+
|
|
144
|
+
### Inventory
|
|
145
|
+
If the source has inventory items with WAC (Weighted Average Cost), the opening inventory value must match. Create inventory adjustments if needed.
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# Quick Conversion (Option 2) — Opening Balances at FYE
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Quick Conversion transfers **opening balances** into Jaz as at the Financial Year End (FYE) date. It creates open AR/AP as conversion transactions (invoices/bills) and transfers all other balances via a TTB journal entry.
|
|
6
|
+
|
|
7
|
+
**Result:** On Jaz, the Trial Balance at FYE matches the source system. Open receivables and payables exist as documents that can receive future payments.
|
|
8
|
+
|
|
9
|
+
## Required Input Files
|
|
10
|
+
|
|
11
|
+
1. **Chart of Accounts** — full CoA list from source system
|
|
12
|
+
2. **Trial Balance at FYE** — all account balances as at the FYE date
|
|
13
|
+
3. **AR Aging at FYE** — outstanding receivable invoices (per customer, per currency)
|
|
14
|
+
4. **AP Aging at FYE** — outstanding payable bills (per supplier, per currency)
|
|
15
|
+
5. **Contact list** — customer and supplier details
|
|
16
|
+
6. **Tax profiles** — tax codes used in the source system
|
|
17
|
+
7. **Exchange rates** — closing rates for all currencies as at FYE
|
|
18
|
+
|
|
19
|
+
## Execution Order
|
|
20
|
+
|
|
21
|
+
### Phase 1: Foundation
|
|
22
|
+
|
|
23
|
+
#### 1.1 Currencies
|
|
24
|
+
- Enable all required currencies on the org
|
|
25
|
+
- Set FYE closing exchange rates
|
|
26
|
+
- These must exist before creating CoA entries with foreign currency
|
|
27
|
+
|
|
28
|
+
#### 1.2 Chart of Accounts
|
|
29
|
+
Two modes:
|
|
30
|
+
|
|
31
|
+
**Fresh org (default system CoA):**
|
|
32
|
+
1. GET existing CoA from Jaz
|
|
33
|
+
2. Identify system-generated accounts (cannot delete)
|
|
34
|
+
3. Delete non-system accounts that aren't in the source CoA
|
|
35
|
+
4. Create/update accounts to match source CoA
|
|
36
|
+
5. Create two clearing accounts:
|
|
37
|
+
- **"AR Conversion Clearing"** — type: `Other Current Assets`, `classificationType: "Current Assets"`
|
|
38
|
+
- **"AP Conversion Clearing"** — type: `Other Current Liabilities`, `classificationType: "Current Liabilities"`
|
|
39
|
+
|
|
40
|
+
**Existing org:**
|
|
41
|
+
1. GET existing CoA from Jaz
|
|
42
|
+
2. Fuzzy match source accounts to existing (by code AND name)
|
|
43
|
+
3. Create any missing accounts
|
|
44
|
+
4. Create clearing accounts if they don't exist
|
|
45
|
+
|
|
46
|
+
#### 1.3 Tax Profiles
|
|
47
|
+
- GET existing tax profiles from Jaz (read-only — cannot create)
|
|
48
|
+
- Match source tax codes to Jaz tax profiles
|
|
49
|
+
- Common mappings: "GST 9%" → SR (Standard Rated), "No Tax" → ES (Exempt Supply)
|
|
50
|
+
|
|
51
|
+
#### 1.4 Contacts
|
|
52
|
+
- Create customer and supplier contacts from source data
|
|
53
|
+
- Ensure each contact has: name, type (customer/supplier/both), currency if FX
|
|
54
|
+
|
|
55
|
+
### Phase 2: Conversion Transactions
|
|
56
|
+
|
|
57
|
+
#### 2.1 Conversion Invoices (AR)
|
|
58
|
+
For each line in the AR Aging report:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
POST /api/v1/invoices
|
|
62
|
+
{
|
|
63
|
+
"contactResourceId": "<customer resource ID>",
|
|
64
|
+
"reference": "CONV-INV-<sequence>",
|
|
65
|
+
"valueDate": "<original invoice date or FYE date>",
|
|
66
|
+
"dueDate": "<original due date or FYE date>",
|
|
67
|
+
"currency": { // ONLY if FX
|
|
68
|
+
"sourceCurrency": "<invoice currency>",
|
|
69
|
+
"exchangeRate": <FYE closing rate> // explicit — ensures zero UGL
|
|
70
|
+
},
|
|
71
|
+
"lineItems": [{
|
|
72
|
+
"name": "Conversion balance — <original invoice ref>",
|
|
73
|
+
"quantity": 1,
|
|
74
|
+
"unitPrice": <outstanding amount in source currency>,
|
|
75
|
+
"accountResourceId": "<AR Conversion Clearing account ID>",
|
|
76
|
+
"taxProfileResourceId": "<exempt tax profile ID>"
|
|
77
|
+
}]
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Effect:** DR Accounts Receivable, CR AR Conversion Clearing
|
|
82
|
+
|
|
83
|
+
**Dates:** Use original dates from the aging report (preserves aging schedules). Fall back to FYE date if not available.
|
|
84
|
+
|
|
85
|
+
**FX invoices:** Use `currency: { sourceCurrency: "USD", exchangeRate: 1.35 }` (object form with explicit FYE rate). The `exchangeRate` field overrides Jaz's auto-fetch, ensuring zero UGL on day 1. See "FX Invoices/Bills — Dates vs. Rates" in Edge Cases below.
|
|
86
|
+
|
|
87
|
+
#### 2.2 Conversion Bills (AP)
|
|
88
|
+
For each line in the AP Aging report:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
POST /api/v1/bills
|
|
92
|
+
{
|
|
93
|
+
"contactResourceId": "<supplier resource ID>",
|
|
94
|
+
"reference": "CONV-BILL-<sequence>",
|
|
95
|
+
"valueDate": "<original bill date or FYE date>",
|
|
96
|
+
"dueDate": "<original due date or FYE date>",
|
|
97
|
+
"currency": { // ONLY if FX
|
|
98
|
+
"sourceCurrency": "<bill currency>",
|
|
99
|
+
"exchangeRate": <FYE closing rate>
|
|
100
|
+
},
|
|
101
|
+
"lineItems": [{
|
|
102
|
+
"name": "Conversion balance — <original bill ref>",
|
|
103
|
+
"quantity": 1,
|
|
104
|
+
"unitPrice": <outstanding amount in source currency>,
|
|
105
|
+
"accountResourceId": "<AP Conversion Clearing account ID>",
|
|
106
|
+
"taxProfileResourceId": "<exempt tax profile ID>"
|
|
107
|
+
}]
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Effect:** DR AP Conversion Clearing, CR Accounts Payable
|
|
112
|
+
|
|
113
|
+
### Phase 3: Transfer Trial Balance (TTB)
|
|
114
|
+
|
|
115
|
+
Create a single journal entry that transfers ALL balances from the source TB, with special handling for AR and AP:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
POST /api/v1/journals
|
|
119
|
+
{
|
|
120
|
+
"reference": "TTB-CONVERSION",
|
|
121
|
+
"valueDate": "<FYE date>",
|
|
122
|
+
"journalEntries": [
|
|
123
|
+
// For each account in the TB (except AR and AP):
|
|
124
|
+
{ "accountResourceId": "<account ID>", "amount": <balance>, "type": "DEBIT" },
|
|
125
|
+
{ "accountResourceId": "<account ID>", "amount": <balance>, "type": "CREDIT" },
|
|
126
|
+
|
|
127
|
+
// For AR: debit to AR Conversion Clearing (NOT to Accounts Receivable)
|
|
128
|
+
{ "accountResourceId": "<AR Clearing ID>", "amount": <AR balance>, "type": "DEBIT" },
|
|
129
|
+
|
|
130
|
+
// For AP: credit to AP Conversion Clearing (NOT to Accounts Payable)
|
|
131
|
+
{ "accountResourceId": "<AP Clearing ID>", "amount": <AP balance>, "type": "CREDIT" }
|
|
132
|
+
]
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**Why AR/AP are different:** The conversion invoices (Phase 2) already created the AR/AP balances. If the TTB also put balances into AR/AP, they'd be doubled. Instead, the TTB debits/credits the clearing accounts, which nets them to zero.
|
|
137
|
+
|
|
138
|
+
**The clearing accounts MUST net to zero after the TTB.** If they don't:
|
|
139
|
+
- AR Clearing balance ≠ 0 → the AR aging total doesn't match the TB's AR balance
|
|
140
|
+
- AP Clearing balance ≠ 0 → the AP aging total doesn't match the TB's AP balance
|
|
141
|
+
|
|
142
|
+
### Phase 4: Lock & Verify
|
|
143
|
+
|
|
144
|
+
#### 4.1 Lock Date
|
|
145
|
+
Set the accounting lock date to the FYE date to prevent accidental edits to the converted data.
|
|
146
|
+
|
|
147
|
+
#### 4.2 Verify
|
|
148
|
+
Pull the Trial Balance from Jaz at the FYE date. Compare against the source TB.
|
|
149
|
+
See `verification.md` for the full checklist format.
|
|
150
|
+
|
|
151
|
+
## Edge Cases
|
|
152
|
+
|
|
153
|
+
### FX Invoices/Bills — Dates vs. Rates (Critical)
|
|
154
|
+
|
|
155
|
+
Quick conversion transfers **open** (unpaid) FX invoices/bills from the prior platform. These must be handled carefully to avoid unrealized gain/loss (UGL) variances:
|
|
156
|
+
|
|
157
|
+
**The problem:** The prior platform already computed UGL up to the FYE date. That UGL is captured in the TTB journal (Phase 3) as part of the Unrealized FX Gain/Loss account balance. If we record conversion invoices at a different rate, Jaz would compute its own UGL — doubling up.
|
|
158
|
+
|
|
159
|
+
**The solution:** Record FX conversion invoices/bills with:
|
|
160
|
+
- **Original dates** (valueDate + dueDate from the aging report) — so aging schedules are correct
|
|
161
|
+
- **Explicit FYE exchange rate** — so Jaz sees zero UGL on day 1
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
POST /api/v1/invoices
|
|
165
|
+
{
|
|
166
|
+
"valueDate": "<original invoice date>", // preserves aging schedule
|
|
167
|
+
"dueDate": "<original due date>", // preserves aging buckets
|
|
168
|
+
"currency": {
|
|
169
|
+
"sourceCurrency": "USD",
|
|
170
|
+
"exchangeRate": 1.35 // explicit FYE rate — overrides auto-fetch
|
|
171
|
+
},
|
|
172
|
+
...
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Why this works:**
|
|
177
|
+
1. FYE rate = transferred transaction rate → zero UGL in Jaz on day 1
|
|
178
|
+
2. Prior platform's UGL is already in the TTB journal (Unrealized FX Gain/Loss account)
|
|
179
|
+
3. When a future payment is recorded against the conversion invoice, Jaz computes RGL against the FYE rate only — which is correct, because the balance was already marked-to-market at FYE
|
|
180
|
+
4. Original dates on the invoices preserve correct aging bucket positions (30/60/90/120+ days)
|
|
181
|
+
|
|
182
|
+
**When dates aren't available:** Some aging reports only show contact name + amount (no individual dates). In this case, fall back to FYE date for both valueDate and dueDate. Aging schedules will be flat ("current") but FX handling remains correct.
|
|
183
|
+
|
|
184
|
+
**Rate source:** FYE rates come from the exchange rates file (e.g., MAS closing rates). They're set on the org in Phase 1 via `POST /organization-currencies/:code/rates` and also passed explicitly on each FX transaction to guarantee the rate is used regardless of valueDate.
|
|
185
|
+
|
|
186
|
+
### Partially Paid Invoices in AR Aging
|
|
187
|
+
The AR Aging shows only the **outstanding** balance. Create the conversion invoice for the outstanding amount only — the historical payments are not relevant for Quick Conversion.
|
|
188
|
+
|
|
189
|
+
### Negative Balances in AR/AP Aging
|
|
190
|
+
A negative AR balance = customer overpayment (credit balance). Create as a customer credit note, not a negative invoice.
|
|
191
|
+
A negative AP balance = supplier overpayment. Create as a supplier credit note.
|
|
192
|
+
|
|
193
|
+
### Multiple Invoices Per Customer
|
|
194
|
+
The AR Aging may show multiple outstanding invoices per customer. Create separate conversion invoices for each — they may need to be paid separately later.
|
|
195
|
+
|
|
196
|
+
### Rounding
|
|
197
|
+
Always use the exact amounts from the source. If the source TB has $1,234.57, the TTB journal must use $1,234.57. Rounding errors of even $0.01 will cause TB mismatch.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Verification — TB Comparison and Checklist Generation
|
|
2
|
+
|
|
3
|
+
## Post-Execution Verification Flow
|
|
4
|
+
|
|
5
|
+
After all conversion transactions are created, verify accuracy by comparing the Trial Balance on Jaz against the source TB.
|
|
6
|
+
|
|
7
|
+
### Step 1: Pull Jaz Trial Balance
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
GET /api/v1/reports/trial-balance?asOnDate=<FYE date>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This returns all account balances as at the specified date.
|
|
14
|
+
|
|
15
|
+
### Step 2: Parse Source Trial Balance
|
|
16
|
+
|
|
17
|
+
From the parsed input files, extract the source TB with:
|
|
18
|
+
- Account code
|
|
19
|
+
- Account name
|
|
20
|
+
- Debit balance (or positive amount)
|
|
21
|
+
- Credit balance (or negative amount)
|
|
22
|
+
|
|
23
|
+
### Step 3: Compare
|
|
24
|
+
|
|
25
|
+
For each account, compare:
|
|
26
|
+
```
|
|
27
|
+
Difference = Jaz balance - Source balance
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Tolerance:** $0.00 — there should be NO difference. Even $0.01 must be investigated and resolved.
|
|
31
|
+
|
|
32
|
+
### Step 4: Categorize Differences
|
|
33
|
+
|
|
34
|
+
| Category | Likely Cause | Fix |
|
|
35
|
+
|----------|-------------|-----|
|
|
36
|
+
| **Missing account** | Account exists in source but not in Jaz | Create the account + journal entry for the balance |
|
|
37
|
+
| **Extra account** | Account in Jaz but not in source | Check if it's a system account (ignore) or a mapping error |
|
|
38
|
+
| **Amount mismatch ≤ $1** | FX rounding | Small adjustment journal with note |
|
|
39
|
+
| **Amount mismatch > $1** | Missing or extra transaction | Investigate GL detail, find the discrepancy |
|
|
40
|
+
| **AR/AP mismatch** | Clearing account didn't net to zero | Check conversion invoices/bills vs TTB |
|
|
41
|
+
| **Sign reversal** | Debit/credit direction wrong | Reverse the journal entry or void and recreate |
|
|
42
|
+
|
|
43
|
+
### Step 5: Fix and Re-Verify
|
|
44
|
+
|
|
45
|
+
After each fix:
|
|
46
|
+
1. Pull Jaz TB again
|
|
47
|
+
2. Compare again
|
|
48
|
+
3. Repeat until all differences are resolved
|
|
49
|
+
|
|
50
|
+
## Verification Checklist Format
|
|
51
|
+
|
|
52
|
+
Generate a checklist in this format for customer sign-off:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
CONVERSION CHECKLIST
|
|
56
|
+
====================
|
|
57
|
+
Client: <Company Name>
|
|
58
|
+
Source: <Source System (e.g., Xero, QuickBooks)>
|
|
59
|
+
Type: <Quick Conversion / Full Conversion>
|
|
60
|
+
FYE Date: <e.g., 2023-12-31>
|
|
61
|
+
Converted: <e.g., 2026-02-14>
|
|
62
|
+
Converted By: <name>
|
|
63
|
+
|
|
64
|
+
TRIAL BALANCE COMPARISON (as at <FYE date>)
|
|
65
|
+
--------------------------------------------
|
|
66
|
+
Source Jaz Diff
|
|
67
|
+
Total Assets $XXX,XXX.XX $XXX,XXX.XX $0.00
|
|
68
|
+
Total Liabilities $XXX,XXX.XX $XXX,XXX.XX $0.00
|
|
69
|
+
Total Equity $XXX,XXX.XX $XXX,XXX.XX $0.00
|
|
70
|
+
Total Revenue $XXX,XXX.XX $XXX,XXX.XX $0.00
|
|
71
|
+
Total Expenses $XXX,XXX.XX $XXX,XXX.XX $0.00
|
|
72
|
+
--------------------------------------------
|
|
73
|
+
Net Balance $0.00 $0.00 $0.00
|
|
74
|
+
|
|
75
|
+
AR / AP VERIFICATION
|
|
76
|
+
--------------------------------------------
|
|
77
|
+
Open Receivables $XXX,XXX.XX $XXX,XXX.XX $0.00
|
|
78
|
+
Open Payables $XXX,XXX.XX $XXX,XXX.XX $0.00
|
|
79
|
+
AR Clearing Balance $0.00
|
|
80
|
+
AP Clearing Balance $0.00
|
|
81
|
+
|
|
82
|
+
ENTITIES CREATED
|
|
83
|
+
--------------------------------------------
|
|
84
|
+
Chart of Accounts XX
|
|
85
|
+
Contacts XX
|
|
86
|
+
Tax Profiles (mapped) XX
|
|
87
|
+
Currencies Enabled XX
|
|
88
|
+
Conversion Invoices (AR) XX
|
|
89
|
+
Conversion Bills (AP) XX
|
|
90
|
+
TTB Journal 1
|
|
91
|
+
Lock Date Set <FYE date>
|
|
92
|
+
|
|
93
|
+
FX RATES APPLIED
|
|
94
|
+
--------------------------------------------
|
|
95
|
+
USD 1.3500
|
|
96
|
+
EUR 1.4500
|
|
97
|
+
JPY 0.0092
|
|
98
|
+
|
|
99
|
+
NOTES
|
|
100
|
+
--------------------------------------------
|
|
101
|
+
- <Any adjustments made, rounding notes, special handling>
|
|
102
|
+
- <Any known limitations or follow-up items>
|
|
103
|
+
|
|
104
|
+
Verified by: _______________ Date: _______________
|
|
105
|
+
Approved by: _______________ Date: _______________
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Detailed Account-Level Comparison
|
|
109
|
+
|
|
110
|
+
For complex conversions, also generate a per-account comparison:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
ACCOUNT-LEVEL COMPARISON (as at <FYE date>)
|
|
114
|
+
--------------------------------------------
|
|
115
|
+
Code Account Name Source Jaz Diff
|
|
116
|
+
1000 Cash at Bank (SGD) $50,000 $50,000 $0
|
|
117
|
+
1001 USD Bank Account $10,000 $10,000 $0
|
|
118
|
+
1100 Accounts Receivable $25,000 $25,000 $0
|
|
119
|
+
1200 Prepaid Expenses $3,000 $3,000 $0
|
|
120
|
+
1299 AR Conversion Clearing - $0 $0
|
|
121
|
+
...
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
This is the definitive proof that the conversion is accurate. Every account must match.
|
|
125
|
+
|
|
126
|
+
## Quick Conversion Specific Checks
|
|
127
|
+
|
|
128
|
+
1. **Clearing accounts net to zero** — both AR and AP clearing
|
|
129
|
+
2. **Open AR on Jaz = AR Aging from source** — check total and per-customer
|
|
130
|
+
3. **Open AP on Jaz = AP Aging from source** — check total and per-supplier
|
|
131
|
+
4. **TB on Jaz = TB from source** — every account
|
|
132
|
+
5. **Lock date is set** — prevents accidental edits to historical data
|
|
133
|
+
6. **FX rates match** — Jaz closing rates = source closing rates at FYE
|
|
134
|
+
|
|
135
|
+
## Full Conversion Specific Checks
|
|
136
|
+
|
|
137
|
+
All Quick checks plus:
|
|
138
|
+
1. **TB matches at multiple dates** — not just FYE, also mid-period spot checks
|
|
139
|
+
2. **Invoice count matches** — total invoices created = total in source
|
|
140
|
+
3. **Payment count matches** — total payments applied = total in source
|
|
141
|
+
4. **GL detail spot check** — pick 5-10 random transactions, verify amounts and accounts
|
|
142
|
+
5. **Bank reconciliation** — bank records imported match bank statement
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import prompts from 'prompts';
|
|
4
|
+
import { SKILL_DESCRIPTIONS } from '../types/index.js';
|
|
5
|
+
import { installSkills } from '../utils/template.js';
|
|
6
|
+
import { logger } from '../utils/logger.js';
|
|
7
|
+
export async function initCommand(options) {
|
|
8
|
+
logger.title('Jaz AI — Skill Installer');
|
|
9
|
+
let skillType = options.skill ?? 'all';
|
|
10
|
+
// Prompt for skill selection if not specified
|
|
11
|
+
if (!options.skill) {
|
|
12
|
+
const response = await prompts({
|
|
13
|
+
type: 'select',
|
|
14
|
+
name: 'skill',
|
|
15
|
+
message: 'Which skills do you want to install?',
|
|
16
|
+
choices: [
|
|
17
|
+
{
|
|
18
|
+
title: `Both (Recommended)`,
|
|
19
|
+
description: 'API reference + data conversion',
|
|
20
|
+
value: 'all',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
title: 'API only',
|
|
24
|
+
description: SKILL_DESCRIPTIONS.api,
|
|
25
|
+
value: 'api',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
title: 'Conversion only',
|
|
29
|
+
description: SKILL_DESCRIPTIONS.conversion,
|
|
30
|
+
value: 'conversion',
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
initial: 0,
|
|
34
|
+
});
|
|
35
|
+
if (!response.skill) {
|
|
36
|
+
logger.warn('Installation cancelled');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
skillType = response.skill;
|
|
40
|
+
}
|
|
41
|
+
const skillLabel = skillType === 'all'
|
|
42
|
+
? 'api + conversion'
|
|
43
|
+
: skillType;
|
|
44
|
+
logger.info(`Installing: ${chalk.cyan(skillLabel)}`);
|
|
45
|
+
const spinner = ora('Installing skill files...').start();
|
|
46
|
+
const cwd = process.cwd();
|
|
47
|
+
try {
|
|
48
|
+
spinner.text = 'Copying skill files...';
|
|
49
|
+
const installedPaths = await installSkills(cwd, skillType, options.force ?? false);
|
|
50
|
+
spinner.succeed('Skills installed!');
|
|
51
|
+
console.log();
|
|
52
|
+
logger.info('Installed:');
|
|
53
|
+
installedPaths.forEach((folder) => {
|
|
54
|
+
console.log(` ${chalk.green('+')} ${folder}/`);
|
|
55
|
+
});
|
|
56
|
+
console.log();
|
|
57
|
+
logger.success('Jaz AI skills installed successfully!');
|
|
58
|
+
console.log();
|
|
59
|
+
console.log(chalk.bold('Next steps:'));
|
|
60
|
+
console.log(chalk.dim(' 1. Restart Claude Code'));
|
|
61
|
+
console.log(chalk.dim(' 2. Try: "Create an invoice with line items and tax"'));
|
|
62
|
+
if (skillType === 'all' || skillType === 'conversion') {
|
|
63
|
+
console.log(chalk.dim(' 3. Try: "Convert this Xero trial balance to Jaz"'));
|
|
64
|
+
}
|
|
65
|
+
console.log();
|
|
66
|
+
console.log(chalk.dim(` Docs: ${chalk.underline('https://help.jaz.ai')}`));
|
|
67
|
+
console.log();
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
spinner.fail('Installation failed');
|
|
71
|
+
if (error instanceof Error) {
|
|
72
|
+
logger.error(error.message);
|
|
73
|
+
}
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { installSkills } from '../utils/template.js';
|
|
4
|
+
import { logger } from '../utils/logger.js';
|
|
5
|
+
export async function updateCommand(options) {
|
|
6
|
+
logger.title('Jaz AI — Update Skills');
|
|
7
|
+
const skillType = options.skill ?? 'all';
|
|
8
|
+
const spinner = ora('Updating skill files...').start();
|
|
9
|
+
try {
|
|
10
|
+
const installedPaths = await installSkills(process.cwd(), skillType, true);
|
|
11
|
+
spinner.succeed('Skills updated!');
|
|
12
|
+
console.log();
|
|
13
|
+
logger.info('Updated:');
|
|
14
|
+
installedPaths.forEach((folder) => {
|
|
15
|
+
console.log(` ${chalk.green('+')} ${folder}/`);
|
|
16
|
+
});
|
|
17
|
+
console.log();
|
|
18
|
+
logger.success('Restart Claude Code to pick up changes.');
|
|
19
|
+
console.log();
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
spinner.fail('Update failed');
|
|
23
|
+
if (error instanceof Error) {
|
|
24
|
+
logger.error(error.message);
|
|
25
|
+
}
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
import { fetchReleases, GitHubRateLimitError } from '../utils/github.js';
|
|
5
|
+
export async function versionsCommand() {
|
|
6
|
+
logger.title('Jaz AI — Available Versions');
|
|
7
|
+
const spinner = ora('Fetching versions from GitHub...').start();
|
|
8
|
+
try {
|
|
9
|
+
const releases = await fetchReleases();
|
|
10
|
+
if (releases.length === 0) {
|
|
11
|
+
spinner.warn('No releases found');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
spinner.succeed(`Found ${releases.length} version(s)`);
|
|
15
|
+
console.log();
|
|
16
|
+
releases.forEach((release, i) => {
|
|
17
|
+
const tag = release.tag_name;
|
|
18
|
+
const date = new Date(release.published_at).toLocaleDateString();
|
|
19
|
+
const label = i === 0 ? chalk.green(' (latest)') : '';
|
|
20
|
+
console.log(` ${chalk.cyan(tag)}${label} ${chalk.dim(date)}`);
|
|
21
|
+
});
|
|
22
|
+
console.log();
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (error instanceof GitHubRateLimitError) {
|
|
26
|
+
spinner.fail('GitHub rate limit reached. Try again later.');
|
|
27
|
+
}
|
|
28
|
+
else if (error instanceof Error) {
|
|
29
|
+
spinner.fail(`Failed to fetch versions: ${error.message}`);
|
|
30
|
+
}
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { readFileSync } from 'fs';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { dirname, join } from 'path';
|
|
6
|
+
import { initCommand } from './commands/init.js';
|
|
7
|
+
import { versionsCommand } from './commands/versions.js';
|
|
8
|
+
import { updateCommand } from './commands/update.js';
|
|
9
|
+
import { SKILL_TYPES } from './types/index.js';
|
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
+
const __dirname = dirname(__filename);
|
|
12
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
|
|
13
|
+
const program = new Command();
|
|
14
|
+
program
|
|
15
|
+
.name('jaz')
|
|
16
|
+
.description('CLI to install Jaz AI skills for Claude Code')
|
|
17
|
+
.version(pkg.version);
|
|
18
|
+
program
|
|
19
|
+
.command('init')
|
|
20
|
+
.description('Install Jaz AI skills into the current project')
|
|
21
|
+
.option('-s, --skill <type>', `Skill to install (${SKILL_TYPES.join(', ')})`)
|
|
22
|
+
.option('-f, --force', 'Overwrite existing files')
|
|
23
|
+
.action(async (options) => {
|
|
24
|
+
if (options.skill && !SKILL_TYPES.includes(options.skill)) {
|
|
25
|
+
console.error(`Invalid skill type: ${options.skill}`);
|
|
26
|
+
console.error(`Valid types: ${SKILL_TYPES.join(', ')}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
await initCommand({
|
|
30
|
+
skill: options.skill,
|
|
31
|
+
force: options.force,
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
program
|
|
35
|
+
.command('versions')
|
|
36
|
+
.description('List available versions')
|
|
37
|
+
.action(versionsCommand);
|
|
38
|
+
program
|
|
39
|
+
.command('update')
|
|
40
|
+
.description('Update Jaz AI skills to latest version')
|
|
41
|
+
.option('-s, --skill <type>', `Skill to update (${SKILL_TYPES.join(', ')})`)
|
|
42
|
+
.action(async (options) => {
|
|
43
|
+
if (options.skill && !SKILL_TYPES.includes(options.skill)) {
|
|
44
|
+
console.error(`Invalid skill type: ${options.skill}`);
|
|
45
|
+
console.error(`Valid types: ${SKILL_TYPES.join(', ')}`);
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
await updateCommand({
|
|
49
|
+
skill: options.skill,
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
program.parse();
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export const SKILL_TYPES = ['api', 'conversion', 'all'];
|
|
2
|
+
export const SKILL_DESCRIPTIONS = {
|
|
3
|
+
api: 'Jaz/Juan REST API reference — 55 rules, endpoint catalog, error catalog, field mapping',
|
|
4
|
+
conversion: 'Data conversion pipeline — Xero, QuickBooks, Sage, Excel migration to Jaz',
|
|
5
|
+
};
|