@aderis-erp/cli 1.0.15 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/README.md +30 -8
  2. package/dist/commands/access-groups.d.ts +0 -1
  3. package/dist/commands/access-groups.js +54 -78
  4. package/dist/commands/account-transaction-allocations.d.ts +0 -1
  5. package/dist/commands/account-transaction-allocations.js +51 -75
  6. package/dist/commands/account-transactions.d.ts +0 -1
  7. package/dist/commands/account-transactions.js +80 -94
  8. package/dist/commands/accounts.d.ts +0 -1
  9. package/dist/commands/accounts.js +59 -83
  10. package/dist/commands/agent-platform.d.ts +0 -1
  11. package/dist/commands/agent-platform.js +58 -82
  12. package/dist/commands/agent-runs.d.ts +39 -0
  13. package/dist/commands/agent-runs.js +1155 -0
  14. package/dist/commands/analytics.d.ts +0 -1
  15. package/dist/commands/analytics.js +52 -76
  16. package/dist/commands/{text-templates.d.ts → api-keys.d.ts} +1 -2
  17. package/dist/commands/api-keys.js +1150 -0
  18. package/dist/commands/async-jobs.d.ts +39 -0
  19. package/dist/commands/async-jobs.js +1158 -0
  20. package/dist/commands/audit-log.d.ts +0 -1
  21. package/dist/commands/audit-log.js +51 -75
  22. package/dist/commands/auth/login.d.ts +9 -0
  23. package/dist/commands/auth/login.js +73 -20
  24. package/dist/commands/auth/logout.d.ts +4 -0
  25. package/dist/commands/auth/logout.js +4 -0
  26. package/dist/commands/auth/status.js +26 -17
  27. package/dist/commands/auth/tenant.js +3 -6
  28. package/dist/commands/auth.d.ts +0 -1
  29. package/dist/commands/auth.js +5 -34
  30. package/dist/commands/bank-accounts.d.ts +0 -1
  31. package/dist/commands/bank-accounts.js +68 -91
  32. package/dist/commands/bank-integrations.d.ts +1 -1
  33. package/dist/commands/bank-integrations.js +71 -92
  34. package/dist/commands/business-partners.d.ts +1 -1
  35. package/dist/commands/business-partners.js +84 -100
  36. package/dist/commands/chat.d.ts +0 -1
  37. package/dist/commands/chat.js +57 -80
  38. package/dist/commands/config/add.d.ts +3 -0
  39. package/dist/commands/config/add.js +34 -16
  40. package/dist/commands/config/current.js +3 -0
  41. package/dist/commands/config/list.js +3 -0
  42. package/dist/commands/credit-card-accounts.d.ts +1 -1
  43. package/dist/commands/credit-card-accounts.js +72 -90
  44. package/dist/commands/delivery-notes.d.ts +0 -1
  45. package/dist/commands/delivery-notes.js +83 -105
  46. package/dist/commands/dunning-configs.d.ts +0 -1
  47. package/dist/commands/dunning-configs.js +54 -78
  48. package/dist/commands/dunning-reminders.d.ts +0 -1
  49. package/dist/commands/dunning-reminders.js +57 -81
  50. package/dist/commands/dunning-runs.d.ts +0 -1
  51. package/dist/commands/dunning-runs.js +50 -74
  52. package/dist/commands/email-transactions.d.ts +0 -1
  53. package/dist/commands/email-transactions.js +52 -76
  54. package/dist/commands/employees.d.ts +0 -1
  55. package/dist/commands/employees.js +81 -105
  56. package/dist/commands/entity-configurations.d.ts +0 -1
  57. package/dist/commands/entity-configurations.js +52 -76
  58. package/dist/commands/event-processor-mappings.d.ts +0 -1
  59. package/dist/commands/event-processor-mappings.js +54 -78
  60. package/dist/commands/files.d.ts +0 -1
  61. package/dist/commands/files.js +61 -85
  62. package/dist/commands/health.d.ts +0 -1
  63. package/dist/commands/health.js +54 -78
  64. package/dist/commands/imports.d.ts +39 -0
  65. package/dist/commands/imports.js +1151 -0
  66. package/dist/commands/inbox.d.ts +0 -1
  67. package/dist/commands/inbox.js +57 -80
  68. package/dist/commands/integration-identities.d.ts +40 -0
  69. package/dist/commands/integration-identities.js +1151 -0
  70. package/dist/commands/integrations.d.ts +0 -1
  71. package/dist/commands/integrations.js +52 -76
  72. package/dist/commands/item-categories.d.ts +0 -1
  73. package/dist/commands/item-categories.js +54 -78
  74. package/dist/commands/items.d.ts +0 -1
  75. package/dist/commands/items.js +54 -78
  76. package/dist/commands/journal-lines.d.ts +0 -1
  77. package/dist/commands/journal-lines.js +50 -74
  78. package/dist/commands/journals.d.ts +1 -1
  79. package/dist/commands/journals.js +75 -96
  80. package/dist/commands/ledgers.d.ts +3 -2
  81. package/dist/commands/ledgers.js +100 -95
  82. package/dist/commands/my-account.d.ts +39 -0
  83. package/dist/commands/my-account.js +1160 -0
  84. package/dist/commands/office-locations.d.ts +0 -1
  85. package/dist/commands/office-locations.js +54 -78
  86. package/dist/commands/payment-methods.d.ts +0 -1
  87. package/dist/commands/payment-methods.js +59 -83
  88. package/dist/commands/payment-runs.d.ts +0 -1
  89. package/dist/commands/payment-runs.js +66 -90
  90. package/dist/commands/payment-terms.d.ts +0 -1
  91. package/dist/commands/payment-terms.js +55 -79
  92. package/dist/commands/payments.d.ts +0 -1
  93. package/dist/commands/payments.js +56 -80
  94. package/dist/commands/payroll-runs.d.ts +43 -0
  95. package/dist/commands/payroll-runs.js +1188 -0
  96. package/dist/commands/permissions.d.ts +39 -0
  97. package/dist/commands/permissions.js +1146 -0
  98. package/dist/commands/price-lists.d.ts +0 -1
  99. package/dist/commands/price-lists.js +59 -83
  100. package/dist/commands/processor-mappings.d.ts +0 -1
  101. package/dist/commands/processor-mappings.js +53 -77
  102. package/dist/commands/processors.d.ts +0 -1
  103. package/dist/commands/processors.js +60 -85
  104. package/dist/commands/purchase-order-types.d.ts +0 -1
  105. package/dist/commands/purchase-order-types.js +54 -78
  106. package/dist/commands/purchase-orders.d.ts +0 -1
  107. package/dist/commands/purchase-orders.js +74 -97
  108. package/dist/commands/reports.d.ts +0 -1
  109. package/dist/commands/reports.js +54 -78
  110. package/dist/commands/roles.d.ts +39 -0
  111. package/dist/commands/{text-templates.js → roles.js} +64 -90
  112. package/dist/commands/salary-types.d.ts +0 -1
  113. package/dist/commands/salary-types.js +54 -78
  114. package/dist/commands/sales-invoices.d.ts +0 -1
  115. package/dist/commands/sales-invoices.js +90 -110
  116. package/dist/commands/sales-orders.d.ts +0 -1
  117. package/dist/commands/sales-orders.js +83 -105
  118. package/dist/commands/saved-views.d.ts +0 -1
  119. package/dist/commands/saved-views.js +52 -76
  120. package/dist/commands/scheduled-processor-mappings.d.ts +0 -1
  121. package/dist/commands/scheduled-processor-mappings.js +54 -78
  122. package/dist/commands/schedules.d.ts +0 -1
  123. package/dist/commands/schedules.js +58 -82
  124. package/dist/commands/switch.js +4 -4
  125. package/dist/commands/tag-configurations.d.ts +0 -1
  126. package/dist/commands/tag-configurations.js +56 -79
  127. package/dist/commands/tags.d.ts +0 -1
  128. package/dist/commands/tags.js +54 -78
  129. package/dist/commands/tax-codes.d.ts +0 -1
  130. package/dist/commands/tax-codes.js +57 -81
  131. package/dist/commands/tax-matrix.d.ts +0 -1
  132. package/dist/commands/tax-matrix.js +54 -78
  133. package/dist/commands/templates.d.ts +39 -0
  134. package/dist/commands/templates.js +1157 -0
  135. package/dist/commands/tenants.d.ts +0 -1
  136. package/dist/commands/tenants.js +58 -81
  137. package/dist/commands/tools.d.ts +0 -1
  138. package/dist/commands/tools.js +51 -75
  139. package/dist/commands/users.d.ts +42 -0
  140. package/dist/commands/users.js +1174 -0
  141. package/dist/commands/vat-declarations.d.ts +3 -1
  142. package/dist/commands/vat-declarations.js +78 -93
  143. package/dist/commands/vendor-invoices.d.ts +0 -1
  144. package/dist/commands/vendor-invoices.js +87 -110
  145. package/dist/commands/webhooks.d.ts +0 -1
  146. package/dist/commands/webhooks.js +56 -80
  147. package/dist/commands/workflows.d.ts +0 -1
  148. package/dist/commands/workflows.js +52 -76
  149. package/dist/lib/api-client.d.ts +6 -0
  150. package/dist/lib/api-client.js +16 -6
  151. package/dist/lib/auth/constants.d.ts +11 -0
  152. package/dist/lib/auth/constants.js +11 -0
  153. package/dist/lib/auth/errors.d.ts +17 -0
  154. package/dist/lib/auth/errors.js +22 -0
  155. package/dist/lib/auth/flow.d.ts +27 -0
  156. package/dist/lib/auth/flow.js +163 -0
  157. package/dist/lib/auth/guards.d.ts +5 -0
  158. package/dist/lib/auth/guards.js +14 -0
  159. package/dist/lib/auth/http.d.ts +16 -0
  160. package/dist/lib/auth/http.js +49 -0
  161. package/dist/lib/auth/index.d.ts +49 -0
  162. package/dist/lib/auth/index.js +228 -0
  163. package/dist/lib/auth/jwks.d.ts +19 -0
  164. package/dist/lib/auth/jwks.js +112 -0
  165. package/dist/lib/auth/keycloak-provider.d.ts +91 -0
  166. package/dist/lib/auth/keycloak-provider.js +244 -0
  167. package/dist/lib/auth/pages.d.ts +25 -0
  168. package/dist/lib/auth/pages.js +123 -0
  169. package/dist/lib/auth/pkce.d.ts +11 -0
  170. package/dist/lib/auth/pkce.js +17 -0
  171. package/dist/lib/auth/tokens.d.ts +59 -0
  172. package/dist/lib/auth/tokens.js +105 -0
  173. package/dist/lib/auth/types.d.ts +61 -0
  174. package/dist/lib/auth/types.js +1 -0
  175. package/dist/lib/auth/validated-url.d.ts +6 -0
  176. package/dist/lib/auth/validated-url.js +53 -0
  177. package/dist/lib/config.d.ts +13 -3
  178. package/dist/lib/config.js +24 -19
  179. package/oclif.manifest.json +2447 -641
  180. package/package.json +5 -4
  181. package/dist/lib/auth.d.ts +0 -43
  182. package/dist/lib/auth.js +0 -610
@@ -15,7 +15,10 @@ export default class VatDeclarations extends Command {
15
15
  file: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
16
16
  set: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
17
17
  'field-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
+ 'notice-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
18
19
  'file-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
+ 'contribution-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
21
+ 'exclusion-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
19
22
  page: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
20
23
  limit: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
21
24
  include: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
@@ -33,7 +36,6 @@ export default class VatDeclarations extends Command {
33
36
  private runCamt053Import;
34
37
  private runNestedImport;
35
38
  private parseFilterValue;
36
- private filterFields;
37
39
  private sanitizeOutput;
38
40
  private getColumns;
39
41
  private getValue;
@@ -1,32 +1,38 @@
1
1
  import { Command, Args, Flags } from '@oclif/core';
2
- import { apiRequest, ApiError, normalizeSortBy } from '../lib/api-client.js';
2
+ import { apiRequest, ApiError, isTextualMediaType, normalizeSortBy } from '../lib/api-client.js';
3
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 = ["files"];
9
- const SUBCOMMANDS = [...["list", "create", "preview", "get", "update", "delete", "regenerate", "replace", "fields-contributions", "fields-contributions-export", "approve", "mark-as-filed", "xml", "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", "preview", "get", "update", "delete", "regenerate", "replace", "fields-contributions", "fields-contributions-export", "approve", "mark-as-filed", "xml", "notices-dismiss", "notices-restore", "list-files", "create-files", "get-files", "update-files", "delete-files", "files-download", "list-payments", "create-payments", "contributions-exclude", "exclusions-restore"], ...(HAS_IMPORT ? ['import'] : []), ...(HAS_EXPORT ? ['export'] : []), ...NESTED_IMPORTS.map(n => `import-${n}`)];
10
10
  const ENDPOINTS = {
11
- 'list': { method: 'GET', path: '/v1/vat-declarations', summary: 'List VAT reports (paginated)', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
12
- 'create': { method: 'POST', path: '/v1/vat-declarations', summary: 'Create a VAT declaration report (always async-accepted)', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
13
- 'preview': { method: 'GET', path: '/v1/vat-declarations/preview', summary: 'Preview the in-scope counts and late entries for a candidate period', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
14
- 'get': { method: 'GET', path: '/v1/vat-declarations/{id}', summary: 'Get a VAT report by id (this is the polling endpoint for async generation)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
15
- 'update': { method: 'PATCH', path: '/v1/vat-declarations/{id}', summary: 'Update manualAdjustments, submission type, or amount basis on a DRAFT report', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: ['manualAdjustments'] },
16
- 'delete': { method: 'DELETE', path: '/v1/vat-declarations/{id}', summary: 'Delete a VAT declaration that is still in DRAFT status', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
17
- 'regenerate': { method: 'POST', path: '/v1/vat-declarations/{id}/regenerate', summary: 'Re-run the full generation pipeline on a DRAFT report', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
18
- 'replace': { method: 'POST', path: '/v1/vat-declarations/{id}/replace', summary: 'Create a corrective DRAFT (Berichtigungsabrechnung) from a FILED report', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
19
- 'fields-contributions': { method: 'GET', path: '/v1/vat-declarations/{id}/fields/{fieldId}/contributions', summary: 'Drill into the contributions for a single Ziffer', pathParams: ['id', 'fieldId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
20
- 'fields-contributions-export': { method: 'GET', path: '/v1/vat-declarations/{id}/fields/{fieldId}/contributions/export', summary: 'Export the drill-down result set as an Excel workbook', pathParams: ['id', 'fieldId'], hasBody: false, isMultipart: false, isBinaryResponse: true, bodyArrayFields: [] },
21
- 'approve': { method: 'POST', path: '/v1/vat-declarations/{id}/approve', summary: 'Approve a VAT report and produce the eCH-0217 XML submission file.', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
22
- 'mark-as-filed': { method: 'POST', path: '/v1/vat-declarations/{id}/mark-as-filed', summary: 'Mark a FINALIZED VAT declaration as filed.', pathParams: ['id'], hasBody: true, isMultipart: true, isBinaryResponse: false, bodyArrayFields: [] },
23
- 'xml': { method: 'GET', path: '/v1/vat-declarations/{id}/xml', summary: 'Download the eCH-0217 XML submission file for a FINALIZED or FILED VAT report.', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: true, bodyArrayFields: [] },
24
- 'list-files': { method: 'GET', path: '/v1/vat-declarations/{parentId}/files', summary: 'List file attachments for a VAT declaration', pathParams: ['parentId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
25
- 'create-files': { method: 'POST', path: '/v1/vat-declarations/{parentId}/files', summary: 'Upload a file attachment to a VAT declaration', pathParams: ['parentId'], hasBody: false, isMultipart: true, isBinaryResponse: false, bodyArrayFields: [] },
26
- 'get-files': { method: 'GET', path: '/v1/vat-declarations/{parentId}/files/{fileId}', summary: 'Get a file attachment for a VAT declaration', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
27
- 'update-files': { method: 'PATCH', path: '/v1/vat-declarations/{parentId}/files/{fileId}', summary: 'Update file attachment metadata for a VAT declaration', pathParams: ['parentId', 'fileId'], hasBody: true, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
28
- 'delete-files': { method: 'DELETE', path: '/v1/vat-declarations/{parentId}/files/{fileId}', summary: 'Delete a file attachment from a VAT declaration', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
29
- 'files-download': { method: 'GET', path: '/v1/vat-declarations/{parentId}/files/{fileId}/download', summary: 'Download a file attachment from a VAT declaration', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, bodyArrayFields: [] },
11
+ 'list': { method: 'GET', path: '/v1/vat-declarations', summary: 'List VAT reports (paginated)', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
12
+ 'create': { method: 'POST', path: '/v1/vat-declarations', summary: 'Create a VAT declaration report (always async-accepted)', pathParams: [], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
13
+ 'preview': { method: 'GET', path: '/v1/vat-declarations/preview', summary: 'Preview the in-scope counts and late entries for a candidate period', pathParams: [], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
14
+ 'get': { method: 'GET', path: '/v1/vat-declarations/{id}', summary: 'Get a VAT report by id (this is the polling endpoint for async generation)', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
15
+ 'update': { method: 'PATCH', path: '/v1/vat-declarations/{id}', summary: 'Update manualAdjustments, submission type, or amount basis on a DRAFT report', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: ['manualAdjustments'] },
16
+ 'delete': { method: 'DELETE', path: '/v1/vat-declarations/{id}', summary: 'Delete a VAT declaration that is still in DRAFT status', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
17
+ 'regenerate': { method: 'POST', path: '/v1/vat-declarations/{id}/regenerate', summary: 'Re-run the full generation pipeline on a DRAFT report', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
18
+ 'replace': { method: 'POST', path: '/v1/vat-declarations/{id}/replace', summary: 'Create a corrective DRAFT (Berichtigungsabrechnung) from a FILED report', pathParams: ['id'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
19
+ 'fields-contributions': { method: 'GET', path: '/v1/vat-declarations/{id}/fields/{fieldId}/contributions', summary: 'Drill into the contributions for a single Ziffer', pathParams: ['id', 'fieldId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
20
+ 'fields-contributions-export': { method: 'GET', path: '/v1/vat-declarations/{id}/fields/{fieldId}/contributions/export', summary: 'Export the drill-down result set as an Excel workbook', pathParams: ['id', 'fieldId'], hasBody: false, isMultipart: false, isBinaryResponse: true, hasBinaryVariant: false, bodyArrayFields: [] },
21
+ 'approve': { method: 'POST', path: '/v1/vat-declarations/{id}/approve', summary: 'Approve a VAT report and produce the eCH-0217 XML submission file.', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
22
+ 'mark-as-filed': { method: 'POST', path: '/v1/vat-declarations/{id}/mark-as-filed', summary: 'Mark a FINALIZED VAT declaration as filed.', pathParams: ['id'], hasBody: true, isMultipart: true, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
23
+ 'xml': { method: 'GET', path: '/v1/vat-declarations/{id}/xml', summary: 'Download the eCH-0217 XML submission file for a FINALIZED or FILED VAT report.', pathParams: ['id'], hasBody: false, isMultipart: false, isBinaryResponse: true, hasBinaryVariant: false, bodyArrayFields: [] },
24
+ 'notices-dismiss': { method: 'POST', path: '/v1/vat-declarations/{id}/notices/{noticeId}/dismiss', summary: 'Dismiss a generation notice with a mandatory reason.', pathParams: ['id', 'noticeId'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
25
+ 'notices-restore': { method: 'POST', path: '/v1/vat-declarations/{id}/notices/{noticeId}/restore', summary: 'Restore a previously dismissed generation notice.', pathParams: ['id', 'noticeId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
26
+ 'list-files': { method: 'GET', path: '/v1/vat-declarations/{parentId}/files', summary: 'List file attachments for a VAT declaration', pathParams: ['parentId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
27
+ 'create-files': { method: 'POST', path: '/v1/vat-declarations/{parentId}/files', summary: 'Upload a file attachment to a VAT declaration', pathParams: ['parentId'], hasBody: false, isMultipart: true, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
28
+ 'get-files': { method: 'GET', path: '/v1/vat-declarations/{parentId}/files/{fileId}', summary: 'Get a file attachment for a VAT declaration', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
29
+ 'update-files': { method: 'PATCH', path: '/v1/vat-declarations/{parentId}/files/{fileId}', summary: 'Update file attachment metadata for a VAT declaration', pathParams: ['parentId', 'fileId'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
30
+ 'delete-files': { method: 'DELETE', path: '/v1/vat-declarations/{parentId}/files/{fileId}', summary: 'Delete a file attachment from a VAT declaration', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
31
+ 'files-download': { method: 'GET', path: '/v1/vat-declarations/{parentId}/files/{fileId}/download', summary: 'Download a file attachment from a VAT declaration', pathParams: ['parentId', 'fileId'], hasBody: false, isMultipart: false, isBinaryResponse: true, hasBinaryVariant: false, bodyArrayFields: [] },
32
+ 'list-payments': { method: 'GET', path: '/v1/vat-declarations/{vatDeclarationId}/payments', summary: 'Get all payments for a VAT declaration', pathParams: ['vatDeclarationId'], hasBody: false, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
33
+ 'create-payments': { method: 'POST', path: '/v1/vat-declarations/{vatDeclarationId}/payments', summary: 'Create the payment for a filed VAT declaration', pathParams: ['vatDeclarationId'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
34
+ 'contributions-exclude': { method: 'POST', path: '/v1/vat-declarations/{id}/contributions/{contributionId}/exclude', summary: 'Take the booking behind one contribution row out of a DRAFT declaration.', pathParams: ['id', 'contributionId'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
35
+ 'exclusions-restore': { method: 'POST', path: '/v1/vat-declarations/{id}/exclusions/{exclusionId}/restore', summary: 'Put an excluded booking back into a DRAFT declaration.', pathParams: ['id', 'exclusionId'], hasBody: true, isMultipart: false, isBinaryResponse: false, hasBinaryVariant: false, bodyArrayFields: [] },
30
36
  };
31
37
  export default class VatDeclarations extends Command {
32
38
  static description = 'Manage vat declarations';
@@ -51,7 +57,10 @@ export default class VatDeclarations extends Command {
51
57
  file: Flags.string({ char: 'f', description: 'Read request body from file' }),
52
58
  set: Flags.string({ char: 's', description: 'Set individual field (e.g. --set firstName=John)', multiple: true }),
53
59
  'field-id': Flags.string({ description: 'Path param: fieldId' }),
60
+ 'notice-id': Flags.string({ description: 'Path param: noticeId' }),
54
61
  'file-id': Flags.string({ description: 'Path param: fileId' }),
62
+ 'contribution-id': Flags.string({ description: 'Path param: contributionId' }),
63
+ 'exclusion-id': Flags.string({ description: 'Path param: exclusionId' }),
55
64
  page: Flags.string({ description: 'Page number' }),
56
65
  limit: Flags.string({ description: 'Items per page' }),
57
66
  include: Flags.string({ description: 'Relations to include' }),
@@ -59,7 +68,7 @@ export default class VatDeclarations extends Command {
59
68
  'sort-by': Flags.string({ description: 'Sort field(s), comma-separated. Direction (:ASC/:DESC) is optional; date-like fields default to DESC, others to ASC.' }),
60
69
  filter: Flags.string({ description: 'Filter (e.g. --filter status=ACTIVE). Operators: in:A,B, like:%, gt:, lt:, null:', multiple: true }),
61
70
  query: Flags.string({ description: 'Additional query params as JSON' }),
62
- fields: Flags.string({ description: 'Comma-separated list of fields to show (e.g. --fields=id,name,status)' }),
71
+ fields: Flags.string({ description: 'Comma-separated list of fields to return, applied by the API (e.g. --fields=id,name,status)' }),
63
72
  sanitize: Flags.boolean({ description: 'Remove null values, audit fields, and duplicate UUIDs from output' }),
64
73
  'show-http-request': Flags.boolean({ description: 'Show HTTP request details (method, URL, body)' }),
65
74
  };
@@ -131,6 +140,8 @@ export default class VatDeclarations extends Command {
131
140
  queryParams.search = flags.search;
132
141
  if (flags['sort-by'])
133
142
  queryParams.sortBy = normalizeSortBy(flags['sort-by']);
143
+ if (flags.fields)
144
+ queryParams.fields = flags.fields;
134
145
  if (flags.query) {
135
146
  try {
136
147
  Object.assign(queryParams, JSON.parse(flags.query));
@@ -278,10 +289,11 @@ export default class VatDeclarations extends Command {
278
289
  process.stderr.write('\n');
279
290
  }
280
291
  try {
281
- // Binary response: download to file
292
+ // Binary response: to -f / --file, or to stdout when it is redirected.
282
293
  if (endpoint.isBinaryResponse) {
283
- if (!flags.file) {
284
- this.error(`Endpoint returns a binary file. Specify the output path with -f / --file (e.g. -f report.xlsx).`);
294
+ const toStdout = !flags.file;
295
+ if (toStdout && process.stdout.isTTY) {
296
+ this.error(`Endpoint returns a binary file. Specify the output path with -f / --file (e.g. -f report.xlsx), or redirect stdout to a file.`);
285
297
  }
286
298
  const binResponse = await apiRequest(endpoint.method, apiPath, {
287
299
  params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
@@ -289,24 +301,55 @@ export default class VatDeclarations extends Command {
289
301
  contextName: flags.context,
290
302
  binary: true,
291
303
  });
292
- const fsModule = await import('node:fs');
293
304
  const binData = binResponse.data;
294
305
  const buffer = Buffer.isBuffer(binData)
295
306
  ? binData
296
307
  : Buffer.from(binData);
308
+ if (toStdout) {
309
+ // Nothing else may reach stdout here — it is the file.
310
+ process.stdout.write(buffer);
311
+ return;
312
+ }
313
+ const fsModule = await import('node:fs');
297
314
  fsModule.writeFileSync(flags.file, buffer);
298
315
  this.log(`Saved ${buffer.length} bytes to ${flags.file}`);
299
316
  return;
300
317
  }
301
- const response = await apiRequest(endpoint.method, apiPath, {
302
- params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
303
- data,
304
- contextName: flags.context,
305
- acceptAny: true,
306
- });
318
+ let response;
319
+ if (endpoint.hasBinaryVariant) {
320
+ // This route answers JSON or a file depending on the request body, so the
321
+ // bytes are read first and the response's own content-type decides. Asking
322
+ // for text here would corrupt an xlsx/pdf before anything could inspect it.
323
+ const raw = await apiRequest(endpoint.method, apiPath, {
324
+ params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
325
+ data,
326
+ contextName: flags.context,
327
+ binary: true,
328
+ });
329
+ const rawType = String(raw.headers['content-type'] || '').toLowerCase();
330
+ const rawData = raw.data;
331
+ const buffer = Buffer.isBuffer(rawData) ? rawData : Buffer.from(rawData);
332
+ if (!isTextualMediaType(rawType)) {
333
+ if (process.stdout.isTTY) {
334
+ this.error(`The API returned ${rawType || 'binary data'}. Redirect stdout to a file, e.g. ... > report.xlsx`);
335
+ }
336
+ // Nothing else may reach stdout here — it is the file.
337
+ process.stdout.write(buffer);
338
+ return;
339
+ }
340
+ response = { data: buffer.toString('utf8'), headers: raw.headers, status: raw.status };
341
+ }
342
+ else {
343
+ response = await apiRequest(endpoint.method, apiPath, {
344
+ params: Object.keys(queryParams).length > 0 ? queryParams : undefined,
345
+ data,
346
+ contextName: flags.context,
347
+ acceptAny: true,
348
+ });
349
+ }
307
350
  // Check content-type for non-JSON responses (XML, text, etc.)
308
351
  const contentType = (response.headers['content-type'] || '').toLowerCase();
309
- if (contentType.includes('xml') || contentType.includes('text/')) {
352
+ if (isTextualMediaType(contentType) && !contentType.startsWith('application/json')) {
310
353
  // Output raw content for XML/text responses (CSV, plain, HTML, etc.)
311
354
  this.log(String(response.data));
312
355
  return;
@@ -333,11 +376,6 @@ export default class VatDeclarations extends Command {
333
376
  output = obj[arrayKeys[0]];
334
377
  }
335
378
  }
336
- // Filter fields if --fields flag is provided
337
- if (flags.fields) {
338
- const fieldList = flags.fields.split(',').map(f => f.trim());
339
- output = this.filterFields(output, fieldList);
340
- }
341
379
  // Sanitize output if requested
342
380
  if (flags.sanitize) {
343
381
  output = this.sanitizeOutput(output);
@@ -592,6 +630,8 @@ export default class VatDeclarations extends Command {
592
630
  baseParams.sortBy = normalizeSortBy(flags['sort-by']);
593
631
  if (flags.include)
594
632
  baseParams.include = flags.include;
633
+ if (flags.fields)
634
+ baseParams.fields = flags.fields;
595
635
  if (flags.query) {
596
636
  try {
597
637
  Object.assign(baseParams, JSON.parse(flags.query));
@@ -646,12 +686,7 @@ export default class VatDeclarations extends Command {
646
686
  }
647
687
  }
648
688
  process.stderr.write(' done\n');
649
- // Filter fields if specified
650
689
  let output = allItems;
651
- if (flags.fields) {
652
- const fieldList = flags.fields.split(',').map(f => f.trim());
653
- output = this.filterFields(allItems, fieldList);
654
- }
655
690
  // Sanitize output if requested
656
691
  if (flags.sanitize) {
657
692
  output = this.sanitizeOutput(output);
@@ -980,56 +1015,6 @@ export default class VatDeclarations extends Command {
980
1015
  return `\$${op}`;
981
1016
  return opRe.test(rest) ? `\$${op}:${this.parseFilterValue(rest)}` : `\$${op}:${rest}`;
982
1017
  }
983
- filterFields(data, fields) {
984
- const isUnsafeKey = (k) => k === '__proto__' || k === 'constructor' || k === 'prototype';
985
- const pick = (obj, keys) => {
986
- // Group keys by their first segment so sibling sub-paths
987
- // (e.g. 'items.amount' + 'items._type') resolve in one recursive pass
988
- // and don't clobber each other on merge.
989
- const directKeys = new Set();
990
- const nestedKeys = new Map();
991
- for (const key of keys) {
992
- if (key.split('.').some(isUnsafeKey))
993
- continue;
994
- if (key.includes('.')) {
995
- const [first, ...rest] = key.split('.');
996
- if (isUnsafeKey(first))
997
- continue;
998
- const list = nestedKeys.get(first);
999
- if (list) {
1000
- list.push(rest.join('.'));
1001
- }
1002
- else {
1003
- nestedKeys.set(first, [rest.join('.')]);
1004
- }
1005
- }
1006
- else {
1007
- directKeys.add(key);
1008
- }
1009
- }
1010
- const result = {};
1011
- for (const key of directKeys) {
1012
- if (key in obj)
1013
- result[key] = obj[key];
1014
- }
1015
- for (const [first, restKeys] of nestedKeys) {
1016
- const val = obj[first];
1017
- if (!val || typeof val !== 'object')
1018
- continue;
1019
- if (Array.isArray(val)) {
1020
- result[first] = val.map(item => pick(item, restKeys));
1021
- }
1022
- else {
1023
- result[first] = pick(val, restKeys);
1024
- }
1025
- }
1026
- return result;
1027
- };
1028
- if (Array.isArray(data)) {
1029
- return data.map(item => pick(item, fields));
1030
- }
1031
- return pick(data, fields);
1032
- }
1033
1018
  sanitizeOutput(data) {
1034
1019
  const auditFields = ['_type', 'tenantId', 'createdAt', 'updatedAt', 'createdBy', 'updatedBy'];
1035
1020
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -35,7 +35,6 @@ export default class VendorInvoices extends Command {
35
35
  private runCamt053Import;
36
36
  private runNestedImport;
37
37
  private parseFilterValue;
38
- private filterFields;
39
38
  private sanitizeOutput;
40
39
  private getColumns;
41
40
  private getValue;