Files
soul-yongping/scripts/test-referral-flow.js

339 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* 新分销逻辑功能测试脚本
*
* 测试场景:
* 1. A 推荐 B新绑定
* 2. B 点击 C 的链接(立即切换)
* 3. B 购买商品(分佣给 C
* 4. B 再次购买(累加佣金)
* 5. 模拟过期解绑
*/
const mysql = require('mysql2/promise')
require('dotenv').config()
const DB_CONFIG = {
host: process.env.DB_HOST || 'localhost',
port: parseInt(process.env.DB_PORT) || 3306,
user: process.env.DB_USER || 'root',
password: process.env.DB_PASSWORD || '',
database: process.env.DB_NAME || 'mycontent_db',
}
// 测试数据
const TEST_USERS = {
A: { id: 'test_user_a', nickname: '推荐人A', referral_code: 'TESTA001' },
B: { id: 'test_user_b', nickname: '购买者B', referral_code: 'TESTB001' },
C: { id: 'test_user_c', nickname: '推荐人C', referral_code: 'TESTC001' },
}
async function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
async function testFlow() {
console.log('=' .repeat(60))
console.log('新分销逻辑 - 功能测试')
console.log('=' .repeat(60))
console.log()
let connection
try {
// 连接数据库
connection = await mysql.createConnection(DB_CONFIG)
console.log('✅ 已连接到数据库')
console.log()
// ========================================
// 步骤1: 清理旧数据
// ========================================
console.log('步骤 1: 清理测试数据...')
console.log('-' .repeat(60))
await connection.execute(
`DELETE FROM referral_bindings WHERE referee_id IN (?, ?, ?)`,
[TEST_USERS.A.id, TEST_USERS.B.id, TEST_USERS.C.id]
)
await connection.execute(
`DELETE FROM users WHERE id IN (?, ?, ?)`,
[TEST_USERS.A.id, TEST_USERS.B.id, TEST_USERS.C.id]
)
console.log('✅ 测试数据已清理')
console.log()
// ========================================
// 步骤2: 创建测试用户
// ========================================
console.log('步骤 2: 创建测试用户...')
console.log('-' .repeat(60))
for (const user of Object.values(TEST_USERS)) {
await connection.execute(
`INSERT INTO users (id, nickname, referral_code, phone, created_at)
VALUES (?, ?, ?, ?, NOW())`,
[user.id, user.nickname, user.referral_code, `138${Math.random().toString().slice(2, 10)}`]
)
console.log(`${user.nickname} (${user.id})`)
}
console.log()
// ========================================
// 步骤3: A 推荐 B新绑定
// ========================================
console.log('步骤 3: A 推荐 B新绑定...')
console.log('-' .repeat(60))
await connection.execute(
`INSERT INTO referral_bindings
(id, referee_id, referrer_id, referral_code, status, binding_date, expiry_date)
VALUES (?, ?, ?, ?, 'active', NOW(), DATE_ADD(NOW(), INTERVAL 30 DAY))`,
['bind_test_1', TEST_USERS.B.id, TEST_USERS.A.id, TEST_USERS.A.referral_code]
)
console.log(` ✓ B 绑定到 A过期时间30天后`)
console.log()
await sleep(500)
// 查询当前绑定
const [bindings1] = await connection.execute(
`SELECT * FROM referral_bindings WHERE referee_id = ?`,
[TEST_USERS.B.id]
)
console.log(' 当前绑定关系:')
bindings1.forEach(b => {
console.log(` - 推荐人: ${b.referrer_id}, 状态: ${b.status}`)
})
console.log()
// ========================================
// 步骤4: B 点击 C 的链接(立即切换)
// ========================================
console.log('步骤 4: B 点击 C 的链接(立即切换)...')
console.log('-' .repeat(60))
// 标记旧绑定为 cancelled
await connection.execute(
`UPDATE referral_bindings SET status = 'cancelled' WHERE id = ?`,
['bind_test_1']
)
// 创建新绑定
await connection.execute(
`INSERT INTO referral_bindings
(id, referee_id, referrer_id, referral_code, status, binding_date, expiry_date)
VALUES (?, ?, ?, ?, 'active', NOW(), DATE_ADD(NOW(), INTERVAL 30 DAY))`,
['bind_test_2', TEST_USERS.B.id, TEST_USERS.C.id, TEST_USERS.C.referral_code]
)
console.log(` ✓ B 的推荐人从 A 切换到 C`)
console.log()
await sleep(500)
// 查询绑定历史
const [bindings2] = await connection.execute(
`SELECT * FROM referral_bindings WHERE referee_id = ? ORDER BY binding_date DESC`,
[TEST_USERS.B.id]
)
console.log(' 绑定历史:')
bindings2.forEach((b, i) => {
console.log(` ${i + 1}. 推荐人: ${b.referrer_id}, 状态: ${b.status}, 时间: ${b.binding_date.toLocaleString('zh-CN')}`)
})
console.log()
// ========================================
// 步骤5: B 购买商品(分佣给 C
// ========================================
console.log('步骤 5: B 购买商品(分佣给 C...')
console.log('-' .repeat(60))
const purchaseAmount = 1.0
const commission = Math.round(purchaseAmount * 0.9 * 100) / 100 // 90%
// 更新 C 的收益
await connection.execute(
`UPDATE users SET pending_earnings = pending_earnings + ? WHERE id = ?`,
[commission, TEST_USERS.C.id]
)
// 更新绑定记录(累加购买次数)
await connection.execute(
`UPDATE referral_bindings
SET purchase_count = purchase_count + 1,
total_commission = total_commission + ?,
last_purchase_date = NOW()
WHERE id = ?`,
[commission, 'bind_test_2']
)
console.log(` ✓ B 购买 ¥${purchaseAmount}C 获得佣金 ¥${commission}`)
console.log()
await sleep(500)
// 查询分佣结果
const [earnings1] = await connection.execute(
`SELECT rb.*, u.pending_earnings
FROM referral_bindings rb
JOIN users u ON rb.referrer_id = u.id
WHERE rb.id = ?`,
['bind_test_2']
)
if (earnings1.length > 0) {
const e = earnings1[0]
console.log(' 分佣结果:')
console.log(` - 购买次数: ${e.purchase_count}`)
console.log(` - 累计佣金: ¥${e.total_commission.toFixed(2)}`)
console.log(` - C 的待提现: ¥${e.pending_earnings.toFixed(2)}`)
}
console.log()
// ========================================
// 步骤6: B 再次购买(累加)
// ========================================
console.log('步骤 6: B 再次购买(累加佣金)...')
console.log('-' .repeat(60))
// 第二次购买
await connection.execute(
`UPDATE users SET pending_earnings = pending_earnings + ? WHERE id = ?`,
[commission, TEST_USERS.C.id]
)
await connection.execute(
`UPDATE referral_bindings
SET purchase_count = purchase_count + 1,
total_commission = total_commission + ?,
last_purchase_date = NOW()
WHERE id = ?`,
[commission, 'bind_test_2']
)
console.log(` ✓ B 再次购买 ¥${purchaseAmount}C 再获得 ¥${commission}`)
console.log()
await sleep(500)
// 查询累加结果
const [earnings2] = await connection.execute(
`SELECT rb.*, u.pending_earnings
FROM referral_bindings rb
JOIN users u ON rb.referrer_id = u.id
WHERE rb.id = ?`,
['bind_test_2']
)
if (earnings2.length > 0) {
const e = earnings2[0]
console.log(' 累加结果:')
console.log(` - 购买次数: ${e.purchase_count}`)
console.log(` - 累计佣金: ¥${e.total_commission.toFixed(2)}`)
console.log(` - C 的待提现: ¥${e.pending_earnings.toFixed(2)}`)
}
console.log()
// ========================================
// 步骤7: 模拟过期解绑
// ========================================
console.log('步骤 7: 模拟过期解绑(修改过期时间)...')
console.log('-' .repeat(60))
// 创建一个无购买的绑定
await connection.execute(
`INSERT INTO referral_bindings
(id, referee_id, referrer_id, referral_code, status, binding_date, expiry_date, purchase_count)
VALUES (?, ?, ?, ?, 'active', NOW(), '2026-02-01', 0)`,
['bind_test_3', 'test_user_d', TEST_USERS.A.id, TEST_USERS.A.referral_code]
)
console.log(` ✓ 创建一个已过期且无购买的绑定test_user_d -> A`)
console.log()
// 查询过期记录
const [expired] = await connection.execute(
`SELECT * FROM referral_bindings
WHERE status = 'active' AND expiry_date < NOW() AND purchase_count = 0`
)
console.log(` 找到 ${expired.length} 条需要解绑的记录`)
if (expired.length > 0) {
// 执行解绑
const ids = expired.map(e => e.id)
const placeholders = ids.map(() => '?').join(',')
await connection.execute(
`UPDATE referral_bindings SET status = 'expired' WHERE id IN (${placeholders})`,
ids
)
console.log(` ✅ 已解绑 ${expired.length} 条记录`)
expired.forEach(e => {
console.log(` - ${e.referee_id}${e.referrer_id} 的绑定已过期`)
})
}
console.log()
// ========================================
// 总结
// ========================================
console.log('=' .repeat(60))
console.log('✅ 测试完成!')
console.log('=' .repeat(60))
console.log()
console.log('测试结果总结:')
console.log(' ✅ 立即切换绑定 - 正常')
console.log(' ✅ 购买分佣给最新推荐人 - 正常')
console.log(' ✅ 购买次数累加 - 正常')
console.log(' ✅ 佣金累加 - 正常')
console.log(' ✅ 过期自动解绑 - 正常')
console.log()
// ========================================
// 清理测试数据
// ========================================
console.log('清理测试数据...')
await connection.execute(
`DELETE FROM referral_bindings WHERE referee_id IN (?, ?, ?, ?)`,
[TEST_USERS.A.id, TEST_USERS.B.id, TEST_USERS.C.id, 'test_user_d']
)
await connection.execute(
`DELETE FROM users WHERE id IN (?, ?, ?)`,
[TEST_USERS.A.id, TEST_USERS.B.id, TEST_USERS.C.id]
)
console.log('✅ 测试数据已清理')
console.log()
} catch (error) {
console.error('❌ 测试失败:', error.message)
console.error(error.stack)
throw error
} finally {
if (connection) {
await connection.end()
}
}
}
// 运行测试
testFlow().then(() => {
console.log('测试脚本执行完成')
process.exit(0)
}).catch(err => {
console.error('脚本执行失败')
process.exit(1)
})