@kevludwig/eve-lexware-office 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/dist/extension/lib/with-card.d.ts +9 -0
- package/dist/extension/lib/with-card.mjs +25 -0
- package/dist/extension/tools/create_customer.mjs +14 -4
- package/dist/extension/tools/create_invoice.mjs +2 -1
- package/dist/extension/tools/create_order_confirmation.mjs +2 -1
- package/dist/extension/tools/create_purchase_invoice.mjs +3 -2
- package/dist/extension/tools/create_quotation.mjs +2 -1
- package/dist/extension/tools/send_payment_reminder.mjs +3 -2
- package/package.json +2 -2
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ApprovalPolicy } from "eve/tools/approval";
|
|
2
|
+
/**
|
|
3
|
+
* Wraps a writing tool's request policy: when it asks for approval, the
|
|
4
|
+
* finished card goes to the mount's onApprovalCard right away — before eve
|
|
5
|
+
* announces the request (`input.requested`). Channels render that event
|
|
6
|
+
* before hooks run, so a card handed over from a hook would come too late
|
|
7
|
+
* for them (eve: channel delivery, then hooks).
|
|
8
|
+
*/
|
|
9
|
+
export declare function withCard<T>(request: ApprovalPolicy<T>): ApprovalPolicy<T>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { fileURLToPath as __eveFileURLToPath } from "node:url";
|
|
2
|
+
import { dirname as __eveDirname } from "node:path";
|
|
3
|
+
import { createRequire as __eveCreateRequire } from "node:module";
|
|
4
|
+
const __filename = __eveFileURLToPath(import.meta.url);
|
|
5
|
+
__eveDirname(__filename);
|
|
6
|
+
__eveCreateRequire(import.meta.url);
|
|
7
|
+
import { config } from "./runtime.mjs";
|
|
8
|
+
import { approvalCard } from "./cards.mjs";
|
|
9
|
+
function withCard(request) {
|
|
10
|
+
return async (ctx) => {
|
|
11
|
+
const status = await request(ctx);
|
|
12
|
+
const asksPerson = status === "user-approval" || typeof status === "object" && status !== null && status.type === "user-approval";
|
|
13
|
+
const onApprovalCard = config().onApprovalCard;
|
|
14
|
+
if (asksPerson && onApprovalCard) {
|
|
15
|
+
const card = approvalCard(ctx.toolName, ctx.callId, ctx.toolInput);
|
|
16
|
+
if (card) try {
|
|
17
|
+
await onApprovalCard(ctx.callId, card);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
console.warn(`[lexware] onApprovalCard failed for ${ctx.callId}: ${String(error)}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return status;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export { withCard };
|
|
@@ -8,8 +8,9 @@ import { approverPolicy, client } from "../lib/runtime.mjs";
|
|
|
8
8
|
import { saveWarnings } from "../lib/findings.mjs";
|
|
9
9
|
import { readJournal, writeJournal } from "../lib/journal.mjs";
|
|
10
10
|
import { rememberShownContacts, shownContactsOf } from "../lib/state.mjs";
|
|
11
|
+
import { withCard } from "../lib/with-card.mjs";
|
|
11
12
|
import { z } from "zod";
|
|
12
|
-
import { createCustomer, describeError, findContactsByName } from "@kevludwig/lexware-office";
|
|
13
|
+
import { MIN_NAME_SEARCH_LENGTH, createCustomer, describeError, findContactsByName } from "@kevludwig/lexware-office";
|
|
13
14
|
import { defineTool } from "eve/tools";
|
|
14
15
|
const inputSchema = z.object({
|
|
15
16
|
company_name: z.string().trim().min(1).max(255).optional().describe("Firmenname inkl. Rechtsform — entweder dieser oder last_name"),
|
|
@@ -25,13 +26,22 @@ const inputSchema = z.object({
|
|
|
25
26
|
const nameOf = (input) => input.company_name?.trim() || input.last_name?.trim() || "";
|
|
26
27
|
const label = (contact) => `${contact.name}${contact.number ? ` (Nr. ${contact.number})` : ""}`;
|
|
27
28
|
var create_customer_default = defineTool({
|
|
28
|
-
description: "Legt einen neuen Kunden in Lexware Office an. Pflicht sind Name (Firma oder Person) UND die Rechnungsadresse (Straße, PLZ, Ort) — fehlt die Adresse, frage sie zuerst beim Nutzer ab. E-Mail und Telefon sind optional. Prüfe vorher mit dem Lese-Tool (/contacts?name=…), ob der Kunde schon existiert. Legt erst nach Freigabe an.",
|
|
29
|
+
description: "Legt einen neuen Kunden in Lexware Office an. Pflicht sind Name (Firma oder Person) UND die Rechnungsadresse (Straße, PLZ, Ort) — fehlt die Adresse, frage sie zuerst beim Nutzer ab. E-Mail und Telefon sind optional. Prüfe vorher mit dem Lese-Tool (/contacts?name=…), ob der Kunde schon existiert — Lexware sucht erst ab 3 Zeichen; kürzere Namen (z. B. „KL“) sind als Kundenname erlaubt, dann ohne Vorabsuche direkt dieses Tool aufrufen. Legt erst nach Freigabe an.",
|
|
29
30
|
inputSchema,
|
|
30
31
|
approval: {
|
|
31
|
-
request: async (ctx) => {
|
|
32
|
+
request: withCard(async (ctx) => {
|
|
32
33
|
const name = nameOf(ctx.toolInput ?? {});
|
|
33
34
|
if (!name) return "user-approval";
|
|
34
35
|
const findings = [];
|
|
36
|
+
if (name.trim().length < MIN_NAME_SEARCH_LENGTH) {
|
|
37
|
+
findings.push({
|
|
38
|
+
kind: "note",
|
|
39
|
+
title: "⚠ Name zu kurz für die Suche",
|
|
40
|
+
value: `Ähnliche Kontakte ungeprüft (Lexware sucht ab ${MIN_NAME_SEARCH_LENGTH} Zeichen).`
|
|
41
|
+
});
|
|
42
|
+
saveWarnings(ctx.callId, findings);
|
|
43
|
+
return "user-approval";
|
|
44
|
+
}
|
|
35
45
|
try {
|
|
36
46
|
const similar = await findContactsByName(client(), name, {
|
|
37
47
|
size: 5,
|
|
@@ -52,7 +62,7 @@ var create_customer_default = defineTool({
|
|
|
52
62
|
}
|
|
53
63
|
saveWarnings(ctx.callId, findings);
|
|
54
64
|
return "user-approval";
|
|
55
|
-
},
|
|
65
|
+
}),
|
|
56
66
|
response: approverPolicy
|
|
57
67
|
},
|
|
58
68
|
async execute(input, ctx) {
|
|
@@ -6,6 +6,7 @@ __eveDirname(__filename);
|
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { approverPolicy } from "../lib/runtime.mjs";
|
|
8
8
|
import { customerFields, executeSalesDocument, lineItemSchema, salesApproval } from "../lib/sales.mjs";
|
|
9
|
+
import { withCard } from "../lib/with-card.mjs";
|
|
9
10
|
import { z } from "zod";
|
|
10
11
|
import { defineTool } from "eve/tools";
|
|
11
12
|
const inputSchema = z.object({
|
|
@@ -18,7 +19,7 @@ var create_invoice_default = defineTool({
|
|
|
18
19
|
description: "Erstellt eine Ausgangsrechnung als Entwurf in Lexware Office — festgeschrieben und versendet wird dort, nie hier. Kunde per Kundennummer oder contact_id, dazu die Positionen; source_document_id, wenn die Rechnung aus einem Angebot oder einer AB hervorgeht. Legt erst nach Freigabe an und prüft vorher auf Dubletten.",
|
|
19
20
|
inputSchema,
|
|
20
21
|
approval: {
|
|
21
|
-
request: salesApproval("invoice"),
|
|
22
|
+
request: withCard(salesApproval("invoice")),
|
|
22
23
|
response: approverPolicy
|
|
23
24
|
},
|
|
24
25
|
async execute(input, ctx) {
|
|
@@ -6,6 +6,7 @@ __eveDirname(__filename);
|
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { approverPolicy } from "../lib/runtime.mjs";
|
|
8
8
|
import { customerFields, executeSalesDocument, lineItemSchema, salesApproval, titleSchema } from "../lib/sales.mjs";
|
|
9
|
+
import { withCard } from "../lib/with-card.mjs";
|
|
9
10
|
import { z } from "zod";
|
|
10
11
|
import { defineTool } from "eve/tools";
|
|
11
12
|
const inputSchema = z.object({
|
|
@@ -23,7 +24,7 @@ var create_order_confirmation_default = defineTool({
|
|
|
23
24
|
description: "Erstellt eine Auftragsbestätigung (AB) in Lexware Office und schreibt sie direkt fest (sie erhält eine AB-Nummer; kein Entwurf). Geht die AB aus einem Angebot hervor, dessen quotation_id mitgeben — das Angebot vorher über /voucherlist (voucherType 'quotation') suchen und lesen; bei mehreren passenden den Nutzer wählen lassen. Legt erst nach Freigabe an.",
|
|
24
25
|
inputSchema,
|
|
25
26
|
approval: {
|
|
26
|
-
request: salesApproval("order-confirmation", withSource),
|
|
27
|
+
request: withCard(salesApproval("order-confirmation", withSource)),
|
|
27
28
|
response: approverPolicy
|
|
28
29
|
},
|
|
29
30
|
async execute(input, ctx) {
|
|
@@ -9,6 +9,7 @@ import { approverPolicy, client, config } from "../lib/runtime.mjs";
|
|
|
9
9
|
import { MISSING_EUR_AMOUNT_INSTRUCTION, approvedPurchaseTarget, bookedGroupsOf, invoiceCurrencyOf, isAllowedAttachmentPath, isForeignCurrency, lacksEurAmount, purchaseSignatureOf, rememberPurchaseTarget, runPurchasePreflight, totalsOf } from "../lib/purchase.mjs";
|
|
10
10
|
import { describeWarning, isCorrectable, notesOf, rememberRejection, saveWarnings, wasRejected, wasShownOnCard } from "../lib/findings.mjs";
|
|
11
11
|
import { readJournal, writeJournal } from "../lib/journal.mjs";
|
|
12
|
+
import { withCard } from "../lib/with-card.mjs";
|
|
12
13
|
import { z } from "zod";
|
|
13
14
|
import { REVERSE_CHARGE_TAX_RATE, createVoucher, describeError, findPurchaseInvoiceByNumber, isReverseChargeCategory, round2, taxFromGross, uploadVoucherFile, voucherFileIds } from "@kevludwig/lexware-office";
|
|
14
15
|
import { defineTool } from "eve/tools";
|
|
@@ -59,7 +60,7 @@ var create_purchase_invoice_default = defineTool({
|
|
|
59
60
|
description: "Erfasst eine Eingangsrechnung (Lieferantenrechnung) als Beleg in Lexware Office und hängt das Original an. Beträge nach Steuersatz gruppiert, nicht als Einzelpositionen — die Artikel stehen im Anhang. Entsteht erst nach Freigabe, unter „Belege zur Prüfung“. Vorher wird geprüft, ob die Gruppen den Endbetrag ergeben und ob die Rechnungsnummer schon erfasst ist.",
|
|
60
61
|
inputSchema,
|
|
61
62
|
approval: {
|
|
62
|
-
request: async (ctx) => {
|
|
63
|
+
request: withCard(async (ctx) => {
|
|
63
64
|
const input = ctx.toolInput;
|
|
64
65
|
if (!input?.voucher_number) return "user-approval";
|
|
65
66
|
if (lacksEurAmount(input)) return {
|
|
@@ -114,7 +115,7 @@ var create_purchase_invoice_default = defineTool({
|
|
|
114
115
|
}
|
|
115
116
|
}
|
|
116
117
|
return "user-approval";
|
|
117
|
-
},
|
|
118
|
+
}),
|
|
118
119
|
response: approverPolicy
|
|
119
120
|
},
|
|
120
121
|
async execute(input, ctx) {
|
|
@@ -6,6 +6,7 @@ __eveDirname(__filename);
|
|
|
6
6
|
__eveCreateRequire(import.meta.url);
|
|
7
7
|
import { approverPolicy } from "../lib/runtime.mjs";
|
|
8
8
|
import { customerFields, executeSalesDocument, isCalendarDate, lineItemSchema, salesApproval, titleSchema } from "../lib/sales.mjs";
|
|
9
|
+
import { withCard } from "../lib/with-card.mjs";
|
|
9
10
|
import { z } from "zod";
|
|
10
11
|
import { defineTool } from "eve/tools";
|
|
11
12
|
const inputSchema = z.object({
|
|
@@ -18,7 +19,7 @@ var create_quotation_default = defineTool({
|
|
|
18
19
|
description: "Erstellt ein Angebot in Lexware Office und schreibt es direkt fest (es erhält eine Angebotsnummer; kein Entwurf). Kunde per Kundennummer oder contact_id — existiert er noch nicht, zuerst create_customer. Legt erst nach Freigabe an und prüft vorher, ob es für diesen Kunden schon ein Angebot mit gleicher Positionssumme gibt. Versendet wird aus Lexware Office.",
|
|
19
20
|
inputSchema,
|
|
20
21
|
approval: {
|
|
21
|
-
request: salesApproval("quotation"),
|
|
22
|
+
request: withCard(salesApproval("quotation")),
|
|
22
23
|
response: approverPolicy
|
|
23
24
|
},
|
|
24
25
|
async execute(input, ctx) {
|
|
@@ -9,6 +9,7 @@ import { approverPolicy, client, config, ledger, renderReminder } from "../lib/r
|
|
|
9
9
|
import { saveWarnings } from "../lib/findings.mjs";
|
|
10
10
|
import { readJournal, writeJournal } from "../lib/journal.mjs";
|
|
11
11
|
import { bindReminderTarget, boundReminderTarget } from "../lib/state.mjs";
|
|
12
|
+
import { withCard } from "../lib/with-card.mjs";
|
|
12
13
|
import { z } from "zod";
|
|
13
14
|
import { DEFAULT_REMINDER_POLICY, contactEmail, daysPastReminderDue, daysSince, describeError, earliestReminderDate, findOverdueInvoice, isDueImmediately, sendReminder } from "@kevludwig/lexware-office";
|
|
14
15
|
import { defineTool } from "eve/tools";
|
|
@@ -24,7 +25,7 @@ var send_payment_reminder_default = defineTool({
|
|
|
24
25
|
description: "Schickt eine freundliche Zahlungserinnerung zu einer überfälligen Rechnung per E-Mail, mit der Rechnung als PDF im Anhang. Die Werte (Nummer, Kunde, offener Betrag, Fälligkeit) übernimmst du unverändert aus Lexware Office bzw. aus dem Tool due_payment_reminders — dieses Tool prüft sie. Der Text ist fest vorgegeben. Verschickt wird erst nach Freigabe.",
|
|
25
26
|
inputSchema,
|
|
26
27
|
approval: {
|
|
27
|
-
request: async (ctx) => {
|
|
28
|
+
request: withCard(async (ctx) => {
|
|
28
29
|
const input = ctx.toolInput;
|
|
29
30
|
if (!input?.invoice_id) return "user-approval";
|
|
30
31
|
const reminders = config().reminders;
|
|
@@ -124,7 +125,7 @@ var send_payment_reminder_default = defineTool({
|
|
|
124
125
|
});
|
|
125
126
|
if (earlier?.status !== "sent") await ledger().markPending(invoice, ctx.session.id).catch(() => {});
|
|
126
127
|
return "user-approval";
|
|
127
|
-
},
|
|
128
|
+
}),
|
|
128
129
|
response: approverPolicy
|
|
129
130
|
},
|
|
130
131
|
async execute(_input, ctx) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kevludwig/eve-lexware-office",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"eve": {
|
|
6
6
|
"extension": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@vercel/blob": "^2.8.0",
|
|
26
26
|
"zod": "4.5.4",
|
|
27
|
-
"@kevludwig/lexware-office": "0.1.
|
|
27
|
+
"@kevludwig/lexware-office": "0.1.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/node": "24.x",
|