新增订阅额度风险预警计算

This commit is contained in:
yuming
2026-08-15 17:43:19 +08:00
parent 07ee98f838
commit 3a61b7952b
2 changed files with 144 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
const test = require('node:test')
const assert = require('node:assert')
const { expandEvents, computeAtRisk, LOOKAHEAD_DAYS } = require('../src/atRisk')
const TODAY = new Date(2026, 7, 15) // 2026-08-15
// 距今 10 天的公历纪念日,提前 3 天提醒
const near = {
id: 'a1', personName: '张三', remindEnabled: 1, importance: 'high',
isLunar: false, solarMonth: 8, solarDay: 25, remindDays: 3
}
// 距今 40 天
const mid = {
id: 'a2', personName: '李四', remindEnabled: 1, importance: 'low',
isLunar: false, solarMonth: 9, solarDay: 24, remindDays: 7
}
test('LOOKAHEAD_DAYS 为 60', () => {
assert.strictEqual(LOOKAHEAD_DAYS, 60)
})
test('一条纪念日展开出「当天」和「提前」两个事件', () => {
const events = expandEvents(near, TODAY)
assert.strictEqual(events.length, 2)
const onDay = events.find(e => e.kind === 'onDay')
const ahead = events.find(e => e.kind === 'ahead')
assert.strictEqual(onDay.fireInDays, 10)
assert.strictEqual(ahead.fireInDays, 7)
})
test('remindDays 为 0 时只有当天事件', () => {
const events = expandEvents({ ...near, remindDays: 0 }, TODAY)
assert.strictEqual(events.length, 1)
assert.strictEqual(events[0].kind, 'onDay')
})
test('超出 60 天窗口的事件被过滤掉', () => {
const far = { ...near, solarMonth: 12, solarDay: 25, remindDays: 3 }
assert.strictEqual(expandEvents(far, TODAY).length, 0)
})
test('提前日已过、当天未到时,只剩当天事件', () => {
// 距今 2 天,但提前 7 天的时点早已过去
const soon = { ...near, solarMonth: 8, solarDay: 17, remindDays: 7 }
const events = expandEvents(soon, TODAY)
assert.strictEqual(events.length, 1)
assert.strictEqual(events[0].kind, 'onDay')
})
test('余额足够时没有风险', () => {
const r = computeAtRisk([near, mid], 10, TODAY)
assert.strictEqual(r.atRiskCount, 0)
assert.deepStrictEqual(r.atRiskNames, [])
})
test('余额为 0 时全部有风险', () => {
const r = computeAtRisk([near, mid], 0, TODAY)
assert.strictEqual(r.atRiskCount, 4)
assert.deepStrictEqual(r.atRiskNames, ['张三', '李四'])
})
test('按时间先后消耗额度,后面的才有风险', () => {
// 张三的两个事件在第 7、10 天,李四的在第 33、40 天
const r = computeAtRisk([near, mid], 2, TODAY)
assert.strictEqual(r.atRiskCount, 2)
assert.deepStrictEqual(r.atRiskNames, ['李四'])
})
test('人名去重,同一人占两条只出现一次', () => {
const r = computeAtRisk([near], 0, TODAY)
assert.strictEqual(r.atRiskCount, 2)
assert.deepStrictEqual(r.atRiskNames, ['张三'])
})
test('未开启提醒的纪念日不参与计算', () => {
const r = computeAtRisk([{ ...near, remindEnabled: 0 }], 0, TODAY)
assert.strictEqual(r.atRiskCount, 0)
})