@aderis-erp/cli 1.0.14 → 1.0.15

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.
Files changed (83) hide show
  1. package/dist/commands/access-groups.js +17 -17
  2. package/dist/commands/account-transaction-allocations.js +17 -17
  3. package/dist/commands/account-transactions.js +19 -19
  4. package/dist/commands/accounts.js +19 -19
  5. package/dist/commands/agent-platform.js +19 -18
  6. package/dist/commands/analytics.d.ts +40 -0
  7. package/dist/commands/{documents.js → analytics.js} +29 -39
  8. package/dist/commands/audit-log.js +17 -17
  9. package/dist/commands/auth/login.js +11 -2
  10. package/dist/commands/auth/logout.d.ts +2 -0
  11. package/dist/commands/auth/logout.js +19 -6
  12. package/dist/commands/auth/status.js +26 -12
  13. package/dist/commands/auth/tenant.js +12 -3
  14. package/dist/commands/auth.js +32 -17
  15. package/dist/commands/bank-accounts.js +17 -17
  16. package/dist/commands/bank-integrations.js +17 -17
  17. package/dist/commands/business-partners.js +25 -22
  18. package/dist/commands/chat.js +17 -17
  19. package/dist/commands/config/add.d.ts +9 -0
  20. package/dist/commands/config/add.js +64 -2
  21. package/dist/commands/config/current.js +9 -4
  22. package/dist/commands/config/list.js +9 -4
  23. package/dist/commands/config/set-api-key.d.ts +10 -0
  24. package/dist/commands/config/set-api-key.js +49 -0
  25. package/dist/commands/config/use.js +3 -4
  26. package/dist/commands/credit-card-accounts.js +17 -17
  27. package/dist/commands/delivery-notes.js +22 -21
  28. package/dist/commands/dunning-configs.js +17 -17
  29. package/dist/commands/dunning-reminders.js +17 -17
  30. package/dist/commands/dunning-runs.js +17 -17
  31. package/dist/commands/email-transactions.js +17 -17
  32. package/dist/commands/employees.js +19 -19
  33. package/dist/commands/entity-configurations.js +17 -17
  34. package/dist/commands/event-processor-mappings.js +17 -17
  35. package/dist/commands/{documents.d.ts → files.d.ts} +1 -1
  36. package/dist/commands/{files-internal.js → files.js} +35 -29
  37. package/dist/commands/health.js +17 -17
  38. package/dist/commands/inbox.js +17 -17
  39. package/dist/commands/integrations.js +17 -17
  40. package/dist/commands/item-categories.js +17 -17
  41. package/dist/commands/items.js +19 -19
  42. package/dist/commands/journal-lines.js +17 -17
  43. package/dist/commands/journals.js +21 -20
  44. package/dist/commands/ledgers.js +21 -18
  45. package/dist/commands/office-locations.js +17 -17
  46. package/dist/commands/payment-methods.js +17 -17
  47. package/dist/commands/payment-runs.js +19 -18
  48. package/dist/commands/payment-terms.js +17 -17
  49. package/dist/commands/payments.js +17 -17
  50. package/dist/commands/price-lists.js +17 -17
  51. package/dist/commands/processor-mappings.js +17 -17
  52. package/dist/commands/processors.js +17 -17
  53. package/dist/commands/purchase-order-types.js +17 -17
  54. package/dist/commands/purchase-orders.d.ts +1 -0
  55. package/dist/commands/purchase-orders.js +28 -21
  56. package/dist/commands/reports.js +17 -17
  57. package/dist/commands/salary-types.js +17 -17
  58. package/dist/commands/sales-invoices.js +27 -25
  59. package/dist/commands/sales-orders.js +19 -19
  60. package/dist/commands/saved-views.js +17 -17
  61. package/dist/commands/scheduled-processor-mappings.js +17 -17
  62. package/dist/commands/schedules.js +17 -17
  63. package/dist/commands/switch.js +10 -3
  64. package/dist/commands/{files-internal.d.ts → tag-configurations.d.ts} +1 -1
  65. package/dist/commands/tag-configurations.js +1178 -0
  66. package/dist/commands/tags.js +17 -17
  67. package/dist/commands/tax-codes.js +17 -17
  68. package/dist/commands/tax-matrix.js +17 -17
  69. package/dist/commands/tenants.js +17 -17
  70. package/dist/commands/text-templates.js +17 -17
  71. package/dist/commands/tools.js +17 -17
  72. package/dist/commands/vat-declarations.js +17 -17
  73. package/dist/commands/vendor-invoices.js +21 -21
  74. package/dist/commands/webhooks.js +17 -17
  75. package/dist/commands/workflows.js +17 -17
  76. package/dist/lib/api-client.js +11 -6
  77. package/dist/lib/auth.d.ts +8 -0
  78. package/dist/lib/auth.js +51 -7
  79. package/dist/lib/base-api-command.js +6 -4
  80. package/dist/lib/config.d.ts +31 -1
  81. package/dist/lib/config.js +31 -0
  82. package/oclif.manifest.json +729 -247
  83. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
2
  import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
3
- import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
3
+ import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
4
4
  // Add 'import' action if both create and update exist
5
5
  const HAS_IMPORT = true;
6
6
  const HAS_EXPORT = true;
@@ -29,7 +29,7 @@ export default class PurchaseOrderTypes extends Command {
29
29
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
30
30
  };
31
31
  static flags = {
32
- context: Flags.string({ char: 'c', description: 'Context to use' }),
32
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
33
33
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
34
34
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
35
35
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -101,9 +101,9 @@ export default class PurchaseOrderTypes extends Command {
101
101
  }
102
102
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
103
103
  if (!context)
104
- this.error('No context configured. Run: aderis auth login --new');
105
- if (!context.tokens)
106
- this.error('Not logged in. Run: aderis auth login');
104
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
105
+ if (!hasCredentials(context))
106
+ this.error(missingCredentialsMessage(context));
107
107
  const queryParams = {};
108
108
  if (flags.page)
109
109
  queryParams.page = flags.page;
@@ -346,9 +346,9 @@ export default class PurchaseOrderTypes extends Command {
346
346
  async runImport(flags) {
347
347
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
348
348
  if (!context)
349
- this.error('No context configured. Run: aderis auth login --new');
350
- if (!context.tokens)
351
- this.error('Not logged in. Run: aderis auth login');
349
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
350
+ if (!hasCredentials(context))
351
+ this.error(missingCredentialsMessage(context));
352
352
  // Get data from file, --data, or --set flags
353
353
  let items = [];
354
354
  if (flags.file) {
@@ -558,9 +558,9 @@ export default class PurchaseOrderTypes extends Command {
558
558
  async runExport(flags) {
559
559
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
560
560
  if (!context)
561
- this.error('No context configured. Run: aderis auth login --new');
562
- if (!context.tokens)
563
- this.error('Not logged in. Run: aderis auth login');
561
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
562
+ if (!hasCredentials(context))
563
+ this.error(missingCredentialsMessage(context));
564
564
  const listEndpoint = ENDPOINTS['list'];
565
565
  if (!listEndpoint)
566
566
  this.error('Export requires a list endpoint');
@@ -652,9 +652,9 @@ export default class PurchaseOrderTypes extends Command {
652
652
  async runCamt053Import(flags) {
653
653
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
654
654
  if (!context)
655
- this.error('No context configured. Run: aderis auth login --new');
656
- if (!context.tokens)
657
- this.error('Not logged in. Run: aderis auth login');
655
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
656
+ if (!hasCredentials(context))
657
+ this.error(missingCredentialsMessage(context));
658
658
  if (!flags.file) {
659
659
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
660
660
  }
@@ -742,9 +742,9 @@ export default class PurchaseOrderTypes extends Command {
742
742
  }
743
743
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
744
744
  if (!context)
745
- this.error('No context configured. Run: aderis auth login --new');
746
- if (!context.tokens)
747
- this.error('Not logged in. Run: aderis auth login');
745
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
746
+ if (!hasCredentials(context))
747
+ this.error(missingCredentialsMessage(context));
748
748
  // Get data from file, --data, or --set flags
749
749
  let items = [];
750
750
  if (flags.file) {
@@ -16,6 +16,7 @@ export default class PurchaseOrders extends Command {
16
16
  set: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
17
  'line-item-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
18
  'note-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
+ 'file-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
20
  page: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
21
  limit: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
21
22
  include: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
@@ -1,17 +1,17 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
2
  import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
3
- import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
3
+ import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
4
4
  // Add 'import' action if both create and update exist
5
5
  const HAS_IMPORT = true;
6
6
  const HAS_EXPORT = true;
7
7
  const HAS_CAMT053 = false;
8
- const NESTED_IMPORTS = ["line-items", "notes"];
9
- const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "submit", "approve", "decline", "cancel", "create-line-items", "update-line-items", "delete-line-items", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
8
+ const NESTED_IMPORTS = ["line-items", "notes", "files"];
9
+ const SUBCOMMANDS = [...["list", "create", "get", "update", "delete", "submit", "approve", "decline", "cancel", "create-line-items", "update-line-items", "delete-line-items", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
10
10
  const ENDPOINTS = {
11
11
  'list': { method: 'GET', path: '/v1/purchase-orders', summary: 'Get all purchase orders with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
12
- 'create': { method: 'POST', path: '/v1/purchase-orders', summary: 'Create a new purchase order', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['tagIds', 'notes', 'discounts', 'lineItems'] },
12
+ 'create': { method: 'POST', path: '/v1/purchase-orders', summary: 'Create a new purchase order', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['tagIds', 'tagCodes', 'files', 'notes', 'discounts', 'lineItems'] },
13
13
  'get': { method: 'GET', path: '/v1/purchase-orders/{id}', summary: 'Get a purchase order by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
14
- 'update': { method: 'PATCH', path: '/v1/purchase-orders/{id}', summary: 'Update a purchase order', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['tagIds', 'notes', 'discounts', 'lineItems'] },
14
+ 'update': { method: 'PATCH', path: '/v1/purchase-orders/{id}', summary: 'Update a purchase order', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['tagIds', 'tagCodes', 'files', 'notes', 'discounts', 'lineItems', 'removeFileIds'] },
15
15
  'delete': { method: 'DELETE', path: '/v1/purchase-orders/{id}', summary: 'Delete a purchase order', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
16
16
  'submit': { method: 'POST', path: '/v1/purchase-orders/{id}/submit', summary: 'Submit order for approval (DRAFT → PENDING_APPROVAL)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
17
17
  'approve': { method: 'POST', path: '/v1/purchase-orders/{id}/approve', summary: 'Approve order (PENDING_APPROVAL → APPROVED). Generates order number if missing.', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
@@ -25,6 +25,12 @@ const ENDPOINTS = {
25
25
  'get-notes': { method: 'GET', path: '/v1/purchase-orders/{purchaseOrderId}/notes/{noteId}', summary: 'Get a specific note for a purchase order', pathParams: ['purchaseOrderId', 'noteId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
26
26
  'update-notes': { method: 'PATCH', path: '/v1/purchase-orders/{purchaseOrderId}/notes/{noteId}', summary: 'Update a note for a purchase order', pathParams: ['purchaseOrderId', 'noteId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
27
27
  'delete-notes': { method: 'DELETE', path: '/v1/purchase-orders/{purchaseOrderId}/notes/{noteId}', summary: 'Delete a note from a purchase order', pathParams: ['purchaseOrderId', 'noteId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
28
+ 'list-files': { method: 'GET', path: '/v1/purchase-orders/{parentId}/files', summary: 'List file attachments for a purchase order', pathParams: ['parentId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
29
+ 'create-files': { method: 'POST', path: '/v1/purchase-orders/{parentId}/files', summary: 'Upload a file attachment to a purchase order', pathParams: ['parentId'], hasBody: false, isMultipart: true, isBinaryResponse: false, bodyArrayFields: [] },
30
+ 'get-files': { method: 'GET', path: '/v1/purchase-orders/{parentId}/files/{fileId}', summary: 'Get a file attachment for a purchase order', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
31
+ 'update-files': { method: 'PATCH', path: '/v1/purchase-orders/{parentId}/files/{fileId}', summary: 'Update file attachment metadata for a purchase order', pathParams: ['parentId', 'fileId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
32
+ 'delete-files': { method: 'DELETE', path: '/v1/purchase-orders/{parentId}/files/{fileId}', summary: 'Delete a file attachment from a purchase order', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
33
+ 'files-download': { method: 'GET', path: '/v1/purchase-orders/{parentId}/files/{fileId}/download', summary: 'Download a file attachment from a purchase order', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
28
34
  };
29
35
  export default class PurchaseOrders extends Command {
30
36
  static description = 'Manage purchase orders';
@@ -41,7 +47,7 @@ export default class PurchaseOrders extends Command {
41
47
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
42
48
  };
43
49
  static flags = {
44
- context: Flags.string({ char: 'c', description: 'Context to use' }),
50
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
45
51
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
46
52
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
47
53
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -50,6 +56,7 @@ export default class PurchaseOrders extends Command {
50
56
  set: Flags.string({ char: 's', description: 'Set individual field (e.g. --set firstName=John)', multiple: true }),
51
57
  'line-item-id': Flags.string({ description: 'Path param: lineItemId' }),
52
58
  'note-id': Flags.string({ description: 'Path param: noteId' }),
59
+ 'file-id': Flags.string({ description: 'Path param: fileId' }),
53
60
  page: Flags.string({ description: 'Page number' }),
54
61
  limit: Flags.string({ description: 'Items per page' }),
55
62
  include: Flags.string({ description: 'Relations to include' }),
@@ -115,9 +122,9 @@ export default class PurchaseOrders extends Command {
115
122
  }
116
123
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
117
124
  if (!context)
118
- this.error('No context configured. Run: aderis auth login --new');
119
- if (!context.tokens)
120
- this.error('Not logged in. Run: aderis auth login');
125
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
126
+ if (!hasCredentials(context))
127
+ this.error(missingCredentialsMessage(context));
121
128
  const queryParams = {};
122
129
  if (flags.page)
123
130
  queryParams.page = flags.page;
@@ -360,9 +367,9 @@ export default class PurchaseOrders extends Command {
360
367
  async runImport(flags) {
361
368
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
362
369
  if (!context)
363
- this.error('No context configured. Run: aderis auth login --new');
364
- if (!context.tokens)
365
- this.error('Not logged in. Run: aderis auth login');
370
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
371
+ if (!hasCredentials(context))
372
+ this.error(missingCredentialsMessage(context));
366
373
  // Get data from file, --data, or --set flags
367
374
  let items = [];
368
375
  if (flags.file) {
@@ -572,9 +579,9 @@ export default class PurchaseOrders extends Command {
572
579
  async runExport(flags) {
573
580
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
574
581
  if (!context)
575
- this.error('No context configured. Run: aderis auth login --new');
576
- if (!context.tokens)
577
- this.error('Not logged in. Run: aderis auth login');
582
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
583
+ if (!hasCredentials(context))
584
+ this.error(missingCredentialsMessage(context));
578
585
  const listEndpoint = ENDPOINTS['list'];
579
586
  if (!listEndpoint)
580
587
  this.error('Export requires a list endpoint');
@@ -666,9 +673,9 @@ export default class PurchaseOrders extends Command {
666
673
  async runCamt053Import(flags) {
667
674
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
668
675
  if (!context)
669
- this.error('No context configured. Run: aderis auth login --new');
670
- if (!context.tokens)
671
- this.error('Not logged in. Run: aderis auth login');
676
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
677
+ if (!hasCredentials(context))
678
+ this.error(missingCredentialsMessage(context));
672
679
  if (!flags.file) {
673
680
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
674
681
  }
@@ -756,9 +763,9 @@ export default class PurchaseOrders extends Command {
756
763
  }
757
764
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
758
765
  if (!context)
759
- this.error('No context configured. Run: aderis auth login --new');
760
- if (!context.tokens)
761
- this.error('Not logged in. Run: aderis auth login');
766
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
767
+ if (!hasCredentials(context))
768
+ this.error(missingCredentialsMessage(context));
762
769
  // Get data from file, --data, or --set flags
763
770
  let items = [];
764
771
  if (flags.file) {
@@ -1,6 +1,6 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
2
  import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
3
- import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
3
+ import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
4
4
  // Add 'import' action if both create and update exist
5
5
  const HAS_IMPORT = false;
6
6
  const HAS_EXPORT = false;
@@ -22,7 +22,7 @@ export default class Reports extends Command {
22
22
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
23
23
  };
24
24
  static flags = {
25
- context: Flags.string({ char: 'c', description: 'Context to use' }),
25
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
26
26
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
27
27
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
28
28
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -94,9 +94,9 @@ export default class Reports extends Command {
94
94
  }
95
95
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
96
96
  if (!context)
97
- this.error('No context configured. Run: aderis auth login --new');
98
- if (!context.tokens)
99
- this.error('Not logged in. Run: aderis auth login');
97
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
98
+ if (!hasCredentials(context))
99
+ this.error(missingCredentialsMessage(context));
100
100
  const queryParams = {};
101
101
  if (flags.page)
102
102
  queryParams.page = flags.page;
@@ -339,9 +339,9 @@ export default class Reports extends Command {
339
339
  async runImport(flags) {
340
340
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
341
341
  if (!context)
342
- this.error('No context configured. Run: aderis auth login --new');
343
- if (!context.tokens)
344
- this.error('Not logged in. Run: aderis auth login');
342
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
343
+ if (!hasCredentials(context))
344
+ this.error(missingCredentialsMessage(context));
345
345
  // Get data from file, --data, or --set flags
346
346
  let items = [];
347
347
  if (flags.file) {
@@ -551,9 +551,9 @@ export default class Reports extends Command {
551
551
  async runExport(flags) {
552
552
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
553
553
  if (!context)
554
- this.error('No context configured. Run: aderis auth login --new');
555
- if (!context.tokens)
556
- this.error('Not logged in. Run: aderis auth login');
554
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
555
+ if (!hasCredentials(context))
556
+ this.error(missingCredentialsMessage(context));
557
557
  const listEndpoint = ENDPOINTS['list'];
558
558
  if (!listEndpoint)
559
559
  this.error('Export requires a list endpoint');
@@ -645,9 +645,9 @@ export default class Reports extends Command {
645
645
  async runCamt053Import(flags) {
646
646
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
647
647
  if (!context)
648
- this.error('No context configured. Run: aderis auth login --new');
649
- if (!context.tokens)
650
- this.error('Not logged in. Run: aderis auth login');
648
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
649
+ if (!hasCredentials(context))
650
+ this.error(missingCredentialsMessage(context));
651
651
  if (!flags.file) {
652
652
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
653
653
  }
@@ -735,9 +735,9 @@ export default class Reports extends Command {
735
735
  }
736
736
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
737
737
  if (!context)
738
- this.error('No context configured. Run: aderis auth login --new');
739
- if (!context.tokens)
740
- this.error('Not logged in. Run: aderis auth login');
738
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
739
+ if (!hasCredentials(context))
740
+ this.error(missingCredentialsMessage(context));
741
741
  // Get data from file, --data, or --set flags
742
742
  let items = [];
743
743
  if (flags.file) {
@@ -1,6 +1,6 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
2
  import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
3
- import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
3
+ import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
4
4
  // Add 'import' action if both create and update exist
5
5
  const HAS_IMPORT = true;
6
6
  const HAS_EXPORT = true;
@@ -29,7 +29,7 @@ export default class SalaryTypes extends Command {
29
29
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
30
30
  };
31
31
  static flags = {
32
- context: Flags.string({ char: 'c', description: 'Context to use' }),
32
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
33
33
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
34
34
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
35
35
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -101,9 +101,9 @@ export default class SalaryTypes extends Command {
101
101
  }
102
102
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
103
103
  if (!context)
104
- this.error('No context configured. Run: aderis auth login --new');
105
- if (!context.tokens)
106
- this.error('Not logged in. Run: aderis auth login');
104
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
105
+ if (!hasCredentials(context))
106
+ this.error(missingCredentialsMessage(context));
107
107
  const queryParams = {};
108
108
  if (flags.page)
109
109
  queryParams.page = flags.page;
@@ -346,9 +346,9 @@ export default class SalaryTypes extends Command {
346
346
  async runImport(flags) {
347
347
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
348
348
  if (!context)
349
- this.error('No context configured. Run: aderis auth login --new');
350
- if (!context.tokens)
351
- this.error('Not logged in. Run: aderis auth login');
349
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
350
+ if (!hasCredentials(context))
351
+ this.error(missingCredentialsMessage(context));
352
352
  // Get data from file, --data, or --set flags
353
353
  let items = [];
354
354
  if (flags.file) {
@@ -558,9 +558,9 @@ export default class SalaryTypes extends Command {
558
558
  async runExport(flags) {
559
559
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
560
560
  if (!context)
561
- this.error('No context configured. Run: aderis auth login --new');
562
- if (!context.tokens)
563
- this.error('Not logged in. Run: aderis auth login');
561
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
562
+ if (!hasCredentials(context))
563
+ this.error(missingCredentialsMessage(context));
564
564
  const listEndpoint = ENDPOINTS['list'];
565
565
  if (!listEndpoint)
566
566
  this.error('Export requires a list endpoint');
@@ -652,9 +652,9 @@ export default class SalaryTypes extends Command {
652
652
  async runCamt053Import(flags) {
653
653
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
654
654
  if (!context)
655
- this.error('No context configured. Run: aderis auth login --new');
656
- if (!context.tokens)
657
- this.error('Not logged in. Run: aderis auth login');
655
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
656
+ if (!hasCredentials(context))
657
+ this.error(missingCredentialsMessage(context));
658
658
  if (!flags.file) {
659
659
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
660
660
  }
@@ -742,9 +742,9 @@ export default class SalaryTypes extends Command {
742
742
  }
743
743
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
744
744
  if (!context)
745
- this.error('No context configured. Run: aderis auth login --new');
746
- if (!context.tokens)
747
- this.error('Not logged in. Run: aderis auth login');
745
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
746
+ if (!hasCredentials(context))
747
+ this.error(missingCredentialsMessage(context));
748
748
  // Get data from file, --data, or --set flags
749
749
  let items = [];
750
750
  if (flags.file) {
@@ -1,32 +1,34 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
2
  import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
3
- import { getCurrentContext, getContext, getBaseUrls } from '../lib/config.js';
3
+ import { getCurrentContext, getContext, getBaseUrls, hasCredentials, missingCredentialsMessage } from '../lib/config.js';
4
4
  // Add 'import' action if both create and update exist
5
5
  const HAS_IMPORT = true;
6
6
  const HAS_EXPORT = true;
7
7
  const HAS_CAMT053 = false;
8
8
  const NESTED_IMPORTS = ["line-items", "notes", "files"];
9
- const SUBCOMMANDS = [...["list", "create", "create-migrated-invoice", "pdf", "get", "update", "delete", "approve", "match-sales-orders", "validate", "request-approval", "send", "send-resend", "cancel", "copy", "replace", "merge", "create-line-items", "line-items-from-sales-order", "update-line-items-reorder", "update-line-items", "delete-line-items", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
9
+ const SUBCOMMANDS = [...["list", "create", "create-migrated-invoice", "pdf", "get", "update", "delete", "approve", "match-sales-orders", "validate", "request-approval", "send", "send-resend", "cancel", "copy", "replace", "rebuild-journal", "merge", "create-line-items", "line-items-from-sales-order", "line-items-from-delivery-note", "update-line-items-reorder", "update-line-items", "delete-line-items", "list-notes", "create-notes", "get-notes", "update-notes", "delete-notes", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
10
10
  const ENDPOINTS = {
11
11
  'list': { method: 'GET', path: '/v1/sales-invoices', summary: 'Get all sales invoices with pagination', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
12
- 'create': { method: 'POST', path: '/v1/sales-invoices', summary: 'Create a new sales invoice', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'lineItems', 'discounts', 'files', 'notes', 'totalAmountByTaxRate', 'tagIds', 'invoiceEmailCc'] },
13
- 'create-migrated-invoice': { method: 'POST', path: '/v1/sales-invoices/create-migrated-invoice', summary: 'Create a sales invoice with explicit tax codes on line items (for data migration)', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['lineItems', 'files', 'notes', 'totalAmountByTaxRate', 'tagIds', 'invoiceEmailCc'] },
12
+ 'create': { method: 'POST', path: '/v1/sales-invoices', summary: 'Create a new sales invoice', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'lineItems', 'discounts', 'files', 'notes', 'totalAmountByTaxRate', 'tagIds', 'tagCodes', 'invoiceEmailCc'] },
13
+ 'create-migrated-invoice': { method: 'POST', path: '/v1/sales-invoices/create-migrated-invoice', summary: 'Create a sales invoice with explicit tax codes on line items (for data migration)', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['lineItems', 'files', 'notes', 'totalAmountByTaxRate', 'tagIds', 'tagCodes', 'invoiceEmailCc'] },
14
14
  'pdf': { method: 'GET', path: '/v1/sales-invoices/{id}/pdf', summary: 'Generate a PDF preview of a sales invoice', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
15
15
  'get': { method: 'GET', path: '/v1/sales-invoices/{id}', summary: 'Get a sales invoice by ID', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
16
- 'update': { method: 'PATCH', path: '/v1/sales-invoices/{id}', summary: 'Update a sales invoice', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'lineItems', 'discounts', 'files', 'notes', 'totalAmountByTaxRate', 'tagIds', 'invoiceEmailCc', 'removeFileIds'] },
16
+ 'update': { method: 'PATCH', path: '/v1/sales-invoices/{id}', summary: 'Update a sales invoice', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'lineItems', 'discounts', 'files', 'notes', 'totalAmountByTaxRate', 'tagIds', 'tagCodes', 'invoiceEmailCc', 'removeFileIds'] },
17
17
  'delete': { method: 'DELETE', path: '/v1/sales-invoices/{id}', summary: 'Delete a sales invoice', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
18
- 'approve': { method: 'POST', path: '/v1/sales-invoices/{id}/approve', summary: 'Approve a sales invoice from DRAFT or PENDING_APPROVAL status (generates invoice number and finalizes)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'lineItems', 'discounts', 'files', 'notes', 'totalAmountByTaxRate', 'tagIds', 'invoiceEmailCc', 'removeFileIds'] },
19
- 'match-sales-orders': { method: 'POST', path: '/v1/sales-invoices/{id}/match-sales-orders', summary: 'Match this invoice\'s lines to sales-order lines', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
20
- 'validate': { method: 'POST', path: '/v1/sales-invoices/{id}/validate', summary: 'Validate a sales invoice update without persisting changes', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'lineItems', 'discounts', 'files', 'notes', 'totalAmountByTaxRate', 'tagIds', 'invoiceEmailCc', 'removeFileIds'] },
18
+ 'approve': { method: 'POST', path: '/v1/sales-invoices/{id}/approve', summary: 'Approve a sales invoice from DRAFT or PENDING_APPROVAL status (generates invoice number and finalizes)', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'lineItems', 'discounts', 'files', 'notes', 'totalAmountByTaxRate', 'tagIds', 'tagCodes', 'invoiceEmailCc', 'removeFileIds'] },
19
+ 'match-sales-orders': { method: 'POST', path: '/v1/sales-invoices/{id}/match-sales-orders', summary: 'Match this invoice\'s lines to sales-order lines and to delivery-note lines', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
20
+ 'validate': { method: 'POST', path: '/v1/sales-invoices/{id}/validate', summary: 'Validate a sales invoice update without persisting changes', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['earlyPaymentDiscounts', 'lineItems', 'discounts', 'files', 'notes', 'totalAmountByTaxRate', 'tagIds', 'tagCodes', 'invoiceEmailCc', 'removeFileIds'] },
21
21
  'request-approval': { method: 'POST', path: '/v1/sales-invoices/{id}/request-approval', summary: 'Request approval for sales invoice (DRAFT → PENDING_APPROVAL)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
22
22
  'send': { method: 'POST', path: '/v1/sales-invoices/{id}/send', summary: 'Mark invoice as sent to customer (APPROVED → SENT)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
23
23
  'send-resend': { method: 'POST', path: '/v1/sales-invoices/{id}/resend', summary: 'Resend a sales invoice to the original delivery recipient or an alternative one', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['emailCc', 'emailBcc'] },
24
24
  'cancel': { method: 'POST', path: '/v1/sales-invoices/{id}/cancel', summary: 'Cancel a sales invoice', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
25
25
  'copy': { method: 'POST', path: '/v1/sales-invoices/{id}/copy', summary: 'Create a copy of a cancelled invoice', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
26
- 'replace': { method: 'POST', path: '/v1/sales-invoices/{id}/replace', summary: 'Replace invoice with corrected version (creates new CORRECTED_INVOICE)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
26
+ 'replace': { method: 'POST', path: '/v1/sales-invoices/{id}/replace', summary: 'Replace invoice (creates a new CORRECTED_INVOICE; a SELF_BILLED_INVOICE is replaced by a new SELF_BILLED_INVOICE)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
27
+ 'rebuild-journal': { method: 'POST', path: '/v1/sales-invoices/{id}/rebuild-journal', summary: 'Re-create the booking journal of a sales invoice', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
27
28
  'merge': { method: 'POST', path: '/v1/sales-invoices/{id}/merge', summary: 'Merge draft invoices into this master', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['sourceIds'] },
28
29
  'create-line-items': { method: 'POST', path: '/v1/sales-invoices/{invoiceId}/line-items', summary: 'Add a line item to a sales invoice', pathParams: ['invoiceId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['discounts', 'salesOrderLineItems', 'deliveryNoteLineItems'] },
29
30
  'line-items-from-sales-order': { method: 'POST', path: '/v1/sales-invoices/{invoiceId}/line-items/from-sales-order', summary: 'Add line items to a sales invoice from a sales order', pathParams: ['invoiceId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['lines'] },
31
+ 'line-items-from-delivery-note': { method: 'POST', path: '/v1/sales-invoices/{invoiceId}/line-items/from-delivery-note', summary: 'Add line items to a sales invoice from a delivery note', pathParams: ['invoiceId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['lines'] },
30
32
  'update-line-items-reorder': { method: 'PATCH', path: '/v1/sales-invoices/{invoiceId}/line-items/reorder', summary: 'Bulk reorder line items (drag-and-drop)', pathParams: ['invoiceId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['items'] },
31
33
  'update-line-items': { method: 'PATCH', path: '/v1/sales-invoices/{invoiceId}/line-items/{lineItemId}', summary: 'Update a line item on a sales invoice', pathParams: ['invoiceId', 'lineItemId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['discounts', 'salesOrderLineItems', 'deliveryNoteLineItems'] },
32
34
  'delete-line-items': { method: 'DELETE', path: '/v1/sales-invoices/{invoiceId}/line-items/{lineItemId}', summary: 'Remove a line item from a sales invoice', pathParams: ['invoiceId', 'lineItemId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
@@ -57,7 +59,7 @@ export default class SalesInvoices extends Command {
57
59
  id: Args.string({ description: 'Resource ID (for get, update, delete operations)', required: false }),
58
60
  };
59
61
  static flags = {
60
- context: Flags.string({ char: 'c', description: 'Context to use' }),
62
+ context: Flags.string({ char: 'c', aliases: ['config'], env: 'ADERIS_CONTEXT', description: 'Context to use for this command, overriding the current context (alias: --config)' }),
61
63
  output: Flags.string({ char: 'o', description: 'Output format (default: table for import, json for other commands)', options: ['json', 'table', 'csv'] }),
62
64
  table: Flags.boolean({ char: 't', description: 'Output as table (shortcut for --output table)' }),
63
65
  csv: Flags.boolean({ description: 'Output as CSV (shortcut for --output csv)' }),
@@ -132,9 +134,9 @@ export default class SalesInvoices extends Command {
132
134
  }
133
135
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
134
136
  if (!context)
135
- this.error('No context configured. Run: aderis auth login --new');
136
- if (!context.tokens)
137
- this.error('Not logged in. Run: aderis auth login');
137
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
138
+ if (!hasCredentials(context))
139
+ this.error(missingCredentialsMessage(context));
138
140
  const queryParams = {};
139
141
  if (flags.page)
140
142
  queryParams.page = flags.page;
@@ -377,9 +379,9 @@ export default class SalesInvoices extends Command {
377
379
  async runImport(flags) {
378
380
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
379
381
  if (!context)
380
- this.error('No context configured. Run: aderis auth login --new');
381
- if (!context.tokens)
382
- this.error('Not logged in. Run: aderis auth login');
382
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
383
+ if (!hasCredentials(context))
384
+ this.error(missingCredentialsMessage(context));
383
385
  // Get data from file, --data, or --set flags
384
386
  let items = [];
385
387
  if (flags.file) {
@@ -589,9 +591,9 @@ export default class SalesInvoices extends Command {
589
591
  async runExport(flags) {
590
592
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
591
593
  if (!context)
592
- this.error('No context configured. Run: aderis auth login --new');
593
- if (!context.tokens)
594
- this.error('Not logged in. Run: aderis auth login');
594
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
595
+ if (!hasCredentials(context))
596
+ this.error(missingCredentialsMessage(context));
595
597
  const listEndpoint = ENDPOINTS['list'];
596
598
  if (!listEndpoint)
597
599
  this.error('Export requires a list endpoint');
@@ -683,9 +685,9 @@ export default class SalesInvoices extends Command {
683
685
  async runCamt053Import(flags) {
684
686
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
685
687
  if (!context)
686
- this.error('No context configured. Run: aderis auth login --new');
687
- if (!context.tokens)
688
- this.error('Not logged in. Run: aderis auth login');
688
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
689
+ if (!hasCredentials(context))
690
+ this.error(missingCredentialsMessage(context));
689
691
  if (!flags.file) {
690
692
  this.error('CAMT.053 import requires --file (-f) flag with path to XML file');
691
693
  }
@@ -773,9 +775,9 @@ export default class SalesInvoices extends Command {
773
775
  }
774
776
  const context = flags.context ? getContext(flags.context) : getCurrentContext();
775
777
  if (!context)
776
- this.error('No context configured. Run: aderis auth login --new');
777
- if (!context.tokens)
778
- this.error('Not logged in. Run: aderis auth login');
778
+ this.error(flags.context ? `Context "${flags.context}" not found. List contexts with: aderis config list` : 'No context configured. Run: aderis auth login --new');
779
+ if (!hasCredentials(context))
780
+ this.error(missingCredentialsMessage(context));
779
781
  // Get data from file, --data, or --set flags
780
782
  let items = [];
781
783
  if (flags.file) {