@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.
- package/LICENSE +21 -0
- package/dist/app/api/stripe/checkout/route.d.ts +19 -0
- package/dist/app/api/stripe/checkout/route.d.ts.map +1 -0
- package/dist/app/api/stripe/checkout/route.js +120 -0
- package/dist/app/api/stripe/checkout/route.mjs +118 -0
- package/dist/app/api/stripe/customer-portal/route.d.ts +11 -0
- package/dist/app/api/stripe/customer-portal/route.d.ts.map +1 -0
- package/dist/app/api/stripe/customer-portal/route.js +73 -0
- package/dist/app/api/stripe/customer-portal/route.mjs +71 -0
- package/dist/app/api/user/anonymous/init/route.d.ts +7 -0
- package/dist/app/api/user/anonymous/init/route.d.ts.map +1 -0
- package/dist/app/api/user/anonymous/init/route.js +210 -0
- package/dist/app/api/user/anonymous/init/route.mjs +208 -0
- package/dist/app/api/webhook/clerk/user/route.d.ts +7 -0
- package/dist/app/api/webhook/clerk/user/route.d.ts.map +1 -0
- package/dist/app/api/webhook/clerk/user/route.js +202 -0
- package/dist/app/api/webhook/clerk/user/route.mjs +200 -0
- package/dist/app/api/webhook/stripe/route.d.ts +8 -0
- package/dist/app/api/webhook/stripe/route.d.ts.map +1 -0
- package/dist/app/api/webhook/stripe/route.js +70 -0
- package/dist/app/api/webhook/stripe/route.mjs +67 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +83 -0
- package/dist/index.mjs +18 -0
- package/dist/lib/auth-utils.d.ts +46 -0
- package/dist/lib/auth-utils.d.ts.map +1 -0
- package/dist/lib/auth-utils.js +107 -0
- package/dist/lib/auth-utils.mjs +102 -0
- package/dist/lib/credit-init.d.ts +8 -0
- package/dist/lib/credit-init.d.ts.map +1 -0
- package/dist/lib/credit-init.js +16 -0
- package/dist/lib/credit-init.mjs +10 -0
- package/dist/lib/index.d.ts +5 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +31 -0
- package/dist/lib/index.mjs +4 -0
- package/dist/lib/money-price-config.d.ts +51 -0
- package/dist/lib/money-price-config.d.ts.map +1 -0
- package/dist/lib/money-price-config.js +156 -0
- package/dist/lib/money-price-config.mjs +151 -0
- package/dist/lib/stripe-config.d.ts +31 -0
- package/dist/lib/stripe-config.d.ts.map +1 -0
- package/dist/lib/stripe-config.js +278 -0
- package/dist/lib/stripe-config.mjs +268 -0
- 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
- 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
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.js +54 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/errors.mjs +51 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.js +44 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/iso.mjs +35 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.js +31 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/parse.mjs +18 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.js +587 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/classic/schemas.mjs +527 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.js +447 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/api.mjs +399 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.js +245 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/checks.mjs +232 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.js +68 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/core.mjs +62 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.js +39 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/doc.mjs +37 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.js +80 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/errors.mjs +75 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.js +101 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/parse.mjs +86 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.js +102 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/regexes.mjs +76 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.js +56 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/registries.mjs +52 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.js +1205 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/schemas.mjs +1157 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.js +407 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/util.mjs +374 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.js +9 -0
- package/dist/node_modules/.pnpm/zod@4.1.12/node_modules/zod/v4/core/versions.mjs +7 -0
- package/dist/prisma/client.d.ts +2 -0
- package/dist/prisma/client.d.ts.map +1 -0
- package/dist/prisma/client.js +12 -0
- package/dist/prisma/client.mjs +1 -0
- package/dist/prisma/index.d.ts +4 -0
- package/dist/prisma/index.d.ts.map +1 -0
- package/dist/prisma/index.js +10 -0
- package/dist/prisma/index.mjs +2 -0
- package/dist/prisma/prisma-transaction-util.d.ts +3 -0
- package/dist/prisma/prisma-transaction-util.d.ts.map +1 -0
- package/dist/prisma/prisma-transaction-util.js +29 -0
- package/dist/prisma/prisma-transaction-util.mjs +27 -0
- package/dist/prisma/prisma.d.ts +4 -0
- package/dist/prisma/prisma.d.ts.map +1 -0
- package/dist/prisma/prisma.js +109 -0
- package/dist/prisma/prisma.mjs +106 -0
- package/dist/services/aggregate/billing.aggregate.service.d.ts +83 -0
- package/dist/services/aggregate/billing.aggregate.service.d.ts.map +1 -0
- package/dist/services/aggregate/billing.aggregate.service.js +308 -0
- package/dist/services/aggregate/billing.aggregate.service.mjs +306 -0
- package/dist/services/aggregate/index.d.ts +3 -0
- package/dist/services/aggregate/index.d.ts.map +1 -0
- package/dist/services/aggregate/index.js +9 -0
- package/dist/services/aggregate/index.mjs +2 -0
- package/dist/services/aggregate/user.aggregate.service.d.ts +34 -0
- package/dist/services/aggregate/user.aggregate.service.d.ts.map +1 -0
- package/dist/services/aggregate/user.aggregate.service.js +136 -0
- package/dist/services/aggregate/user.aggregate.service.mjs +133 -0
- package/dist/services/context/index.d.ts +2 -0
- package/dist/services/context/index.d.ts.map +1 -0
- package/dist/services/context/index.js +13 -0
- package/dist/services/context/index.mjs +1 -0
- package/dist/services/context/user-context-service.d.ts +30 -0
- package/dist/services/context/user-context-service.d.ts.map +1 -0
- package/dist/services/context/user-context-service.js +170 -0
- package/dist/services/context/user-context-service.mjs +162 -0
- package/dist/services/database/apilog.service.d.ts +39 -0
- package/dist/services/database/apilog.service.d.ts.map +1 -0
- package/dist/services/database/apilog.service.js +174 -0
- package/dist/services/database/apilog.service.mjs +170 -0
- package/dist/services/database/constants.d.ts +73 -0
- package/dist/services/database/constants.d.ts.map +1 -0
- package/dist/services/database/constants.js +135 -0
- package/dist/services/database/constants.mjs +117 -0
- package/dist/services/database/credit.service.d.ts +107 -0
- package/dist/services/database/credit.service.d.ts.map +1 -0
- package/dist/services/database/credit.service.js +515 -0
- package/dist/services/database/credit.service.mjs +512 -0
- package/dist/services/database/creditAuditLog.service.d.ts +73 -0
- package/dist/services/database/creditAuditLog.service.d.ts.map +1 -0
- package/dist/services/database/creditAuditLog.service.js +305 -0
- package/dist/services/database/creditAuditLog.service.mjs +302 -0
- package/dist/services/database/index.d.ts +10 -0
- package/dist/services/database/index.d.ts.map +1 -0
- package/dist/services/database/index.js +38 -0
- package/dist/services/database/index.mjs +8 -0
- package/dist/services/database/prisma-model-type.d.ts +3 -0
- package/dist/services/database/prisma-model-type.d.ts.map +1 -0
- package/dist/services/database/subscription.service.d.ts +48 -0
- package/dist/services/database/subscription.service.d.ts.map +1 -0
- package/dist/services/database/subscription.service.js +267 -0
- package/dist/services/database/subscription.service.mjs +264 -0
- package/dist/services/database/transaction.service.d.ts +92 -0
- package/dist/services/database/transaction.service.d.ts.map +1 -0
- package/dist/services/database/transaction.service.js +326 -0
- package/dist/services/database/transaction.service.mjs +323 -0
- package/dist/services/database/user.service.d.ts +45 -0
- package/dist/services/database/user.service.d.ts.map +1 -0
- package/dist/services/database/user.service.js +180 -0
- package/dist/services/database/user.service.mjs +177 -0
- package/dist/services/database/userBackup.service.d.ts +45 -0
- package/dist/services/database/userBackup.service.d.ts.map +1 -0
- package/dist/services/database/userBackup.service.js +249 -0
- package/dist/services/database/userBackup.service.mjs +246 -0
- package/dist/services/stripe/index.d.ts +2 -0
- package/dist/services/stripe/index.d.ts.map +1 -0
- package/dist/services/stripe/index.js +7 -0
- package/dist/services/stripe/index.mjs +1 -0
- package/dist/services/stripe/webhook-handler.d.ts +6 -0
- package/dist/services/stripe/webhook-handler.d.ts.map +1 -0
- package/dist/services/stripe/webhook-handler.js +537 -0
- package/dist/services/stripe/webhook-handler.mjs +535 -0
- package/migrations/create.sql +176 -0
- package/migrations/db.init.sql +13 -0
- package/migrations/init-schema.sql +19 -0
- package/migrations/purge.sql +27 -0
- package/migrations/test-check.sql +167 -0
- package/package.json +123 -0
- package/prisma/schema.prisma +191 -0
- package/src/app/api/stripe/checkout/route.ts +145 -0
- package/src/app/api/stripe/customer-portal/route.ts +83 -0
- package/src/app/api/user/anonymous/init/route.ts +284 -0
- package/src/app/api/webhook/clerk/user/route.ts +249 -0
- package/src/app/api/webhook/stripe/route.ts +93 -0
- package/src/index.ts +6 -0
- package/src/lib/auth-utils.ts +101 -0
- package/src/lib/credit-init.ts +9 -0
- package/src/lib/index.ts +4 -0
- package/src/lib/money-price-config.ts +168 -0
- package/src/lib/stripe-config.ts +333 -0
- package/src/prisma/client.ts +2 -0
- package/src/prisma/index.ts +3 -0
- package/src/prisma/prisma-transaction-util.ts +24 -0
- package/src/prisma/prisma.ts +122 -0
- package/src/services/aggregate/billing.aggregate.service.ts +498 -0
- package/src/services/aggregate/index.ts +2 -0
- package/src/services/aggregate/user.aggregate.service.ts +168 -0
- package/src/services/context/index.ts +1 -0
- package/src/services/context/user-context-service.ts +200 -0
- package/src/services/database/apilog.service.ts +185 -0
- package/src/services/database/constants.ts +148 -0
- package/src/services/database/credit.service.ts +747 -0
- package/src/services/database/creditAuditLog.service.ts +402 -0
- package/src/services/database/index.ts +41 -0
- package/src/services/database/prisma-model-type.ts +13 -0
- package/src/services/database/subscription.service.ts +319 -0
- package/src/services/database/transaction.service.ts +447 -0
- package/src/services/database/user.service.ts +218 -0
- package/src/services/database/userBackup.service.ts +290 -0
- package/src/services/stripe/index.ts +1 -0
- package/src/services/stripe/webhook-handler.ts +648 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Prisma, Subscription } from './prisma-model-type';
|
|
2
|
+
export declare class SubscriptionService {
|
|
3
|
+
/**
|
|
4
|
+
* Initialize a placeholder subscription record for new users
|
|
5
|
+
* This allows Stripe webhook handlers to UPDATE instead of CREATE,
|
|
6
|
+
* ensuring consistent logic across all subscription scenarios.
|
|
7
|
+
*
|
|
8
|
+
* The record will be updated once the user subscribes via Stripe.
|
|
9
|
+
*
|
|
10
|
+
* @param userId - The user ID to initialize subscription for
|
|
11
|
+
* @returns The created placeholder subscription record
|
|
12
|
+
*/
|
|
13
|
+
initializeSubscription(userId: string, tx?: Prisma.TransactionClient): Promise<Subscription>;
|
|
14
|
+
createSubscription(data: {
|
|
15
|
+
userId: string;
|
|
16
|
+
orderId: string;
|
|
17
|
+
paySubscriptionId?: string;
|
|
18
|
+
priceId?: string;
|
|
19
|
+
priceName?: string;
|
|
20
|
+
status?: string;
|
|
21
|
+
creditsAllocated: number;
|
|
22
|
+
subPeriodStart?: Date;
|
|
23
|
+
subPeriodEnd?: Date;
|
|
24
|
+
}, tx?: Prisma.TransactionClient): Promise<Subscription>;
|
|
25
|
+
findByPaySubscriptionId(paySubscriptionId: string, tx?: Prisma.TransactionClient): Promise<Subscription | null>;
|
|
26
|
+
getActiveSubscription(userId: string, tx?: Prisma.TransactionClient): Promise<Subscription | null>;
|
|
27
|
+
getNonActiveSubscription(userId: string, tx?: Prisma.TransactionClient): Promise<Subscription | null>;
|
|
28
|
+
updateSubscription(id: bigint, data: Prisma.SubscriptionUpdateInput, tx?: Prisma.TransactionClient): Promise<Subscription>;
|
|
29
|
+
updateStatus(id: bigint, status: string, tx?: Prisma.TransactionClient): Promise<Subscription>;
|
|
30
|
+
updatePeriod(id: bigint, subPeriodStart: Date, subPeriodEnd: Date, tx?: Prisma.TransactionClient): Promise<Subscription>;
|
|
31
|
+
cancelSubscription(id: bigint, cancelAtPeriodEnd?: boolean, tx?: Prisma.TransactionClient): Promise<Subscription>;
|
|
32
|
+
renewSubscription(id: bigint, newPeriodEnd: Date, creditsToAdd?: number, tx?: Prisma.TransactionClient): Promise<Subscription>;
|
|
33
|
+
deleteSubscription(id: bigint, tx?: Prisma.TransactionClient): Promise<void>;
|
|
34
|
+
getExpiringSubscriptions(days?: number, tx?: Prisma.TransactionClient): Promise<Subscription[]>;
|
|
35
|
+
getExpiredSubscriptions(tx?: Prisma.TransactionClient): Promise<Subscription[]>;
|
|
36
|
+
updateExpiredSubscriptions(tx?: Prisma.TransactionClient): Promise<number>;
|
|
37
|
+
getSubscriptionStats(tx?: Prisma.TransactionClient): Promise<{
|
|
38
|
+
total: number;
|
|
39
|
+
active: number;
|
|
40
|
+
canceled: number;
|
|
41
|
+
pastDue: number;
|
|
42
|
+
incomplete: number;
|
|
43
|
+
trialing: number;
|
|
44
|
+
revenue: number;
|
|
45
|
+
}>;
|
|
46
|
+
}
|
|
47
|
+
export declare const subscriptionService: SubscriptionService;
|
|
48
|
+
//# sourceMappingURL=subscription.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription.service.d.ts","sourceRoot":"","sources":["../../../src/services/database/subscription.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var tslib_es6 = require('../../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');
|
|
4
|
+
var constants = require('./constants.js');
|
|
5
|
+
var prisma = require('../../prisma/prisma.js');
|
|
6
|
+
|
|
7
|
+
class SubscriptionService {
|
|
8
|
+
/**
|
|
9
|
+
* Initialize a placeholder subscription record for new users
|
|
10
|
+
* This allows Stripe webhook handlers to UPDATE instead of CREATE,
|
|
11
|
+
* ensuring consistent logic across all subscription scenarios.
|
|
12
|
+
*
|
|
13
|
+
* The record will be updated once the user subscribes via Stripe.
|
|
14
|
+
*
|
|
15
|
+
* @param userId - The user ID to initialize subscription for
|
|
16
|
+
* @returns The created placeholder subscription record
|
|
17
|
+
*/
|
|
18
|
+
initializeSubscription(userId, tx) {
|
|
19
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
21
|
+
return yield client.subscription.create({
|
|
22
|
+
data: {
|
|
23
|
+
userId,
|
|
24
|
+
status: constants.SubscriptionStatus.INCOMPLETE,
|
|
25
|
+
creditsAllocated: 0,
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
// Create a new subscription
|
|
31
|
+
createSubscription(data, tx) {
|
|
32
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
34
|
+
return yield client.subscription.create({
|
|
35
|
+
data: {
|
|
36
|
+
userId: data.userId,
|
|
37
|
+
orderId: data.orderId,
|
|
38
|
+
paySubscriptionId: data.paySubscriptionId,
|
|
39
|
+
priceId: data.priceId,
|
|
40
|
+
priceName: data.priceName,
|
|
41
|
+
status: data.status || constants.SubscriptionStatus.INCOMPLETE,
|
|
42
|
+
creditsAllocated: data.creditsAllocated,
|
|
43
|
+
subPeriodStart: data.subPeriodStart,
|
|
44
|
+
subPeriodEnd: data.subPeriodEnd,
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
// Find subscription by pay subscription ID
|
|
50
|
+
findByPaySubscriptionId(paySubscriptionId, tx) {
|
|
51
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
53
|
+
return yield client.subscription.findFirst({
|
|
54
|
+
where: { paySubscriptionId, deleted: 0 }
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
// Get user's active subscription
|
|
59
|
+
getActiveSubscription(userId, tx) {
|
|
60
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
62
|
+
return yield client.subscription.findUnique({
|
|
63
|
+
where: {
|
|
64
|
+
userId,
|
|
65
|
+
status: constants.SubscriptionStatus.ACTIVE,
|
|
66
|
+
deleted: 0
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
getNonActiveSubscription(userId, tx) {
|
|
72
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
73
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
74
|
+
return yield client.subscription.findUnique({
|
|
75
|
+
where: {
|
|
76
|
+
userId,
|
|
77
|
+
status: { not: constants.SubscriptionStatus.ACTIVE },
|
|
78
|
+
deleted: 0
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
// Update subscription
|
|
84
|
+
updateSubscription(id, data, tx) {
|
|
85
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
86
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
87
|
+
return yield client.subscription.update({
|
|
88
|
+
where: { id },
|
|
89
|
+
data,
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// Update subscription status
|
|
94
|
+
updateStatus(id, status, tx) {
|
|
95
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
96
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
97
|
+
return yield client.subscription.update({
|
|
98
|
+
where: { id },
|
|
99
|
+
data: { status },
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
// Update subscription period
|
|
104
|
+
updatePeriod(id, subPeriodStart, subPeriodEnd, tx) {
|
|
105
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
106
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
107
|
+
return yield client.subscription.update({
|
|
108
|
+
where: { id },
|
|
109
|
+
data: {
|
|
110
|
+
subPeriodStart,
|
|
111
|
+
subPeriodEnd,
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
// Cancel subscription
|
|
117
|
+
cancelSubscription(id_1) {
|
|
118
|
+
return tslib_es6.__awaiter(this, arguments, void 0, function* (id, cancelAtPeriodEnd = true, tx) {
|
|
119
|
+
const updateData = {
|
|
120
|
+
status: constants.SubscriptionStatus.CANCELED,
|
|
121
|
+
};
|
|
122
|
+
if (!cancelAtPeriodEnd) {
|
|
123
|
+
updateData.subPeriodEnd = new Date();
|
|
124
|
+
}
|
|
125
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
126
|
+
return yield client.subscription.update({
|
|
127
|
+
where: { id },
|
|
128
|
+
data: updateData,
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
// Renew subscription
|
|
133
|
+
renewSubscription(id, newPeriodEnd, creditsToAdd, tx) {
|
|
134
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
135
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
136
|
+
const subscription = yield client.subscription.findFirst({
|
|
137
|
+
where: { id },
|
|
138
|
+
});
|
|
139
|
+
if (!subscription) {
|
|
140
|
+
throw new Error('Subscription not found');
|
|
141
|
+
}
|
|
142
|
+
return yield client.subscription.update({
|
|
143
|
+
where: { id },
|
|
144
|
+
data: {
|
|
145
|
+
status: constants.SubscriptionStatus.ACTIVE,
|
|
146
|
+
subPeriodStart: subscription.subPeriodEnd || new Date(),
|
|
147
|
+
subPeriodEnd: newPeriodEnd,
|
|
148
|
+
creditsAllocated: creditsToAdd
|
|
149
|
+
? subscription.creditsAllocated + creditsToAdd
|
|
150
|
+
: subscription.creditsAllocated,
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
// Soft Delete subscription
|
|
156
|
+
deleteSubscription(id, tx) {
|
|
157
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
158
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
159
|
+
yield client.subscription.update({
|
|
160
|
+
where: { id },
|
|
161
|
+
data: { deleted: 1, status: constants.SubscriptionStatus.INCOMPLETE },
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
// Get expiring subscriptions (within 7 days)
|
|
166
|
+
getExpiringSubscriptions() {
|
|
167
|
+
return tslib_es6.__awaiter(this, arguments, void 0, function* (days = 7, tx) {
|
|
168
|
+
const now = new Date();
|
|
169
|
+
const expiryDate = new Date();
|
|
170
|
+
expiryDate.setDate(expiryDate.getDate() + days);
|
|
171
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
172
|
+
return yield client.subscription.findMany({
|
|
173
|
+
where: {
|
|
174
|
+
status: constants.SubscriptionStatus.ACTIVE,
|
|
175
|
+
deleted: 0,
|
|
176
|
+
subPeriodEnd: {
|
|
177
|
+
gte: now,
|
|
178
|
+
lte: expiryDate,
|
|
179
|
+
},
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
// Get expired subscriptions
|
|
185
|
+
getExpiredSubscriptions(tx) {
|
|
186
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
187
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
188
|
+
return yield client.subscription.findMany({
|
|
189
|
+
where: {
|
|
190
|
+
status: constants.SubscriptionStatus.ACTIVE,
|
|
191
|
+
deleted: 0,
|
|
192
|
+
subPeriodEnd: {
|
|
193
|
+
lt: new Date(),
|
|
194
|
+
},
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
// Update expired subscriptions status
|
|
200
|
+
updateExpiredSubscriptions(tx) {
|
|
201
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
202
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
203
|
+
const result = yield client.subscription.updateMany({
|
|
204
|
+
where: {
|
|
205
|
+
status: constants.SubscriptionStatus.ACTIVE,
|
|
206
|
+
deleted: 0,
|
|
207
|
+
subPeriodEnd: {
|
|
208
|
+
lt: new Date(),
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
data: {
|
|
212
|
+
status: constants.SubscriptionStatus.PAST_DUE,
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
return result.count;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
// Get subscription statistics
|
|
219
|
+
getSubscriptionStats(tx) {
|
|
220
|
+
return tslib_es6.__awaiter(this, void 0, void 0, function* () {
|
|
221
|
+
const client = prisma.checkAndFallbackWithNonTCClient(tx);
|
|
222
|
+
const [total, active, canceled, pastDue, incomplete, trialing] = yield Promise.all([
|
|
223
|
+
client.subscription.count({ where: { deleted: 0 } }),
|
|
224
|
+
client.subscription.count({
|
|
225
|
+
where: { status: constants.SubscriptionStatus.ACTIVE, deleted: 0 }
|
|
226
|
+
}),
|
|
227
|
+
client.subscription.count({
|
|
228
|
+
where: { status: constants.SubscriptionStatus.CANCELED, deleted: 0 }
|
|
229
|
+
}),
|
|
230
|
+
client.subscription.count({
|
|
231
|
+
where: { status: constants.SubscriptionStatus.PAST_DUE, deleted: 0 }
|
|
232
|
+
}),
|
|
233
|
+
client.subscription.count({
|
|
234
|
+
where: { status: constants.SubscriptionStatus.INCOMPLETE, deleted: 0 }
|
|
235
|
+
}),
|
|
236
|
+
client.subscription.count({
|
|
237
|
+
where: { status: constants.SubscriptionStatus.TRIALING, deleted: 0 }
|
|
238
|
+
}),
|
|
239
|
+
]);
|
|
240
|
+
// Calculate active subscription revenue (need to combine with transaction table)
|
|
241
|
+
const activeSubscriptions = yield client.subscription.findMany({
|
|
242
|
+
where: { status: constants.SubscriptionStatus.ACTIVE, deleted: 0 },
|
|
243
|
+
select: { paySubscriptionId: true },
|
|
244
|
+
});
|
|
245
|
+
let revenue = 0;
|
|
246
|
+
if (activeSubscriptions.length > 0) {
|
|
247
|
+
const transactions = yield client.transaction.findMany({
|
|
248
|
+
where: {
|
|
249
|
+
paySubscriptionId: {
|
|
250
|
+
in: activeSubscriptions
|
|
251
|
+
.map(s => s.paySubscriptionId)
|
|
252
|
+
.filter(Boolean),
|
|
253
|
+
},
|
|
254
|
+
orderStatus: 'success',
|
|
255
|
+
},
|
|
256
|
+
select: { amount: true },
|
|
257
|
+
});
|
|
258
|
+
revenue = transactions.reduce((sum, t) => sum + (t.amount ? parseFloat(t.amount.toString()) : 0), 0);
|
|
259
|
+
}
|
|
260
|
+
return { total, active, canceled, pastDue, incomplete, trialing, revenue };
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const subscriptionService = new SubscriptionService();
|
|
265
|
+
|
|
266
|
+
exports.SubscriptionService = SubscriptionService;
|
|
267
|
+
exports.subscriptionService = subscriptionService;
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { __awaiter } from '../../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';
|
|
2
|
+
import { SubscriptionStatus } from './constants.mjs';
|
|
3
|
+
import { checkAndFallbackWithNonTCClient } from '../../prisma/prisma.mjs';
|
|
4
|
+
|
|
5
|
+
class SubscriptionService {
|
|
6
|
+
/**
|
|
7
|
+
* Initialize a placeholder subscription record for new users
|
|
8
|
+
* This allows Stripe webhook handlers to UPDATE instead of CREATE,
|
|
9
|
+
* ensuring consistent logic across all subscription scenarios.
|
|
10
|
+
*
|
|
11
|
+
* The record will be updated once the user subscribes via Stripe.
|
|
12
|
+
*
|
|
13
|
+
* @param userId - The user ID to initialize subscription for
|
|
14
|
+
* @returns The created placeholder subscription record
|
|
15
|
+
*/
|
|
16
|
+
initializeSubscription(userId, tx) {
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
19
|
+
return yield client.subscription.create({
|
|
20
|
+
data: {
|
|
21
|
+
userId,
|
|
22
|
+
status: SubscriptionStatus.INCOMPLETE,
|
|
23
|
+
creditsAllocated: 0,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
// Create a new subscription
|
|
29
|
+
createSubscription(data, tx) {
|
|
30
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
32
|
+
return yield client.subscription.create({
|
|
33
|
+
data: {
|
|
34
|
+
userId: data.userId,
|
|
35
|
+
orderId: data.orderId,
|
|
36
|
+
paySubscriptionId: data.paySubscriptionId,
|
|
37
|
+
priceId: data.priceId,
|
|
38
|
+
priceName: data.priceName,
|
|
39
|
+
status: data.status || SubscriptionStatus.INCOMPLETE,
|
|
40
|
+
creditsAllocated: data.creditsAllocated,
|
|
41
|
+
subPeriodStart: data.subPeriodStart,
|
|
42
|
+
subPeriodEnd: data.subPeriodEnd,
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// Find subscription by pay subscription ID
|
|
48
|
+
findByPaySubscriptionId(paySubscriptionId, tx) {
|
|
49
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
51
|
+
return yield client.subscription.findFirst({
|
|
52
|
+
where: { paySubscriptionId, deleted: 0 }
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// Get user's active subscription
|
|
57
|
+
getActiveSubscription(userId, tx) {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
60
|
+
return yield client.subscription.findUnique({
|
|
61
|
+
where: {
|
|
62
|
+
userId,
|
|
63
|
+
status: SubscriptionStatus.ACTIVE,
|
|
64
|
+
deleted: 0
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
getNonActiveSubscription(userId, tx) {
|
|
70
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
72
|
+
return yield client.subscription.findUnique({
|
|
73
|
+
where: {
|
|
74
|
+
userId,
|
|
75
|
+
status: { not: SubscriptionStatus.ACTIVE },
|
|
76
|
+
deleted: 0
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// Update subscription
|
|
82
|
+
updateSubscription(id, data, tx) {
|
|
83
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
85
|
+
return yield client.subscription.update({
|
|
86
|
+
where: { id },
|
|
87
|
+
data,
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
// Update subscription status
|
|
92
|
+
updateStatus(id, status, tx) {
|
|
93
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
94
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
95
|
+
return yield client.subscription.update({
|
|
96
|
+
where: { id },
|
|
97
|
+
data: { status },
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
// Update subscription period
|
|
102
|
+
updatePeriod(id, subPeriodStart, subPeriodEnd, tx) {
|
|
103
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
104
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
105
|
+
return yield client.subscription.update({
|
|
106
|
+
where: { id },
|
|
107
|
+
data: {
|
|
108
|
+
subPeriodStart,
|
|
109
|
+
subPeriodEnd,
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
// Cancel subscription
|
|
115
|
+
cancelSubscription(id_1) {
|
|
116
|
+
return __awaiter(this, arguments, void 0, function* (id, cancelAtPeriodEnd = true, tx) {
|
|
117
|
+
const updateData = {
|
|
118
|
+
status: SubscriptionStatus.CANCELED,
|
|
119
|
+
};
|
|
120
|
+
if (!cancelAtPeriodEnd) {
|
|
121
|
+
updateData.subPeriodEnd = new Date();
|
|
122
|
+
}
|
|
123
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
124
|
+
return yield client.subscription.update({
|
|
125
|
+
where: { id },
|
|
126
|
+
data: updateData,
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
// Renew subscription
|
|
131
|
+
renewSubscription(id, newPeriodEnd, creditsToAdd, tx) {
|
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
134
|
+
const subscription = yield client.subscription.findFirst({
|
|
135
|
+
where: { id },
|
|
136
|
+
});
|
|
137
|
+
if (!subscription) {
|
|
138
|
+
throw new Error('Subscription not found');
|
|
139
|
+
}
|
|
140
|
+
return yield client.subscription.update({
|
|
141
|
+
where: { id },
|
|
142
|
+
data: {
|
|
143
|
+
status: SubscriptionStatus.ACTIVE,
|
|
144
|
+
subPeriodStart: subscription.subPeriodEnd || new Date(),
|
|
145
|
+
subPeriodEnd: newPeriodEnd,
|
|
146
|
+
creditsAllocated: creditsToAdd
|
|
147
|
+
? subscription.creditsAllocated + creditsToAdd
|
|
148
|
+
: subscription.creditsAllocated,
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
// Soft Delete subscription
|
|
154
|
+
deleteSubscription(id, tx) {
|
|
155
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
156
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
157
|
+
yield client.subscription.update({
|
|
158
|
+
where: { id },
|
|
159
|
+
data: { deleted: 1, status: SubscriptionStatus.INCOMPLETE },
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
// Get expiring subscriptions (within 7 days)
|
|
164
|
+
getExpiringSubscriptions() {
|
|
165
|
+
return __awaiter(this, arguments, void 0, function* (days = 7, tx) {
|
|
166
|
+
const now = new Date();
|
|
167
|
+
const expiryDate = new Date();
|
|
168
|
+
expiryDate.setDate(expiryDate.getDate() + days);
|
|
169
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
170
|
+
return yield client.subscription.findMany({
|
|
171
|
+
where: {
|
|
172
|
+
status: SubscriptionStatus.ACTIVE,
|
|
173
|
+
deleted: 0,
|
|
174
|
+
subPeriodEnd: {
|
|
175
|
+
gte: now,
|
|
176
|
+
lte: expiryDate,
|
|
177
|
+
},
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
// Get expired subscriptions
|
|
183
|
+
getExpiredSubscriptions(tx) {
|
|
184
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
185
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
186
|
+
return yield client.subscription.findMany({
|
|
187
|
+
where: {
|
|
188
|
+
status: SubscriptionStatus.ACTIVE,
|
|
189
|
+
deleted: 0,
|
|
190
|
+
subPeriodEnd: {
|
|
191
|
+
lt: new Date(),
|
|
192
|
+
},
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
// Update expired subscriptions status
|
|
198
|
+
updateExpiredSubscriptions(tx) {
|
|
199
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
200
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
201
|
+
const result = yield client.subscription.updateMany({
|
|
202
|
+
where: {
|
|
203
|
+
status: SubscriptionStatus.ACTIVE,
|
|
204
|
+
deleted: 0,
|
|
205
|
+
subPeriodEnd: {
|
|
206
|
+
lt: new Date(),
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
data: {
|
|
210
|
+
status: SubscriptionStatus.PAST_DUE,
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
return result.count;
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
// Get subscription statistics
|
|
217
|
+
getSubscriptionStats(tx) {
|
|
218
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
219
|
+
const client = checkAndFallbackWithNonTCClient(tx);
|
|
220
|
+
const [total, active, canceled, pastDue, incomplete, trialing] = yield Promise.all([
|
|
221
|
+
client.subscription.count({ where: { deleted: 0 } }),
|
|
222
|
+
client.subscription.count({
|
|
223
|
+
where: { status: SubscriptionStatus.ACTIVE, deleted: 0 }
|
|
224
|
+
}),
|
|
225
|
+
client.subscription.count({
|
|
226
|
+
where: { status: SubscriptionStatus.CANCELED, deleted: 0 }
|
|
227
|
+
}),
|
|
228
|
+
client.subscription.count({
|
|
229
|
+
where: { status: SubscriptionStatus.PAST_DUE, deleted: 0 }
|
|
230
|
+
}),
|
|
231
|
+
client.subscription.count({
|
|
232
|
+
where: { status: SubscriptionStatus.INCOMPLETE, deleted: 0 }
|
|
233
|
+
}),
|
|
234
|
+
client.subscription.count({
|
|
235
|
+
where: { status: SubscriptionStatus.TRIALING, deleted: 0 }
|
|
236
|
+
}),
|
|
237
|
+
]);
|
|
238
|
+
// Calculate active subscription revenue (need to combine with transaction table)
|
|
239
|
+
const activeSubscriptions = yield client.subscription.findMany({
|
|
240
|
+
where: { status: SubscriptionStatus.ACTIVE, deleted: 0 },
|
|
241
|
+
select: { paySubscriptionId: true },
|
|
242
|
+
});
|
|
243
|
+
let revenue = 0;
|
|
244
|
+
if (activeSubscriptions.length > 0) {
|
|
245
|
+
const transactions = yield client.transaction.findMany({
|
|
246
|
+
where: {
|
|
247
|
+
paySubscriptionId: {
|
|
248
|
+
in: activeSubscriptions
|
|
249
|
+
.map(s => s.paySubscriptionId)
|
|
250
|
+
.filter(Boolean),
|
|
251
|
+
},
|
|
252
|
+
orderStatus: 'success',
|
|
253
|
+
},
|
|
254
|
+
select: { amount: true },
|
|
255
|
+
});
|
|
256
|
+
revenue = transactions.reduce((sum, t) => sum + (t.amount ? parseFloat(t.amount.toString()) : 0), 0);
|
|
257
|
+
}
|
|
258
|
+
return { total, active, canceled, pastDue, incomplete, trialing, revenue };
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
const subscriptionService = new SubscriptionService();
|
|
263
|
+
|
|
264
|
+
export { SubscriptionService, subscriptionService };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { Prisma } from './prisma-model-type';
|
|
2
|
+
import type { Transaction } from './prisma-model-type';
|
|
3
|
+
import { PaySupplier } from './constants';
|
|
4
|
+
export declare class TransactionService {
|
|
5
|
+
createTransaction(data: {
|
|
6
|
+
userId: string;
|
|
7
|
+
orderId: string;
|
|
8
|
+
orderStatus?: string;
|
|
9
|
+
paymentStatus?: string;
|
|
10
|
+
paySupplier?: PaySupplier;
|
|
11
|
+
payTransactionId?: string;
|
|
12
|
+
paySubscriptionId?: string;
|
|
13
|
+
subPeriodStart?: Date;
|
|
14
|
+
subPeriodEnd?: Date;
|
|
15
|
+
paySessionId?: string;
|
|
16
|
+
payInvoiceId?: string;
|
|
17
|
+
hostedInvoiceUrl?: string;
|
|
18
|
+
invoicePdf?: string;
|
|
19
|
+
billingReason?: string;
|
|
20
|
+
priceId?: string;
|
|
21
|
+
priceName?: string;
|
|
22
|
+
amount?: number;
|
|
23
|
+
currency?: string;
|
|
24
|
+
type?: string;
|
|
25
|
+
creditsGranted?: number;
|
|
26
|
+
orderDetail?: string;
|
|
27
|
+
orderExpiredAt?: Date;
|
|
28
|
+
paidAt?: Date;
|
|
29
|
+
paidEmail: string | null;
|
|
30
|
+
payUpdatedAt?: Date;
|
|
31
|
+
}, tx?: Prisma.TransactionClient): Promise<Transaction>;
|
|
32
|
+
findByOrderId(orderId: string, tx?: Prisma.TransactionClient): Promise<Transaction | null>;
|
|
33
|
+
findByPaySessionId(paySessionId: string, tx?: Prisma.TransactionClient): Promise<Transaction | null>;
|
|
34
|
+
findByPayTransactionId(payTransactionId: string, tx?: Prisma.TransactionClient): Promise<Transaction | null>;
|
|
35
|
+
findByUserId(userId: string, params?: {
|
|
36
|
+
orderStatus?: string;
|
|
37
|
+
type?: string;
|
|
38
|
+
skip?: number;
|
|
39
|
+
take?: number;
|
|
40
|
+
orderBy?: Prisma.TransactionOrderByWithRelationInput;
|
|
41
|
+
}, tx?: Prisma.TransactionClient): Promise<{
|
|
42
|
+
transactions: Transaction[];
|
|
43
|
+
total: number;
|
|
44
|
+
}>;
|
|
45
|
+
updateStatus(orderId: string, orderStatus: string, additionalData?: {
|
|
46
|
+
payTransactionId?: string;
|
|
47
|
+
paidAt?: Date;
|
|
48
|
+
paidEmail?: string;
|
|
49
|
+
paidDetail?: string;
|
|
50
|
+
payUpdatedAt?: Date;
|
|
51
|
+
paymentStatus?: string;
|
|
52
|
+
paySubscriptionId?: string;
|
|
53
|
+
paySessionId?: string;
|
|
54
|
+
payInvoiceId?: string;
|
|
55
|
+
hostedInvoiceUrl?: string;
|
|
56
|
+
invoicePdf?: string;
|
|
57
|
+
billingReason?: string;
|
|
58
|
+
orderDetail?: string;
|
|
59
|
+
}, tx?: Prisma.TransactionClient): Promise<Transaction>;
|
|
60
|
+
update(orderId: string, data: Prisma.TransactionUpdateInput, tx?: Prisma.TransactionClient): Promise<Transaction>;
|
|
61
|
+
completePayment(orderId: string, paymentData: {
|
|
62
|
+
payTransactionId?: string;
|
|
63
|
+
paidAt: Date;
|
|
64
|
+
paidEmail?: string;
|
|
65
|
+
paidDetail?: string;
|
|
66
|
+
creditsGranted?: number;
|
|
67
|
+
payUpdatedAt?: Date;
|
|
68
|
+
paymentStatus?: string;
|
|
69
|
+
}, tx?: Prisma.TransactionClient): Promise<Transaction>;
|
|
70
|
+
processRefund(orderId: string, refundData: {
|
|
71
|
+
refundAmount?: number;
|
|
72
|
+
refundReason?: string;
|
|
73
|
+
refundedAt?: Date;
|
|
74
|
+
}, tx?: Prisma.TransactionClient): Promise<Transaction>;
|
|
75
|
+
cancelOrder(orderId: string, reason?: string, tx?: Prisma.TransactionClient): Promise<Transaction>;
|
|
76
|
+
getExpiredOrders(tx?: Prisma.TransactionClient): Promise<Transaction[]>;
|
|
77
|
+
updateExpiredOrders(tx?: Prisma.TransactionClient): Promise<number>;
|
|
78
|
+
getSubscriptionTransactions(paySubscriptionId: string, tx?: Prisma.TransactionClient): Promise<Transaction[]>;
|
|
79
|
+
getRevenueStats(startDate?: Date, endDate?: Date, tx?: Prisma.TransactionClient): Promise<{
|
|
80
|
+
totalRevenue: number;
|
|
81
|
+
totalTransactions: number;
|
|
82
|
+
averageOrderValue: number;
|
|
83
|
+
subscriptionRevenue: number;
|
|
84
|
+
oneTimeRevenue: number;
|
|
85
|
+
refundedAmount: number;
|
|
86
|
+
}>;
|
|
87
|
+
getDailyRevenue(days?: number, tx?: Prisma.TransactionClient): Promise<any[]>;
|
|
88
|
+
deleteTransaction(orderId: string, tx?: Prisma.TransactionClient): Promise<void>;
|
|
89
|
+
createBatchTransactions(transactions: Prisma.TransactionCreateManyInput[], tx?: Prisma.TransactionClient): Promise<number>;
|
|
90
|
+
}
|
|
91
|
+
export declare const transactionService: TransactionService;
|
|
92
|
+
//# sourceMappingURL=transaction.service.d.ts.map
|