@kevludwig/eve-lexware-office 0.1.0 → 0.1.2
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 +2 -2
- package/dist/extension/_manifest.json +5 -5
- package/dist/extension/lib/purchase.d.ts +6 -1
- package/dist/extension/lib/purchase.mjs +12 -0
- package/dist/extension/lib/runtime.d.ts +6 -2
- package/dist/extension/lib/runtime.mjs +2 -2
- package/dist/extension/lib/types.d.ts +2 -2
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Built on [`@kevludwig/lexware-office`](../lexware-office), which holds the API c
|
|
|
8
8
|
npm install @kevludwig/eve-lexware-office @kevludwig/lexware-office
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Node 24 or newer, eve 0.
|
|
11
|
+
Node 24 or newer, eve 0.70 or newer.
|
|
12
12
|
|
|
13
13
|
## Mount it
|
|
14
14
|
|
|
@@ -68,7 +68,7 @@ Between card and click, hours can pass, so every writing tool checks again immed
|
|
|
68
68
|
| `baseUrl`, `appUrl` | the API and app URLs | Only for another environment. |
|
|
69
69
|
| `storage.store` | Vercel Blob | Where journal, reminder records, and send claims live. Any `JsonStore`. |
|
|
70
70
|
| `storage.prefix` | `lexware-office` | Key prefix inside the store. |
|
|
71
|
-
| `canApprove` | anyone in the session | `(responder) => boolean` — who may approve a write. |
|
|
71
|
+
| `canApprove` | anyone in the session | `(responder) => boolean` — who may approve a write or cancel it. |
|
|
72
72
|
| `onApprovalCard` | — | `(callId, card)` with the finished card: title, subtitle, facts, note, findings. For your own UI. |
|
|
73
73
|
| `conversationUrl` | — | `(sessionId) => string`, for "waits in another conversation". |
|
|
74
74
|
| `attachments` | — | A second source for an upload the sandbox lost: `{ read, size?, release? }`. |
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"kind": "eve-extension",
|
|
3
3
|
"formatVersion": 2,
|
|
4
|
-
"builtWithEve": "0.
|
|
4
|
+
"builtWithEve": "0.70.0",
|
|
5
5
|
"requires": {
|
|
6
6
|
"extension": 1,
|
|
7
|
-
"tool":
|
|
8
|
-
"hook":
|
|
9
|
-
"skill":
|
|
7
|
+
"tool": 73,
|
|
8
|
+
"hook": 37,
|
|
9
|
+
"skill": 2,
|
|
10
10
|
"instructions": 2,
|
|
11
11
|
"config": 1,
|
|
12
|
-
"state":
|
|
12
|
+
"state": 9
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -93,7 +93,12 @@ export declare function runPurchasePreflight(input: PurchaseInput, options?: {
|
|
|
93
93
|
category: PostingCategory | null;
|
|
94
94
|
groupCategories: Array<PostingCategory | null> | null;
|
|
95
95
|
}>;
|
|
96
|
-
/**
|
|
96
|
+
/**
|
|
97
|
+
* Per-group categories when a group names one, otherwise the single pick.
|
|
98
|
+
* Group categories face the same deviation check against the vendor's usual
|
|
99
|
+
* ones as the single pick — otherwise a category moved into a group would
|
|
100
|
+
* skip it.
|
|
101
|
+
*/
|
|
97
102
|
export declare function resolveCategories(input: PurchaseInput, contactId: string | undefined, signal?: AbortSignal): Promise<{
|
|
98
103
|
category: PostingCategory | null;
|
|
99
104
|
groupCategories: Array<PostingCategory | null> | null;
|
|
@@ -178,6 +178,10 @@ async function resolveCategories(input, contactId, signal) {
|
|
|
178
178
|
...await pickCategory(input, contactId, signal),
|
|
179
179
|
groupCategories: null
|
|
180
180
|
};
|
|
181
|
+
let usual = [];
|
|
182
|
+
if (contactId) try {
|
|
183
|
+
usual = (await findVendorCategoryHistory(client(), contactId, { signal })).categories;
|
|
184
|
+
} catch {}
|
|
181
185
|
const warnings = [];
|
|
182
186
|
const resolved = [];
|
|
183
187
|
for (const [index, group] of groups.entries()) {
|
|
@@ -201,6 +205,14 @@ async function resolveCategories(input, contactId, signal) {
|
|
|
201
205
|
resolved.push(null);
|
|
202
206
|
}
|
|
203
207
|
}
|
|
208
|
+
if (usual.length > 0) {
|
|
209
|
+
const deviating = new Set(resolved.flatMap((match) => match && !usual.some((category) => category.id === match.id) ? [match.name] : []));
|
|
210
|
+
for (const name of deviating) warnings.push({
|
|
211
|
+
kind: "category-deviation",
|
|
212
|
+
chosen: name,
|
|
213
|
+
usual: usual.map((category) => category.name).join(", ")
|
|
214
|
+
});
|
|
215
|
+
}
|
|
204
216
|
return {
|
|
205
217
|
category: null,
|
|
206
218
|
groupCategories: resolved,
|
|
@@ -13,6 +13,10 @@ export declare const store: () => JsonStore;
|
|
|
13
13
|
export declare function key(...segments: string[]): string;
|
|
14
14
|
export declare function ledger(): ReminderLedger;
|
|
15
15
|
export declare function renderReminder(): import("@kevludwig/lexware-office").RenderReminderMail;
|
|
16
|
-
/**
|
|
17
|
-
|
|
16
|
+
/**
|
|
17
|
+
* The response policy of every writing tool: the mount's canApprove, if any.
|
|
18
|
+
* eve asks it for Cancel as well as Approve — only someone allowed to approve
|
|
19
|
+
* may withdraw a request someone else is waiting on.
|
|
20
|
+
*/
|
|
21
|
+
export declare function approverPolicy<T>({ response }: ApprovalResponseContext<T>): Promise<ApprovalResponseDecision>;
|
|
18
22
|
export {};
|
|
@@ -36,9 +36,9 @@ function renderReminder() {
|
|
|
36
36
|
if (reminders.render) return reminders.render;
|
|
37
37
|
return defaultReminderMail(reminders.sender ?? { name: "Ihr Team" });
|
|
38
38
|
}
|
|
39
|
-
async function approverPolicy({
|
|
39
|
+
async function approverPolicy({ response }) {
|
|
40
40
|
const canApprove = config().canApprove;
|
|
41
|
-
if (!canApprove || await canApprove(
|
|
41
|
+
if (!canApprove || await canApprove(response.principal)) return { status: "allowed" };
|
|
42
42
|
return {
|
|
43
43
|
status: "rejected",
|
|
44
44
|
reason: "Nur berechtigte Personen dürfen freigeben."
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ApprovalResponseContext } from "eve/tools/approval";
|
|
2
|
-
/** Whoever answers an approval, as the channel authenticated them. */
|
|
3
|
-
export type Responder = ApprovalResponseContext["
|
|
2
|
+
/** Whoever answers an approval (approve or cancel), as the channel authenticated them. */
|
|
3
|
+
export type Responder = ApprovalResponseContext["response"]["principal"];
|
|
4
4
|
/** One line of findings on a card: "⚠ " in front of the title marks a warning. */
|
|
5
5
|
export interface Finding {
|
|
6
6
|
title: string;
|
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.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"eve": {
|
|
6
6
|
"extension": {
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@types/node": "24.x",
|
|
31
|
-
"eve": "0.
|
|
31
|
+
"eve": "0.70.0",
|
|
32
32
|
"typescript": "7.0.2"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"eve": "
|
|
35
|
+
"eve": ">=0.70.0"
|
|
36
36
|
},
|
|
37
37
|
"description": "eve extension for Lexware Office: read the account, create customers, quotations, order confirmations, invoices and purchase invoices, and send payment reminders — every write behind an approval.",
|
|
38
38
|
"license": "MIT",
|