@genz-its/sevdesk-cli 0.1.3 → 0.1.5
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 +49 -13
- package/dist/index.js +206 -62
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
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
|
}
|
|
@@ -190,40 +201,60 @@ var get_default$8 = defineCommand({
|
|
|
190
201
|
}
|
|
191
202
|
});
|
|
192
203
|
//#endregion
|
|
193
|
-
//#region src/
|
|
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
|
+
*/
|
|
194
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
|
|
195
241
|
var list_default$9 = defineCommand({
|
|
196
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.",
|
|
197
243
|
options: defineOptions(z.object({
|
|
198
244
|
number: z.string().optional().describe("Only show accounts with this account number. Filtered client-side across all visible accounts."),
|
|
199
245
|
nameLike: z.string().optional().describe("Only show accounts whose name contains this text. Filtered client-side across all visible accounts."),
|
|
200
|
-
limit: z.coerce.number().optional().describe("Maximum number of accounts to return."),
|
|
201
|
-
offset: z.coerce.number().optional().describe("Number of accounts to skip
|
|
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."),
|
|
202
248
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
203
249
|
})),
|
|
204
250
|
action: async (options) => {
|
|
205
251
|
const client = await requireClient();
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
accounts = [];
|
|
210
|
-
for (let offset = 0;; offset += PAGE_SIZE) {
|
|
211
|
-
const page = await client.accountsDatev.list({
|
|
212
|
-
limit: PAGE_SIZE,
|
|
213
|
-
offset
|
|
214
|
-
});
|
|
215
|
-
accounts.push(...page);
|
|
216
|
-
if (page.length < PAGE_SIZE) break;
|
|
217
|
-
}
|
|
218
|
-
if (options.number !== void 0) accounts = accounts.filter((account) => account.number === options.number);
|
|
219
|
-
if (options.nameLike !== void 0) {
|
|
220
|
-
const needle = options.nameLike.toLowerCase();
|
|
221
|
-
accounts = accounts.filter((account) => (account.name ?? "").toLowerCase().includes(needle));
|
|
222
|
-
}
|
|
223
|
-
if (options.limit !== void 0) accounts = accounts.slice(0, options.limit);
|
|
224
|
-
} else accounts = await client.accountsDatev.list({
|
|
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), {
|
|
225
255
|
limit: options.limit,
|
|
226
|
-
offset: options.offset
|
|
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
|
|
227
258
|
});
|
|
228
259
|
if (options.json) {
|
|
229
260
|
printJson(accounts);
|
|
@@ -368,12 +399,13 @@ var get_default$7 = defineCommand({
|
|
|
368
399
|
var list_default$8 = defineCommand({
|
|
369
400
|
description: "List your check accounts.",
|
|
370
401
|
options: defineOptions(z.object({
|
|
371
|
-
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."),
|
|
372
403
|
offset: z.coerce.number().optional().describe("The number of check accounts to skip."),
|
|
373
404
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
374
405
|
})),
|
|
375
406
|
action: async (options) => {
|
|
376
|
-
const
|
|
407
|
+
const client = await requireClient();
|
|
408
|
+
const checkAccounts = await fetchAll((page) => client.checkAccounts.list(page), {
|
|
377
409
|
limit: options.limit,
|
|
378
410
|
offset: options.offset
|
|
379
411
|
});
|
|
@@ -588,9 +620,36 @@ var delete_default$1 = defineCommand({
|
|
|
588
620
|
}
|
|
589
621
|
});
|
|
590
622
|
//#endregion
|
|
623
|
+
//#region src/commands/contacts/delete-address.ts
|
|
624
|
+
var delete_address_default = defineCommand({
|
|
625
|
+
description: "Delete an address of a contact.",
|
|
626
|
+
options: defineOptions(z.object({
|
|
627
|
+
id: z.coerce.number().optional().describe("The contact address ID, as shown by contacts:get. If omitted, you will be prompted."),
|
|
628
|
+
yes: z.boolean().default(false).describe("Skip the confirmation prompt."),
|
|
629
|
+
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
630
|
+
})),
|
|
631
|
+
action: async (options) => {
|
|
632
|
+
const client = await requireClient();
|
|
633
|
+
const contactAddressId = await requireNumberOption({
|
|
634
|
+
value: options.id,
|
|
635
|
+
requirement: "a contact address ID via --id",
|
|
636
|
+
question: "Enter the contact address ID:"
|
|
637
|
+
});
|
|
638
|
+
if (!await confirmOrAbort({
|
|
639
|
+
message: `Delete contact address ${contactAddressId}?`,
|
|
640
|
+
yes: options.yes,
|
|
641
|
+
initial: false
|
|
642
|
+
})) return;
|
|
643
|
+
await client.contactAddresses.delete({ contactAddressId });
|
|
644
|
+
if (options.json) {
|
|
645
|
+
printJson({ deleted: true });
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
consola.success("Contact address deleted.");
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
//#endregion
|
|
591
652
|
//#region src/commands/contacts/get.ts
|
|
592
|
-
/** The `/ContactAddress` endpoint cannot filter by contact, so we filter here. */
|
|
593
|
-
const ADDRESS_LOOKUP_LIMIT = 100;
|
|
594
653
|
var get_default$6 = defineCommand({
|
|
595
654
|
description: "Show a single contact with its addresses and communication ways.",
|
|
596
655
|
options: defineOptions(z.object({
|
|
@@ -605,8 +664,12 @@ var get_default$6 = defineCommand({
|
|
|
605
664
|
question: "Enter the contact ID:"
|
|
606
665
|
});
|
|
607
666
|
const contact = await client.contacts.get({ contactId });
|
|
608
|
-
|
|
609
|
-
const
|
|
667
|
+
/** The `/ContactAddress` endpoint cannot filter by contact, so we filter here. */
|
|
668
|
+
const addresses = await fetchAll((page) => client.contactAddresses.list(page), { keep: (address) => address.contact.id === String(contactId) });
|
|
669
|
+
const communicationWays = await fetchAll((page) => client.communicationWays.list({
|
|
670
|
+
contactId,
|
|
671
|
+
...page
|
|
672
|
+
}));
|
|
610
673
|
if (options.json) {
|
|
611
674
|
printJson({
|
|
612
675
|
contact,
|
|
@@ -633,12 +696,14 @@ function printSection(title, lines) {
|
|
|
633
696
|
consola.info(title);
|
|
634
697
|
for (const line of lines.length === 0 ? ["-"] : lines) consola.info(` ${line}`);
|
|
635
698
|
}
|
|
699
|
+
/** The id is shown because contacts:update-address and contacts:delete-address need it. */
|
|
636
700
|
function formatAddress(address) {
|
|
637
|
-
|
|
701
|
+
const parts = [
|
|
638
702
|
address.street,
|
|
639
703
|
[address.zip, address.city].filter((part) => part).join(" "),
|
|
640
704
|
`country ${address.country.id}`
|
|
641
|
-
]
|
|
705
|
+
];
|
|
706
|
+
return `#${address.id} ${parts.filter((part) => part).join(", ")}`;
|
|
642
707
|
}
|
|
643
708
|
function formatCommunicationWay(communicationWay) {
|
|
644
709
|
const main = communicationWay.main === "1" ? " (main)" : "";
|
|
@@ -653,16 +718,19 @@ var list_default$7 = defineCommand({
|
|
|
653
718
|
customerNumber: z.string().optional().describe("Filter by customer number."),
|
|
654
719
|
depth: z.coerce.number().optional().describe("Contact depth: 0 returns only organizations, 1 organizations and persons. Defaults to 0."),
|
|
655
720
|
category: z.coerce.number().optional().describe("ID of the contact category to filter by: 2 supplier, 3 customer, 4 partner."),
|
|
656
|
-
limit: z.coerce.number().optional().describe("Maximum number of contacts to return."),
|
|
721
|
+
limit: z.coerce.number().optional().describe("Maximum number of contacts to return. Defaults to all of them."),
|
|
657
722
|
offset: z.coerce.number().optional().describe("Number of contacts to skip."),
|
|
658
723
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
659
724
|
})),
|
|
660
725
|
action: async (options) => {
|
|
661
|
-
const
|
|
726
|
+
const client = await requireClient();
|
|
727
|
+
const contacts = await fetchAll((page) => client.contacts.list({
|
|
662
728
|
name: options.name,
|
|
663
729
|
customerNumber: options.customerNumber,
|
|
664
730
|
depth: toDepth(options.depth),
|
|
665
731
|
categoryId: options.category,
|
|
732
|
+
...page
|
|
733
|
+
}), {
|
|
666
734
|
limit: options.limit,
|
|
667
735
|
offset: options.offset
|
|
668
736
|
});
|
|
@@ -732,6 +800,48 @@ var update_default = defineCommand({
|
|
|
732
800
|
}
|
|
733
801
|
});
|
|
734
802
|
//#endregion
|
|
803
|
+
//#region src/commands/contacts/update-address.ts
|
|
804
|
+
var update_address_default = defineCommand({
|
|
805
|
+
description: "Update an address of a contact.",
|
|
806
|
+
options: defineOptions(z.object({
|
|
807
|
+
id: z.coerce.number().optional().describe("The contact address ID, as shown by contacts:get. If omitted, you will be prompted."),
|
|
808
|
+
street: z.string().optional().describe("Street and house number."),
|
|
809
|
+
zip: z.string().optional().describe("Zip code."),
|
|
810
|
+
city: z.string().optional().describe("City name."),
|
|
811
|
+
country: z.coerce.number().optional().describe("ID of the country as a StaticCountry ID, for example 1 for Germany."),
|
|
812
|
+
category: z.coerce.number().optional().describe("ID of the address category."),
|
|
813
|
+
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
814
|
+
})),
|
|
815
|
+
action: async (options) => {
|
|
816
|
+
const fields = {
|
|
817
|
+
street: options.street,
|
|
818
|
+
zip: options.zip,
|
|
819
|
+
city: options.city,
|
|
820
|
+
countryId: options.country,
|
|
821
|
+
categoryId: options.category
|
|
822
|
+
};
|
|
823
|
+
if (Object.values(fields).every((value) => value === void 0)) {
|
|
824
|
+
consola.error("You must provide at least one of --street, --zip, --city, --country or --category.");
|
|
825
|
+
process.exit(1);
|
|
826
|
+
}
|
|
827
|
+
const client = await requireClient();
|
|
828
|
+
const contactAddressId = await requireNumberOption({
|
|
829
|
+
value: options.id,
|
|
830
|
+
requirement: "a contact address ID via --id",
|
|
831
|
+
question: "Enter the contact address ID:"
|
|
832
|
+
});
|
|
833
|
+
const address = await client.contactAddresses.update({
|
|
834
|
+
contactAddressId,
|
|
835
|
+
...fields
|
|
836
|
+
});
|
|
837
|
+
if (options.json) {
|
|
838
|
+
printJson(address);
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
consola.success(`Updated contact address ${address.id}.`);
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
//#endregion
|
|
735
845
|
//#region src/commands/credit-notes/get.ts
|
|
736
846
|
var get_default$5 = defineCommand({
|
|
737
847
|
description: "Show a single credit note.",
|
|
@@ -775,20 +885,23 @@ var list_default$6 = defineCommand({
|
|
|
775
885
|
startDate: z.string().optional().describe("Only credit notes on or after this date as dd.mm.yyyy or Unix timestamp."),
|
|
776
886
|
endDate: z.string().optional().describe("Only credit notes on or before this date as dd.mm.yyyy or Unix timestamp."),
|
|
777
887
|
contact: z.coerce.number().optional().describe("ID of the contact whose credit notes to list."),
|
|
778
|
-
limit: z.coerce.number().optional().describe("Maximum number of credit notes to return."),
|
|
888
|
+
limit: z.coerce.number().optional().describe("Maximum number of credit notes to return. Defaults to all of them."),
|
|
779
889
|
offset: z.coerce.number().optional().describe("Number of credit notes to skip."),
|
|
780
890
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
781
891
|
})),
|
|
782
892
|
action: async (options) => {
|
|
783
|
-
const
|
|
893
|
+
const client = await requireClient();
|
|
894
|
+
const creditNotes = await fetchAll((page) => client.creditNotes.list({
|
|
784
895
|
status: options.status,
|
|
785
896
|
creditNoteNumber: options.creditNoteNumber,
|
|
786
897
|
startDate: options.startDate,
|
|
787
898
|
endDate: options.endDate,
|
|
788
899
|
contactId: options.contact,
|
|
900
|
+
embed: ["contact"],
|
|
901
|
+
...page
|
|
902
|
+
}), {
|
|
789
903
|
limit: options.limit,
|
|
790
|
-
offset: options.offset
|
|
791
|
-
embed: ["contact"]
|
|
904
|
+
offset: options.offset
|
|
792
905
|
});
|
|
793
906
|
if (options.json) {
|
|
794
907
|
printJson(creditNotes);
|
|
@@ -1162,20 +1275,23 @@ var list_default$5 = defineCommand({
|
|
|
1162
1275
|
startDate: z.string().optional().describe("Only invoices on or after this date as dd.mm.yyyy or Unix timestamp."),
|
|
1163
1276
|
endDate: z.string().optional().describe("Only invoices on or before this date as dd.mm.yyyy or Unix timestamp."),
|
|
1164
1277
|
contact: z.coerce.number().optional().describe("ID of the contact whose invoices to list."),
|
|
1165
|
-
limit: z.coerce.number().optional().describe("Maximum number of invoices to return."),
|
|
1278
|
+
limit: z.coerce.number().optional().describe("Maximum number of invoices to return. Defaults to all of them."),
|
|
1166
1279
|
offset: z.coerce.number().optional().describe("Number of invoices to skip."),
|
|
1167
1280
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1168
1281
|
})),
|
|
1169
1282
|
action: async (options) => {
|
|
1170
|
-
const
|
|
1283
|
+
const client = await requireClient();
|
|
1284
|
+
const invoices = await fetchAll((page) => client.invoices.list({
|
|
1171
1285
|
status: options.status,
|
|
1172
1286
|
invoiceNumber: options.invoiceNumber,
|
|
1173
1287
|
startDate: options.startDate,
|
|
1174
1288
|
endDate: options.endDate,
|
|
1175
1289
|
contactId: options.contact,
|
|
1290
|
+
embed: ["contact"],
|
|
1291
|
+
...page
|
|
1292
|
+
}), {
|
|
1176
1293
|
limit: options.limit,
|
|
1177
|
-
offset: options.offset
|
|
1178
|
-
embed: ["contact"]
|
|
1294
|
+
offset: options.offset
|
|
1179
1295
|
});
|
|
1180
1296
|
if (options.json) {
|
|
1181
1297
|
printJson(invoices);
|
|
@@ -1312,20 +1428,23 @@ var list_default$4 = defineCommand({
|
|
|
1312
1428
|
startDate: z.string().optional().describe("Only orders on or after this date as dd.mm.yyyy or Unix timestamp."),
|
|
1313
1429
|
endDate: z.string().optional().describe("Only orders on or before this date as dd.mm.yyyy or Unix timestamp."),
|
|
1314
1430
|
contact: z.coerce.number().optional().describe("ID of the contact whose orders to list."),
|
|
1315
|
-
limit: z.coerce.number().optional().describe("Maximum number of orders to return."),
|
|
1431
|
+
limit: z.coerce.number().optional().describe("Maximum number of orders to return. Defaults to all of them."),
|
|
1316
1432
|
offset: z.coerce.number().optional().describe("Number of orders to skip."),
|
|
1317
1433
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1318
1434
|
})),
|
|
1319
1435
|
action: async (options) => {
|
|
1320
|
-
const
|
|
1436
|
+
const client = await requireClient();
|
|
1437
|
+
const orders = await fetchAll((page) => client.orders.list({
|
|
1321
1438
|
status: options.status,
|
|
1322
1439
|
orderNumber: options.orderNumber,
|
|
1323
1440
|
startDate: options.startDate,
|
|
1324
1441
|
endDate: options.endDate,
|
|
1325
1442
|
contactId: options.contact,
|
|
1443
|
+
embed: ["contact"],
|
|
1444
|
+
...page
|
|
1445
|
+
}), {
|
|
1326
1446
|
limit: options.limit,
|
|
1327
|
-
offset: options.offset
|
|
1328
|
-
embed: ["contact"]
|
|
1447
|
+
offset: options.offset
|
|
1329
1448
|
});
|
|
1330
1449
|
if (options.json) {
|
|
1331
1450
|
printJson(orders);
|
|
@@ -1417,14 +1536,17 @@ var list_default$3 = defineCommand({
|
|
|
1417
1536
|
options: defineOptions(z.object({
|
|
1418
1537
|
name: z.string().optional().describe("Filter by part name."),
|
|
1419
1538
|
partNumber: z.string().optional().describe("Filter by part number."),
|
|
1420
|
-
limit: z.coerce.number().optional().describe("Maximum number of parts to return."),
|
|
1539
|
+
limit: z.coerce.number().optional().describe("Maximum number of parts to return. Defaults to all of them."),
|
|
1421
1540
|
offset: z.coerce.number().optional().describe("Number of parts to skip."),
|
|
1422
1541
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1423
1542
|
})),
|
|
1424
1543
|
action: async (options) => {
|
|
1425
|
-
const
|
|
1544
|
+
const client = await requireClient();
|
|
1545
|
+
const parts = await fetchAll((page) => client.parts.list({
|
|
1426
1546
|
name: options.name,
|
|
1427
1547
|
partNumber: options.partNumber,
|
|
1548
|
+
...page
|
|
1549
|
+
}), {
|
|
1428
1550
|
limit: options.limit,
|
|
1429
1551
|
offset: options.offset
|
|
1430
1552
|
});
|
|
@@ -1533,12 +1655,13 @@ var delete_default = defineCommand({
|
|
|
1533
1655
|
var list_default$2 = defineCommand({
|
|
1534
1656
|
description: "List tags.",
|
|
1535
1657
|
options: defineOptions(z.object({
|
|
1536
|
-
limit: z.coerce.number().optional().describe("Maximum number of tags to return."),
|
|
1658
|
+
limit: z.coerce.number().optional().describe("Maximum number of tags to return. Defaults to all of them."),
|
|
1537
1659
|
offset: z.coerce.number().optional().describe("Number of tags to skip."),
|
|
1538
1660
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1539
1661
|
})),
|
|
1540
1662
|
action: async (options) => {
|
|
1541
|
-
const
|
|
1663
|
+
const client = await requireClient();
|
|
1664
|
+
const tags = await fetchAll((page) => client.tags.list(page), {
|
|
1542
1665
|
limit: options.limit,
|
|
1543
1666
|
offset: options.offset
|
|
1544
1667
|
});
|
|
@@ -1644,26 +1767,29 @@ var list_default$1 = defineCommand({
|
|
|
1644
1767
|
description: "List transactions of your check accounts.",
|
|
1645
1768
|
options: defineOptions(z.object({
|
|
1646
1769
|
checkAccount: z.coerce.number().optional().describe("Only show transactions of this check account ID."),
|
|
1647
|
-
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
|
|
1770
|
+
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."),
|
|
1648
1771
|
startDate: z.string().optional().describe("Only show transactions on or after this date (ISO 8601)."),
|
|
1649
1772
|
endDate: z.string().optional().describe("Only show transactions on or before this date (ISO 8601)."),
|
|
1650
1773
|
payee: z.string().optional().describe("Only show transactions with this payee or payer name."),
|
|
1651
1774
|
purpose: z.string().optional().describe("Only show transactions with this payment purpose."),
|
|
1652
|
-
limit: z.coerce.number().optional().describe("The maximum number of transactions to return."),
|
|
1775
|
+
limit: z.coerce.number().optional().describe("The maximum number of transactions to return. Defaults to all of them."),
|
|
1653
1776
|
offset: z.coerce.number().optional().describe("The number of transactions to skip."),
|
|
1654
1777
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1655
1778
|
})),
|
|
1656
1779
|
action: async (options) => {
|
|
1657
|
-
|
|
1780
|
+
const client = await requireClient();
|
|
1781
|
+
const transactions = await fetchAll((page) => client.transactions.list({
|
|
1658
1782
|
checkAccountId: options.checkAccount,
|
|
1659
1783
|
startDate: options.startDate,
|
|
1660
1784
|
endDate: options.endDate,
|
|
1661
1785
|
payeePayerName: options.payee,
|
|
1662
1786
|
paymtPurpose: options.purpose,
|
|
1787
|
+
...page
|
|
1788
|
+
}), {
|
|
1663
1789
|
limit: options.limit,
|
|
1664
|
-
offset: options.offset
|
|
1790
|
+
offset: options.offset,
|
|
1791
|
+
keep: options.unbooked ? (transaction) => transaction.status === "100" : void 0
|
|
1665
1792
|
});
|
|
1666
|
-
if (options.unbooked) transactions = transactions.filter((transaction) => transaction.status === "100");
|
|
1667
1793
|
if (options.json) {
|
|
1668
1794
|
printJson(transactions);
|
|
1669
1795
|
return;
|
|
@@ -1756,6 +1882,8 @@ var create_default = defineCommand({
|
|
|
1756
1882
|
taxRate: z.coerce.number().default(19).describe("Tax rate of the voucher position in percent."),
|
|
1757
1883
|
voucherDate: z.string().optional().describe("Date as dd.mm.yyyy or Unix timestamp."),
|
|
1758
1884
|
payDate: z.string().optional().describe("Date as dd.mm.yyyy or Unix timestamp."),
|
|
1885
|
+
deliveryDate: z.string().optional().describe("Start of the service period, or the single service date, as dd.mm.yyyy or Unix timestamp."),
|
|
1886
|
+
deliveryDateUntil: z.string().optional().describe("End of the service period as dd.mm.yyyy or Unix timestamp. Requires --delivery-date."),
|
|
1759
1887
|
supplierId: z.coerce.number().optional().describe("ID of the supplier contact."),
|
|
1760
1888
|
supplierName: z.string().optional().describe("Name of the supplier, used when no supplier ID is given."),
|
|
1761
1889
|
description: z.string().optional().describe("The voucher number."),
|
|
@@ -1763,6 +1891,10 @@ var create_default = defineCommand({
|
|
|
1763
1891
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1764
1892
|
})),
|
|
1765
1893
|
action: async (options) => {
|
|
1894
|
+
if (options.deliveryDateUntil !== void 0 && options.deliveryDate === void 0) {
|
|
1895
|
+
consola.error("You must provide --delivery-date when using --delivery-date-until.");
|
|
1896
|
+
process.exit(1);
|
|
1897
|
+
}
|
|
1766
1898
|
const client = await requireClient();
|
|
1767
1899
|
const path = await requireStringOption({
|
|
1768
1900
|
value: options.file,
|
|
@@ -1802,6 +1934,8 @@ var create_default = defineCommand({
|
|
|
1802
1934
|
taxRuleId,
|
|
1803
1935
|
voucherDate: options.voucherDate,
|
|
1804
1936
|
payDate: options.payDate,
|
|
1937
|
+
deliveryDate: options.deliveryDate,
|
|
1938
|
+
deliveryDateUntil: options.deliveryDateUntil,
|
|
1805
1939
|
supplierId: options.supplierId,
|
|
1806
1940
|
supplierName,
|
|
1807
1941
|
description: options.description
|
|
@@ -1876,6 +2010,7 @@ var get_default = defineCommand({
|
|
|
1876
2010
|
consola.info(`ID: ${voucher.id}`);
|
|
1877
2011
|
consola.info(`Status: ${voucher.status ?? "-"}`);
|
|
1878
2012
|
consola.info(`Date: ${voucher.voucherDate ?? "-"}`);
|
|
2013
|
+
consola.info(`Service period: ${servicePeriodLabel(voucher.deliveryDate, voucher.deliveryDateUntil) || "-"}`);
|
|
1879
2014
|
consola.info(`Supplier: ${voucher.supplierName ?? contactLabel(voucher.supplier)}`);
|
|
1880
2015
|
consola.info(`Description: ${voucher.description ?? "-"}`);
|
|
1881
2016
|
consola.info(`Net: ${voucher.sumNet}`);
|
|
@@ -1896,21 +2031,24 @@ var list_default = defineCommand({
|
|
|
1896
2031
|
startDate: z.string().optional().describe("Only vouchers on or after this date as dd.mm.yyyy or Unix timestamp."),
|
|
1897
2032
|
endDate: z.string().optional().describe("Only vouchers on or before this date as dd.mm.yyyy or Unix timestamp."),
|
|
1898
2033
|
contact: z.coerce.number().optional().describe("ID of the contact whose vouchers to list."),
|
|
1899
|
-
limit: z.coerce.number().optional().describe("Maximum number of vouchers to return."),
|
|
2034
|
+
limit: z.coerce.number().optional().describe("Maximum number of vouchers to return. Defaults to all of them."),
|
|
1900
2035
|
offset: z.coerce.number().optional().describe("Number of vouchers to skip."),
|
|
1901
2036
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1902
2037
|
})),
|
|
1903
2038
|
action: async (options) => {
|
|
1904
|
-
const
|
|
2039
|
+
const client = await requireClient();
|
|
2040
|
+
const vouchers = await fetchAll((page) => client.vouchers.list({
|
|
1905
2041
|
status: options.status,
|
|
1906
2042
|
creditDebit: options.creditDebit,
|
|
1907
2043
|
descriptionLike: options.descriptionLike,
|
|
1908
2044
|
startDate: options.startDate,
|
|
1909
2045
|
endDate: options.endDate,
|
|
1910
2046
|
contactId: options.contact,
|
|
2047
|
+
embed: ["supplier"],
|
|
2048
|
+
...page
|
|
2049
|
+
}), {
|
|
1911
2050
|
limit: options.limit,
|
|
1912
|
-
offset: options.offset
|
|
1913
|
-
embed: ["supplier"]
|
|
2051
|
+
offset: options.offset
|
|
1914
2052
|
});
|
|
1915
2053
|
if (options.json) {
|
|
1916
2054
|
printJson(vouchers);
|
|
@@ -1923,6 +2061,7 @@ var list_default = defineCommand({
|
|
|
1923
2061
|
printTable(vouchers.map((voucher) => ({
|
|
1924
2062
|
id: voucher.id,
|
|
1925
2063
|
date: voucher.voucherDate ?? "",
|
|
2064
|
+
servicePeriod: servicePeriodLabel(voucher.deliveryDate, voucher.deliveryDateUntil),
|
|
1926
2065
|
supplier: voucher.supplierName ?? contactLabel(voucher.supplier),
|
|
1927
2066
|
description: voucher.description ?? "",
|
|
1928
2067
|
gross: voucher.sumGross,
|
|
@@ -1936,16 +2075,19 @@ var positions_default = defineCommand({
|
|
|
1936
2075
|
description: "List voucher positions.",
|
|
1937
2076
|
options: defineOptions(z.object({
|
|
1938
2077
|
voucher: z.coerce.number().optional().describe("ID of the voucher whose positions to list."),
|
|
1939
|
-
limit: z.coerce.number().optional().describe("Maximum number of positions to return."),
|
|
2078
|
+
limit: z.coerce.number().optional().describe("Maximum number of positions to return. Defaults to all of them."),
|
|
1940
2079
|
offset: z.coerce.number().optional().describe("Number of positions to skip."),
|
|
1941
2080
|
json: z.boolean().default(false).describe("Output in JSON format.")
|
|
1942
2081
|
})),
|
|
1943
2082
|
action: async (options) => {
|
|
1944
|
-
const
|
|
2083
|
+
const client = await requireClient();
|
|
2084
|
+
const positions = await fetchAll((page) => client.vouchers.listPositions({
|
|
1945
2085
|
voucherId: options.voucher,
|
|
2086
|
+
embed: ["accountDatev"],
|
|
2087
|
+
...page
|
|
2088
|
+
}), {
|
|
1946
2089
|
limit: options.limit,
|
|
1947
|
-
offset: options.offset
|
|
1948
|
-
embed: ["accountDatev"]
|
|
2090
|
+
offset: options.offset
|
|
1949
2091
|
});
|
|
1950
2092
|
if (options.json) {
|
|
1951
2093
|
printJson(positions);
|
|
@@ -2053,9 +2195,11 @@ const config = defineConfig({
|
|
|
2053
2195
|
"contacts:add-phone": add_phone_default,
|
|
2054
2196
|
"contacts:create": create_default$3,
|
|
2055
2197
|
"contacts:delete": delete_default$1,
|
|
2198
|
+
"contacts:delete-address": delete_address_default,
|
|
2056
2199
|
"contacts:get": get_default$6,
|
|
2057
2200
|
"contacts:list": list_default$7,
|
|
2058
2201
|
"contacts:update": update_default,
|
|
2202
|
+
"contacts:update-address": update_address_default,
|
|
2059
2203
|
"credit-notes:get": get_default$5,
|
|
2060
2204
|
"credit-notes:list": list_default$6,
|
|
2061
2205
|
"credit-notes:pdf": pdf_default$2,
|