@ixo/editor 6.7.0 → 6.9.0
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/action-manifest.json +7 -7
- package/dist/{chunk-JS7P4DUX.js → chunk-ABM3ZZIX.js} +389 -650
- package/dist/chunk-ABM3ZZIX.js.map +1 -0
- package/dist/{chunk-RIJGQ4W6.js → chunk-VPMDJE6B.js} +2 -2
- package/dist/{chunk-ETSJMVZ7.js → chunk-ZE2EEZH6.js} +512 -246
- package/dist/chunk-ZE2EEZH6.js.map +1 -0
- package/dist/core/index.d.ts +114 -2
- package/dist/core/index.js +30 -2
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +3 -3
- package/dist/mantine/index.js +2 -2
- package/package.json +2 -2
- package/dist/chunk-ETSJMVZ7.js.map +0 -1
- package/dist/chunk-JS7P4DUX.js.map +0 -1
- /package/dist/{chunk-RIJGQ4W6.js.map → chunk-VPMDJE6B.js.map} +0 -0
|
@@ -439,6 +439,127 @@ function buildServicesFromHandlers(handlers) {
|
|
|
439
439
|
};
|
|
440
440
|
}
|
|
441
441
|
|
|
442
|
+
// src/core/lib/xeroWorkItems.ts
|
|
443
|
+
var XERO_WORK_ITEMS_MAP_NAME = "xeroWorkItems";
|
|
444
|
+
function getXeroWorkItemsMap(doc) {
|
|
445
|
+
return doc.getMap(XERO_WORK_ITEMS_MAP_NAME);
|
|
446
|
+
}
|
|
447
|
+
function getEditorXeroWorkItemsMap(editor) {
|
|
448
|
+
return editor?._yXeroWorkItems || null;
|
|
449
|
+
}
|
|
450
|
+
function readMapItems(map) {
|
|
451
|
+
if (!map) return [];
|
|
452
|
+
const items = [];
|
|
453
|
+
map.forEach((value) => {
|
|
454
|
+
if (value && typeof value === "object" && "id" in value) {
|
|
455
|
+
items.push({ ...value });
|
|
456
|
+
}
|
|
457
|
+
});
|
|
458
|
+
return items;
|
|
459
|
+
}
|
|
460
|
+
function mergeItem(existing, next) {
|
|
461
|
+
if (existing.status === "completed") {
|
|
462
|
+
return existing;
|
|
463
|
+
}
|
|
464
|
+
return {
|
|
465
|
+
...existing,
|
|
466
|
+
...next,
|
|
467
|
+
id: existing.id,
|
|
468
|
+
attempts: existing.attempts ?? [],
|
|
469
|
+
originalPayload: existing.originalPayload,
|
|
470
|
+
submittedPayload: existing.submittedPayload,
|
|
471
|
+
result: existing.result,
|
|
472
|
+
completedAt: existing.completedAt,
|
|
473
|
+
completedByDid: existing.completedByDid
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
function buildXeroInvoiceWorkKey(params) {
|
|
477
|
+
return ["xero", "invoice.create", params.flowId, params.evaluationBlockId, params.claimId].join(":");
|
|
478
|
+
}
|
|
479
|
+
function buildXeroPaymentWorkKey(params) {
|
|
480
|
+
return ["xero", "payment.create", params.flowId, params.evaluationBlockId, params.claimId, params.invoiceWorkItemId].join(":");
|
|
481
|
+
}
|
|
482
|
+
function findXeroWorkItems(map, filter = {}) {
|
|
483
|
+
return readMapItems(map).filter((item) => {
|
|
484
|
+
if (filter.kind && item.kind !== filter.kind) return false;
|
|
485
|
+
if (filter.assignedBlockId && item.assignedBlockId !== filter.assignedBlockId) return false;
|
|
486
|
+
if (filter.statuses && !filter.statuses.includes(item.status)) return false;
|
|
487
|
+
return true;
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
function upsertXeroWorkItem(map, next) {
|
|
491
|
+
if (!map) {
|
|
492
|
+
return next;
|
|
493
|
+
}
|
|
494
|
+
let existing;
|
|
495
|
+
map.forEach((item) => {
|
|
496
|
+
if (item?.idempotencyKey === next.idempotencyKey) existing = item;
|
|
497
|
+
});
|
|
498
|
+
const stored = existing ? mergeItem(existing, next) : next;
|
|
499
|
+
map.set(stored.id, stored);
|
|
500
|
+
return stored;
|
|
501
|
+
}
|
|
502
|
+
function updateXeroWorkReviewPayload(map, itemId, reviewPayload) {
|
|
503
|
+
if (!map) return null;
|
|
504
|
+
const item = map.get(itemId);
|
|
505
|
+
if (!item) return null;
|
|
506
|
+
if (item.status === "completed") return item;
|
|
507
|
+
const updatedItem = { ...item, reviewPayload };
|
|
508
|
+
map.set(itemId, updatedItem);
|
|
509
|
+
return updatedItem;
|
|
510
|
+
}
|
|
511
|
+
function markXeroWorkFailed(map, itemId, params) {
|
|
512
|
+
if (!map) return null;
|
|
513
|
+
const item = map.get(itemId);
|
|
514
|
+
if (!item) return null;
|
|
515
|
+
if (item.status === "completed") return item;
|
|
516
|
+
const at = params.at ?? Date.now();
|
|
517
|
+
const updatedItem = {
|
|
518
|
+
...item,
|
|
519
|
+
status: "failed",
|
|
520
|
+
reviewPayload: params.payload,
|
|
521
|
+
error: { message: params.error, at },
|
|
522
|
+
attempts: [...item.attempts ?? [], { at, byDid: params.byDid, payload: params.payload, error: params.error }]
|
|
523
|
+
};
|
|
524
|
+
map.set(itemId, updatedItem);
|
|
525
|
+
return updatedItem;
|
|
526
|
+
}
|
|
527
|
+
function markXeroWorkCompleted(map, itemId, params) {
|
|
528
|
+
if (!map) return null;
|
|
529
|
+
const item = map.get(itemId);
|
|
530
|
+
if (!item) return null;
|
|
531
|
+
if (item.status === "completed") return item;
|
|
532
|
+
const at = params.at ?? Date.now();
|
|
533
|
+
const updatedItem = {
|
|
534
|
+
...item,
|
|
535
|
+
status: "completed",
|
|
536
|
+
reviewPayload: params.payload,
|
|
537
|
+
submittedPayload: params.payload,
|
|
538
|
+
result: params.result,
|
|
539
|
+
error: void 0,
|
|
540
|
+
completedAt: at,
|
|
541
|
+
completedByDid: params.byDid,
|
|
542
|
+
attempts: [...item.attempts ?? [], { at, byDid: params.byDid, payload: params.payload, result: params.result }]
|
|
543
|
+
};
|
|
544
|
+
map.set(itemId, updatedItem);
|
|
545
|
+
return updatedItem;
|
|
546
|
+
}
|
|
547
|
+
function findXeroWorkItemsForEditor(editor, filter) {
|
|
548
|
+
return findXeroWorkItems(getEditorXeroWorkItemsMap(editor), filter);
|
|
549
|
+
}
|
|
550
|
+
function upsertXeroWorkItemForEditor(editor, next) {
|
|
551
|
+
return upsertXeroWorkItem(getEditorXeroWorkItemsMap(editor), next);
|
|
552
|
+
}
|
|
553
|
+
function updateXeroWorkReviewPayloadForEditor(editor, itemId, reviewPayload) {
|
|
554
|
+
return updateXeroWorkReviewPayload(getEditorXeroWorkItemsMap(editor), itemId, reviewPayload);
|
|
555
|
+
}
|
|
556
|
+
function markXeroWorkFailedForEditor(editor, itemId, params) {
|
|
557
|
+
return markXeroWorkFailed(getEditorXeroWorkItemsMap(editor), itemId, params);
|
|
558
|
+
}
|
|
559
|
+
function markXeroWorkCompletedForEditor(editor, itemId, params) {
|
|
560
|
+
return markXeroWorkCompleted(getEditorXeroWorkItemsMap(editor), itemId, params);
|
|
561
|
+
}
|
|
562
|
+
|
|
442
563
|
// src/core/lib/matrixDm.ts
|
|
443
564
|
function getHomeserver(matrixClient) {
|
|
444
565
|
const userId = matrixClient.getUserId();
|
|
@@ -2939,606 +3060,89 @@ registerAction({
|
|
|
2939
3060
|
throw new Error("surveyAnswers must be valid JSON");
|
|
2940
3061
|
}
|
|
2941
3062
|
}
|
|
2942
|
-
if (!surveyAnswers || typeof surveyAnswers !== "object" || Array.isArray(surveyAnswers)) {
|
|
2943
|
-
throw new Error("surveyAnswers must be an object");
|
|
2944
|
-
}
|
|
2945
|
-
let pin = String(inputs.pin || "").trim();
|
|
2946
|
-
if (!pin) {
|
|
2947
|
-
pin = await service.requestPin({
|
|
2948
|
-
title: "Verify Identity",
|
|
2949
|
-
description: "Enter your PIN to submit the claim",
|
|
2950
|
-
submitText: "Verify"
|
|
2951
|
-
});
|
|
2952
|
-
}
|
|
2953
|
-
if (!pin) {
|
|
2954
|
-
throw new Error("PIN is required to submit claim");
|
|
2955
|
-
}
|
|
2956
|
-
if (isGroupExecution(inputs)) {
|
|
2957
|
-
const { coreAddress, title, description } = requireGroupExecutionParams(inputs);
|
|
2958
|
-
const handlers = ctx.handlers;
|
|
2959
|
-
if (typeof handlers?.prepareGroupClaimSubmission !== "function") {
|
|
2960
|
-
throw new Error("Acting as a POD is not available: the host does not implement prepareGroupClaimSubmission");
|
|
2961
|
-
}
|
|
2962
|
-
const prepared = await handlers.prepareGroupClaimSubmission({
|
|
2963
|
-
surveyData: surveyAnswers,
|
|
2964
|
-
deedDid,
|
|
2965
|
-
entityDid: deedDid,
|
|
2966
|
-
collectionId,
|
|
2967
|
-
adminAddress,
|
|
2968
|
-
pin,
|
|
2969
|
-
groupAddress: coreAddress
|
|
2970
|
-
});
|
|
2971
|
-
const claimId2 = String(prepared?.claimId || "").trim();
|
|
2972
|
-
if (!claimId2) throw new Error("prepareGroupClaimSubmission returned no claim identifier");
|
|
2973
|
-
return proposeGroupExecution(ctx, {
|
|
2974
|
-
coreAddress,
|
|
2975
|
-
title,
|
|
2976
|
-
description,
|
|
2977
|
-
msgs: prepared.msgs || [],
|
|
2978
|
-
expectedOutput: {
|
|
2979
|
-
claimId: claimId2,
|
|
2980
|
-
transactionHash: "",
|
|
2981
|
-
collectionId,
|
|
2982
|
-
deedDid,
|
|
2983
|
-
submittedByDid: coreAddress,
|
|
2984
|
-
submittedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2985
|
-
surveyAnswers
|
|
2986
|
-
},
|
|
2987
|
-
completionEvent: "submitted"
|
|
2988
|
-
});
|
|
2989
|
-
}
|
|
2990
|
-
const result = await service.submitClaim({
|
|
2991
|
-
surveyData: surveyAnswers,
|
|
2992
|
-
deedDid,
|
|
2993
|
-
entityDid: deedDid,
|
|
2994
|
-
collectionId,
|
|
2995
|
-
adminAddress,
|
|
2996
|
-
pin
|
|
2997
|
-
});
|
|
2998
|
-
const claimId = String(result?.claimId || result?.id || "");
|
|
2999
|
-
if (!claimId) {
|
|
3000
|
-
throw new Error("submitClaim returned no claim identifier");
|
|
3001
|
-
}
|
|
3002
|
-
const transactionHash = String(result?.transactionHash || "");
|
|
3003
|
-
const submittedByDid = ctx.actorDid || "";
|
|
3004
|
-
const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3005
|
-
const output = {
|
|
3006
|
-
claimId,
|
|
3007
|
-
transactionHash,
|
|
3008
|
-
collectionId,
|
|
3009
|
-
deedDid,
|
|
3010
|
-
submittedByDid,
|
|
3011
|
-
submittedAt,
|
|
3012
|
-
surveyAnswers
|
|
3013
|
-
};
|
|
3014
|
-
return {
|
|
3015
|
-
output,
|
|
3016
|
-
events: [
|
|
3017
|
-
{
|
|
3018
|
-
name: "submitted",
|
|
3019
|
-
payload: output
|
|
3020
|
-
}
|
|
3021
|
-
]
|
|
3022
|
-
};
|
|
3023
|
-
}
|
|
3024
|
-
});
|
|
3025
|
-
|
|
3026
|
-
// src/core/lib/xeroWorkItems.ts
|
|
3027
|
-
function getXeroWorkItemsMap(editor) {
|
|
3028
|
-
return editor?._yXeroWorkItems || null;
|
|
3029
|
-
}
|
|
3030
|
-
function readMapItems(map) {
|
|
3031
|
-
if (!map) return [];
|
|
3032
|
-
const items = [];
|
|
3033
|
-
map.forEach((value) => {
|
|
3034
|
-
if (value && typeof value === "object" && "id" in value) {
|
|
3035
|
-
items.push({ ...value });
|
|
3036
|
-
}
|
|
3037
|
-
});
|
|
3038
|
-
return items;
|
|
3039
|
-
}
|
|
3040
|
-
function mergeItem(existing, next) {
|
|
3041
|
-
if (existing.status === "completed") {
|
|
3042
|
-
return existing;
|
|
3043
|
-
}
|
|
3044
|
-
return {
|
|
3045
|
-
...existing,
|
|
3046
|
-
...next,
|
|
3047
|
-
id: existing.id,
|
|
3048
|
-
attempts: existing.attempts ?? [],
|
|
3049
|
-
originalPayload: existing.originalPayload,
|
|
3050
|
-
submittedPayload: existing.submittedPayload,
|
|
3051
|
-
result: existing.result,
|
|
3052
|
-
completedAt: existing.completedAt,
|
|
3053
|
-
completedByDid: existing.completedByDid
|
|
3054
|
-
};
|
|
3055
|
-
}
|
|
3056
|
-
function buildXeroInvoiceWorkKey(params) {
|
|
3057
|
-
return ["xero", "invoice.create", params.flowId, params.evaluationBlockId, params.claimId, params.invoiceBlockId].join(":");
|
|
3058
|
-
}
|
|
3059
|
-
function buildXeroPaymentWorkKey(params) {
|
|
3060
|
-
return ["xero", "payment.create", params.flowId, params.evaluationBlockId, params.claimId, params.paymentBlockId, params.invoiceWorkItemId].join(":");
|
|
3061
|
-
}
|
|
3062
|
-
function findXeroWorkItemsForEditor(editor, filter) {
|
|
3063
|
-
return readMapItems(getXeroWorkItemsMap(editor)).filter((item) => {
|
|
3064
|
-
if (filter.kind && item.kind !== filter.kind) return false;
|
|
3065
|
-
if (filter.assignedBlockId && item.assignedBlockId !== filter.assignedBlockId) return false;
|
|
3066
|
-
if (filter.statuses && !filter.statuses.includes(item.status)) return false;
|
|
3067
|
-
return true;
|
|
3068
|
-
});
|
|
3069
|
-
}
|
|
3070
|
-
function upsertXeroWorkItemForEditor(editor, next) {
|
|
3071
|
-
const map = getXeroWorkItemsMap(editor);
|
|
3072
|
-
if (!map) {
|
|
3073
|
-
return next;
|
|
3074
|
-
}
|
|
3075
|
-
let existing;
|
|
3076
|
-
map.forEach((item) => {
|
|
3077
|
-
if (item?.idempotencyKey === next.idempotencyKey) existing = item;
|
|
3078
|
-
});
|
|
3079
|
-
const stored = existing ? mergeItem(existing, next) : next;
|
|
3080
|
-
map.set(stored.id, stored);
|
|
3081
|
-
return stored;
|
|
3082
|
-
}
|
|
3083
|
-
function updateXeroWorkReviewPayloadForEditor(editor, itemId, reviewPayload) {
|
|
3084
|
-
const map = getXeroWorkItemsMap(editor);
|
|
3085
|
-
if (!map) return null;
|
|
3086
|
-
const item = map.get(itemId);
|
|
3087
|
-
if (!item) return null;
|
|
3088
|
-
const updatedItem = { ...item, reviewPayload };
|
|
3089
|
-
map.set(itemId, updatedItem);
|
|
3090
|
-
return updatedItem;
|
|
3091
|
-
}
|
|
3092
|
-
function markXeroWorkFailedForEditor(editor, itemId, params) {
|
|
3093
|
-
const map = getXeroWorkItemsMap(editor);
|
|
3094
|
-
if (!map) return null;
|
|
3095
|
-
const item = map.get(itemId);
|
|
3096
|
-
if (!item) return null;
|
|
3097
|
-
const at = params.at ?? Date.now();
|
|
3098
|
-
const updatedItem = {
|
|
3099
|
-
...item,
|
|
3100
|
-
status: "failed",
|
|
3101
|
-
reviewPayload: params.payload,
|
|
3102
|
-
error: { message: params.error, at },
|
|
3103
|
-
attempts: [...item.attempts ?? [], { at, byDid: params.byDid, payload: params.payload, error: params.error }]
|
|
3104
|
-
};
|
|
3105
|
-
map.set(itemId, updatedItem);
|
|
3106
|
-
return updatedItem;
|
|
3107
|
-
}
|
|
3108
|
-
function markXeroWorkCompletedForEditor(editor, itemId, params) {
|
|
3109
|
-
const map = getXeroWorkItemsMap(editor);
|
|
3110
|
-
if (!map) return null;
|
|
3111
|
-
const item = map.get(itemId);
|
|
3112
|
-
if (!item) return null;
|
|
3113
|
-
const at = params.at ?? Date.now();
|
|
3114
|
-
const updatedItem = {
|
|
3115
|
-
...item,
|
|
3116
|
-
status: "completed",
|
|
3117
|
-
reviewPayload: params.payload,
|
|
3118
|
-
submittedPayload: params.payload,
|
|
3119
|
-
result: params.result,
|
|
3120
|
-
error: void 0,
|
|
3121
|
-
completedAt: at,
|
|
3122
|
-
completedByDid: params.byDid,
|
|
3123
|
-
attempts: [...item.attempts ?? [], { at, byDid: params.byDid, payload: params.payload, result: params.result }]
|
|
3124
|
-
};
|
|
3125
|
-
map.set(itemId, updatedItem);
|
|
3126
|
-
return updatedItem;
|
|
3127
|
-
}
|
|
3128
|
-
|
|
3129
|
-
// src/core/lib/actionRegistry/actions/xero/invoiceCreate.types.ts
|
|
3130
|
-
var LINE_ITEM_FIELD_KEYS = ["Description", "Quantity", "UnitAmount", "AccountCode", "TaxType", "ItemCode", "DiscountRate"];
|
|
3131
|
-
function emptyLineItemCells() {
|
|
3132
|
-
return {
|
|
3133
|
-
Description: "",
|
|
3134
|
-
Quantity: "1",
|
|
3135
|
-
UnitAmount: "",
|
|
3136
|
-
AccountCode: "",
|
|
3137
|
-
TaxType: "",
|
|
3138
|
-
ItemCode: "",
|
|
3139
|
-
DiscountRate: ""
|
|
3140
|
-
};
|
|
3141
|
-
}
|
|
3142
|
-
function emptyLineItems() {
|
|
3143
|
-
return { mode: "manual", rows: [emptyLineItemCells()] };
|
|
3144
|
-
}
|
|
3145
|
-
function coerceCells(raw) {
|
|
3146
|
-
const base = emptyLineItemCells();
|
|
3147
|
-
if (!raw || typeof raw !== "object") return base;
|
|
3148
|
-
for (const key of LINE_ITEM_FIELD_KEYS) {
|
|
3149
|
-
const v = raw[key];
|
|
3150
|
-
if (typeof v === "string") base[key] = v;
|
|
3151
|
-
else if (typeof v === "number") base[key] = String(v);
|
|
3152
|
-
else if (typeof v === "boolean") base[key] = v ? "true" : "false";
|
|
3153
|
-
}
|
|
3154
|
-
return base;
|
|
3155
|
-
}
|
|
3156
|
-
function normaliseLineItems(raw) {
|
|
3157
|
-
if (raw && typeof raw === "object") {
|
|
3158
|
-
const candidate = raw;
|
|
3159
|
-
if (candidate.mode === "iterative") {
|
|
3160
|
-
return {
|
|
3161
|
-
mode: "iterative",
|
|
3162
|
-
source: typeof candidate.source === "string" ? candidate.source : "",
|
|
3163
|
-
map: coerceCells(candidate.map)
|
|
3164
|
-
};
|
|
3165
|
-
}
|
|
3166
|
-
if (candidate.mode === "manual") {
|
|
3167
|
-
const rows = Array.isArray(candidate.rows) ? candidate.rows.map(coerceCells) : [];
|
|
3168
|
-
return { mode: "manual", rows: rows.length > 0 ? rows : [emptyLineItemCells()] };
|
|
3169
|
-
}
|
|
3170
|
-
}
|
|
3171
|
-
if (typeof raw === "string") {
|
|
3172
|
-
const trimmed = raw.trim();
|
|
3173
|
-
if (!trimmed) return emptyLineItems();
|
|
3174
|
-
try {
|
|
3175
|
-
const parsed = JSON.parse(trimmed);
|
|
3176
|
-
if (Array.isArray(parsed) && parsed.length > 0) {
|
|
3177
|
-
return { mode: "manual", rows: parsed.map(coerceCells) };
|
|
3178
|
-
}
|
|
3179
|
-
} catch {
|
|
3180
|
-
}
|
|
3181
|
-
}
|
|
3182
|
-
return emptyLineItems();
|
|
3183
|
-
}
|
|
3184
|
-
function parseXeroInvoiceCreateInputs(raw) {
|
|
3185
|
-
try {
|
|
3186
|
-
const parsed = typeof raw === "string" ? JSON.parse(raw || "{}") : raw || {};
|
|
3187
|
-
const conn = parsed.connection;
|
|
3188
|
-
const connection = conn && typeof conn === "object" && typeof conn.connectedAccountId === "string" && typeof conn.entityDid === "string" ? { connectedAccountId: conn.connectedAccountId, entityDid: conn.entityDid } : null;
|
|
3189
|
-
return {
|
|
3190
|
-
connection,
|
|
3191
|
-
tenant_id: typeof parsed.tenant_id === "string" ? parsed.tenant_id : "",
|
|
3192
|
-
Type: typeof parsed.Type === "string" && parsed.Type ? parsed.Type : "ACCREC",
|
|
3193
|
-
Status: typeof parsed.Status === "string" ? parsed.Status : "DRAFT",
|
|
3194
|
-
Date: typeof parsed.Date === "string" ? parsed.Date : "",
|
|
3195
|
-
DueDate: typeof parsed.DueDate === "string" ? parsed.DueDate : "",
|
|
3196
|
-
ContactID: typeof parsed.ContactID === "string" ? parsed.ContactID : "",
|
|
3197
|
-
ContactName: typeof parsed.ContactName === "string" ? parsed.ContactName : "",
|
|
3198
|
-
Reference: typeof parsed.Reference === "string" ? parsed.Reference : "",
|
|
3199
|
-
InvoiceNumber: typeof parsed.InvoiceNumber === "string" ? parsed.InvoiceNumber : "",
|
|
3200
|
-
CurrencyCode: typeof parsed.CurrencyCode === "string" ? parsed.CurrencyCode : "",
|
|
3201
|
-
LineItems: normaliseLineItems(parsed.LineItems)
|
|
3202
|
-
};
|
|
3203
|
-
} catch {
|
|
3204
|
-
return {
|
|
3205
|
-
connection: null,
|
|
3206
|
-
tenant_id: "",
|
|
3207
|
-
Type: "ACCREC",
|
|
3208
|
-
Status: "DRAFT",
|
|
3209
|
-
Date: "",
|
|
3210
|
-
DueDate: "",
|
|
3211
|
-
ContactID: "",
|
|
3212
|
-
ContactName: "",
|
|
3213
|
-
Reference: "",
|
|
3214
|
-
InvoiceNumber: "",
|
|
3215
|
-
CurrencyCode: "",
|
|
3216
|
-
LineItems: emptyLineItems()
|
|
3217
|
-
};
|
|
3218
|
-
}
|
|
3219
|
-
}
|
|
3220
|
-
function serializeXeroInvoiceCreateInputs(inputs) {
|
|
3221
|
-
return JSON.stringify(inputs);
|
|
3222
|
-
}
|
|
3223
|
-
var NUMERIC_LINE_ITEM_FIELDS = ["Quantity", "UnitAmount", "DiscountRate"];
|
|
3224
|
-
function finaliseLineItem(cells) {
|
|
3225
|
-
const out = {};
|
|
3226
|
-
for (const key of LINE_ITEM_FIELD_KEYS) {
|
|
3227
|
-
const raw = (cells[key] ?? "").trim();
|
|
3228
|
-
if (!raw) continue;
|
|
3229
|
-
if (NUMERIC_LINE_ITEM_FIELDS.includes(key)) {
|
|
3230
|
-
const n = Number(raw);
|
|
3231
|
-
if (!Number.isFinite(n)) {
|
|
3232
|
-
throw new Error(`Line item field ${key} must be a number; got "${raw}"`);
|
|
3233
|
-
}
|
|
3234
|
-
out[key] = n;
|
|
3235
|
-
} else {
|
|
3236
|
-
out[key] = raw;
|
|
3237
|
-
}
|
|
3238
|
-
}
|
|
3239
|
-
if (!out.Description) {
|
|
3240
|
-
out.Description = "payment";
|
|
3241
|
-
}
|
|
3242
|
-
return out;
|
|
3243
|
-
}
|
|
3244
|
-
|
|
3245
|
-
// src/core/lib/actionRegistry/actions/xero/paymentCreate.types.ts
|
|
3246
|
-
function parseXeroPaymentCreateInputs(raw) {
|
|
3247
|
-
try {
|
|
3248
|
-
const parsed = typeof raw === "string" ? JSON.parse(raw || "{}") : raw || {};
|
|
3249
|
-
const conn = parsed.connection;
|
|
3250
|
-
const connection = conn && typeof conn === "object" && typeof conn.connectedAccountId === "string" && typeof conn.entityDid === "string" ? { connectedAccountId: conn.connectedAccountId, entityDid: conn.entityDid } : null;
|
|
3251
|
-
return {
|
|
3252
|
-
connection,
|
|
3253
|
-
tenant_id: typeof parsed.tenant_id === "string" ? parsed.tenant_id : "",
|
|
3254
|
-
InvoiceID: typeof parsed.InvoiceID === "string" ? parsed.InvoiceID : "",
|
|
3255
|
-
AccountID: typeof parsed.AccountID === "string" ? parsed.AccountID : "",
|
|
3256
|
-
Date: typeof parsed.Date === "string" ? parsed.Date : "",
|
|
3257
|
-
Amount: typeof parsed.Amount === "string" ? parsed.Amount : typeof parsed.Amount === "number" ? String(parsed.Amount) : "",
|
|
3258
|
-
Reference: typeof parsed.Reference === "string" ? parsed.Reference : "",
|
|
3259
|
-
CurrencyRate: typeof parsed.CurrencyRate === "string" ? parsed.CurrencyRate : ""
|
|
3260
|
-
};
|
|
3261
|
-
} catch {
|
|
3262
|
-
return {
|
|
3263
|
-
connection: null,
|
|
3264
|
-
tenant_id: "",
|
|
3265
|
-
InvoiceID: "",
|
|
3266
|
-
AccountID: "",
|
|
3267
|
-
Date: "",
|
|
3268
|
-
Amount: "",
|
|
3269
|
-
Reference: "",
|
|
3270
|
-
CurrencyRate: ""
|
|
3271
|
-
};
|
|
3272
|
-
}
|
|
3273
|
-
}
|
|
3274
|
-
function serializeXeroPaymentCreateInputs(inputs) {
|
|
3275
|
-
return JSON.stringify(inputs);
|
|
3276
|
-
}
|
|
3277
|
-
|
|
3278
|
-
// src/core/lib/flowEngine/referenceResolver.ts
|
|
3279
|
-
var REFERENCE_REGEX = /\{\{([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_.:]+)\}\}/g;
|
|
3280
|
-
function parseReferences(input) {
|
|
3281
|
-
const references = [];
|
|
3282
|
-
const regex = new RegExp(REFERENCE_REGEX);
|
|
3283
|
-
let match;
|
|
3284
|
-
while ((match = regex.exec(input)) !== null) {
|
|
3285
|
-
references.push({
|
|
3286
|
-
fullMatch: match[0],
|
|
3287
|
-
blockId: match[1],
|
|
3288
|
-
propPath: match[2],
|
|
3289
|
-
startIndex: match.index,
|
|
3290
|
-
endIndex: match.index + match[0].length
|
|
3291
|
-
});
|
|
3292
|
-
}
|
|
3293
|
-
return references;
|
|
3294
|
-
}
|
|
3295
|
-
function getNestedValue(obj, path) {
|
|
3296
|
-
return path.split(".").reduce((current, key) => {
|
|
3297
|
-
return current?.[key];
|
|
3298
|
-
}, obj);
|
|
3299
|
-
}
|
|
3300
|
-
function resolveSingleReferenceDetailed(blockId, propPath, editorDocument, yRuntime, scope) {
|
|
3301
|
-
if (scope && Object.prototype.hasOwnProperty.call(scope, blockId)) {
|
|
3302
|
-
const root = scope[blockId];
|
|
3303
|
-
if (root == null) return { value: void 0, reason: "missing-value" };
|
|
3304
|
-
const value2 = getNestedValue(root, propPath);
|
|
3305
|
-
return { value: value2, reason: value2 === void 0 ? "missing-value" : void 0 };
|
|
3306
|
-
}
|
|
3307
|
-
if (!editorDocument || !Array.isArray(editorDocument)) {
|
|
3308
|
-
return { value: void 0, reason: "unknown-block" };
|
|
3309
|
-
}
|
|
3310
|
-
const block = editorDocument.find((b) => b.id === blockId);
|
|
3311
|
-
if (!block) {
|
|
3312
|
-
return { value: void 0, reason: "unknown-block" };
|
|
3313
|
-
}
|
|
3314
|
-
if (propPath.startsWith("output.")) {
|
|
3315
|
-
if (!yRuntime) return { value: void 0, reason: "missing-value" };
|
|
3316
|
-
const runtimeState = yRuntime.get(blockId);
|
|
3317
|
-
if (!runtimeState?.output) return { value: void 0, reason: "missing-value" };
|
|
3318
|
-
const innerPath = propPath.substring("output.".length);
|
|
3319
|
-
const direct = getNestedValue(runtimeState.output, innerPath);
|
|
3320
|
-
if (direct !== void 0) return { value: direct };
|
|
3321
|
-
if (runtimeState.output.data !== void 0) {
|
|
3322
|
-
const value2 = getNestedValue(runtimeState.output.data, innerPath);
|
|
3323
|
-
return { value: value2, reason: value2 === void 0 ? "missing-value" : void 0 };
|
|
3324
|
-
}
|
|
3325
|
-
if (runtimeState.output.http?.data !== void 0) {
|
|
3326
|
-
const value2 = getNestedValue(runtimeState.output.http.data, innerPath);
|
|
3327
|
-
return { value: value2, reason: value2 === void 0 ? "missing-value" : void 0 };
|
|
3328
|
-
}
|
|
3329
|
-
return { value: void 0, reason: "missing-value" };
|
|
3330
|
-
}
|
|
3331
|
-
if (propPath.startsWith("response.")) {
|
|
3332
|
-
const responseData = block.props.response;
|
|
3333
|
-
if (!responseData) {
|
|
3334
|
-
return { value: void 0, reason: "missing-value" };
|
|
3335
|
-
}
|
|
3336
|
-
try {
|
|
3337
|
-
const parsedResponse = typeof responseData === "string" ? JSON.parse(responseData) : responseData;
|
|
3338
|
-
const innerPath = propPath.substring("response.".length);
|
|
3339
|
-
const value2 = getNestedValue(parsedResponse, innerPath);
|
|
3340
|
-
return { value: value2, reason: value2 === void 0 ? "missing-value" : void 0 };
|
|
3341
|
-
} catch {
|
|
3342
|
-
warnOnce(`ref-response-parse:${blockId}`, `[flow-config] block ${blockId}: props.response is not valid JSON; {{${blockId}.${propPath}}} cannot resolve`);
|
|
3343
|
-
return { value: void 0, reason: "response-parse-error" };
|
|
3344
|
-
}
|
|
3345
|
-
}
|
|
3346
|
-
const value = getNestedValue(block.props, propPath);
|
|
3347
|
-
return { value, reason: value === void 0 ? "missing-value" : void 0 };
|
|
3348
|
-
}
|
|
3349
|
-
function resolveSingleReference(blockId, propPath, editorDocument, yRuntime, scope) {
|
|
3350
|
-
return resolveSingleReferenceDetailed(blockId, propPath, editorDocument, yRuntime, scope).value;
|
|
3351
|
-
}
|
|
3352
|
-
function resolveReferencesDetailed(input, editorDocument, options = {}) {
|
|
3353
|
-
const { fallback = "", stringifyObjects = true, yRuntime, scope, warnContext } = options;
|
|
3354
|
-
const unresolved = [];
|
|
3355
|
-
if (input == null) {
|
|
3356
|
-
return { value: "", unresolved };
|
|
3357
|
-
}
|
|
3358
|
-
const inputStr = String(input);
|
|
3359
|
-
const references = parseReferences(inputStr);
|
|
3360
|
-
if (references.length === 0) {
|
|
3361
|
-
return { value: inputStr, unresolved };
|
|
3362
|
-
}
|
|
3363
|
-
let result = inputStr;
|
|
3364
|
-
for (let i = references.length - 1; i >= 0; i--) {
|
|
3365
|
-
const ref = references[i];
|
|
3366
|
-
const resolution = resolveSingleReferenceDetailed(ref.blockId, ref.propPath, editorDocument, yRuntime, scope);
|
|
3367
|
-
const resolvedValue = resolution.value;
|
|
3368
|
-
let replacementStr;
|
|
3369
|
-
if (resolvedValue === void 0 || resolvedValue === null) {
|
|
3370
|
-
replacementStr = fallback;
|
|
3371
|
-
unresolved.push({ ref: ref.fullMatch, blockId: ref.blockId, propPath: ref.propPath, reason: resolution.reason || "missing-value" });
|
|
3372
|
-
} else if (typeof resolvedValue === "object") {
|
|
3373
|
-
replacementStr = stringifyObjects ? JSON.stringify(resolvedValue) : fallback;
|
|
3374
|
-
} else {
|
|
3375
|
-
replacementStr = String(resolvedValue);
|
|
3376
|
-
}
|
|
3377
|
-
result = result.substring(0, ref.startIndex) + replacementStr + result.substring(ref.endIndex);
|
|
3378
|
-
}
|
|
3379
|
-
if (warnContext && unresolved.length > 0) {
|
|
3380
|
-
for (const entry of unresolved) {
|
|
3381
|
-
warnOnce(`ref-unresolved:${warnContext}:${entry.ref}`, `[flow-config] ${warnContext}: reference ${entry.ref} did not resolve (${entry.reason}); using fallback '${fallback}'`);
|
|
3382
|
-
}
|
|
3383
|
-
}
|
|
3384
|
-
return { value: result, unresolved };
|
|
3385
|
-
}
|
|
3386
|
-
function resolveReferences(input, editorDocument, options = {}) {
|
|
3387
|
-
return resolveReferencesDetailed(input, editorDocument, options).value;
|
|
3388
|
-
}
|
|
3389
|
-
function hasReferences(input) {
|
|
3390
|
-
if (input == null) return false;
|
|
3391
|
-
return parseReferences(String(input)).length > 0;
|
|
3392
|
-
}
|
|
3393
|
-
function createReference(blockId, propPath) {
|
|
3394
|
-
return `{{${blockId}.${propPath}}}`;
|
|
3395
|
-
}
|
|
3396
|
-
|
|
3397
|
-
// src/core/lib/xeroWorkItemPayloads.ts
|
|
3398
|
-
function resolveXeroBindings(editorDocument, invoiceBlockId, paymentBlockId) {
|
|
3399
|
-
if (!Array.isArray(editorDocument)) return { invoiceCreateBlock: null, paymentCreateBlock: null, evaluateBlockId: null };
|
|
3400
|
-
const findById = (id, expectedActionType) => {
|
|
3401
|
-
const trimmed = String(id || "").trim();
|
|
3402
|
-
if (!trimmed) return null;
|
|
3403
|
-
const block = editorDocument.find((b) => b?.id === trimmed);
|
|
3404
|
-
if (!block || block.type !== "action" || block.props?.actionType !== expectedActionType) return null;
|
|
3405
|
-
return block;
|
|
3406
|
-
};
|
|
3407
|
-
return {
|
|
3408
|
-
invoiceCreateBlock: findById(invoiceBlockId, "qi/xero.invoice.create"),
|
|
3409
|
-
paymentCreateBlock: findById(paymentBlockId, "qi/xero.payment.create"),
|
|
3410
|
-
evaluateBlockId: null
|
|
3411
|
-
};
|
|
3412
|
-
}
|
|
3413
|
-
function buildClaimScope(claim, claimData, evaluateBlockId, evaluateContext) {
|
|
3414
|
-
const surveyAnswers = claimData && typeof claimData === "object" ? claimData.credentialSubject ?? claimData.surveyAnswers ?? claimData : {};
|
|
3415
|
-
const evaluationOutput = evaluateContext?.evaluationOutput ?? {};
|
|
3416
|
-
const scope = {
|
|
3417
|
-
claim: {
|
|
3418
|
-
claimId: claim?.claimId || evaluationOutput.claimId || "",
|
|
3419
|
-
agentDid: claim?.agentDid || "",
|
|
3420
|
-
agentAddress: claim?.agentAddress || "",
|
|
3421
|
-
submissionDate: claim?.submissionDate || "",
|
|
3422
|
-
surveyAnswers,
|
|
3423
|
-
...surveyAnswers
|
|
3424
|
-
},
|
|
3425
|
-
evaluation: {
|
|
3426
|
-
transactionHash: evaluationOutput.transactionHash || "",
|
|
3427
|
-
amount: evaluationOutput.amount || "",
|
|
3428
|
-
date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
|
|
3429
|
-
}
|
|
3430
|
-
};
|
|
3431
|
-
const trimmedId = String(evaluateBlockId || "").trim();
|
|
3432
|
-
if (trimmedId) {
|
|
3433
|
-
scope[trimmedId] = {
|
|
3434
|
-
output: {
|
|
3435
|
-
claimId: claim?.claimId || evaluationOutput.claimId || "",
|
|
3436
|
-
collectionId: evaluateContext?.collectionId || "",
|
|
3437
|
-
deedDid: evaluateContext?.deedDid || "",
|
|
3438
|
-
surveyAnswers,
|
|
3439
|
-
...evaluationOutput
|
|
3440
|
-
}
|
|
3441
|
-
};
|
|
3442
|
-
}
|
|
3443
|
-
return scope;
|
|
3444
|
-
}
|
|
3445
|
-
function resolveIterativeSource(source, editorDocument, opts) {
|
|
3446
|
-
const refs = parseReferences(source || "");
|
|
3447
|
-
if (refs.length === 0) return [];
|
|
3448
|
-
const ref = refs[0];
|
|
3449
|
-
const value = resolveSingleReference(ref.blockId, ref.propPath, editorDocument, opts.yRuntime, opts.scope);
|
|
3450
|
-
return Array.isArray(value) ? value : [];
|
|
3451
|
-
}
|
|
3452
|
-
function resolveCells(cells, editorDocument, opts) {
|
|
3453
|
-
const out = {};
|
|
3454
|
-
for (const key of LINE_ITEM_FIELD_KEYS) {
|
|
3455
|
-
out[key] = resolveReferences(cells[key] || "", editorDocument, opts);
|
|
3456
|
-
}
|
|
3457
|
-
return out;
|
|
3458
|
-
}
|
|
3459
|
-
function buildLineItemsArray(config, editorDocument, opts) {
|
|
3460
|
-
if (config.mode === "manual") {
|
|
3461
|
-
if (config.rows.length === 0) throw new Error("At least one line item is required.");
|
|
3462
|
-
return config.rows.map((row) => finaliseLineItem(resolveCells(row, editorDocument, opts)));
|
|
3463
|
-
}
|
|
3464
|
-
const elements = resolveIterativeSource(config.source, editorDocument, opts);
|
|
3465
|
-
if (elements.length === 0) throw new Error("The bound source list is empty or could not be resolved.");
|
|
3466
|
-
return elements.map((element) => {
|
|
3467
|
-
const perItemOpts = { ...opts, scope: { ...opts.scope || {}, item: element } };
|
|
3468
|
-
return finaliseLineItem(resolveCells(config.map, editorDocument, perItemOpts));
|
|
3469
|
-
});
|
|
3470
|
-
}
|
|
3471
|
-
async function resolveInvoiceWorkPayload(block, editorDocument, scope) {
|
|
3472
|
-
const parsed = parseXeroInvoiceCreateInputs(block?.props?.inputs);
|
|
3473
|
-
const opts = { scope };
|
|
3474
|
-
const resolveStr = (v) => resolveReferences(v || "", editorDocument, opts);
|
|
3475
|
-
const payload = {
|
|
3476
|
-
connection: parsed.connection,
|
|
3477
|
-
tenant_id: resolveStr(parsed.tenant_id),
|
|
3478
|
-
Type: resolveStr(parsed.Type) || "ACCREC",
|
|
3479
|
-
Status: resolveStr(parsed.Status) || "DRAFT",
|
|
3480
|
-
Date: resolveStr(parsed.Date),
|
|
3481
|
-
DueDate: resolveStr(parsed.DueDate),
|
|
3482
|
-
ContactID: resolveStr(parsed.ContactID),
|
|
3483
|
-
ContactName: resolveStr(parsed.ContactName),
|
|
3484
|
-
Reference: resolveStr(parsed.Reference),
|
|
3485
|
-
InvoiceNumber: resolveStr(parsed.InvoiceNumber),
|
|
3486
|
-
CurrencyCode: resolveStr(parsed.CurrencyCode),
|
|
3487
|
-
LineItems: buildLineItemsArray(parsed.LineItems, editorDocument, opts)
|
|
3488
|
-
};
|
|
3489
|
-
let preview = [];
|
|
3490
|
-
const resolver = getDiffResolver("qi/xero.invoice.create");
|
|
3491
|
-
if (resolver) {
|
|
3492
|
-
try {
|
|
3493
|
-
preview = await resolver.resolver({ ...payload, LineItems: parsed.LineItems }, {});
|
|
3494
|
-
} catch {
|
|
3495
|
-
preview = [];
|
|
3496
|
-
}
|
|
3497
|
-
}
|
|
3498
|
-
return { payload, preview };
|
|
3499
|
-
}
|
|
3500
|
-
async function resolvePaymentWorkPayload(block, editorDocument, baseScope, settlement) {
|
|
3501
|
-
const parsed = parseXeroPaymentCreateInputs(block?.props?.inputs);
|
|
3502
|
-
const scope = {
|
|
3503
|
-
...baseScope,
|
|
3504
|
-
invoice: { invoiceId: settlement.invoiceId, InvoiceID: settlement.invoiceId },
|
|
3505
|
-
evaluation: {
|
|
3506
|
-
transactionHash: settlement.transactionHash,
|
|
3507
|
-
amount: settlement.amount,
|
|
3508
|
-
date: settlement.date || (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
|
|
3063
|
+
if (!surveyAnswers || typeof surveyAnswers !== "object" || Array.isArray(surveyAnswers)) {
|
|
3064
|
+
throw new Error("surveyAnswers must be an object");
|
|
3509
3065
|
}
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3066
|
+
let pin = String(inputs.pin || "").trim();
|
|
3067
|
+
if (!pin) {
|
|
3068
|
+
pin = await service.requestPin({
|
|
3069
|
+
title: "Verify Identity",
|
|
3070
|
+
description: "Enter your PIN to submit the claim",
|
|
3071
|
+
submitText: "Verify"
|
|
3072
|
+
});
|
|
3073
|
+
}
|
|
3074
|
+
if (!pin) {
|
|
3075
|
+
throw new Error("PIN is required to submit claim");
|
|
3076
|
+
}
|
|
3077
|
+
if (isGroupExecution(inputs)) {
|
|
3078
|
+
const { coreAddress, title, description } = requireGroupExecutionParams(inputs);
|
|
3079
|
+
const handlers = ctx.handlers;
|
|
3080
|
+
if (typeof handlers?.prepareGroupClaimSubmission !== "function") {
|
|
3081
|
+
throw new Error("Acting as a POD is not available: the host does not implement prepareGroupClaimSubmission");
|
|
3082
|
+
}
|
|
3083
|
+
const prepared = await handlers.prepareGroupClaimSubmission({
|
|
3084
|
+
surveyData: surveyAnswers,
|
|
3085
|
+
deedDid,
|
|
3086
|
+
entityDid: deedDid,
|
|
3087
|
+
collectionId,
|
|
3088
|
+
adminAddress,
|
|
3089
|
+
pin,
|
|
3090
|
+
groupAddress: coreAddress
|
|
3091
|
+
});
|
|
3092
|
+
const claimId2 = String(prepared?.claimId || "").trim();
|
|
3093
|
+
if (!claimId2) throw new Error("prepareGroupClaimSubmission returned no claim identifier");
|
|
3094
|
+
return proposeGroupExecution(ctx, {
|
|
3095
|
+
coreAddress,
|
|
3096
|
+
title,
|
|
3097
|
+
description,
|
|
3098
|
+
msgs: prepared.msgs || [],
|
|
3099
|
+
expectedOutput: {
|
|
3100
|
+
claimId: claimId2,
|
|
3101
|
+
transactionHash: "",
|
|
3102
|
+
collectionId,
|
|
3103
|
+
deedDid,
|
|
3104
|
+
submittedByDid: coreAddress,
|
|
3105
|
+
submittedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3106
|
+
surveyAnswers
|
|
3107
|
+
},
|
|
3108
|
+
completionEvent: "submitted"
|
|
3109
|
+
});
|
|
3110
|
+
}
|
|
3111
|
+
const result = await service.submitClaim({
|
|
3112
|
+
surveyData: surveyAnswers,
|
|
3113
|
+
deedDid,
|
|
3114
|
+
entityDid: deedDid,
|
|
3115
|
+
collectionId,
|
|
3116
|
+
adminAddress,
|
|
3117
|
+
pin
|
|
3118
|
+
});
|
|
3119
|
+
const claimId = String(result?.claimId || result?.id || "");
|
|
3120
|
+
if (!claimId) {
|
|
3121
|
+
throw new Error("submitClaim returned no claim identifier");
|
|
3534
3122
|
}
|
|
3123
|
+
const transactionHash = String(result?.transactionHash || "");
|
|
3124
|
+
const submittedByDid = ctx.actorDid || "";
|
|
3125
|
+
const submittedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
3126
|
+
const output = {
|
|
3127
|
+
claimId,
|
|
3128
|
+
transactionHash,
|
|
3129
|
+
collectionId,
|
|
3130
|
+
deedDid,
|
|
3131
|
+
submittedByDid,
|
|
3132
|
+
submittedAt,
|
|
3133
|
+
surveyAnswers
|
|
3134
|
+
};
|
|
3135
|
+
return {
|
|
3136
|
+
output,
|
|
3137
|
+
events: [
|
|
3138
|
+
{
|
|
3139
|
+
name: "submitted",
|
|
3140
|
+
payload: output
|
|
3141
|
+
}
|
|
3142
|
+
]
|
|
3143
|
+
};
|
|
3535
3144
|
}
|
|
3536
|
-
|
|
3537
|
-
}
|
|
3538
|
-
function getInvoiceTotal(output) {
|
|
3539
|
-
const total = typeof output.total === "number" ? output.total : Number(output.total);
|
|
3540
|
-
return Number.isFinite(total) && total > 0 ? total : 0;
|
|
3541
|
-
}
|
|
3145
|
+
});
|
|
3542
3146
|
|
|
3543
3147
|
// src/core/lib/actionRegistry/actions/evaluateClaim/evaluateClaim.ts
|
|
3544
3148
|
var BASELINE_OUTPUT2 = [
|
|
@@ -3583,6 +3187,27 @@ function isEvaluatorRole(role) {
|
|
|
3583
3187
|
const normalized = String(role || "").trim().toLowerCase();
|
|
3584
3188
|
return normalized === "ea" || normalized === "evaluation_agent";
|
|
3585
3189
|
}
|
|
3190
|
+
function isTruthyFlag(value) {
|
|
3191
|
+
if (value === true) return true;
|
|
3192
|
+
if (typeof value === "number") return value === 1;
|
|
3193
|
+
if (typeof value === "string") {
|
|
3194
|
+
const normalized = value.trim().toLowerCase();
|
|
3195
|
+
return normalized === "true" || normalized === "1" || normalized === "yes" || normalized === "on";
|
|
3196
|
+
}
|
|
3197
|
+
return false;
|
|
3198
|
+
}
|
|
3199
|
+
var XERO_INVOICE_DEFAULT_KEYS = ["Type", "Status", "CurrencyCode", "tenant_id", "ContactID", "ContactName"];
|
|
3200
|
+
function buildXeroInvoiceDefaults(raw) {
|
|
3201
|
+
const source = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
3202
|
+
const defaults = {};
|
|
3203
|
+
for (const key of XERO_INVOICE_DEFAULT_KEYS) {
|
|
3204
|
+
const value = String(source[key] ?? "").trim();
|
|
3205
|
+
if (value) defaults[key] = value;
|
|
3206
|
+
}
|
|
3207
|
+
if (!defaults.Type) defaults.Type = "ACCREC";
|
|
3208
|
+
if (!defaults.Status) defaults.Status = "DRAFT";
|
|
3209
|
+
return defaults;
|
|
3210
|
+
}
|
|
3586
3211
|
registerAction({
|
|
3587
3212
|
type: "qi/claim.evaluate",
|
|
3588
3213
|
can: "claim/evaluate",
|
|
@@ -3671,9 +3296,12 @@ registerAction({
|
|
|
3671
3296
|
traceCid: { type: "string", description: "Trace CID passed through to the UDID." },
|
|
3672
3297
|
items: { type: "array", description: "Evaluation items passed through to the UDID." },
|
|
3673
3298
|
patch: { type: "object", description: "Patch object passed through to the UDID." },
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3299
|
+
xeroOracleInvoiceOnApprove: { type: "boolean", description: "Create a Xero draft invoice via the contracted xero-oracle when a claim is approved." },
|
|
3300
|
+
xeroInvoiceDefaults: {
|
|
3301
|
+
type: "object",
|
|
3302
|
+
description: "Optional template-level Xero invoice defaults (Type, Status, CurrencyCode, tenant_id, ContactID, ContactName) pinned into the invoice work payload."
|
|
3303
|
+
},
|
|
3304
|
+
claimSnapshot: { type: "object", description: "Claim snapshot used to build the Xero invoice work payload." }
|
|
3677
3305
|
}
|
|
3678
3306
|
},
|
|
3679
3307
|
run: async (inputs, ctx) => {
|
|
@@ -3855,36 +3483,30 @@ registerAction({
|
|
|
3855
3483
|
evaluatedAt,
|
|
3856
3484
|
surveyAnswers
|
|
3857
3485
|
};
|
|
3858
|
-
|
|
3859
|
-
if (decision === "approve" && xeroInvoiceBlockId) {
|
|
3860
|
-
const editorDoc = ctx.editor?.document || [];
|
|
3861
|
-
const runtime = ctx.runtime;
|
|
3862
|
-
if (!runtime) {
|
|
3863
|
-
throw new Error("Cannot queue Xero invoice work: runtime state manager is unavailable");
|
|
3864
|
-
}
|
|
3865
|
-
const bindings = resolveXeroBindings(editorDoc, xeroInvoiceBlockId, String(inputs.xeroPaymentBlockId || ""));
|
|
3866
|
-
const invoiceBlock = bindings.invoiceCreateBlock;
|
|
3867
|
-
if (!invoiceBlock) {
|
|
3868
|
-
throw new Error("Cannot queue Xero invoice work: bound invoice block was not found");
|
|
3869
|
-
}
|
|
3486
|
+
if (decision === "approve" && isTruthyFlag(inputs.xeroOracleInvoiceOnApprove)) {
|
|
3870
3487
|
const flowId = String(ctx.flowId || ctx.flowUri || "flow");
|
|
3871
|
-
const
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3488
|
+
const claimSnapshot = inputs.claimSnapshot && typeof inputs.claimSnapshot === "object" && !Array.isArray(inputs.claimSnapshot) ? inputs.claimSnapshot : void 0;
|
|
3489
|
+
const surveyQuestions = Array.isArray(claimSnapshot?.surveyQuestions) ? claimSnapshot.surveyQuestions : Array.isArray(inputs?.surveyAnswersSchema) ? inputs.surveyAnswersSchema : [];
|
|
3490
|
+
const idempotencyKey = buildXeroInvoiceWorkKey({ flowId, evaluationBlockId: ctx.nodeId, claimId });
|
|
3491
|
+
const originalPayload = {
|
|
3492
|
+
claim: { claimId, collectionId, deedDid },
|
|
3493
|
+
surveyQuestions,
|
|
3494
|
+
surveyAnswers,
|
|
3495
|
+
evaluation: {
|
|
3496
|
+
decision,
|
|
3497
|
+
amount: normalizedCoin,
|
|
3498
|
+
evaluatedByDid,
|
|
3499
|
+
evaluatedAt,
|
|
3500
|
+
verificationProof,
|
|
3501
|
+
transactionHash
|
|
3502
|
+
},
|
|
3503
|
+
invoiceDefaults: buildXeroInvoiceDefaults(inputs.xeroInvoiceDefaults)
|
|
3504
|
+
};
|
|
3883
3505
|
upsertXeroWorkItemForEditor(ctx.editor, {
|
|
3884
3506
|
id: idempotencyKey,
|
|
3885
3507
|
kind: "invoice.create",
|
|
3886
3508
|
status: "pending",
|
|
3887
|
-
assignedBlockId:
|
|
3509
|
+
assignedBlockId: ctx.nodeId,
|
|
3888
3510
|
idempotencyKey,
|
|
3889
3511
|
source: {
|
|
3890
3512
|
claimId,
|
|
@@ -3892,15 +3514,14 @@ registerAction({
|
|
|
3892
3514
|
deedDid,
|
|
3893
3515
|
collectionId
|
|
3894
3516
|
},
|
|
3895
|
-
originalPayload
|
|
3896
|
-
reviewPayload:
|
|
3517
|
+
originalPayload,
|
|
3518
|
+
reviewPayload: originalPayload,
|
|
3897
3519
|
provenance: {
|
|
3898
3520
|
createdAt: Date.now(),
|
|
3899
3521
|
createdByDid: ctx.actorDid,
|
|
3900
|
-
templateBlockId:
|
|
3901
|
-
templateInputsSnapshot: invoiceBlock.props?.inputs,
|
|
3522
|
+
templateBlockId: ctx.nodeId,
|
|
3902
3523
|
evaluationOutput: output,
|
|
3903
|
-
claimSnapshot
|
|
3524
|
+
claimSnapshot
|
|
3904
3525
|
},
|
|
3905
3526
|
attempts: []
|
|
3906
3527
|
});
|
|
@@ -10614,6 +10235,127 @@ function isRuntimeRef(value) {
|
|
|
10614
10235
|
|
|
10615
10236
|
// src/core/lib/flowEngine/triggers.ts
|
|
10616
10237
|
import * as Y from "yjs";
|
|
10238
|
+
|
|
10239
|
+
// src/core/lib/flowEngine/referenceResolver.ts
|
|
10240
|
+
var REFERENCE_REGEX = /\{\{([a-zA-Z0-9_-]+)\.([a-zA-Z0-9_.:]+)\}\}/g;
|
|
10241
|
+
function parseReferences(input) {
|
|
10242
|
+
const references = [];
|
|
10243
|
+
const regex = new RegExp(REFERENCE_REGEX);
|
|
10244
|
+
let match;
|
|
10245
|
+
while ((match = regex.exec(input)) !== null) {
|
|
10246
|
+
references.push({
|
|
10247
|
+
fullMatch: match[0],
|
|
10248
|
+
blockId: match[1],
|
|
10249
|
+
propPath: match[2],
|
|
10250
|
+
startIndex: match.index,
|
|
10251
|
+
endIndex: match.index + match[0].length
|
|
10252
|
+
});
|
|
10253
|
+
}
|
|
10254
|
+
return references;
|
|
10255
|
+
}
|
|
10256
|
+
function getNestedValue(obj, path) {
|
|
10257
|
+
return path.split(".").reduce((current, key) => {
|
|
10258
|
+
return current?.[key];
|
|
10259
|
+
}, obj);
|
|
10260
|
+
}
|
|
10261
|
+
function resolveSingleReferenceDetailed(blockId, propPath, editorDocument, yRuntime, scope) {
|
|
10262
|
+
if (scope && Object.prototype.hasOwnProperty.call(scope, blockId)) {
|
|
10263
|
+
const root = scope[blockId];
|
|
10264
|
+
if (root == null) return { value: void 0, reason: "missing-value" };
|
|
10265
|
+
const value2 = getNestedValue(root, propPath);
|
|
10266
|
+
return { value: value2, reason: value2 === void 0 ? "missing-value" : void 0 };
|
|
10267
|
+
}
|
|
10268
|
+
if (!editorDocument || !Array.isArray(editorDocument)) {
|
|
10269
|
+
return { value: void 0, reason: "unknown-block" };
|
|
10270
|
+
}
|
|
10271
|
+
const block = editorDocument.find((b) => b.id === blockId);
|
|
10272
|
+
if (!block) {
|
|
10273
|
+
return { value: void 0, reason: "unknown-block" };
|
|
10274
|
+
}
|
|
10275
|
+
if (propPath.startsWith("output.")) {
|
|
10276
|
+
if (!yRuntime) return { value: void 0, reason: "missing-value" };
|
|
10277
|
+
const runtimeState = yRuntime.get(blockId);
|
|
10278
|
+
if (!runtimeState?.output) return { value: void 0, reason: "missing-value" };
|
|
10279
|
+
const innerPath = propPath.substring("output.".length);
|
|
10280
|
+
const direct = getNestedValue(runtimeState.output, innerPath);
|
|
10281
|
+
if (direct !== void 0) return { value: direct };
|
|
10282
|
+
if (runtimeState.output.data !== void 0) {
|
|
10283
|
+
const value2 = getNestedValue(runtimeState.output.data, innerPath);
|
|
10284
|
+
return { value: value2, reason: value2 === void 0 ? "missing-value" : void 0 };
|
|
10285
|
+
}
|
|
10286
|
+
if (runtimeState.output.http?.data !== void 0) {
|
|
10287
|
+
const value2 = getNestedValue(runtimeState.output.http.data, innerPath);
|
|
10288
|
+
return { value: value2, reason: value2 === void 0 ? "missing-value" : void 0 };
|
|
10289
|
+
}
|
|
10290
|
+
return { value: void 0, reason: "missing-value" };
|
|
10291
|
+
}
|
|
10292
|
+
if (propPath.startsWith("response.")) {
|
|
10293
|
+
const responseData = block.props.response;
|
|
10294
|
+
if (!responseData) {
|
|
10295
|
+
return { value: void 0, reason: "missing-value" };
|
|
10296
|
+
}
|
|
10297
|
+
try {
|
|
10298
|
+
const parsedResponse = typeof responseData === "string" ? JSON.parse(responseData) : responseData;
|
|
10299
|
+
const innerPath = propPath.substring("response.".length);
|
|
10300
|
+
const value2 = getNestedValue(parsedResponse, innerPath);
|
|
10301
|
+
return { value: value2, reason: value2 === void 0 ? "missing-value" : void 0 };
|
|
10302
|
+
} catch {
|
|
10303
|
+
warnOnce(`ref-response-parse:${blockId}`, `[flow-config] block ${blockId}: props.response is not valid JSON; {{${blockId}.${propPath}}} cannot resolve`);
|
|
10304
|
+
return { value: void 0, reason: "response-parse-error" };
|
|
10305
|
+
}
|
|
10306
|
+
}
|
|
10307
|
+
const value = getNestedValue(block.props, propPath);
|
|
10308
|
+
return { value, reason: value === void 0 ? "missing-value" : void 0 };
|
|
10309
|
+
}
|
|
10310
|
+
function resolveSingleReference(blockId, propPath, editorDocument, yRuntime, scope) {
|
|
10311
|
+
return resolveSingleReferenceDetailed(blockId, propPath, editorDocument, yRuntime, scope).value;
|
|
10312
|
+
}
|
|
10313
|
+
function resolveReferencesDetailed(input, editorDocument, options = {}) {
|
|
10314
|
+
const { fallback = "", stringifyObjects = true, yRuntime, scope, warnContext } = options;
|
|
10315
|
+
const unresolved = [];
|
|
10316
|
+
if (input == null) {
|
|
10317
|
+
return { value: "", unresolved };
|
|
10318
|
+
}
|
|
10319
|
+
const inputStr = String(input);
|
|
10320
|
+
const references = parseReferences(inputStr);
|
|
10321
|
+
if (references.length === 0) {
|
|
10322
|
+
return { value: inputStr, unresolved };
|
|
10323
|
+
}
|
|
10324
|
+
let result = inputStr;
|
|
10325
|
+
for (let i = references.length - 1; i >= 0; i--) {
|
|
10326
|
+
const ref = references[i];
|
|
10327
|
+
const resolution = resolveSingleReferenceDetailed(ref.blockId, ref.propPath, editorDocument, yRuntime, scope);
|
|
10328
|
+
const resolvedValue = resolution.value;
|
|
10329
|
+
let replacementStr;
|
|
10330
|
+
if (resolvedValue === void 0 || resolvedValue === null) {
|
|
10331
|
+
replacementStr = fallback;
|
|
10332
|
+
unresolved.push({ ref: ref.fullMatch, blockId: ref.blockId, propPath: ref.propPath, reason: resolution.reason || "missing-value" });
|
|
10333
|
+
} else if (typeof resolvedValue === "object") {
|
|
10334
|
+
replacementStr = stringifyObjects ? JSON.stringify(resolvedValue) : fallback;
|
|
10335
|
+
} else {
|
|
10336
|
+
replacementStr = String(resolvedValue);
|
|
10337
|
+
}
|
|
10338
|
+
result = result.substring(0, ref.startIndex) + replacementStr + result.substring(ref.endIndex);
|
|
10339
|
+
}
|
|
10340
|
+
if (warnContext && unresolved.length > 0) {
|
|
10341
|
+
for (const entry of unresolved) {
|
|
10342
|
+
warnOnce(`ref-unresolved:${warnContext}:${entry.ref}`, `[flow-config] ${warnContext}: reference ${entry.ref} did not resolve (${entry.reason}); using fallback '${fallback}'`);
|
|
10343
|
+
}
|
|
10344
|
+
}
|
|
10345
|
+
return { value: result, unresolved };
|
|
10346
|
+
}
|
|
10347
|
+
function resolveReferences(input, editorDocument, options = {}) {
|
|
10348
|
+
return resolveReferencesDetailed(input, editorDocument, options).value;
|
|
10349
|
+
}
|
|
10350
|
+
function hasReferences(input) {
|
|
10351
|
+
if (input == null) return false;
|
|
10352
|
+
return parseReferences(String(input)).length > 0;
|
|
10353
|
+
}
|
|
10354
|
+
function createReference(blockId, propPath) {
|
|
10355
|
+
return `{{${blockId}.${propPath}}}`;
|
|
10356
|
+
}
|
|
10357
|
+
|
|
10358
|
+
// src/core/lib/flowEngine/triggers.ts
|
|
10617
10359
|
var RUN_RECORD_AUDIT_TYPE = "block.run";
|
|
10618
10360
|
function computePendingInvocationId(args) {
|
|
10619
10361
|
const { sourceBlockId, sourceRunId, listenerBlockId, eventName, eventIndex } = args;
|
|
@@ -11239,7 +10981,7 @@ var buildFlowNodeFromBlock = (block) => {
|
|
|
11239
10981
|
};
|
|
11240
10982
|
|
|
11241
10983
|
// src/core/lib/flowEngine/runtime.ts
|
|
11242
|
-
var
|
|
10984
|
+
var XERO_WORK_ITEMS_MAP_NAME2 = "xeroWorkItems";
|
|
11243
10985
|
var XERO_CONNECTION_MAP_NAME = "xeroConnection";
|
|
11244
10986
|
var ensureStateObject = (value) => {
|
|
11245
10987
|
if (!value || typeof value !== "object") {
|
|
@@ -11285,7 +11027,7 @@ function clearRuntimeForTemplateClone(yDoc) {
|
|
|
11285
11027
|
const agentOutbox = yDoc.getMap("agentOutbox");
|
|
11286
11028
|
const agentLeases = yDoc.getMap("agentLeases");
|
|
11287
11029
|
const auditTrail = yDoc.getMap("auditTrail");
|
|
11288
|
-
const xeroWorkItems = yDoc.getMap(
|
|
11030
|
+
const xeroWorkItems = yDoc.getMap(XERO_WORK_ITEMS_MAP_NAME2);
|
|
11289
11031
|
const xeroConnection = yDoc.getMap(XERO_CONNECTION_MAP_NAME);
|
|
11290
11032
|
yDoc.transact(() => {
|
|
11291
11033
|
runtime.forEach((_, key) => runtime.delete(key));
|
|
@@ -15071,29 +14813,20 @@ export {
|
|
|
15071
14813
|
hasDiffResolver,
|
|
15072
14814
|
extractDid,
|
|
15073
14815
|
extractSurveyAnswerSchema,
|
|
14816
|
+
XERO_WORK_ITEMS_MAP_NAME,
|
|
14817
|
+
getXeroWorkItemsMap,
|
|
14818
|
+
buildXeroInvoiceWorkKey,
|
|
15074
14819
|
buildXeroPaymentWorkKey,
|
|
14820
|
+
findXeroWorkItems,
|
|
14821
|
+
upsertXeroWorkItem,
|
|
14822
|
+
updateXeroWorkReviewPayload,
|
|
14823
|
+
markXeroWorkFailed,
|
|
14824
|
+
markXeroWorkCompleted,
|
|
15075
14825
|
findXeroWorkItemsForEditor,
|
|
15076
14826
|
upsertXeroWorkItemForEditor,
|
|
15077
14827
|
updateXeroWorkReviewPayloadForEditor,
|
|
15078
14828
|
markXeroWorkFailedForEditor,
|
|
15079
14829
|
markXeroWorkCompletedForEditor,
|
|
15080
|
-
LINE_ITEM_FIELD_KEYS,
|
|
15081
|
-
emptyLineItemCells,
|
|
15082
|
-
parseXeroInvoiceCreateInputs,
|
|
15083
|
-
serializeXeroInvoiceCreateInputs,
|
|
15084
|
-
finaliseLineItem,
|
|
15085
|
-
parseXeroPaymentCreateInputs,
|
|
15086
|
-
serializeXeroPaymentCreateInputs,
|
|
15087
|
-
parseReferences,
|
|
15088
|
-
resolveSingleReference,
|
|
15089
|
-
resolveReferencesDetailed,
|
|
15090
|
-
resolveReferences,
|
|
15091
|
-
hasReferences,
|
|
15092
|
-
createReference,
|
|
15093
|
-
resolveXeroBindings,
|
|
15094
|
-
buildClaimScope,
|
|
15095
|
-
resolvePaymentWorkPayload,
|
|
15096
|
-
getInvoiceTotal,
|
|
15097
14830
|
transformSurveyToCredentialSubject,
|
|
15098
14831
|
buildVerifiableCredential,
|
|
15099
14832
|
buildDomainCardLinkedResource,
|
|
@@ -15124,6 +14857,12 @@ export {
|
|
|
15124
14857
|
formatCoinAmount,
|
|
15125
14858
|
createUcanService,
|
|
15126
14859
|
isRuntimeRef,
|
|
14860
|
+
parseReferences,
|
|
14861
|
+
resolveSingleReference,
|
|
14862
|
+
resolveReferencesDetailed,
|
|
14863
|
+
resolveReferences,
|
|
14864
|
+
hasReferences,
|
|
14865
|
+
createReference,
|
|
15127
14866
|
RUN_RECORD_AUDIT_TYPE,
|
|
15128
14867
|
computePendingInvocationId,
|
|
15129
14868
|
snapshotInputRefs,
|
|
@@ -15218,4 +14957,4 @@ export {
|
|
|
15218
14957
|
executeQueuedFlowAgentCoreCommands,
|
|
15219
14958
|
FlowAgentService
|
|
15220
14959
|
};
|
|
15221
|
-
//# sourceMappingURL=chunk-
|
|
14960
|
+
//# sourceMappingURL=chunk-ABM3ZZIX.js.map
|