@aderis-erp/cli 1.1.1 → 1.1.2
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/dist/commands/access-groups.d.ts +8 -0
- package/dist/commands/access-groups.js +54 -6
- package/dist/commands/account-transaction-allocations.d.ts +8 -0
- package/dist/commands/account-transaction-allocations.js +52 -5
- package/dist/commands/account-transactions.d.ts +8 -0
- package/dist/commands/account-transactions.js +55 -7
- package/dist/commands/accounts.d.ts +8 -0
- package/dist/commands/accounts.js +52 -5
- package/dist/commands/agent-platform.d.ts +8 -0
- package/dist/commands/agent-platform.js +52 -5
- package/dist/commands/agent-runs.d.ts +8 -0
- package/dist/commands/agent-runs.js +52 -5
- package/dist/commands/analytics.d.ts +8 -0
- package/dist/commands/analytics.js +52 -5
- package/dist/commands/api-keys.d.ts +8 -0
- package/dist/commands/api-keys.js +52 -5
- package/dist/commands/async-jobs.d.ts +8 -0
- package/dist/commands/async-jobs.js +52 -5
- package/dist/commands/audit-log.d.ts +8 -0
- package/dist/commands/audit-log.js +52 -5
- package/dist/commands/bank-accounts.d.ts +8 -0
- package/dist/commands/bank-accounts.js +52 -5
- package/dist/commands/bank-integrations.d.ts +8 -0
- package/dist/commands/bank-integrations.js +52 -5
- package/dist/commands/business-partners.d.ts +9 -0
- package/dist/commands/business-partners.js +64 -7
- package/dist/commands/chat.d.ts +8 -0
- package/dist/commands/chat.js +52 -5
- package/dist/commands/credit-card-accounts.d.ts +8 -0
- package/dist/commands/credit-card-accounts.js +52 -5
- package/dist/commands/delivery-notes.d.ts +8 -0
- package/dist/commands/delivery-notes.js +52 -5
- package/dist/commands/dunning-configs.d.ts +8 -0
- package/dist/commands/dunning-configs.js +52 -5
- package/dist/commands/dunning-reminders.d.ts +8 -0
- package/dist/commands/dunning-reminders.js +52 -5
- package/dist/commands/dunning-runs.d.ts +8 -0
- package/dist/commands/dunning-runs.js +52 -5
- package/dist/commands/email-transactions.d.ts +8 -0
- package/dist/commands/email-transactions.js +52 -5
- package/dist/commands/employees.d.ts +8 -0
- package/dist/commands/employees.js +52 -5
- package/dist/commands/entity-configurations.d.ts +8 -0
- package/dist/commands/entity-configurations.js +52 -5
- package/dist/commands/event-processor-mappings.d.ts +8 -0
- package/dist/commands/event-processor-mappings.js +52 -5
- package/dist/commands/files.d.ts +8 -0
- package/dist/commands/files.js +52 -5
- package/dist/commands/health.d.ts +8 -0
- package/dist/commands/health.js +52 -5
- package/dist/commands/imports.d.ts +8 -0
- package/dist/commands/imports.js +53 -8
- package/dist/commands/inbox.d.ts +8 -0
- package/dist/commands/inbox.js +53 -7
- package/dist/commands/integration-identities.d.ts +8 -0
- package/dist/commands/integration-identities.js +52 -5
- package/dist/commands/integrations.d.ts +8 -0
- package/dist/commands/integrations.js +52 -5
- package/dist/commands/item-categories.d.ts +8 -0
- package/dist/commands/item-categories.js +52 -5
- package/dist/commands/items.d.ts +8 -0
- package/dist/commands/items.js +52 -5
- package/dist/commands/journal-lines.d.ts +8 -0
- package/dist/commands/journal-lines.js +52 -5
- package/dist/commands/journals.d.ts +8 -0
- package/dist/commands/journals.js +52 -5
- package/dist/commands/ledgers.d.ts +8 -0
- package/dist/commands/ledgers.js +52 -5
- package/dist/commands/my-account.d.ts +8 -0
- package/dist/commands/my-account.js +52 -5
- package/dist/commands/office-locations.d.ts +8 -0
- package/dist/commands/office-locations.js +52 -5
- package/dist/commands/payment-methods.d.ts +8 -0
- package/dist/commands/payment-methods.js +52 -5
- package/dist/commands/payment-runs.d.ts +8 -0
- package/dist/commands/payment-runs.js +54 -6
- package/dist/commands/payment-terms.d.ts +8 -0
- package/dist/commands/payment-terms.js +52 -5
- package/dist/commands/payments.d.ts +8 -0
- package/dist/commands/payments.js +52 -5
- package/dist/commands/payroll-runs.d.ts +8 -0
- package/dist/commands/payroll-runs.js +52 -5
- package/dist/commands/permissions.d.ts +8 -0
- package/dist/commands/permissions.js +52 -5
- package/dist/commands/price-lists.d.ts +8 -0
- package/dist/commands/price-lists.js +52 -5
- package/dist/commands/processor-mappings.d.ts +8 -0
- package/dist/commands/processor-mappings.js +52 -5
- package/dist/commands/processors.d.ts +8 -0
- package/dist/commands/processors.js +52 -5
- package/dist/commands/purchase-order-types.d.ts +8 -0
- package/dist/commands/purchase-order-types.js +52 -5
- package/dist/commands/purchase-orders.d.ts +8 -0
- package/dist/commands/purchase-orders.js +52 -5
- package/dist/commands/reports.d.ts +8 -0
- package/dist/commands/reports.js +52 -5
- package/dist/commands/roles.d.ts +8 -0
- package/dist/commands/roles.js +52 -5
- package/dist/commands/salary-types.d.ts +8 -0
- package/dist/commands/salary-types.js +52 -5
- package/dist/commands/sales-invoices.d.ts +10 -0
- package/dist/commands/sales-invoices.js +62 -6
- package/dist/commands/sales-orders.d.ts +8 -0
- package/dist/commands/sales-orders.js +52 -5
- package/dist/commands/saved-views.d.ts +8 -0
- package/dist/commands/saved-views.js +52 -5
- package/dist/commands/scheduled-processor-mappings.d.ts +8 -0
- package/dist/commands/scheduled-processor-mappings.js +52 -5
- package/dist/commands/schedules.d.ts +8 -0
- package/dist/commands/schedules.js +52 -5
- package/dist/commands/tags.d.ts +8 -0
- package/dist/commands/tags.js +52 -5
- package/dist/commands/tax-codes.d.ts +8 -0
- package/dist/commands/tax-codes.js +52 -5
- package/dist/commands/tax-matrix.d.ts +8 -0
- package/dist/commands/tax-matrix.js +52 -5
- package/dist/commands/templates.d.ts +8 -0
- package/dist/commands/templates.js +52 -5
- package/dist/commands/tenants.d.ts +8 -0
- package/dist/commands/tenants.js +52 -5
- package/dist/commands/tools.d.ts +8 -0
- package/dist/commands/tools.js +52 -5
- package/dist/commands/users.d.ts +8 -0
- package/dist/commands/users.js +52 -5
- package/dist/commands/vat-declarations.d.ts +8 -0
- package/dist/commands/vat-declarations.js +52 -5
- package/dist/commands/vendor-invoices.d.ts +9 -0
- package/dist/commands/vendor-invoices.js +60 -8
- package/dist/commands/webhooks.d.ts +8 -0
- package/dist/commands/webhooks.js +52 -5
- package/dist/commands/workflows.d.ts +8 -0
- package/dist/commands/workflows.js +52 -5
- package/oclif.manifest.json +433 -10
- package/package.json +1 -1
|
@@ -26,6 +26,7 @@ export default class BankIntegrations extends Command {
|
|
|
26
26
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
27
27
|
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
28
28
|
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
29
|
+
meta: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
29
30
|
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
30
31
|
};
|
|
31
32
|
run(): Promise<void>;
|
|
@@ -34,6 +35,13 @@ export default class BankIntegrations extends Command {
|
|
|
34
35
|
private runCamt053Import;
|
|
35
36
|
private runNestedImport;
|
|
36
37
|
private parseFilterValue;
|
|
38
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
39
|
+
private printPageSummary;
|
|
40
|
+
/**
|
|
41
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
42
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
43
|
+
*/
|
|
44
|
+
private warnShortPage;
|
|
37
45
|
private sanitizeOutput;
|
|
38
46
|
private getColumns;
|
|
39
47
|
private getValue;
|
|
@@ -63,6 +63,7 @@ export default class BankIntegrations extends Command {
|
|
|
63
63
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
64
64
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
65
65
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
66
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
66
67
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
67
68
|
};
|
|
68
69
|
async run() {
|
|
@@ -355,9 +356,15 @@ export default class BankIntegrations extends Command {
|
|
|
355
356
|
}
|
|
356
357
|
catch { /* keep as string */ }
|
|
357
358
|
}
|
|
358
|
-
//
|
|
359
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
360
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
361
|
+
// dropping it silently let a script read one page as the whole result
|
|
362
|
+
// (AderisERP/product#61).
|
|
363
|
+
let envelope;
|
|
359
364
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
360
|
-
|
|
365
|
+
const page = output;
|
|
366
|
+
envelope = page;
|
|
367
|
+
output = page.data;
|
|
361
368
|
}
|
|
362
369
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
363
370
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -374,12 +381,24 @@ export default class BankIntegrations extends Command {
|
|
|
374
381
|
output = this.sanitizeOutput(output);
|
|
375
382
|
}
|
|
376
383
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
377
|
-
if (
|
|
384
|
+
if (envelope)
|
|
385
|
+
this.warnShortPage(envelope, flags.limit);
|
|
386
|
+
if (flags.csv || flags.output === 'csv') {
|
|
378
387
|
this.printCsv(output, fieldList);
|
|
379
|
-
|
|
388
|
+
}
|
|
389
|
+
else if (flags.table || flags.output === 'table') {
|
|
380
390
|
this.printTable(output, fieldList);
|
|
381
|
-
|
|
391
|
+
if (envelope)
|
|
392
|
+
this.printPageSummary(envelope);
|
|
393
|
+
}
|
|
394
|
+
else if (envelope && flags.meta) {
|
|
395
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
396
|
+
// a bare array so existing scripts are unaffected.
|
|
397
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
382
400
|
this.log(JSON.stringify(output, null, 2));
|
|
401
|
+
}
|
|
383
402
|
}
|
|
384
403
|
catch (error) {
|
|
385
404
|
if (error instanceof ApiError) {
|
|
@@ -1008,6 +1027,34 @@ export default class BankIntegrations extends Command {
|
|
|
1008
1027
|
return `\$${op}`;
|
|
1009
1028
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
1010
1029
|
}
|
|
1030
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1031
|
+
printPageSummary(envelope) {
|
|
1032
|
+
const meta = envelope.meta;
|
|
1033
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1034
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1035
|
+
this.log(`
|
|
1036
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1037
|
+
}
|
|
1038
|
+
for (const total of envelope.totals ?? []) {
|
|
1039
|
+
const { currency, ...sums } = total;
|
|
1040
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1041
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
/**
|
|
1045
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1046
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1047
|
+
*/
|
|
1048
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1049
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1050
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1051
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1052
|
+
return;
|
|
1053
|
+
const pages = envelope.meta?.totalPages;
|
|
1054
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1055
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1056
|
+
`);
|
|
1057
|
+
}
|
|
1011
1058
|
sanitizeOutput(data) {
|
|
1012
1059
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1013
1060
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -17,6 +17,7 @@ export default class BusinessPartners extends Command {
|
|
|
17
17
|
'note-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
18
|
'file-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
19
|
'business-partner-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
|
+
id: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
21
|
page: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
22
|
limit: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
23
|
include: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -26,6 +27,7 @@ export default class BusinessPartners extends Command {
|
|
|
26
27
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
27
28
|
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
28
29
|
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
30
|
+
meta: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
29
31
|
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
30
32
|
};
|
|
31
33
|
run(): Promise<void>;
|
|
@@ -34,6 +36,13 @@ export default class BusinessPartners extends Command {
|
|
|
34
36
|
private runCamt053Import;
|
|
35
37
|
private runNestedImport;
|
|
36
38
|
private parseFilterValue;
|
|
39
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
40
|
+
private printPageSummary;
|
|
41
|
+
/**
|
|
42
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
43
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
44
|
+
*/
|
|
45
|
+
private warnShortPage;
|
|
37
46
|
private sanitizeOutput;
|
|
38
47
|
private getColumns;
|
|
39
48
|
private getValue;
|
|
@@ -5,8 +5,8 @@ import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCred
|
|
|
5
5
|
const HAS_IMPORT = true;
|
|
6
6
|
const HAS_EXPORT = true;
|
|
7
7
|
const HAS_CAMT053 = false;
|
|
8
|
-
const NESTED_IMPORTS = ["notes", "files", "contacts", "contacts-notes"];
|
|
9
|
-
const SUBCOMMANDS = [...["list", "create", "match-candidates", "get", "update", "delete", "merge", "activate", "get-favicon", "update-favicon", "trigger-favicon-backfill", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download", "list-contacts", "create-contacts", "get-contacts", "update-contacts", "delete-contacts", "list-contacts-notes", "create-contacts-notes", "get-contacts-notes", "update-contacts-notes", "delete-contacts-notes"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
8
|
+
const NESTED_IMPORTS = ["notes", "files", "contacts", "contacts-notes", "beneficiary-accounts"];
|
|
9
|
+
const SUBCOMMANDS = [...["list", "create", "match-candidates", "get", "update", "delete", "merge", "activate", "get-favicon", "update-favicon", "trigger-favicon-backfill", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download", "list-contacts", "create-contacts", "get-contacts", "update-contacts", "delete-contacts", "list-contacts-notes", "create-contacts-notes", "get-contacts-notes", "update-contacts-notes", "delete-contacts-notes", "list-beneficiary-accounts", "create-beneficiary-accounts", "get-beneficiary-accounts", "update-beneficiary-accounts", "delete-beneficiary-accounts", "beneficiary-accounts-approve", "beneficiary-accounts-retire", "beneficiary-accounts-reactivate", "beneficiary-accounts-default"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
|
|
10
10
|
const ENDPOINTS = {
|
|
11
11
|
'list': { method: 'GET', path: '/v1/business-partners', summary: 'Get all business partners with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
12
12
|
'create': { method: 'POST', path: '/v1/business-partners', summary: 'Create a new business partner', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['salesOrderRecipientCc', 'salesOrderRecipientBcc', 'salesInvoiceRecipientCc', 'salesInvoiceRecipientBcc', 'deliveryNoteRecipientCc', 'deliveryNoteRecipientBcc', 'dunningRecipientCc', 'dunningRecipientBcc', 'contacts', 'tagIds', 'tagCodes', 'salesEarlyPaymentDiscounts', 'purchaseEarlyPaymentDiscounts', 'notes'] },
|
|
@@ -40,6 +40,15 @@ const ENDPOINTS = {
|
|
|
40
40
|
'get-contacts-notes': { method: 'GET', path: '/v1/business-partners/contacts/{contactId}/notes/{noteId}', summary: 'Get a specific note for a contact', pathParams: ['contactId', 'noteId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
41
41
|
'update-contacts-notes': { method: 'PATCH', path: '/v1/business-partners/contacts/{contactId}/notes/{noteId}', summary: 'Update a note for a contact', pathParams: ['contactId', 'noteId'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
42
42
|
'delete-contacts-notes': { method: 'DELETE', path: '/v1/business-partners/contacts/{contactId}/notes/{noteId}', summary: 'Delete a note from a contact', pathParams: ['contactId', 'noteId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
43
|
+
'list-beneficiary-accounts': { method: 'GET', path: '/v1/business-partners/{businessPartnerId}/beneficiary-accounts', summary: 'List the beneficiary bank accounts of a business partner', pathParams: ['businessPartnerId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
44
|
+
'create-beneficiary-accounts': { method: 'POST', path: '/v1/business-partners/{businessPartnerId}/beneficiary-accounts', summary: 'Store a new beneficiary bank account (status NEW)', pathParams: ['businessPartnerId'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
45
|
+
'get-beneficiary-accounts': { method: 'GET', path: '/v1/business-partners/{businessPartnerId}/beneficiary-accounts/{id}', summary: 'Get one beneficiary bank account of a business partner', pathParams: ['businessPartnerId', 'id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
46
|
+
'update-beneficiary-accounts': { method: 'PATCH', path: '/v1/business-partners/{businessPartnerId}/beneficiary-accounts/{id}', summary: 'Edit a beneficiary bank account', pathParams: ['businessPartnerId', 'id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
47
|
+
'delete-beneficiary-accounts': { method: 'DELETE', path: '/v1/business-partners/{businessPartnerId}/beneficiary-accounts/{id}', summary: 'Delete a beneficiary bank account', pathParams: ['businessPartnerId', 'id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
48
|
+
'beneficiary-accounts-approve': { method: 'POST', path: '/v1/business-partners/{businessPartnerId}/beneficiary-accounts/{id}/approve', summary: 'Approve a beneficiary bank account', pathParams: ['businessPartnerId', 'id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
49
|
+
'beneficiary-accounts-retire': { method: 'POST', path: '/v1/business-partners/{businessPartnerId}/beneficiary-accounts/{id}/retire', summary: 'Retire a beneficiary bank account; clears its default flag', pathParams: ['businessPartnerId', 'id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
50
|
+
'beneficiary-accounts-reactivate': { method: 'POST', path: '/v1/business-partners/{businessPartnerId}/beneficiary-accounts/{id}/reactivate', summary: 'Reactivate a retired account: NEW again, both approvals cleared', pathParams: ['businessPartnerId', 'id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
51
|
+
'beneficiary-accounts-default': { method: 'POST', path: '/v1/business-partners/{businessPartnerId}/beneficiary-accounts/{id}/default', summary: 'Make this account the partner default; the previous one is unset', pathParams: ['businessPartnerId', 'id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
|
|
43
52
|
};
|
|
44
53
|
export default class BusinessPartners extends Command {
|
|
45
54
|
static description = 'Manage business partners';
|
|
@@ -66,6 +75,7 @@ export default class BusinessPartners extends Command {
|
|
|
66
75
|
'note-id': Flags.string({ description: 'Path param: noteId' }),
|
|
67
76
|
'file-id': Flags.string({ description: 'Path param: fileId' }),
|
|
68
77
|
'business-partner-id': Flags.string({ description: 'Path param: businessPartnerId' }),
|
|
78
|
+
'id': Flags.string({ description: 'Path param: id' }),
|
|
69
79
|
page: Flags.string({ description: 'Page number' }),
|
|
70
80
|
limit: Flags.string({ description: 'Items per page' }),
|
|
71
81
|
include: Flags.string({ description: 'Relations to include' }),
|
|
@@ -75,6 +85,7 @@ export default class BusinessPartners extends Command {
|
|
|
75
85
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
76
86
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
77
87
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
88
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
78
89
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
79
90
|
};
|
|
80
91
|
async run() {
|
|
@@ -367,9 +378,15 @@ export default class BusinessPartners extends Command {
|
|
|
367
378
|
}
|
|
368
379
|
catch { /* keep as string */ }
|
|
369
380
|
}
|
|
370
|
-
//
|
|
381
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
382
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
383
|
+
// dropping it silently let a script read one page as the whole result
|
|
384
|
+
// (AderisERP/product#61).
|
|
385
|
+
let envelope;
|
|
371
386
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
372
|
-
|
|
387
|
+
const page = output;
|
|
388
|
+
envelope = page;
|
|
389
|
+
output = page.data;
|
|
373
390
|
}
|
|
374
391
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
375
392
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -386,12 +403,24 @@ export default class BusinessPartners extends Command {
|
|
|
386
403
|
output = this.sanitizeOutput(output);
|
|
387
404
|
}
|
|
388
405
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
389
|
-
if (
|
|
406
|
+
if (envelope)
|
|
407
|
+
this.warnShortPage(envelope, flags.limit);
|
|
408
|
+
if (flags.csv || flags.output === 'csv') {
|
|
390
409
|
this.printCsv(output, fieldList);
|
|
391
|
-
|
|
410
|
+
}
|
|
411
|
+
else if (flags.table || flags.output === 'table') {
|
|
392
412
|
this.printTable(output, fieldList);
|
|
393
|
-
|
|
413
|
+
if (envelope)
|
|
414
|
+
this.printPageSummary(envelope);
|
|
415
|
+
}
|
|
416
|
+
else if (envelope && flags.meta) {
|
|
417
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
418
|
+
// a bare array so existing scripts are unaffected.
|
|
419
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
394
422
|
this.log(JSON.stringify(output, null, 2));
|
|
423
|
+
}
|
|
395
424
|
}
|
|
396
425
|
catch (error) {
|
|
397
426
|
if (error instanceof ApiError) {
|
|
@@ -1020,6 +1049,34 @@ export default class BusinessPartners extends Command {
|
|
|
1020
1049
|
return `\$${op}`;
|
|
1021
1050
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
1022
1051
|
}
|
|
1052
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1053
|
+
printPageSummary(envelope) {
|
|
1054
|
+
const meta = envelope.meta;
|
|
1055
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1056
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1057
|
+
this.log(`
|
|
1058
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1059
|
+
}
|
|
1060
|
+
for (const total of envelope.totals ?? []) {
|
|
1061
|
+
const { currency, ...sums } = total;
|
|
1062
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1063
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
/**
|
|
1067
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1068
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1069
|
+
*/
|
|
1070
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1071
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1072
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1073
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1074
|
+
return;
|
|
1075
|
+
const pages = envelope.meta?.totalPages;
|
|
1076
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1077
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1078
|
+
`);
|
|
1079
|
+
}
|
|
1023
1080
|
sanitizeOutput(data) {
|
|
1024
1081
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1025
1082
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
package/dist/commands/chat.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export default class Chat extends Command {
|
|
|
23
23
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
24
|
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
25
|
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
|
+
meta: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
27
|
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
27
28
|
};
|
|
28
29
|
run(): Promise<void>;
|
|
@@ -31,6 +32,13 @@ export default class Chat extends Command {
|
|
|
31
32
|
private runCamt053Import;
|
|
32
33
|
private runNestedImport;
|
|
33
34
|
private parseFilterValue;
|
|
35
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
36
|
+
private printPageSummary;
|
|
37
|
+
/**
|
|
38
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
39
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
40
|
+
*/
|
|
41
|
+
private warnShortPage;
|
|
34
42
|
private sanitizeOutput;
|
|
35
43
|
private getColumns;
|
|
36
44
|
private getValue;
|
package/dist/commands/chat.js
CHANGED
|
@@ -45,6 +45,7 @@ export default class Chat extends Command {
|
|
|
45
45
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
46
46
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
47
47
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
48
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
48
49
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
49
50
|
};
|
|
50
51
|
async run() {
|
|
@@ -337,9 +338,15 @@ export default class Chat extends Command {
|
|
|
337
338
|
}
|
|
338
339
|
catch { /* keep as string */ }
|
|
339
340
|
}
|
|
340
|
-
//
|
|
341
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
342
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
343
|
+
// dropping it silently let a script read one page as the whole result
|
|
344
|
+
// (AderisERP/product#61).
|
|
345
|
+
let envelope;
|
|
341
346
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
342
|
-
|
|
347
|
+
const page = output;
|
|
348
|
+
envelope = page;
|
|
349
|
+
output = page.data;
|
|
343
350
|
}
|
|
344
351
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
345
352
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -356,12 +363,24 @@ export default class Chat extends Command {
|
|
|
356
363
|
output = this.sanitizeOutput(output);
|
|
357
364
|
}
|
|
358
365
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
359
|
-
if (
|
|
366
|
+
if (envelope)
|
|
367
|
+
this.warnShortPage(envelope, flags.limit);
|
|
368
|
+
if (flags.csv || flags.output === 'csv') {
|
|
360
369
|
this.printCsv(output, fieldList);
|
|
361
|
-
|
|
370
|
+
}
|
|
371
|
+
else if (flags.table || flags.output === 'table') {
|
|
362
372
|
this.printTable(output, fieldList);
|
|
363
|
-
|
|
373
|
+
if (envelope)
|
|
374
|
+
this.printPageSummary(envelope);
|
|
375
|
+
}
|
|
376
|
+
else if (envelope && flags.meta) {
|
|
377
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
378
|
+
// a bare array so existing scripts are unaffected.
|
|
379
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
364
382
|
this.log(JSON.stringify(output, null, 2));
|
|
383
|
+
}
|
|
365
384
|
}
|
|
366
385
|
catch (error) {
|
|
367
386
|
if (error instanceof ApiError) {
|
|
@@ -990,6 +1009,34 @@ export default class Chat extends Command {
|
|
|
990
1009
|
return `\$${op}`;
|
|
991
1010
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
992
1011
|
}
|
|
1012
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1013
|
+
printPageSummary(envelope) {
|
|
1014
|
+
const meta = envelope.meta;
|
|
1015
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1016
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1017
|
+
this.log(`
|
|
1018
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1019
|
+
}
|
|
1020
|
+
for (const total of envelope.totals ?? []) {
|
|
1021
|
+
const { currency, ...sums } = total;
|
|
1022
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1023
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
/**
|
|
1027
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1028
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1029
|
+
*/
|
|
1030
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1031
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1032
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1033
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1034
|
+
return;
|
|
1035
|
+
const pages = envelope.meta?.totalPages;
|
|
1036
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1037
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1038
|
+
`);
|
|
1039
|
+
}
|
|
993
1040
|
sanitizeOutput(data) {
|
|
994
1041
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
995
1042
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -26,6 +26,7 @@ export default class CreditCardAccounts extends Command {
|
|
|
26
26
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
27
27
|
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
28
28
|
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
29
|
+
meta: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
29
30
|
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
30
31
|
};
|
|
31
32
|
run(): Promise<void>;
|
|
@@ -34,6 +35,13 @@ export default class CreditCardAccounts extends Command {
|
|
|
34
35
|
private runCamt053Import;
|
|
35
36
|
private runNestedImport;
|
|
36
37
|
private parseFilterValue;
|
|
38
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
39
|
+
private printPageSummary;
|
|
40
|
+
/**
|
|
41
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
42
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
43
|
+
*/
|
|
44
|
+
private warnShortPage;
|
|
37
45
|
private sanitizeOutput;
|
|
38
46
|
private getColumns;
|
|
39
47
|
private getValue;
|
|
@@ -63,6 +63,7 @@ export default class CreditCardAccounts extends Command {
|
|
|
63
63
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
64
64
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
65
65
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
66
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
66
67
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
67
68
|
};
|
|
68
69
|
async run() {
|
|
@@ -355,9 +356,15 @@ export default class CreditCardAccounts extends Command {
|
|
|
355
356
|
}
|
|
356
357
|
catch { /* keep as string */ }
|
|
357
358
|
}
|
|
358
|
-
//
|
|
359
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
360
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
361
|
+
// dropping it silently let a script read one page as the whole result
|
|
362
|
+
// (AderisERP/product#61).
|
|
363
|
+
let envelope;
|
|
359
364
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
360
|
-
|
|
365
|
+
const page = output;
|
|
366
|
+
envelope = page;
|
|
367
|
+
output = page.data;
|
|
361
368
|
}
|
|
362
369
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
363
370
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -374,12 +381,24 @@ export default class CreditCardAccounts extends Command {
|
|
|
374
381
|
output = this.sanitizeOutput(output);
|
|
375
382
|
}
|
|
376
383
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
377
|
-
if (
|
|
384
|
+
if (envelope)
|
|
385
|
+
this.warnShortPage(envelope, flags.limit);
|
|
386
|
+
if (flags.csv || flags.output === 'csv') {
|
|
378
387
|
this.printCsv(output, fieldList);
|
|
379
|
-
|
|
388
|
+
}
|
|
389
|
+
else if (flags.table || flags.output === 'table') {
|
|
380
390
|
this.printTable(output, fieldList);
|
|
381
|
-
|
|
391
|
+
if (envelope)
|
|
392
|
+
this.printPageSummary(envelope);
|
|
393
|
+
}
|
|
394
|
+
else if (envelope && flags.meta) {
|
|
395
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
396
|
+
// a bare array so existing scripts are unaffected.
|
|
397
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
382
400
|
this.log(JSON.stringify(output, null, 2));
|
|
401
|
+
}
|
|
383
402
|
}
|
|
384
403
|
catch (error) {
|
|
385
404
|
if (error instanceof ApiError) {
|
|
@@ -1008,6 +1027,34 @@ export default class CreditCardAccounts extends Command {
|
|
|
1008
1027
|
return `\$${op}`;
|
|
1009
1028
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
1010
1029
|
}
|
|
1030
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1031
|
+
printPageSummary(envelope) {
|
|
1032
|
+
const meta = envelope.meta;
|
|
1033
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1034
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1035
|
+
this.log(`
|
|
1036
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1037
|
+
}
|
|
1038
|
+
for (const total of envelope.totals ?? []) {
|
|
1039
|
+
const { currency, ...sums } = total;
|
|
1040
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1041
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
/**
|
|
1045
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1046
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1047
|
+
*/
|
|
1048
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1049
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1050
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1051
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1052
|
+
return;
|
|
1053
|
+
const pages = envelope.meta?.totalPages;
|
|
1054
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1055
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1056
|
+
`);
|
|
1057
|
+
}
|
|
1011
1058
|
sanitizeOutput(data) {
|
|
1012
1059
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1013
1060
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -26,6 +26,7 @@ export default class DeliveryNotes extends Command {
|
|
|
26
26
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
27
27
|
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
28
28
|
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
29
|
+
meta: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
29
30
|
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
30
31
|
};
|
|
31
32
|
run(): Promise<void>;
|
|
@@ -34,6 +35,13 @@ export default class DeliveryNotes extends Command {
|
|
|
34
35
|
private runCamt053Import;
|
|
35
36
|
private runNestedImport;
|
|
36
37
|
private parseFilterValue;
|
|
38
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
39
|
+
private printPageSummary;
|
|
40
|
+
/**
|
|
41
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
42
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
43
|
+
*/
|
|
44
|
+
private warnShortPage;
|
|
37
45
|
private sanitizeOutput;
|
|
38
46
|
private getColumns;
|
|
39
47
|
private getValue;
|
|
@@ -76,6 +76,7 @@ export default class DeliveryNotes extends Command {
|
|
|
76
76
|
query: Flags.string({ description: 'Additional query params as JSON' }),
|
|
77
77
|
fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
|
|
78
78
|
sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
|
|
79
|
+
meta: Flags.boolean({ description: 'Keep the API envelope in JSON output: data plus page, totals and sums' }),
|
|
79
80
|
'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
|
|
80
81
|
};
|
|
81
82
|
async run() {
|
|
@@ -368,9 +369,15 @@ export default class DeliveryNotes extends Command {
|
|
|
368
369
|
}
|
|
369
370
|
catch { /* keep as string */ }
|
|
370
371
|
}
|
|
371
|
-
//
|
|
372
|
+
// A paginated answer is { data, meta, links, totals }. The records are
|
|
373
|
+
// unwrapped for output, but what the API said about the page is kept:
|
|
374
|
+
// dropping it silently let a script read one page as the whole result
|
|
375
|
+
// (AderisERP/product#61).
|
|
376
|
+
let envelope;
|
|
372
377
|
if (output && typeof output === 'object' && !Array.isArray(output) && 'data' in output && Array.isArray(output.data)) {
|
|
373
|
-
|
|
378
|
+
const page = output;
|
|
379
|
+
envelope = page;
|
|
380
|
+
output = page.data;
|
|
374
381
|
}
|
|
375
382
|
// For table/csv on non-array responses, auto-extract the primary array
|
|
376
383
|
// e.g., { payments: [...], total: 3 } → extract payments array
|
|
@@ -387,12 +394,24 @@ export default class DeliveryNotes extends Command {
|
|
|
387
394
|
output = this.sanitizeOutput(output);
|
|
388
395
|
}
|
|
389
396
|
const fieldList = flags.fields?.split(',').map(f => f.trim());
|
|
390
|
-
if (
|
|
397
|
+
if (envelope)
|
|
398
|
+
this.warnShortPage(envelope, flags.limit);
|
|
399
|
+
if (flags.csv || flags.output === 'csv') {
|
|
391
400
|
this.printCsv(output, fieldList);
|
|
392
|
-
|
|
401
|
+
}
|
|
402
|
+
else if (flags.table || flags.output === 'table') {
|
|
393
403
|
this.printTable(output, fieldList);
|
|
394
|
-
|
|
404
|
+
if (envelope)
|
|
405
|
+
this.printPageSummary(envelope);
|
|
406
|
+
}
|
|
407
|
+
else if (envelope && flags.meta) {
|
|
408
|
+
// The whole envelope, for a caller that asked for it; the default stays
|
|
409
|
+
// a bare array so existing scripts are unaffected.
|
|
410
|
+
this.log(JSON.stringify({ ...envelope, data: output }, null, 2));
|
|
411
|
+
}
|
|
412
|
+
else {
|
|
395
413
|
this.log(JSON.stringify(output, null, 2));
|
|
414
|
+
}
|
|
396
415
|
}
|
|
397
416
|
catch (error) {
|
|
398
417
|
if (error instanceof ApiError) {
|
|
@@ -1021,6 +1040,34 @@ export default class DeliveryNotes extends Command {
|
|
|
1021
1040
|
return `\$${op}`;
|
|
1022
1041
|
return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
|
|
1023
1042
|
}
|
|
1043
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
1044
|
+
printPageSummary(envelope) {
|
|
1045
|
+
const meta = envelope.meta;
|
|
1046
|
+
if (meta && typeof meta.currentPage === 'number' && typeof meta.totalPages === 'number') {
|
|
1047
|
+
const shown = Array.isArray(envelope.data) ? envelope.data.length : 0;
|
|
1048
|
+
this.log(`
|
|
1049
|
+
Page ${meta.currentPage}/${meta.totalPages} — ${shown} of ${meta.totalItems ?? '?'} records`);
|
|
1050
|
+
}
|
|
1051
|
+
for (const total of envelope.totals ?? []) {
|
|
1052
|
+
const { currency, ...sums } = total;
|
|
1053
|
+
const parts = Object.entries(sums).map(([column, value]) => `${column} ${value}`).join(', ');
|
|
1054
|
+
this.log(`Total ${currency ?? ''}: ${parts}`.trim());
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
1059
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
1060
|
+
*/
|
|
1061
|
+
warnShortPage(envelope, requestedLimit) {
|
|
1062
|
+
const asked = requestedLimit === undefined ? undefined : Number(requestedLimit);
|
|
1063
|
+
const perPage = envelope.meta?.itemsPerPage;
|
|
1064
|
+
if (asked === undefined || Number.isNaN(asked) || typeof perPage !== 'number' || perPage >= asked)
|
|
1065
|
+
return;
|
|
1066
|
+
const pages = envelope.meta?.totalPages;
|
|
1067
|
+
const more = typeof pages === 'number' && pages > 1 ? ` Use --page, or the export action for every page.` : '';
|
|
1068
|
+
process.stderr.write(`! Asked for ${asked} records per page; the API returned at most ${perPage}.${more}
|
|
1069
|
+
`);
|
|
1070
|
+
}
|
|
1024
1071
|
sanitizeOutput(data) {
|
|
1025
1072
|
const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
|
|
1026
1073
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -23,6 +23,7 @@ export default class DunningConfigs extends Command {
|
|
|
23
23
|
query: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
24
|
fields: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
25
|
sanitize: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
|
+
meta: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
27
|
'show-http-request': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
27
28
|
};
|
|
28
29
|
run(): Promise<void>;
|
|
@@ -31,6 +32,13 @@ export default class DunningConfigs extends Command {
|
|
|
31
32
|
private runCamt053Import;
|
|
32
33
|
private runNestedImport;
|
|
33
34
|
private parseFilterValue;
|
|
35
|
+
/** The page line under a table: which page, how many, and any sums the API returned. */
|
|
36
|
+
private printPageSummary;
|
|
37
|
+
/**
|
|
38
|
+
* The API caps how many records a page may hold. Asking for more and getting
|
|
39
|
+
* fewer looks like "that is everything" unless it is said out loud.
|
|
40
|
+
*/
|
|
41
|
+
private warnShortPage;
|
|
34
42
|
private sanitizeOutput;
|
|
35
43
|
private getColumns;
|
|
36
44
|
private getValue;
|