@instockng/api-client 1.0.8 → 1.0.10

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 (193) hide show
  1. package/dist/fetchers/brands.d.ts +1 -1
  2. package/dist/fetchers/carts.d.ts +85 -47
  3. package/dist/fetchers/delivery-zones.d.ts +2 -0
  4. package/dist/fetchers/orders.d.ts +26 -14
  5. package/dist/fetchers/products.d.ts +14 -6
  6. package/dist/hooks/admin/abandoned-carts.d.ts +18 -10
  7. package/dist/hooks/admin/brands.d.ts +4 -4
  8. package/dist/hooks/admin/customers.d.ts +13 -7
  9. package/dist/hooks/admin/delivery-zones.d.ts +23 -15
  10. package/dist/hooks/admin/discount-codes.d.ts +10 -10
  11. package/dist/hooks/admin/inventory.d.ts +4 -0
  12. package/dist/hooks/admin/orders.d.ts +78 -42
  13. package/dist/hooks/admin/products.d.ts +14 -6
  14. package/dist/hooks/admin/stats.d.ts +13 -7
  15. package/dist/hooks/admin/variants.d.ts +5 -5
  16. package/dist/hooks/admin/warehouses.d.ts +11 -7
  17. package/dist/hooks/public/brands.d.ts +1 -1
  18. package/dist/hooks/public/carts.d.ts +85 -47
  19. package/dist/hooks/public/delivery-zones.d.ts +2 -0
  20. package/dist/hooks/public/orders.d.ts +26 -14
  21. package/dist/hooks/public/products.d.ts +14 -6
  22. package/dist/rpc-client.d.ts +335 -187
  23. package/package.json +1 -1
  24. package/dist/apps/backend/src/generated/zod/index.d.ts +0 -1114
  25. package/dist/apps/backend/src/generated/zod/index.js +0 -670
  26. package/dist/apps/backend/src/http-app.d.ts +0 -40
  27. package/dist/apps/backend/src/http-app.js +0 -134
  28. package/dist/apps/backend/src/lib/brand-response.d.ts +0 -14
  29. package/dist/apps/backend/src/lib/brand-response.js +0 -8
  30. package/dist/apps/backend/src/lib/cart-helpers.d.ts +0 -282
  31. package/dist/apps/backend/src/lib/cart-helpers.js +0 -121
  32. package/dist/apps/backend/src/lib/cart-recovery.d.ts +0 -30
  33. package/dist/apps/backend/src/lib/cart-recovery.js +0 -147
  34. package/dist/apps/backend/src/lib/cart-response.d.ts +0 -121
  35. package/dist/apps/backend/src/lib/cart-response.js +0 -150
  36. package/dist/apps/backend/src/lib/clerk.d.ts +0 -18
  37. package/dist/apps/backend/src/lib/clerk.js +0 -190
  38. package/dist/apps/backend/src/lib/delivery-zone-response.d.ts +0 -64
  39. package/dist/apps/backend/src/lib/delivery-zone-response.js +0 -24
  40. package/dist/apps/backend/src/lib/discount-code-response.d.ts +0 -42
  41. package/dist/apps/backend/src/lib/discount-code-response.js +0 -19
  42. package/dist/apps/backend/src/lib/discount.d.ts +0 -20
  43. package/dist/apps/backend/src/lib/discount.js +0 -35
  44. package/dist/apps/backend/src/lib/inventory.d.ts +0 -26
  45. package/dist/apps/backend/src/lib/inventory.js +0 -160
  46. package/dist/apps/backend/src/lib/meta-capi.d.ts +0 -53
  47. package/dist/apps/backend/src/lib/meta-capi.js +0 -151
  48. package/dist/apps/backend/src/lib/openapi.d.ts +0 -36
  49. package/dist/apps/backend/src/lib/openapi.js +0 -69
  50. package/dist/apps/backend/src/lib/order-recovery.d.ts +0 -459
  51. package/dist/apps/backend/src/lib/order-recovery.js +0 -378
  52. package/dist/apps/backend/src/lib/order-response.d.ts +0 -138
  53. package/dist/apps/backend/src/lib/order-response.js +0 -61
  54. package/dist/apps/backend/src/lib/pricing.d.ts +0 -39
  55. package/dist/apps/backend/src/lib/pricing.js +0 -62
  56. package/dist/apps/backend/src/lib/prisma.d.ts +0 -9
  57. package/dist/apps/backend/src/lib/prisma.js +0 -30
  58. package/dist/apps/backend/src/lib/product-response.d.ts +0 -82
  59. package/dist/apps/backend/src/lib/product-response.js +0 -29
  60. package/dist/apps/backend/src/lib/sentry.d.ts +0 -48
  61. package/dist/apps/backend/src/lib/sentry.js +0 -180
  62. package/dist/apps/backend/src/lib/utils.d.ts +0 -32
  63. package/dist/apps/backend/src/lib/utils.js +0 -63
  64. package/dist/apps/backend/src/middleware/clerk-auth.d.ts +0 -8
  65. package/dist/apps/backend/src/middleware/clerk-auth.js +0 -89
  66. package/dist/apps/backend/src/middleware/cors.d.ts +0 -8
  67. package/dist/apps/backend/src/middleware/cors.js +0 -11
  68. package/dist/apps/backend/src/notifications/producers/meta-capi-producer.d.ts +0 -62
  69. package/dist/apps/backend/src/notifications/producers/meta-capi-producer.js +0 -180
  70. package/dist/apps/backend/src/notifications/producers/order-notification.d.ts +0 -9
  71. package/dist/apps/backend/src/notifications/producers/order-notification.js +0 -18
  72. package/dist/apps/backend/src/notifications/producers/prospect-recovery-notification.d.ts +0 -10
  73. package/dist/apps/backend/src/notifications/producers/prospect-recovery-notification.js +0 -11
  74. package/dist/apps/backend/src/routes/admin/abandoned-carts.d.ts +0 -605
  75. package/dist/apps/backend/src/routes/admin/abandoned-carts.js +0 -194
  76. package/dist/apps/backend/src/routes/admin/brands.d.ts +0 -175
  77. package/dist/apps/backend/src/routes/admin/brands.js +0 -118
  78. package/dist/apps/backend/src/routes/admin/customers.d.ts +0 -308
  79. package/dist/apps/backend/src/routes/admin/customers.js +0 -39
  80. package/dist/apps/backend/src/routes/admin/delivery-zones.d.ts +0 -446
  81. package/dist/apps/backend/src/routes/admin/delivery-zones.js +0 -300
  82. package/dist/apps/backend/src/routes/admin/discount-codes.d.ts +0 -478
  83. package/dist/apps/backend/src/routes/admin/discount-codes.js +0 -418
  84. package/dist/apps/backend/src/routes/admin/inventory.d.ts +0 -273
  85. package/dist/apps/backend/src/routes/admin/inventory.js +0 -199
  86. package/dist/apps/backend/src/routes/admin/orders.d.ts +0 -1780
  87. package/dist/apps/backend/src/routes/admin/orders.js +0 -552
  88. package/dist/apps/backend/src/routes/admin/products.d.ts +0 -860
  89. package/dist/apps/backend/src/routes/admin/products.js +0 -126
  90. package/dist/apps/backend/src/routes/admin/stats.d.ts +0 -290
  91. package/dist/apps/backend/src/routes/admin/stats.js +0 -55
  92. package/dist/apps/backend/src/routes/admin/variants.d.ts +0 -239
  93. package/dist/apps/backend/src/routes/admin/variants.js +0 -197
  94. package/dist/apps/backend/src/routes/admin/warehouses.d.ts +0 -373
  95. package/dist/apps/backend/src/routes/admin/warehouses.js +0 -123
  96. package/dist/apps/backend/src/routes/public/brands.d.ts +0 -40
  97. package/dist/apps/backend/src/routes/public/brands.js +0 -38
  98. package/dist/apps/backend/src/routes/public/carts.d.ts +0 -2657
  99. package/dist/apps/backend/src/routes/public/carts.js +0 -778
  100. package/dist/apps/backend/src/routes/public/delivery-zones.d.ts +0 -37
  101. package/dist/apps/backend/src/routes/public/delivery-zones.js +0 -64
  102. package/dist/apps/backend/src/routes/public/orders.d.ts +0 -609
  103. package/dist/apps/backend/src/routes/public/orders.js +0 -184
  104. package/dist/apps/backend/src/routes/public/products.d.ts +0 -449
  105. package/dist/apps/backend/src/routes/public/products.js +0 -133
  106. package/dist/apps/backend/src/types/index.d.ts +0 -43
  107. package/dist/apps/backend/src/types/index.js +0 -2
  108. package/dist/apps/backend/src/validators/brand.d.ts +0 -17
  109. package/dist/apps/backend/src/validators/brand.js +0 -15
  110. package/dist/apps/backend/src/validators/delivery-zone.d.ts +0 -35
  111. package/dist/apps/backend/src/validators/delivery-zone.js +0 -55
  112. package/dist/apps/backend/src/validators/discount-code.d.ts +0 -74
  113. package/dist/apps/backend/src/validators/discount-code.js +0 -50
  114. package/dist/apps/backend/src/validators/inventory.d.ts +0 -20
  115. package/dist/apps/backend/src/validators/inventory.js +0 -15
  116. package/dist/apps/backend/src/validators/order.d.ts +0 -58
  117. package/dist/apps/backend/src/validators/order.js +0 -62
  118. package/dist/apps/backend/src/validators/product.d.ts +0 -18
  119. package/dist/apps/backend/src/validators/product.js +0 -19
  120. package/dist/apps/backend/src/validators/variant.d.ts +0 -19
  121. package/dist/apps/backend/src/validators/variant.js +0 -19
  122. package/dist/apps/backend/src/validators/warehouse.d.ts +0 -15
  123. package/dist/apps/backend/src/validators/warehouse.js +0 -15
  124. package/dist/packages/api-client/src/backend-types.d.ts +0 -10
  125. package/dist/packages/api-client/src/backend-types.js +0 -10
  126. package/dist/packages/api-client/src/client.d.ts +0 -20
  127. package/dist/packages/api-client/src/client.js +0 -40
  128. package/dist/packages/api-client/src/enum-types.d.ts +0 -8
  129. package/dist/packages/api-client/src/enum-types.js +0 -5
  130. package/dist/packages/api-client/src/fetchers/brands.d.ts +0 -25
  131. package/dist/packages/api-client/src/fetchers/brands.js +0 -26
  132. package/dist/packages/api-client/src/fetchers/carts.d.ts +0 -2337
  133. package/dist/packages/api-client/src/fetchers/carts.js +0 -174
  134. package/dist/packages/api-client/src/fetchers/delivery-zones.d.ts +0 -30
  135. package/dist/packages/api-client/src/fetchers/delivery-zones.js +0 -26
  136. package/dist/packages/api-client/src/fetchers/index.d.ts +0 -22
  137. package/dist/packages/api-client/src/fetchers/index.js +0 -22
  138. package/dist/packages/api-client/src/fetchers/orders.d.ts +0 -544
  139. package/dist/packages/api-client/src/fetchers/orders.js +0 -44
  140. package/dist/packages/api-client/src/fetchers/products.d.ts +0 -386
  141. package/dist/packages/api-client/src/fetchers/products.js +0 -42
  142. package/dist/packages/api-client/src/hooks/admin/abandoned-carts.d.ts +0 -535
  143. package/dist/packages/api-client/src/hooks/admin/abandoned-carts.js +0 -83
  144. package/dist/packages/api-client/src/hooks/admin/brands.d.ts +0 -79
  145. package/dist/packages/api-client/src/hooks/admin/brands.js +0 -108
  146. package/dist/packages/api-client/src/hooks/admin/customers.d.ts +0 -280
  147. package/dist/packages/api-client/src/hooks/admin/customers.js +0 -26
  148. package/dist/packages/api-client/src/hooks/admin/delivery-zones.d.ts +0 -278
  149. package/dist/packages/api-client/src/hooks/admin/delivery-zones.js +0 -176
  150. package/dist/packages/api-client/src/hooks/admin/discount-codes.d.ts +0 -299
  151. package/dist/packages/api-client/src/hooks/admin/discount-codes.js +0 -165
  152. package/dist/packages/api-client/src/hooks/admin/index.d.ts +0 -16
  153. package/dist/packages/api-client/src/hooks/admin/index.js +0 -16
  154. package/dist/packages/api-client/src/hooks/admin/inventory.d.ts +0 -224
  155. package/dist/packages/api-client/src/hooks/admin/inventory.js +0 -107
  156. package/dist/packages/api-client/src/hooks/admin/orders.d.ts +0 -1674
  157. package/dist/packages/api-client/src/hooks/admin/orders.js +0 -178
  158. package/dist/packages/api-client/src/hooks/admin/products.d.ts +0 -374
  159. package/dist/packages/api-client/src/hooks/admin/products.js +0 -89
  160. package/dist/packages/api-client/src/hooks/admin/stats.d.ts +0 -279
  161. package/dist/packages/api-client/src/hooks/admin/stats.js +0 -25
  162. package/dist/packages/api-client/src/hooks/admin/variants.d.ts +0 -115
  163. package/dist/packages/api-client/src/hooks/admin/variants.js +0 -127
  164. package/dist/packages/api-client/src/hooks/admin/warehouses.d.ts +0 -277
  165. package/dist/packages/api-client/src/hooks/admin/warehouses.js +0 -108
  166. package/dist/packages/api-client/src/hooks/public/brands.d.ts +0 -33
  167. package/dist/packages/api-client/src/hooks/public/brands.js +0 -30
  168. package/dist/packages/api-client/src/hooks/public/carts.d.ts +0 -2407
  169. package/dist/packages/api-client/src/hooks/public/carts.js +0 -213
  170. package/dist/packages/api-client/src/hooks/public/delivery-zones.d.ts +0 -36
  171. package/dist/packages/api-client/src/hooks/public/delivery-zones.js +0 -28
  172. package/dist/packages/api-client/src/hooks/public/index.d.ts +0 -10
  173. package/dist/packages/api-client/src/hooks/public/index.js +0 -10
  174. package/dist/packages/api-client/src/hooks/public/orders.d.ts +0 -563
  175. package/dist/packages/api-client/src/hooks/public/orders.js +0 -50
  176. package/dist/packages/api-client/src/hooks/public/products.d.ts +0 -398
  177. package/dist/packages/api-client/src/hooks/public/products.js +0 -47
  178. package/dist/packages/api-client/src/hooks/use-query-unwrapped.d.ts +0 -20
  179. package/dist/packages/api-client/src/hooks/use-query-unwrapped.js +0 -22
  180. package/dist/packages/api-client/src/hooks/useApiConfig.d.ts +0 -12
  181. package/dist/packages/api-client/src/hooks/useApiConfig.js +0 -14
  182. package/dist/packages/api-client/src/index.d.ts +0 -20
  183. package/dist/packages/api-client/src/index.js +0 -25
  184. package/dist/packages/api-client/src/provider.d.ts +0 -36
  185. package/dist/packages/api-client/src/provider.js +0 -54
  186. package/dist/packages/api-client/src/rpc-client.d.ts +0 -9639
  187. package/dist/packages/api-client/src/rpc-client.js +0 -78
  188. package/dist/packages/api-client/src/rpc-types.d.ts +0 -76
  189. package/dist/packages/api-client/src/rpc-types.js +0 -7
  190. package/dist/packages/api-client/src/types.d.ts +0 -34
  191. package/dist/packages/api-client/src/types.js +0 -16
  192. package/dist/packages/api-client/src/utils/query-keys.d.ts +0 -106
  193. package/dist/packages/api-client/src/utils/query-keys.js +0 -108
@@ -1,418 +0,0 @@
1
- import { Hono } from 'hono';
2
- import { zValidator } from '@hono/zod-validator';
3
- import { getPrismaClient } from '../../lib/prisma';
4
- import { createDiscountCodeSchema, updateDiscountCodeSchema, bulkGenerateCodesSchema, } from '../../validators/discount-code';
5
- import { generateDiscountCode } from '../../lib/discount';
6
- import { formatDiscountCodeResponse } from '../../lib/discount-code-response';
7
- const app = new Hono()
8
- // List discount codes
9
- .get('/', async (c) => {
10
- try {
11
- const prisma = getPrismaClient(c.env.DATABASE_URL);
12
- const page = parseInt(c.req.query('page') || '1');
13
- const limit = parseInt(c.req.query('limit') || '20');
14
- const category = c.req.query('category');
15
- const brandId = c.req.query('brandId');
16
- const isActive = c.req.query('isActive');
17
- const search = c.req.query('search');
18
- const where = {
19
- deletedAt: null,
20
- };
21
- if (category && category !== 'all') {
22
- where.category = category;
23
- }
24
- if (brandId) {
25
- where.brandId = brandId;
26
- }
27
- if (isActive !== undefined) {
28
- where.isActive = isActive === 'true';
29
- }
30
- if (search) {
31
- where.OR = [
32
- { code: { contains: search, mode: 'insensitive' } },
33
- { description: { contains: search, mode: 'insensitive' } },
34
- ];
35
- }
36
- const [codes, total] = await Promise.all([
37
- prisma.discountCode.findMany({
38
- where,
39
- include: {
40
- brand: true,
41
- _count: {
42
- select: {
43
- usageLog: true,
44
- },
45
- },
46
- },
47
- orderBy: { createdAt: 'desc' },
48
- skip: (page - 1) * limit,
49
- take: limit,
50
- }),
51
- prisma.discountCode.count({ where }),
52
- ]);
53
- const enhancedCodes = codes.map(formatDiscountCodeResponse);
54
- return c.json({
55
- data: enhancedCodes,
56
- pagination: {
57
- page,
58
- limit,
59
- total,
60
- totalPages: Math.ceil(total / limit),
61
- },
62
- });
63
- }
64
- catch (error) {
65
- console.error('Error fetching discount codes:', error);
66
- return c.json({ error: { code: 'INTERNAL_ERROR', message: error.message } }, 500);
67
- }
68
- })
69
- // Get single discount code
70
- .get('/:id', async (c) => {
71
- try {
72
- const id = c.req.param('id');
73
- const prisma = getPrismaClient(c.env.DATABASE_URL);
74
- const code = await prisma.discountCode.findFirst({
75
- where: { id, deletedAt: null },
76
- include: {
77
- brand: true,
78
- _count: {
79
- select: {
80
- usageLog: true,
81
- orders: true,
82
- },
83
- },
84
- },
85
- });
86
- if (!code) {
87
- return c.json({ error: { code: 'NOT_FOUND', message: 'Discount code not found' } }, 404);
88
- }
89
- return c.json({
90
- ...formatDiscountCodeResponse(code),
91
- _count: code._count ? {
92
- usageLog: code._count.usageLog,
93
- orders: code._count.orders,
94
- } : null,
95
- });
96
- }
97
- catch (error) {
98
- console.error('Error fetching discount code:', error);
99
- return c.json({ error: { code: 'INTERNAL_ERROR', message: error.message } }, 500);
100
- }
101
- })
102
- // Create discount code
103
- .post('/', zValidator('json', createDiscountCodeSchema), async (c) => {
104
- try {
105
- const input = c.req.valid('json');
106
- const prisma = getPrismaClient(c.env.DATABASE_URL);
107
- const user = c.get('user');
108
- // Check if code already exists
109
- const existing = await prisma.discountCode.findUnique({
110
- where: { code: input.code },
111
- });
112
- if (existing) {
113
- return c.json({ error: { code: 'CODE_EXISTS', message: 'Discount code already exists' } }, 400);
114
- }
115
- // If brandId provided, verify it exists
116
- if (input.brandId) {
117
- const brand = await prisma.brand.findFirst({
118
- where: { id: input.brandId, deletedAt: null },
119
- });
120
- if (!brand) {
121
- return c.json({ error: { code: 'BRAND_NOT_FOUND', message: 'Brand not found' } }, 404);
122
- }
123
- }
124
- // Create the discount code
125
- const discountCode = await prisma.discountCode.create({
126
- data: {
127
- code: input.code,
128
- brandId: input.brandId ?? null,
129
- type: input.type,
130
- value: input.value,
131
- description: input.description,
132
- category: input.category ?? 'manual',
133
- minPurchase: input.minPurchase ?? null,
134
- maxDiscount: input.maxDiscount ?? null,
135
- usageLimit: input.usageLimit ?? null,
136
- perCustomerLimit: input.perCustomerLimit ?? null,
137
- validFrom: input.validFrom ? new Date(input.validFrom) : new Date(),
138
- validUntil: input.validUntil ? new Date(input.validUntil) : null,
139
- isActive: input.isActive ?? true,
140
- isAutoApply: input.isAutoApply ?? false,
141
- createdBy: user?.id,
142
- },
143
- include: {
144
- brand: true,
145
- },
146
- });
147
- return c.json(formatDiscountCodeResponse(discountCode), 201);
148
- }
149
- catch (error) {
150
- console.error('Error creating discount code:', error);
151
- return c.json({ error: { code: 'INTERNAL_ERROR', message: error.message } }, 500);
152
- }
153
- })
154
- // Update discount code
155
- .patch('/:id', zValidator('json', updateDiscountCodeSchema), async (c) => {
156
- try {
157
- const id = c.req.param('id');
158
- const input = c.req.valid('json');
159
- const prisma = getPrismaClient(c.env.DATABASE_URL);
160
- const existing = await prisma.discountCode.findFirst({
161
- where: { id, deletedAt: null },
162
- });
163
- if (!existing) {
164
- return c.json({ error: { code: 'NOT_FOUND', message: 'Discount code not found' } }, 404);
165
- }
166
- // If updating code, check for duplicates
167
- if (input.code && input.code !== existing.code) {
168
- const duplicate = await prisma.discountCode.findUnique({
169
- where: { code: input.code },
170
- });
171
- if (duplicate) {
172
- return c.json({ error: { code: 'CODE_EXISTS', message: 'Discount code already exists' } }, 400);
173
- }
174
- }
175
- const updateData = {};
176
- if (input.code !== undefined)
177
- updateData.code = input.code;
178
- if (input.type !== undefined)
179
- updateData.type = input.type;
180
- if (input.value !== undefined)
181
- updateData.value = input.value;
182
- if (input.description !== undefined)
183
- updateData.description = input.description;
184
- if (input.category !== undefined)
185
- updateData.category = input.category;
186
- if (input.minPurchase !== undefined)
187
- updateData.minPurchase = input.minPurchase;
188
- if (input.maxDiscount !== undefined)
189
- updateData.maxDiscount = input.maxDiscount;
190
- if (input.usageLimit !== undefined)
191
- updateData.usageLimit = input.usageLimit;
192
- if (input.perCustomerLimit !== undefined)
193
- updateData.perCustomerLimit = input.perCustomerLimit;
194
- if (input.validFrom !== undefined)
195
- updateData.validFrom = new Date(input.validFrom);
196
- if (input.validUntil !== undefined)
197
- updateData.validUntil = input.validUntil ? new Date(input.validUntil) : null;
198
- if (input.isActive !== undefined)
199
- updateData.isActive = input.isActive;
200
- if (input.isAutoApply !== undefined)
201
- updateData.isAutoApply = input.isAutoApply;
202
- const discountCode = await prisma.discountCode.update({
203
- where: { id },
204
- data: updateData,
205
- include: {
206
- brand: true,
207
- },
208
- });
209
- return c.json(formatDiscountCodeResponse(discountCode));
210
- }
211
- catch (error) {
212
- console.error('Error updating discount code:', error);
213
- return c.json({ error: { code: 'INTERNAL_ERROR', message: error.message } }, 500);
214
- }
215
- })
216
- // Delete discount code (soft delete)
217
- .delete('/:id', async (c) => {
218
- try {
219
- const id = c.req.param('id');
220
- const prisma = getPrismaClient(c.env.DATABASE_URL);
221
- const existing = await prisma.discountCode.findFirst({
222
- where: { id, deletedAt: null },
223
- });
224
- if (!existing) {
225
- return c.json({ error: { code: 'NOT_FOUND', message: 'Discount code not found' } }, 404);
226
- }
227
- await prisma.discountCode.update({
228
- where: { id },
229
- data: { deletedAt: new Date() },
230
- });
231
- return c.status(204);
232
- }
233
- catch (error) {
234
- console.error('Error deleting discount code:', error);
235
- return c.json({ error: { code: 'INTERNAL_ERROR', message: error.message } }, 500);
236
- }
237
- })
238
- // Get discount code analytics
239
- .get('/:id/analytics', async (c) => {
240
- try {
241
- const id = c.req.param('id');
242
- const prisma = getPrismaClient(c.env.DATABASE_URL);
243
- const code = await prisma.discountCode.findFirst({
244
- where: { id, deletedAt: null },
245
- include: {
246
- brand: true,
247
- usageLog: {
248
- include: {
249
- order: true,
250
- },
251
- orderBy: {
252
- createdAt: 'desc',
253
- },
254
- },
255
- },
256
- });
257
- if (!code) {
258
- return c.json({ error: { code: 'NOT_FOUND', message: 'Discount code not found' } }, 404);
259
- }
260
- // Calculate analytics
261
- const totalUses = code.usageLog.length;
262
- const totalDiscountGiven = code.usageLog.reduce((sum, log) => sum + log.discountAmount.toNumber(), 0);
263
- const totalRevenue = code.usageLog.reduce((sum, log) => sum + log.order.totalPrice.toNumber(), 0);
264
- const averageOrderValue = totalUses > 0 ? totalRevenue / totalUses : 0;
265
- const averageDiscount = totalUses > 0 ? totalDiscountGiven / totalUses : 0;
266
- // Unique customers
267
- const uniqueCustomers = new Set(code.usageLog.map((log) => log.customerPhone)).size;
268
- // Usage by date (last 30 days)
269
- const thirtyDaysAgo = new Date();
270
- thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
271
- const usageByDate = code.usageLog
272
- .filter((log) => log.createdAt >= thirtyDaysAgo)
273
- .reduce((acc, log) => {
274
- const date = log.createdAt.toISOString().split('T')[0];
275
- if (!acc[date]) {
276
- acc[date] = { date, uses: 0, revenue: 0, discount: 0 };
277
- }
278
- acc[date].uses++;
279
- acc[date].revenue += log.order.totalPrice;
280
- acc[date].discount += log.discountAmount;
281
- return acc;
282
- }, {});
283
- const usageByDateArray = Object.values(usageByDate).sort((a, b) => a.date.localeCompare(b.date));
284
- // Top customers
285
- const customerStats = code.usageLog.reduce((acc, log) => {
286
- if (!acc[log.customerPhone]) {
287
- acc[log.customerPhone] = { phone: log.customerPhone, uses: 0, revenue: 0, discount: 0 };
288
- }
289
- acc[log.customerPhone].uses++;
290
- acc[log.customerPhone].revenue += log.order.totalPrice;
291
- acc[log.customerPhone].discount += log.discountAmount;
292
- return acc;
293
- }, {});
294
- const topCustomers = Object.values(customerStats)
295
- .sort((a, b) => b.revenue - a.revenue)
296
- .slice(0, 10);
297
- // Recent usages with order details
298
- const recentUsages = code.usageLog.slice(0, 20).map((log) => ({
299
- id: log.id,
300
- orderId: log.orderId,
301
- customerPhone: log.customerPhone,
302
- usedAt: log.createdAt,
303
- discountAmount: log.discountAmount,
304
- orderTotal: log.order.totalPrice,
305
- order: {
306
- id: log.order.id,
307
- phone: log.order.phone,
308
- },
309
- }));
310
- return c.json({
311
- ...formatDiscountCodeResponse(code),
312
- totalUses,
313
- usagePercentage: code.usageLimit ? (totalUses / code.usageLimit) * 100 : null,
314
- totalDiscountGiven,
315
- totalRevenue,
316
- averageOrderValue,
317
- averageDiscount,
318
- uniqueCustomers,
319
- usageByDate: usageByDateArray,
320
- topCustomers,
321
- recentUsages,
322
- });
323
- }
324
- catch (error) {
325
- console.error('Error fetching discount code analytics:', error);
326
- return c.json({ error: { code: 'INTERNAL_ERROR', message: error.message } }, 500);
327
- }
328
- })
329
- // Bulk generate discount codes
330
- .post('/bulk-generate', zValidator('json', bulkGenerateCodesSchema), async (c) => {
331
- try {
332
- const input = c.req.valid('json');
333
- const prisma = getPrismaClient(c.env.DATABASE_URL);
334
- const user = c.get('user');
335
- const codes = [];
336
- const codeRecords = [];
337
- // Generate unique codes
338
- for (let i = 0; i < input.count; i++) {
339
- let code;
340
- let attempts = 0;
341
- const maxAttempts = 10;
342
- do {
343
- const randomPart = generateDiscountCode().replace('CART', '');
344
- code = `${input.prefix}${randomPart}`;
345
- attempts++;
346
- if (attempts >= maxAttempts) {
347
- return c.json({ error: { code: 'GENERATION_FAILED', message: 'Failed to generate unique codes' } }, 500);
348
- }
349
- } while (codes.includes(code) || await prisma.discountCode.findUnique({ where: { code } }));
350
- codes.push(code);
351
- codeRecords.push({
352
- code,
353
- brandId: input.brandId ?? null,
354
- type: input.type,
355
- value: input.value,
356
- description: input.description ?? `Bulk generated - ${input.prefix}`,
357
- category: input.category ?? 'manual',
358
- minPurchase: input.minPurchase ?? null,
359
- maxDiscount: input.maxDiscount ?? null,
360
- usageLimit: 1, // Each bulk code can only be used once by default
361
- perCustomerLimit: input.perCustomerLimit ?? 1,
362
- validFrom: input.validFrom ? new Date(input.validFrom) : new Date(),
363
- validUntil: input.validUntil ? new Date(input.validUntil) : null,
364
- isActive: input.isActive ?? true,
365
- isAutoApply: false,
366
- createdBy: user?.id,
367
- });
368
- }
369
- // Create all codes in a transaction
370
- await prisma.discountCode.createMany({
371
- data: codeRecords,
372
- });
373
- return c.json({
374
- codes,
375
- count: codes.length,
376
- }, 201);
377
- }
378
- catch (error) {
379
- console.error('Error bulk generating codes:', error);
380
- return c.json({ error: { code: 'INTERNAL_ERROR', message: error.message } }, 500);
381
- }
382
- })
383
- // Get overall discount code stats
384
- .get('/stats/overview', async (c) => {
385
- try {
386
- const prisma = getPrismaClient(c.env.DATABASE_URL);
387
- const [totalCodes, activeCodes, totalUsage, totalDiscountGiven, totalRevenue,] = await Promise.all([
388
- prisma.discountCode.count({ where: { deletedAt: null } }),
389
- prisma.discountCode.count({ where: { deletedAt: null, isActive: true } }),
390
- prisma.discountCodeUsage.count(),
391
- prisma.discountCodeUsage.aggregate({
392
- _sum: { discountAmount: true },
393
- }),
394
- prisma.discountCodeUsage.aggregate({
395
- _sum: { originalAmount: true },
396
- }),
397
- ]);
398
- // Category breakdown
399
- const codesByCategory = await prisma.discountCode.groupBy({
400
- by: ['category'],
401
- where: { deletedAt: null },
402
- _count: true,
403
- });
404
- return c.json({
405
- totalCodes,
406
- activeCodes,
407
- totalUsage,
408
- totalDiscountGiven: totalDiscountGiven._sum.discountAmount || 0,
409
- totalRevenue: totalRevenue._sum.originalAmount || 0,
410
- codesByCategory,
411
- });
412
- }
413
- catch (error) {
414
- console.error('Error fetching discount code stats:', error);
415
- return c.json({ error: { code: 'INTERNAL_ERROR', message: error.message } }, 500);
416
- }
417
- });
418
- export default app;
@@ -1,273 +0,0 @@
1
- import { AppContext } from '../../types';
2
- declare const app: import("hono/hono-base").HonoBase<AppContext, {
3
- "/": {
4
- $get: {
5
- input: {};
6
- output: {
7
- variantId: string;
8
- warehouseId: string;
9
- sku: string;
10
- productName: string;
11
- name: string;
12
- brandName: string;
13
- warehouseName: string;
14
- inventoryCount: number;
15
- lowStockThreshold: number;
16
- isLowStock: boolean;
17
- }[];
18
- outputFormat: "json";
19
- status: import("hono/utils/http-status").ContentfulStatusCode;
20
- } | {
21
- input: {};
22
- output: {
23
- error: {
24
- code: string;
25
- message: string;
26
- };
27
- };
28
- outputFormat: "json";
29
- status: 500;
30
- };
31
- };
32
- } & {
33
- "/adjust": {
34
- $post: {
35
- input: {};
36
- output: {};
37
- outputFormat: string;
38
- status: import("hono/utils/http-status").StatusCode;
39
- } | {
40
- input: {};
41
- output: {};
42
- outputFormat: string;
43
- status: import("hono/utils/http-status").StatusCode;
44
- };
45
- };
46
- } & {
47
- "/transfer": {
48
- $post: {
49
- input: {};
50
- output: {};
51
- outputFormat: string;
52
- status: import("hono/utils/http-status").StatusCode;
53
- } | {
54
- input: {};
55
- output: {};
56
- outputFormat: string;
57
- status: import("hono/utils/http-status").StatusCode;
58
- };
59
- };
60
- } & {
61
- "/transactions": {
62
- $get: {
63
- input: {};
64
- output: {
65
- data: {
66
- id: string;
67
- type: import("@prisma/client").$Enums.InventoryTransactionType;
68
- quantity: number;
69
- balanceAfter: number;
70
- reason: string;
71
- orderId: string;
72
- orderNumber: number;
73
- userId: string;
74
- metadata: string | number | boolean | {
75
- [x: string]: string | number | boolean | /*elided*/ any | {
76
- [x: number]: string | number | boolean | /*elided*/ any | /*elided*/ any;
77
- length: number;
78
- toString: never;
79
- toLocaleString: never;
80
- pop: never;
81
- push: never;
82
- concat: never;
83
- join: never;
84
- reverse: never;
85
- shift: never;
86
- slice: never;
87
- sort: never;
88
- splice: never;
89
- unshift: never;
90
- indexOf: never;
91
- lastIndexOf: never;
92
- every: never;
93
- some: never;
94
- forEach: never;
95
- map: never;
96
- filter: never;
97
- reduce: never;
98
- reduceRight: never;
99
- find: never;
100
- findIndex: never;
101
- fill: never;
102
- copyWithin: never;
103
- entries: never;
104
- keys: never;
105
- values: never;
106
- includes: never;
107
- flatMap: never;
108
- flat: never;
109
- [Symbol.iterator]: never;
110
- readonly [Symbol.unscopables]: {
111
- [x: number]: boolean;
112
- length?: boolean;
113
- toString?: boolean;
114
- toLocaleString?: boolean;
115
- pop?: boolean;
116
- push?: boolean;
117
- concat?: boolean;
118
- join?: boolean;
119
- reverse?: boolean;
120
- shift?: boolean;
121
- slice?: boolean;
122
- sort?: boolean;
123
- splice?: boolean;
124
- unshift?: boolean;
125
- indexOf?: boolean;
126
- lastIndexOf?: boolean;
127
- every?: boolean;
128
- some?: boolean;
129
- forEach?: boolean;
130
- map?: boolean;
131
- filter?: boolean;
132
- reduce?: boolean;
133
- reduceRight?: boolean;
134
- find?: boolean;
135
- findIndex?: boolean;
136
- fill?: boolean;
137
- copyWithin?: boolean;
138
- entries?: boolean;
139
- keys?: boolean;
140
- values?: boolean;
141
- includes?: boolean;
142
- flatMap?: boolean;
143
- flat?: boolean;
144
- };
145
- };
146
- } | {
147
- [x: number]: string | number | boolean | {
148
- [x: string]: string | number | boolean | /*elided*/ any | /*elided*/ any;
149
- } | /*elided*/ any;
150
- length: number;
151
- toString: never;
152
- toLocaleString: never;
153
- pop: never;
154
- push: never;
155
- concat: never;
156
- join: never;
157
- reverse: never;
158
- shift: never;
159
- slice: never;
160
- sort: never;
161
- splice: never;
162
- unshift: never;
163
- indexOf: never;
164
- lastIndexOf: never;
165
- every: never;
166
- some: never;
167
- forEach: never;
168
- map: never;
169
- filter: never;
170
- reduce: never;
171
- reduceRight: never;
172
- find: never;
173
- findIndex: never;
174
- fill: never;
175
- copyWithin: never;
176
- entries: never;
177
- keys: never;
178
- values: never;
179
- includes: never;
180
- flatMap: never;
181
- flat: never;
182
- [Symbol.iterator]: never;
183
- readonly [Symbol.unscopables]: {
184
- [x: number]: boolean;
185
- length?: boolean;
186
- toString?: boolean;
187
- toLocaleString?: boolean;
188
- pop?: boolean;
189
- push?: boolean;
190
- concat?: boolean;
191
- join?: boolean;
192
- reverse?: boolean;
193
- shift?: boolean;
194
- slice?: boolean;
195
- sort?: boolean;
196
- splice?: boolean;
197
- unshift?: boolean;
198
- indexOf?: boolean;
199
- lastIndexOf?: boolean;
200
- every?: boolean;
201
- some?: boolean;
202
- forEach?: boolean;
203
- map?: boolean;
204
- filter?: boolean;
205
- reduce?: boolean;
206
- reduceRight?: boolean;
207
- find?: boolean;
208
- findIndex?: boolean;
209
- fill?: boolean;
210
- copyWithin?: boolean;
211
- entries?: boolean;
212
- keys?: boolean;
213
- values?: boolean;
214
- includes?: boolean;
215
- flatMap?: boolean;
216
- flat?: boolean;
217
- };
218
- };
219
- createdAt: string;
220
- variant: {
221
- id: string;
222
- sku: string;
223
- name: string;
224
- productName: string;
225
- brandName: string;
226
- };
227
- warehouse: {
228
- id: string;
229
- name: string;
230
- };
231
- }[];
232
- pagination: {
233
- page: number;
234
- limit: number;
235
- total: number;
236
- totalPages: number;
237
- };
238
- };
239
- outputFormat: "json";
240
- status: import("hono/utils/http-status").ContentfulStatusCode;
241
- } | {
242
- input: {};
243
- output: {
244
- error: {
245
- code: string;
246
- message: string;
247
- };
248
- };
249
- outputFormat: "json";
250
- status: 500;
251
- };
252
- };
253
- } & {
254
- "/low-stock": {
255
- $get: {
256
- input: {};
257
- output: never;
258
- outputFormat: "json";
259
- status: import("hono/utils/http-status").ContentfulStatusCode;
260
- } | {
261
- input: {};
262
- output: {
263
- error: {
264
- code: string;
265
- message: string;
266
- };
267
- };
268
- outputFormat: "json";
269
- status: 500;
270
- };
271
- };
272
- }, "/">;
273
- export default app;