339 lines
11 KiB
JavaScript
339 lines
11 KiB
JavaScript
|
|
#!/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)
|
|||
|
|
})
|