whale-code 6.5.8 → 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/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 +26 -3
- package/vendor/ink/package.json +0 -2
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
// server/handlers/pipeline.ts — Sales pipeline and deal management
|
|
2
|
+
|
|
3
|
+
import { sanitizeFilterValue } from "../lib/utils.js";
|
|
4
|
+
export async function handlePipeline(sb, args, storeId) {
|
|
5
|
+
const sid = storeId;
|
|
6
|
+
switch (args.action) {
|
|
7
|
+
// ---- STAGES: list pipeline stages ----
|
|
8
|
+
case "stages":
|
|
9
|
+
{
|
|
10
|
+
const {
|
|
11
|
+
data,
|
|
12
|
+
error
|
|
13
|
+
} = await sb.from("sales_pipeline_stages").select("*").eq("store_id", sid).order("display_order", {
|
|
14
|
+
ascending: true
|
|
15
|
+
});
|
|
16
|
+
return error ? {
|
|
17
|
+
success: false,
|
|
18
|
+
error: error.message
|
|
19
|
+
} : {
|
|
20
|
+
success: true,
|
|
21
|
+
count: data?.length,
|
|
22
|
+
data
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ---- CREATE_STAGE: add a new pipeline stage ----
|
|
27
|
+
case "create_stage":
|
|
28
|
+
{
|
|
29
|
+
const name = args.name;
|
|
30
|
+
if (!name) return {
|
|
31
|
+
success: false,
|
|
32
|
+
error: "name is required"
|
|
33
|
+
};
|
|
34
|
+
const record = {
|
|
35
|
+
store_id: sid,
|
|
36
|
+
name
|
|
37
|
+
};
|
|
38
|
+
if (args.display_order !== undefined) record.display_order = args.display_order;
|
|
39
|
+
if (args.color !== undefined) record.color = args.color;
|
|
40
|
+
if (args.is_won !== undefined) record.is_won = args.is_won;
|
|
41
|
+
if (args.is_lost !== undefined) record.is_lost = args.is_lost;
|
|
42
|
+
const {
|
|
43
|
+
data,
|
|
44
|
+
error
|
|
45
|
+
} = await sb.from("sales_pipeline_stages").insert(record).select().single();
|
|
46
|
+
return error ? {
|
|
47
|
+
success: false,
|
|
48
|
+
error: error.message
|
|
49
|
+
} : {
|
|
50
|
+
success: true,
|
|
51
|
+
data
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ---- LIST_DEALS: list deals with optional filters ----
|
|
56
|
+
case "list_deals":
|
|
57
|
+
{
|
|
58
|
+
let q = sb.from("sales_deals").select("*, stage:sales_pipeline_stages!stage_id(name, color, is_won, is_lost)").eq("store_id", sid).order("created_at", {
|
|
59
|
+
ascending: false
|
|
60
|
+
});
|
|
61
|
+
if (args.status) q = q.eq("status", args.status);
|
|
62
|
+
if (args.stage_id) q = q.eq("stage_id", args.stage_id);
|
|
63
|
+
if (args.customer_id) q = q.eq("customer_id", args.customer_id);
|
|
64
|
+
if (args.assigned_to) q = q.eq("assigned_to", args.assigned_to);
|
|
65
|
+
if (args.query) {
|
|
66
|
+
const sq = sanitizeFilterValue(String(args.query));
|
|
67
|
+
q = q.or(`title.ilike.%${sq}%,contact_name.ilike.%${sq}%,contact_email.ilike.%${sq}%`);
|
|
68
|
+
}
|
|
69
|
+
q = q.limit(args.limit || 50);
|
|
70
|
+
const {
|
|
71
|
+
data,
|
|
72
|
+
error
|
|
73
|
+
} = await q;
|
|
74
|
+
return error ? {
|
|
75
|
+
success: false,
|
|
76
|
+
error: error.message
|
|
77
|
+
} : {
|
|
78
|
+
success: true,
|
|
79
|
+
count: data?.length,
|
|
80
|
+
data
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ---- GET_DEAL: get deal detail ----
|
|
85
|
+
case "get_deal":
|
|
86
|
+
{
|
|
87
|
+
const dealId = args.deal_id;
|
|
88
|
+
if (!dealId) return {
|
|
89
|
+
success: false,
|
|
90
|
+
error: "deal_id is required"
|
|
91
|
+
};
|
|
92
|
+
const {
|
|
93
|
+
data,
|
|
94
|
+
error
|
|
95
|
+
} = await sb.from("sales_deals").select("*, stage:sales_pipeline_stages!stage_id(name, color, is_won, is_lost)").eq("id", dealId).eq("store_id", sid).single();
|
|
96
|
+
return error ? {
|
|
97
|
+
success: false,
|
|
98
|
+
error: error.message
|
|
99
|
+
} : {
|
|
100
|
+
success: true,
|
|
101
|
+
data
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// ---- CREATE_DEAL: create a new deal ----
|
|
106
|
+
case "create_deal":
|
|
107
|
+
{
|
|
108
|
+
const title = args.title;
|
|
109
|
+
if (!title) return {
|
|
110
|
+
success: false,
|
|
111
|
+
error: "title is required"
|
|
112
|
+
};
|
|
113
|
+
const record = {
|
|
114
|
+
store_id: sid,
|
|
115
|
+
title,
|
|
116
|
+
status: "open"
|
|
117
|
+
};
|
|
118
|
+
if (args.value !== undefined) record.value = args.value;
|
|
119
|
+
if (args.stage_id !== undefined) record.stage_id = args.stage_id;
|
|
120
|
+
if (args.probability !== undefined) record.probability = args.probability;
|
|
121
|
+
if (args.expected_close_date !== undefined) record.expected_close_date = args.expected_close_date;
|
|
122
|
+
if (args.customer_id !== undefined) record.customer_id = args.customer_id;
|
|
123
|
+
if (args.contact_name !== undefined) record.contact_name = args.contact_name;
|
|
124
|
+
if (args.contact_email !== undefined) record.contact_email = args.contact_email;
|
|
125
|
+
if (args.contact_phone !== undefined) record.contact_phone = args.contact_phone;
|
|
126
|
+
if (args.assigned_to !== undefined) record.assigned_to = args.assigned_to;
|
|
127
|
+
if (args.source !== undefined) record.source = args.source;
|
|
128
|
+
if (args.notes !== undefined) record.notes = args.notes;
|
|
129
|
+
const {
|
|
130
|
+
data,
|
|
131
|
+
error
|
|
132
|
+
} = await sb.from("sales_deals").insert(record).select().single();
|
|
133
|
+
return error ? {
|
|
134
|
+
success: false,
|
|
135
|
+
error: error.message
|
|
136
|
+
} : {
|
|
137
|
+
success: true,
|
|
138
|
+
data
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ---- UPDATE_DEAL: modify a deal ----
|
|
143
|
+
case "update_deal":
|
|
144
|
+
{
|
|
145
|
+
const dealId = args.deal_id;
|
|
146
|
+
if (!dealId) return {
|
|
147
|
+
success: false,
|
|
148
|
+
error: "deal_id is required"
|
|
149
|
+
};
|
|
150
|
+
const updates = {
|
|
151
|
+
updated_at: new Date().toISOString()
|
|
152
|
+
};
|
|
153
|
+
if (args.title !== undefined) updates.title = args.title;
|
|
154
|
+
if (args.value !== undefined) updates.value = args.value;
|
|
155
|
+
if (args.stage_id !== undefined) updates.stage_id = args.stage_id;
|
|
156
|
+
if (args.probability !== undefined) updates.probability = args.probability;
|
|
157
|
+
if (args.expected_close_date !== undefined) updates.expected_close_date = args.expected_close_date;
|
|
158
|
+
if (args.status !== undefined) {
|
|
159
|
+
updates.status = args.status;
|
|
160
|
+
if (args.status === "won" || args.status === "lost") {
|
|
161
|
+
updates.actual_close_date = new Date().toISOString().split("T")[0];
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (args.assigned_to !== undefined) updates.assigned_to = args.assigned_to;
|
|
165
|
+
if (args.notes !== undefined) updates.notes = args.notes;
|
|
166
|
+
if (args.contact_name !== undefined) updates.contact_name = args.contact_name;
|
|
167
|
+
if (args.contact_email !== undefined) updates.contact_email = args.contact_email;
|
|
168
|
+
if (args.contact_phone !== undefined) updates.contact_phone = args.contact_phone;
|
|
169
|
+
const {
|
|
170
|
+
data,
|
|
171
|
+
error
|
|
172
|
+
} = await sb.from("sales_deals").update(updates).eq("id", dealId).eq("store_id", sid).select().single();
|
|
173
|
+
return error ? {
|
|
174
|
+
success: false,
|
|
175
|
+
error: error.message
|
|
176
|
+
} : {
|
|
177
|
+
success: true,
|
|
178
|
+
data
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ---- MOVE_DEAL: move a deal to a different stage ----
|
|
183
|
+
case "move_deal":
|
|
184
|
+
{
|
|
185
|
+
const dealId = args.deal_id;
|
|
186
|
+
const stageId = args.stage_id;
|
|
187
|
+
if (!dealId || !stageId) return {
|
|
188
|
+
success: false,
|
|
189
|
+
error: "deal_id and stage_id are required"
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
// Check if stage is a terminal stage (won/lost)
|
|
193
|
+
const {
|
|
194
|
+
data: stage
|
|
195
|
+
} = await sb.from("sales_pipeline_stages").select("is_won, is_lost").eq("id", stageId).eq("store_id", sid).single();
|
|
196
|
+
const updates = {
|
|
197
|
+
stage_id: stageId,
|
|
198
|
+
updated_at: new Date().toISOString()
|
|
199
|
+
};
|
|
200
|
+
if (stage?.is_won) {
|
|
201
|
+
updates.status = "won";
|
|
202
|
+
updates.actual_close_date = new Date().toISOString().split("T")[0];
|
|
203
|
+
}
|
|
204
|
+
if (stage?.is_lost) {
|
|
205
|
+
updates.status = "lost";
|
|
206
|
+
updates.actual_close_date = new Date().toISOString().split("T")[0];
|
|
207
|
+
}
|
|
208
|
+
const {
|
|
209
|
+
data,
|
|
210
|
+
error
|
|
211
|
+
} = await sb.from("sales_deals").update(updates).eq("id", dealId).eq("store_id", sid).select("*, stage:sales_pipeline_stages!stage_id(name, color)").single();
|
|
212
|
+
return error ? {
|
|
213
|
+
success: false,
|
|
214
|
+
error: error.message
|
|
215
|
+
} : {
|
|
216
|
+
success: true,
|
|
217
|
+
data
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ---- SUMMARY: pipeline value and deal count per stage ----
|
|
222
|
+
case "summary":
|
|
223
|
+
{
|
|
224
|
+
const [{
|
|
225
|
+
data: stages,
|
|
226
|
+
error: stErr
|
|
227
|
+
}, {
|
|
228
|
+
data: deals,
|
|
229
|
+
error: dErr
|
|
230
|
+
}] = await Promise.all([sb.from("sales_pipeline_stages").select("id, name, display_order, color, is_won, is_lost").eq("store_id", sid).order("display_order", {
|
|
231
|
+
ascending: true
|
|
232
|
+
}), sb.from("sales_deals").select("stage_id, value, status").eq("store_id", sid).eq("status", "open")]);
|
|
233
|
+
if (stErr) return {
|
|
234
|
+
success: false,
|
|
235
|
+
error: stErr.message
|
|
236
|
+
};
|
|
237
|
+
if (dErr) return {
|
|
238
|
+
success: false,
|
|
239
|
+
error: dErr.message
|
|
240
|
+
};
|
|
241
|
+
const stageMap = {};
|
|
242
|
+
for (const s of stages || []) {
|
|
243
|
+
stageMap[s.id] = {
|
|
244
|
+
name: s.name,
|
|
245
|
+
color: s.color,
|
|
246
|
+
deal_count: 0,
|
|
247
|
+
total_value: 0,
|
|
248
|
+
weighted_value: 0
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
for (const d of deals || []) {
|
|
252
|
+
const s = stageMap[d.stage_id];
|
|
253
|
+
if (s) {
|
|
254
|
+
s.deal_count++;
|
|
255
|
+
s.total_value += Number(d.value) || 0;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const pipeline = Object.values(stageMap);
|
|
259
|
+
const totalDeals = pipeline.reduce((s, st) => s + st.deal_count, 0);
|
|
260
|
+
const totalValue = pipeline.reduce((s, st) => s + st.total_value, 0);
|
|
261
|
+
return {
|
|
262
|
+
success: true,
|
|
263
|
+
data: {
|
|
264
|
+
total_open_deals: totalDeals,
|
|
265
|
+
total_pipeline_value: totalValue,
|
|
266
|
+
stages: pipeline
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
default:
|
|
271
|
+
return {
|
|
272
|
+
success: false,
|
|
273
|
+
error: `Unknown pipeline action: ${args.action}. Valid: stages, create_stage, list_deals, get_deal, create_deal, update_deal, move_deal, summary`
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=pipeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.js","names":["sanitizeFilterValue","handlePipeline","sb","args","storeId","sid","action","data","error","from","select","eq","order","ascending","success","message","count","length","name","record","store_id","display_order","undefined","color","is_won","is_lost","insert","single","q","status","stage_id","customer_id","assigned_to","query","sq","String","or","limit","dealId","deal_id","title","value","probability","expected_close_date","contact_name","contact_email","contact_phone","source","notes","updates","updated_at","Date","toISOString","actual_close_date","split","update","stageId","stage","stages","stErr","deals","dErr","Promise","all","stageMap","s","id","deal_count","total_value","weighted_value","d","Number","pipeline","Object","values","totalDeals","reduce","st","totalValue","total_open_deals","total_pipeline_value"],"sources":["../../../src/server/handlers/pipeline.ts"],"sourcesContent":["// server/handlers/pipeline.ts — Sales pipeline and deal management\n\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\nimport { sanitizeFilterValue } from \"../lib/utils.js\";\n\ntype Result = { success: boolean; data?: unknown; error?: string; [key: string]: unknown };\n\nexport async function handlePipeline(\n sb: SupabaseClient,\n args: Record<string, unknown>,\n storeId?: string,\n): Promise<Result> {\n const sid = storeId as string;\n\n switch (args.action) {\n // ---- STAGES: list pipeline stages ----\n case \"stages\": {\n const { data, error } = await sb.from(\"sales_pipeline_stages\")\n .select(\"*\")\n .eq(\"store_id\", sid)\n .order(\"display_order\", { ascending: true });\n return error ? { success: false, error: error.message } : { success: true, count: data?.length, data };\n }\n\n // ---- CREATE_STAGE: add a new pipeline stage ----\n case \"create_stage\": {\n const name = args.name as string;\n if (!name) return { success: false, error: \"name is required\" };\n const record: Record<string, unknown> = { store_id: sid, name };\n if (args.display_order !== undefined) record.display_order = args.display_order;\n if (args.color !== undefined) record.color = args.color;\n if (args.is_won !== undefined) record.is_won = args.is_won;\n if (args.is_lost !== undefined) record.is_lost = args.is_lost;\n\n const { data, error } = await sb.from(\"sales_pipeline_stages\")\n .insert(record)\n .select()\n .single();\n return error ? { success: false, error: error.message } : { success: true, data };\n }\n\n // ---- LIST_DEALS: list deals with optional filters ----\n case \"list_deals\": {\n let q = sb.from(\"sales_deals\")\n .select(\"*, stage:sales_pipeline_stages!stage_id(name, color, is_won, is_lost)\")\n .eq(\"store_id\", sid)\n .order(\"created_at\", { ascending: false });\n if (args.status) q = q.eq(\"status\", args.status as string);\n if (args.stage_id) q = q.eq(\"stage_id\", args.stage_id as string);\n if (args.customer_id) q = q.eq(\"customer_id\", args.customer_id as string);\n if (args.assigned_to) q = q.eq(\"assigned_to\", args.assigned_to as string);\n if (args.query) {\n const sq = sanitizeFilterValue(String(args.query));\n q = q.or(`title.ilike.%${sq}%,contact_name.ilike.%${sq}%,contact_email.ilike.%${sq}%`);\n }\n q = q.limit(args.limit as number || 50);\n const { data, error } = await q;\n return error ? { success: false, error: error.message } : { success: true, count: data?.length, data };\n }\n\n // ---- GET_DEAL: get deal detail ----\n case \"get_deal\": {\n const dealId = args.deal_id as string;\n if (!dealId) return { success: false, error: \"deal_id is required\" };\n const { data, error } = await sb.from(\"sales_deals\")\n .select(\"*, stage:sales_pipeline_stages!stage_id(name, color, is_won, is_lost)\")\n .eq(\"id\", dealId)\n .eq(\"store_id\", sid)\n .single();\n return error ? { success: false, error: error.message } : { success: true, data };\n }\n\n // ---- CREATE_DEAL: create a new deal ----\n case \"create_deal\": {\n const title = args.title as string;\n if (!title) return { success: false, error: \"title is required\" };\n const record: Record<string, unknown> = {\n store_id: sid,\n title,\n status: \"open\",\n };\n if (args.value !== undefined) record.value = args.value;\n if (args.stage_id !== undefined) record.stage_id = args.stage_id;\n if (args.probability !== undefined) record.probability = args.probability;\n if (args.expected_close_date !== undefined) record.expected_close_date = args.expected_close_date;\n if (args.customer_id !== undefined) record.customer_id = args.customer_id;\n if (args.contact_name !== undefined) record.contact_name = args.contact_name;\n if (args.contact_email !== undefined) record.contact_email = args.contact_email;\n if (args.contact_phone !== undefined) record.contact_phone = args.contact_phone;\n if (args.assigned_to !== undefined) record.assigned_to = args.assigned_to;\n if (args.source !== undefined) record.source = args.source;\n if (args.notes !== undefined) record.notes = args.notes;\n\n const { data, error } = await sb.from(\"sales_deals\")\n .insert(record)\n .select()\n .single();\n return error ? { success: false, error: error.message } : { success: true, data };\n }\n\n // ---- UPDATE_DEAL: modify a deal ----\n case \"update_deal\": {\n const dealId = args.deal_id as string;\n if (!dealId) return { success: false, error: \"deal_id is required\" };\n const updates: Record<string, unknown> = { updated_at: new Date().toISOString() };\n if (args.title !== undefined) updates.title = args.title;\n if (args.value !== undefined) updates.value = args.value;\n if (args.stage_id !== undefined) updates.stage_id = args.stage_id;\n if (args.probability !== undefined) updates.probability = args.probability;\n if (args.expected_close_date !== undefined) updates.expected_close_date = args.expected_close_date;\n if (args.status !== undefined) {\n updates.status = args.status;\n if (args.status === \"won\" || args.status === \"lost\") {\n updates.actual_close_date = new Date().toISOString().split(\"T\")[0];\n }\n }\n if (args.assigned_to !== undefined) updates.assigned_to = args.assigned_to;\n if (args.notes !== undefined) updates.notes = args.notes;\n if (args.contact_name !== undefined) updates.contact_name = args.contact_name;\n if (args.contact_email !== undefined) updates.contact_email = args.contact_email;\n if (args.contact_phone !== undefined) updates.contact_phone = args.contact_phone;\n\n const { data, error } = await sb.from(\"sales_deals\")\n .update(updates)\n .eq(\"id\", dealId)\n .eq(\"store_id\", sid)\n .select()\n .single();\n return error ? { success: false, error: error.message } : { success: true, data };\n }\n\n // ---- MOVE_DEAL: move a deal to a different stage ----\n case \"move_deal\": {\n const dealId = args.deal_id as string;\n const stageId = args.stage_id as string;\n if (!dealId || !stageId) return { success: false, error: \"deal_id and stage_id are required\" };\n\n // Check if stage is a terminal stage (won/lost)\n const { data: stage } = await sb.from(\"sales_pipeline_stages\")\n .select(\"is_won, is_lost\")\n .eq(\"id\", stageId)\n .eq(\"store_id\", sid)\n .single();\n\n const updates: Record<string, unknown> = {\n stage_id: stageId,\n updated_at: new Date().toISOString(),\n };\n if (stage?.is_won) { updates.status = \"won\"; updates.actual_close_date = new Date().toISOString().split(\"T\")[0]; }\n if (stage?.is_lost) { updates.status = \"lost\"; updates.actual_close_date = new Date().toISOString().split(\"T\")[0]; }\n\n const { data, error } = await sb.from(\"sales_deals\")\n .update(updates)\n .eq(\"id\", dealId)\n .eq(\"store_id\", sid)\n .select(\"*, stage:sales_pipeline_stages!stage_id(name, color)\")\n .single();\n return error ? { success: false, error: error.message } : { success: true, data };\n }\n\n // ---- SUMMARY: pipeline value and deal count per stage ----\n case \"summary\": {\n const [{ data: stages, error: stErr }, { data: deals, error: dErr }] = await Promise.all([\n sb.from(\"sales_pipeline_stages\").select(\"id, name, display_order, color, is_won, is_lost\").eq(\"store_id\", sid).order(\"display_order\", { ascending: true }),\n sb.from(\"sales_deals\").select(\"stage_id, value, status\").eq(\"store_id\", sid).eq(\"status\", \"open\"),\n ]);\n if (stErr) return { success: false, error: stErr.message };\n if (dErr) return { success: false, error: dErr.message };\n\n const stageMap: Record<string, { name: string; color: string; deal_count: number; total_value: number; weighted_value: number }> = {};\n for (const s of stages || []) {\n stageMap[s.id] = { name: s.name, color: s.color, deal_count: 0, total_value: 0, weighted_value: 0 };\n }\n for (const d of deals || []) {\n const s = stageMap[d.stage_id];\n if (s) {\n s.deal_count++;\n s.total_value += Number(d.value) || 0;\n }\n }\n\n const pipeline = Object.values(stageMap);\n const totalDeals = pipeline.reduce((s, st) => s + st.deal_count, 0);\n const totalValue = pipeline.reduce((s, st) => s + st.total_value, 0);\n\n return {\n success: true,\n data: { total_open_deals: totalDeals, total_pipeline_value: totalValue, stages: pipeline },\n };\n }\n\n default:\n return { success: false, error: `Unknown pipeline action: ${args.action}. Valid: stages, create_stage, list_deals, get_deal, create_deal, update_deal, move_deal, summary` };\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
+
type Result = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
data?: unknown;
|
|
5
|
+
error?: string;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
};
|
|
8
|
+
export declare function handleQRCodes(sb: SupabaseClient, args: Record<string, unknown>, storeId?: string): Promise<Result>;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// server/handlers/qr-codes.ts — QR code generation and management
|
|
2
|
+
|
|
3
|
+
import { sanitizeFilterValue } from "../lib/utils.js";
|
|
4
|
+
export async function handleQRCodes(sb, args, storeId) {
|
|
5
|
+
const sid = storeId;
|
|
6
|
+
switch (args.action) {
|
|
7
|
+
// ---- LIST: list QR codes ----
|
|
8
|
+
case "list":
|
|
9
|
+
{
|
|
10
|
+
let q = sb.from("qr_codes").select("id, code, name, type, destination_url, is_active, total_scans, unique_scans, last_scanned_at, tags, status, created_at").eq("store_id", sid).order("created_at", {
|
|
11
|
+
ascending: false
|
|
12
|
+
});
|
|
13
|
+
if (args.type) q = q.eq("type", args.type);
|
|
14
|
+
if (args.is_active !== undefined) q = q.eq("is_active", args.is_active);
|
|
15
|
+
if (args.status) q = q.eq("status", args.status);
|
|
16
|
+
if (args.query) {
|
|
17
|
+
const sq = sanitizeFilterValue(String(args.query));
|
|
18
|
+
q = q.or(`code.ilike.%${sq}%,name.ilike.%${sq}%`);
|
|
19
|
+
}
|
|
20
|
+
q = q.limit(args.limit || 50);
|
|
21
|
+
const {
|
|
22
|
+
data,
|
|
23
|
+
error
|
|
24
|
+
} = await q;
|
|
25
|
+
return error ? {
|
|
26
|
+
success: false,
|
|
27
|
+
error: error.message
|
|
28
|
+
} : {
|
|
29
|
+
success: true,
|
|
30
|
+
count: data?.length,
|
|
31
|
+
data
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ---- GET: get QR code detail with CTAs and scan stats ----
|
|
36
|
+
case "get":
|
|
37
|
+
{
|
|
38
|
+
const qrId = args.qr_code_id;
|
|
39
|
+
if (!qrId) return {
|
|
40
|
+
success: false,
|
|
41
|
+
error: "qr_code_id is required"
|
|
42
|
+
};
|
|
43
|
+
const {
|
|
44
|
+
data,
|
|
45
|
+
error
|
|
46
|
+
} = await sb.from("qr_codes").select("*, ctas:qr_code_ctas(*)").eq("id", qrId).eq("store_id", sid).single();
|
|
47
|
+
return error ? {
|
|
48
|
+
success: false,
|
|
49
|
+
error: error.message
|
|
50
|
+
} : {
|
|
51
|
+
success: true,
|
|
52
|
+
data
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ---- CREATE: create a new QR code ----
|
|
57
|
+
case "create":
|
|
58
|
+
{
|
|
59
|
+
const code = args.code;
|
|
60
|
+
const type = args.type;
|
|
61
|
+
const destinationUrl = args.destination_url;
|
|
62
|
+
if (!code || !type || !destinationUrl) {
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
error: "code, type, and destination_url are required"
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const record = {
|
|
69
|
+
store_id: sid,
|
|
70
|
+
code,
|
|
71
|
+
type,
|
|
72
|
+
destination_url: destinationUrl
|
|
73
|
+
};
|
|
74
|
+
if (args.name !== undefined) record.name = args.name;
|
|
75
|
+
if (args.landing_page_url !== undefined) record.landing_page_url = args.landing_page_url;
|
|
76
|
+
if (args.qr_style !== undefined) record.qr_style = args.qr_style;
|
|
77
|
+
if (args.brand_color !== undefined) record.brand_color = args.brand_color;
|
|
78
|
+
if (args.logo_url !== undefined) record.logo_url = args.logo_url;
|
|
79
|
+
if (args.campaign_name !== undefined) record.campaign_name = args.campaign_name;
|
|
80
|
+
if (args.landing_page_title !== undefined) record.landing_page_title = args.landing_page_title;
|
|
81
|
+
if (args.landing_page_description !== undefined) record.landing_page_description = args.landing_page_description;
|
|
82
|
+
if (args.landing_page_image_url !== undefined) record.landing_page_image_url = args.landing_page_image_url;
|
|
83
|
+
if (args.expires_at !== undefined) record.expires_at = args.expires_at;
|
|
84
|
+
if (args.max_scans !== undefined) record.max_scans = args.max_scans;
|
|
85
|
+
if (args.tags !== undefined) record.tags = args.tags;
|
|
86
|
+
const {
|
|
87
|
+
data,
|
|
88
|
+
error
|
|
89
|
+
} = await sb.from("qr_codes").insert(record).select().single();
|
|
90
|
+
return error ? {
|
|
91
|
+
success: false,
|
|
92
|
+
error: error.message
|
|
93
|
+
} : {
|
|
94
|
+
success: true,
|
|
95
|
+
data
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ---- UPDATE: modify a QR code ----
|
|
100
|
+
case "update":
|
|
101
|
+
{
|
|
102
|
+
const qrId = args.qr_code_id;
|
|
103
|
+
if (!qrId) return {
|
|
104
|
+
success: false,
|
|
105
|
+
error: "qr_code_id is required"
|
|
106
|
+
};
|
|
107
|
+
const updates = {
|
|
108
|
+
updated_at: new Date().toISOString()
|
|
109
|
+
};
|
|
110
|
+
if (args.name !== undefined) updates.name = args.name;
|
|
111
|
+
if (args.destination_url !== undefined) updates.destination_url = args.destination_url;
|
|
112
|
+
if (args.is_active !== undefined) updates.is_active = args.is_active;
|
|
113
|
+
if (args.landing_page_title !== undefined) updates.landing_page_title = args.landing_page_title;
|
|
114
|
+
if (args.landing_page_description !== undefined) updates.landing_page_description = args.landing_page_description;
|
|
115
|
+
if (args.tags !== undefined) updates.tags = args.tags;
|
|
116
|
+
const {
|
|
117
|
+
data,
|
|
118
|
+
error
|
|
119
|
+
} = await sb.from("qr_codes").update(updates).eq("id", qrId).eq("store_id", sid).select().single();
|
|
120
|
+
return error ? {
|
|
121
|
+
success: false,
|
|
122
|
+
error: error.message
|
|
123
|
+
} : {
|
|
124
|
+
success: true,
|
|
125
|
+
data
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// ---- SCANS: list scan history for a QR code ----
|
|
130
|
+
case "scans":
|
|
131
|
+
{
|
|
132
|
+
const qrId = args.qr_code_id;
|
|
133
|
+
if (!qrId) return {
|
|
134
|
+
success: false,
|
|
135
|
+
error: "qr_code_id is required"
|
|
136
|
+
};
|
|
137
|
+
let q = sb.from("qr_scans").select("id, scanned_at, is_first_scan, city, region, country, device_type, browser_name, converted, conversion_value, operation").eq("qr_code_id", qrId).eq("store_id", sid).order("scanned_at", {
|
|
138
|
+
ascending: false
|
|
139
|
+
});
|
|
140
|
+
q = q.limit(args.limit || 50);
|
|
141
|
+
const {
|
|
142
|
+
data,
|
|
143
|
+
error
|
|
144
|
+
} = await q;
|
|
145
|
+
return error ? {
|
|
146
|
+
success: false,
|
|
147
|
+
error: error.message
|
|
148
|
+
} : {
|
|
149
|
+
success: true,
|
|
150
|
+
count: data?.length,
|
|
151
|
+
data
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ---- ANALYTICS: scan analytics summary for a QR code ----
|
|
156
|
+
case "analytics":
|
|
157
|
+
{
|
|
158
|
+
const qrId = args.qr_code_id;
|
|
159
|
+
if (!qrId) return {
|
|
160
|
+
success: false,
|
|
161
|
+
error: "qr_code_id is required"
|
|
162
|
+
};
|
|
163
|
+
const {
|
|
164
|
+
data: scans,
|
|
165
|
+
error
|
|
166
|
+
} = await sb.from("qr_scans").select("city, region, country, device_type, converted, conversion_value, scanned_at").eq("qr_code_id", qrId).eq("store_id", sid);
|
|
167
|
+
if (error) return {
|
|
168
|
+
success: false,
|
|
169
|
+
error: error.message
|
|
170
|
+
};
|
|
171
|
+
const scanList = scans || [];
|
|
172
|
+
const conversions = scanList.filter(s => s.converted);
|
|
173
|
+
const byCity = {};
|
|
174
|
+
const byDevice = {};
|
|
175
|
+
for (const s of scanList) {
|
|
176
|
+
if (s.city) byCity[s.city] = (byCity[s.city] || 0) + 1;
|
|
177
|
+
if (s.device_type) byDevice[s.device_type] = (byDevice[s.device_type] || 0) + 1;
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
success: true,
|
|
181
|
+
data: {
|
|
182
|
+
total_scans: scanList.length,
|
|
183
|
+
conversions: conversions.length,
|
|
184
|
+
conversion_rate: scanList.length > 0 ? Math.round(conversions.length / scanList.length * 1000) / 10 : 0,
|
|
185
|
+
total_revenue: conversions.reduce((s, c) => s + (Number(c.conversion_value) || 0), 0),
|
|
186
|
+
by_city: byCity,
|
|
187
|
+
by_device: byDevice
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
default:
|
|
192
|
+
return {
|
|
193
|
+
success: false,
|
|
194
|
+
error: `Unknown qr_codes action: ${args.action}. Valid: list, get, create, update, scans, analytics`
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=qr-codes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr-codes.js","names":["sanitizeFilterValue","handleQRCodes","sb","args","storeId","sid","action","q","from","select","eq","order","ascending","type","is_active","undefined","status","query","sq","String","or","limit","data","error","success","message","count","length","qrId","qr_code_id","single","code","destinationUrl","destination_url","record","store_id","name","landing_page_url","qr_style","brand_color","logo_url","campaign_name","landing_page_title","landing_page_description","landing_page_image_url","expires_at","max_scans","tags","insert","updates","updated_at","Date","toISOString","update","scans","scanList","conversions","filter","s","converted","byCity","byDevice","city","device_type","total_scans","conversion_rate","Math","round","total_revenue","reduce","c","Number","conversion_value","by_city","by_device"],"sources":["../../../src/server/handlers/qr-codes.ts"],"sourcesContent":["// server/handlers/qr-codes.ts — QR code generation and management\n\nimport type { SupabaseClient } from \"@supabase/supabase-js\";\nimport { sanitizeFilterValue } from \"../lib/utils.js\";\n\ntype Result = { success: boolean; data?: unknown; error?: string; [key: string]: unknown };\n\nexport async function handleQRCodes(\n sb: SupabaseClient,\n args: Record<string, unknown>,\n storeId?: string,\n): Promise<Result> {\n const sid = storeId as string;\n\n switch (args.action) {\n // ---- LIST: list QR codes ----\n case \"list\": {\n let q = sb.from(\"qr_codes\")\n .select(\"id, code, name, type, destination_url, is_active, total_scans, unique_scans, last_scanned_at, tags, status, created_at\")\n .eq(\"store_id\", sid)\n .order(\"created_at\", { ascending: false });\n if (args.type) q = q.eq(\"type\", args.type as string);\n if (args.is_active !== undefined) q = q.eq(\"is_active\", args.is_active as boolean);\n if (args.status) q = q.eq(\"status\", args.status as string);\n if (args.query) {\n const sq = sanitizeFilterValue(String(args.query));\n q = q.or(`code.ilike.%${sq}%,name.ilike.%${sq}%`);\n }\n q = q.limit(args.limit as number || 50);\n const { data, error } = await q;\n return error ? { success: false, error: error.message } : { success: true, count: data?.length, data };\n }\n\n // ---- GET: get QR code detail with CTAs and scan stats ----\n case \"get\": {\n const qrId = args.qr_code_id as string;\n if (!qrId) return { success: false, error: \"qr_code_id is required\" };\n const { data, error } = await sb.from(\"qr_codes\")\n .select(\"*, ctas:qr_code_ctas(*)\")\n .eq(\"id\", qrId)\n .eq(\"store_id\", sid)\n .single();\n return error ? { success: false, error: error.message } : { success: true, data };\n }\n\n // ---- CREATE: create a new QR code ----\n case \"create\": {\n const code = args.code as string;\n const type = args.type as string;\n const destinationUrl = args.destination_url as string;\n if (!code || !type || !destinationUrl) {\n return { success: false, error: \"code, type, and destination_url are required\" };\n }\n const record: Record<string, unknown> = {\n store_id: sid,\n code,\n type,\n destination_url: destinationUrl,\n };\n if (args.name !== undefined) record.name = args.name;\n if (args.landing_page_url !== undefined) record.landing_page_url = args.landing_page_url;\n if (args.qr_style !== undefined) record.qr_style = args.qr_style;\n if (args.brand_color !== undefined) record.brand_color = args.brand_color;\n if (args.logo_url !== undefined) record.logo_url = args.logo_url;\n if (args.campaign_name !== undefined) record.campaign_name = args.campaign_name;\n if (args.landing_page_title !== undefined) record.landing_page_title = args.landing_page_title;\n if (args.landing_page_description !== undefined) record.landing_page_description = args.landing_page_description;\n if (args.landing_page_image_url !== undefined) record.landing_page_image_url = args.landing_page_image_url;\n if (args.expires_at !== undefined) record.expires_at = args.expires_at;\n if (args.max_scans !== undefined) record.max_scans = args.max_scans;\n if (args.tags !== undefined) record.tags = args.tags;\n\n const { data, error } = await sb.from(\"qr_codes\")\n .insert(record)\n .select()\n .single();\n return error ? { success: false, error: error.message } : { success: true, data };\n }\n\n // ---- UPDATE: modify a QR code ----\n case \"update\": {\n const qrId = args.qr_code_id as string;\n if (!qrId) return { success: false, error: \"qr_code_id is required\" };\n const updates: Record<string, unknown> = { updated_at: new Date().toISOString() };\n if (args.name !== undefined) updates.name = args.name;\n if (args.destination_url !== undefined) updates.destination_url = args.destination_url;\n if (args.is_active !== undefined) updates.is_active = args.is_active;\n if (args.landing_page_title !== undefined) updates.landing_page_title = args.landing_page_title;\n if (args.landing_page_description !== undefined) updates.landing_page_description = args.landing_page_description;\n if (args.tags !== undefined) updates.tags = args.tags;\n\n const { data, error } = await sb.from(\"qr_codes\")\n .update(updates)\n .eq(\"id\", qrId)\n .eq(\"store_id\", sid)\n .select()\n .single();\n return error ? { success: false, error: error.message } : { success: true, data };\n }\n\n // ---- SCANS: list scan history for a QR code ----\n case \"scans\": {\n const qrId = args.qr_code_id as string;\n if (!qrId) return { success: false, error: \"qr_code_id is required\" };\n let q = sb.from(\"qr_scans\")\n .select(\"id, scanned_at, is_first_scan, city, region, country, device_type, browser_name, converted, conversion_value, operation\")\n .eq(\"qr_code_id\", qrId)\n .eq(\"store_id\", sid)\n .order(\"scanned_at\", { ascending: false });\n q = q.limit(args.limit as number || 50);\n const { data, error } = await q;\n return error ? { success: false, error: error.message } : { success: true, count: data?.length, data };\n }\n\n // ---- ANALYTICS: scan analytics summary for a QR code ----\n case \"analytics\": {\n const qrId = args.qr_code_id as string;\n if (!qrId) return { success: false, error: \"qr_code_id is required\" };\n const { data: scans, error } = await sb.from(\"qr_scans\")\n .select(\"city, region, country, device_type, converted, conversion_value, scanned_at\")\n .eq(\"qr_code_id\", qrId)\n .eq(\"store_id\", sid);\n if (error) return { success: false, error: error.message };\n\n const scanList = scans || [];\n const conversions = scanList.filter(s => s.converted);\n const byCity: Record<string, number> = {};\n const byDevice: Record<string, number> = {};\n for (const s of scanList) {\n if (s.city) byCity[s.city] = (byCity[s.city] || 0) + 1;\n if (s.device_type) byDevice[s.device_type] = (byDevice[s.device_type] || 0) + 1;\n }\n\n return {\n success: true,\n data: {\n total_scans: scanList.length,\n conversions: conversions.length,\n conversion_rate: scanList.length > 0 ? Math.round((conversions.length / scanList.length) * 1000) / 10 : 0,\n total_revenue: conversions.reduce((s, c) => s + (Number(c.conversion_value) || 0), 0),\n by_city: byCity,\n by_device: byDevice,\n },\n };\n }\n\n default:\n return { success: false, error: `Unknown qr_codes action: ${args.action}. Valid: list, get, create, update, scans, analytics` };\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { SupabaseClient } from "@supabase/supabase-js";
|
|
2
|
+
type Result = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
data?: unknown;
|
|
5
|
+
error?: string;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
};
|
|
8
|
+
export declare function handleReviews(sb: SupabaseClient, args: Record<string, unknown>, storeId?: string): Promise<Result>;
|
|
9
|
+
export {};
|