- 移除「用户 → 推广码运营」页面(trait、子菜单、admin SPA 跳转路由) - 移除管理端 REST:/revenue/codes 列表与 generate/disable/regenerate 变更接口, 清理 rest_codes/rest_mutate_code/can_manage_codes/list_codes 死代码 - 推广码改为注册即得:bind_registered_user 内生成唯一推广码,无需后台管理 - 推广配置统一收敛到「支付&付费 → 推广返佣」设置段(现状保留,无改动) - 契约测试固化:无管理路由/页面残留 + 注册即得码
96 lines
5.3 KiB
JavaScript
96 lines
5.3 KiB
JavaScript
const test = require('node:test')
|
|
const assert = require('node:assert/strict')
|
|
const fs = require('node:fs')
|
|
const path = require('node:path')
|
|
|
|
const root = path.resolve(__dirname, '..', '..')
|
|
const read = (...segments) => fs.readFileSync(path.join(root, ...segments), 'utf8')
|
|
|
|
test('referral attribution model is a single runtime source with schema surface', () => {
|
|
const runtime = read('src', 'Settings', 'CreditsRuntime.php')
|
|
const attribution = read('src', 'Payment', 'ReferralAttribution.php')
|
|
const phpSchema = read('src', 'Admin', 'Schema', 'SchemaPayment.php')
|
|
const jsSchema = read('assets', 'admin', 'src', 'schema', 'sections', 'payment', 'affiliate.js')
|
|
|
|
// 运行时:唯一枚举与默认值。
|
|
assert.match(runtime, /referral_attribution_model/)
|
|
assert.match(runtime, /\['first_touch', 'last_touch'\]/)
|
|
assert.match(runtime, /'attribution_model' => \$attribution/)
|
|
|
|
// 归因行为:capture 末触覆盖、首触保持;注册仲裁按模式取优先方。
|
|
assert.match(attribution, /\$this->attribution_model\(\) !== 'last_touch'/)
|
|
assert.match(attribution, /!?\(\$last_touch && \$submitted_valid\)/)
|
|
assert.match(attribution, /已按最近访问的推广关系绑定/)
|
|
assert.match(attribution, /已按首次访问的推广关系绑定/)
|
|
|
|
// 管理端双 schema 同步暴露该字段。
|
|
for (const schema of [phpSchema, jsSchema]) {
|
|
assert.match(schema, /referral_attribution_model/)
|
|
assert.match(schema, /first_touch/)
|
|
assert.match(schema, /last_touch/)
|
|
}
|
|
})
|
|
|
|
test('disabled-code stop-commission switch is wired end to end', () => {
|
|
const runtime = read('src', 'Settings', 'PaymentRuntime.php')
|
|
const ledger = read('src', 'Payment', 'CommissionLedger.php')
|
|
const attribution = read('src', 'Payment', 'ReferralAttribution.php')
|
|
const phpSchema = read('src', 'Admin', 'Schema', 'SchemaPayment.php')
|
|
const jsSchema = read('assets', 'admin', 'src', 'schema', 'sections', 'payment', 'affiliate.js')
|
|
|
|
assert.match(runtime, /'disabled_code_stops_commission' => !empty\(\$settings\['affiliate_disabled_code_stops_commission'\]\)/)
|
|
// 记账入口必须在 resolve 推广人之后、写 ledger 之前校验推广码状态。
|
|
assert.match(ledger, /ReferralAttribution::get_instance\(\)->resolve\(\$buyer\)/)
|
|
assert.match(ledger, /is_promoter_code_active\(\$promoter\)/)
|
|
assert.ok(
|
|
ledger.indexOf('is_promoter_code_active($promoter)') < ledger.indexOf('$wpdb->insert($table'),
|
|
'disabled-code gate must run before the ledger insert'
|
|
)
|
|
assert.match(attribution, /public function is_promoter_code_active\(int \$promoter_id\): bool/)
|
|
for (const schema of [phpSchema, jsSchema]) {
|
|
assert.match(schema, /affiliate_disabled_code_stops_commission/)
|
|
}
|
|
})
|
|
|
|
test('commission base is the discounted payable amount, not the list price', () => {
|
|
// 下单侧:content 订单金额取优惠链(推广让利 + 优惠券)后的应付净额。
|
|
const payOrders = read('src', 'Content', 'PayOrders.php')
|
|
assert.match(payOrders, /\$amount_minor = max\(0, \(int\) \(\$discounted\['payable_minor'\] \?\? 0\)\)/)
|
|
// 记账侧:佣金基数直接取订单实付金额。
|
|
const ledger = read('src', 'Payment', 'CommissionLedger.php')
|
|
assert.match(ledger, /AssetAmount::balance\(is_string\(\$order\['amount'\] \?\? null\) \? \$order\['amount'\] : ''\)/)
|
|
})
|
|
|
|
test('lazy settlement backstop guards the earnings entry points', () => {
|
|
const ledger = read('src', 'Payment', 'CommissionLedger.php')
|
|
const attribution = read('src', 'Payment', 'ReferralAttribution.php')
|
|
|
|
assert.match(ledger, /private static bool \$lazy_settled = false/)
|
|
assert.match(ledger, /public function lazy_settle_due\(\): void/)
|
|
assert.match(ledger, /if \(!\\AKSRT\\Settings\\Settings::affiliate_enabled\(\)\) return;/)
|
|
assert.ok(
|
|
ledger.indexOf('lazy_settle_due()') < ledger.indexOf('global \$wpdb; \$table=\$this->table\(\'commission_ledger\'\); \$row=\$wpdb->get_row'),
|
|
'overview() must trigger the backstop before aggregating balances'
|
|
)
|
|
// 收益总览与我的推广两个入口都接入了兜底。
|
|
assert.match(attribution, /CommissionLedger::get_instance\(\)->lazy_settle_due\(\)/)
|
|
})
|
|
|
|
test('referral codes are self-serve: no admin ops page, granted at registration', () => {
|
|
const service = read('src', 'Payment', 'ReferralAttribution.php')
|
|
// 管理端代码已清理:无 /revenue/codes 路由、无后台增删改接口、无管理列表。
|
|
assert.doesNotMatch(service, /revenue\/codes/)
|
|
assert.doesNotMatch(service, /rest_mutate_code|rest_codes|can_manage_codes|private function list_codes/)
|
|
// 注册即得唯一推广码:bind_registered_user 内调用 generate_code,不依赖归因开关。
|
|
assert.match(service, /public function bind_registered_user\(int \$invitee_id\): void \{\s*\n\s*\/\/ 每个新用户注册即拥有唯一推广码[\s\S]*?\$this->generate_code\(\$invitee_id, false\)/)
|
|
|
|
// 用户菜单不再挂"推广码运营"页,trait 文件已删除。
|
|
const menus = read('src', 'Admin', 'Native', 'UsersMenus.php')
|
|
assert.doesNotMatch(menus, /UsersMenusReferral|aksrt_referral_codes|render_referral_codes_page/)
|
|
assert.equal(fs.existsSync(path.join(root, 'src', 'Admin', 'Native', 'UsersMenusReferral.php')), false)
|
|
|
|
// admin SPA 不再保留跳转路由。
|
|
const router = read('assets', 'admin', 'src', 'router', 'index.js')
|
|
assert.doesNotMatch(router, /referral-codes/)
|
|
})
|