@tailormade/billit-mcp 1.0.0 → 1.1.1
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 +36 -11
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/tools/documents.d.ts.map +1 -1
- package/dist/tools/documents.js +9 -13
- package/dist/tools/documents.js.map +1 -1
- package/dist/tools/financial.d.ts.map +1 -1
- package/dist/tools/financial.js +22 -26
- package/dist/tools/financial.js.map +1 -1
- package/dist/tools/orders.d.ts.map +1 -1
- package/dist/tools/orders.js +32 -25
- package/dist/tools/orders.js.map +1 -1
- package/dist/tools/parties.d.ts.map +1 -1
- package/dist/tools/parties.js +13 -16
- package/dist/tools/parties.js.map +1 -1
- package/dist/tools/peppol.d.ts.map +1 -1
- package/dist/tools/peppol.js +21 -18
- package/dist/tools/peppol.js.map +1 -1
- package/dist/tools/products.d.ts.map +1 -1
- package/dist/tools/products.js +7 -11
- package/dist/tools/products.js.map +1 -1
- package/dist/tools/toprocess.d.ts.map +1 -1
- package/dist/tools/toprocess.js +5 -9
- package/dist/tools/toprocess.js.map +1 -1
- package/dist/tools/utils.d.ts +9 -0
- package/dist/tools/utils.d.ts.map +1 -0
- package/dist/tools/utils.js +11 -0
- package/dist/tools/utils.js.map +1 -0
- package/dist/tools/workflows.d.ts +4 -0
- package/dist/tools/workflows.d.ts.map +1 -0
- package/dist/tools/workflows.js +189 -0
- package/dist/tools/workflows.js.map +1 -0
- package/package.json +46 -30
package/dist/tools/parties.js
CHANGED
|
@@ -2,24 +2,21 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.registerPartyTools = registerPartyTools;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
|
|
6
|
-
return { content: [{ type: "text", text }] };
|
|
7
|
-
}
|
|
8
|
-
const companyId = zod_1.z.coerce.number().optional()
|
|
9
|
-
.describe("Billit PartyID of the company to act as. If not set, uses BILLIT_PARTY_ID env. If env is 0, call billit_get_account_info first to discover available companies.");
|
|
5
|
+
const utils_js_1 = require("./utils.js");
|
|
10
6
|
function registerPartyTools(server, client) {
|
|
11
|
-
server.tool("billit_list_parties", "List parties (customers and/or suppliers) in Billit. Returns array with PartyID, CommercialName, VATNumber, Email, PartyType. Supports OData $filter, $orderby, full-text search. Next steps: billit_get_party for full details, billit_create_order to create an invoice for a party.\n\nEXAMPLES:\n- filter=\"PartyType eq 'Customer'\"\n- filter=\"DisplayName eq 'Acme NV'\"\n- orderby='CommercialName asc'\n\nNOTE: fullTextSearch is a separate param — do NOT put it in OData $filter.", {
|
|
7
|
+
server.tool("billit_list_parties", "List parties (customers and/or suppliers) in Billit. Returns array with PartyID, CommercialName, VATNumber, Email, PartyType. Supports OData $filter, $orderby, full-text search. Next steps: billit_get_party for full details, billit_create_order to create an invoice for a party.\n\nEXAMPLES:\n- filter=\"PartyType eq 'Customer'\"\n- filter=\"DisplayName eq 'Acme NV'\"\n- orderby='CommercialName asc'\n\nNOTE: fullTextSearch is a separate param — do NOT put it in OData $filter. NOTE: PartyName/DisplayName may be empty in list responses — use billit_get_party to retrieve the full party name.", {
|
|
12
8
|
party_type: zod_1.z.enum(["Customer", "Supplier", "Both"]).optional().describe("Shortcut filter by party type. Equivalent to filter=\"PartyType eq '...'\"."),
|
|
13
|
-
filter: zod_1.z.string().optional().describe("OData $filter expression. Examples: \"DisplayName eq 'Acme NV'\", \"PartyType eq 'Customer'\""),
|
|
9
|
+
filter: zod_1.z.string().optional().describe("OData $filter expression. Examples: \"DisplayName eq 'Acme NV'\", \"PartyType eq 'Customer'\". NOTE: If you also provide party_type, it will be merged with AND unless your filter already contains a PartyType condition."),
|
|
14
10
|
orderby: zod_1.z.string().optional().describe("OData $orderby expression. Examples: 'CommercialName asc', 'DisplayName desc'"),
|
|
15
11
|
search: zod_1.z.string().optional().describe("Full-text search on name, VAT number, email. Sent as separate 'fullTextSearch' query param."),
|
|
16
12
|
top: zod_1.z.coerce.number().optional().describe("Max results per page (max: 120)"),
|
|
17
13
|
skip: zod_1.z.coerce.number().optional().describe("Items to skip for pagination (default: 0)"),
|
|
18
|
-
company_id: companyId,
|
|
14
|
+
company_id: utils_js_1.companyId,
|
|
19
15
|
}, async ({ party_type, filter, orderby, search, top, skip, company_id }) => {
|
|
20
16
|
const filters = [];
|
|
21
|
-
if (party_type)
|
|
17
|
+
if (party_type && !(filter && /PartyType/i.test(filter))) {
|
|
22
18
|
filters.push(`PartyType eq '${party_type}'`);
|
|
19
|
+
}
|
|
23
20
|
if (filter)
|
|
24
21
|
filters.push(filter);
|
|
25
22
|
const params = new URLSearchParams();
|
|
@@ -35,14 +32,14 @@ function registerPartyTools(server, client) {
|
|
|
35
32
|
params.set("$skip", String(skip));
|
|
36
33
|
const qs = params.toString();
|
|
37
34
|
const data = await client.request("GET", `/v1/parties${qs ? `?${qs}` : ""}`, undefined, company_id);
|
|
38
|
-
return respond(JSON.stringify(data, null, 2));
|
|
35
|
+
return (0, utils_js_1.respond)(JSON.stringify(data, null, 2));
|
|
39
36
|
});
|
|
40
37
|
server.tool("billit_get_party", "Get full details of a party including all addresses, identifiers (GLN, VAT), IBAN/BIC, language, and contact info. Use PartyID from billit_list_parties.", {
|
|
41
38
|
party_id: zod_1.z.coerce.number().describe("Numeric party ID from billit_list_parties result"),
|
|
42
|
-
company_id: companyId,
|
|
39
|
+
company_id: utils_js_1.companyId,
|
|
43
40
|
}, async ({ party_id, company_id }) => {
|
|
44
41
|
const data = await client.request("GET", `/v1/parties/${party_id}`, undefined, company_id);
|
|
45
|
-
return respond(JSON.stringify(data, null, 2));
|
|
42
|
+
return (0, utils_js_1.respond)(JSON.stringify(data, null, 2));
|
|
46
43
|
});
|
|
47
44
|
server.tool("billit_create_party", "Create a new customer or supplier party in Billit. Use billit_search_company first to auto-fill company details from KBO/VAT lookup. Returns the created PartyID. Next steps: billit_create_order to create an invoice for this party.\n\nNOTE: Use billit_search_company with the company VAT/KBO number to look up official company data (name, address) before creating. This avoids typos and ensures correct data.", {
|
|
48
45
|
commercial_name: zod_1.z.string().describe("Company or person name (required)"),
|
|
@@ -61,7 +58,7 @@ function registerPartyTools(server, client) {
|
|
|
61
58
|
city: zod_1.z.string().optional().describe("City name"),
|
|
62
59
|
country_code: zod_1.z.string().optional().describe("ISO country code (default: BE)"),
|
|
63
60
|
address_type: zod_1.z.enum(["InvoiceAddress", "DeliveryAddress"]).optional().describe("Address type: 'InvoiceAddress' (default) or 'DeliveryAddress'"),
|
|
64
|
-
company_id: companyId,
|
|
61
|
+
company_id: utils_js_1.companyId,
|
|
65
62
|
}, async (params) => {
|
|
66
63
|
const body = {
|
|
67
64
|
CommercialName: params.commercial_name,
|
|
@@ -86,7 +83,7 @@ function registerPartyTools(server, client) {
|
|
|
86
83
|
}];
|
|
87
84
|
}
|
|
88
85
|
const data = await client.request("POST", "/v1/parties", body, params.company_id);
|
|
89
|
-
return respond(JSON.stringify(data, null, 2));
|
|
86
|
+
return (0, utils_js_1.respond)(JSON.stringify(data, null, 2));
|
|
90
87
|
});
|
|
91
88
|
server.tool("billit_update_party", "Update party details. Only fields provided in the request are modified — absent fields remain unchanged.", {
|
|
92
89
|
party_id: zod_1.z.coerce.number().describe("Numeric party ID to update"),
|
|
@@ -97,7 +94,7 @@ function registerPartyTools(server, client) {
|
|
|
97
94
|
language: zod_1.z.enum(["NL", "FR", "EN", "DE"]).optional().describe("Updated language: NL, FR, EN, or DE"),
|
|
98
95
|
iban: zod_1.z.string().optional().describe("Updated IBAN"),
|
|
99
96
|
bic: zod_1.z.string().optional().describe("Updated BIC/SWIFT"),
|
|
100
|
-
company_id: companyId,
|
|
97
|
+
company_id: utils_js_1.companyId,
|
|
101
98
|
}, async ({ party_id, commercial_name, vat_number, email, phone, language, iban, bic, company_id }) => {
|
|
102
99
|
const body = {};
|
|
103
100
|
if (commercial_name !== undefined)
|
|
@@ -115,7 +112,7 @@ function registerPartyTools(server, client) {
|
|
|
115
112
|
if (bic !== undefined)
|
|
116
113
|
body.BIC = bic;
|
|
117
114
|
const data = await client.request("PATCH", `/v1/parties/${party_id}`, body, company_id);
|
|
118
|
-
return respond(JSON.stringify(data, null, 2));
|
|
115
|
+
return (0, utils_js_1.respond)(JSON.stringify(data, null, 2));
|
|
119
116
|
});
|
|
120
117
|
}
|
|
121
118
|
//# sourceMappingURL=parties.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parties.js","sourceRoot":"","sources":["../../src/tools/parties.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"parties.js","sourceRoot":"","sources":["../../src/tools/parties.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"peppol.d.ts","sourceRoot":"","sources":["../../src/tools/peppol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"peppol.d.ts","sourceRoot":"","sources":["../../src/tools/peppol.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,QAkG1E"}
|
package/dist/tools/peppol.js
CHANGED
|
@@ -2,17 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.registerPeppolTools = registerPeppolTools;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
|
|
6
|
-
return { content: [{ type: "text", text }] };
|
|
7
|
-
}
|
|
8
|
-
const companyId = zod_1.z.coerce.number().optional()
|
|
9
|
-
.describe("Billit PartyID of the company to act as. If not set, uses BILLIT_PARTY_ID env. If env is 0, call billit_get_account_info first to discover available companies.");
|
|
5
|
+
const utils_js_1 = require("./utils.js");
|
|
10
6
|
function registerPeppolTools(server, client) {
|
|
11
7
|
server.tool("billit_peppol_list_inbox", "List incoming Peppol messages (e-invoices received from suppliers via the Peppol network). Returns inbox items with inboxItemId, sender, document type, and date. Supports OData $orderby. Next steps: billit_peppol_confirm_inbox to accept, billit_peppol_refuse_inbox to reject.", {
|
|
12
8
|
orderby: zod_1.z.string().optional().describe("OData $orderby expression. Example: 'ReceivedDate desc'"),
|
|
13
9
|
top: zod_1.z.coerce.number().optional().describe("Max results per page (max: 120)"),
|
|
14
10
|
skip: zod_1.z.coerce.number().optional().describe("Items to skip for pagination (default: 0)"),
|
|
15
|
-
company_id: companyId,
|
|
11
|
+
company_id: utils_js_1.companyId,
|
|
16
12
|
}, async ({ orderby, top, skip, company_id }) => {
|
|
17
13
|
const params = new URLSearchParams();
|
|
18
14
|
if (orderby)
|
|
@@ -23,42 +19,49 @@ function registerPeppolTools(server, client) {
|
|
|
23
19
|
params.set("$skip", String(skip));
|
|
24
20
|
const qs = params.toString();
|
|
25
21
|
const data = await client.request("GET", `/v1/peppol/inbox${qs ? `?${qs}` : ""}`, undefined, company_id);
|
|
26
|
-
return respond(JSON.stringify(data, null, 2));
|
|
22
|
+
return (0, utils_js_1.respond)(JSON.stringify(data, null, 2));
|
|
27
23
|
});
|
|
28
24
|
server.tool("billit_peppol_confirm_inbox", "Accept an incoming Peppol message. Marks the item as processed and accepted. Use after reviewing an incoming e-invoice.", {
|
|
29
25
|
inbox_item_id: zod_1.z.string().describe("Inbox item ID from billit_peppol_list_inbox result"),
|
|
30
|
-
company_id: companyId,
|
|
26
|
+
company_id: utils_js_1.companyId,
|
|
31
27
|
}, async ({ inbox_item_id, company_id }) => {
|
|
32
28
|
const data = await client.request("POST", `/v1/peppol/inbox/${inbox_item_id}/confirm`, undefined, company_id);
|
|
33
|
-
return respond(JSON.stringify(data ?? { success: true }, null, 2));
|
|
29
|
+
return (0, utils_js_1.respond)(JSON.stringify(data ?? { success: true }, null, 2));
|
|
34
30
|
});
|
|
35
31
|
server.tool("billit_peppol_refuse_inbox", "Refuse/reject an incoming Peppol message. Use when an incoming e-invoice is incorrect or unexpected.", {
|
|
36
32
|
inbox_item_id: zod_1.z.string().describe("Inbox item ID from billit_peppol_list_inbox result"),
|
|
37
|
-
company_id: companyId,
|
|
33
|
+
company_id: utils_js_1.companyId,
|
|
38
34
|
}, async ({ inbox_item_id, company_id }) => {
|
|
39
35
|
const data = await client.request("POST", `/v1/peppol/inbox/${inbox_item_id}/refuse`, undefined, company_id);
|
|
40
|
-
return respond(JSON.stringify(data ?? { success: true }, null, 2));
|
|
36
|
+
return (0, utils_js_1.respond)(JSON.stringify(data ?? { success: true }, null, 2));
|
|
41
37
|
});
|
|
42
38
|
server.tool("billit_peppol_send_order", "Send a specific order directly via the Peppol e-invoicing network. Use billit_peppol_lookup_participant first to verify the customer is a Peppol participant. Prerequisites: order must be confirmed (ApprovalStatus=approved).\n\nCRITICAL: The customer must be registered on Peppol before you can send. Use billit_peppol_lookup_participant with their VAT/CBE number first. If they are not on Peppol, use billit_send_order (which falls back to email) instead.", {
|
|
43
39
|
order_id: zod_1.z.coerce.number().describe("Numeric order ID to send via Peppol"),
|
|
44
|
-
company_id: companyId,
|
|
40
|
+
company_id: utils_js_1.companyId,
|
|
45
41
|
}, async ({ order_id, company_id }) => {
|
|
46
42
|
const data = await client.request("POST", "/v1/peppol/sendOrder", { OrderID: order_id }, company_id);
|
|
47
|
-
return respond(JSON.stringify(data ?? { success: true }, null, 2));
|
|
43
|
+
return (0, utils_js_1.respond)(JSON.stringify(data ?? { success: true }, null, 2));
|
|
48
44
|
});
|
|
49
45
|
server.tool("billit_peppol_lookup_participant", "Check if a company is registered as a Peppol participant. Returns participant information including endpoint and supported document types. Use before billit_peppol_send_order to verify the customer is reachable.", {
|
|
50
46
|
vat_or_cbe: zod_1.z.string().describe("Company VAT number (e.g. BE0123456789) or CBE/KBO enterprise number to look up on Peppol"),
|
|
51
47
|
}, async ({ vat_or_cbe }) => {
|
|
52
48
|
const data = await client.request("GET", `/v1/peppol/participantInformation/${vat_or_cbe}`);
|
|
53
|
-
return respond(JSON.stringify(data, null, 2));
|
|
49
|
+
return (0, utils_js_1.respond)(JSON.stringify(data, null, 2));
|
|
54
50
|
});
|
|
55
|
-
server.tool("billit_peppol_register", "Register the current Billit party as a Peppol participant. Enables receiving e-invoices via Peppol and sending outgoing invoices via the network. One-time setup operation.", { company_id: companyId }, async ({ company_id }) => {
|
|
51
|
+
server.tool("billit_peppol_register", "Register the current Billit party as a Peppol participant. Enables receiving e-invoices via Peppol and sending outgoing invoices via the network. One-time setup operation.", { company_id: utils_js_1.companyId }, async ({ company_id }) => {
|
|
56
52
|
const data = await client.request("POST", "/v1/peppol/participants", undefined, company_id);
|
|
57
|
-
return respond(JSON.stringify(data ?? { success: true }, null, 2));
|
|
53
|
+
return (0, utils_js_1.respond)(JSON.stringify(data ?? { success: true }, null, 2));
|
|
58
54
|
});
|
|
59
|
-
server.tool("billit_peppol_unregister", "Unregister the current Billit party from the Peppol network. After this, the party can no longer receive or send via Peppol. Use with caution.\n\nWARNING: Unregistering from Peppol is immediate and affects all incoming e-invoices. Confirm with the user before calling this
|
|
55
|
+
server.tool("billit_peppol_unregister", "Unregister the current Billit party from the Peppol network. After this, the party can no longer receive or send via Peppol. Use with caution.\n\nWARNING: Unregistering from Peppol is immediate and affects all incoming e-invoices. Confirm with the user before calling this.\n\nSupports dry_run=true to preview without making changes.", {
|
|
56
|
+
company_id: utils_js_1.companyId,
|
|
57
|
+
dry_run: zod_1.z.union([zod_1.z.boolean(), zod_1.z.string().transform(v => v === "true")]).optional()
|
|
58
|
+
.describe("If true, returns what would happen without actually unregistering. Default: false."),
|
|
59
|
+
}, async ({ company_id, dry_run }) => {
|
|
60
|
+
if (dry_run) {
|
|
61
|
+
return (0, utils_js_1.respond)("Dry run: would unregister party from Peppol. No changes made.");
|
|
62
|
+
}
|
|
60
63
|
const data = await client.request("DELETE", "/v1/peppol/participants", undefined, company_id);
|
|
61
|
-
return respond(JSON.stringify(data ?? { success: true }, null, 2));
|
|
64
|
+
return (0, utils_js_1.respond)(JSON.stringify(data ?? { success: true }, null, 2));
|
|
62
65
|
});
|
|
63
66
|
}
|
|
64
67
|
//# sourceMappingURL=peppol.js.map
|
package/dist/tools/peppol.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"peppol.js","sourceRoot":"","sources":["../../src/tools/peppol.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"peppol.js","sourceRoot":"","sources":["../../src/tools/peppol.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../src/tools/products.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"products.d.ts","sourceRoot":"","sources":["../../src/tools/products.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,QA2D3E"}
|
package/dist/tools/products.js
CHANGED
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.registerProductTools = registerProductTools;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
|
|
6
|
-
return { content: [{ type: "text", text }] };
|
|
7
|
-
}
|
|
8
|
-
const companyId = zod_1.z.coerce.number().optional()
|
|
9
|
-
.describe("Billit PartyID of the company to act as. If not set, uses BILLIT_PARTY_ID env. If env is 0, call billit_get_account_info first to discover available companies.");
|
|
5
|
+
const utils_js_1 = require("./utils.js");
|
|
10
6
|
function registerProductTools(server, client) {
|
|
11
7
|
server.tool("billit_list_products", "List products/services in the Billit product catalog. Returns ProductID, Description, Reference, UnitPrice, VATPercentage, Unit. Supports OData $filter, $orderby, full-text search. Next step: billit_create_order using product descriptions and prices.\n\nEXAMPLES:\n- orderby='Description asc'\n- filter=\"VATPercentage eq 21\"", {
|
|
12
8
|
filter: zod_1.z.string().optional().describe("OData $filter expression. Examples: \"VATPercentage eq 21\", \"Reference eq 'SKU-001'\""),
|
|
@@ -14,7 +10,7 @@ function registerProductTools(server, client) {
|
|
|
14
10
|
search: zod_1.z.string().optional().describe("Full-text search on product description or reference code. Sent as 'fullTextSearch' query param."),
|
|
15
11
|
top: zod_1.z.coerce.number().optional().describe("Max results per page (max: 120)"),
|
|
16
12
|
skip: zod_1.z.coerce.number().optional().describe("Items to skip for pagination (default: 0)"),
|
|
17
|
-
company_id: companyId,
|
|
13
|
+
company_id: utils_js_1.companyId,
|
|
18
14
|
}, async ({ filter, orderby, search, top, skip, company_id }) => {
|
|
19
15
|
const params = new URLSearchParams();
|
|
20
16
|
if (filter)
|
|
@@ -29,14 +25,14 @@ function registerProductTools(server, client) {
|
|
|
29
25
|
params.set("$skip", String(skip));
|
|
30
26
|
const qs = params.toString();
|
|
31
27
|
const data = await client.request("GET", `/v1/products${qs ? `?${qs}` : ""}`, undefined, company_id);
|
|
32
|
-
return respond(JSON.stringify(data, null, 2));
|
|
28
|
+
return (0, utils_js_1.respond)(JSON.stringify(data, null, 2));
|
|
33
29
|
});
|
|
34
30
|
server.tool("billit_get_product", "Get full details of a single product including price, VAT percentage, and unit. Use ProductID from billit_list_products.", {
|
|
35
31
|
product_id: zod_1.z.coerce.number().describe("Numeric product ID from billit_list_products result"),
|
|
36
|
-
company_id: companyId,
|
|
32
|
+
company_id: utils_js_1.companyId,
|
|
37
33
|
}, async ({ product_id, company_id }) => {
|
|
38
34
|
const data = await client.request("GET", `/v1/products/${product_id}`, undefined, company_id);
|
|
39
|
-
return respond(JSON.stringify(data, null, 2));
|
|
35
|
+
return (0, utils_js_1.respond)(JSON.stringify(data, null, 2));
|
|
40
36
|
});
|
|
41
37
|
server.tool("billit_create_product", "Create a new product in the Billit catalog, or update an existing product if one with the same reference already exists. Use to maintain a reusable product list for order lines.\n\nNOTE: If a product with the same 'reference' already exists, this acts as an upsert (update). Use a unique reference code to distinguish products.", {
|
|
42
38
|
description: zod_1.z.string().describe("Product or service description (required)"),
|
|
@@ -44,7 +40,7 @@ function registerProductTools(server, client) {
|
|
|
44
40
|
unit_price: zod_1.z.coerce.number().optional().describe("Default unit price (excl. VAT) as decimal"),
|
|
45
41
|
vat_percentage: zod_1.z.coerce.number().optional().describe("VAT percentage as number (e.g. 21 for 21%, 0 for VAT exempt)"),
|
|
46
42
|
unit: zod_1.z.string().optional().describe("Unit of measure (e.g. 'piece', 'hour', 'kg')"),
|
|
47
|
-
company_id: companyId,
|
|
43
|
+
company_id: utils_js_1.companyId,
|
|
48
44
|
}, async ({ description, reference, unit_price, vat_percentage, unit, company_id }) => {
|
|
49
45
|
const body = { Description: description };
|
|
50
46
|
if (reference !== undefined)
|
|
@@ -56,7 +52,7 @@ function registerProductTools(server, client) {
|
|
|
56
52
|
if (unit !== undefined)
|
|
57
53
|
body.Unit = unit;
|
|
58
54
|
const data = await client.request("POST", "/v1/products", body, company_id);
|
|
59
|
-
return respond(JSON.stringify(data, null, 2));
|
|
55
|
+
return (0, utils_js_1.respond)(JSON.stringify(data, null, 2));
|
|
60
56
|
});
|
|
61
57
|
}
|
|
62
58
|
//# sourceMappingURL=products.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"products.js","sourceRoot":"","sources":["../../src/tools/products.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"products.js","sourceRoot":"","sources":["../../src/tools/products.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toprocess.d.ts","sourceRoot":"","sources":["../../src/tools/toprocess.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"toprocess.d.ts","sourceRoot":"","sources":["../../src/tools/toprocess.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,QA+B7E"}
|
package/dist/tools/toprocess.js
CHANGED
|
@@ -2,30 +2,26 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.registerToProcessTools = registerToProcessTools;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
|
|
6
|
-
return { content: [{ type: "text", text }] };
|
|
7
|
-
}
|
|
8
|
-
const companyId = zod_1.z.coerce.number().optional()
|
|
9
|
-
.describe("Billit PartyID of the company to act as. If not set, uses BILLIT_PARTY_ID env. If env is 0, call billit_get_account_info first to discover available companies.");
|
|
5
|
+
const utils_js_1 = require("./utils.js");
|
|
10
6
|
function registerToProcessTools(server, client) {
|
|
11
7
|
server.tool("billit_submit_for_processing", "Submit a file (e.g. incoming invoice PDF) to Billit for automated processing. Billit will parse the document and create a corresponding order. Returns an uploadID that can be used to cancel. Use for processing incoming supplier invoices without manual data entry.\n\nNOTE: file_base64 must be base64-encoded file content. The processing is async — Billit will parse the document and create an order in the background. Use billit_list_orders with direction='Cost' after processing to find the created order.", {
|
|
12
8
|
file_base64: zod_1.z.string().describe("Base64-encoded file content of the document to process"),
|
|
13
9
|
file_name: zod_1.z.string().describe("File name including extension (e.g. 'supplier-invoice-001.pdf')"),
|
|
14
10
|
content_type: zod_1.z.string().optional().describe("MIME type (default: 'application/pdf'). Billit processes PDF and common image formats."),
|
|
15
|
-
company_id: companyId,
|
|
11
|
+
company_id: utils_js_1.companyId,
|
|
16
12
|
}, async ({ file_base64, file_name, content_type, company_id }) => {
|
|
17
13
|
const body = {
|
|
18
14
|
FileBase64: file_base64, FileName: file_name, ContentType: content_type ?? "application/pdf",
|
|
19
15
|
};
|
|
20
16
|
const data = await client.request("POST", "/v1/toProcess", body, company_id);
|
|
21
|
-
return respond(JSON.stringify(data, null, 2));
|
|
17
|
+
return (0, utils_js_1.respond)(JSON.stringify(data, null, 2));
|
|
22
18
|
});
|
|
23
19
|
server.tool("billit_cancel_processing", "Cancel a pending processing upload. Use if a wrong file was submitted. Only works while the upload is still pending — cannot cancel already-processed documents.", {
|
|
24
20
|
upload_id: zod_1.z.string().describe("Upload ID returned by billit_submit_for_processing"),
|
|
25
|
-
company_id: companyId,
|
|
21
|
+
company_id: utils_js_1.companyId,
|
|
26
22
|
}, async ({ upload_id, company_id }) => {
|
|
27
23
|
const data = await client.request("DELETE", `/v1/toProcess/${upload_id}`, undefined, company_id);
|
|
28
|
-
return respond(JSON.stringify(data ?? { success: true }, null, 2));
|
|
24
|
+
return (0, utils_js_1.respond)(JSON.stringify(data ?? { success: true }, null, 2));
|
|
29
25
|
});
|
|
30
26
|
}
|
|
31
27
|
//# sourceMappingURL=toprocess.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toprocess.js","sourceRoot":"","sources":["../../src/tools/toprocess.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"toprocess.js","sourceRoot":"","sources":["../../src/tools/toprocess.ts"],"names":[],"mappings":";;AAKA,wDA+BC;AAnCD,6BAAwB;AAExB,yCAAgD;AAEhD,SAAgB,sBAAsB,CAAC,MAAiB,EAAE,MAAoB;IAC5E,MAAM,CAAC,IAAI,CACT,8BAA8B,EAC9B,4fAA4f,EAC5f;QACE,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,wDAAwD,CAAC;QAC1F,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iEAAiE,CAAC;QACjG,YAAY,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wFAAwF,CAAC;QACtI,UAAU,EAAE,oBAAS;KACtB,EACD,KAAK,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,EAAE,EAAE;QAC7D,MAAM,IAAI,GAA4B;YACpC,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,IAAI,iBAAiB;SAC7F,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QAC7E,OAAO,IAAA,kBAAO,EAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,0BAA0B,EAC1B,kKAAkK,EAClK;QACE,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oDAAoD,CAAC;QACpF,UAAU,EAAE,oBAAS;KACtB,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,iBAAiB,SAAS,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACjG,OAAO,IAAA,kBAAO,EAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/tools/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM;;;;;EAEnC;AAED,eAAO,MAAM,SAAS,4CACwJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.companyId = void 0;
|
|
4
|
+
exports.respond = respond;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
function respond(text) {
|
|
7
|
+
return { content: [{ type: "text", text }] };
|
|
8
|
+
}
|
|
9
|
+
exports.companyId = zod_1.z.coerce.number().optional()
|
|
10
|
+
.describe("Billit PartyID of the company to act as. If not set, uses BILLIT_PARTY_ID env. If env is 0, call billit_get_account_info first to discover available companies.");
|
|
11
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/tools/utils.ts"],"names":[],"mappings":";;;AAEA,0BAEC;AAJD,6BAAwB;AAExB,SAAgB,OAAO,CAAC,IAAY;IAClC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC;AAEY,QAAA,SAAS,GAAG,OAAC,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;KAClD,QAAQ,CAAC,iKAAiK,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflows.d.ts","sourceRoot":"","sources":["../../src/tools/workflows.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAyDhD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,QAqN5E"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerWorkflowTools = registerWorkflowTools;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const utils_js_1 = require("./utils.js");
|
|
6
|
+
async function batchAll(tasks, batchSize = 5) {
|
|
7
|
+
const results = [];
|
|
8
|
+
for (let i = 0; i < tasks.length; i += batchSize) {
|
|
9
|
+
const batch = tasks.slice(i, i + batchSize);
|
|
10
|
+
results.push(...await Promise.all(batch.map(fn => fn())));
|
|
11
|
+
}
|
|
12
|
+
return results;
|
|
13
|
+
}
|
|
14
|
+
function currentYearStart() {
|
|
15
|
+
return new Date(new Date().getFullYear(), 0, 1).toISOString().slice(0, 10);
|
|
16
|
+
}
|
|
17
|
+
function registerWorkflowTools(server, client) {
|
|
18
|
+
server.tool("billit_check_peppol_coverage", "WORKFLOW (multi-step): Scans all outgoing invoices (Income/Invoice) since a date, deduplicates customers by VAT number, and checks each unique VAT against the Peppol network. Returns two groups: customers NOT on Peppol (priority list for onboarding) and customers already on Peppol.\n\nUSE THIS when the user asks: 'which customers are not on Peppol?', 'who should I onboard to e-invoicing?', 'check Peppol coverage', 'which invoices can't be sent via Peppol?'\nDO NOT use this for a single VAT lookup — use billit_peppol_lookup_participant instead.\n\nOUTPUT: { summary: { period_from, total_customers_with_vat, not_on_peppol, on_peppol }, not_on_peppol: [{ vat, name, invoiceCount, totalAmount, invoices[] }] sorted by totalAmount desc, on_peppol: [{ vat, name, invoiceCount }] }\n\nNOTE: May be slow if there are many invoices — paginates through all pages automatically. Peppol lookups run in parallel.", {
|
|
19
|
+
since_date: zod_1.z.string().optional()
|
|
20
|
+
.describe("Start date for invoice scan (YYYY-MM-DD). Default: 2026-01-01. Use a recent date to limit scope and improve speed."),
|
|
21
|
+
company_id: utils_js_1.companyId,
|
|
22
|
+
}, async ({ since_date, company_id }) => {
|
|
23
|
+
const fromDate = since_date ?? currentYearStart();
|
|
24
|
+
// Fetch all outgoing invoices since date (paginate through all pages)
|
|
25
|
+
const allOrders = [];
|
|
26
|
+
let skip = 0;
|
|
27
|
+
const pageSize = 120;
|
|
28
|
+
while (true) {
|
|
29
|
+
const filter = `OrderDirection eq 'Income' and OrderType eq 'Invoice' and OrderDate ge datetime'${fromDate}T00:00:00'`;
|
|
30
|
+
const params = new URLSearchParams({
|
|
31
|
+
"$filter": filter,
|
|
32
|
+
"$top": String(pageSize),
|
|
33
|
+
"$skip": String(skip),
|
|
34
|
+
"$orderby": "OrderDate desc",
|
|
35
|
+
});
|
|
36
|
+
const page = await client.request("GET", `/v1/orders?${params.toString()}`, undefined, company_id);
|
|
37
|
+
const items = page?.Items ?? [];
|
|
38
|
+
allOrders.push(...items);
|
|
39
|
+
if (items.length < pageSize)
|
|
40
|
+
break;
|
|
41
|
+
skip += pageSize;
|
|
42
|
+
}
|
|
43
|
+
// Deduplicate by VAT number — collect unique VATs with their invoices
|
|
44
|
+
const byVat = new Map();
|
|
45
|
+
for (const order of allOrders) {
|
|
46
|
+
const vat = order.CounterParty?.VATNumber;
|
|
47
|
+
if (!vat)
|
|
48
|
+
continue;
|
|
49
|
+
if (!byVat.has(vat)) {
|
|
50
|
+
byVat.set(vat, { name: order.CounterParty.DisplayName, invoices: [] });
|
|
51
|
+
}
|
|
52
|
+
byVat.get(vat).invoices.push({
|
|
53
|
+
id: order.OrderID,
|
|
54
|
+
number: order.OrderNumber,
|
|
55
|
+
date: (order.OrderDate ?? "").slice(0, 10),
|
|
56
|
+
amount: order.TotalIncl,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
// Check Peppol registration for each unique VAT (batches of 5)
|
|
60
|
+
const vatList = Array.from(byVat.entries());
|
|
61
|
+
const peppolResults = await batchAll(vatList.map(([vat]) => () => client.request("GET", `/v1/peppol/participantInformation/${vat}`)
|
|
62
|
+
.then(r => ({ vat, registered: r?.Registered ?? false }))
|
|
63
|
+
.catch(() => ({ vat, registered: false }))));
|
|
64
|
+
const notOnPeppol = [];
|
|
65
|
+
const onPeppol = [];
|
|
66
|
+
for (const { vat, registered } of peppolResults) {
|
|
67
|
+
const entry = byVat.get(vat);
|
|
68
|
+
const totalAmount = entry.invoices.reduce((sum, i) => sum + i.amount, 0);
|
|
69
|
+
if (registered) {
|
|
70
|
+
onPeppol.push({ vat, name: entry.name, invoiceCount: entry.invoices.length });
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
notOnPeppol.push({ vat, name: entry.name, invoiceCount: entry.invoices.length, totalAmount, invoices: entry.invoices });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const result = {
|
|
77
|
+
summary: {
|
|
78
|
+
period_from: fromDate,
|
|
79
|
+
total_customers_with_vat: vatList.length,
|
|
80
|
+
not_on_peppol: notOnPeppol.length,
|
|
81
|
+
on_peppol: onPeppol.length,
|
|
82
|
+
},
|
|
83
|
+
not_on_peppol: notOnPeppol.sort((a, b) => b.totalAmount - a.totalAmount),
|
|
84
|
+
on_peppol: onPeppol,
|
|
85
|
+
};
|
|
86
|
+
return (0, utils_js_1.respond)(JSON.stringify(result, null, 2));
|
|
87
|
+
});
|
|
88
|
+
server.tool("billit_peppol_send_report", "WORKFLOW (multi-step): Scans all outgoing invoices (Income/Invoice) since a date and reports their Peppol send status. For each invoice with a VAT number: checks if customer is on Peppol, then fetches full order to check if it was actually sent via Peppol.\n\nUSE THIS when the user asks: 'which invoices were sent via Peppol?', 'which Peppol invoices are not yet sent?', 'Peppol send status overview', 'which invoices still need to be sent via Peppol?', 'have all Peppol invoices been dispatched?'\nDO NOT use this to check if a customer is on Peppol — use billit_check_peppol_coverage or billit_peppol_lookup_participant instead.\nDO NOT use this to send invoices — use billit_peppol_send_order to dispatch a single invoice.\n\nOUTPUT: { summary: { period_from, total_invoices, sent_via_peppol, on_peppol_not_sent, not_on_peppol, no_vat }, sent_via_peppol: [{ id, number, date, amount, vat, customer, deliveryStatus }], on_peppol_not_sent: [...], not_on_peppol: [...] }\n\nNOTE: Slower than billit_check_peppol_coverage — fetches full order details for every Peppol-eligible invoice (N requests). Use a recent since_date to limit scope. Peppol send is detected via order Messages (TransportType='Peppol') or CurrentDocumentDeliveryDetails.IsDocumentDelivered.", {
|
|
89
|
+
since_date: zod_1.z.string().optional()
|
|
90
|
+
.describe("Start date for invoice scan (YYYY-MM-DD). Default: 2026-01-01. Use a recent date (e.g. current month) to limit scope and reduce API calls."),
|
|
91
|
+
company_id: utils_js_1.companyId,
|
|
92
|
+
}, async ({ since_date, company_id }) => {
|
|
93
|
+
const fromDate = since_date ?? currentYearStart();
|
|
94
|
+
// 1. Paginate all Income invoices since date
|
|
95
|
+
const allOrders = [];
|
|
96
|
+
let skip = 0;
|
|
97
|
+
const pageSize = 120;
|
|
98
|
+
while (true) {
|
|
99
|
+
const filter = `OrderDirection eq 'Income' and OrderType eq 'Invoice' and OrderDate ge datetime'${fromDate}T00:00:00'`;
|
|
100
|
+
const params = new URLSearchParams({
|
|
101
|
+
"$filter": filter,
|
|
102
|
+
"$top": String(pageSize),
|
|
103
|
+
"$skip": String(skip),
|
|
104
|
+
"$orderby": "OrderDate desc",
|
|
105
|
+
});
|
|
106
|
+
const page = await client.request("GET", `/v1/orders?${params.toString()}`, undefined, company_id);
|
|
107
|
+
const items = page?.Items ?? [];
|
|
108
|
+
allOrders.push(...items);
|
|
109
|
+
if (items.length < pageSize)
|
|
110
|
+
break;
|
|
111
|
+
skip += pageSize;
|
|
112
|
+
}
|
|
113
|
+
// 2. Split: no VAT / has VAT
|
|
114
|
+
const noVat = [];
|
|
115
|
+
const hasVat = [];
|
|
116
|
+
for (const order of allOrders) {
|
|
117
|
+
if (!order.CounterParty?.VATNumber)
|
|
118
|
+
noVat.push(order);
|
|
119
|
+
else
|
|
120
|
+
hasVat.push(order);
|
|
121
|
+
}
|
|
122
|
+
// 3. Deduplicate VATs for Peppol lookup (batches of 5)
|
|
123
|
+
const uniqueVats = [...new Set(hasVat.map(o => o.CounterParty.VATNumber))];
|
|
124
|
+
const peppolMap = new Map();
|
|
125
|
+
await batchAll(uniqueVats.map(vat => () => client.request("GET", `/v1/peppol/participantInformation/${vat}`)
|
|
126
|
+
.then(r => { peppolMap.set(vat, r?.Registered ?? false); })
|
|
127
|
+
.catch(() => { peppolMap.set(vat, false); })));
|
|
128
|
+
// 4. Split into Peppol-eligible vs not
|
|
129
|
+
const notOnPeppolOrders = [];
|
|
130
|
+
const peppolEligible = [];
|
|
131
|
+
for (const order of hasVat) {
|
|
132
|
+
const vat = order.CounterParty.VATNumber;
|
|
133
|
+
if (peppolMap.get(vat))
|
|
134
|
+
peppolEligible.push(order);
|
|
135
|
+
else
|
|
136
|
+
notOnPeppolOrders.push(order);
|
|
137
|
+
}
|
|
138
|
+
const fullOrderResults = await batchAll(peppolEligible.map(order => () => client.request("GET", `/v1/orders/${order.OrderID}`, undefined, company_id)
|
|
139
|
+
.then(full => {
|
|
140
|
+
// Check Messages for Peppol send
|
|
141
|
+
const peppolMsg = full?.Messages?.find(m => m.TransportType === "Peppol" || m.ExternalProvider === "Peppol");
|
|
142
|
+
const sent = !!(peppolMsg?.SentDate || peppolMsg?.DeliveredDate ||
|
|
143
|
+
full?.CurrentDocumentDeliveryDetails?.IsDocumentDelivered);
|
|
144
|
+
const deliveryStatus = full?.CurrentDocumentDeliveryDetails?.DocumentDeliveryStatus;
|
|
145
|
+
return { order, sent, deliveryStatus };
|
|
146
|
+
})
|
|
147
|
+
.catch(() => ({ order, sent: false }))));
|
|
148
|
+
const sentViaPeppol = [];
|
|
149
|
+
const onPeppolNotSent = [];
|
|
150
|
+
for (const { order, sent, deliveryStatus } of fullOrderResults) {
|
|
151
|
+
const info = {
|
|
152
|
+
id: order.OrderID,
|
|
153
|
+
number: order.OrderNumber,
|
|
154
|
+
date: (order.OrderDate ?? "").slice(0, 10),
|
|
155
|
+
amount: order.TotalIncl,
|
|
156
|
+
vat: order.CounterParty.VATNumber,
|
|
157
|
+
customer: order.CounterParty.DisplayName,
|
|
158
|
+
deliveryStatus,
|
|
159
|
+
};
|
|
160
|
+
if (sent)
|
|
161
|
+
sentViaPeppol.push(info);
|
|
162
|
+
else
|
|
163
|
+
onPeppolNotSent.push(info);
|
|
164
|
+
}
|
|
165
|
+
const notOnPeppol = notOnPeppolOrders.map(o => ({
|
|
166
|
+
id: o.OrderID,
|
|
167
|
+
number: o.OrderNumber,
|
|
168
|
+
date: (o.OrderDate ?? "").slice(0, 10),
|
|
169
|
+
amount: o.TotalIncl,
|
|
170
|
+
vat: o.CounterParty.VATNumber,
|
|
171
|
+
customer: o.CounterParty.DisplayName,
|
|
172
|
+
}));
|
|
173
|
+
const result = {
|
|
174
|
+
summary: {
|
|
175
|
+
period_from: fromDate,
|
|
176
|
+
total_invoices: allOrders.length,
|
|
177
|
+
no_vat: noVat.length,
|
|
178
|
+
sent_via_peppol: sentViaPeppol.length,
|
|
179
|
+
on_peppol_not_sent: onPeppolNotSent.length,
|
|
180
|
+
not_on_peppol: notOnPeppol.length,
|
|
181
|
+
},
|
|
182
|
+
sent_via_peppol: sentViaPeppol,
|
|
183
|
+
on_peppol_not_sent: onPeppolNotSent,
|
|
184
|
+
not_on_peppol: notOnPeppol,
|
|
185
|
+
};
|
|
186
|
+
return (0, utils_js_1.respond)(JSON.stringify(result, null, 2));
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=workflows.js.map
|