@stacksjs/commerce 0.70.55 → 0.70.57
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/package.json +10 -7
- package/src/carts/destroy.ts +0 -54
- package/src/carts/fetch.ts +0 -20
- package/src/carts/index.ts +0 -13
- package/src/carts/store.ts +0 -75
- package/src/carts/update.ts +0 -78
- package/src/coupons/destroy.ts +0 -49
- package/src/coupons/fetch.ts +0 -510
- package/src/coupons/index.ts +0 -30
- package/src/coupons/store.ts +0 -46
- package/src/coupons/update.ts +0 -147
- package/src/customers/destroy.ts +0 -62
- package/src/customers/fetch.ts +0 -20
- package/src/customers/index.ts +0 -17
- package/src/customers/store.ts +0 -45
- package/src/customers/update.ts +0 -44
- package/src/devices/destroy.ts +0 -54
- package/src/devices/export.ts +0 -98
- package/src/devices/fetch.ts +0 -125
- package/src/devices/index.ts +0 -31
- package/src/devices/store.ts +0 -82
- package/src/devices/update.ts +0 -125
- package/src/errors/destroy.ts +0 -54
- package/src/errors/fetch.ts +0 -197
- package/src/errors/index.ts +0 -28
- package/src/errors/update.ts +0 -116
- package/src/gift-cards/destroy.ts +0 -87
- package/src/gift-cards/fetch.ts +0 -431
- package/src/gift-cards/index.ts +0 -26
- package/src/gift-cards/store.ts +0 -56
- package/src/gift-cards/update.ts +0 -102
- package/src/index.ts +0 -78
- package/src/orders/destroy.ts +0 -111
- package/src/orders/events.ts +0 -121
- package/src/orders/export.ts +0 -158
- package/src/orders/fetch.ts +0 -379
- package/src/orders/guards.ts +0 -261
- package/src/orders/index.ts +0 -91
- package/src/orders/place-order.ts +0 -274
- package/src/orders/store.ts +0 -51
- package/src/orders/totals.ts +0 -190
- package/src/orders/update.ts +0 -164
- package/src/orders/webhook.ts +0 -312
- package/src/payments/destroy.ts +0 -56
- package/src/payments/fetch.ts +0 -288
- package/src/payments/index.ts +0 -16
- package/src/payments/store.ts +0 -63
- package/src/payments/update.ts +0 -52
- package/src/product.ts +0 -0
- package/src/products/categories/destroy.ts +0 -103
- package/src/products/categories/fetch.ts +0 -285
- package/src/products/categories/index.ts +0 -36
- package/src/products/categories/store.ts +0 -87
- package/src/products/categories/update.ts +0 -251
- package/src/products/index.ts +0 -35
- package/src/products/items/destroy.ts +0 -54
- package/src/products/items/fetch.ts +0 -282
- package/src/products/items/index.ts +0 -26
- package/src/products/items/store.ts +0 -84
- package/src/products/items/update.ts +0 -324
- package/src/products/manufacturers/destroy.ts +0 -56
- package/src/products/manufacturers/fetch.ts +0 -117
- package/src/products/manufacturers/index.ts +0 -24
- package/src/products/manufacturers/store.ts +0 -82
- package/src/products/manufacturers/update.ts +0 -113
- package/src/products/reviews/destroy.ts +0 -56
- package/src/products/reviews/fetch.ts +0 -63
- package/src/products/reviews/index.ts +0 -25
- package/src/products/reviews/store.ts +0 -46
- package/src/products/reviews/update.ts +0 -82
- package/src/products/units/destroy.ts +0 -56
- package/src/products/units/fetch.ts +0 -20
- package/src/products/units/index.ts +0 -13
- package/src/products/units/store.ts +0 -162
- package/src/products/units/update.ts +0 -159
- package/src/products/variants/destroy.ts +0 -56
- package/src/products/variants/fetch.ts +0 -20
- package/src/products/variants/index.ts +0 -21
- package/src/products/variants/store.ts +0 -136
- package/src/products/variants/update.ts +0 -104
- package/src/receipts/destroy.ts +0 -54
- package/src/receipts/export.ts +0 -0
- package/src/receipts/fetch.ts +0 -222
- package/src/receipts/index.ts +0 -24
- package/src/receipts/printer.ts +0 -69
- package/src/receipts/store.ts +0 -69
- package/src/receipts/update.ts +0 -124
- package/src/shippings/delivery-routes/destroy.ts +0 -54
- package/src/shippings/delivery-routes/fetch.ts +0 -42
- package/src/shippings/delivery-routes/index.ts +0 -26
- package/src/shippings/delivery-routes/store.ts +0 -69
- package/src/shippings/delivery-routes/update.ts +0 -120
- package/src/shippings/digital-deliveries/destroy.ts +0 -111
- package/src/shippings/digital-deliveries/fetch.ts +0 -20
- package/src/shippings/digital-deliveries/index.ts +0 -26
- package/src/shippings/digital-deliveries/store.ts +0 -76
- package/src/shippings/digital-deliveries/update.ts +0 -129
- package/src/shippings/drivers/destroy.ts +0 -78
- package/src/shippings/drivers/fetch.ts +0 -20
- package/src/shippings/drivers/index.ts +0 -24
- package/src/shippings/drivers/store.ts +0 -69
- package/src/shippings/drivers/update.ts +0 -117
- package/src/shippings/index.ts +0 -39
- package/src/shippings/license-keys/destroy.ts +0 -111
- package/src/shippings/license-keys/fetch.ts +0 -20
- package/src/shippings/license-keys/index.ts +0 -26
- package/src/shippings/license-keys/store.ts +0 -77
- package/src/shippings/license-keys/update.ts +0 -117
- package/src/shippings/shipping-methods/destroy.ts +0 -111
- package/src/shippings/shipping-methods/fetch.ts +0 -62
- package/src/shippings/shipping-methods/index.ts +0 -28
- package/src/shippings/shipping-methods/store.ts +0 -123
- package/src/shippings/shipping-methods/update.ts +0 -120
- package/src/shippings/shipping-rates/destroy.ts +0 -102
- package/src/shippings/shipping-rates/fetch.ts +0 -320
- package/src/shippings/shipping-rates/index.ts +0 -36
- package/src/shippings/shipping-rates/store.ts +0 -102
- package/src/shippings/shipping-rates/update.ts +0 -139
- package/src/shippings/shipping-zones/destroy.ts +0 -111
- package/src/shippings/shipping-zones/fetch.ts +0 -96
- package/src/shippings/shipping-zones/index.ts +0 -26
- package/src/shippings/shipping-zones/store.ts +0 -74
- package/src/shippings/shipping-zones/update.ts +0 -156
- package/src/tax/destroy.ts +0 -54
- package/src/tax/fetch.ts +0 -20
- package/src/tax/index.ts +0 -24
- package/src/tax/store.ts +0 -69
- package/src/tax/update.ts +0 -119
- package/src/tests/coupons.test.ts +0 -90
- package/src/tests/customers.test.ts +0 -39
- package/src/tests/device.test.ts +0 -111
- package/src/tests/digitals.test.ts +0 -31
- package/src/tests/drivers.test.ts +0 -25
- package/src/tests/gift-cards.test.ts +0 -36
- package/src/tests/license.test.ts +0 -31
- package/src/tests/manufacturers.test.ts +0 -80
- package/src/tests/orders.test.ts +0 -25
- package/src/tests/payments.test.ts +0 -75
- package/src/tests/rates.test.ts +0 -367
- package/src/tests/receipts.test.ts +0 -287
- package/src/tests/restaurant.test.ts +0 -522
- package/src/tests/reviews.test.ts +0 -165
- package/src/tests/routes.test.ts +0 -51
- package/src/tests/setup.ts +0 -149
- package/src/tests/shipping.test.ts +0 -88
- package/src/tests/tax.test.ts +0 -25
- package/src/tests/units.test.ts +0 -110
- package/src/tests/variants.test.ts +0 -133
- package/src/tests/waitlist.test.ts +0 -303
- package/src/tests/zones.test.ts +0 -86
- package/src/types.ts +0 -312
- package/src/utils/typed-stats.ts +0 -67
- package/src/waitlists/index.ts +0 -19
- package/src/waitlists/products/destroy.ts +0 -65
- package/src/waitlists/products/export.ts +0 -113
- package/src/waitlists/products/fetch.ts +0 -362
- package/src/waitlists/products/index.ts +0 -33
- package/src/waitlists/products/store.ts +0 -112
- package/src/waitlists/products/update.ts +0 -125
- package/src/waitlists/restaurant/destroy.ts +0 -65
- package/src/waitlists/restaurant/export.ts +0 -107
- package/src/waitlists/restaurant/fetch.ts +0 -538
- package/src/waitlists/restaurant/index.ts +0 -43
- package/src/waitlists/restaurant/store.ts +0 -109
- package/src/waitlists/restaurant/update.ts +0 -198
- /package/dist/{src/coupons → coupons}/destroy.d.ts +0 -0
- /package/dist/{src/coupons → coupons}/fetch.d.ts +0 -0
- /package/dist/{src/coupons → coupons}/index.d.ts +0 -0
- /package/dist/{src/coupons → coupons}/store.d.ts +0 -0
- /package/dist/{src/coupons → coupons}/update.d.ts +0 -0
- /package/dist/{src/customers → customers}/destroy.d.ts +0 -0
- /package/dist/{src/customers → customers}/fetch.d.ts +0 -0
- /package/dist/{src/customers → customers}/index.d.ts +0 -0
- /package/dist/{src/customers → customers}/store.d.ts +0 -0
- /package/dist/{src/customers → customers}/update.d.ts +0 -0
- /package/dist/{src/devices → devices}/destroy.d.ts +0 -0
- /package/dist/{src/devices → devices}/export.d.ts +0 -0
- /package/dist/{src/devices → devices}/fetch.d.ts +0 -0
- /package/dist/{src/devices → devices}/index.d.ts +0 -0
- /package/dist/{src/devices → devices}/store.d.ts +0 -0
- /package/dist/{src/devices → devices}/update.d.ts +0 -0
- /package/dist/{src/errors → errors}/destroy.d.ts +0 -0
- /package/dist/{src/errors → errors}/fetch.d.ts +0 -0
- /package/dist/{src/errors → errors}/index.d.ts +0 -0
- /package/dist/{src/errors → errors}/update.d.ts +0 -0
- /package/dist/{src/gift-cards → gift-cards}/destroy.d.ts +0 -0
- /package/dist/{src/gift-cards → gift-cards}/fetch.d.ts +0 -0
- /package/dist/{src/gift-cards → gift-cards}/index.d.ts +0 -0
- /package/dist/{src/gift-cards → gift-cards}/store.d.ts +0 -0
- /package/dist/{src/gift-cards → gift-cards}/update.d.ts +0 -0
- /package/dist/{src/index.d.ts → index.d.ts} +0 -0
- /package/dist/{src/orders → orders}/destroy.d.ts +0 -0
- /package/dist/{src/orders → orders}/events.d.ts +0 -0
- /package/dist/{src/orders → orders}/export.d.ts +0 -0
- /package/dist/{src/orders → orders}/fetch.d.ts +0 -0
- /package/dist/{src/orders → orders}/guards.d.ts +0 -0
- /package/dist/{src/orders → orders}/index.d.ts +0 -0
- /package/dist/{src/orders → orders}/place-order.d.ts +0 -0
- /package/dist/{src/orders → orders}/store.d.ts +0 -0
- /package/dist/{src/orders → orders}/totals.d.ts +0 -0
- /package/dist/{src/orders → orders}/update.d.ts +0 -0
- /package/dist/{src/orders → orders}/webhook.d.ts +0 -0
- /package/dist/{src/payments → payments}/destroy.d.ts +0 -0
- /package/dist/{src/payments → payments}/fetch.d.ts +0 -0
- /package/dist/{src/payments → payments}/index.d.ts +0 -0
- /package/dist/{src/payments → payments}/store.d.ts +0 -0
- /package/dist/{src/payments → payments}/update.d.ts +0 -0
- /package/dist/{src/products → products}/categories/destroy.d.ts +0 -0
- /package/dist/{src/products → products}/categories/fetch.d.ts +0 -0
- /package/dist/{src/products → products}/categories/index.d.ts +0 -0
- /package/dist/{src/products → products}/categories/store.d.ts +0 -0
- /package/dist/{src/products → products}/categories/update.d.ts +0 -0
- /package/dist/{src/products → products}/index.d.ts +0 -0
- /package/dist/{src/products → products}/items/destroy.d.ts +0 -0
- /package/dist/{src/products → products}/items/fetch.d.ts +0 -0
- /package/dist/{src/products → products}/items/index.d.ts +0 -0
- /package/dist/{src/products → products}/items/store.d.ts +0 -0
- /package/dist/{src/products → products}/items/update.d.ts +0 -0
- /package/dist/{src/products → products}/manufacturers/destroy.d.ts +0 -0
- /package/dist/{src/products → products}/manufacturers/fetch.d.ts +0 -0
- /package/dist/{src/products → products}/manufacturers/index.d.ts +0 -0
- /package/dist/{src/products → products}/manufacturers/store.d.ts +0 -0
- /package/dist/{src/products → products}/manufacturers/update.d.ts +0 -0
- /package/dist/{src/products → products}/reviews/destroy.d.ts +0 -0
- /package/dist/{src/products → products}/reviews/fetch.d.ts +0 -0
- /package/dist/{src/products → products}/reviews/index.d.ts +0 -0
- /package/dist/{src/products → products}/reviews/store.d.ts +0 -0
- /package/dist/{src/products → products}/reviews/update.d.ts +0 -0
- /package/dist/{src/products → products}/units/destroy.d.ts +0 -0
- /package/dist/{src/products → products}/units/fetch.d.ts +0 -0
- /package/dist/{src/products → products}/units/index.d.ts +0 -0
- /package/dist/{src/products → products}/units/store.d.ts +0 -0
- /package/dist/{src/products → products}/units/update.d.ts +0 -0
- /package/dist/{src/products → products}/variants/destroy.d.ts +0 -0
- /package/dist/{src/products → products}/variants/fetch.d.ts +0 -0
- /package/dist/{src/products → products}/variants/index.d.ts +0 -0
- /package/dist/{src/products → products}/variants/store.d.ts +0 -0
- /package/dist/{src/products → products}/variants/update.d.ts +0 -0
- /package/dist/{src/receipts → receipts}/destroy.d.ts +0 -0
- /package/dist/{src/receipts → receipts}/fetch.d.ts +0 -0
- /package/dist/{src/receipts → receipts}/index.d.ts +0 -0
- /package/dist/{src/receipts → receipts}/store.d.ts +0 -0
- /package/dist/{src/receipts → receipts}/update.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/delivery-routes/destroy.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/delivery-routes/fetch.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/delivery-routes/index.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/delivery-routes/store.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/delivery-routes/update.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/digital-deliveries/destroy.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/digital-deliveries/fetch.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/digital-deliveries/index.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/digital-deliveries/store.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/digital-deliveries/update.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/drivers/destroy.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/drivers/fetch.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/drivers/index.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/drivers/store.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/drivers/update.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/index.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/license-keys/destroy.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/license-keys/fetch.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/license-keys/index.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/license-keys/store.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/license-keys/update.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-methods/destroy.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-methods/fetch.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-methods/index.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-methods/store.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-methods/update.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-rates/destroy.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-rates/fetch.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-rates/index.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-rates/store.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-rates/update.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-zones/destroy.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-zones/fetch.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-zones/index.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-zones/store.d.ts +0 -0
- /package/dist/{src/shippings → shippings}/shipping-zones/update.d.ts +0 -0
- /package/dist/{src/tax → tax}/destroy.d.ts +0 -0
- /package/dist/{src/tax → tax}/fetch.d.ts +0 -0
- /package/dist/{src/tax → tax}/index.d.ts +0 -0
- /package/dist/{src/tax → tax}/store.d.ts +0 -0
- /package/dist/{src/tax → tax}/update.d.ts +0 -0
- /package/dist/{src/types.d.ts → types.d.ts} +0 -0
- /package/dist/{src/utils → utils}/typed-stats.d.ts +0 -0
- /package/dist/{src/waitlists → waitlists}/index.d.ts +0 -0
- /package/dist/{src/waitlists → waitlists}/products/destroy.d.ts +0 -0
- /package/dist/{src/waitlists → waitlists}/products/fetch.d.ts +0 -0
- /package/dist/{src/waitlists → waitlists}/products/index.d.ts +0 -0
- /package/dist/{src/waitlists → waitlists}/products/store.d.ts +0 -0
- /package/dist/{src/waitlists → waitlists}/products/update.d.ts +0 -0
- /package/dist/{src/waitlists → waitlists}/restaurant/destroy.d.ts +0 -0
- /package/dist/{src/waitlists → waitlists}/restaurant/fetch.d.ts +0 -0
- /package/dist/{src/waitlists → waitlists}/restaurant/index.d.ts +0 -0
- /package/dist/{src/waitlists → waitlists}/restaurant/store.d.ts +0 -0
- /package/dist/{src/waitlists → waitlists}/restaurant/update.d.ts +0 -0
package/src/utils/typed-stats.ts
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Typed helpers for the aggregate-stats queries the commerce package uses
|
|
3
|
-
* heavily. The bun-query-builder `eb` expression-builder callback is
|
|
4
|
-
* effectively `any` from the consumer side (its return type is the
|
|
5
|
-
* builder's internal `SelectExpressionList`, not exported), so without a
|
|
6
|
-
* thin wrapper every call site has to `as any` both the callback param
|
|
7
|
-
* and the awaited result. That dropped *all* type safety for column
|
|
8
|
-
* names, bindings, and result shapes — fields like `averageSize` could
|
|
9
|
-
* be renamed in one place and silently break another.
|
|
10
|
-
*
|
|
11
|
-
* These helpers give us a typed result shape (caller declares the keys)
|
|
12
|
-
* and a single localized `as any` at the bun-query-builder boundary.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import type { StacksExpressionBuilder } from '@stacksjs/database'
|
|
16
|
-
import { db } from '@stacksjs/database'
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Stats descriptors map: each key is the result-row alias; each value is
|
|
20
|
-
* a `{ kind, column, where? }` triple describing the aggregate to emit.
|
|
21
|
-
*/
|
|
22
|
-
export type StatsDescriptor =
|
|
23
|
-
| { kind: 'count', column?: string, filter?: { column: string, op: string, value: unknown } }
|
|
24
|
-
| { kind: 'sum', column: string, filter?: { column: string, op: string, value: unknown } }
|
|
25
|
-
| { kind: 'avg', column: string, filter?: { column: string, op: string, value: unknown } }
|
|
26
|
-
| { kind: 'min', column: string, filter?: { column: string, op: string, value: unknown } }
|
|
27
|
-
| { kind: 'max', column: string, filter?: { column: string, op: string, value: unknown } }
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Run a typed aggregate query against a table.
|
|
31
|
-
*
|
|
32
|
-
* @example
|
|
33
|
-
* ```ts
|
|
34
|
-
* const stats = await aggregateStats('receipts', {
|
|
35
|
-
* total: { kind: 'count' },
|
|
36
|
-
* success: { kind: 'count', filter: { column: 'status', op: '=', value: 'success' } },
|
|
37
|
-
* averageSize: { kind: 'avg', column: 'size' },
|
|
38
|
-
* }, qb => qb.where('timestamp', '>=', start).where('timestamp', '<=', end))
|
|
39
|
-
* // typeof stats: { total: number; success: number; averageSize: number }
|
|
40
|
-
* ```
|
|
41
|
-
*/
|
|
42
|
-
export async function aggregateStats<TKeys extends string>(
|
|
43
|
-
table: string,
|
|
44
|
-
descriptors: Record<TKeys, StatsDescriptor>,
|
|
45
|
-
applyWhere?: (qb: any) => any,
|
|
46
|
-
): Promise<Record<TKeys, number>> {
|
|
47
|
-
let query: any = (db as any).selectFrom(table)
|
|
48
|
-
if (applyWhere) query = applyWhere(query)
|
|
49
|
-
|
|
50
|
-
query = query.select((eb: StacksExpressionBuilder) => Object.entries(descriptors).map(([alias, d]) => {
|
|
51
|
-
const col = (d as { column?: string }).column ?? 'id'
|
|
52
|
-
let expr = eb.fn[(d as StatsDescriptor).kind](col)
|
|
53
|
-
if ((d as { filter?: unknown }).filter) {
|
|
54
|
-
const f = (d as StatsDescriptor & { filter: NonNullable<StatsDescriptor['filter']> }).filter
|
|
55
|
-
expr = expr.filterWhere(f.column, f.op, f.value)
|
|
56
|
-
}
|
|
57
|
-
return expr.as(alias)
|
|
58
|
-
}))
|
|
59
|
-
|
|
60
|
-
const row = await query.executeTakeFirst()
|
|
61
|
-
const out = {} as Record<TKeys, number>
|
|
62
|
-
for (const alias of Object.keys(descriptors) as TKeys[]) {
|
|
63
|
-
const v = row?.[alias]
|
|
64
|
-
out[alias] = typeof v === 'number' ? v : Number(v ?? 0) || 0
|
|
65
|
-
}
|
|
66
|
-
return out
|
|
67
|
-
}
|
package/src/waitlists/index.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import * as products from './products'
|
|
2
|
-
import * as restaurant from './restaurant'
|
|
3
|
-
|
|
4
|
-
export {
|
|
5
|
-
products,
|
|
6
|
-
restaurant,
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface WaitlistsNamespace {
|
|
10
|
-
products: typeof products
|
|
11
|
-
restaurant: typeof restaurant
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const waitlists: WaitlistsNamespace = {
|
|
15
|
-
products,
|
|
16
|
-
restaurant,
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export default waitlists
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
type WaitlistProductJsonResponse = ModelRow<typeof WaitlistProduct>
|
|
2
|
-
import { db } from '@stacksjs/database'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Delete a waitlist product entry by ID
|
|
6
|
-
*
|
|
7
|
-
* @param id The ID of the waitlist product to delete
|
|
8
|
-
* @returns The deleted waitlist product record
|
|
9
|
-
*/
|
|
10
|
-
export async function destroy(id: number): Promise<WaitlistProductJsonResponse | undefined> {
|
|
11
|
-
try {
|
|
12
|
-
// First get the waitlist product to return it after deletion
|
|
13
|
-
const waitlistProduct = await db
|
|
14
|
-
.selectFrom('waitlist_products')
|
|
15
|
-
.where('id', '=', id)
|
|
16
|
-
.selectAll()
|
|
17
|
-
.executeTakeFirst()
|
|
18
|
-
|
|
19
|
-
if (!waitlistProduct)
|
|
20
|
-
return undefined
|
|
21
|
-
|
|
22
|
-
// Delete the waitlist product
|
|
23
|
-
await db
|
|
24
|
-
.deleteFrom('waitlist_products')
|
|
25
|
-
.where('id', '=', id)
|
|
26
|
-
.execute()
|
|
27
|
-
|
|
28
|
-
return waitlistProduct as WaitlistProductJsonResponse
|
|
29
|
-
}
|
|
30
|
-
catch (error) {
|
|
31
|
-
if (error instanceof Error) {
|
|
32
|
-
throw new TypeError(`Failed to delete waitlist product: ${error.message}`)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
throw error
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Delete multiple waitlist product entries by their IDs
|
|
41
|
-
*
|
|
42
|
-
* @param ids Array of waitlist product IDs to delete
|
|
43
|
-
* @returns Number of waitlist products deleted
|
|
44
|
-
*/
|
|
45
|
-
export async function bulkDestroy(ids: number[]): Promise<number> {
|
|
46
|
-
if (!ids.length)
|
|
47
|
-
return 0
|
|
48
|
-
|
|
49
|
-
try {
|
|
50
|
-
// Delete all waitlist products with the given IDs
|
|
51
|
-
const result = await db
|
|
52
|
-
.deleteFrom('waitlist_products')
|
|
53
|
-
.where('id', 'in', ids)
|
|
54
|
-
.execute()
|
|
55
|
-
|
|
56
|
-
return (result as any).length || 0
|
|
57
|
-
}
|
|
58
|
-
catch (error) {
|
|
59
|
-
if (error instanceof Error) {
|
|
60
|
-
throw new TypeError(`Failed to delete waitlist products in bulk: ${error.message}`)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
throw error
|
|
64
|
-
}
|
|
65
|
-
}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
type WaitlistProductJsonResponse = ModelRow<typeof WaitlistProduct>
|
|
2
|
-
import type { SpreadsheetWrapper } from 'ts-spreadsheets'
|
|
3
|
-
import { createSpreadsheet } from 'ts-spreadsheets'
|
|
4
|
-
import { fetchAll } from './fetch'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Represents the structure of an exported waitlist product
|
|
8
|
-
*/
|
|
9
|
-
export interface ExportedWaitlistProduct {
|
|
10
|
-
'ID': number
|
|
11
|
-
'Name': string
|
|
12
|
-
'Email': string
|
|
13
|
-
'Phone': string
|
|
14
|
-
'Party Size': number
|
|
15
|
-
'Notification Preference': string
|
|
16
|
-
'Source': string
|
|
17
|
-
'Status': string
|
|
18
|
-
'Created At': string
|
|
19
|
-
'Notified At': string
|
|
20
|
-
'Purchased At': string
|
|
21
|
-
'Cancelled At': string
|
|
22
|
-
'Notes': string
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Export waitlist products to a spreadsheet
|
|
27
|
-
* @param format The format of the spreadsheet (default is CSV)
|
|
28
|
-
* @returns Spreadsheet object ready for download or storage
|
|
29
|
-
*/
|
|
30
|
-
export async function exportWaitlist(format: 'csv' | 'excel' = 'csv'): Promise<SpreadsheetWrapper> {
|
|
31
|
-
// Fetch all waitlist products
|
|
32
|
-
const waitlistProducts = await fetchAll()
|
|
33
|
-
|
|
34
|
-
// Prepare data for spreadsheet
|
|
35
|
-
const spreadsheetData = prepareWaitlistForExport(waitlistProducts)
|
|
36
|
-
|
|
37
|
-
// Create and return spreadsheet
|
|
38
|
-
return createSpreadsheet(spreadsheetData, { type: format })
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Prepare waitlist data for spreadsheet export
|
|
43
|
-
* @param waitlistProducts Array of waitlist product objects
|
|
44
|
-
* @returns Spreadsheet data structure
|
|
45
|
-
*/
|
|
46
|
-
function prepareWaitlistForExport(waitlistProducts: WaitlistProductJsonResponse[]) {
|
|
47
|
-
// Define headings
|
|
48
|
-
const headings: (keyof ExportedWaitlistProduct)[] = [
|
|
49
|
-
'ID',
|
|
50
|
-
'Name',
|
|
51
|
-
'Email',
|
|
52
|
-
'Phone',
|
|
53
|
-
'Party Size',
|
|
54
|
-
'Notification Preference',
|
|
55
|
-
'Source',
|
|
56
|
-
'Status',
|
|
57
|
-
'Created At',
|
|
58
|
-
'Notified At',
|
|
59
|
-
'Purchased At',
|
|
60
|
-
'Cancelled At',
|
|
61
|
-
'Notes',
|
|
62
|
-
]
|
|
63
|
-
|
|
64
|
-
// Transform waitlist products into export format
|
|
65
|
-
const data = waitlistProducts.map((product) => {
|
|
66
|
-
return [
|
|
67
|
-
product.id,
|
|
68
|
-
product.name,
|
|
69
|
-
product.email,
|
|
70
|
-
product.phone || 'N/A',
|
|
71
|
-
(product as any).party_size,
|
|
72
|
-
product.notificationPreference,
|
|
73
|
-
product.source,
|
|
74
|
-
product.status,
|
|
75
|
-
product.created_at,
|
|
76
|
-
product.notifiedAt || 'N/A',
|
|
77
|
-
product.purchasedAt || 'N/A',
|
|
78
|
-
product.cancelledAt || 'N/A',
|
|
79
|
-
product.notes || 'N/A',
|
|
80
|
-
]
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
return { headings, data }
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Export waitlist products and automatically download
|
|
88
|
-
* @param format The format of the spreadsheet (default is CSV)
|
|
89
|
-
* @param filename Optional filename for the download
|
|
90
|
-
* @returns Download response
|
|
91
|
-
*/
|
|
92
|
-
export async function downloadWaitlist(format: 'csv' | 'excel' = 'csv', filename?: string): Promise<Response> {
|
|
93
|
-
const spreadsheet = await exportWaitlist(format)
|
|
94
|
-
|
|
95
|
-
// Use default filename if not provided
|
|
96
|
-
const defaultFilename = `waitlist_export_${new Date().toISOString().split('T')[0]}.${format}`
|
|
97
|
-
return spreadsheet.download(filename || defaultFilename)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Store waitlist export to disk
|
|
102
|
-
* @param format The format of the spreadsheet (default is CSV)
|
|
103
|
-
* @param path Optional path to store the file
|
|
104
|
-
* @returns Path where the file is stored
|
|
105
|
-
*/
|
|
106
|
-
export async function storeWaitlistExport(format: 'csv' | 'excel' = 'csv', path?: string): Promise<void> {
|
|
107
|
-
const spreadsheet = await exportWaitlist(format)
|
|
108
|
-
|
|
109
|
-
// Use default path and filename if not provided
|
|
110
|
-
const defaultPath = `waitlist_export_${new Date().toISOString().split('T')[0]}.${format}`
|
|
111
|
-
|
|
112
|
-
spreadsheet.store(path || defaultPath)
|
|
113
|
-
}
|
|
@@ -1,362 +0,0 @@
|
|
|
1
|
-
import type { StacksExpressionBuilder } from '@stacksjs/database'
|
|
2
|
-
import { db } from '@stacksjs/database'
|
|
3
|
-
import { formatDate } from '@stacksjs/orm'
|
|
4
|
-
type WaitlistProductJsonResponse = ModelRow<typeof WaitlistProduct>
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Fetch a waitlist product by ID
|
|
8
|
-
*/
|
|
9
|
-
export async function fetchById(id: number): Promise<WaitlistProductJsonResponse | undefined> {
|
|
10
|
-
return await db
|
|
11
|
-
.selectFrom('waitlist_products')
|
|
12
|
-
.where('id', '=', id)
|
|
13
|
-
.selectAll()
|
|
14
|
-
.executeTakeFirst() as WaitlistProductJsonResponse | undefined
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Fetch all waitlist products
|
|
19
|
-
*/
|
|
20
|
-
export async function fetchAll(): Promise<WaitlistProductJsonResponse[]> {
|
|
21
|
-
return await db.selectFrom('waitlist_products').selectAll().execute() as WaitlistProductJsonResponse[]
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Fetch the count of waitlist products grouped by source
|
|
26
|
-
* @param startDate Optional start date to filter by
|
|
27
|
-
* @param endDate Optional end date to filter by
|
|
28
|
-
* @returns An object containing the count for each source
|
|
29
|
-
*/
|
|
30
|
-
export async function fetchCountBySource(
|
|
31
|
-
startDate?: Date,
|
|
32
|
-
_endDate?: Date,
|
|
33
|
-
): Promise<Record<string, number>> {
|
|
34
|
-
let query = db
|
|
35
|
-
.selectFrom('waitlist_products')
|
|
36
|
-
.select(['source', (eb: StacksExpressionBuilder) => eb.fn.count('id').as('count')] as any)
|
|
37
|
-
.groupBy('source') as any
|
|
38
|
-
|
|
39
|
-
if (startDate && _endDate) {
|
|
40
|
-
const startDateStr = formatDate(startDate)
|
|
41
|
-
const endDateStr = formatDate(_endDate)
|
|
42
|
-
query = query
|
|
43
|
-
.where('created_at', '>=', startDateStr)
|
|
44
|
-
.where('created_at', '<=', endDateStr)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const results = await query.execute()
|
|
48
|
-
|
|
49
|
-
return results.reduce((acc: any, { source, count }: any) => {
|
|
50
|
-
acc[source] = count
|
|
51
|
-
return acc
|
|
52
|
-
}, {} as Record<string, number>)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Fetch the count of waitlist products for a specific date
|
|
57
|
-
* @param date The date to count entries for (defaults to today)
|
|
58
|
-
* @returns The count of entries for the specified date
|
|
59
|
-
*/
|
|
60
|
-
export async function fetchCountByDate(date: Date = new Date()): Promise<number> {
|
|
61
|
-
const startOfDay = new Date(date)
|
|
62
|
-
startOfDay.setHours(0, 0, 0, 0)
|
|
63
|
-
|
|
64
|
-
const endOfDay = new Date(date)
|
|
65
|
-
endOfDay.setHours(23, 59, 59, 999)
|
|
66
|
-
|
|
67
|
-
const startDateStr = formatDate(startOfDay)
|
|
68
|
-
const endDateStr = formatDate(endOfDay)
|
|
69
|
-
|
|
70
|
-
const result = await db
|
|
71
|
-
.selectFrom('waitlist_products')
|
|
72
|
-
.select(((eb: StacksExpressionBuilder) => eb.fn.count('id').as('count')) as any)
|
|
73
|
-
.where('created_at', '>=', startDateStr)
|
|
74
|
-
.where('created_at', '<=', endDateStr)
|
|
75
|
-
.executeTakeFirst() as { count: number } | undefined
|
|
76
|
-
|
|
77
|
-
return result?.count ?? 0
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Fetch the count of waitlist products with a specific quantity
|
|
82
|
-
* @param quantity The quantity to count orders for
|
|
83
|
-
* @returns The count of orders with the specified quantity
|
|
84
|
-
*/
|
|
85
|
-
export async function fetchCountByQuantity(quantity: number): Promise<number> {
|
|
86
|
-
const result = await db
|
|
87
|
-
.selectFrom('waitlist_products')
|
|
88
|
-
.select(((eb: StacksExpressionBuilder) => eb.fn.count('id').as('count')) as any)
|
|
89
|
-
.where('quantity', '=', quantity)
|
|
90
|
-
.executeTakeFirst() as { count: number } | undefined
|
|
91
|
-
|
|
92
|
-
return result?.count ?? 0
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Fetch the count of waitlist products grouped by quantity
|
|
97
|
-
* @param startDate Optional start date to filter by
|
|
98
|
-
* @param endDate Optional end date to filter by
|
|
99
|
-
* @returns An object containing the count for each quantity
|
|
100
|
-
*/
|
|
101
|
-
export async function fetchCountByAllQuantities(
|
|
102
|
-
startDate?: Date,
|
|
103
|
-
_endDate?: Date,
|
|
104
|
-
): Promise<Record<number, number>> {
|
|
105
|
-
let query = db
|
|
106
|
-
.selectFrom('waitlist_products')
|
|
107
|
-
.select(['quantity', (eb: StacksExpressionBuilder) => eb.fn.count('id').as('count')] as any)
|
|
108
|
-
.groupBy('quantity') as any
|
|
109
|
-
|
|
110
|
-
if (startDate && _endDate) {
|
|
111
|
-
const startDateStr = formatDate(startDate)
|
|
112
|
-
const endDateStr = formatDate(_endDate)
|
|
113
|
-
query = query
|
|
114
|
-
.where('created_at', '>=', startDateStr)
|
|
115
|
-
.where('created_at', '<=', endDateStr)
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const results = await query.execute()
|
|
119
|
-
|
|
120
|
-
return results.reduce((acc: any, { quantity, count }: any) => {
|
|
121
|
-
acc[quantity] = count
|
|
122
|
-
return acc
|
|
123
|
-
}, {} as Record<number, number>)
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Fetch waitlist products between two dates
|
|
128
|
-
* @param startDate The start date of the range
|
|
129
|
-
* @param endDate The end date of the range
|
|
130
|
-
* @returns Array of waitlist products within the date range
|
|
131
|
-
*/
|
|
132
|
-
export async function fetchBetweenDates(
|
|
133
|
-
startDate: Date,
|
|
134
|
-
endDate: Date,
|
|
135
|
-
): Promise<WaitlistProductJsonResponse[]> {
|
|
136
|
-
const startDateStr = formatDate(startDate)
|
|
137
|
-
const endDateStr = formatDate(endDate)
|
|
138
|
-
|
|
139
|
-
return await db
|
|
140
|
-
.selectFrom('waitlist_products')
|
|
141
|
-
.selectAll()
|
|
142
|
-
.where('created_at', '>=', startDateStr)
|
|
143
|
-
.where('created_at', '<=', endDateStr)
|
|
144
|
-
.execute() as WaitlistProductJsonResponse[]
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Fetch waitlist products that were notified between two dates
|
|
149
|
-
* @param startDate The start date of the range
|
|
150
|
-
* @param endDate The end date of the range
|
|
151
|
-
* @returns Array of waitlist products that were notified within the date range
|
|
152
|
-
*/
|
|
153
|
-
export async function fetchNotifiedBetweenDates(
|
|
154
|
-
startDate: Date,
|
|
155
|
-
endDate: Date,
|
|
156
|
-
): Promise<WaitlistProductJsonResponse[]> {
|
|
157
|
-
const startDateStr = formatDate(startDate)
|
|
158
|
-
const endDateStr = formatDate(endDate)
|
|
159
|
-
|
|
160
|
-
return await db
|
|
161
|
-
.selectFrom('waitlist_products')
|
|
162
|
-
.selectAll()
|
|
163
|
-
.where('notified_at', '>=', startDateStr)
|
|
164
|
-
.where('notified_at', '<=', endDateStr)
|
|
165
|
-
.where('notified_at', 'is not', null)
|
|
166
|
-
.execute() as WaitlistProductJsonResponse[]
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Fetch waitlist products that were purchased between two dates
|
|
171
|
-
* @param startDate The start date of the range
|
|
172
|
-
* @param endDate The end date of the range
|
|
173
|
-
* @returns Array of waitlist products that were purchased within the date range
|
|
174
|
-
*/
|
|
175
|
-
export async function fetchPurchasedBetweenDates(
|
|
176
|
-
startDate: Date,
|
|
177
|
-
endDate: Date,
|
|
178
|
-
): Promise<WaitlistProductJsonResponse[]> {
|
|
179
|
-
const startDateStr = formatDate(startDate)
|
|
180
|
-
const endDateStr = formatDate(endDate)
|
|
181
|
-
|
|
182
|
-
return await db
|
|
183
|
-
.selectFrom('waitlist_products')
|
|
184
|
-
.selectAll()
|
|
185
|
-
.where('purchased_at', '>=', startDateStr)
|
|
186
|
-
.where('purchased_at', '<=', endDateStr)
|
|
187
|
-
.where('purchased_at', 'is not', null)
|
|
188
|
-
.execute() as WaitlistProductJsonResponse[]
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Fetch waitlist products that were cancelled between two dates
|
|
193
|
-
* @param startDate The start date of the range
|
|
194
|
-
* @param endDate The end date of the range
|
|
195
|
-
* @returns Array of waitlist products that were cancelled within the date range
|
|
196
|
-
*/
|
|
197
|
-
export async function fetchCancelledBetweenDates(
|
|
198
|
-
startDate: Date,
|
|
199
|
-
endDate: Date,
|
|
200
|
-
): Promise<WaitlistProductJsonResponse[]> {
|
|
201
|
-
const startDateStr = formatDate(startDate)
|
|
202
|
-
const endDateStr = formatDate(endDate)
|
|
203
|
-
|
|
204
|
-
return await db
|
|
205
|
-
.selectFrom('waitlist_products')
|
|
206
|
-
.selectAll()
|
|
207
|
-
.where('cancelled_at', '>=', startDateStr)
|
|
208
|
-
.where('cancelled_at', '<=', endDateStr)
|
|
209
|
-
.where('cancelled_at', 'is not', null)
|
|
210
|
-
.execute() as WaitlistProductJsonResponse[]
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
/**
|
|
214
|
-
* Fetch all waitlist products with waiting status
|
|
215
|
-
* @returns Array of waitlist products with waiting status
|
|
216
|
-
*/
|
|
217
|
-
export async function fetchWaiting(): Promise<WaitlistProductJsonResponse[]> {
|
|
218
|
-
return await db
|
|
219
|
-
.selectFrom('waitlist_products')
|
|
220
|
-
.selectAll()
|
|
221
|
-
.where('status', '=', 'waiting')
|
|
222
|
-
.execute() as WaitlistProductJsonResponse[]
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Fetch the count of waitlist products by status
|
|
227
|
-
* @param status The status to filter by
|
|
228
|
-
* @param startDate Optional start date to filter by
|
|
229
|
-
* @param endDate Optional end date to filter by
|
|
230
|
-
* @returns The count of waitlist products with the specified status
|
|
231
|
-
*/
|
|
232
|
-
export async function fetchCountByStatus(
|
|
233
|
-
status: string,
|
|
234
|
-
startDate?: Date,
|
|
235
|
-
_endDate?: Date,
|
|
236
|
-
): Promise<number> {
|
|
237
|
-
let query = db
|
|
238
|
-
.selectFrom('waitlist_products')
|
|
239
|
-
.select(((eb: StacksExpressionBuilder) => eb.fn.count('id').as('count')) as any)
|
|
240
|
-
.where('status', '=', status) as any
|
|
241
|
-
|
|
242
|
-
if (startDate && _endDate) {
|
|
243
|
-
const startDateStr = formatDate(startDate)
|
|
244
|
-
const endDateStr = formatDate(_endDate)
|
|
245
|
-
query = query
|
|
246
|
-
.where('created_at', '>=', startDateStr)
|
|
247
|
-
.where('created_at', '<=', endDateStr)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
const result = await query.executeTakeFirst() as { count: number } | undefined
|
|
251
|
-
return result?.count ?? 0
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Fetch conversion rates for waitlist products
|
|
256
|
-
* @param startDate Optional start date to filter by
|
|
257
|
-
* @param endDate Optional end date to filter by
|
|
258
|
-
* @returns Object containing total conversion rate and breakdown by status
|
|
259
|
-
*/
|
|
260
|
-
export async function fetchConversionRates(
|
|
261
|
-
_startDate?: Date,
|
|
262
|
-
_endDate?: Date,
|
|
263
|
-
): Promise<{
|
|
264
|
-
totalConversionRate: number
|
|
265
|
-
statusBreakdown: Record<string, { count: number, percentage: number }>
|
|
266
|
-
}> {
|
|
267
|
-
let query = db
|
|
268
|
-
.selectFrom('waitlist_products')
|
|
269
|
-
.select(['status', (eb: StacksExpressionBuilder) => eb.fn.count('id').as('count')] as any)
|
|
270
|
-
.groupBy('status') as any
|
|
271
|
-
|
|
272
|
-
if (_startDate && _endDate) {
|
|
273
|
-
const startDateStr = formatDate(_startDate)
|
|
274
|
-
const endDateStr = formatDate(_endDate)
|
|
275
|
-
query = query
|
|
276
|
-
.where('created_at', '>=', startDateStr)
|
|
277
|
-
.where('created_at', '<=', endDateStr)
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const results = await query.execute()
|
|
281
|
-
|
|
282
|
-
// Calculate total count and purchased count
|
|
283
|
-
const totalCount = results.reduce((sum: any, { count }: any) => sum + count, 0)
|
|
284
|
-
const purchasedCount = results.find((r: any) => r.status === 'purchased')?.count ?? 0
|
|
285
|
-
|
|
286
|
-
// Calculate conversion rate
|
|
287
|
-
const totalConversionRate = totalCount > 0 ? (purchasedCount / totalCount) * 100 : 0
|
|
288
|
-
|
|
289
|
-
// Create status breakdown with percentages
|
|
290
|
-
const statusBreakdown = results.reduce((acc: any, { status, count }: any) => {
|
|
291
|
-
acc[status as string] = {
|
|
292
|
-
count,
|
|
293
|
-
percentage: totalCount > 0 ? (count / totalCount) * 100 : 0,
|
|
294
|
-
}
|
|
295
|
-
return acc
|
|
296
|
-
}, {} as Record<string, { count: number, percentage: number }>)
|
|
297
|
-
|
|
298
|
-
return {
|
|
299
|
-
totalConversionRate,
|
|
300
|
-
statusBreakdown,
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Fetch the count of waitlist products between two dates
|
|
306
|
-
* @param startDate The start date of the range
|
|
307
|
-
* @param endDate The end date of the range
|
|
308
|
-
* @returns The count of waitlist products within the date range
|
|
309
|
-
*/
|
|
310
|
-
export async function fetchCountBetweenDates(
|
|
311
|
-
startDate: Date,
|
|
312
|
-
endDate: Date,
|
|
313
|
-
): Promise<number> {
|
|
314
|
-
const startDateStr = formatDate(startDate)
|
|
315
|
-
const endDateStr = formatDate(endDate)
|
|
316
|
-
|
|
317
|
-
const result = await db
|
|
318
|
-
.selectFrom('waitlist_products')
|
|
319
|
-
.select(((eb: StacksExpressionBuilder) => eb.fn.count('id').as('count')) as any)
|
|
320
|
-
.where('created_at', '>=', startDateStr)
|
|
321
|
-
.where('created_at', '<=', endDateStr)
|
|
322
|
-
.executeTakeFirst() as { count: number } | undefined
|
|
323
|
-
|
|
324
|
-
return result?.count ?? 0
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Fetch the count of waitlist products grouped by date
|
|
329
|
-
* @param startDate Optional start date to filter by
|
|
330
|
-
* @param endDate Optional end date to filter by
|
|
331
|
-
* @returns An array of objects containing date and count
|
|
332
|
-
*/
|
|
333
|
-
export async function fetchCountByDateGrouped(
|
|
334
|
-
startDate?: Date,
|
|
335
|
-
_endDate?: Date,
|
|
336
|
-
): Promise<{ date: string, count: number }[]> {
|
|
337
|
-
let query = db
|
|
338
|
-
.selectFrom('waitlist_products')
|
|
339
|
-
.select(['created_at'])
|
|
340
|
-
|
|
341
|
-
if (startDate && _endDate) {
|
|
342
|
-
const startDateStr = formatDate(startDate)
|
|
343
|
-
const endDateStr = formatDate(_endDate)
|
|
344
|
-
query = query
|
|
345
|
-
.where('created_at', '>=', startDateStr)
|
|
346
|
-
.where('created_at', '<=', endDateStr)
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
const results = await query.execute()
|
|
350
|
-
|
|
351
|
-
// Group by date and count
|
|
352
|
-
const dateCounts = results.reduce((acc: any, { created_at }: any) => {
|
|
353
|
-
const date = (created_at || '').split('T')[0] || 'unknown' // Get YYYY-MM-DD
|
|
354
|
-
acc[date] = (acc[date] || 0) + 1
|
|
355
|
-
return acc
|
|
356
|
-
}, {} as Record<string, number>)
|
|
357
|
-
|
|
358
|
-
// Convert to array and sort by date
|
|
359
|
-
return Object.entries(dateCounts)
|
|
360
|
-
.map(([date, count]) => ({ date, count: count as number }))
|
|
361
|
-
.sort((a, b) => a.date.localeCompare(b.date))
|
|
362
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// Functions from destroy.ts
|
|
2
|
-
export {
|
|
3
|
-
bulkDestroy,
|
|
4
|
-
destroy,
|
|
5
|
-
} from './destroy'
|
|
6
|
-
|
|
7
|
-
export {
|
|
8
|
-
fetchAll,
|
|
9
|
-
fetchById,
|
|
10
|
-
fetchCancelledBetweenDates,
|
|
11
|
-
fetchConversionRates,
|
|
12
|
-
fetchCountBetweenDates,
|
|
13
|
-
fetchCountByAllQuantities,
|
|
14
|
-
fetchCountByDate,
|
|
15
|
-
fetchCountByDateGrouped,
|
|
16
|
-
fetchCountByQuantity,
|
|
17
|
-
fetchCountBySource,
|
|
18
|
-
fetchCountByStatus,
|
|
19
|
-
fetchNotifiedBetweenDates,
|
|
20
|
-
fetchPurchasedBetweenDates,
|
|
21
|
-
fetchWaiting,
|
|
22
|
-
} from './fetch'
|
|
23
|
-
|
|
24
|
-
export {
|
|
25
|
-
bulkStore,
|
|
26
|
-
store,
|
|
27
|
-
} from './store'
|
|
28
|
-
|
|
29
|
-
export {
|
|
30
|
-
update,
|
|
31
|
-
updatePartySize,
|
|
32
|
-
updateStatus,
|
|
33
|
-
} from './update'
|