whale-code 6.5.7 → 6.5.9
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 +14 -2
- package/dist/cli/services/agent-loop.js +26 -2
- package/dist/cli/services/agent-loop.js.map +1 -1
- package/dist/cli/services/hooks.js +2 -1
- package/dist/cli/services/hooks.js.map +1 -1
- package/dist/cli/services/telemetry-spans.js +1 -0
- package/dist/cli/services/telemetry-spans.js.map +1 -1
- package/dist/cli/services/telemetry.d.ts +23 -0
- package/dist/cli/services/telemetry.js +45 -1
- package/dist/cli/services/telemetry.js.map +1 -1
- package/dist/server/handlers/__test-utils__/test-db.d.ts +17 -3
- package/dist/server/handlers/__test-utils__/test-db.js +113 -14
- package/dist/server/handlers/__test-utils__/test-db.js.map +1 -1
- package/dist/server/handlers/affiliates.d.ts +9 -0
- package/dist/server/handlers/affiliates.js +197 -0
- package/dist/server/handlers/affiliates.js.map +1 -0
- package/dist/server/handlers/api-docs.d.ts +4 -2
- package/dist/server/handlers/api-docs.js +204 -1681
- package/dist/server/handlers/api-docs.js.map +1 -1
- package/dist/server/handlers/campaigns.d.ts +9 -0
- package/dist/server/handlers/campaigns.js +237 -0
- package/dist/server/handlers/campaigns.js.map +1 -0
- package/dist/server/handlers/catalog-schemas.js +9 -9
- package/dist/server/handlers/catalog-schemas.js.map +1 -1
- package/dist/server/handlers/catalog.js +1 -1
- package/dist/server/handlers/catalog.js.map +1 -1
- package/dist/server/handlers/comms-documents.js +28 -2
- package/dist/server/handlers/comms-documents.js.map +1 -1
- package/dist/server/handlers/comms-pdf-generation.js +25 -3
- package/dist/server/handlers/comms-pdf-generation.js.map +1 -1
- package/dist/server/handlers/comms-pdf-helpers.js +4 -4
- package/dist/server/handlers/comms-pdf-helpers.js.map +1 -1
- package/dist/server/handlers/comms.d.ts +100 -0
- package/dist/server/handlers/comms.js +146 -12
- package/dist/server/handlers/comms.js.map +1 -1
- package/dist/server/handlers/coupons.d.ts +9 -0
- package/dist/server/handlers/coupons.js +220 -0
- package/dist/server/handlers/coupons.js.map +1 -0
- package/dist/server/handlers/embeddings.js +1 -1
- package/dist/server/handlers/embeddings.js.map +1 -1
- package/dist/server/handlers/enrichment.js +2 -622
- package/dist/server/handlers/enrichment.js.map +1 -1
- package/dist/server/handlers/fulfillment.d.ts +9 -0
- package/dist/server/handlers/fulfillment.js +209 -0
- package/dist/server/handlers/fulfillment.js.map +1 -0
- package/dist/server/handlers/google-ads.d.ts +24 -0
- package/dist/server/handlers/google-ads.js +2199 -0
- package/dist/server/handlers/google-ads.js.map +1 -0
- package/dist/server/handlers/invoices.d.ts +9 -0
- package/dist/server/handlers/invoices.js +252 -0
- package/dist/server/handlers/invoices.js.map +1 -0
- package/dist/server/handlers/loyalty.d.ts +9 -0
- package/dist/server/handlers/loyalty.js +197 -0
- package/dist/server/handlers/loyalty.js.map +1 -0
- package/dist/server/handlers/meta-ads-graph-api.js +18 -3
- package/dist/server/handlers/meta-ads-graph-api.js.map +1 -1
- package/dist/server/handlers/phone.d.ts +9 -0
- package/dist/server/handlers/phone.js +197 -0
- package/dist/server/handlers/phone.js.map +1 -0
- package/dist/server/handlers/pipeline.d.ts +9 -0
- package/dist/server/handlers/pipeline.js +277 -0
- package/dist/server/handlers/pipeline.js.map +1 -0
- package/dist/server/handlers/qr-codes.d.ts +9 -0
- package/dist/server/handlers/qr-codes.js +198 -0
- package/dist/server/handlers/qr-codes.js.map +1 -0
- package/dist/server/handlers/reviews.d.ts +9 -0
- package/dist/server/handlers/reviews.js +171 -0
- package/dist/server/handlers/reviews.js.map +1 -0
- package/dist/server/handlers/segments.d.ts +9 -0
- package/dist/server/handlers/segments.js +229 -0
- package/dist/server/handlers/segments.js.map +1 -0
- package/dist/server/handlers/social.d.ts +9 -0
- package/dist/server/handlers/social.js +81 -0
- package/dist/server/handlers/social.js.map +1 -0
- package/dist/server/handlers/tax.d.ts +9 -0
- package/dist/server/handlers/tax.js +182 -0
- package/dist/server/handlers/tax.js.map +1 -0
- package/dist/server/handlers/wallet.d.ts +9 -0
- package/dist/server/handlers/wallet.js +203 -0
- package/dist/server/handlers/wallet.js.map +1 -0
- package/dist/server/handlers/webhooks-mgmt.d.ts +9 -0
- package/dist/server/handlers/webhooks-mgmt.js +181 -0
- package/dist/server/handlers/webhooks-mgmt.js.map +1 -0
- package/dist/server/handlers/wholesale.d.ts +9 -0
- package/dist/server/handlers/wholesale.js +219 -0
- package/dist/server/handlers/wholesale.js.map +1 -0
- package/dist/server/index.js +20 -9
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/clickhouse-buffer.js +1 -0
- package/dist/server/lib/clickhouse-buffer.js.map +1 -1
- package/dist/server/lib/coa-renderer.d.ts +1 -1
- package/dist/server/lib/coa-renderer.js +32 -10
- package/dist/server/lib/coa-renderer.js.map +1 -1
- package/dist/server/server-worker.d.ts +1 -0
- package/dist/server/server-worker.js +464 -3
- package/dist/server/server-worker.js.map +1 -1
- package/dist/server/tool-router.js +118 -4
- package/dist/server/tool-router.js.map +1 -1
- package/package.json +28 -4
- package/vendor/ink/package.json +0 -2
- package/whale-logo.png +0 -0
|
@@ -35,6 +35,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
35
35
|
results?: undefined;
|
|
36
36
|
errors?: undefined;
|
|
37
37
|
warnings?: undefined;
|
|
38
|
+
clients?: undefined;
|
|
39
|
+
hint?: undefined;
|
|
38
40
|
document_ids?: undefined;
|
|
39
41
|
customer_id?: undefined;
|
|
40
42
|
customer_email?: undefined;
|
|
@@ -72,6 +74,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
72
74
|
results?: undefined;
|
|
73
75
|
errors?: undefined;
|
|
74
76
|
warnings?: undefined;
|
|
77
|
+
clients?: undefined;
|
|
78
|
+
hint?: undefined;
|
|
75
79
|
document_ids?: undefined;
|
|
76
80
|
customer_id?: undefined;
|
|
77
81
|
customer_email?: undefined;
|
|
@@ -101,6 +105,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
101
105
|
results?: undefined;
|
|
102
106
|
errors?: undefined;
|
|
103
107
|
warnings?: undefined;
|
|
108
|
+
clients?: undefined;
|
|
109
|
+
hint?: undefined;
|
|
104
110
|
document_ids?: undefined;
|
|
105
111
|
customer_id?: undefined;
|
|
106
112
|
customer_email?: undefined;
|
|
@@ -130,6 +136,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
130
136
|
results?: undefined;
|
|
131
137
|
errors?: undefined;
|
|
132
138
|
warnings?: undefined;
|
|
139
|
+
clients?: undefined;
|
|
140
|
+
hint?: undefined;
|
|
133
141
|
document_ids?: undefined;
|
|
134
142
|
customer_id?: undefined;
|
|
135
143
|
customer_email?: undefined;
|
|
@@ -166,6 +174,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
166
174
|
results?: undefined;
|
|
167
175
|
errors?: undefined;
|
|
168
176
|
warnings?: undefined;
|
|
177
|
+
clients?: undefined;
|
|
178
|
+
hint?: undefined;
|
|
169
179
|
document_ids?: undefined;
|
|
170
180
|
customer_id?: undefined;
|
|
171
181
|
customer_email?: undefined;
|
|
@@ -195,6 +205,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
195
205
|
results?: undefined;
|
|
196
206
|
errors?: undefined;
|
|
197
207
|
warnings?: undefined;
|
|
208
|
+
clients?: undefined;
|
|
209
|
+
hint?: undefined;
|
|
198
210
|
document_ids?: undefined;
|
|
199
211
|
customer_id?: undefined;
|
|
200
212
|
customer_email?: undefined;
|
|
@@ -230,6 +242,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
230
242
|
results?: undefined;
|
|
231
243
|
errors?: undefined;
|
|
232
244
|
warnings?: undefined;
|
|
245
|
+
clients?: undefined;
|
|
246
|
+
hint?: undefined;
|
|
233
247
|
document_ids?: undefined;
|
|
234
248
|
customer_id?: undefined;
|
|
235
249
|
customer_email?: undefined;
|
|
@@ -266,6 +280,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
266
280
|
results?: undefined;
|
|
267
281
|
errors?: undefined;
|
|
268
282
|
warnings?: undefined;
|
|
283
|
+
clients?: undefined;
|
|
284
|
+
hint?: undefined;
|
|
269
285
|
document_ids?: undefined;
|
|
270
286
|
customer_id?: undefined;
|
|
271
287
|
customer_email?: undefined;
|
|
@@ -299,6 +315,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
299
315
|
profiles?: undefined;
|
|
300
316
|
errors?: undefined;
|
|
301
317
|
warnings?: undefined;
|
|
318
|
+
clients?: undefined;
|
|
319
|
+
hint?: undefined;
|
|
302
320
|
document_ids?: undefined;
|
|
303
321
|
customer_id?: undefined;
|
|
304
322
|
customer_email?: undefined;
|
|
@@ -329,6 +347,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
329
347
|
succeeded?: undefined;
|
|
330
348
|
failed?: undefined;
|
|
331
349
|
results?: undefined;
|
|
350
|
+
clients?: undefined;
|
|
351
|
+
hint?: undefined;
|
|
332
352
|
document_ids?: undefined;
|
|
333
353
|
customer_id?: undefined;
|
|
334
354
|
customer_email?: undefined;
|
|
@@ -357,6 +377,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
357
377
|
failed?: undefined;
|
|
358
378
|
results?: undefined;
|
|
359
379
|
errors?: undefined;
|
|
380
|
+
clients?: undefined;
|
|
381
|
+
hint?: undefined;
|
|
360
382
|
document_ids?: undefined;
|
|
361
383
|
customer_id?: undefined;
|
|
362
384
|
customer_email?: undefined;
|
|
@@ -393,6 +415,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
393
415
|
results?: undefined;
|
|
394
416
|
errors?: undefined;
|
|
395
417
|
warnings?: undefined;
|
|
418
|
+
clients?: undefined;
|
|
419
|
+
hint?: undefined;
|
|
396
420
|
document_ids?: undefined;
|
|
397
421
|
customer_id?: undefined;
|
|
398
422
|
customer_email?: undefined;
|
|
@@ -429,6 +453,78 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
429
453
|
results?: undefined;
|
|
430
454
|
errors?: undefined;
|
|
431
455
|
warnings?: undefined;
|
|
456
|
+
clients?: undefined;
|
|
457
|
+
hint?: undefined;
|
|
458
|
+
document_ids?: undefined;
|
|
459
|
+
customer_id?: undefined;
|
|
460
|
+
customer_email?: undefined;
|
|
461
|
+
email_sent?: undefined;
|
|
462
|
+
};
|
|
463
|
+
error?: undefined;
|
|
464
|
+
} | {
|
|
465
|
+
success: boolean;
|
|
466
|
+
data: {
|
|
467
|
+
count: number;
|
|
468
|
+
clients: never[];
|
|
469
|
+
hint: string;
|
|
470
|
+
id?: undefined;
|
|
471
|
+
name?: undefined;
|
|
472
|
+
type?: undefined;
|
|
473
|
+
url?: undefined;
|
|
474
|
+
file_name?: undefined;
|
|
475
|
+
size?: undefined;
|
|
476
|
+
documents?: undefined;
|
|
477
|
+
deleted?: undefined;
|
|
478
|
+
template_id?: undefined;
|
|
479
|
+
templates?: undefined;
|
|
480
|
+
template?: undefined;
|
|
481
|
+
stores?: undefined;
|
|
482
|
+
profiles?: undefined;
|
|
483
|
+
total?: undefined;
|
|
484
|
+
succeeded?: undefined;
|
|
485
|
+
failed?: undefined;
|
|
486
|
+
results?: undefined;
|
|
487
|
+
errors?: undefined;
|
|
488
|
+
warnings?: undefined;
|
|
489
|
+
document_ids?: undefined;
|
|
490
|
+
customer_id?: undefined;
|
|
491
|
+
customer_email?: undefined;
|
|
492
|
+
email_sent?: undefined;
|
|
493
|
+
};
|
|
494
|
+
error?: undefined;
|
|
495
|
+
} | {
|
|
496
|
+
success: boolean;
|
|
497
|
+
data: {
|
|
498
|
+
count: number;
|
|
499
|
+
clients: {
|
|
500
|
+
id: any;
|
|
501
|
+
name: any;
|
|
502
|
+
store_name: any;
|
|
503
|
+
address: string;
|
|
504
|
+
license: any;
|
|
505
|
+
phone: any;
|
|
506
|
+
email: any;
|
|
507
|
+
}[];
|
|
508
|
+
id?: undefined;
|
|
509
|
+
name?: undefined;
|
|
510
|
+
type?: undefined;
|
|
511
|
+
url?: undefined;
|
|
512
|
+
file_name?: undefined;
|
|
513
|
+
size?: undefined;
|
|
514
|
+
documents?: undefined;
|
|
515
|
+
deleted?: undefined;
|
|
516
|
+
template_id?: undefined;
|
|
517
|
+
templates?: undefined;
|
|
518
|
+
template?: undefined;
|
|
519
|
+
stores?: undefined;
|
|
520
|
+
profiles?: undefined;
|
|
521
|
+
total?: undefined;
|
|
522
|
+
succeeded?: undefined;
|
|
523
|
+
failed?: undefined;
|
|
524
|
+
results?: undefined;
|
|
525
|
+
errors?: undefined;
|
|
526
|
+
warnings?: undefined;
|
|
527
|
+
hint?: undefined;
|
|
432
528
|
document_ids?: undefined;
|
|
433
529
|
customer_id?: undefined;
|
|
434
530
|
customer_email?: undefined;
|
|
@@ -462,6 +558,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
462
558
|
results?: undefined;
|
|
463
559
|
errors?: undefined;
|
|
464
560
|
warnings?: undefined;
|
|
561
|
+
clients?: undefined;
|
|
562
|
+
hint?: undefined;
|
|
465
563
|
};
|
|
466
564
|
error?: undefined;
|
|
467
565
|
} | {
|
|
@@ -496,6 +594,8 @@ export declare function handleDocuments(sb: SupabaseClient, args: Record<string,
|
|
|
496
594
|
results?: undefined;
|
|
497
595
|
errors?: undefined;
|
|
498
596
|
warnings?: undefined;
|
|
597
|
+
clients?: undefined;
|
|
598
|
+
hint?: undefined;
|
|
499
599
|
document_ids?: undefined;
|
|
500
600
|
customer_id?: undefined;
|
|
501
601
|
customer_email?: undefined;
|
|
@@ -1008,12 +1008,12 @@ export async function handleDocuments(sb, args, storeId) {
|
|
|
1008
1008
|
};
|
|
1009
1009
|
}
|
|
1010
1010
|
}
|
|
1011
|
-
//
|
|
1012
|
-
|
|
1013
|
-
profileClientData.sampleName = profile.name;
|
|
1014
|
-
}
|
|
1011
|
+
// Profile name is a category (e.g. "THCA Flower"), not a sample name.
|
|
1012
|
+
// sampleName must come from user data (productName or sampleName override).
|
|
1015
1013
|
if (profile.sample_type) {
|
|
1016
1014
|
profileClientData.sampleType = profile.sample_type;
|
|
1015
|
+
} else if (profile.name) {
|
|
1016
|
+
profileClientData.sampleType = profile.name;
|
|
1017
1017
|
}
|
|
1018
1018
|
if (profile.default_size) {
|
|
1019
1019
|
profileClientData.sampleSize = profile.default_size;
|
|
@@ -1054,15 +1054,32 @@ export async function handleDocuments(sb, args, storeId) {
|
|
|
1054
1054
|
cannabinoids: _cfgRanges,
|
|
1055
1055
|
...profileDataOnly
|
|
1056
1056
|
} = profileConfig;
|
|
1057
|
+
// Normalize common field name aliases to what the COA renderer expects
|
|
1058
|
+
const rawOverrides = args.data || {};
|
|
1059
|
+
const userOverrides = {
|
|
1060
|
+
...rawOverrides
|
|
1061
|
+
};
|
|
1062
|
+
if (userOverrides.productName && !userOverrides.sampleName) {
|
|
1063
|
+
userOverrides.sampleName = userOverrides.productName;
|
|
1064
|
+
}
|
|
1065
|
+
if (userOverrides.dateCompleted && !userOverrides.dateTested) {
|
|
1066
|
+
userOverrides.dateTested = userOverrides.dateCompleted;
|
|
1067
|
+
delete userOverrides.dateCompleted;
|
|
1068
|
+
}
|
|
1069
|
+
if (userOverrides.clientLicense && !userOverrides.licenseNumber) {
|
|
1070
|
+
userOverrides.licenseNumber = userOverrides.clientLicense;
|
|
1071
|
+
delete userOverrides.clientLicense;
|
|
1072
|
+
}
|
|
1057
1073
|
let mergedData = {
|
|
1058
1074
|
...mergedConstants,
|
|
1059
1075
|
...profileDataOnly,
|
|
1060
1076
|
...profileClientData,
|
|
1061
1077
|
...clientData,
|
|
1062
|
-
...
|
|
1063
|
-
date: new Date().toISOString().slice(0, 10)
|
|
1064
|
-
approvalDate: new Date().toISOString().slice(0, 10)
|
|
1078
|
+
...userOverrides,
|
|
1079
|
+
date: new Date().toISOString().slice(0, 10)
|
|
1065
1080
|
};
|
|
1081
|
+
// Track if user explicitly set sampleName (so productName doesn't clobber it)
|
|
1082
|
+
const _sampleNameExplicit = !!userOverrides.sampleName;
|
|
1066
1083
|
|
|
1067
1084
|
// 5. Apply generation rules — auto-fill sampleId, dates, etc.
|
|
1068
1085
|
mergedData = applyGenerationRules(tpl.generation_rules, mergedData);
|
|
@@ -1143,12 +1160,23 @@ export async function handleDocuments(sb, args, storeId) {
|
|
|
1143
1160
|
mergedData.testsBatch = true;
|
|
1144
1161
|
}
|
|
1145
1162
|
|
|
1146
|
-
//
|
|
1163
|
+
// 7b3. Resolve product name: productName override → sampleName from profile
|
|
1164
|
+
if (mergedData.productName && !_sampleNameExplicit) {
|
|
1165
|
+
mergedData.sampleName = mergedData.productName;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
// 7c. Generate QR code for COA templates — uses universal resolver URL
|
|
1147
1169
|
if (tpl.slug?.startsWith("cannabis-coa") && !mergedData.qrCodeDataUrl) {
|
|
1148
1170
|
const productSlug = (mergedData.sampleName || "certificate").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_|_$/g, "");
|
|
1149
|
-
const coaUrl = `https://quantixanalytics.com/coa/${sid}/${productSlug}`;
|
|
1171
|
+
const coaUrl = `https://www.quantixanalytics.com/coa/${sid}/${productSlug}`;
|
|
1172
|
+
mergedData._coaVerificationUrl = coaUrl;
|
|
1173
|
+
// Generate a predictable QR code — will be registered in qr_codes table after document insert
|
|
1174
|
+
const _qrCodePrefix = `DOC-${Date.now().toString(36)}`;
|
|
1175
|
+
mergedData._qrCodePrefix = _qrCodePrefix;
|
|
1176
|
+
const resolverUrl = `https://whale-gateway.fly.dev/q/${_qrCodePrefix}`;
|
|
1177
|
+
mergedData._resolverUrl = resolverUrl;
|
|
1150
1178
|
try {
|
|
1151
|
-
mergedData.qrCodeDataUrl = await QRCode.toDataURL(
|
|
1179
|
+
mergedData.qrCodeDataUrl = await QRCode.toDataURL(resolverUrl, {
|
|
1152
1180
|
width: 120,
|
|
1153
1181
|
margin: 1
|
|
1154
1182
|
});
|
|
@@ -1170,6 +1198,21 @@ export async function handleDocuments(sb, args, storeId) {
|
|
|
1170
1198
|
};
|
|
1171
1199
|
}
|
|
1172
1200
|
|
|
1201
|
+
// 8b. Pre-fetch image URLs as base64 data URLs — React-PDF in Node can't fetch external URLs
|
|
1202
|
+
for (const key of ["logoUrl", "signatureUrl"]) {
|
|
1203
|
+
const url = mergedData[key];
|
|
1204
|
+
if (typeof url === "string" && url.startsWith("http")) {
|
|
1205
|
+
try {
|
|
1206
|
+
const res = await fetch(url);
|
|
1207
|
+
if (res.ok) {
|
|
1208
|
+
const buf = Buffer.from(await res.arrayBuffer());
|
|
1209
|
+
const mime = res.headers.get("content-type") || "image/png";
|
|
1210
|
+
mergedData[key] = `data:${mime};base64,${buf.toString("base64")}`;
|
|
1211
|
+
}
|
|
1212
|
+
} catch {/* leave as URL if fetch fails */}
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1173
1216
|
// 9-10. Render PDF — all templates use React-PDF
|
|
1174
1217
|
let pdfBuffer;
|
|
1175
1218
|
try {
|
|
@@ -1196,7 +1239,9 @@ export async function handleDocuments(sb, args, storeId) {
|
|
|
1196
1239
|
|
|
1197
1240
|
// 11. Upload to Supabase storage
|
|
1198
1241
|
const sampleName = mergedData.sampleName || mergedData.productName || "";
|
|
1199
|
-
const
|
|
1242
|
+
const batchId = mergedData.batchId;
|
|
1243
|
+
const defaultName = sampleName ? batchId ? `COA - ${sampleName} - ${batchId}` : `${sampleName} COA` : fillTemplate(tpl.name || "Document", mergedData);
|
|
1244
|
+
const docName = args.name || defaultName;
|
|
1200
1245
|
const safeName = docName.replace(/[^a-zA-Z0-9_\-]/g, "_");
|
|
1201
1246
|
const fileName = `${safeName}_${Date.now()}.pdf`;
|
|
1202
1247
|
const storagePath = `${sid}/${fileName}`;
|
|
@@ -1223,6 +1268,7 @@ export async function handleDocuments(sb, args, storeId) {
|
|
|
1223
1268
|
};
|
|
1224
1269
|
if (tpl.slug?.startsWith("cannabis-coa")) {
|
|
1225
1270
|
coaMetadata.sample_name = sampleName;
|
|
1271
|
+
coaMetadata.product_name = mergedData.productName || sampleName;
|
|
1226
1272
|
coaMetadata.sample_id = mergedData.sampleId || null;
|
|
1227
1273
|
coaMetadata.sample_type = mergedData.sampleType || mergedData.strain || null;
|
|
1228
1274
|
coaMetadata.sample_size = mergedData.sampleSize || null;
|
|
@@ -1294,6 +1340,7 @@ export async function handleDocuments(sb, args, storeId) {
|
|
|
1294
1340
|
document_date: new Date().toISOString().split("T")[0],
|
|
1295
1341
|
customer_id: args.customer_id || null,
|
|
1296
1342
|
client_store_id: resolvedClientStoreId,
|
|
1343
|
+
qr_code_url: mergedData._coaVerificationUrl || null,
|
|
1297
1344
|
data: {
|
|
1298
1345
|
template_id: tpl.id,
|
|
1299
1346
|
template_slug: tpl.slug,
|
|
@@ -1306,6 +1353,53 @@ export async function handleDocuments(sb, args, storeId) {
|
|
|
1306
1353
|
error: insertErr.message
|
|
1307
1354
|
};
|
|
1308
1355
|
await generateThumbnail(sb, record.id, urlData.publicUrl).catch(() => {});
|
|
1356
|
+
|
|
1357
|
+
// 14. Create unified qr_codes record for scan tracking
|
|
1358
|
+
if (mergedData._coaVerificationUrl && mergedData._qrCodePrefix) {
|
|
1359
|
+
const qrCode = mergedData._qrCodePrefix;
|
|
1360
|
+
const resolverUrl = `https://whale-gateway.fly.dev/q/${qrCode}`;
|
|
1361
|
+
sb.from("qr_codes").insert({
|
|
1362
|
+
store_id: sid,
|
|
1363
|
+
code: qrCode,
|
|
1364
|
+
name: docName,
|
|
1365
|
+
type: "document",
|
|
1366
|
+
destination_url: mergedData._coaVerificationUrl,
|
|
1367
|
+
product_id: args.product_id || null,
|
|
1368
|
+
batch_id: args.batch_id || null,
|
|
1369
|
+
is_active: true
|
|
1370
|
+
}).select("id").single().then(({
|
|
1371
|
+
data: qrRecord,
|
|
1372
|
+
error: qrErr
|
|
1373
|
+
}) => {
|
|
1374
|
+
if (qrErr) {
|
|
1375
|
+
console.error("[comms] qr_codes insert error:", qrErr.message);
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1378
|
+
// Link qr_code to the document via qr_code_references
|
|
1379
|
+
if (qrRecord) {
|
|
1380
|
+
sb.from("qr_code_references").insert({
|
|
1381
|
+
store_id: sid,
|
|
1382
|
+
qr_code_id: qrRecord.id,
|
|
1383
|
+
entity_type: "store_document",
|
|
1384
|
+
entity_id: record.id,
|
|
1385
|
+
entity_name: docName,
|
|
1386
|
+
field_name: "coa_verification_qr"
|
|
1387
|
+
}).then(({
|
|
1388
|
+
error: refErr
|
|
1389
|
+
}) => {
|
|
1390
|
+
if (refErr) console.error("[comms] qr_code_references insert error:", refErr.message);
|
|
1391
|
+
});
|
|
1392
|
+
}
|
|
1393
|
+
// Update document with resolver URL
|
|
1394
|
+
sb.from("store_documents").update({
|
|
1395
|
+
qr_code_url: resolverUrl
|
|
1396
|
+
}).eq("id", record.id).then(({
|
|
1397
|
+
error: updErr
|
|
1398
|
+
}) => {
|
|
1399
|
+
if (updErr) console.error("[comms] store_documents qr_code_url update error:", updErr.message);
|
|
1400
|
+
});
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1309
1403
|
return {
|
|
1310
1404
|
success: true,
|
|
1311
1405
|
data: {
|
|
@@ -1376,10 +1470,50 @@ export async function handleDocuments(sb, args, storeId) {
|
|
|
1376
1470
|
};
|
|
1377
1471
|
}
|
|
1378
1472
|
case "list_clients":
|
|
1473
|
+
{
|
|
1474
|
+
// List B2B client stores linked via document_profiles.client_store_id
|
|
1475
|
+
const {
|
|
1476
|
+
data: profiles
|
|
1477
|
+
} = await sb.from("document_profiles").select("client_store_id").eq("owner_store_id", sid).eq("is_active", true).not("client_store_id", "is", null);
|
|
1478
|
+
const clientIds = [...new Set((profiles || []).map(p => p.client_store_id).filter(Boolean))];
|
|
1479
|
+
if (!clientIds.length) {
|
|
1480
|
+
return {
|
|
1481
|
+
success: true,
|
|
1482
|
+
data: {
|
|
1483
|
+
count: 0,
|
|
1484
|
+
clients: [],
|
|
1485
|
+
hint: "No client stores linked to document profiles. Use list_customers for retail customers."
|
|
1486
|
+
}
|
|
1487
|
+
};
|
|
1488
|
+
}
|
|
1489
|
+
const {
|
|
1490
|
+
data: stores,
|
|
1491
|
+
error: storesErr
|
|
1492
|
+
} = await sb.from("stores").select("id, store_name, legal_name, address, city, state, zip, distributor_license_number, phone, email").in("id", clientIds);
|
|
1493
|
+
if (storesErr) return {
|
|
1494
|
+
success: false,
|
|
1495
|
+
error: storesErr.message
|
|
1496
|
+
};
|
|
1497
|
+
return {
|
|
1498
|
+
success: true,
|
|
1499
|
+
data: {
|
|
1500
|
+
count: stores?.length || 0,
|
|
1501
|
+
clients: (stores || []).map(s => ({
|
|
1502
|
+
id: s.id,
|
|
1503
|
+
name: s.legal_name || s.store_name,
|
|
1504
|
+
store_name: s.store_name,
|
|
1505
|
+
address: [s.address, s.city, s.state, s.zip].filter(Boolean).join(", "),
|
|
1506
|
+
license: s.distributor_license_number || null,
|
|
1507
|
+
phone: s.phone || null,
|
|
1508
|
+
email: s.email || null
|
|
1509
|
+
}))
|
|
1510
|
+
}
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1379
1513
|
case "list_customers":
|
|
1380
1514
|
return {
|
|
1381
1515
|
success: false,
|
|
1382
|
-
error: "Use the 'customers' tool
|
|
1516
|
+
error: "Use the 'customers' tool for retail customers. Use list_clients for B2B client stores."
|
|
1383
1517
|
};
|
|
1384
1518
|
case "deliver_documents":
|
|
1385
1519
|
{
|