@stacksjs/commerce 0.70.53 → 0.70.55

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.
Files changed (165) hide show
  1. package/package.json +3 -2
  2. package/src/carts/destroy.ts +54 -0
  3. package/src/carts/fetch.ts +20 -0
  4. package/src/carts/index.ts +13 -0
  5. package/src/carts/store.ts +75 -0
  6. package/src/carts/update.ts +78 -0
  7. package/src/coupons/destroy.ts +49 -0
  8. package/src/coupons/fetch.ts +510 -0
  9. package/src/coupons/index.ts +30 -0
  10. package/src/coupons/store.ts +46 -0
  11. package/src/coupons/update.ts +147 -0
  12. package/src/customers/destroy.ts +62 -0
  13. package/src/customers/fetch.ts +20 -0
  14. package/src/customers/index.ts +17 -0
  15. package/src/customers/store.ts +45 -0
  16. package/src/customers/update.ts +44 -0
  17. package/src/devices/destroy.ts +54 -0
  18. package/src/devices/export.ts +98 -0
  19. package/src/devices/fetch.ts +125 -0
  20. package/src/devices/index.ts +31 -0
  21. package/src/devices/store.ts +82 -0
  22. package/src/devices/update.ts +125 -0
  23. package/src/errors/destroy.ts +54 -0
  24. package/src/errors/fetch.ts +197 -0
  25. package/src/errors/index.ts +28 -0
  26. package/src/errors/update.ts +116 -0
  27. package/src/gift-cards/destroy.ts +87 -0
  28. package/src/gift-cards/fetch.ts +431 -0
  29. package/src/gift-cards/index.ts +26 -0
  30. package/src/gift-cards/store.ts +56 -0
  31. package/src/gift-cards/update.ts +102 -0
  32. package/src/index.ts +78 -0
  33. package/src/orders/destroy.ts +111 -0
  34. package/src/orders/events.ts +121 -0
  35. package/src/orders/export.ts +158 -0
  36. package/src/orders/fetch.ts +379 -0
  37. package/src/orders/guards.ts +261 -0
  38. package/src/orders/index.ts +91 -0
  39. package/src/orders/place-order.ts +274 -0
  40. package/src/orders/store.ts +51 -0
  41. package/src/orders/totals.ts +190 -0
  42. package/src/orders/update.ts +164 -0
  43. package/src/orders/webhook.ts +312 -0
  44. package/src/payments/destroy.ts +56 -0
  45. package/src/payments/fetch.ts +288 -0
  46. package/src/payments/index.ts +16 -0
  47. package/src/payments/store.ts +63 -0
  48. package/src/payments/update.ts +52 -0
  49. package/src/product.ts +0 -0
  50. package/src/products/categories/destroy.ts +103 -0
  51. package/src/products/categories/fetch.ts +285 -0
  52. package/src/products/categories/index.ts +36 -0
  53. package/src/products/categories/store.ts +87 -0
  54. package/src/products/categories/update.ts +251 -0
  55. package/src/products/index.ts +35 -0
  56. package/src/products/items/destroy.ts +54 -0
  57. package/src/products/items/fetch.ts +282 -0
  58. package/src/products/items/index.ts +26 -0
  59. package/src/products/items/store.ts +84 -0
  60. package/src/products/items/update.ts +324 -0
  61. package/src/products/manufacturers/destroy.ts +56 -0
  62. package/src/products/manufacturers/fetch.ts +117 -0
  63. package/src/products/manufacturers/index.ts +24 -0
  64. package/src/products/manufacturers/store.ts +82 -0
  65. package/src/products/manufacturers/update.ts +113 -0
  66. package/src/products/reviews/destroy.ts +56 -0
  67. package/src/products/reviews/fetch.ts +63 -0
  68. package/src/products/reviews/index.ts +25 -0
  69. package/src/products/reviews/store.ts +46 -0
  70. package/src/products/reviews/update.ts +82 -0
  71. package/src/products/units/destroy.ts +56 -0
  72. package/src/products/units/fetch.ts +20 -0
  73. package/src/products/units/index.ts +13 -0
  74. package/src/products/units/store.ts +162 -0
  75. package/src/products/units/update.ts +159 -0
  76. package/src/products/variants/destroy.ts +56 -0
  77. package/src/products/variants/fetch.ts +20 -0
  78. package/src/products/variants/index.ts +21 -0
  79. package/src/products/variants/store.ts +136 -0
  80. package/src/products/variants/update.ts +104 -0
  81. package/src/receipts/destroy.ts +54 -0
  82. package/src/receipts/export.ts +0 -0
  83. package/src/receipts/fetch.ts +222 -0
  84. package/src/receipts/index.ts +24 -0
  85. package/src/receipts/printer.ts +69 -0
  86. package/src/receipts/store.ts +69 -0
  87. package/src/receipts/update.ts +124 -0
  88. package/src/shippings/delivery-routes/destroy.ts +54 -0
  89. package/src/shippings/delivery-routes/fetch.ts +42 -0
  90. package/src/shippings/delivery-routes/index.ts +26 -0
  91. package/src/shippings/delivery-routes/store.ts +69 -0
  92. package/src/shippings/delivery-routes/update.ts +120 -0
  93. package/src/shippings/digital-deliveries/destroy.ts +111 -0
  94. package/src/shippings/digital-deliveries/fetch.ts +20 -0
  95. package/src/shippings/digital-deliveries/index.ts +26 -0
  96. package/src/shippings/digital-deliveries/store.ts +76 -0
  97. package/src/shippings/digital-deliveries/update.ts +129 -0
  98. package/src/shippings/drivers/destroy.ts +78 -0
  99. package/src/shippings/drivers/fetch.ts +20 -0
  100. package/src/shippings/drivers/index.ts +24 -0
  101. package/src/shippings/drivers/store.ts +69 -0
  102. package/src/shippings/drivers/update.ts +117 -0
  103. package/src/shippings/index.ts +39 -0
  104. package/src/shippings/license-keys/destroy.ts +111 -0
  105. package/src/shippings/license-keys/fetch.ts +20 -0
  106. package/src/shippings/license-keys/index.ts +26 -0
  107. package/src/shippings/license-keys/store.ts +77 -0
  108. package/src/shippings/license-keys/update.ts +117 -0
  109. package/src/shippings/shipping-methods/destroy.ts +111 -0
  110. package/src/shippings/shipping-methods/fetch.ts +62 -0
  111. package/src/shippings/shipping-methods/index.ts +28 -0
  112. package/src/shippings/shipping-methods/store.ts +123 -0
  113. package/src/shippings/shipping-methods/update.ts +120 -0
  114. package/src/shippings/shipping-rates/destroy.ts +102 -0
  115. package/src/shippings/shipping-rates/fetch.ts +320 -0
  116. package/src/shippings/shipping-rates/index.ts +36 -0
  117. package/src/shippings/shipping-rates/store.ts +102 -0
  118. package/src/shippings/shipping-rates/update.ts +139 -0
  119. package/src/shippings/shipping-zones/destroy.ts +111 -0
  120. package/src/shippings/shipping-zones/fetch.ts +96 -0
  121. package/src/shippings/shipping-zones/index.ts +26 -0
  122. package/src/shippings/shipping-zones/store.ts +74 -0
  123. package/src/shippings/shipping-zones/update.ts +156 -0
  124. package/src/tax/destroy.ts +54 -0
  125. package/src/tax/fetch.ts +20 -0
  126. package/src/tax/index.ts +24 -0
  127. package/src/tax/store.ts +69 -0
  128. package/src/tax/update.ts +119 -0
  129. package/src/tests/coupons.test.ts +90 -0
  130. package/src/tests/customers.test.ts +39 -0
  131. package/src/tests/device.test.ts +111 -0
  132. package/src/tests/digitals.test.ts +31 -0
  133. package/src/tests/drivers.test.ts +25 -0
  134. package/src/tests/gift-cards.test.ts +36 -0
  135. package/src/tests/license.test.ts +31 -0
  136. package/src/tests/manufacturers.test.ts +80 -0
  137. package/src/tests/orders.test.ts +25 -0
  138. package/src/tests/payments.test.ts +75 -0
  139. package/src/tests/rates.test.ts +367 -0
  140. package/src/tests/receipts.test.ts +287 -0
  141. package/src/tests/restaurant.test.ts +522 -0
  142. package/src/tests/reviews.test.ts +165 -0
  143. package/src/tests/routes.test.ts +51 -0
  144. package/src/tests/setup.ts +149 -0
  145. package/src/tests/shipping.test.ts +88 -0
  146. package/src/tests/tax.test.ts +25 -0
  147. package/src/tests/units.test.ts +110 -0
  148. package/src/tests/variants.test.ts +133 -0
  149. package/src/tests/waitlist.test.ts +303 -0
  150. package/src/tests/zones.test.ts +86 -0
  151. package/src/types.ts +312 -0
  152. package/src/utils/typed-stats.ts +67 -0
  153. package/src/waitlists/index.ts +19 -0
  154. package/src/waitlists/products/destroy.ts +65 -0
  155. package/src/waitlists/products/export.ts +113 -0
  156. package/src/waitlists/products/fetch.ts +362 -0
  157. package/src/waitlists/products/index.ts +33 -0
  158. package/src/waitlists/products/store.ts +112 -0
  159. package/src/waitlists/products/update.ts +125 -0
  160. package/src/waitlists/restaurant/destroy.ts +65 -0
  161. package/src/waitlists/restaurant/export.ts +107 -0
  162. package/src/waitlists/restaurant/fetch.ts +538 -0
  163. package/src/waitlists/restaurant/index.ts +43 -0
  164. package/src/waitlists/restaurant/store.ts +109 -0
  165. package/src/waitlists/restaurant/update.ts +198 -0
@@ -0,0 +1,303 @@
1
+ type WaitlistProductJsonResponse = ModelRow<typeof WaitlistProduct>
2
+ import { beforeEach, describe, expect, it } from 'bun:test'
3
+ import { formatDate } from '@stacksjs/orm'
4
+ import { refreshDatabase } from './setup'
5
+ import { bulkDestroy } from '../waitlists/products/destroy'
6
+ import {
7
+ fetchBetweenDates,
8
+ fetchCancelledBetweenDates,
9
+ fetchNotifiedBetweenDates,
10
+ fetchPurchasedBetweenDates,
11
+ fetchWaiting,
12
+ } from '../waitlists/products/fetch'
13
+ import { bulkStore } from '../waitlists/products/store'
14
+
15
+ beforeEach(async () => {
16
+ await refreshDatabase()
17
+ })
18
+
19
+ describe('Waitlist Product Module', () => {
20
+ describe('store', () => {
21
+ it('should return 0 when trying to bulk store an empty array', async () => {
22
+ const count = await bulkStore([])
23
+ expect(count).toBe(0)
24
+ })
25
+ })
26
+
27
+ describe('destroy', () => {
28
+ it('should return 0 when trying to delete an empty array of waitlist products', async () => {
29
+ // Try to delete with an empty array
30
+ const deletedCount = await bulkDestroy([])
31
+ expect(deletedCount).toBe(0)
32
+ })
33
+ })
34
+
35
+ describe('fetch', () => {
36
+ it('should fetch waitlist products between two dates', async () => {
37
+ // Create test dates using today
38
+ const today = new Date()
39
+ const startDate = new Date(today.setHours(0, 0, 0, 0))
40
+ const endDate = new Date(today.setHours(23, 59, 59, 999))
41
+
42
+ // Create test waitlist products
43
+ const requests = [
44
+ {
45
+ name: 'John Doe',
46
+ email: 'john@example.com',
47
+ quantity: 4,
48
+ notification_preference: 'email',
49
+ source: 'website',
50
+ status: 'waiting',
51
+ product_id: 1,
52
+ customer_id: 1,
53
+ },
54
+ {
55
+ name: 'Jane Smith',
56
+ email: 'jane@example.com',
57
+ quantity: 2,
58
+ notification_preference: 'sms',
59
+ source: 'website',
60
+ status: 'waiting',
61
+ product_id: 2,
62
+ customer_id: 2,
63
+ },
64
+ {
65
+ name: 'Bob Wilson',
66
+ email: 'bob@example.com',
67
+ quantity: 6,
68
+ notification_preference: 'both',
69
+ source: 'app',
70
+ status: 'waiting',
71
+ product_id: 3,
72
+ customer_id: 3,
73
+ },
74
+ ]
75
+
76
+ // Create the waitlist products
77
+ await bulkStore(requests)
78
+
79
+ // Fetch waitlists between dates
80
+ const waitlists = await fetchBetweenDates(startDate, endDate)
81
+ expect(waitlists).toBeDefined()
82
+ expect(waitlists.length).toBe(3) // All entries should be within the date range since they're created now
83
+ expect(waitlists.map((w: WaitlistProductJsonResponse) => w.name)).toContain('John Doe')
84
+ expect(waitlists.map((w: WaitlistProductJsonResponse) => w.name)).toContain('Jane Smith')
85
+ expect(waitlists.map((w: WaitlistProductJsonResponse) => w.name)).toContain('Bob Wilson')
86
+ })
87
+
88
+ it('should fetch notified waitlist products between two dates', async () => {
89
+ // Create test dates using today
90
+ const today = new Date()
91
+ const startDate = new Date(today.setHours(0, 0, 0, 0))
92
+ const endDate = new Date(today.setHours(23, 59, 59, 999))
93
+
94
+ // Create test waitlist products with different notification dates
95
+ const requests = [
96
+ {
97
+ name: 'John Doe',
98
+ email: 'john@example.com',
99
+ quantity: 4,
100
+ notification_preference: 'email',
101
+ source: 'website',
102
+ status: 'notified',
103
+ product_id: 1,
104
+ customer_id: 1,
105
+ notified_at: formatDate(startDate),
106
+ },
107
+ {
108
+ name: 'Jane Smith',
109
+ email: 'jane@example.com',
110
+ quantity: 2,
111
+ notification_preference: 'sms',
112
+ source: 'website',
113
+ status: 'notified',
114
+ product_id: 2,
115
+ customer_id: 2,
116
+ notified_at: formatDate(endDate),
117
+ },
118
+ {
119
+ name: 'Bob Wilson',
120
+ email: 'bob@example.com',
121
+ quantity: 6,
122
+ notification_preference: 'both',
123
+ source: 'app',
124
+ status: 'waiting',
125
+ product_id: 3,
126
+ customer_id: 3,
127
+ },
128
+ ]
129
+
130
+ // Create the waitlist products
131
+ await bulkStore(requests as any)
132
+
133
+ // Fetch notified waitlists between dates
134
+ const notifiedWaitlists = await fetchNotifiedBetweenDates(startDate, endDate)
135
+ expect(notifiedWaitlists).toBeDefined()
136
+ expect(notifiedWaitlists.length).toBe(2)
137
+ expect(notifiedWaitlists.map((w: WaitlistProductJsonResponse) => w.name)).toContain('John Doe')
138
+ expect(notifiedWaitlists.map((w: WaitlistProductJsonResponse) => w.name)).toContain('Jane Smith')
139
+ })
140
+
141
+ it('should fetch purchased waitlist products between two dates', async () => {
142
+ // Create test dates using today
143
+ const today = new Date()
144
+ const startDate = new Date(today.setHours(0, 0, 0, 0))
145
+ const endDate = new Date(today.setHours(23, 59, 59, 999))
146
+
147
+ // Create test waitlist products with different purchase dates
148
+ const requests = [
149
+ {
150
+ name: 'John Doe',
151
+ email: 'john@example.com',
152
+ quantity: 4,
153
+ notification_preference: 'email',
154
+ source: 'website',
155
+ status: 'purchased',
156
+ product_id: 1,
157
+ customer_id: 1,
158
+ purchased_at: startDate.getTime(),
159
+ },
160
+ {
161
+ name: 'Jane Smith',
162
+ email: 'jane@example.com',
163
+ quantity: 2,
164
+ notification_preference: 'sms',
165
+ source: 'website',
166
+ status: 'purchased',
167
+ product_id: 2,
168
+ customer_id: 2,
169
+ purchased_at: endDate.getTime(),
170
+ },
171
+ {
172
+ name: 'Bob Wilson',
173
+ email: 'bob@example.com',
174
+ quantity: 6,
175
+ notification_preference: 'both',
176
+ source: 'app',
177
+ status: 'waiting',
178
+ product_id: 3,
179
+ customer_id: 3,
180
+ },
181
+ ]
182
+
183
+ // Create the waitlist products
184
+ await bulkStore(requests)
185
+
186
+ // Fetch purchased waitlists between dates
187
+ const purchasedWaitlists = await fetchPurchasedBetweenDates(startDate, endDate)
188
+ expect(purchasedWaitlists).toBeDefined()
189
+ expect(purchasedWaitlists.length).toBe(2)
190
+ expect(purchasedWaitlists.map((w: WaitlistProductJsonResponse) => w.name)).toContain('John Doe')
191
+ expect(purchasedWaitlists.map((w: WaitlistProductJsonResponse) => w.name)).toContain('Jane Smith')
192
+ })
193
+
194
+ it('should fetch cancelled waitlist products between two dates', async () => {
195
+ // Create test dates using today
196
+ const today = new Date()
197
+ const startDate = new Date(today.setHours(0, 0, 0, 0))
198
+ const endDate = new Date(today.setHours(23, 59, 59, 999))
199
+
200
+ // Create test waitlist products with different cancellation dates
201
+ const requests = [
202
+ {
203
+ name: 'John Doe',
204
+ email: 'john@example.com',
205
+ quantity: 4,
206
+ notification_preference: 'email',
207
+ source: 'website',
208
+ status: 'cancelled',
209
+ product_id: 1,
210
+ customer_id: 1,
211
+ cancelled_at: formatDate(startDate),
212
+ },
213
+ {
214
+ name: 'Jane Smith',
215
+ email: 'jane@example.com',
216
+ quantity: 2,
217
+ notification_preference: 'sms',
218
+ source: 'website',
219
+ status: 'cancelled',
220
+ product_id: 2,
221
+ customer_id: 2,
222
+ cancelled_at: formatDate(endDate),
223
+ },
224
+ {
225
+ name: 'Bob Wilson',
226
+ email: 'bob@example.com',
227
+ quantity: 6,
228
+ notification_preference: 'both',
229
+ source: 'app',
230
+ status: 'waiting',
231
+ product_id: 3,
232
+ customer_id: 3,
233
+ },
234
+ ]
235
+
236
+ // Create the waitlist products
237
+ await bulkStore(requests as any)
238
+
239
+ // Fetch cancelled waitlists between dates
240
+ const cancelledWaitlists = await fetchCancelledBetweenDates(startDate, endDate)
241
+ expect(cancelledWaitlists).toBeDefined()
242
+ expect(cancelledWaitlists.length).toBe(2)
243
+ expect(cancelledWaitlists.map((w: WaitlistProductJsonResponse) => w.name)).toContain('John Doe')
244
+ expect(cancelledWaitlists.map((w: WaitlistProductJsonResponse) => w.name)).toContain('Jane Smith')
245
+ })
246
+
247
+ it('should fetch all waitlist products with waiting status', async () => {
248
+ // Create test waitlist products with different statuses
249
+ const requests = [
250
+ {
251
+ name: 'John Doe',
252
+ email: 'john@example.com',
253
+ quantity: 4,
254
+ notification_preference: 'email',
255
+ source: 'website',
256
+ status: 'waiting',
257
+ product_id: 1,
258
+ customer_id: 1,
259
+ },
260
+ {
261
+ name: 'Jane Smith',
262
+ email: 'jane@example.com',
263
+ quantity: 2,
264
+ notification_preference: 'sms',
265
+ source: 'website',
266
+ status: 'waiting',
267
+ product_id: 2,
268
+ customer_id: 2,
269
+ },
270
+ {
271
+ name: 'Bob Wilson',
272
+ email: 'bob@example.com',
273
+ quantity: 6,
274
+ notification_preference: 'both',
275
+ source: 'app',
276
+ status: 'notified',
277
+ product_id: 3,
278
+ customer_id: 3,
279
+ },
280
+ {
281
+ name: 'Alice Brown',
282
+ email: 'alice@example.com',
283
+ quantity: 3,
284
+ notification_preference: 'email',
285
+ source: 'social_media',
286
+ status: 'purchased',
287
+ product_id: 4,
288
+ customer_id: 4,
289
+ },
290
+ ]
291
+
292
+ // Create the waitlist products
293
+ await bulkStore(requests as any)
294
+
295
+ // Fetch waitlists with waiting status
296
+ const waitingWaitlists = await fetchWaiting()
297
+ expect(waitingWaitlists).toBeDefined()
298
+ expect(waitingWaitlists.length).toBe(2)
299
+ expect(waitingWaitlists.map((w: WaitlistProductJsonResponse) => w.name)).toContain('John Doe')
300
+ expect(waitingWaitlists.map((w: WaitlistProductJsonResponse) => w.name)).toContain('Jane Smith')
301
+ })
302
+ })
303
+ })
@@ -0,0 +1,86 @@
1
+ import { beforeEach, describe, expect, it } from 'bun:test'
2
+ import { refreshDatabase } from './setup'
3
+ import { formatZoneOptions, getActiveShippingZones } from '../shippings/shipping-zones/fetch'
4
+ import { bulkStore, store } from '../shippings/shipping-zones/store'
5
+ import { bulkDestroy } from '../shippings/shipping-zones/destroy'
6
+
7
+ beforeEach(async () => {
8
+ await refreshDatabase()
9
+ })
10
+
11
+ describe('Shipping Zone Module', () => {
12
+ describe('store', () => {
13
+ it('should return 0 when trying to bulk store an empty array', async () => {
14
+ const count = await bulkStore([])
15
+ expect(count).toBe(0)
16
+ })
17
+
18
+ it('should format zone options for dropdowns', async () => {
19
+ // First create some zones
20
+ await store({
21
+ name: 'Zone A',
22
+ countries: JSON.stringify(['US']),
23
+ status: 'active',
24
+ shipping_method_id: 1,
25
+ })
26
+
27
+ await store({
28
+ name: 'Zone B',
29
+ countries: JSON.stringify(['CA']),
30
+ status: 'inactive',
31
+ shipping_method_id: 1,
32
+ })
33
+
34
+ // Now get formatted options
35
+ const options = await formatZoneOptions()
36
+
37
+ expect(options).toBeDefined()
38
+ expect(options.length).toBe(2)
39
+
40
+ // Verify structure of options
41
+ expect(options[0].id).toBeDefined()
42
+ expect(options[0].name).toBeDefined()
43
+ expect(options[0].status).toBeDefined()
44
+ expect(options[0].countries).toBeDefined()
45
+
46
+ // Verify names are present
47
+ const names = options.map(opt => opt.name)
48
+ expect(names).toContain('Zone A')
49
+ expect(names).toContain('Zone B')
50
+ })
51
+
52
+ it('should get active shipping zones', async () => {
53
+ // Create active zone
54
+ await store({
55
+ name: 'Active Zone',
56
+ countries: JSON.stringify(['US']),
57
+ status: 'active',
58
+ shipping_method_id: 1,
59
+ })
60
+
61
+ // Create inactive zone
62
+ await store({
63
+ name: 'Inactive Zone',
64
+ countries: JSON.stringify(['CA']),
65
+ status: 'inactive',
66
+ shipping_method_id: 1,
67
+ })
68
+
69
+ // Get active zones
70
+ const activeZones = await getActiveShippingZones()
71
+
72
+ expect(activeZones).toBeDefined()
73
+ expect(activeZones.length).toBe(1)
74
+ expect(activeZones[0].name).toBe('Active Zone')
75
+ expect(activeZones[0].status).toBe('active')
76
+ })
77
+ })
78
+
79
+ describe('destroy', () => {
80
+ it('should return 0 when trying to delete an empty array of zones', async () => {
81
+ // Try to delete with an empty array
82
+ const deletedCount = await bulkDestroy([])
83
+ expect(deletedCount).toBe(0)
84
+ })
85
+ })
86
+ })
package/src/types.ts ADDED
@@ -0,0 +1,312 @@
1
+ // Import the CustomerTable type from the ORM
2
+
3
+ type CouponJsonResponse = ModelRow<typeof Coupon>
4
+ type CustomerJsonResponse = ModelRow<typeof Customer>
5
+ type GiftCardJsonResponse = ModelRow<typeof GiftCard>
6
+ type ManufacturerJsonResponse = ModelRow<typeof Manufacturer>
7
+ type OrderJsonResponse = ModelRow<typeof Order>
8
+ type OrderItemJsonResponse = ModelRow<typeof OrderItem>
9
+ type ReviewJsonResponse = ModelRow<typeof Review>
10
+
11
+ // Define the input for creating a customer
12
+ export interface CreateCustomerInput {
13
+ name: string
14
+ email: string
15
+ phone: string
16
+ orders?: number
17
+ total_spent?: number // Changed from totalSpent to match the schema
18
+ last_order?: string // Changed from lastOrder to match the schema
19
+ status?: string
20
+ avatar?: string
21
+ user_id?: number
22
+ }
23
+
24
+ // Define the input for updating a customer
25
+ export interface UpdateCustomerInput {
26
+ name?: string
27
+ email?: string
28
+ phone?: string
29
+ orders?: number
30
+ total_spent?: number // Changed from totalSpent to match the schema
31
+ last_order?: string // Changed from lastOrder to match the schema
32
+ status?: string
33
+ avatar?: string
34
+ user_id?: number
35
+ }
36
+
37
+ // Define the structure of an order item
38
+ export interface OrderItem {
39
+ product_id: string
40
+ quantity: number
41
+ price: number
42
+ special_instructions?: string
43
+ }
44
+
45
+ // Type for status count
46
+ export interface StatusCount {
47
+ status: string
48
+ count: number | string // Using string since SQL count might return as string
49
+ }
50
+
51
+ // Type for order type count
52
+ export interface OrderTypeCount {
53
+ order_type: string
54
+ count: number | string // Using string since SQL count might return as string
55
+ }
56
+
57
+ // Type for the stats return value
58
+ export interface OrderStats {
59
+ total: number
60
+ by_status: StatusCount[]
61
+ by_type: OrderTypeCount[]
62
+ recent: OrderJsonResponse[]
63
+ revenue: number
64
+ }
65
+
66
+ /**
67
+ * Represents a simplified order item structure with required properties for total calculation
68
+ */
69
+ export interface OrderItemForCalculation {
70
+ price: number
71
+ quantity: number
72
+ }
73
+
74
+ /**
75
+ * Represents the totals calculated for an order
76
+ */
77
+ export interface OrderTotals {
78
+ subtotal: number
79
+ tax_amount: number
80
+ total_amount: number
81
+ }
82
+
83
+ /**
84
+ * Represents statistics for a discount type
85
+ */
86
+ export interface DiscountTypeCount {
87
+ discount_type: string | undefined
88
+ count: string | number | bigint
89
+ }
90
+
91
+ /**
92
+ * Represents comprehensive coupon statistics
93
+ */
94
+ export interface CouponStats {
95
+ /** Total number of coupons in the system */
96
+ total: number
97
+
98
+ /** Number of currently active coupons */
99
+ active: number
100
+
101
+ /** Distribution of coupons by discount type */
102
+ by_type: DiscountTypeCount[]
103
+
104
+ /** List of most frequently used coupons */
105
+ most_used: {
106
+ id: number | undefined
107
+ code: string | undefined
108
+ discount_type: string | undefined
109
+ discount_value: number | undefined
110
+ usage_count: number | undefined
111
+ }[]
112
+
113
+ /** List of upcoming coupons that will be active soon */
114
+ upcoming: {
115
+ id: number | undefined
116
+ code: string | undefined
117
+ discount_type: string | undefined
118
+ discount_value: number | undefined
119
+ start_date: Date | string
120
+ end_date: Date | string
121
+ }[]
122
+ }
123
+ export interface OrderWithTotals {
124
+ order_items: OrderItemJsonResponse[] | []
125
+ id: number
126
+ customer_id: number
127
+ customer: CustomerJsonResponse | undefined
128
+ coupon_id: number
129
+ coupon: CouponJsonResponse | undefined
130
+ status: string
131
+ total_amount: number
132
+ tax_amount: number | undefined
133
+ discount_amount: number | undefined
134
+ delivery_fee: number | undefined
135
+ tip_amount: number | undefined
136
+ order_type: string
137
+ delivery_address: string | undefined
138
+ special_instructions: string | undefined
139
+ estimated_delivery_time: string | undefined
140
+ applied_coupon_id: string | undefined
141
+ uuid: string | undefined
142
+ created_at: Date | undefined
143
+ updated_at: Date | undefined
144
+ customer_name: string | null
145
+ customer_email: string | null
146
+ // Add the new calculated fields
147
+ totalItems: number
148
+ totalPrice: number
149
+ }
150
+
151
+ export interface FetchGiftCardsOptions {
152
+ page?: number
153
+ limit?: number
154
+ search?: string
155
+ status?: string
156
+ is_active?: boolean
157
+ is_digital?: boolean
158
+ is_reloadable?: boolean
159
+ sortBy?: string
160
+ sortOrder?: 'asc' | 'desc'
161
+ purchaser_id?: string
162
+ from_date?: string
163
+ to_date?: string
164
+ min_balance?: number
165
+ max_balance?: number
166
+ }
167
+
168
+ interface BaseResponse {
169
+ paging: {
170
+ total_records: number
171
+ page: number
172
+ total_pages: number
173
+ }
174
+ next_cursor: number | null
175
+ }
176
+
177
+ export interface GiftCardResponse extends BaseResponse {
178
+ data: GiftCardJsonResponse[]
179
+ }
180
+
181
+ export interface GiftCardStats {
182
+ total: number
183
+ active: number
184
+ by_status: Array<{ status: string, count: number }>
185
+ by_balance: {
186
+ low: number // Count of cards with less than 25% of initial balance
187
+ medium: number // Count of cards with 25-75% of initial balance
188
+ high: number // Count of cards with more than 75% of initial balance
189
+ }
190
+ expiring_soon: GiftCardJsonResponse[]
191
+ recently_used: GiftCardJsonResponse[]
192
+ }
193
+
194
+ export interface FetchReviewsOptions {
195
+ page?: number
196
+ limit?: number
197
+ }
198
+
199
+ export interface ReviewResponse extends BaseResponse {
200
+ data: ReviewJsonResponse[]
201
+ }
202
+
203
+ export interface ManufacturerResponse extends BaseResponse {
204
+ data: ManufacturerJsonResponse[]
205
+ }
206
+ export interface ReviewStats {
207
+ total: number
208
+ average_rating: number
209
+ rating_distribution: {
210
+ one_star: number
211
+ two_star: number
212
+ three_star: number
213
+ four_star: number
214
+ five_star: number
215
+ }
216
+ recent_reviews: ReviewJsonResponse[]
217
+ }
218
+
219
+ /**
220
+ * Represents comprehensive category statistics
221
+ */
222
+ export interface CategoryStats {
223
+ /** Total number of categories in the system */
224
+ total: number
225
+
226
+ /** Number of currently active categories */
227
+ active: number
228
+
229
+ /** Number of root categories (no parent) */
230
+ root_categories: number
231
+
232
+ /** Number of child categories (has parent) */
233
+ child_categories: number
234
+
235
+ /** Number of categories with images */
236
+ with_images: number
237
+
238
+ /** Recently added categories */
239
+ recently_added: Array<any>
240
+
241
+ /** Top parent categories with most children */
242
+ top_parent_categories: Array<{
243
+ id: string
244
+ name: string
245
+ child_count: number
246
+ }>
247
+ }
248
+
249
+ /**
250
+ * Options for fetching product manufacturers
251
+ */
252
+ export interface FetchManufacturersOptions {
253
+ country?: string
254
+ featured?: boolean
255
+ search?: string
256
+ }
257
+
258
+ export interface FetchCouponsOptions {
259
+ page?: number
260
+ limit?: number
261
+ search?: string
262
+ is_active?: boolean
263
+ discount_type?: string
264
+ sortBy?: string
265
+ sortOrder?: 'asc' | 'desc'
266
+ product_id?: string
267
+ category_id?: string
268
+ from_date?: string
269
+ to_date?: string
270
+ }
271
+
272
+ /**
273
+ * Interface for coupon count statistics
274
+ */
275
+ export interface CouponCountStats {
276
+ total: number
277
+ active: number
278
+ inactive: number
279
+ }
280
+
281
+ /**
282
+ * Interface for time-based coupon statistics
283
+ */
284
+ export interface CouponTimeStats {
285
+ week: CouponCountStats
286
+ month: CouponCountStats
287
+ year: CouponCountStats
288
+ all_time: CouponCountStats
289
+ }
290
+
291
+ /**
292
+ * Interface for coupon redemption statistics
293
+ */
294
+ export interface CouponRedemptionStats {
295
+ total: number
296
+ week: number
297
+ month: number
298
+ year: number
299
+ by_type: Record<string, number>
300
+ }
301
+ export interface FetchOrdersOptions {
302
+ page?: number
303
+ limit?: number
304
+ search?: string
305
+ status?: string
306
+ order_type?: string
307
+ customer_id?: number
308
+ sortBy?: string
309
+ sortOrder?: 'asc' | 'desc'
310
+ from_date?: string
311
+ to_date?: string
312
+ }