refactor: remove unused Stripe dependency and update credit expiration logic
This commit is contained in:
parent
8a08dfdf3b
commit
31116cbf8b
@ -11,9 +11,9 @@
|
|||||||
"language": "切换语言",
|
"language": "切换语言",
|
||||||
"mode": {
|
"mode": {
|
||||||
"label": "切换模式",
|
"label": "切换模式",
|
||||||
"light": "浅色",
|
"light": "浅色模式",
|
||||||
"dark": "深色",
|
"dark": "深色模式",
|
||||||
"system": "系统"
|
"system": "跟随系统"
|
||||||
},
|
},
|
||||||
"theme": {
|
"theme": {
|
||||||
"label": "切换主题",
|
"label": "切换主题",
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"dev-https": "next dev --experimental-https",
|
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"postinstall": "fumadocs-mdx",
|
"postinstall": "fumadocs-mdx",
|
||||||
@ -73,7 +72,6 @@
|
|||||||
"@radix-ui/react-tooltip": "^1.1.8",
|
"@radix-ui/react-tooltip": "^1.1.8",
|
||||||
"@react-email/components": "0.0.33",
|
"@react-email/components": "0.0.33",
|
||||||
"@react-email/render": "1.0.5",
|
"@react-email/render": "1.0.5",
|
||||||
"@stripe/react-stripe-js": "^3.7.0",
|
|
||||||
"@stripe/stripe-js": "^5.6.0",
|
"@stripe/stripe-js": "^5.6.0",
|
||||||
"@tabler/icons-react": "^3.31.0",
|
"@tabler/icons-react": "^3.31.0",
|
||||||
"@tanstack/react-table": "^8.21.2",
|
"@tanstack/react-table": "^8.21.2",
|
||||||
|
17
pnpm-lock.yaml
generated
17
pnpm-lock.yaml
generated
@ -152,9 +152,6 @@ importers:
|
|||||||
'@react-email/render':
|
'@react-email/render':
|
||||||
specifier: 1.0.5
|
specifier: 1.0.5
|
||||||
version: 1.0.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 1.0.5(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
'@stripe/react-stripe-js':
|
|
||||||
specifier: ^3.7.0
|
|
||||||
version: 3.7.0(@stripe/stripe-js@5.6.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
|
||||||
'@stripe/stripe-js':
|
'@stripe/stripe-js':
|
||||||
specifier: ^5.6.0
|
specifier: ^5.6.0
|
||||||
version: 5.6.0
|
version: 5.6.0
|
||||||
@ -3854,13 +3851,6 @@ packages:
|
|||||||
'@standard-schema/spec@1.0.0':
|
'@standard-schema/spec@1.0.0':
|
||||||
resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
|
resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
|
||||||
|
|
||||||
'@stripe/react-stripe-js@3.7.0':
|
|
||||||
resolution: {integrity: sha512-PYls/2S9l0FF+2n0wHaEJsEU8x7CmBagiH7zYOsxbBlLIHEsqUIQ4MlIAbV9Zg6xwT8jlYdlRIyBTHmO3yM7kQ==}
|
|
||||||
peerDependencies:
|
|
||||||
'@stripe/stripe-js': '>=1.44.1 <8.0.0'
|
|
||||||
react: '>=16.8.0 <20.0.0'
|
|
||||||
react-dom: '>=16.8.0 <20.0.0'
|
|
||||||
|
|
||||||
'@stripe/stripe-js@5.6.0':
|
'@stripe/stripe-js@5.6.0':
|
||||||
resolution: {integrity: sha512-w8CEY73X/7tw2KKlL3iOk679V9bWseE4GzNz3zlaYxcTjmcmWOathRb0emgo/QQ3eoNzmq68+2Y2gxluAv3xGw==}
|
resolution: {integrity: sha512-w8CEY73X/7tw2KKlL3iOk679V9bWseE4GzNz3zlaYxcTjmcmWOathRb0emgo/QQ3eoNzmq68+2Y2gxluAv3xGw==}
|
||||||
engines: {node: '>=12.16'}
|
engines: {node: '>=12.16'}
|
||||||
@ -10003,13 +9993,6 @@ snapshots:
|
|||||||
|
|
||||||
'@standard-schema/spec@1.0.0': {}
|
'@standard-schema/spec@1.0.0': {}
|
||||||
|
|
||||||
'@stripe/react-stripe-js@3.7.0(@stripe/stripe-js@5.6.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
|
||||||
dependencies:
|
|
||||||
'@stripe/stripe-js': 5.6.0
|
|
||||||
prop-types: 15.8.1
|
|
||||||
react: 19.0.0
|
|
||||||
react-dom: 19.0.0(react@19.0.0)
|
|
||||||
|
|
||||||
'@stripe/stripe-js@5.6.0': {}
|
'@stripe/stripe-js@5.6.0': {}
|
||||||
|
|
||||||
'@swc/counter@0.1.3': {}
|
'@swc/counter@0.1.3': {}
|
||||||
|
@ -8,8 +8,8 @@ import { addDays } from 'date-fns';
|
|||||||
import { and, eq, gte, isNotNull, lte, sql, sum } from 'drizzle-orm';
|
import { and, eq, gte, isNotNull, lte, sql, sum } from 'drizzle-orm';
|
||||||
import { createSafeActionClient } from 'next-safe-action';
|
import { createSafeActionClient } from 'next-safe-action';
|
||||||
|
|
||||||
const CREDITS_EXPIRATION_DAYS = 30;
|
const CREDITS_EXPIRATION_DAYS = 31;
|
||||||
const CREDITS_MONTHLY_DAYS = 30;
|
const CREDITS_MONTHLY_DAYS = 31;
|
||||||
|
|
||||||
// Create a safe action client
|
// Create a safe action client
|
||||||
const actionClient = createSafeActionClient();
|
const actionClient = createSafeActionClient();
|
||||||
@ -21,6 +21,7 @@ export const getCreditStatsAction = actionClient.action(async () => {
|
|||||||
try {
|
try {
|
||||||
const session = await getSession();
|
const session = await getSession();
|
||||||
if (!session) {
|
if (!session) {
|
||||||
|
console.warn('unauthorized request to get credit stats');
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: 'Unauthorized',
|
error: 'Unauthorized',
|
||||||
@ -30,8 +31,8 @@ export const getCreditStatsAction = actionClient.action(async () => {
|
|||||||
const db = await getDb();
|
const db = await getDb();
|
||||||
const userId = session.user.id;
|
const userId = session.user.id;
|
||||||
|
|
||||||
// Get credits expiring in the next 30 days
|
// Get credits expiring in the next CREDITS_EXPIRATION_DAYS days
|
||||||
const thirtyDaysFromNow = addDays(new Date(), CREDITS_EXPIRATION_DAYS);
|
const expirationDaysFromNow = addDays(new Date(), CREDITS_EXPIRATION_DAYS);
|
||||||
const expiringCredits = await db
|
const expiringCredits = await db
|
||||||
.select({
|
.select({
|
||||||
amount: sum(creditTransaction.remainingAmount),
|
amount: sum(creditTransaction.remainingAmount),
|
||||||
@ -44,13 +45,13 @@ export const getCreditStatsAction = actionClient.action(async () => {
|
|||||||
isNotNull(creditTransaction.expirationDate),
|
isNotNull(creditTransaction.expirationDate),
|
||||||
isNotNull(creditTransaction.remainingAmount),
|
isNotNull(creditTransaction.remainingAmount),
|
||||||
gte(creditTransaction.remainingAmount, 1),
|
gte(creditTransaction.remainingAmount, 1),
|
||||||
lte(creditTransaction.expirationDate, thirtyDaysFromNow),
|
lte(creditTransaction.expirationDate, expirationDaysFromNow),
|
||||||
gte(creditTransaction.expirationDate, new Date())
|
gte(creditTransaction.expirationDate, new Date())
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get credits from subscription renewals (recent 30 days)
|
// Get credits from subscription renewals (recent CREDITS_MONTHLY_DAYS days)
|
||||||
const thirtyDaysAgo = addDays(new Date(), -CREDITS_MONTHLY_DAYS);
|
const monthlyRefreshDaysAgo = addDays(new Date(), -CREDITS_MONTHLY_DAYS);
|
||||||
const subscriptionCredits = await db
|
const subscriptionCredits = await db
|
||||||
.select({
|
.select({
|
||||||
amount: sum(creditTransaction.amount),
|
amount: sum(creditTransaction.amount),
|
||||||
@ -63,11 +64,11 @@ export const getCreditStatsAction = actionClient.action(async () => {
|
|||||||
creditTransaction.type,
|
creditTransaction.type,
|
||||||
CREDIT_TRANSACTION_TYPE.SUBSCRIPTION_RENEWAL
|
CREDIT_TRANSACTION_TYPE.SUBSCRIPTION_RENEWAL
|
||||||
),
|
),
|
||||||
gte(creditTransaction.createdAt, thirtyDaysAgo)
|
gte(creditTransaction.createdAt, monthlyRefreshDaysAgo)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get credits from monthly lifetime distribution (recent 30 days)
|
// Get credits from monthly lifetime distribution (recent CREDITS_MONTHLY_DAYS days)
|
||||||
const lifetimeCredits = await db
|
const lifetimeCredits = await db
|
||||||
.select({
|
.select({
|
||||||
amount: sum(creditTransaction.amount),
|
amount: sum(creditTransaction.amount),
|
||||||
@ -77,7 +78,7 @@ export const getCreditStatsAction = actionClient.action(async () => {
|
|||||||
and(
|
and(
|
||||||
eq(creditTransaction.userId, userId),
|
eq(creditTransaction.userId, userId),
|
||||||
eq(creditTransaction.type, CREDIT_TRANSACTION_TYPE.LIFETIME_MONTHLY),
|
eq(creditTransaction.type, CREDIT_TRANSACTION_TYPE.LIFETIME_MONTHLY),
|
||||||
gte(creditTransaction.createdAt, thirtyDaysAgo)
|
gte(creditTransaction.createdAt, monthlyRefreshDaysAgo)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import {
|
|||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { useTranslations } from 'next-intl';
|
import { useTranslations } from 'next-intl';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { CREDIT_TRANSACTION_TYPE } from './types';
|
import { CREDIT_TRANSACTION_TYPE } from '../../../credits/types';
|
||||||
|
|
||||||
// Define the credit transaction interface (matching the one in the table)
|
// Define the credit transaction interface (matching the one in the table)
|
||||||
export interface CreditTransaction {
|
export interface CreditTransaction {
|
@ -1,5 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { CreditDetailViewer } from '@/components/settings/credits/credit-detail-viewer';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@ -31,7 +32,6 @@ import {
|
|||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from '@/components/ui/tooltip';
|
} from '@/components/ui/tooltip';
|
||||||
import { CreditDetailViewer } from '@/credits/credit-detail-viewer';
|
|
||||||
import { CREDIT_TRANSACTION_TYPE } from '@/credits/types';
|
import { CREDIT_TRANSACTION_TYPE } from '@/credits/types';
|
||||||
import { formatDate } from '@/lib/formatter';
|
import { formatDate } from '@/lib/formatter';
|
||||||
import { CaretDownIcon, CaretUpIcon } from '@radix-ui/react-icons';
|
import { CaretDownIcon, CaretUpIcon } from '@radix-ui/react-icons';
|
||||||
|
@ -118,18 +118,18 @@ export async function addCredits({
|
|||||||
}) {
|
}) {
|
||||||
if (!userId || !type || !description) {
|
if (!userId || !type || !description) {
|
||||||
console.error('addCredits, invalid params', userId, type, description);
|
console.error('addCredits, invalid params', userId, type, description);
|
||||||
throw new Error('addCredits, invalid params');
|
throw new Error('Invalid params');
|
||||||
}
|
}
|
||||||
if (!Number.isFinite(amount) || amount <= 0) {
|
if (!Number.isFinite(amount) || amount <= 0) {
|
||||||
console.error('addCredits, invalid amount', userId, amount);
|
console.error('addCredits, invalid amount', userId, amount);
|
||||||
throw new Error('addCredits, invalid amount');
|
throw new Error('Invalid amount');
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
expireDays !== undefined &&
|
expireDays !== undefined &&
|
||||||
(!Number.isFinite(expireDays) || expireDays <= 0)
|
(!Number.isFinite(expireDays) || expireDays <= 0)
|
||||||
) {
|
) {
|
||||||
console.error('addCredits, invalid expire days', userId, expireDays);
|
console.error('addCredits, invalid expire days', userId, expireDays);
|
||||||
throw new Error('addCredits, invalid expire days');
|
throw new Error('Invalid expire days');
|
||||||
}
|
}
|
||||||
// Process expired credits first
|
// Process expired credits first
|
||||||
await processExpiredCredits(userId);
|
await processExpiredCredits(userId);
|
||||||
@ -201,11 +201,11 @@ export async function consumeCredits({
|
|||||||
}) {
|
}) {
|
||||||
if (!userId || !description) {
|
if (!userId || !description) {
|
||||||
console.error('consumeCredits, invalid params', userId, description);
|
console.error('consumeCredits, invalid params', userId, description);
|
||||||
throw new Error('consumeCredits, invalid params');
|
throw new Error('Invalid params');
|
||||||
}
|
}
|
||||||
if (!Number.isFinite(amount) || amount <= 0) {
|
if (!Number.isFinite(amount) || amount <= 0) {
|
||||||
console.error('consumeCredits, invalid amount', userId, amount);
|
console.error('consumeCredits, invalid amount', userId, amount);
|
||||||
throw new Error('consumeCredits, invalid amount');
|
throw new Error('Invalid amount');
|
||||||
}
|
}
|
||||||
// Process expired credits first
|
// Process expired credits first
|
||||||
await processExpiredCredits(userId);
|
await processExpiredCredits(userId);
|
||||||
|
Loading…
Reference in New Issue
Block a user