@genz-its/sevdesk-cli 0.1.2 → 0.1.4
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/README.md +45 -12
- package/dist/index.js +192 -38
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -83,6 +83,8 @@ sevdesk transactions:list --unbooked --json | jq -r '.[].id'
|
|
|
83
83
|
- [`login`](#login)
|
|
84
84
|
- [`logout`](#logout)
|
|
85
85
|
- [`doctor`](#doctor)
|
|
86
|
+
- [`accounts-datev:get`](#accounts-datevget)
|
|
87
|
+
- [`accounts-datev:list`](#accounts-datevlist)
|
|
86
88
|
- [`accounts:balance`](#accountsbalance)
|
|
87
89
|
- [`accounts:create-clearing`](#accountscreate-clearing)
|
|
88
90
|
- [`accounts:create-file-import`](#accountscreate-file-import)
|
|
@@ -160,6 +162,35 @@ sevdesk doctor [options]
|
|
|
160
162
|
|
|
161
163
|
- `--json`: Output in JSON format.
|
|
162
164
|
|
|
165
|
+
### `accounts-datev:get`
|
|
166
|
+
|
|
167
|
+
Show a single booking account (AccountDatev), including hidden accounts that [`accounts-datev:list`](#accounts-datevlist) does not return. Backed by an undocumented sevdesk endpoint that may change without notice.
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
sevdesk accounts-datev:get [options]
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Options:**
|
|
174
|
+
|
|
175
|
+
- `--id`: The booking account ID. If omitted, you will be prompted.
|
|
176
|
+
- `--json`: Output in JSON format.
|
|
177
|
+
|
|
178
|
+
### `accounts-datev:list`
|
|
179
|
+
|
|
180
|
+
List booking accounts (AccountDatev). Covers only accounts visible in the sevdesk account picker; hidden accounts (for example some tax accounts) are reachable via [`accounts-datev:get`](#accounts-datevget). Backed by an undocumented sevdesk endpoint that may change without notice.
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
sevdesk accounts-datev:list [options]
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Options:**
|
|
187
|
+
|
|
188
|
+
- `--number`: Only show accounts with this account number. Filtered client-side across all visible accounts.
|
|
189
|
+
- `--name-like`: Only show accounts whose name contains this text. Filtered client-side across all visible accounts.
|
|
190
|
+
- `--limit`: Maximum number of accounts to return. Defaults to all of them.
|
|
191
|
+
- `--offset`: Number of accounts to skip before filtering.
|
|
192
|
+
- `--json`: Output in JSON format.
|
|
193
|
+
|
|
163
194
|
### `accounts:balance`
|
|
164
195
|
|
|
165
196
|
Show the balance of a check account at a given date. The balance is the sum of all transactions known to sevdesk, which is not necessarily the real bank balance.
|
|
@@ -227,7 +258,7 @@ sevdesk accounts:list [options]
|
|
|
227
258
|
|
|
228
259
|
**Options:**
|
|
229
260
|
|
|
230
|
-
- `--limit`: The maximum number of check accounts to return.
|
|
261
|
+
- `--limit`: The maximum number of check accounts to return. Defaults to all of them.
|
|
231
262
|
- `--offset`: The number of check accounts to skip.
|
|
232
263
|
- `--json`: Output in JSON format.
|
|
233
264
|
|
|
@@ -342,7 +373,7 @@ sevdesk contacts:list [options]
|
|
|
342
373
|
- `--customer-number`: Filter by customer number.
|
|
343
374
|
- `--depth`: Contact depth: `0` returns only organizations, `1` organizations and persons. Defaults to `0`.
|
|
344
375
|
- `--category`: ID of the contact category to filter by: `2` supplier, `3` customer, `4` partner.
|
|
345
|
-
- `--limit`: Maximum number of contacts to return.
|
|
376
|
+
- `--limit`: Maximum number of contacts to return. Defaults to all of them.
|
|
346
377
|
- `--offset`: Number of contacts to skip.
|
|
347
378
|
- `--json`: Output in JSON format.
|
|
348
379
|
|
|
@@ -395,7 +426,7 @@ sevdesk credit-notes:list [options]
|
|
|
395
426
|
- `--start-date`: Only credit notes on or after this date as `dd.mm.yyyy` or Unix timestamp.
|
|
396
427
|
- `--end-date`: Only credit notes on or before this date as `dd.mm.yyyy` or Unix timestamp.
|
|
397
428
|
- `--contact`: ID of the contact whose credit notes to list.
|
|
398
|
-
- `--limit`: Maximum number of credit notes to return.
|
|
429
|
+
- `--limit`: Maximum number of credit notes to return. Defaults to all of them.
|
|
399
430
|
- `--offset`: Number of credit notes to skip.
|
|
400
431
|
- `--json`: Output in JSON format.
|
|
401
432
|
|
|
@@ -496,7 +527,7 @@ sevdesk export:vouchers [options]
|
|
|
496
527
|
|
|
497
528
|
### `guidance:accounts`
|
|
498
529
|
|
|
499
|
-
List bookable accounts and their allowed tax rules. The first matching filter wins: `--account-number`, `--tax-rule`, `--revenue`, `--expense`. Without a filter, all accounts are listed.
|
|
530
|
+
List bookable accounts and their allowed tax rules. Covers only the ReceiptGuidance subset of VAT-relevant accounts — use [`accounts-datev:list`](#accounts-datevlist) for all booking accounts. The first matching filter wins: `--account-number`, `--tax-rule`, `--revenue`, `--expense`. Without a filter, all accounts are listed.
|
|
500
531
|
|
|
501
532
|
```bash
|
|
502
533
|
sevdesk guidance:accounts [options]
|
|
@@ -538,7 +569,7 @@ sevdesk invoices:list [options]
|
|
|
538
569
|
- `--start-date`: Only invoices on or after this date as `dd.mm.yyyy` or Unix timestamp.
|
|
539
570
|
- `--end-date`: Only invoices on or before this date as `dd.mm.yyyy` or Unix timestamp.
|
|
540
571
|
- `--contact`: ID of the contact whose invoices to list.
|
|
541
|
-
- `--limit`: Maximum number of invoices to return.
|
|
572
|
+
- `--limit`: Maximum number of invoices to return. Defaults to all of them.
|
|
542
573
|
- `--offset`: Number of invoices to skip.
|
|
543
574
|
- `--json`: Output in JSON format.
|
|
544
575
|
|
|
@@ -585,7 +616,7 @@ sevdesk orders:list [options]
|
|
|
585
616
|
- `--start-date`: Only orders on or after this date as `dd.mm.yyyy` or Unix timestamp.
|
|
586
617
|
- `--end-date`: Only orders on or before this date as `dd.mm.yyyy` or Unix timestamp.
|
|
587
618
|
- `--contact`: ID of the contact whose orders to list.
|
|
588
|
-
- `--limit`: Maximum number of orders to return.
|
|
619
|
+
- `--limit`: Maximum number of orders to return. Defaults to all of them.
|
|
589
620
|
- `--offset`: Number of orders to skip.
|
|
590
621
|
- `--json`: Output in JSON format.
|
|
591
622
|
|
|
@@ -629,7 +660,7 @@ sevdesk parts:list [options]
|
|
|
629
660
|
|
|
630
661
|
- `--name`: Filter by part name.
|
|
631
662
|
- `--part-number`: Filter by part number.
|
|
632
|
-
- `--limit`: Maximum number of parts to return.
|
|
663
|
+
- `--limit`: Maximum number of parts to return. Defaults to all of them.
|
|
633
664
|
- `--offset`: Number of parts to skip.
|
|
634
665
|
- `--json`: Output in JSON format.
|
|
635
666
|
|
|
@@ -672,7 +703,7 @@ sevdesk tags:list [options]
|
|
|
672
703
|
|
|
673
704
|
**Options:**
|
|
674
705
|
|
|
675
|
-
- `--limit`: Maximum number of tags to return.
|
|
706
|
+
- `--limit`: Maximum number of tags to return. Defaults to all of them.
|
|
676
707
|
- `--offset`: Number of tags to skip.
|
|
677
708
|
- `--json`: Output in JSON format.
|
|
678
709
|
|
|
@@ -719,12 +750,12 @@ sevdesk transactions:list [options]
|
|
|
719
750
|
**Options:**
|
|
720
751
|
|
|
721
752
|
- `--check-account`: Only show transactions of this check account ID.
|
|
722
|
-
- `--unbooked`: Only show transactions with status `100` (created). Filtered client-side because the sevdesk API ignores its `isBooked=false` filter
|
|
753
|
+
- `--unbooked`: Only show transactions with status `100` (created). Filtered client-side because the sevdesk API ignores its `isBooked=false` filter. Defaults to `false`.
|
|
723
754
|
- `--start-date`: Only show transactions on or after this date (ISO 8601).
|
|
724
755
|
- `--end-date`: Only show transactions on or before this date (ISO 8601).
|
|
725
756
|
- `--payee`: Only show transactions with this payee or payer name.
|
|
726
757
|
- `--purpose`: Only show transactions with this payment purpose.
|
|
727
|
-
- `--limit`: The maximum number of transactions to return.
|
|
758
|
+
- `--limit`: The maximum number of transactions to return. Defaults to all of them.
|
|
728
759
|
- `--offset`: The number of transactions to skip.
|
|
729
760
|
- `--json`: Output in JSON format.
|
|
730
761
|
|
|
@@ -768,6 +799,8 @@ sevdesk vouchers:create [options]
|
|
|
768
799
|
- `--tax-rate`: Tax rate of the voucher position in percent. Defaults to `19`.
|
|
769
800
|
- `--voucher-date`: Date as `dd.mm.yyyy` or Unix timestamp.
|
|
770
801
|
- `--pay-date`: Date as `dd.mm.yyyy` or Unix timestamp.
|
|
802
|
+
- `--delivery-date`: Start of the service period (Leistungszeitraum), or the single service date, as `dd.mm.yyyy` or Unix timestamp.
|
|
803
|
+
- `--delivery-date-until`: End of the service period as `dd.mm.yyyy` or Unix timestamp. Requires `--delivery-date`.
|
|
771
804
|
- `--supplier-id`: ID of the supplier contact.
|
|
772
805
|
- `--supplier-name`: Name of the supplier, used when no supplier ID is given.
|
|
773
806
|
- `--description`: The voucher number.
|
|
@@ -817,7 +850,7 @@ sevdesk vouchers:list [options]
|
|
|
817
850
|
- `--start-date`: Only vouchers on or after this date as `dd.mm.yyyy` or Unix timestamp.
|
|
818
851
|
- `--end-date`: Only vouchers on or before this date as `dd.mm.yyyy` or Unix timestamp.
|
|
819
852
|
- `--contact`: ID of the contact whose vouchers to list.
|
|
820
|
-
- `--limit`: Maximum number of vouchers to return.
|
|
853
|
+
- `--limit`: Maximum number of vouchers to return. Defaults to all of them.
|
|
821
854
|
- `--offset`: Number of vouchers to skip.
|
|
822
855
|
- `--json`: Output in JSON format.
|
|
823
856
|
|
|
@@ -832,7 +865,7 @@ sevdesk vouchers:positions [options]
|
|
|
832
865
|
**Options:**
|
|
833
866
|
|
|
834
867
|
- `--voucher`: ID of the voucher whose positions to list.
|
|
835
|
-
- `--limit`: Maximum number of positions to return.
|
|
868
|
+
- `--limit`: Maximum number of positions to return. Defaults to all of them.
|
|
836
869
|
- `--offset`: Number of positions to skip.
|
|
837
870
|
- `--json`: Output in JSON format.
|
|
838
871
|
|
package/dist/index.js
CHANGED
|
@@ -148,6 +148,17 @@ function contactLabel(ref) {
|
|
|
148
148
|
const personName = [ref.surename, ref.familyname].filter((part) => part).join(" ");
|
|
149
149
|
return ref.name || personName || ref.id || "-";
|
|
150
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Formats a service period (Leistungszeitraum) as plain dates, collapsing to a
|
|
153
|
+
* single date when there is no end. The API returns local datetimes, so the
|
|
154
|
+
* date part is sliced off instead of parsed, which would shift the day across
|
|
155
|
+
* the UTC boundary.
|
|
156
|
+
*/
|
|
157
|
+
function servicePeriodLabel(from, until) {
|
|
158
|
+
if (!from) return "";
|
|
159
|
+
const start = from.slice(0, 10);
|
|
160
|
+
return until ? `${start} – ${until.slice(0, 10)}` : start;
|
|
161
|
+
}
|
|
151
162
|
function printJson(value) {
|
|
152
163
|
console.log(JSON.stringify(value, null, 2));
|
|
153
164
|
}
|
|
@@ -161,6 +172,109 @@ function printTable(rows) {
|
|
|
161
172
|
for (const row of rows) console.log(line(columns.map((column) => row[column] ?? "")));
|
|
162
173
|
}
|
|
163
174
|
//#endregion
|
|
175
|
+
//#region src/commands/accounts-datev/get.ts
|
|
176
|
+
var get_default$8 = defineCommand({
|
|
177
|
+
description: "Show a single booking account (AccountDatev), including hidden accounts that accounts-datev:list does not return. Backed by an undocumented sevdesk endpoint that may change without notice.",
|
|
178
|
+
options: defineOptions(z.object({
|
|
179
|
+
id: z.coerce.number().optional().describe("The booking account ID. If omitted, you will be prompted."),
|
|
180
|
+
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
181
|
+
})),
|
|
182
|
+
action: async (options) => {
|
|
183
|
+
const client = await requireClient();
|
|
184
|
+
const accountDatevId = await requireNumberOption({
|
|
185
|
+
value: options.id,
|
|
186
|
+
requirement: "a booking account via --id",
|
|
187
|
+
question: "Enter the booking account ID:"
|
|
188
|
+
});
|
|
189
|
+
const account = await client.accountsDatev.get({ accountDatevId });
|
|
190
|
+
if (options.json) {
|
|
191
|
+
printJson(account);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
consola.info(`ID: ${account.id}`);
|
|
195
|
+
consola.info(`Number: ${account.number ?? "-"}`);
|
|
196
|
+
consola.info(`Name: ${account.name ?? "-"}`);
|
|
197
|
+
consola.info(`Tax rate: ${account.taxRate ?? "-"}`);
|
|
198
|
+
consola.info(`Deprecated: ${account.deprecated ?? "-"}`);
|
|
199
|
+
consola.info(`Hidden: ${account.hidden ?? "-"}`);
|
|
200
|
+
consola.info(`Deactivated: ${account.deactivated ?? "-"}`);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
//#endregion
|
|
204
|
+
//#region src/pagination.ts
|
|
205
|
+
/**
|
|
206
|
+
* Rows requested per page. The sevdesk API defaults to 100 when no `limit` is
|
|
207
|
+
* sent, which is why an unpaginated list silently stops at 100 rows.
|
|
208
|
+
*/
|
|
209
|
+
const PAGE_SIZE = 1e3;
|
|
210
|
+
/**
|
|
211
|
+
* Collects rows of a list endpoint across as many pages as needed.
|
|
212
|
+
*
|
|
213
|
+
* Paging stops on an empty page rather than a short one, so a server-side cap
|
|
214
|
+
* on `limit` cannot truncate the result the way the API default does.
|
|
215
|
+
*/
|
|
216
|
+
async function fetchAll(fetchPage, options = {}) {
|
|
217
|
+
const { limit, keep } = options;
|
|
218
|
+
const items = [];
|
|
219
|
+
let offset = options.offset ?? 0;
|
|
220
|
+
while (limit === void 0 || items.length < limit) {
|
|
221
|
+
const page = await fetchPage({
|
|
222
|
+
limit: pageSize(limit, items.length, keep),
|
|
223
|
+
offset
|
|
224
|
+
});
|
|
225
|
+
if (page.length === 0) break;
|
|
226
|
+
offset += page.length;
|
|
227
|
+
items.push(...keep === void 0 ? page : page.filter(keep));
|
|
228
|
+
}
|
|
229
|
+
return limit === void 0 ? items : items.slice(0, limit);
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Without a `keep` filter every row counts towards `limit`, so a small `limit`
|
|
233
|
+
* only needs a correspondingly small page.
|
|
234
|
+
*/
|
|
235
|
+
function pageSize(limit, collected, keep) {
|
|
236
|
+
if (limit === void 0 || keep !== void 0) return PAGE_SIZE;
|
|
237
|
+
return Math.min(limit - collected, PAGE_SIZE);
|
|
238
|
+
}
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region src/commands/accounts-datev/list.ts
|
|
241
|
+
var list_default$9 = defineCommand({
|
|
242
|
+
description: "List booking accounts (AccountDatev). Covers only accounts visible in the sevdesk account picker; hidden accounts (for example some tax accounts) are reachable via accounts-datev:get. Backed by an undocumented sevdesk endpoint that may change without notice.",
|
|
243
|
+
options: defineOptions(z.object({
|
|
244
|
+
number: z.string().optional().describe("Only show accounts with this account number. Filtered client-side across all visible accounts."),
|
|
245
|
+
nameLike: z.string().optional().describe("Only show accounts whose name contains this text. Filtered client-side across all visible accounts."),
|
|
246
|
+
limit: z.coerce.number().optional().describe("Maximum number of accounts to return. Defaults to all of them."),
|
|
247
|
+
offset: z.coerce.number().optional().describe("Number of accounts to skip before filtering."),
|
|
248
|
+
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
249
|
+
})),
|
|
250
|
+
action: async (options) => {
|
|
251
|
+
const client = await requireClient();
|
|
252
|
+
const needle = options.nameLike?.toLowerCase();
|
|
253
|
+
const filtering = options.number !== void 0 || needle !== void 0;
|
|
254
|
+
const accounts = await fetchAll((page) => client.accountsDatev.list(page), {
|
|
255
|
+
limit: options.limit,
|
|
256
|
+
offset: options.offset,
|
|
257
|
+
keep: filtering ? (account) => (options.number === void 0 || account.number === options.number) && (needle === void 0 || (account.name ?? "").toLowerCase().includes(needle)) : void 0
|
|
258
|
+
});
|
|
259
|
+
if (options.json) {
|
|
260
|
+
printJson(accounts);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (accounts.length === 0) {
|
|
264
|
+
consola.info("No booking accounts found.");
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
printTable(accounts.map((account) => ({
|
|
268
|
+
id: account.id,
|
|
269
|
+
number: account.number ?? "",
|
|
270
|
+
name: account.name ?? "",
|
|
271
|
+
taxRate: account.taxRate ?? "",
|
|
272
|
+
deprecated: account.deprecated ?? "",
|
|
273
|
+
hidden: account.hidden ?? ""
|
|
274
|
+
})));
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
//#endregion
|
|
164
278
|
//#region src/commands/accounts/balance.ts
|
|
165
279
|
var balance_default = defineCommand({
|
|
166
280
|
description: "Show the balance of a check account at a given date.",
|
|
@@ -285,12 +399,13 @@ var get_default$7 = defineCommand({
|
|
|
285
399
|
var list_default$8 = defineCommand({
|
|
286
400
|
description: "List your check accounts.",
|
|
287
401
|
options: defineOptions(z.object({
|
|
288
|
-
limit: z.coerce.number().optional().describe("The maximum number of check accounts to return."),
|
|
402
|
+
limit: z.coerce.number().optional().describe("The maximum number of check accounts to return. Defaults to all of them."),
|
|
289
403
|
offset: z.coerce.number().optional().describe("The number of check accounts to skip."),
|
|
290
404
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
291
405
|
})),
|
|
292
406
|
action: async (options) => {
|
|
293
|
-
const
|
|
407
|
+
const client = await requireClient();
|
|
408
|
+
const checkAccounts = await fetchAll((page) => client.checkAccounts.list(page), {
|
|
294
409
|
limit: options.limit,
|
|
295
410
|
offset: options.offset
|
|
296
411
|
});
|
|
@@ -506,8 +621,6 @@ var delete_default$1 = defineCommand({
|
|
|
506
621
|
});
|
|
507
622
|
//#endregion
|
|
508
623
|
//#region src/commands/contacts/get.ts
|
|
509
|
-
/** The `/ContactAddress` endpoint cannot filter by contact, so we filter here. */
|
|
510
|
-
const ADDRESS_LOOKUP_LIMIT = 100;
|
|
511
624
|
var get_default$6 = defineCommand({
|
|
512
625
|
description: "Show a single contact with its addresses and communication ways.",
|
|
513
626
|
options: defineOptions(z.object({
|
|
@@ -522,8 +635,12 @@ var get_default$6 = defineCommand({
|
|
|
522
635
|
question: "Enter the contact ID:"
|
|
523
636
|
});
|
|
524
637
|
const contact = await client.contacts.get({ contactId });
|
|
525
|
-
|
|
526
|
-
const
|
|
638
|
+
/** The `/ContactAddress` endpoint cannot filter by contact, so we filter here. */
|
|
639
|
+
const addresses = await fetchAll((page) => client.contactAddresses.list(page), { keep: (address) => address.contact.id === String(contactId) });
|
|
640
|
+
const communicationWays = await fetchAll((page) => client.communicationWays.list({
|
|
641
|
+
contactId,
|
|
642
|
+
...page
|
|
643
|
+
}));
|
|
527
644
|
if (options.json) {
|
|
528
645
|
printJson({
|
|
529
646
|
contact,
|
|
@@ -570,16 +687,19 @@ var list_default$7 = defineCommand({
|
|
|
570
687
|
customerNumber: z.string().optional().describe("Filter by customer number."),
|
|
571
688
|
depth: z.coerce.number().optional().describe("Contact depth: 0 returns only organizations, 1 organizations and persons. Defaults to 0."),
|
|
572
689
|
category: z.coerce.number().optional().describe("ID of the contact category to filter by: 2 supplier, 3 customer, 4 partner."),
|
|
573
|
-
limit: z.coerce.number().optional().describe("Maximum number of contacts to return."),
|
|
690
|
+
limit: z.coerce.number().optional().describe("Maximum number of contacts to return. Defaults to all of them."),
|
|
574
691
|
offset: z.coerce.number().optional().describe("Number of contacts to skip."),
|
|
575
692
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
576
693
|
})),
|
|
577
694
|
action: async (options) => {
|
|
578
|
-
const
|
|
695
|
+
const client = await requireClient();
|
|
696
|
+
const contacts = await fetchAll((page) => client.contacts.list({
|
|
579
697
|
name: options.name,
|
|
580
698
|
customerNumber: options.customerNumber,
|
|
581
699
|
depth: toDepth(options.depth),
|
|
582
700
|
categoryId: options.category,
|
|
701
|
+
...page
|
|
702
|
+
}), {
|
|
583
703
|
limit: options.limit,
|
|
584
704
|
offset: options.offset
|
|
585
705
|
});
|
|
@@ -692,20 +812,23 @@ var list_default$6 = defineCommand({
|
|
|
692
812
|
startDate: z.string().optional().describe("Only credit notes on or after this date as dd.mm.yyyy or Unix timestamp."),
|
|
693
813
|
endDate: z.string().optional().describe("Only credit notes on or before this date as dd.mm.yyyy or Unix timestamp."),
|
|
694
814
|
contact: z.coerce.number().optional().describe("ID of the contact whose credit notes to list."),
|
|
695
|
-
limit: z.coerce.number().optional().describe("Maximum number of credit notes to return."),
|
|
815
|
+
limit: z.coerce.number().optional().describe("Maximum number of credit notes to return. Defaults to all of them."),
|
|
696
816
|
offset: z.coerce.number().optional().describe("Number of credit notes to skip."),
|
|
697
817
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
698
818
|
})),
|
|
699
819
|
action: async (options) => {
|
|
700
|
-
const
|
|
820
|
+
const client = await requireClient();
|
|
821
|
+
const creditNotes = await fetchAll((page) => client.creditNotes.list({
|
|
701
822
|
status: options.status,
|
|
702
823
|
creditNoteNumber: options.creditNoteNumber,
|
|
703
824
|
startDate: options.startDate,
|
|
704
825
|
endDate: options.endDate,
|
|
705
826
|
contactId: options.contact,
|
|
827
|
+
embed: ["contact"],
|
|
828
|
+
...page
|
|
829
|
+
}), {
|
|
706
830
|
limit: options.limit,
|
|
707
|
-
offset: options.offset
|
|
708
|
-
embed: ["contact"]
|
|
831
|
+
offset: options.offset
|
|
709
832
|
});
|
|
710
833
|
if (options.json) {
|
|
711
834
|
printJson(creditNotes);
|
|
@@ -1003,7 +1126,7 @@ function formatTaxRules(taxRules) {
|
|
|
1003
1126
|
return names.join(", ");
|
|
1004
1127
|
}
|
|
1005
1128
|
var accounts_default = defineCommand({
|
|
1006
|
-
description: "List bookable accounts and their allowed tax rules. The first matching filter wins: --account-number, --tax-rule, --revenue, --expense. Without a filter, all accounts are listed.",
|
|
1129
|
+
description: "List bookable accounts and their allowed tax rules. Covers only the ReceiptGuidance subset of VAT-relevant accounts — use accounts-datev:list for all booking accounts. The first matching filter wins: --account-number, --tax-rule, --revenue, --expense. Without a filter, all accounts are listed.",
|
|
1007
1130
|
options: defineOptions(z.object({
|
|
1008
1131
|
accountNumber: z.string().optional().describe("Only show the account with this datev account number."),
|
|
1009
1132
|
taxRule: z.string().optional().describe("Tax rule name, for example USTPFL_UMS_EINN."),
|
|
@@ -1079,20 +1202,23 @@ var list_default$5 = defineCommand({
|
|
|
1079
1202
|
startDate: z.string().optional().describe("Only invoices on or after this date as dd.mm.yyyy or Unix timestamp."),
|
|
1080
1203
|
endDate: z.string().optional().describe("Only invoices on or before this date as dd.mm.yyyy or Unix timestamp."),
|
|
1081
1204
|
contact: z.coerce.number().optional().describe("ID of the contact whose invoices to list."),
|
|
1082
|
-
limit: z.coerce.number().optional().describe("Maximum number of invoices to return."),
|
|
1205
|
+
limit: z.coerce.number().optional().describe("Maximum number of invoices to return. Defaults to all of them."),
|
|
1083
1206
|
offset: z.coerce.number().optional().describe("Number of invoices to skip."),
|
|
1084
1207
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1085
1208
|
})),
|
|
1086
1209
|
action: async (options) => {
|
|
1087
|
-
const
|
|
1210
|
+
const client = await requireClient();
|
|
1211
|
+
const invoices = await fetchAll((page) => client.invoices.list({
|
|
1088
1212
|
status: options.status,
|
|
1089
1213
|
invoiceNumber: options.invoiceNumber,
|
|
1090
1214
|
startDate: options.startDate,
|
|
1091
1215
|
endDate: options.endDate,
|
|
1092
1216
|
contactId: options.contact,
|
|
1217
|
+
embed: ["contact"],
|
|
1218
|
+
...page
|
|
1219
|
+
}), {
|
|
1093
1220
|
limit: options.limit,
|
|
1094
|
-
offset: options.offset
|
|
1095
|
-
embed: ["contact"]
|
|
1221
|
+
offset: options.offset
|
|
1096
1222
|
});
|
|
1097
1223
|
if (options.json) {
|
|
1098
1224
|
printJson(invoices);
|
|
@@ -1229,20 +1355,23 @@ var list_default$4 = defineCommand({
|
|
|
1229
1355
|
startDate: z.string().optional().describe("Only orders on or after this date as dd.mm.yyyy or Unix timestamp."),
|
|
1230
1356
|
endDate: z.string().optional().describe("Only orders on or before this date as dd.mm.yyyy or Unix timestamp."),
|
|
1231
1357
|
contact: z.coerce.number().optional().describe("ID of the contact whose orders to list."),
|
|
1232
|
-
limit: z.coerce.number().optional().describe("Maximum number of orders to return."),
|
|
1358
|
+
limit: z.coerce.number().optional().describe("Maximum number of orders to return. Defaults to all of them."),
|
|
1233
1359
|
offset: z.coerce.number().optional().describe("Number of orders to skip."),
|
|
1234
1360
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1235
1361
|
})),
|
|
1236
1362
|
action: async (options) => {
|
|
1237
|
-
const
|
|
1363
|
+
const client = await requireClient();
|
|
1364
|
+
const orders = await fetchAll((page) => client.orders.list({
|
|
1238
1365
|
status: options.status,
|
|
1239
1366
|
orderNumber: options.orderNumber,
|
|
1240
1367
|
startDate: options.startDate,
|
|
1241
1368
|
endDate: options.endDate,
|
|
1242
1369
|
contactId: options.contact,
|
|
1370
|
+
embed: ["contact"],
|
|
1371
|
+
...page
|
|
1372
|
+
}), {
|
|
1243
1373
|
limit: options.limit,
|
|
1244
|
-
offset: options.offset
|
|
1245
|
-
embed: ["contact"]
|
|
1374
|
+
offset: options.offset
|
|
1246
1375
|
});
|
|
1247
1376
|
if (options.json) {
|
|
1248
1377
|
printJson(orders);
|
|
@@ -1334,14 +1463,17 @@ var list_default$3 = defineCommand({
|
|
|
1334
1463
|
options: defineOptions(z.object({
|
|
1335
1464
|
name: z.string().optional().describe("Filter by part name."),
|
|
1336
1465
|
partNumber: z.string().optional().describe("Filter by part number."),
|
|
1337
|
-
limit: z.coerce.number().optional().describe("Maximum number of parts to return."),
|
|
1466
|
+
limit: z.coerce.number().optional().describe("Maximum number of parts to return. Defaults to all of them."),
|
|
1338
1467
|
offset: z.coerce.number().optional().describe("Number of parts to skip."),
|
|
1339
1468
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1340
1469
|
})),
|
|
1341
1470
|
action: async (options) => {
|
|
1342
|
-
const
|
|
1471
|
+
const client = await requireClient();
|
|
1472
|
+
const parts = await fetchAll((page) => client.parts.list({
|
|
1343
1473
|
name: options.name,
|
|
1344
1474
|
partNumber: options.partNumber,
|
|
1475
|
+
...page
|
|
1476
|
+
}), {
|
|
1345
1477
|
limit: options.limit,
|
|
1346
1478
|
offset: options.offset
|
|
1347
1479
|
});
|
|
@@ -1450,12 +1582,13 @@ var delete_default = defineCommand({
|
|
|
1450
1582
|
var list_default$2 = defineCommand({
|
|
1451
1583
|
description: "List tags.",
|
|
1452
1584
|
options: defineOptions(z.object({
|
|
1453
|
-
limit: z.coerce.number().optional().describe("Maximum number of tags to return."),
|
|
1585
|
+
limit: z.coerce.number().optional().describe("Maximum number of tags to return. Defaults to all of them."),
|
|
1454
1586
|
offset: z.coerce.number().optional().describe("Number of tags to skip."),
|
|
1455
1587
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1456
1588
|
})),
|
|
1457
1589
|
action: async (options) => {
|
|
1458
|
-
const
|
|
1590
|
+
const client = await requireClient();
|
|
1591
|
+
const tags = await fetchAll((page) => client.tags.list(page), {
|
|
1459
1592
|
limit: options.limit,
|
|
1460
1593
|
offset: options.offset
|
|
1461
1594
|
});
|
|
@@ -1561,26 +1694,29 @@ var list_default$1 = defineCommand({
|
|
|
1561
1694
|
description: "List transactions of your check accounts.",
|
|
1562
1695
|
options: defineOptions(z.object({
|
|
1563
1696
|
checkAccount: z.coerce.number().optional().describe("Only show transactions of this check account ID."),
|
|
1564
|
-
unbooked: z.boolean().default(false).describe("Only show transactions with status 100 (created). Filtered client-side because the sevdesk API ignores its isBooked=false filter
|
|
1697
|
+
unbooked: z.boolean().default(false).describe("Only show transactions with status 100 (created). Filtered client-side because the sevdesk API ignores its isBooked=false filter."),
|
|
1565
1698
|
startDate: z.string().optional().describe("Only show transactions on or after this date (ISO 8601)."),
|
|
1566
1699
|
endDate: z.string().optional().describe("Only show transactions on or before this date (ISO 8601)."),
|
|
1567
1700
|
payee: z.string().optional().describe("Only show transactions with this payee or payer name."),
|
|
1568
1701
|
purpose: z.string().optional().describe("Only show transactions with this payment purpose."),
|
|
1569
|
-
limit: z.coerce.number().optional().describe("The maximum number of transactions to return."),
|
|
1702
|
+
limit: z.coerce.number().optional().describe("The maximum number of transactions to return. Defaults to all of them."),
|
|
1570
1703
|
offset: z.coerce.number().optional().describe("The number of transactions to skip."),
|
|
1571
1704
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1572
1705
|
})),
|
|
1573
1706
|
action: async (options) => {
|
|
1574
|
-
|
|
1707
|
+
const client = await requireClient();
|
|
1708
|
+
const transactions = await fetchAll((page) => client.transactions.list({
|
|
1575
1709
|
checkAccountId: options.checkAccount,
|
|
1576
1710
|
startDate: options.startDate,
|
|
1577
1711
|
endDate: options.endDate,
|
|
1578
1712
|
payeePayerName: options.payee,
|
|
1579
1713
|
paymtPurpose: options.purpose,
|
|
1714
|
+
...page
|
|
1715
|
+
}), {
|
|
1580
1716
|
limit: options.limit,
|
|
1581
|
-
offset: options.offset
|
|
1717
|
+
offset: options.offset,
|
|
1718
|
+
keep: options.unbooked ? (transaction) => transaction.status === "100" : void 0
|
|
1582
1719
|
});
|
|
1583
|
-
if (options.unbooked) transactions = transactions.filter((transaction) => transaction.status === "100");
|
|
1584
1720
|
if (options.json) {
|
|
1585
1721
|
printJson(transactions);
|
|
1586
1722
|
return;
|
|
@@ -1673,6 +1809,8 @@ var create_default = defineCommand({
|
|
|
1673
1809
|
taxRate: z.coerce.number().default(19).describe("Tax rate of the voucher position in percent."),
|
|
1674
1810
|
voucherDate: z.string().optional().describe("Date as dd.mm.yyyy or Unix timestamp."),
|
|
1675
1811
|
payDate: z.string().optional().describe("Date as dd.mm.yyyy or Unix timestamp."),
|
|
1812
|
+
deliveryDate: z.string().optional().describe("Start of the service period, or the single service date, as dd.mm.yyyy or Unix timestamp."),
|
|
1813
|
+
deliveryDateUntil: z.string().optional().describe("End of the service period as dd.mm.yyyy or Unix timestamp. Requires --delivery-date."),
|
|
1676
1814
|
supplierId: z.coerce.number().optional().describe("ID of the supplier contact."),
|
|
1677
1815
|
supplierName: z.string().optional().describe("Name of the supplier, used when no supplier ID is given."),
|
|
1678
1816
|
description: z.string().optional().describe("The voucher number."),
|
|
@@ -1680,6 +1818,10 @@ var create_default = defineCommand({
|
|
|
1680
1818
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1681
1819
|
})),
|
|
1682
1820
|
action: async (options) => {
|
|
1821
|
+
if (options.deliveryDateUntil !== void 0 && options.deliveryDate === void 0) {
|
|
1822
|
+
consola.error("You must provide --delivery-date when using --delivery-date-until.");
|
|
1823
|
+
process.exit(1);
|
|
1824
|
+
}
|
|
1683
1825
|
const client = await requireClient();
|
|
1684
1826
|
const path = await requireStringOption({
|
|
1685
1827
|
value: options.file,
|
|
@@ -1719,6 +1861,8 @@ var create_default = defineCommand({
|
|
|
1719
1861
|
taxRuleId,
|
|
1720
1862
|
voucherDate: options.voucherDate,
|
|
1721
1863
|
payDate: options.payDate,
|
|
1864
|
+
deliveryDate: options.deliveryDate,
|
|
1865
|
+
deliveryDateUntil: options.deliveryDateUntil,
|
|
1722
1866
|
supplierId: options.supplierId,
|
|
1723
1867
|
supplierName,
|
|
1724
1868
|
description: options.description
|
|
@@ -1793,6 +1937,7 @@ var get_default = defineCommand({
|
|
|
1793
1937
|
consola.info(`ID: ${voucher.id}`);
|
|
1794
1938
|
consola.info(`Status: ${voucher.status ?? "-"}`);
|
|
1795
1939
|
consola.info(`Date: ${voucher.voucherDate ?? "-"}`);
|
|
1940
|
+
consola.info(`Service period: ${servicePeriodLabel(voucher.deliveryDate, voucher.deliveryDateUntil) || "-"}`);
|
|
1796
1941
|
consola.info(`Supplier: ${voucher.supplierName ?? contactLabel(voucher.supplier)}`);
|
|
1797
1942
|
consola.info(`Description: ${voucher.description ?? "-"}`);
|
|
1798
1943
|
consola.info(`Net: ${voucher.sumNet}`);
|
|
@@ -1813,21 +1958,24 @@ var list_default = defineCommand({
|
|
|
1813
1958
|
startDate: z.string().optional().describe("Only vouchers on or after this date as dd.mm.yyyy or Unix timestamp."),
|
|
1814
1959
|
endDate: z.string().optional().describe("Only vouchers on or before this date as dd.mm.yyyy or Unix timestamp."),
|
|
1815
1960
|
contact: z.coerce.number().optional().describe("ID of the contact whose vouchers to list."),
|
|
1816
|
-
limit: z.coerce.number().optional().describe("Maximum number of vouchers to return."),
|
|
1961
|
+
limit: z.coerce.number().optional().describe("Maximum number of vouchers to return. Defaults to all of them."),
|
|
1817
1962
|
offset: z.coerce.number().optional().describe("Number of vouchers to skip."),
|
|
1818
1963
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1819
1964
|
})),
|
|
1820
1965
|
action: async (options) => {
|
|
1821
|
-
const
|
|
1966
|
+
const client = await requireClient();
|
|
1967
|
+
const vouchers = await fetchAll((page) => client.vouchers.list({
|
|
1822
1968
|
status: options.status,
|
|
1823
1969
|
creditDebit: options.creditDebit,
|
|
1824
1970
|
descriptionLike: options.descriptionLike,
|
|
1825
1971
|
startDate: options.startDate,
|
|
1826
1972
|
endDate: options.endDate,
|
|
1827
1973
|
contactId: options.contact,
|
|
1974
|
+
embed: ["supplier"],
|
|
1975
|
+
...page
|
|
1976
|
+
}), {
|
|
1828
1977
|
limit: options.limit,
|
|
1829
|
-
offset: options.offset
|
|
1830
|
-
embed: ["supplier"]
|
|
1978
|
+
offset: options.offset
|
|
1831
1979
|
});
|
|
1832
1980
|
if (options.json) {
|
|
1833
1981
|
printJson(vouchers);
|
|
@@ -1840,6 +1988,7 @@ var list_default = defineCommand({
|
|
|
1840
1988
|
printTable(vouchers.map((voucher) => ({
|
|
1841
1989
|
id: voucher.id,
|
|
1842
1990
|
date: voucher.voucherDate ?? "",
|
|
1991
|
+
servicePeriod: servicePeriodLabel(voucher.deliveryDate, voucher.deliveryDateUntil),
|
|
1843
1992
|
supplier: voucher.supplierName ?? contactLabel(voucher.supplier),
|
|
1844
1993
|
description: voucher.description ?? "",
|
|
1845
1994
|
gross: voucher.sumGross,
|
|
@@ -1853,16 +2002,19 @@ var positions_default = defineCommand({
|
|
|
1853
2002
|
description: "List voucher positions.",
|
|
1854
2003
|
options: defineOptions(z.object({
|
|
1855
2004
|
voucher: z.coerce.number().optional().describe("ID of the voucher whose positions to list."),
|
|
1856
|
-
limit: z.coerce.number().optional().describe("Maximum number of positions to return."),
|
|
2005
|
+
limit: z.coerce.number().optional().describe("Maximum number of positions to return. Defaults to all of them."),
|
|
1857
2006
|
offset: z.coerce.number().optional().describe("Number of positions to skip."),
|
|
1858
2007
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1859
2008
|
})),
|
|
1860
2009
|
action: async (options) => {
|
|
1861
|
-
const
|
|
2010
|
+
const client = await requireClient();
|
|
2011
|
+
const positions = await fetchAll((page) => client.vouchers.listPositions({
|
|
1862
2012
|
voucherId: options.voucher,
|
|
2013
|
+
embed: ["accountDatev"],
|
|
2014
|
+
...page
|
|
2015
|
+
}), {
|
|
1863
2016
|
limit: options.limit,
|
|
1864
|
-
offset: options.offset
|
|
1865
|
-
embed: ["accountDatev"]
|
|
2017
|
+
offset: options.offset
|
|
1866
2018
|
});
|
|
1867
2019
|
if (options.json) {
|
|
1868
2020
|
printJson(positions);
|
|
@@ -1958,6 +2110,8 @@ const config = defineConfig({
|
|
|
1958
2110
|
login: login_default,
|
|
1959
2111
|
logout: logout_default,
|
|
1960
2112
|
doctor: doctor_default,
|
|
2113
|
+
"accounts-datev:get": get_default$8,
|
|
2114
|
+
"accounts-datev:list": list_default$9,
|
|
1961
2115
|
"accounts:balance": balance_default,
|
|
1962
2116
|
"accounts:create-clearing": create_clearing_default,
|
|
1963
2117
|
"accounts:create-file-import": create_file_import_default,
|