@windrun-huaiin/backend-core 10.0.1

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 (198) hide show
  1. package/LICENSE +21 -0
  2. package/dist/app/api/stripe/checkout/route.d.ts +19 -0
  3. package/dist/app/api/stripe/checkout/route.d.ts.map +1 -0
  4. package/dist/app/api/stripe/checkout/route.js +120 -0
  5. package/dist/app/api/stripe/checkout/route.mjs +118 -0
  6. package/dist/app/api/stripe/customer-portal/route.d.ts +11 -0
  7. package/dist/app/api/stripe/customer-portal/route.d.ts.map +1 -0
  8. package/dist/app/api/stripe/customer-portal/route.js +73 -0
  9. package/dist/app/api/stripe/customer-portal/route.mjs +71 -0
  10. package/dist/app/api/user/anonymous/init/route.d.ts +7 -0
  11. package/dist/app/api/user/anonymous/init/route.d.ts.map +1 -0
  12. package/dist/app/api/user/anonymous/init/route.js +210 -0
  13. package/dist/app/api/user/anonymous/init/route.mjs +208 -0
  14. package/dist/app/api/webhook/clerk/user/route.d.ts +7 -0
  15. package/dist/app/api/webhook/clerk/user/route.d.ts.map +1 -0
  16. package/dist/app/api/webhook/clerk/user/route.js +202 -0
  17. package/dist/app/api/webhook/clerk/user/route.mjs +200 -0
  18. package/dist/app/api/webhook/stripe/route.d.ts +8 -0
  19. package/dist/app/api/webhook/stripe/route.d.ts.map +1 -0
  20. package/dist/app/api/webhook/stripe/route.js +70 -0
  21. package/dist/app/api/webhook/stripe/route.mjs +67 -0
  22. package/dist/index.d.ts +7 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +83 -0
  25. package/dist/index.mjs +18 -0
  26. package/dist/lib/auth-utils.d.ts +46 -0
  27. package/dist/lib/auth-utils.d.ts.map +1 -0
  28. package/dist/lib/auth-utils.js +107 -0
  29. package/dist/lib/auth-utils.mjs +102 -0
  30. package/dist/lib/credit-init.d.ts +8 -0
  31. package/dist/lib/credit-init.d.ts.map +1 -0
  32. package/dist/lib/credit-init.js +16 -0
  33. package/dist/lib/credit-init.mjs +10 -0
  34. package/dist/lib/index.d.ts +5 -0
  35. package/dist/lib/index.d.ts.map +1 -0
  36. package/dist/lib/index.js +31 -0
  37. package/dist/lib/index.mjs +4 -0
  38. package/dist/lib/money-price-config.d.ts +51 -0
  39. package/dist/lib/money-price-config.d.ts.map +1 -0
  40. package/dist/lib/money-price-config.js +156 -0
  41. package/dist/lib/money-price-config.mjs +151 -0
  42. package/dist/lib/stripe-config.d.ts +31 -0
  43. package/dist/lib/stripe-config.d.ts.map +1 -0
  44. package/dist/lib/stripe-config.js +278 -0
  45. package/dist/lib/stripe-config.mjs +268 -0
  46. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.46.2_tslib@2.8.1_typescript@5.9.3/node_modules/tslib/tslib.es6.js +48 -0
  47. package/dist/node_modules/.pnpm/@rollup_plugin-typescript@12.1.4_rollup@4.46.2_tslib@2.8.1_typescript@5.9.3/node_modules/tslib/tslib.es6.mjs +45 -0
  48. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.js +54 -0
  49. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.mjs +51 -0
  50. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.js +44 -0
  51. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.mjs +35 -0
  52. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.js +31 -0
  53. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.mjs +18 -0
  54. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.js +587 -0
  55. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.mjs +527 -0
  56. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.js +447 -0
  57. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.mjs +399 -0
  58. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.js +245 -0
  59. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.mjs +232 -0
  60. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.js +68 -0
  61. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.mjs +62 -0
  62. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.js +39 -0
  63. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.mjs +37 -0
  64. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.js +80 -0
  65. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.mjs +75 -0
  66. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.js +101 -0
  67. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.mjs +86 -0
  68. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.js +102 -0
  69. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.mjs +76 -0
  70. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.js +56 -0
  71. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.mjs +52 -0
  72. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.js +1205 -0
  73. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.mjs +1157 -0
  74. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.js +407 -0
  75. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.mjs +374 -0
  76. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.js +9 -0
  77. package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.mjs +7 -0
  78. package/dist/prisma/client.d.ts +2 -0
  79. package/dist/prisma/client.d.ts.map +1 -0
  80. package/dist/prisma/client.js +12 -0
  81. package/dist/prisma/client.mjs +1 -0
  82. package/dist/prisma/index.d.ts +4 -0
  83. package/dist/prisma/index.d.ts.map +1 -0
  84. package/dist/prisma/index.js +10 -0
  85. package/dist/prisma/index.mjs +2 -0
  86. package/dist/prisma/prisma-transaction-util.d.ts +3 -0
  87. package/dist/prisma/prisma-transaction-util.d.ts.map +1 -0
  88. package/dist/prisma/prisma-transaction-util.js +29 -0
  89. package/dist/prisma/prisma-transaction-util.mjs +27 -0
  90. package/dist/prisma/prisma.d.ts +4 -0
  91. package/dist/prisma/prisma.d.ts.map +1 -0
  92. package/dist/prisma/prisma.js +109 -0
  93. package/dist/prisma/prisma.mjs +106 -0
  94. package/dist/services/aggregate/billing.aggregate.service.d.ts +83 -0
  95. package/dist/services/aggregate/billing.aggregate.service.d.ts.map +1 -0
  96. package/dist/services/aggregate/billing.aggregate.service.js +308 -0
  97. package/dist/services/aggregate/billing.aggregate.service.mjs +306 -0
  98. package/dist/services/aggregate/index.d.ts +3 -0
  99. package/dist/services/aggregate/index.d.ts.map +1 -0
  100. package/dist/services/aggregate/index.js +9 -0
  101. package/dist/services/aggregate/index.mjs +2 -0
  102. package/dist/services/aggregate/user.aggregate.service.d.ts +34 -0
  103. package/dist/services/aggregate/user.aggregate.service.d.ts.map +1 -0
  104. package/dist/services/aggregate/user.aggregate.service.js +136 -0
  105. package/dist/services/aggregate/user.aggregate.service.mjs +133 -0
  106. package/dist/services/context/index.d.ts +2 -0
  107. package/dist/services/context/index.d.ts.map +1 -0
  108. package/dist/services/context/index.js +13 -0
  109. package/dist/services/context/index.mjs +1 -0
  110. package/dist/services/context/user-context-service.d.ts +30 -0
  111. package/dist/services/context/user-context-service.d.ts.map +1 -0
  112. package/dist/services/context/user-context-service.js +170 -0
  113. package/dist/services/context/user-context-service.mjs +162 -0
  114. package/dist/services/database/apilog.service.d.ts +39 -0
  115. package/dist/services/database/apilog.service.d.ts.map +1 -0
  116. package/dist/services/database/apilog.service.js +174 -0
  117. package/dist/services/database/apilog.service.mjs +170 -0
  118. package/dist/services/database/constants.d.ts +73 -0
  119. package/dist/services/database/constants.d.ts.map +1 -0
  120. package/dist/services/database/constants.js +135 -0
  121. package/dist/services/database/constants.mjs +117 -0
  122. package/dist/services/database/credit.service.d.ts +107 -0
  123. package/dist/services/database/credit.service.d.ts.map +1 -0
  124. package/dist/services/database/credit.service.js +515 -0
  125. package/dist/services/database/credit.service.mjs +512 -0
  126. package/dist/services/database/creditAuditLog.service.d.ts +73 -0
  127. package/dist/services/database/creditAuditLog.service.d.ts.map +1 -0
  128. package/dist/services/database/creditAuditLog.service.js +305 -0
  129. package/dist/services/database/creditAuditLog.service.mjs +302 -0
  130. package/dist/services/database/index.d.ts +10 -0
  131. package/dist/services/database/index.d.ts.map +1 -0
  132. package/dist/services/database/index.js +38 -0
  133. package/dist/services/database/index.mjs +8 -0
  134. package/dist/services/database/prisma-model-type.d.ts +3 -0
  135. package/dist/services/database/prisma-model-type.d.ts.map +1 -0
  136. package/dist/services/database/subscription.service.d.ts +48 -0
  137. package/dist/services/database/subscription.service.d.ts.map +1 -0
  138. package/dist/services/database/subscription.service.js +267 -0
  139. package/dist/services/database/subscription.service.mjs +264 -0
  140. package/dist/services/database/transaction.service.d.ts +92 -0
  141. package/dist/services/database/transaction.service.d.ts.map +1 -0
  142. package/dist/services/database/transaction.service.js +326 -0
  143. package/dist/services/database/transaction.service.mjs +323 -0
  144. package/dist/services/database/user.service.d.ts +45 -0
  145. package/dist/services/database/user.service.d.ts.map +1 -0
  146. package/dist/services/database/user.service.js +180 -0
  147. package/dist/services/database/user.service.mjs +177 -0
  148. package/dist/services/database/userBackup.service.d.ts +45 -0
  149. package/dist/services/database/userBackup.service.d.ts.map +1 -0
  150. package/dist/services/database/userBackup.service.js +249 -0
  151. package/dist/services/database/userBackup.service.mjs +246 -0
  152. package/dist/services/stripe/index.d.ts +2 -0
  153. package/dist/services/stripe/index.d.ts.map +1 -0
  154. package/dist/services/stripe/index.js +7 -0
  155. package/dist/services/stripe/index.mjs +1 -0
  156. package/dist/services/stripe/webhook-handler.d.ts +6 -0
  157. package/dist/services/stripe/webhook-handler.d.ts.map +1 -0
  158. package/dist/services/stripe/webhook-handler.js +537 -0
  159. package/dist/services/stripe/webhook-handler.mjs +535 -0
  160. package/migrations/create.sql +176 -0
  161. package/migrations/db.init.sql +13 -0
  162. package/migrations/init-schema.sql +19 -0
  163. package/migrations/purge.sql +27 -0
  164. package/migrations/test-check.sql +167 -0
  165. package/package.json +123 -0
  166. package/prisma/schema.prisma +191 -0
  167. package/src/app/api/stripe/checkout/route.ts +145 -0
  168. package/src/app/api/stripe/customer-portal/route.ts +83 -0
  169. package/src/app/api/user/anonymous/init/route.ts +284 -0
  170. package/src/app/api/webhook/clerk/user/route.ts +249 -0
  171. package/src/app/api/webhook/stripe/route.ts +93 -0
  172. package/src/index.ts +6 -0
  173. package/src/lib/auth-utils.ts +101 -0
  174. package/src/lib/credit-init.ts +9 -0
  175. package/src/lib/index.ts +4 -0
  176. package/src/lib/money-price-config.ts +168 -0
  177. package/src/lib/stripe-config.ts +333 -0
  178. package/src/prisma/client.ts +2 -0
  179. package/src/prisma/index.ts +3 -0
  180. package/src/prisma/prisma-transaction-util.ts +24 -0
  181. package/src/prisma/prisma.ts +122 -0
  182. package/src/services/aggregate/billing.aggregate.service.ts +498 -0
  183. package/src/services/aggregate/index.ts +2 -0
  184. package/src/services/aggregate/user.aggregate.service.ts +168 -0
  185. package/src/services/context/index.ts +1 -0
  186. package/src/services/context/user-context-service.ts +200 -0
  187. package/src/services/database/apilog.service.ts +185 -0
  188. package/src/services/database/constants.ts +148 -0
  189. package/src/services/database/credit.service.ts +747 -0
  190. package/src/services/database/creditAuditLog.service.ts +402 -0
  191. package/src/services/database/index.ts +41 -0
  192. package/src/services/database/prisma-model-type.ts +13 -0
  193. package/src/services/database/subscription.service.ts +319 -0
  194. package/src/services/database/transaction.service.ts +447 -0
  195. package/src/services/database/user.service.ts +218 -0
  196. package/src/services/database/userBackup.service.ts +290 -0
  197. package/src/services/stripe/index.ts +1 -0
  198. package/src/services/stripe/webhook-handler.ts +648 -0
@@ -0,0 +1,402 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
3
+ import { Prisma } from './prisma-model-type';
4
+ import type { CreditAuditLog } from './prisma-model-type';
5
+ import { CreditType, OperationType } from './constants';
6
+ import { checkAndFallbackWithNonTCClient } from '../../prisma/index';
7
+
8
+ export class CreditAuditLogService {
9
+
10
+ // Record Credit Audit
11
+ async recordAuditLog(data: {
12
+ userId: string;
13
+ feature?: string;
14
+ operationReferId?: string;
15
+ creditType: string;
16
+ operationType: string;
17
+ creditsChange: number;
18
+ }, tx?: Prisma.TransactionClient): Promise<CreditAuditLog> {
19
+ const client = checkAndFallbackWithNonTCClient(tx);
20
+
21
+ return await client.creditAuditLog.create({
22
+ data: {
23
+ userId: data.userId,
24
+ feature: data.feature,
25
+ operationReferId: data.operationReferId,
26
+ creditType: data.creditType,
27
+ operationType: data.operationType,
28
+ creditsChange: data.creditsChange,
29
+ },
30
+ });
31
+ }
32
+
33
+ // Record Credit Operation (alias for recordUsage)
34
+ async recordCreditOperation(data: {
35
+ userId: string;
36
+ feature?: string;
37
+ operationReferId?: string;
38
+ creditType: string;
39
+ operationType: string;
40
+ creditsChange: number;
41
+ }, tx?: Prisma.TransactionClient): Promise<CreditAuditLog> {
42
+ return this.recordAuditLog(data, tx);
43
+ }
44
+
45
+ // Batch Record Credit Audit
46
+ async recordBatchAudit(
47
+ auditLogs: Prisma.CreditAuditLogCreateManyInput[],
48
+ tx?: Prisma.TransactionClient
49
+ ): Promise<number> {
50
+ const client = checkAndFallbackWithNonTCClient(tx);
51
+ const result = await client.creditAuditLog.createMany({
52
+ data: auditLogs,
53
+ });
54
+ return result.count;
55
+ }
56
+
57
+ // Get User Credit Audit History
58
+ async getUserCreditAuditHistory(
59
+ userId: string,
60
+ params?: {
61
+ creditType?: string;
62
+ operationType?: string;
63
+ feature?: string;
64
+ startDate?: Date;
65
+ endDate?: Date;
66
+ skip?: number;
67
+ take?: number;
68
+ orderBy?: Prisma.CreditAuditLogOrderByWithRelationInput;
69
+ },
70
+ tx?: Prisma.TransactionClient
71
+ ): Promise<{ creditAudit: CreditAuditLog[]; total: number }> {
72
+ const client = checkAndFallbackWithNonTCClient(tx);
73
+ const where: Prisma.CreditAuditLogWhereInput = { userId, deleted: 0 };
74
+
75
+ if (params?.creditType) {
76
+ where.creditType = params.creditType;
77
+ }
78
+
79
+ if (params?.operationType) {
80
+ where.operationType = params.operationType;
81
+ }
82
+
83
+ if (params?.feature) {
84
+ where.feature = params.feature;
85
+ }
86
+
87
+ if (params?.startDate || params?.endDate) {
88
+ where.createdAt = {};
89
+ if (params.startDate) where.createdAt.gte = params.startDate;
90
+ if (params.endDate) where.createdAt.lte = params.endDate;
91
+ }
92
+
93
+ const [creditAudit, total] = await Promise.all([
94
+ client.creditAuditLog.findMany({
95
+ where,
96
+ skip: params?.skip || 0,
97
+ take: params?.take || 20,
98
+ orderBy: params?.orderBy || { createdAt: 'desc' },
99
+ }),
100
+ client.creditAuditLog.count({ where }),
101
+ ]);
102
+
103
+ return { creditAudit, total };
104
+ }
105
+
106
+ // Get Credit Audit Record by operationReferId
107
+ async getCreditAuditList(operationReferId: string, tx?: Prisma.TransactionClient): Promise<CreditAuditLog[]> {
108
+ const client = checkAndFallbackWithNonTCClient(tx);
109
+
110
+ return await client.creditAuditLog.findMany({
111
+ where: { operationReferId, deleted: 0 },
112
+ orderBy: { createdAt: 'desc' },
113
+ });
114
+ }
115
+
116
+ // Get User Credit Audit Statistics
117
+ async getUserCreditAuditStats(
118
+ userId: string,
119
+ startDate?: Date,
120
+ endDate?: Date,
121
+ tx?: Prisma.TransactionClient
122
+ ): Promise<{
123
+ totalConsumed: number;
124
+ totalRecharged: number;
125
+ freeConsumed: number;
126
+ paidConsumed: number;
127
+ freeRecharged: number;
128
+ paidRecharged: number;
129
+ featureUsage: { feature: string; credits: number }[];
130
+ }> {
131
+ const client = checkAndFallbackWithNonTCClient(tx);
132
+ const where: Prisma.CreditAuditLogWhereInput = { userId, deleted: 0 };
133
+
134
+ if (startDate || endDate) {
135
+ where.createdAt = {};
136
+ if (startDate) where.createdAt.gte = startDate;
137
+ if (endDate) where.createdAt.lte = endDate;
138
+ }
139
+
140
+ // Get all creditAudit records
141
+ const allUsage = await client.creditAuditLog.findMany({
142
+ where,
143
+ select: {
144
+ creditType: true,
145
+ operationType: true,
146
+ creditsChange: true,
147
+ feature: true,
148
+ },
149
+ });
150
+
151
+ // Calculate statistics
152
+ const stats = {
153
+ totalConsumed: 0,
154
+ totalRecharged: 0,
155
+ freeConsumed: 0,
156
+ paidConsumed: 0,
157
+ freeRecharged: 0,
158
+ paidRecharged: 0,
159
+ featureUsage: [] as any[],
160
+ };
161
+
162
+ // Calculate creditAudit statistics by feature
163
+ const featureMap = new Map<string, number>();
164
+
165
+ allUsage.forEach((creditAudit) => {
166
+ if (creditAudit.operationType === OperationType.CONSUME) {
167
+ stats.totalConsumed += creditAudit.creditsChange;
168
+ if (creditAudit.creditType === CreditType.FREE) {
169
+ stats.freeConsumed += creditAudit.creditsChange;
170
+ } else {
171
+ stats.paidConsumed += creditAudit.creditsChange;
172
+ }
173
+
174
+ if (creditAudit.feature) {
175
+ featureMap.set(
176
+ creditAudit.feature,
177
+ (featureMap.get(creditAudit.feature) || 0) + creditAudit.creditsChange
178
+ );
179
+ }
180
+ } else if (creditAudit.operationType === OperationType.RECHARGE) {
181
+ stats.totalRecharged += creditAudit.creditsChange;
182
+ if (creditAudit.creditType === CreditType.FREE) {
183
+ stats.freeRecharged += creditAudit.creditsChange;
184
+ } else {
185
+ stats.paidRecharged += creditAudit.creditsChange;
186
+ }
187
+ }
188
+ });
189
+
190
+ // Convert feature creditAudit statistics to array
191
+ stats.featureUsage = Array.from(featureMap.entries())
192
+ .map(([feature, credits]) => ({ feature, credits }))
193
+ .sort((a, b) => b.credits - a.credits);
194
+
195
+ return stats;
196
+ }
197
+
198
+ // Get Popular Features
199
+ async getPopularFeatures(
200
+ limit: number = 10,
201
+ startDate?: Date,
202
+ endDate?: Date,
203
+ tx?: Prisma.TransactionClient
204
+ ): Promise<{ feature: string | null; totalCredits: number; usageCount: number }[]> {
205
+ const client = checkAndFallbackWithNonTCClient(tx);
206
+ const where: Prisma.CreditAuditLogWhereInput = {
207
+ operationType: OperationType.CONSUME,
208
+ feature: { not: null },
209
+ deleted: 0,
210
+ };
211
+
212
+ if (startDate || endDate) {
213
+ where.createdAt = {};
214
+ if (startDate) where.createdAt.gte = startDate;
215
+ if (endDate) where.createdAt.lte = endDate;
216
+ }
217
+
218
+ const result = await client.creditAuditLog.groupBy({
219
+ by: ['feature'],
220
+ where,
221
+ _sum: {
222
+ creditsChange: true,
223
+ },
224
+ _count: true,
225
+ orderBy: {
226
+ _sum: {
227
+ creditsChange: 'desc',
228
+ },
229
+ },
230
+ take: limit,
231
+ });
232
+
233
+ return result.map((item) => ({
234
+ feature: item.feature,
235
+ totalCredits: item._sum.creditsChange || 0,
236
+ usageCount: item._count,
237
+ }));
238
+ }
239
+
240
+ // Get Daily Credit Usage Trend
241
+ async getDailyUsageTrend(
242
+ days: number = 30,
243
+ userId?: string,
244
+ tx?: Prisma.TransactionClient
245
+ ): Promise<{
246
+ date: Date;
247
+ consumed: number;
248
+ recharged: number;
249
+ free_consumed: number;
250
+ paid_consumed: number;
251
+ unique_users: number;
252
+ }[]> {
253
+ const startDate = new Date();
254
+ startDate.setDate(startDate.getDate() - days);
255
+
256
+ const client = checkAndFallbackWithNonTCClient(tx);
257
+ const userFilter = userId ? Prisma.sql`AND user_id = ${userId}` : Prisma.sql``;
258
+
259
+ const result = await client.$queryRaw`
260
+ SELECT
261
+ DATE(created_at) as date,
262
+ SUM(CASE WHEN operation_type = 'consume' THEN credits_used ELSE 0 END) as consumed,
263
+ SUM(CASE WHEN operation_type = 'recharge' THEN credits_used ELSE 0 END) as recharged,
264
+ SUM(CASE WHEN credit_type = 'free' AND operation_type = 'consume'
265
+ THEN credits_used ELSE 0 END) as free_consumed,
266
+ SUM(CASE WHEN credit_type = 'paid' AND operation_type = 'consume'
267
+ THEN credits_used ELSE 0 END) as paid_consumed,
268
+ COUNT(DISTINCT user_id) as unique_users
269
+ FROM credit_usage
270
+ WHERE created_at >= ${startDate}
271
+ AND deleted = 0
272
+ ${userFilter}
273
+ GROUP BY DATE(created_at)
274
+ ORDER BY date DESC
275
+ `;
276
+
277
+ return result as {
278
+ date: Date;
279
+ consumed: number;
280
+ recharged: number;
281
+ free_consumed: number;
282
+ paid_consumed: number;
283
+ unique_users: number;
284
+ }[];
285
+ }
286
+
287
+ // Get Recent Credit Usage Operations
288
+ async getRecentOperations(
289
+ userId: string,
290
+ limit: number = 10,
291
+ tx?: Prisma.TransactionClient
292
+ ): Promise<CreditAuditLog[]> {
293
+ const client = checkAndFallbackWithNonTCClient(tx);
294
+
295
+ return await client.creditAuditLog.findMany({
296
+ where: { userId, deleted: 0 },
297
+ orderBy: { createdAt: 'desc' },
298
+ take: limit,
299
+ });
300
+ }
301
+
302
+ // Soft Delete Old Credit Usage Records
303
+ async deleteOldRecords(daysToKeep: number = 365, tx?: Prisma.TransactionClient): Promise<number> {
304
+ const cutoffDate = new Date();
305
+ cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);
306
+
307
+ const client = checkAndFallbackWithNonTCClient(tx);
308
+
309
+ const result = await client.creditAuditLog.updateMany({
310
+ where: {
311
+ createdAt: {
312
+ lt: cutoffDate,
313
+ },
314
+ deleted: 0,
315
+ },
316
+ data: {
317
+ deleted: 1,
318
+ },
319
+ });
320
+
321
+ return result.count;
322
+ }
323
+
324
+ // Get System-wide Credit Usage Statistics
325
+ async getSystemStats(tx?: Prisma.TransactionClient): Promise<{
326
+ totalUsers: number;
327
+ totalOperations: number;
328
+ totalConsumed: number;
329
+ totalRecharged: number;
330
+ avgDailyConsumption: number;
331
+ avgDailyRecharge: number;
332
+ }> {
333
+ const client = checkAndFallbackWithNonTCClient(tx);
334
+ const [
335
+ totalUsers,
336
+ totalOperations,
337
+ consumeStats,
338
+ rechargeStats,
339
+ ] = await Promise.all([
340
+ client.creditAuditLog.groupBy({
341
+ by: ['userId'],
342
+ where: { deleted: 0 },
343
+ }).then((result) => result.length),
344
+ client.creditAuditLog.count({ where: { deleted: 0 } }),
345
+ client.creditAuditLog.aggregate({
346
+ where: { operationType: OperationType.CONSUME, deleted: 0 },
347
+ _sum: { creditsChange: true },
348
+ _count: true,
349
+ }),
350
+ client.creditAuditLog.aggregate({
351
+ where: { operationType: OperationType.RECHARGE, deleted: 0 },
352
+ _sum: { creditsChange: true },
353
+ _count: true,
354
+ }),
355
+ ]);
356
+
357
+ // Calculate operating days (from first record to now)
358
+ const firstRecord = await client.creditAuditLog.findFirst({
359
+ where: { deleted: 0 },
360
+ orderBy: { createdAt: 'asc' },
361
+ select: { createdAt: true },
362
+ });
363
+
364
+ const operatingDays = firstRecord && firstRecord.createdAt
365
+ ? Math.ceil((Date.now() - firstRecord.createdAt.getTime()) / (1000 * 60 * 60 * 24))
366
+ : 1;
367
+
368
+ const totalConsumed = consumeStats._sum.creditsChange || 0;
369
+ const totalRecharged = rechargeStats._sum.creditsChange || 0;
370
+
371
+ return {
372
+ totalUsers,
373
+ totalOperations,
374
+ totalConsumed,
375
+ totalRecharged,
376
+ avgDailyConsumption: Math.round(totalConsumed / operatingDays),
377
+ avgDailyRecharge: Math.round(totalRecharged / operatingDays),
378
+ };
379
+ }
380
+
381
+ // Check for Duplicate Operations
382
+ async isDuplicateOperation(
383
+ userId: string,
384
+ operationReferId: string,
385
+ operationType: string,
386
+ tx?: Prisma.TransactionClient
387
+ ): Promise<boolean> {
388
+ const client = checkAndFallbackWithNonTCClient(tx);
389
+ const count = await client.creditAuditLog.count({
390
+ where: {
391
+ userId,
392
+ operationReferId,
393
+ operationType,
394
+ deleted: 0,
395
+ },
396
+ });
397
+
398
+ return count > 0;
399
+ }
400
+ }
401
+
402
+ export const creditAuditLogService = new CreditAuditLogService();
@@ -0,0 +1,41 @@
1
+ export { userService } from './user.service';
2
+ export { subscriptionService } from './subscription.service';
3
+ export { creditService } from './credit.service';
4
+ export { transactionService } from './transaction.service';
5
+ export { creditAuditLogService } from './creditAuditLog.service';
6
+ export { userBackupService } from './userBackup.service';
7
+ export { apilogService, Apilogger } from './apilog.service';
8
+
9
+ // Export Enums and Types
10
+ export {
11
+ UserStatus,
12
+ SubscriptionStatus,
13
+ OrderStatus,
14
+ TransactionType,
15
+ CreditType,
16
+ OperationType,
17
+ PaySupplier,
18
+ BillingReason,
19
+ PaymentStatus,
20
+ isValidUserStatus,
21
+ isValidSubscriptionStatus,
22
+ isValidOrderStatus,
23
+ isValidTransactionType,
24
+ isValidCreditType,
25
+ isValidOperationType,
26
+ isValidBillingReason,
27
+ isValidPaymentStatus,
28
+ } from './constants';
29
+
30
+ // Export Enum Type Definitions
31
+ export type {
32
+ UserStatus as UserStatusType,
33
+ SubscriptionStatus as SubscriptionStatusType,
34
+ OrderStatus as OrderStatusType,
35
+ TransactionType as TransactionTypeType,
36
+ CreditType as CreditTypeType,
37
+ OperationType as OperationTypeType,
38
+ PaySupplier as PaySupplierType,
39
+ BillingReason as BillingReasonType,
40
+ PaymentStatus as PaymentStatusType,
41
+ } from './constants';
@@ -0,0 +1,13 @@
1
+ // Export Prisma Model Types
2
+ export type {
3
+ User,
4
+ Subscription,
5
+ Credit,
6
+ CreditAuditLog,
7
+ Transaction,
8
+ Apilog,
9
+ UserBackup,
10
+ } from '@prisma/client';
11
+
12
+ // Prisma既是类型也是值
13
+ export { Prisma } from '@prisma/client';