@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 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.63 or newer.
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.63.0",
4
+ "builtWithEve": "0.70.0",
5
5
  "requires": {
6
6
  "extension": 1,
7
- "tool": 53,
8
- "hook": 24,
9
- "skill": 1,
7
+ "tool": 73,
8
+ "hook": 37,
9
+ "skill": 2,
10
10
  "instructions": 2,
11
11
  "config": 1,
12
- "state": 6
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
- /** Per-group categories when a group names one, otherwise the single pick. */
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
- /** The response policy of every writing tool: the mount's canApprove, if any. */
17
- export declare function approverPolicy<T>({ responder }: ApprovalResponseContext<T>): Promise<ApprovalResponseDecision>;
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({ responder }) {
39
+ async function approverPolicy({ response }) {
40
40
  const canApprove = config().canApprove;
41
- if (!canApprove || await canApprove(responder)) return { status: "allowed" };
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["responder"];
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.0",
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.63.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",