jaz-cli 2.3.0 → 2.6.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 +35 -34
- package/assets/skills/api/references/errors.md +15 -7
- package/assets/skills/api/references/feature-glossary.md +2 -0
- package/assets/skills/api/references/field-map.md +3 -3
- package/assets/skills/conversion/SKILL.md +1 -1
- package/assets/skills/transaction-recipes/SKILL.md +158 -14
- package/assets/skills/transaction-recipes/references/asset-disposal.md +174 -0
- package/assets/skills/transaction-recipes/references/bad-debt-provision.md +145 -0
- package/assets/skills/transaction-recipes/references/building-blocks.md +25 -2
- package/assets/skills/transaction-recipes/references/capital-wip.md +167 -0
- package/assets/skills/transaction-recipes/references/dividend.md +111 -0
- package/assets/skills/transaction-recipes/references/employee-accruals.md +154 -0
- package/assets/skills/transaction-recipes/references/fixed-deposit.md +164 -0
- package/assets/skills/transaction-recipes/references/fx-revaluation.md +135 -0
- package/assets/skills/transaction-recipes/references/hire-purchase.md +190 -0
- package/assets/skills/transaction-recipes/references/intercompany.md +150 -0
- package/assets/skills/transaction-recipes/references/provisions.md +142 -0
- package/dist/calc/amortization.js +122 -0
- package/dist/calc/asset-disposal.js +151 -0
- package/dist/calc/blueprint.js +46 -0
- package/dist/calc/depreciation.js +200 -0
- package/dist/calc/ecl.js +101 -0
- package/dist/calc/fixed-deposit.js +169 -0
- package/dist/calc/format.js +494 -0
- package/dist/calc/fx-reval.js +93 -0
- package/dist/calc/lease.js +146 -0
- package/dist/calc/loan.js +107 -0
- package/dist/calc/provision.js +128 -0
- package/dist/calc/types.js +21 -0
- package/dist/calc/validate.js +48 -0
- package/dist/commands/calc.js +252 -0
- package/dist/index.js +2 -0
- package/package.json +3 -2
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { calculateLoan } from '../calc/loan.js';
|
|
3
|
+
import { calculateLease } from '../calc/lease.js';
|
|
4
|
+
import { calculateDepreciation } from '../calc/depreciation.js';
|
|
5
|
+
import { calculatePrepaidExpense, calculateDeferredRevenue } from '../calc/amortization.js';
|
|
6
|
+
import { calculateFxReval } from '../calc/fx-reval.js';
|
|
7
|
+
import { calculateEcl } from '../calc/ecl.js';
|
|
8
|
+
import { calculateProvision } from '../calc/provision.js';
|
|
9
|
+
import { calculateFixedDeposit } from '../calc/fixed-deposit.js';
|
|
10
|
+
import { calculateAssetDisposal } from '../calc/asset-disposal.js';
|
|
11
|
+
import { printResult, printJson } from '../calc/format.js';
|
|
12
|
+
import { CalcValidationError } from '../calc/validate.js';
|
|
13
|
+
/** Wrap calc action with validation error handling. */
|
|
14
|
+
function calcAction(fn) {
|
|
15
|
+
return (opts) => {
|
|
16
|
+
try {
|
|
17
|
+
fn(opts);
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
if (err instanceof CalcValidationError) {
|
|
21
|
+
console.error(chalk.red(`Error: ${err.message}`));
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
throw err;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function registerCalcCommand(program) {
|
|
29
|
+
const calc = program
|
|
30
|
+
.command('calc')
|
|
31
|
+
.description('Financial calculators — loan, lease, depreciation, prepaid-expense, deferred-revenue, fx-reval, ecl, provision, fixed-deposit, asset-disposal');
|
|
32
|
+
// ── jaz calc loan ──────────────────────────────────────────────
|
|
33
|
+
calc
|
|
34
|
+
.command('loan')
|
|
35
|
+
.description('Loan amortization schedule')
|
|
36
|
+
.requiredOption('--principal <amount>', 'Loan principal', parseFloat)
|
|
37
|
+
.requiredOption('--rate <percent>', 'Annual interest rate (%)', parseFloat)
|
|
38
|
+
.requiredOption('--term <months>', 'Loan term in months', parseInt)
|
|
39
|
+
.option('--start-date <date>', 'Start date (YYYY-MM-DD)')
|
|
40
|
+
.option('--currency <code>', 'Currency code (e.g. SGD, USD)')
|
|
41
|
+
.option('--json', 'Output as JSON')
|
|
42
|
+
.action(calcAction((opts) => {
|
|
43
|
+
const result = calculateLoan({
|
|
44
|
+
principal: opts.principal,
|
|
45
|
+
annualRate: opts.rate,
|
|
46
|
+
termMonths: opts.term,
|
|
47
|
+
startDate: opts.startDate,
|
|
48
|
+
currency: opts.currency,
|
|
49
|
+
});
|
|
50
|
+
opts.json ? printJson(result) : printResult(result);
|
|
51
|
+
}));
|
|
52
|
+
// ── jaz calc lease ─────────────────────────────────────────────
|
|
53
|
+
calc
|
|
54
|
+
.command('lease')
|
|
55
|
+
.description('IFRS 16 lease schedule (liability unwinding + ROU depreciation). Add --useful-life for hire purchase.')
|
|
56
|
+
.requiredOption('--payment <amount>', 'Monthly lease payment', parseFloat)
|
|
57
|
+
.requiredOption('--term <months>', 'Lease term in months', parseInt)
|
|
58
|
+
.requiredOption('--rate <percent>', 'Incremental borrowing rate (%)', parseFloat)
|
|
59
|
+
.option('--useful-life <months>', 'Asset useful life in months (hire purchase: depreciate over useful life, not term)', parseInt)
|
|
60
|
+
.option('--start-date <date>', 'Lease commencement date (YYYY-MM-DD)')
|
|
61
|
+
.option('--currency <code>', 'Currency code (e.g. SGD, USD)')
|
|
62
|
+
.option('--json', 'Output as JSON')
|
|
63
|
+
.action(calcAction((opts) => {
|
|
64
|
+
const result = calculateLease({
|
|
65
|
+
monthlyPayment: opts.payment,
|
|
66
|
+
termMonths: opts.term,
|
|
67
|
+
annualRate: opts.rate,
|
|
68
|
+
usefulLifeMonths: opts.usefulLife,
|
|
69
|
+
startDate: opts.startDate,
|
|
70
|
+
currency: opts.currency,
|
|
71
|
+
});
|
|
72
|
+
opts.json ? printJson(result) : printResult(result);
|
|
73
|
+
}));
|
|
74
|
+
// ── jaz calc depreciation ──────────────────────────────────────
|
|
75
|
+
calc
|
|
76
|
+
.command('depreciation')
|
|
77
|
+
.description('Depreciation schedule (straight-line, double declining, or 150% declining)')
|
|
78
|
+
.requiredOption('--cost <amount>', 'Asset cost', parseFloat)
|
|
79
|
+
.requiredOption('--salvage <amount>', 'Salvage value', parseFloat)
|
|
80
|
+
.requiredOption('--life <years>', 'Useful life in years', parseInt)
|
|
81
|
+
.option('--method <method>', 'Method: sl, ddb (default), or 150db', 'ddb')
|
|
82
|
+
.option('--frequency <freq>', 'Frequency: annual (default) or monthly', 'annual')
|
|
83
|
+
.option('--currency <code>', 'Currency code (e.g. SGD, USD)')
|
|
84
|
+
.option('--json', 'Output as JSON')
|
|
85
|
+
.action(calcAction((opts) => {
|
|
86
|
+
const result = calculateDepreciation({
|
|
87
|
+
cost: opts.cost,
|
|
88
|
+
salvageValue: opts.salvage,
|
|
89
|
+
usefulLifeYears: opts.life,
|
|
90
|
+
method: opts.method,
|
|
91
|
+
frequency: opts.frequency,
|
|
92
|
+
currency: opts.currency,
|
|
93
|
+
});
|
|
94
|
+
opts.json ? printJson(result) : printResult(result);
|
|
95
|
+
}));
|
|
96
|
+
// ── jaz calc prepaid-expense ──────────────────────────────────
|
|
97
|
+
calc
|
|
98
|
+
.command('prepaid-expense')
|
|
99
|
+
.description('Prepaid expense recognition schedule (e.g. insurance, rent, subscriptions)')
|
|
100
|
+
.requiredOption('--amount <amount>', 'Total prepaid amount', parseFloat)
|
|
101
|
+
.requiredOption('--periods <count>', 'Number of recognition periods', parseInt)
|
|
102
|
+
.option('--frequency <freq>', 'Frequency: monthly (default) or quarterly', 'monthly')
|
|
103
|
+
.option('--start-date <date>', 'Start date (YYYY-MM-DD)')
|
|
104
|
+
.option('--currency <code>', 'Currency code (e.g. SGD, USD)')
|
|
105
|
+
.option('--json', 'Output as JSON')
|
|
106
|
+
.action(calcAction((opts) => {
|
|
107
|
+
const result = calculatePrepaidExpense({
|
|
108
|
+
amount: opts.amount,
|
|
109
|
+
periods: opts.periods,
|
|
110
|
+
frequency: opts.frequency,
|
|
111
|
+
startDate: opts.startDate,
|
|
112
|
+
currency: opts.currency,
|
|
113
|
+
});
|
|
114
|
+
opts.json ? printJson(result) : printResult(result);
|
|
115
|
+
}));
|
|
116
|
+
// ── jaz calc deferred-revenue ───────────────────────────────────
|
|
117
|
+
calc
|
|
118
|
+
.command('deferred-revenue')
|
|
119
|
+
.description('Deferred revenue recognition schedule (e.g. annual contracts, retainers)')
|
|
120
|
+
.requiredOption('--amount <amount>', 'Total deferred amount', parseFloat)
|
|
121
|
+
.requiredOption('--periods <count>', 'Number of recognition periods', parseInt)
|
|
122
|
+
.option('--frequency <freq>', 'Frequency: monthly (default) or quarterly', 'monthly')
|
|
123
|
+
.option('--start-date <date>', 'Start date (YYYY-MM-DD)')
|
|
124
|
+
.option('--currency <code>', 'Currency code (e.g. SGD, USD)')
|
|
125
|
+
.option('--json', 'Output as JSON')
|
|
126
|
+
.action(calcAction((opts) => {
|
|
127
|
+
const result = calculateDeferredRevenue({
|
|
128
|
+
amount: opts.amount,
|
|
129
|
+
periods: opts.periods,
|
|
130
|
+
frequency: opts.frequency,
|
|
131
|
+
startDate: opts.startDate,
|
|
132
|
+
currency: opts.currency,
|
|
133
|
+
});
|
|
134
|
+
opts.json ? printJson(result) : printResult(result);
|
|
135
|
+
}));
|
|
136
|
+
// ── jaz calc fx-reval ───────────────────────────────────────────
|
|
137
|
+
calc
|
|
138
|
+
.command('fx-reval')
|
|
139
|
+
.description('FX revaluation — unrealized gain/loss on non-AR/AP foreign currency balances (IAS 21)')
|
|
140
|
+
.requiredOption('--amount <amount>', 'Foreign currency amount outstanding', parseFloat)
|
|
141
|
+
.requiredOption('--book-rate <rate>', 'Original booking exchange rate', parseFloat)
|
|
142
|
+
.requiredOption('--closing-rate <rate>', 'Period-end closing exchange rate', parseFloat)
|
|
143
|
+
.option('--currency <code>', 'Foreign currency code (e.g. USD)', 'USD')
|
|
144
|
+
.option('--base-currency <code>', 'Base (functional) currency code (e.g. SGD)', 'SGD')
|
|
145
|
+
.option('--json', 'Output as JSON')
|
|
146
|
+
.action(calcAction((opts) => {
|
|
147
|
+
const result = calculateFxReval({
|
|
148
|
+
amount: opts.amount,
|
|
149
|
+
bookRate: opts.bookRate,
|
|
150
|
+
closingRate: opts.closingRate,
|
|
151
|
+
currency: opts.currency,
|
|
152
|
+
baseCurrency: opts.baseCurrency,
|
|
153
|
+
});
|
|
154
|
+
opts.json ? printJson(result) : printResult(result);
|
|
155
|
+
}));
|
|
156
|
+
// ── jaz calc ecl ────────────────────────────────────────────────
|
|
157
|
+
calc
|
|
158
|
+
.command('ecl')
|
|
159
|
+
.description('Expected credit loss provision matrix (IFRS 9 simplified approach)')
|
|
160
|
+
.requiredOption('--current <amount>', 'Current (not overdue) receivables balance', parseFloat)
|
|
161
|
+
.requiredOption('--30d <amount>', '1-30 days overdue balance', parseFloat)
|
|
162
|
+
.requiredOption('--60d <amount>', '31-60 days overdue balance', parseFloat)
|
|
163
|
+
.requiredOption('--90d <amount>', '61-90 days overdue balance', parseFloat)
|
|
164
|
+
.requiredOption('--120d <amount>', '91+ days overdue balance', parseFloat)
|
|
165
|
+
.requiredOption('--rates <rates>', 'Loss rates per bucket (comma-separated %)', (v) => v.split(',').map(Number))
|
|
166
|
+
.option('--existing-provision <amount>', 'Existing provision balance', parseFloat, 0)
|
|
167
|
+
.option('--currency <code>', 'Currency code (e.g. SGD, USD)')
|
|
168
|
+
.option('--json', 'Output as JSON')
|
|
169
|
+
.action(calcAction((opts) => {
|
|
170
|
+
const rates = opts.rates;
|
|
171
|
+
const result = calculateEcl({
|
|
172
|
+
buckets: [
|
|
173
|
+
{ name: 'Current', balance: opts.current, rate: rates[0] },
|
|
174
|
+
{ name: '1-30 days', balance: opts['30d'], rate: rates[1] },
|
|
175
|
+
{ name: '31-60 days', balance: opts['60d'], rate: rates[2] },
|
|
176
|
+
{ name: '61-90 days', balance: opts['90d'], rate: rates[3] },
|
|
177
|
+
{ name: '91+ days', balance: opts['120d'], rate: rates[4] },
|
|
178
|
+
],
|
|
179
|
+
existingProvision: opts.existingProvision,
|
|
180
|
+
currency: opts.currency,
|
|
181
|
+
});
|
|
182
|
+
opts.json ? printJson(result) : printResult(result);
|
|
183
|
+
}));
|
|
184
|
+
// ── jaz calc provision ──────────────────────────────────────────
|
|
185
|
+
calc
|
|
186
|
+
.command('provision')
|
|
187
|
+
.description('IAS 37 provision PV measurement + discount unwinding schedule')
|
|
188
|
+
.requiredOption('--amount <amount>', 'Estimated future cash outflow', parseFloat)
|
|
189
|
+
.requiredOption('--rate <percent>', 'Discount rate (%)', parseFloat)
|
|
190
|
+
.requiredOption('--term <months>', 'Months until expected settlement', parseInt)
|
|
191
|
+
.option('--start-date <date>', 'Recognition date (YYYY-MM-DD)')
|
|
192
|
+
.option('--currency <code>', 'Currency code (e.g. SGD, USD)')
|
|
193
|
+
.option('--json', 'Output as JSON')
|
|
194
|
+
.action(calcAction((opts) => {
|
|
195
|
+
const result = calculateProvision({
|
|
196
|
+
amount: opts.amount,
|
|
197
|
+
annualRate: opts.rate,
|
|
198
|
+
termMonths: opts.term,
|
|
199
|
+
startDate: opts.startDate,
|
|
200
|
+
currency: opts.currency,
|
|
201
|
+
});
|
|
202
|
+
opts.json ? printJson(result) : printResult(result);
|
|
203
|
+
}));
|
|
204
|
+
// ── jaz calc fixed-deposit ────────────────────────────────────
|
|
205
|
+
calc
|
|
206
|
+
.command('fixed-deposit')
|
|
207
|
+
.description('Fixed deposit interest accrual schedule (IFRS 9 amortized cost)')
|
|
208
|
+
.requiredOption('--principal <amount>', 'Deposit principal', parseFloat)
|
|
209
|
+
.requiredOption('--rate <percent>', 'Annual interest rate (%)', parseFloat)
|
|
210
|
+
.requiredOption('--term <months>', 'Term in months', parseInt)
|
|
211
|
+
.option('--compound <method>', 'Compounding: none (default), monthly, quarterly, annually', 'none')
|
|
212
|
+
.option('--start-date <date>', 'Placement date (YYYY-MM-DD)')
|
|
213
|
+
.option('--currency <code>', 'Currency code (e.g. SGD, USD)')
|
|
214
|
+
.option('--json', 'Output as JSON')
|
|
215
|
+
.action(calcAction((opts) => {
|
|
216
|
+
const result = calculateFixedDeposit({
|
|
217
|
+
principal: opts.principal,
|
|
218
|
+
annualRate: opts.rate,
|
|
219
|
+
termMonths: opts.term,
|
|
220
|
+
compounding: opts.compound,
|
|
221
|
+
startDate: opts.startDate,
|
|
222
|
+
currency: opts.currency,
|
|
223
|
+
});
|
|
224
|
+
opts.json ? printJson(result) : printResult(result);
|
|
225
|
+
}));
|
|
226
|
+
// ── jaz calc asset-disposal ───────────────────────────────────
|
|
227
|
+
calc
|
|
228
|
+
.command('asset-disposal')
|
|
229
|
+
.description('Fixed asset disposal — gain/loss calculation (IAS 16)')
|
|
230
|
+
.requiredOption('--cost <amount>', 'Original asset cost', parseFloat)
|
|
231
|
+
.requiredOption('--salvage <amount>', 'Salvage value', parseFloat)
|
|
232
|
+
.requiredOption('--life <years>', 'Useful life in years', parseInt)
|
|
233
|
+
.requiredOption('--acquired <date>', 'Acquisition date (YYYY-MM-DD)')
|
|
234
|
+
.requiredOption('--disposed <date>', 'Disposal date (YYYY-MM-DD)')
|
|
235
|
+
.requiredOption('--proceeds <amount>', 'Disposal proceeds (0 for scrap)', parseFloat)
|
|
236
|
+
.option('--method <method>', 'Depreciation method: sl (default), ddb, 150db', 'sl')
|
|
237
|
+
.option('--currency <code>', 'Currency code (e.g. SGD, USD)')
|
|
238
|
+
.option('--json', 'Output as JSON')
|
|
239
|
+
.action(calcAction((opts) => {
|
|
240
|
+
const result = calculateAssetDisposal({
|
|
241
|
+
cost: opts.cost,
|
|
242
|
+
salvageValue: opts.salvage,
|
|
243
|
+
usefulLifeYears: opts.life,
|
|
244
|
+
acquisitionDate: opts.acquired,
|
|
245
|
+
disposalDate: opts.disposed,
|
|
246
|
+
proceeds: opts.proceeds,
|
|
247
|
+
method: opts.method,
|
|
248
|
+
currency: opts.currency,
|
|
249
|
+
});
|
|
250
|
+
opts.json ? printJson(result) : printResult(result);
|
|
251
|
+
}));
|
|
252
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { dirname, join } from 'path';
|
|
|
6
6
|
import { initCommand } from './commands/init.js';
|
|
7
7
|
import { versionsCommand } from './commands/versions.js';
|
|
8
8
|
import { updateCommand } from './commands/update.js';
|
|
9
|
+
import { registerCalcCommand } from './commands/calc.js';
|
|
9
10
|
import { SKILL_TYPES } from './types/index.js';
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
12
|
const __dirname = dirname(__filename);
|
|
@@ -49,4 +50,5 @@ program
|
|
|
49
50
|
skill: options.skill,
|
|
50
51
|
});
|
|
51
52
|
});
|
|
53
|
+
registerCalcCommand(program);
|
|
52
54
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jaz-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "CLI to install Jaz AI skills for Claude Code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -36,8 +36,9 @@
|
|
|
36
36
|
"author": "Jaz Engineering <api-support@jaz.ai>",
|
|
37
37
|
"license": "MIT",
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"commander": "^12.1.0",
|
|
40
39
|
"chalk": "^5.3.0",
|
|
40
|
+
"commander": "^12.1.0",
|
|
41
|
+
"financial": "^0.2.4",
|
|
41
42
|
"ora": "^8.1.1",
|
|
42
43
|
"prompts": "^2.4.2"
|
|
43
44
|
},
|