@instockng/api-client 1.0.5 → 1.0.7
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/apps/backend/src/lib/meta-capi.d.ts +1 -1
- package/dist/apps/backend/src/lib/meta-capi.js +1 -1
- package/dist/apps/backend/src/lib/order-recovery.d.ts +86 -0
- package/dist/apps/backend/src/lib/order-recovery.js +7 -2
- package/dist/apps/backend/src/notifications/producers/meta-capi-producer.d.ts +7 -0
- package/dist/apps/backend/src/notifications/producers/meta-capi-producer.js +41 -0
- package/dist/apps/backend/src/routes/admin/orders.d.ts +310 -20
- package/dist/apps/backend/src/routes/admin/orders.js +26 -2
- package/dist/apps/backend/src/routes/public/orders.d.ts +288 -6
- package/dist/apps/backend/src/routes/public/orders.js +1 -1
- package/dist/apps/backend/src/validators/order.d.ts +6 -37
- package/dist/apps/backend/src/validators/order.js +6 -7
- package/dist/enum-types.d.ts +8 -0
- package/dist/enum-types.js +5 -0
- package/dist/fetchers/carts.js +5 -0
- package/dist/fetchers/orders.d.ts +258 -1
- package/dist/hooks/admin/abandoned-carts.js +12 -8
- package/dist/hooks/admin/brands.js +15 -10
- package/dist/hooks/admin/customers.js +3 -2
- package/dist/hooks/admin/delivery-zones.js +24 -16
- package/dist/hooks/admin/discount-codes.js +24 -16
- package/dist/hooks/admin/inventory.js +15 -10
- package/dist/hooks/admin/orders.d.ts +285 -3
- package/dist/hooks/admin/orders.js +24 -15
- package/dist/hooks/admin/products.js +15 -10
- package/dist/hooks/admin/stats.js +3 -2
- package/dist/hooks/admin/variants.js +18 -12
- package/dist/hooks/admin/warehouses.js +15 -10
- package/dist/hooks/public/orders.d.ts +258 -1
- package/dist/hooks/useApiConfig.d.ts +2 -1
- package/dist/hooks/useApiConfig.js +2 -2
- package/dist/packages/api-client/src/enum-types.d.ts +8 -0
- package/dist/packages/api-client/src/enum-types.js +5 -0
- package/dist/packages/api-client/src/fetchers/carts.js +5 -0
- package/dist/packages/api-client/src/fetchers/orders.d.ts +258 -1
- package/dist/packages/api-client/src/hooks/admin/orders.d.ts +285 -3
- package/dist/packages/api-client/src/hooks/admin/orders.js +7 -4
- package/dist/packages/api-client/src/hooks/public/orders.d.ts +258 -1
- package/dist/packages/api-client/src/rpc-client.d.ts +891 -319
- package/dist/packages/api-client/src/types.d.ts +1 -4
- package/dist/packages/api-client/src/utils/query-keys.d.ts +1 -1
- package/dist/packages/api-client/src/utils/query-keys.js +1 -1
- package/dist/provider.d.ts +7 -4
- package/dist/provider.js +5 -3
- package/dist/rpc-client.d.ts +891 -319
- package/dist/types.d.ts +1 -0
- package/dist/utils/query-keys.d.ts +1 -1
- package/dist/utils/query-keys.js +1 -1
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Sends server-side events to Meta for conversion tracking.
|
|
5
5
|
* Used alongside browser pixel for maximum reliability and iOS 14+ compliance.
|
|
6
6
|
*/
|
|
7
|
-
export type MetaEventName = 'AddToCart' | 'InitiateCheckout' | 'Purchase' | 'ViewContent';
|
|
7
|
+
export type MetaEventName = 'AddToCart' | 'InitiateCheckout' | 'Purchase' | 'ViewContent' | 'ConfirmedPurchase';
|
|
8
8
|
export interface MetaCapiQueueMessage {
|
|
9
9
|
pixelId: string;
|
|
10
10
|
eventName: MetaEventName;
|
|
@@ -114,7 +114,7 @@ export async function sendMetaCapiEvent(accessToken, message) {
|
|
|
114
114
|
*/
|
|
115
115
|
export function generateEventId(type, id, suffix) {
|
|
116
116
|
if (type === 'order') {
|
|
117
|
-
return `order_${id}`;
|
|
117
|
+
return suffix ? `order_${id}_${suffix}` : `order_${id}`;
|
|
118
118
|
}
|
|
119
119
|
return suffix ? `cart_${id}_${suffix}` : `cart_${id}`;
|
|
120
120
|
}
|
|
@@ -282,6 +282,92 @@ export declare function prepareOrderForRecoveryAttempt(prisma: PrismaClient, ord
|
|
|
282
282
|
* Convert prospect order back to pending when customer confirms
|
|
283
283
|
*/
|
|
284
284
|
export declare function confirmProspectOrder(prisma: PrismaClient, orderId: string, userActionToken: string): Promise<{
|
|
285
|
+
brand: {
|
|
286
|
+
name: string;
|
|
287
|
+
id: string;
|
|
288
|
+
slug: string;
|
|
289
|
+
logoUrl: string | null;
|
|
290
|
+
siteUrl: string;
|
|
291
|
+
domain: string;
|
|
292
|
+
metaPixelId: string | null;
|
|
293
|
+
createdAt: Date;
|
|
294
|
+
updatedAt: Date;
|
|
295
|
+
deletedAt: Date | null;
|
|
296
|
+
};
|
|
297
|
+
deliveryZone: {
|
|
298
|
+
state: {
|
|
299
|
+
name: string;
|
|
300
|
+
id: string;
|
|
301
|
+
createdAt: Date;
|
|
302
|
+
updatedAt: Date;
|
|
303
|
+
deletedAt: Date | null;
|
|
304
|
+
isActive: boolean;
|
|
305
|
+
};
|
|
306
|
+
} & {
|
|
307
|
+
name: string;
|
|
308
|
+
id: string;
|
|
309
|
+
createdAt: Date;
|
|
310
|
+
updatedAt: Date;
|
|
311
|
+
deletedAt: Date | null;
|
|
312
|
+
brandId: string | null;
|
|
313
|
+
stateId: string;
|
|
314
|
+
deliveryCost: import("@prisma/client/runtime/library").Decimal;
|
|
315
|
+
freeShippingThreshold: import("@prisma/client/runtime/library").Decimal | null;
|
|
316
|
+
allowCOD: boolean;
|
|
317
|
+
allowOnline: boolean;
|
|
318
|
+
waybillOnly: boolean;
|
|
319
|
+
estimatedDays: number | null;
|
|
320
|
+
isActive: boolean;
|
|
321
|
+
};
|
|
322
|
+
items: ({
|
|
323
|
+
warehouse: {
|
|
324
|
+
name: string;
|
|
325
|
+
id: string;
|
|
326
|
+
createdAt: Date;
|
|
327
|
+
updatedAt: Date;
|
|
328
|
+
deletedAt: Date | null;
|
|
329
|
+
isActive: boolean;
|
|
330
|
+
address: string | null;
|
|
331
|
+
city: string | null;
|
|
332
|
+
state: string | null;
|
|
333
|
+
};
|
|
334
|
+
variant: {
|
|
335
|
+
product: {
|
|
336
|
+
name: string;
|
|
337
|
+
id: string;
|
|
338
|
+
slug: string;
|
|
339
|
+
createdAt: Date;
|
|
340
|
+
updatedAt: Date;
|
|
341
|
+
deletedAt: Date | null;
|
|
342
|
+
brandId: string;
|
|
343
|
+
isActive: boolean;
|
|
344
|
+
description: string | null;
|
|
345
|
+
thumbnailUrl: string | null;
|
|
346
|
+
quantityDiscounts: import("@prisma/client/runtime/library").JsonValue | null;
|
|
347
|
+
};
|
|
348
|
+
} & {
|
|
349
|
+
name: string | null;
|
|
350
|
+
id: string;
|
|
351
|
+
createdAt: Date;
|
|
352
|
+
updatedAt: Date;
|
|
353
|
+
deletedAt: Date | null;
|
|
354
|
+
isActive: boolean;
|
|
355
|
+
thumbnailUrl: string | null;
|
|
356
|
+
productId: string;
|
|
357
|
+
sku: string;
|
|
358
|
+
price: import("@prisma/client/runtime/library").Decimal;
|
|
359
|
+
trackInventory: boolean;
|
|
360
|
+
lowStockThreshold: number | null;
|
|
361
|
+
};
|
|
362
|
+
} & {
|
|
363
|
+
id: string;
|
|
364
|
+
orderId: string;
|
|
365
|
+
variantId: string;
|
|
366
|
+
warehouseId: string | null;
|
|
367
|
+
quantity: number;
|
|
368
|
+
priceAtPurchase: import("@prisma/client/runtime/library").Decimal;
|
|
369
|
+
})[];
|
|
370
|
+
} & {
|
|
285
371
|
id: string;
|
|
286
372
|
email: string | null;
|
|
287
373
|
createdAt: Date;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { OrderStatus, ProspectReason, NoteType } from '@prisma/client';
|
|
2
2
|
import { subHours, addHours } from 'date-fns';
|
|
3
3
|
import { generateDiscountCode } from './discount';
|
|
4
|
+
import { ORDER_INCLUDE_FULL } from './cart-helpers';
|
|
4
5
|
// Recovery schedule configuration
|
|
5
6
|
// Note: First email sent immediately after marking as prospect (since manual contact already attempted)
|
|
6
7
|
export const PROSPECT_RECOVERY_SCHEDULE = [
|
|
@@ -200,7 +201,7 @@ export async function confirmProspectOrder(prisma, orderId, userActionToken) {
|
|
|
200
201
|
updateData.discountAmount = discountAmount;
|
|
201
202
|
}
|
|
202
203
|
// Update order status
|
|
203
|
-
|
|
204
|
+
await tx.order.update({
|
|
204
205
|
where: { id: orderId },
|
|
205
206
|
data: updateData
|
|
206
207
|
});
|
|
@@ -216,7 +217,11 @@ export async function confirmProspectOrder(prisma, orderId, userActionToken) {
|
|
|
216
217
|
}
|
|
217
218
|
}
|
|
218
219
|
});
|
|
219
|
-
|
|
220
|
+
// Return the full order with all relations
|
|
221
|
+
return tx.order.findUnique({
|
|
222
|
+
where: { id: orderId },
|
|
223
|
+
include: ORDER_INCLUDE_FULL
|
|
224
|
+
});
|
|
220
225
|
});
|
|
221
226
|
}
|
|
222
227
|
/**
|
|
@@ -53,3 +53,10 @@ export declare function enqueuePurchaseEvent(env: Env, order: OrderDBResponse, o
|
|
|
53
53
|
fbc?: string;
|
|
54
54
|
fbp?: string;
|
|
55
55
|
}): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Queue a ConfirmedPurchase event when order is delivered & paid
|
|
58
|
+
*
|
|
59
|
+
* This event tracks successful order completion (delivered + paid),
|
|
60
|
+
* which is a higher value conversion signal than initial purchase.
|
|
61
|
+
*/
|
|
62
|
+
export declare function enqueueConfirmedPurchaseEvent(env: Env, order: OrderDBResponse): Promise<void>;
|
|
@@ -123,3 +123,44 @@ export async function enqueuePurchaseEvent(env, order, options) {
|
|
|
123
123
|
await env.META_CAPI_QUEUE.send(message);
|
|
124
124
|
console.log(`[Meta CAPI] Queued Purchase event: ${message.eventId}`);
|
|
125
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* Queue a ConfirmedPurchase event when order is delivered & paid
|
|
128
|
+
*
|
|
129
|
+
* This event tracks successful order completion (delivered + paid),
|
|
130
|
+
* which is a higher value conversion signal than initial purchase.
|
|
131
|
+
*/
|
|
132
|
+
export async function enqueueConfirmedPurchaseEvent(env, order) {
|
|
133
|
+
if (!env.META_CAPI_QUEUE) {
|
|
134
|
+
console.warn('[Meta CAPI] Queue not configured, skipping ConfirmedPurchase event');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const pixelId = order.brand.metaPixelId;
|
|
138
|
+
if (!pixelId) {
|
|
139
|
+
console.log('[Meta CAPI] No pixel ID for brand, skipping ConfirmedPurchase event');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const message = {
|
|
143
|
+
pixelId,
|
|
144
|
+
eventName: 'ConfirmedPurchase',
|
|
145
|
+
eventId: generateEventId('order', order.id, 'confirmed'),
|
|
146
|
+
eventTime: Math.floor(Date.now() / 1000),
|
|
147
|
+
eventSourceUrl: order.brand.siteUrl,
|
|
148
|
+
userData: {
|
|
149
|
+
email: order.email || undefined,
|
|
150
|
+
phone: order.phone,
|
|
151
|
+
firstName: order.firstName,
|
|
152
|
+
lastName: order.lastName,
|
|
153
|
+
city: order.city,
|
|
154
|
+
country: 'ng', // Nigeria
|
|
155
|
+
},
|
|
156
|
+
customData: {
|
|
157
|
+
value: Number(order.totalPrice),
|
|
158
|
+
currency: 'NGN',
|
|
159
|
+
contentIds: order.items.map((item) => item.variant.sku),
|
|
160
|
+
contentType: 'product',
|
|
161
|
+
numItems: order.items.reduce((sum, item) => sum + item.quantity, 0),
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
await env.META_CAPI_QUEUE.send(message);
|
|
165
|
+
console.log(`[Meta CAPI] Queued ConfirmedPurchase event: ${message.eventId}`);
|
|
166
|
+
}
|
|
@@ -572,20 +572,6 @@ declare const app: import("hono/hono-base").HonoBase<AppContext, {
|
|
|
572
572
|
} & {
|
|
573
573
|
"/:id": {
|
|
574
574
|
$get: {
|
|
575
|
-
input: {
|
|
576
|
-
param: {
|
|
577
|
-
id: string;
|
|
578
|
-
};
|
|
579
|
-
};
|
|
580
|
-
output: {
|
|
581
|
-
error: {
|
|
582
|
-
code: string;
|
|
583
|
-
message: string;
|
|
584
|
-
};
|
|
585
|
-
};
|
|
586
|
-
outputFormat: "json";
|
|
587
|
-
status: 404;
|
|
588
|
-
} | {
|
|
589
575
|
input: {
|
|
590
576
|
param: {
|
|
591
577
|
id: string;
|
|
@@ -851,6 +837,20 @@ declare const app: import("hono/hono-base").HonoBase<AppContext, {
|
|
|
851
837
|
};
|
|
852
838
|
outputFormat: "json";
|
|
853
839
|
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
840
|
+
} | {
|
|
841
|
+
input: {
|
|
842
|
+
param: {
|
|
843
|
+
id: string;
|
|
844
|
+
};
|
|
845
|
+
};
|
|
846
|
+
output: {
|
|
847
|
+
error: {
|
|
848
|
+
code: string;
|
|
849
|
+
message: string;
|
|
850
|
+
};
|
|
851
|
+
};
|
|
852
|
+
outputFormat: "json";
|
|
853
|
+
status: 404;
|
|
854
854
|
} | {
|
|
855
855
|
input: {
|
|
856
856
|
param: {
|
|
@@ -1438,18 +1438,308 @@ declare const app: import("hono/hono-base").HonoBase<AppContext, {
|
|
|
1438
1438
|
id: string;
|
|
1439
1439
|
};
|
|
1440
1440
|
};
|
|
1441
|
-
output: {
|
|
1442
|
-
|
|
1443
|
-
|
|
1441
|
+
output: {
|
|
1442
|
+
subtotal: number;
|
|
1443
|
+
deliveryCharge: number;
|
|
1444
|
+
totalPrice: number;
|
|
1445
|
+
discountAmount: number;
|
|
1446
|
+
createdAt: string;
|
|
1447
|
+
updatedAt: string;
|
|
1448
|
+
deletedAt: string;
|
|
1449
|
+
prospectSince: string;
|
|
1450
|
+
lastRecoveryAttemptAt: string;
|
|
1451
|
+
brand: {
|
|
1452
|
+
createdAt: string;
|
|
1453
|
+
updatedAt: string;
|
|
1454
|
+
deletedAt: string;
|
|
1455
|
+
name: string;
|
|
1456
|
+
id: string;
|
|
1457
|
+
slug: string;
|
|
1458
|
+
logoUrl: string | null;
|
|
1459
|
+
siteUrl: string;
|
|
1460
|
+
domain: string;
|
|
1461
|
+
metaPixelId: string | null;
|
|
1462
|
+
};
|
|
1463
|
+
deliveryZone: {
|
|
1464
|
+
deliveryCost: number;
|
|
1465
|
+
freeShippingThreshold: number;
|
|
1466
|
+
createdAt: string;
|
|
1467
|
+
updatedAt: string;
|
|
1468
|
+
deletedAt: string;
|
|
1469
|
+
state: {
|
|
1470
|
+
createdAt: string;
|
|
1471
|
+
updatedAt: string;
|
|
1472
|
+
deletedAt: string;
|
|
1473
|
+
name: string;
|
|
1474
|
+
id: string;
|
|
1475
|
+
isActive: boolean;
|
|
1476
|
+
};
|
|
1477
|
+
name: string;
|
|
1478
|
+
id: string;
|
|
1479
|
+
brandId: string | null;
|
|
1480
|
+
stateId: string;
|
|
1481
|
+
allowCOD: boolean;
|
|
1482
|
+
allowOnline: boolean;
|
|
1483
|
+
waybillOnly: boolean;
|
|
1484
|
+
estimatedDays: number | null;
|
|
1485
|
+
isActive: boolean;
|
|
1486
|
+
};
|
|
1487
|
+
items: {
|
|
1488
|
+
priceAtPurchase: number;
|
|
1489
|
+
variant: {
|
|
1490
|
+
price: number;
|
|
1491
|
+
createdAt: string;
|
|
1492
|
+
updatedAt: string;
|
|
1493
|
+
deletedAt: string;
|
|
1494
|
+
product: {
|
|
1495
|
+
createdAt: string;
|
|
1496
|
+
updatedAt: string;
|
|
1497
|
+
deletedAt: string;
|
|
1498
|
+
name: string;
|
|
1499
|
+
id: string;
|
|
1500
|
+
slug: string;
|
|
1501
|
+
brandId: string;
|
|
1502
|
+
isActive: boolean;
|
|
1503
|
+
description: string | null;
|
|
1504
|
+
thumbnailUrl: string | null;
|
|
1505
|
+
quantityDiscounts: string | number | boolean | {
|
|
1506
|
+
[x: string]: string | number | boolean | /*elided*/ any | {
|
|
1507
|
+
[x: number]: string | number | boolean | /*elided*/ any | /*elided*/ any;
|
|
1508
|
+
length: number;
|
|
1509
|
+
toString: never;
|
|
1510
|
+
toLocaleString: never;
|
|
1511
|
+
pop: never;
|
|
1512
|
+
push: never;
|
|
1513
|
+
concat: never;
|
|
1514
|
+
join: never;
|
|
1515
|
+
reverse: never;
|
|
1516
|
+
shift: never;
|
|
1517
|
+
slice: never;
|
|
1518
|
+
sort: never;
|
|
1519
|
+
splice: never;
|
|
1520
|
+
unshift: never;
|
|
1521
|
+
indexOf: never;
|
|
1522
|
+
lastIndexOf: never;
|
|
1523
|
+
every: never;
|
|
1524
|
+
some: never;
|
|
1525
|
+
forEach: never;
|
|
1526
|
+
map: never;
|
|
1527
|
+
filter: never;
|
|
1528
|
+
reduce: never;
|
|
1529
|
+
reduceRight: never;
|
|
1530
|
+
find: never;
|
|
1531
|
+
findIndex: never;
|
|
1532
|
+
fill: never;
|
|
1533
|
+
copyWithin: never;
|
|
1534
|
+
entries: never;
|
|
1535
|
+
keys: never;
|
|
1536
|
+
values: never;
|
|
1537
|
+
includes: never;
|
|
1538
|
+
flatMap: never;
|
|
1539
|
+
flat: never;
|
|
1540
|
+
[Symbol.iterator]: never;
|
|
1541
|
+
readonly [Symbol.unscopables]: {
|
|
1542
|
+
[x: number]: boolean;
|
|
1543
|
+
length?: boolean;
|
|
1544
|
+
toString?: boolean;
|
|
1545
|
+
toLocaleString?: boolean;
|
|
1546
|
+
pop?: boolean;
|
|
1547
|
+
push?: boolean;
|
|
1548
|
+
concat?: boolean;
|
|
1549
|
+
join?: boolean;
|
|
1550
|
+
reverse?: boolean;
|
|
1551
|
+
shift?: boolean;
|
|
1552
|
+
slice?: boolean;
|
|
1553
|
+
sort?: boolean;
|
|
1554
|
+
splice?: boolean;
|
|
1555
|
+
unshift?: boolean;
|
|
1556
|
+
indexOf?: boolean;
|
|
1557
|
+
lastIndexOf?: boolean;
|
|
1558
|
+
every?: boolean;
|
|
1559
|
+
some?: boolean;
|
|
1560
|
+
forEach?: boolean;
|
|
1561
|
+
map?: boolean;
|
|
1562
|
+
filter?: boolean;
|
|
1563
|
+
reduce?: boolean;
|
|
1564
|
+
reduceRight?: boolean;
|
|
1565
|
+
find?: boolean;
|
|
1566
|
+
findIndex?: boolean;
|
|
1567
|
+
fill?: boolean;
|
|
1568
|
+
copyWithin?: boolean;
|
|
1569
|
+
entries?: boolean;
|
|
1570
|
+
keys?: boolean;
|
|
1571
|
+
values?: boolean;
|
|
1572
|
+
includes?: boolean;
|
|
1573
|
+
flatMap?: boolean;
|
|
1574
|
+
flat?: boolean;
|
|
1575
|
+
};
|
|
1576
|
+
};
|
|
1577
|
+
} | {
|
|
1578
|
+
[x: number]: string | number | boolean | {
|
|
1579
|
+
[x: string]: string | number | boolean | /*elided*/ any | /*elided*/ any;
|
|
1580
|
+
} | /*elided*/ any;
|
|
1581
|
+
length: number;
|
|
1582
|
+
toString: never;
|
|
1583
|
+
toLocaleString: never;
|
|
1584
|
+
pop: never;
|
|
1585
|
+
push: never;
|
|
1586
|
+
concat: never;
|
|
1587
|
+
join: never;
|
|
1588
|
+
reverse: never;
|
|
1589
|
+
shift: never;
|
|
1590
|
+
slice: never;
|
|
1591
|
+
sort: never;
|
|
1592
|
+
splice: never;
|
|
1593
|
+
unshift: never;
|
|
1594
|
+
indexOf: never;
|
|
1595
|
+
lastIndexOf: never;
|
|
1596
|
+
every: never;
|
|
1597
|
+
some: never;
|
|
1598
|
+
forEach: never;
|
|
1599
|
+
map: never;
|
|
1600
|
+
filter: never;
|
|
1601
|
+
reduce: never;
|
|
1602
|
+
reduceRight: never;
|
|
1603
|
+
find: never;
|
|
1604
|
+
findIndex: never;
|
|
1605
|
+
fill: never;
|
|
1606
|
+
copyWithin: never;
|
|
1607
|
+
entries: never;
|
|
1608
|
+
keys: never;
|
|
1609
|
+
values: never;
|
|
1610
|
+
includes: never;
|
|
1611
|
+
flatMap: never;
|
|
1612
|
+
flat: never;
|
|
1613
|
+
[Symbol.iterator]: never;
|
|
1614
|
+
readonly [Symbol.unscopables]: {
|
|
1615
|
+
[x: number]: boolean;
|
|
1616
|
+
length?: boolean;
|
|
1617
|
+
toString?: boolean;
|
|
1618
|
+
toLocaleString?: boolean;
|
|
1619
|
+
pop?: boolean;
|
|
1620
|
+
push?: boolean;
|
|
1621
|
+
concat?: boolean;
|
|
1622
|
+
join?: boolean;
|
|
1623
|
+
reverse?: boolean;
|
|
1624
|
+
shift?: boolean;
|
|
1625
|
+
slice?: boolean;
|
|
1626
|
+
sort?: boolean;
|
|
1627
|
+
splice?: boolean;
|
|
1628
|
+
unshift?: boolean;
|
|
1629
|
+
indexOf?: boolean;
|
|
1630
|
+
lastIndexOf?: boolean;
|
|
1631
|
+
every?: boolean;
|
|
1632
|
+
some?: boolean;
|
|
1633
|
+
forEach?: boolean;
|
|
1634
|
+
map?: boolean;
|
|
1635
|
+
filter?: boolean;
|
|
1636
|
+
reduce?: boolean;
|
|
1637
|
+
reduceRight?: boolean;
|
|
1638
|
+
find?: boolean;
|
|
1639
|
+
findIndex?: boolean;
|
|
1640
|
+
fill?: boolean;
|
|
1641
|
+
copyWithin?: boolean;
|
|
1642
|
+
entries?: boolean;
|
|
1643
|
+
keys?: boolean;
|
|
1644
|
+
values?: boolean;
|
|
1645
|
+
includes?: boolean;
|
|
1646
|
+
flatMap?: boolean;
|
|
1647
|
+
flat?: boolean;
|
|
1648
|
+
};
|
|
1649
|
+
};
|
|
1650
|
+
};
|
|
1651
|
+
name: string | null;
|
|
1652
|
+
id: string;
|
|
1653
|
+
isActive: boolean;
|
|
1654
|
+
thumbnailUrl: string | null;
|
|
1655
|
+
productId: string;
|
|
1656
|
+
sku: string;
|
|
1657
|
+
trackInventory: boolean;
|
|
1658
|
+
lowStockThreshold: number | null;
|
|
1659
|
+
};
|
|
1660
|
+
warehouse: {
|
|
1661
|
+
createdAt: string;
|
|
1662
|
+
updatedAt: string;
|
|
1663
|
+
deletedAt: string;
|
|
1664
|
+
name: string;
|
|
1665
|
+
id: string;
|
|
1666
|
+
isActive: boolean;
|
|
1667
|
+
address: string | null;
|
|
1668
|
+
city: string | null;
|
|
1669
|
+
state: string | null;
|
|
1670
|
+
};
|
|
1671
|
+
id: string;
|
|
1672
|
+
orderId: string;
|
|
1673
|
+
variantId: string;
|
|
1674
|
+
warehouseId: string | null;
|
|
1675
|
+
quantity: number;
|
|
1676
|
+
}[];
|
|
1677
|
+
id: string;
|
|
1678
|
+
email: string | null;
|
|
1679
|
+
brandId: string;
|
|
1680
|
+
deliveryZoneId: string;
|
|
1681
|
+
recoveryAttempts: number;
|
|
1682
|
+
recoveryDiscountCodeId: string | null;
|
|
1683
|
+
wasRecovered: boolean;
|
|
1684
|
+
estimatedDays: number | null;
|
|
1685
|
+
orderNumber: number;
|
|
1686
|
+
firstName: string;
|
|
1687
|
+
lastName: string;
|
|
1688
|
+
phone: string;
|
|
1689
|
+
address: string;
|
|
1690
|
+
city: string;
|
|
1691
|
+
discountCodeId: string | null;
|
|
1692
|
+
paymentMethod: import("@prisma/client").$Enums.PaymentMethod;
|
|
1693
|
+
paystackReference: string | null;
|
|
1694
|
+
status: import("@prisma/client").$Enums.OrderStatus;
|
|
1695
|
+
cancellationReason: string | null;
|
|
1696
|
+
prospectReason: import("@prisma/client").$Enums.ProspectReason | null;
|
|
1697
|
+
userActionToken: string;
|
|
1698
|
+
};
|
|
1699
|
+
outputFormat: "json";
|
|
1700
|
+
status: import("hono/utils/http-status").ContentfulStatusCode;
|
|
1444
1701
|
} | {
|
|
1445
1702
|
input: {
|
|
1446
1703
|
param: {
|
|
1447
1704
|
id: string;
|
|
1448
1705
|
};
|
|
1449
1706
|
};
|
|
1450
|
-
output: {
|
|
1451
|
-
|
|
1452
|
-
|
|
1707
|
+
output: {
|
|
1708
|
+
error: {
|
|
1709
|
+
code: string;
|
|
1710
|
+
message: string;
|
|
1711
|
+
};
|
|
1712
|
+
};
|
|
1713
|
+
outputFormat: "json";
|
|
1714
|
+
status: 404;
|
|
1715
|
+
} | {
|
|
1716
|
+
input: {
|
|
1717
|
+
param: {
|
|
1718
|
+
id: string;
|
|
1719
|
+
};
|
|
1720
|
+
};
|
|
1721
|
+
output: {
|
|
1722
|
+
error: {
|
|
1723
|
+
code: string;
|
|
1724
|
+
message: string;
|
|
1725
|
+
};
|
|
1726
|
+
};
|
|
1727
|
+
outputFormat: "json";
|
|
1728
|
+
status: 400;
|
|
1729
|
+
} | {
|
|
1730
|
+
input: {
|
|
1731
|
+
param: {
|
|
1732
|
+
id: string;
|
|
1733
|
+
};
|
|
1734
|
+
};
|
|
1735
|
+
output: {
|
|
1736
|
+
error: {
|
|
1737
|
+
code: string;
|
|
1738
|
+
message: string;
|
|
1739
|
+
};
|
|
1740
|
+
};
|
|
1741
|
+
outputFormat: "json";
|
|
1742
|
+
status: 500;
|
|
1453
1743
|
};
|
|
1454
1744
|
};
|
|
1455
1745
|
} & {
|
|
@@ -139,6 +139,7 @@ const app = new Hono()
|
|
|
139
139
|
{ phone: { contains: query.search } },
|
|
140
140
|
{ firstName: { contains: query.search, mode: 'insensitive' } },
|
|
141
141
|
{ lastName: { contains: query.search, mode: 'insensitive' } },
|
|
142
|
+
{ address: { contains: query.search, mode: 'insensitive' } },
|
|
142
143
|
].filter((item) => Object.values(item).some((v) => v !== undefined));
|
|
143
144
|
}
|
|
144
145
|
if (query.startDate)
|
|
@@ -267,7 +268,7 @@ const app = new Hono()
|
|
|
267
268
|
address: input.address ?? order.address,
|
|
268
269
|
city: input.city ?? order.city,
|
|
269
270
|
deliveryCharge,
|
|
270
|
-
paymentMethod: input.paymentMethod ?? order.paymentMethod,
|
|
271
|
+
paymentMethod: (input.paymentMethod ?? order.paymentMethod),
|
|
271
272
|
paystackReference: input.paystackReference ?? order.paystackReference,
|
|
272
273
|
totalPrice,
|
|
273
274
|
},
|
|
@@ -477,8 +478,31 @@ const app = new Hono()
|
|
|
477
478
|
catch (error) {
|
|
478
479
|
console.error('Failed to queue order status update notification:', error);
|
|
479
480
|
}
|
|
481
|
+
// Queue Meta CAPI ConfirmedPurchase event when order is delivered & paid
|
|
482
|
+
if (newStatus === 'delivered' && previousStatus !== 'delivered') {
|
|
483
|
+
try {
|
|
484
|
+
const { enqueueConfirmedPurchaseEvent } = await import('../../notifications/producers/meta-capi-producer');
|
|
485
|
+
// Fetch full order details with items for the CAPI event
|
|
486
|
+
const fullOrder = await prisma.order.findFirst({
|
|
487
|
+
where: { id, deletedAt: null },
|
|
488
|
+
include: ORDER_INCLUDE_FULL,
|
|
489
|
+
});
|
|
490
|
+
if (fullOrder) {
|
|
491
|
+
await enqueueConfirmedPurchaseEvent(c.env, fullOrder);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
catch (error) {
|
|
495
|
+
console.error('Failed to queue Meta CAPI ConfirmedPurchase event:', error);
|
|
496
|
+
// Don't fail the status update if CAPI queuing fails
|
|
497
|
+
}
|
|
498
|
+
}
|
|
480
499
|
}
|
|
481
|
-
return
|
|
500
|
+
// Fetch updated order to return
|
|
501
|
+
const updatedOrder = await prisma.order.findFirst({
|
|
502
|
+
where: { id, deletedAt: null },
|
|
503
|
+
include: ORDER_INCLUDE_FULL,
|
|
504
|
+
});
|
|
505
|
+
return c.json(formatOrderResponse(updatedOrder));
|
|
482
506
|
}
|
|
483
507
|
catch (error) {
|
|
484
508
|
return c.json({
|