feat: unified gravity system - VIP members consume gravity instead of unlimited; add monthly gravity top-up cron
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 引力值迁移脚本
|
||||
* 将现有用户的多维额度合并到 gravity 字段
|
||||
* 公式: gravity = interviewCredits×5 + resumeOptimizeCredits×3 + resumeDownloadCredits×2 + shareCredits×1 + remaining×5
|
||||
* 用法: npx ts-node --project tsconfig.json scripts/migrate-gravity.ts
|
||||
*/
|
||||
import { NestFactory } from '@nestjs/core'
|
||||
import { AppModule } from '../src/app.module'
|
||||
import { getModelToken } from '@nestjs/mongoose'
|
||||
import { User, UserDocument } from '../src/modules/user/user.schema'
|
||||
import { Model } from 'mongoose'
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.createApplicationContext(AppModule)
|
||||
const userModel = app.get<Model<UserDocument>>(getModelToken(User.name))
|
||||
|
||||
const total = await userModel.countDocuments().exec()
|
||||
console.log(`Total users: ${total}`)
|
||||
|
||||
let migrated = 0
|
||||
let skipped = 0
|
||||
const cursor = userModel.find().cursor()
|
||||
|
||||
for await (const user of cursor) {
|
||||
const interviewVal = (user.interviewCredits ?? 0) * 5
|
||||
const optimizeVal = (user.resumeOptimizeCredits ?? 0) * 3
|
||||
const downloadVal = (user.resumeDownloadCredits ?? 0) * 2
|
||||
const oldRemainVal = (user.remaining ?? 0) * 5
|
||||
const shareVal = (user.shareCredits ?? 0) * 1
|
||||
const totalGravity = interviewVal + optimizeVal + downloadVal + oldRemainVal + shareVal
|
||||
|
||||
if (totalGravity <= 0 && (user.gravity ?? 0) === 0) {
|
||||
skipped++
|
||||
continue
|
||||
}
|
||||
|
||||
await userModel.findByIdAndUpdate(user._id, {
|
||||
$set: {
|
||||
gravity: Math.max(user.gravity ?? 0, totalGravity),
|
||||
interviewCredits: 0,
|
||||
resumeOptimizeCredits: 0,
|
||||
resumeDownloadCredits: 0,
|
||||
remaining: 0,
|
||||
shareCredits: 0,
|
||||
},
|
||||
}).exec()
|
||||
migrated++
|
||||
}
|
||||
|
||||
console.log(`Migrated: ${migrated}, Skipped (no credits): ${skipped}`)
|
||||
await app.close()
|
||||
}
|
||||
|
||||
bootstrap().catch(console.error)
|
||||
Reference in New Issue
Block a user