jaz-cli 2.6.0 → 2.8.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 +12 -2
- package/assets/skills/api/references/dependencies.md +3 -2
- package/assets/skills/api/references/endpoints.md +78 -0
- package/assets/skills/api/references/feature-glossary.md +4 -4
- package/assets/skills/api/references/field-map.md +17 -0
- package/assets/skills/api/references/full-api-surface.md +1 -1
- package/assets/skills/conversion/SKILL.md +1 -1
- package/assets/skills/jobs/SKILL.md +104 -0
- package/assets/skills/jobs/references/audit-prep.md +319 -0
- package/assets/skills/jobs/references/bank-recon.md +234 -0
- package/assets/skills/jobs/references/building-blocks.md +135 -0
- package/assets/skills/jobs/references/credit-control.md +273 -0
- package/assets/skills/jobs/references/fa-review.md +267 -0
- package/assets/skills/jobs/references/gst-vat-filing.md +250 -0
- package/assets/skills/jobs/references/month-end-close.md +308 -0
- package/assets/skills/jobs/references/payment-run.md +246 -0
- package/assets/skills/jobs/references/quarter-end-close.md +268 -0
- package/assets/skills/jobs/references/supplier-recon.md +330 -0
- package/assets/skills/jobs/references/year-end-close.md +341 -0
- package/assets/skills/transaction-recipes/SKILL.md +1 -1
- package/dist/__tests__/amortization.test.js +101 -0
- package/dist/__tests__/asset-disposal.test.js +249 -0
- package/dist/__tests__/blueprint.test.js +72 -0
- package/dist/__tests__/depreciation.test.js +125 -0
- package/dist/__tests__/ecl.test.js +134 -0
- package/dist/__tests__/fixed-deposit.test.js +214 -0
- package/dist/__tests__/fx-reval.test.js +115 -0
- package/dist/__tests__/jobs-audit-prep.test.js +125 -0
- package/dist/__tests__/jobs-bank-recon.test.js +108 -0
- package/dist/__tests__/jobs-credit-control.test.js +98 -0
- package/dist/__tests__/jobs-fa-review.test.js +104 -0
- package/dist/__tests__/jobs-gst-vat.test.js +113 -0
- package/dist/__tests__/jobs-month-end.test.js +162 -0
- package/dist/__tests__/jobs-payment-run.test.js +106 -0
- package/dist/__tests__/jobs-quarter-end.test.js +155 -0
- package/dist/__tests__/jobs-supplier-recon.test.js +115 -0
- package/dist/__tests__/jobs-validate.test.js +181 -0
- package/dist/__tests__/jobs-year-end.test.js +149 -0
- package/dist/__tests__/lease.test.js +96 -0
- package/dist/__tests__/loan.test.js +80 -0
- package/dist/__tests__/provision.test.js +141 -0
- package/dist/__tests__/validate.test.js +81 -0
- package/dist/calc/asset-disposal.js +17 -13
- package/dist/calc/fixed-deposit.js +26 -17
- package/dist/calc/lease.js +7 -3
- package/dist/commands/jobs.js +184 -0
- package/dist/index.js +2 -0
- package/dist/jobs/audit-prep.js +211 -0
- package/dist/jobs/bank-recon.js +163 -0
- package/dist/jobs/credit-control.js +126 -0
- package/dist/jobs/fa-review.js +121 -0
- package/dist/jobs/format.js +102 -0
- package/dist/jobs/gst-vat.js +187 -0
- package/dist/jobs/month-end.js +232 -0
- package/dist/jobs/payment-run.js +199 -0
- package/dist/jobs/quarter-end.js +135 -0
- package/dist/jobs/supplier-recon.js +132 -0
- package/dist/jobs/types.js +36 -0
- package/dist/jobs/validate.js +115 -0
- package/dist/jobs/year-end.js +153 -0
- package/dist/types/index.js +2 -1
- package/package.json +5 -2
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit Preparation blueprint generator.
|
|
3
|
+
* Produces a structured JobBlueprint for compiling audit-ready financial packs —
|
|
4
|
+
* no actual API calls, just an actionable checklist for accountants.
|
|
5
|
+
*/
|
|
6
|
+
import { buildSummary } from './types.js';
|
|
7
|
+
import { parseQuarterPeriod, parseYearPeriod } from './validate.js';
|
|
8
|
+
function parsePeriod(period) {
|
|
9
|
+
if (/^\d{4}-Q[1-4]$/i.test(period)) {
|
|
10
|
+
return parseQuarterPeriod(period);
|
|
11
|
+
}
|
|
12
|
+
return parseYearPeriod(period);
|
|
13
|
+
}
|
|
14
|
+
export function generateAuditPrepBlueprint(opts) {
|
|
15
|
+
const p = parsePeriod(opts.period);
|
|
16
|
+
const currency = opts.currency ?? 'SGD';
|
|
17
|
+
// Phase 1: Financial Statements
|
|
18
|
+
const financialStatements = {
|
|
19
|
+
name: 'Financial Statements',
|
|
20
|
+
description: `Generate the core financial statements for ${p.label}.`,
|
|
21
|
+
steps: [
|
|
22
|
+
{
|
|
23
|
+
order: 1,
|
|
24
|
+
description: 'Generate Trial Balance',
|
|
25
|
+
category: 'report',
|
|
26
|
+
apiCall: 'POST /generate-reports/trial-balance',
|
|
27
|
+
apiBody: {
|
|
28
|
+
startDate: p.startDate,
|
|
29
|
+
endDate: p.endDate,
|
|
30
|
+
},
|
|
31
|
+
verification: 'TB balances (total debits = total credits)',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
order: 2,
|
|
35
|
+
description: 'Generate Balance Sheet',
|
|
36
|
+
category: 'report',
|
|
37
|
+
apiCall: 'POST /generate-reports/balance-sheet',
|
|
38
|
+
apiBody: {
|
|
39
|
+
primarySnapshotDate: p.endDate,
|
|
40
|
+
},
|
|
41
|
+
verification: 'Assets = Liabilities + Equity',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
order: 3,
|
|
45
|
+
description: 'Generate Profit & Loss',
|
|
46
|
+
category: 'report',
|
|
47
|
+
apiCall: 'POST /generate-reports/profit-and-loss',
|
|
48
|
+
apiBody: {
|
|
49
|
+
primarySnapshotDate: p.endDate,
|
|
50
|
+
secondarySnapshotDate: p.startDate,
|
|
51
|
+
},
|
|
52
|
+
verification: 'Net profit/loss ties to retained earnings movement on BS',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
order: 4,
|
|
56
|
+
description: 'Generate Cash Flow Statement',
|
|
57
|
+
category: 'report',
|
|
58
|
+
apiCall: 'POST /generate-reports/cashflow',
|
|
59
|
+
apiBody: {
|
|
60
|
+
primaryStartDate: p.startDate,
|
|
61
|
+
primaryEndDate: p.endDate,
|
|
62
|
+
},
|
|
63
|
+
verification: 'Closing cash ties to bank balances on BS',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
order: 5,
|
|
67
|
+
description: 'Generate Statement of Changes in Equity',
|
|
68
|
+
category: 'report',
|
|
69
|
+
apiCall: 'POST /generate-reports/equity-movement',
|
|
70
|
+
apiBody: {
|
|
71
|
+
primarySnapshotStartDate: p.startDate,
|
|
72
|
+
primarySnapshotEndDate: p.endDate,
|
|
73
|
+
},
|
|
74
|
+
verification: 'Closing equity ties to BS equity section',
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
// Phase 2: Supporting Schedules
|
|
79
|
+
const supportingSchedules = {
|
|
80
|
+
name: 'Supporting Schedules',
|
|
81
|
+
description: 'Generate detailed schedules that support the financial statements.',
|
|
82
|
+
steps: [
|
|
83
|
+
{
|
|
84
|
+
order: 6,
|
|
85
|
+
description: 'Generate AR aging schedule',
|
|
86
|
+
category: 'report',
|
|
87
|
+
apiCall: 'POST /generate-reports/ar-aging',
|
|
88
|
+
apiBody: {
|
|
89
|
+
endDate: p.endDate,
|
|
90
|
+
},
|
|
91
|
+
verification: 'AR aging total ties to trade receivables on BS',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
order: 7,
|
|
95
|
+
description: 'Generate AP aging schedule',
|
|
96
|
+
category: 'report',
|
|
97
|
+
apiCall: 'POST /generate-reports/ap-aging',
|
|
98
|
+
apiBody: {
|
|
99
|
+
endDate: p.endDate,
|
|
100
|
+
},
|
|
101
|
+
verification: 'AP aging total ties to trade payables on BS',
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
order: 8,
|
|
105
|
+
description: 'Generate Fixed Asset register',
|
|
106
|
+
category: 'report',
|
|
107
|
+
apiCall: 'POST /generate-reports/fixed-assets',
|
|
108
|
+
apiBody: {
|
|
109
|
+
endDate: p.endDate,
|
|
110
|
+
},
|
|
111
|
+
notes: 'Include cost, accumulated depreciation, and NBV per asset. Should show additions, disposals, and depreciation for the period.',
|
|
112
|
+
verification: 'FA register NBV total ties to property/equipment on BS',
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
order: 9,
|
|
116
|
+
description: 'Generate Tax Ledger',
|
|
117
|
+
category: 'report',
|
|
118
|
+
apiCall: 'POST /generate-reports/vat-ledger',
|
|
119
|
+
apiBody: {
|
|
120
|
+
startDate: p.startDate,
|
|
121
|
+
endDate: p.endDate,
|
|
122
|
+
},
|
|
123
|
+
notes: 'Full tax ledger for the audit period — auditors will test-check individual entries',
|
|
124
|
+
verification: 'Tax ledger totals consistent with GST returns filed',
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
};
|
|
128
|
+
// Phase 3: Reconciliations
|
|
129
|
+
const reconciliations = {
|
|
130
|
+
name: 'Reconciliations',
|
|
131
|
+
description: 'Perform key reconciliations for audit evidence.',
|
|
132
|
+
steps: [
|
|
133
|
+
{
|
|
134
|
+
order: 10,
|
|
135
|
+
description: 'Bank reconciliation for all accounts',
|
|
136
|
+
category: 'verify',
|
|
137
|
+
apiCall: 'POST /bank-records/search',
|
|
138
|
+
apiBody: {
|
|
139
|
+
filters: {
|
|
140
|
+
reconciliationStatus: 'UNRECONCILED',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
recipeRef: 'bank-reconciliation',
|
|
144
|
+
notes: 'Reconcile all bank accounts as at period end. Document any reconciling items (outstanding cheques, deposits in transit).',
|
|
145
|
+
verification: 'All bank accounts reconciled — GL balance agrees with bank statements',
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
order: 11,
|
|
149
|
+
description: 'Intercompany reconciliation',
|
|
150
|
+
category: 'verify',
|
|
151
|
+
apiCall: 'POST /generate-reports/trial-balance',
|
|
152
|
+
conditional: 'If intercompany transactions exist',
|
|
153
|
+
notes: 'Compare intercompany receivables and payables across entities. Eliminate for consolidated accounts.',
|
|
154
|
+
verification: 'Intercompany balances net to zero across group entities',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
order: 12,
|
|
158
|
+
description: 'Loan schedule reconciliation',
|
|
159
|
+
category: 'verify',
|
|
160
|
+
calcCommand: 'jaz calc loan',
|
|
161
|
+
conditional: 'If loan facilities exist',
|
|
162
|
+
notes: 'Compare loan amortization schedule to GL balances. Verify principal, interest, and current/non-current split.',
|
|
163
|
+
verification: 'Loan balances per GL match lender statements and amortization schedule',
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
};
|
|
167
|
+
// Phase 4: Export & Compile
|
|
168
|
+
const exportCompile = {
|
|
169
|
+
name: 'Export & Compile Audit Pack',
|
|
170
|
+
description: 'Export all reports and compile the audit-ready pack.',
|
|
171
|
+
steps: [
|
|
172
|
+
{
|
|
173
|
+
order: 13,
|
|
174
|
+
description: 'Export all data for audit working papers',
|
|
175
|
+
category: 'export',
|
|
176
|
+
notes: [
|
|
177
|
+
'Export the following as CSV/PDF:',
|
|
178
|
+
'(1) Chart of accounts with balances,',
|
|
179
|
+
'(2) General ledger detail for the period,',
|
|
180
|
+
'(3) All reports generated in phases 1-2,',
|
|
181
|
+
'(4) Bank statements and reconciliations,',
|
|
182
|
+
'(5) Supporting invoices/bills for sample testing.',
|
|
183
|
+
].join(' '),
|
|
184
|
+
verification: 'All data exports completed successfully',
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
order: 14,
|
|
188
|
+
description: 'Compile audit preparation pack',
|
|
189
|
+
category: 'report',
|
|
190
|
+
notes: [
|
|
191
|
+
'Organize into audit pack structure:',
|
|
192
|
+
'(a) Financial statements (TB, BS, P&L, Cash Flow, Equity),',
|
|
193
|
+
'(b) Supporting schedules (AR, AP, FA, Tax),',
|
|
194
|
+
'(c) Reconciliations (Bank, Intercompany, Loans),',
|
|
195
|
+
'(d) Data exports and sample documents.',
|
|
196
|
+
'Include index/table of contents for auditor reference.',
|
|
197
|
+
].join(' '),
|
|
198
|
+
verification: 'Audit pack complete, indexed, and ready for auditor handoff',
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
const phases = [financialStatements, supportingSchedules, reconciliations, exportCompile];
|
|
203
|
+
return {
|
|
204
|
+
jobType: 'audit-prep',
|
|
205
|
+
period: p.label,
|
|
206
|
+
currency,
|
|
207
|
+
mode: 'standalone',
|
|
208
|
+
phases,
|
|
209
|
+
summary: buildSummary(phases),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bank Reconciliation blueprint generator.
|
|
3
|
+
* Produces a structured JobBlueprint describing the bank recon workflow —
|
|
4
|
+
* no actual API calls, just an actionable checklist for accountants.
|
|
5
|
+
*/
|
|
6
|
+
import { buildSummary } from './types.js';
|
|
7
|
+
import { parseMonthPeriod } from './validate.js';
|
|
8
|
+
export function generateBankReconBlueprint(opts = {}) {
|
|
9
|
+
const currency = opts.currency ?? 'SGD';
|
|
10
|
+
const period = opts.period ?? 'current';
|
|
11
|
+
const accountFilter = opts.account
|
|
12
|
+
? { accountName: opts.account }
|
|
13
|
+
: {};
|
|
14
|
+
const periodFilter = opts.period
|
|
15
|
+
? (() => {
|
|
16
|
+
const mp = parseMonthPeriod(opts.period);
|
|
17
|
+
return { valueDateFrom: mp.startDate, valueDateTo: mp.endDate };
|
|
18
|
+
})()
|
|
19
|
+
: {};
|
|
20
|
+
// Phase 1: Identify bank accounts
|
|
21
|
+
const identify = {
|
|
22
|
+
name: 'Identify Bank Accounts',
|
|
23
|
+
description: 'List all bank accounts in the chart of accounts.',
|
|
24
|
+
steps: [
|
|
25
|
+
{
|
|
26
|
+
order: 1,
|
|
27
|
+
description: 'List bank accounts from chart of accounts',
|
|
28
|
+
category: 'verify',
|
|
29
|
+
apiCall: 'POST /chart-of-accounts/search',
|
|
30
|
+
apiBody: {
|
|
31
|
+
filters: {
|
|
32
|
+
classificationType: 'Bank Accounts',
|
|
33
|
+
...accountFilter,
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
notes: opts.account
|
|
37
|
+
? `Filtered to account: ${opts.account}`
|
|
38
|
+
: 'Returns all bank accounts — pick which to reconcile',
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
// Phase 2: Pull unreconciled records
|
|
43
|
+
const pullUnreconciled = {
|
|
44
|
+
name: 'Pull Unreconciled Records',
|
|
45
|
+
description: 'Retrieve all unreconciled bank records and check for duplicates.',
|
|
46
|
+
steps: [
|
|
47
|
+
{
|
|
48
|
+
order: 2,
|
|
49
|
+
description: 'Search unreconciled bank records',
|
|
50
|
+
category: 'verify',
|
|
51
|
+
apiCall: 'POST /bank-records/search',
|
|
52
|
+
apiBody: {
|
|
53
|
+
filters: {
|
|
54
|
+
reconciliationStatus: 'UNRECONCILED',
|
|
55
|
+
...accountFilter,
|
|
56
|
+
...periodFilter,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
verification: 'Note total count and amount of unreconciled items',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
order: 3,
|
|
63
|
+
description: 'Check for duplicate bank records',
|
|
64
|
+
category: 'verify',
|
|
65
|
+
apiCall: 'POST /bank-records/search',
|
|
66
|
+
apiBody: {
|
|
67
|
+
filters: {
|
|
68
|
+
reconciliationStatus: 'UNRECONCILED',
|
|
69
|
+
...accountFilter,
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
notes: 'Compare reference numbers, amounts, and dates to identify duplicates',
|
|
73
|
+
verification: 'Flag any records with matching amount + date + reference',
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
// Phase 3: Resolve unreconciled items
|
|
78
|
+
const resolve = {
|
|
79
|
+
name: 'Resolve Unreconciled Items',
|
|
80
|
+
description: 'Match, create, or flag each unreconciled bank record.',
|
|
81
|
+
steps: [
|
|
82
|
+
{
|
|
83
|
+
order: 4,
|
|
84
|
+
description: 'Match bank records to existing transactions',
|
|
85
|
+
category: 'resolve',
|
|
86
|
+
apiCall: 'POST /bank-records/{id}/reconcile',
|
|
87
|
+
notes: 'Match by reference, amount, and date against open invoices/bills/journals',
|
|
88
|
+
recipeRef: 'bank-reconciliation',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
order: 5,
|
|
92
|
+
description: 'Create transactions from bank statement (Jaz Magic)',
|
|
93
|
+
category: 'resolve',
|
|
94
|
+
apiCall: 'POST /bank-records/import-from-attachment',
|
|
95
|
+
apiBody: {
|
|
96
|
+
sourceType: 'FILE',
|
|
97
|
+
businessTransactionType: 'BANK_STATEMENT',
|
|
98
|
+
},
|
|
99
|
+
notes: 'Import CSV/OFX files — uses sourceFile, accountResourceId fields',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
order: 6,
|
|
103
|
+
description: 'Create cash receipt/payment journals for unmatched items',
|
|
104
|
+
category: 'resolve',
|
|
105
|
+
apiCall: 'POST /journals',
|
|
106
|
+
recipeRef: 'cash-receipt',
|
|
107
|
+
notes: 'For bank records with no matching transaction — create cash journal entries',
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
order: 7,
|
|
111
|
+
description: 'Flag remaining items for investigation',
|
|
112
|
+
category: 'review',
|
|
113
|
+
notes: 'Items that cannot be matched or journaled need manual investigation — document reason for each',
|
|
114
|
+
verification: 'All unreconciled items should be resolved or flagged',
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
};
|
|
118
|
+
// Phase 4: Verification
|
|
119
|
+
const verification = {
|
|
120
|
+
name: 'Verification',
|
|
121
|
+
description: 'Confirm reconciliation is complete and bank balances agree.',
|
|
122
|
+
steps: [
|
|
123
|
+
{
|
|
124
|
+
order: 8,
|
|
125
|
+
description: 'Re-check unreconciled count',
|
|
126
|
+
category: 'verify',
|
|
127
|
+
apiCall: 'POST /bank-records/search',
|
|
128
|
+
apiBody: {
|
|
129
|
+
filters: {
|
|
130
|
+
reconciliationStatus: 'UNRECONCILED',
|
|
131
|
+
...accountFilter,
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
verification: 'Unreconciled count should be zero (or only flagged items remain)',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
order: 9,
|
|
138
|
+
description: 'Review bank balance summary',
|
|
139
|
+
category: 'verify',
|
|
140
|
+
apiCall: 'POST /generate-reports/trial-balance',
|
|
141
|
+
notes: 'Compare GL bank balance to bank statement closing balance',
|
|
142
|
+
verification: 'GL balance must equal bank statement balance after reconciling items',
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
order: 10,
|
|
146
|
+
description: 'Generate reconciliation report',
|
|
147
|
+
category: 'report',
|
|
148
|
+
apiCall: 'POST /generate-reports/trial-balance',
|
|
149
|
+
notes: 'Document: opening balance, reconciled items, outstanding items, closing balance',
|
|
150
|
+
verification: 'Reconciliation report balances and is saved for audit trail',
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
};
|
|
154
|
+
const phases = [identify, pullUnreconciled, resolve, verification];
|
|
155
|
+
return {
|
|
156
|
+
jobType: 'bank-recon',
|
|
157
|
+
period,
|
|
158
|
+
currency,
|
|
159
|
+
mode: 'standalone',
|
|
160
|
+
phases,
|
|
161
|
+
summary: buildSummary(phases),
|
|
162
|
+
};
|
|
163
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credit Control blueprint generator.
|
|
3
|
+
* Produces a structured JobBlueprint for managing overdue receivables —
|
|
4
|
+
* no actual API calls, just an actionable checklist for accountants.
|
|
5
|
+
*/
|
|
6
|
+
import { buildSummary } from './types.js';
|
|
7
|
+
import { validateOverdueDays } from './validate.js';
|
|
8
|
+
export function generateCreditControlBlueprint(opts = {}) {
|
|
9
|
+
const overdueDays = opts.overdueDays ?? 30;
|
|
10
|
+
if (opts.overdueDays !== undefined) {
|
|
11
|
+
validateOverdueDays(opts.overdueDays);
|
|
12
|
+
}
|
|
13
|
+
const currency = opts.currency ?? 'SGD';
|
|
14
|
+
const period = `Overdue > ${overdueDays} days`;
|
|
15
|
+
// Phase 1: AR Analysis
|
|
16
|
+
const arAnalysis = {
|
|
17
|
+
name: 'AR Analysis',
|
|
18
|
+
description: 'Generate AR aging and identify overdue invoices beyond the threshold.',
|
|
19
|
+
steps: [
|
|
20
|
+
{
|
|
21
|
+
order: 1,
|
|
22
|
+
description: 'Generate AR aging report',
|
|
23
|
+
category: 'report',
|
|
24
|
+
apiCall: 'POST /generate-reports/ar-aging',
|
|
25
|
+
notes: 'Current, 1-30, 31-60, 61-90, 90+ day buckets. Focus on buckets beyond threshold.',
|
|
26
|
+
verification: 'AR aging report generated — note total receivables and overdue amount',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
order: 2,
|
|
30
|
+
description: `Identify invoices overdue by more than ${overdueDays} days`,
|
|
31
|
+
category: 'verify',
|
|
32
|
+
apiCall: 'POST /invoices/search',
|
|
33
|
+
apiBody: {
|
|
34
|
+
filters: {
|
|
35
|
+
status: ['APPROVED'],
|
|
36
|
+
overdue: true,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
notes: `Filter to invoices past due by ${overdueDays}+ days. Record customer name, invoice number, amount, and days overdue.`,
|
|
40
|
+
verification: 'Overdue invoice list matches AR aging report totals',
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
44
|
+
// Phase 2: Chase List
|
|
45
|
+
const chaseList = {
|
|
46
|
+
name: 'Chase List',
|
|
47
|
+
description: 'Prioritize customers and generate a follow-up action list.',
|
|
48
|
+
steps: [
|
|
49
|
+
{
|
|
50
|
+
order: 3,
|
|
51
|
+
description: 'Group overdue invoices by customer priority',
|
|
52
|
+
category: 'review',
|
|
53
|
+
apiCall: 'POST /invoices/search',
|
|
54
|
+
apiBody: {
|
|
55
|
+
filters: {
|
|
56
|
+
status: ['APPROVED'],
|
|
57
|
+
overdue: true,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
notes: 'Rank customers by: (1) total overdue amount, (2) days overdue, (3) payment history. Top customers get priority outreach.',
|
|
61
|
+
verification: 'Customer priority list established',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
order: 4,
|
|
65
|
+
description: 'Generate follow-up action list',
|
|
66
|
+
category: 'report',
|
|
67
|
+
notes: [
|
|
68
|
+
'For each overdue customer, assign action:',
|
|
69
|
+
'(a) 30-60 days: friendly reminder email/call,',
|
|
70
|
+
'(b) 60-90 days: formal demand letter,',
|
|
71
|
+
'(c) 90+ days: escalate to management / external collection.',
|
|
72
|
+
'Document contact attempts and agreed payment plans.',
|
|
73
|
+
].join(' '),
|
|
74
|
+
verification: 'Every overdue customer has an assigned follow-up action and owner',
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
// Phase 3: Bad Debt Assessment
|
|
79
|
+
const badDebtAssessment = {
|
|
80
|
+
name: 'Bad Debt Assessment',
|
|
81
|
+
description: 'Assess doubtful debts and calculate expected credit losses if needed.',
|
|
82
|
+
steps: [
|
|
83
|
+
{
|
|
84
|
+
order: 5,
|
|
85
|
+
description: 'Identify doubtful debts',
|
|
86
|
+
category: 'review',
|
|
87
|
+
apiCall: 'POST /generate-reports/ar-aging',
|
|
88
|
+
notes: 'Review 90+ day bucket for potential bad debts. Consider: customer financial health, dispute status, collateral, historical write-off rates.',
|
|
89
|
+
verification: 'Doubtful debt candidates identified and documented',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
order: 6,
|
|
93
|
+
description: 'Calculate expected credit loss (ECL) provision',
|
|
94
|
+
category: 'value',
|
|
95
|
+
calcCommand: 'jaz calc ecl',
|
|
96
|
+
recipeRef: 'bad-debt-provision',
|
|
97
|
+
notes: 'ECL model: apply loss rates per aging bucket (e.g., current 0.5%, 30d 2%, 60d 5%, 90d 10%, 120+ 50%). Book provision journal if ECL differs from existing allowance.',
|
|
98
|
+
verification: 'ECL calculated and compared to existing provision balance. Adjustment journal prepared if needed.',
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
// Phase 4: Verification
|
|
103
|
+
const verification = {
|
|
104
|
+
name: 'Verification',
|
|
105
|
+
description: 'Review AR aging after all credit control actions.',
|
|
106
|
+
steps: [
|
|
107
|
+
{
|
|
108
|
+
order: 7,
|
|
109
|
+
description: 'Review AR aging after credit control actions',
|
|
110
|
+
category: 'verify',
|
|
111
|
+
apiCall: 'POST /generate-reports/ar-aging',
|
|
112
|
+
notes: 'Compare to opening AR aging. Document: payments received, payment plans agreed, write-offs processed, provisions updated.',
|
|
113
|
+
verification: 'AR aging reviewed, all actions documented, follow-up dates set',
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
};
|
|
117
|
+
const phases = [arAnalysis, chaseList, badDebtAssessment, verification];
|
|
118
|
+
return {
|
|
119
|
+
jobType: 'credit-control',
|
|
120
|
+
period,
|
|
121
|
+
currency,
|
|
122
|
+
mode: 'standalone',
|
|
123
|
+
phases,
|
|
124
|
+
summary: buildSummary(phases),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed Asset Review blueprint generator.
|
|
3
|
+
* Produces a structured JobBlueprint for reviewing the fixed asset register —
|
|
4
|
+
* no actual API calls, just an actionable checklist for accountants.
|
|
5
|
+
*/
|
|
6
|
+
import { buildSummary } from './types.js';
|
|
7
|
+
export function generateFaReviewBlueprint(opts = {}) {
|
|
8
|
+
const currency = opts.currency ?? 'SGD';
|
|
9
|
+
// Phase 1: Register Review
|
|
10
|
+
const registerReview = {
|
|
11
|
+
name: 'Register Review',
|
|
12
|
+
description: 'Pull the fixed asset summary and verify against general ledger balances.',
|
|
13
|
+
steps: [
|
|
14
|
+
{
|
|
15
|
+
order: 1,
|
|
16
|
+
description: 'Pull fixed asset summary report',
|
|
17
|
+
category: 'report',
|
|
18
|
+
apiCall: 'POST /generate-reports/fixed-assets',
|
|
19
|
+
notes: 'Review: asset description, cost, accumulated depreciation, NBV, useful life remaining, depreciation method per asset',
|
|
20
|
+
verification: 'FA register generated — note total cost, total accumulated depreciation, total NBV',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
order: 2,
|
|
24
|
+
description: 'Verify FA register against GL balances',
|
|
25
|
+
category: 'verify',
|
|
26
|
+
apiCall: 'POST /generate-reports/trial-balance',
|
|
27
|
+
notes: 'Compare FA register totals to TB: (1) total cost should match FA cost accounts, (2) total accumulated depreciation should match contra accounts, (3) NBV should match net FA on BS',
|
|
28
|
+
verification: 'FA register totals agree with GL. Any differences investigated and resolved.',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
};
|
|
32
|
+
// Phase 2: Depreciation Check
|
|
33
|
+
const depreciationCheck = {
|
|
34
|
+
name: 'Depreciation Check',
|
|
35
|
+
description: 'Verify depreciation has been run correctly and review fully depreciated assets.',
|
|
36
|
+
steps: [
|
|
37
|
+
{
|
|
38
|
+
order: 3,
|
|
39
|
+
description: 'Verify depreciation runs are up to date',
|
|
40
|
+
category: 'verify',
|
|
41
|
+
apiCall: 'POST /generate-reports/fixed-assets',
|
|
42
|
+
calcCommand: 'jaz calc depreciation',
|
|
43
|
+
notes: 'Check that monthly/annual depreciation has been posted for all assets through the current period. Recalculate sample of assets to verify amounts.',
|
|
44
|
+
verification: 'Depreciation is current — no missed periods. Sample recalculations match posted amounts.',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
order: 4,
|
|
48
|
+
description: 'Check fully depreciated assets',
|
|
49
|
+
category: 'review',
|
|
50
|
+
apiCall: 'POST /generate-reports/fixed-assets',
|
|
51
|
+
notes: 'Identify assets with NBV = 0 or NBV = salvage value. Review whether: (1) asset is still in use, (2) asset should be disposed/written off, (3) useful life estimate needs revision.',
|
|
52
|
+
verification: 'All fully depreciated assets reviewed — disposals and write-offs identified',
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
// Phase 3: Disposals & Write-offs
|
|
57
|
+
const disposalsWriteoffs = {
|
|
58
|
+
name: 'Disposals & Write-offs',
|
|
59
|
+
description: 'Process asset disposals and calculate gain/loss on disposal.',
|
|
60
|
+
steps: [
|
|
61
|
+
{
|
|
62
|
+
order: 5,
|
|
63
|
+
description: 'Process asset disposals',
|
|
64
|
+
category: 'adjust',
|
|
65
|
+
apiCall: 'POST /journals',
|
|
66
|
+
recipeRef: 'asset-disposal',
|
|
67
|
+
calcCommand: 'jaz calc asset-disposal',
|
|
68
|
+
notes: 'For each disposal: (1) calculate NBV at disposal date, (2) compare to sale proceeds, (3) recognize gain or loss. Journal: Dr Bank/Receivable, Dr Accumulated Depreciation, Cr Asset Cost, Cr/Dr Gain/Loss on Disposal.',
|
|
69
|
+
verification: 'Disposal journals balanced. Gain/loss correctly calculated. Asset removed from register.',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
order: 6,
|
|
73
|
+
description: 'Process asset write-offs',
|
|
74
|
+
category: 'adjust',
|
|
75
|
+
apiCall: 'POST /journals',
|
|
76
|
+
recipeRef: 'asset-disposal',
|
|
77
|
+
notes: 'For write-offs (zero proceeds): Dr Accumulated Depreciation, Dr Loss on Write-off (for remaining NBV), Cr Asset Cost. Document reason for write-off (obsolescence, damage, etc.).',
|
|
78
|
+
verification: 'Write-off journals balanced. Assets removed from register. Reasons documented.',
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
// Phase 4: Verification
|
|
83
|
+
const verification = {
|
|
84
|
+
name: 'Verification',
|
|
85
|
+
description: 'Final reconciliation of fixed assets to trial balance and reasonableness check.',
|
|
86
|
+
steps: [
|
|
87
|
+
{
|
|
88
|
+
order: 7,
|
|
89
|
+
description: 'Reconcile updated FA register to trial balance',
|
|
90
|
+
category: 'verify',
|
|
91
|
+
apiCall: 'POST /generate-reports/trial-balance',
|
|
92
|
+
notes: 'After all disposals and write-offs, re-pull TB and FA register. Verify they agree.',
|
|
93
|
+
verification: 'FA register totals match TB. All movements accounted for (additions, depreciation, disposals, write-offs).',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
order: 8,
|
|
97
|
+
description: 'Check NBV reasonableness',
|
|
98
|
+
category: 'review',
|
|
99
|
+
apiCall: 'POST /generate-reports/fixed-assets',
|
|
100
|
+
notes: [
|
|
101
|
+
'Review remaining NBV for reasonableness:',
|
|
102
|
+
'(1) No negative NBV,',
|
|
103
|
+
'(2) NBV does not exceed replacement cost,',
|
|
104
|
+
'(3) Useful lives are appropriate for asset type,',
|
|
105
|
+
'(4) Salvage values are reasonable,',
|
|
106
|
+
'(5) No impairment indicators (market value decline, physical damage, change in use).',
|
|
107
|
+
].join(' '),
|
|
108
|
+
verification: 'All NBV values reasonable. No impairment indicators identified, or impairment review initiated where needed.',
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
};
|
|
112
|
+
const phases = [registerReview, depreciationCheck, disposalsWriteoffs, verification];
|
|
113
|
+
return {
|
|
114
|
+
jobType: 'fa-review',
|
|
115
|
+
period: 'current',
|
|
116
|
+
currency,
|
|
117
|
+
mode: 'standalone',
|
|
118
|
+
phases,
|
|
119
|
+
summary: buildSummary(phases),
|
|
120
|
+
};
|
|
121
|
+
}
|