fix(wecom): 经营报告截账至发送日前一天24点

日报、周报、月报均不含发送当天发生额,避免盘中数据未闭合。
This commit is contained in:
2026-09-02 22:05:03 +08:00
parent 68a4b7f984
commit 92dfbf5722
5 changed files with 34 additions and 23 deletions
+11 -8
View File
@@ -25,11 +25,12 @@ const emptyStats = {
};
describe('wecomReportPeriod', () => {
it('daily is the Shanghai calendar day', () => {
it('daily is the previous Shanghai calendar day (closed at send-day 00:00)', () => {
const p = wecomReportPeriod('daily', new Date('2026-09-02T20:00:00+08:00'));
expect(p.periodKey).toBe('2026-09-02');
expect(p.periodKey).toBe('2026-09-01');
expect(p.incrementLabel).toBe('当日新增');
expect(p.start.toISOString()).toBe(new Date('2026-09-02T00:00:00+08:00').toISOString());
expect(p.start.toISOString()).toBe(new Date('2026-09-01T00:00:00+08:00').toISOString());
expect(p.endExclusive.toISOString()).toBe(new Date('2026-09-02T00:00:00+08:00').toISOString());
});
it('weekly is the previous natural week', () => {
@@ -37,26 +38,28 @@ describe('wecomReportPeriod', () => {
expect(p.periodKey).toBe('2026-08-24');
expect(p.rangeLabel).toBe('2026-08-24 ~ 2026-08-30');
expect(p.incrementLabel).toBe('本期新增');
expect(p.endExclusive.toISOString()).toBe(new Date('2026-08-31T00:00:00+08:00').toISOString());
});
it('monthly is the previous natural month', () => {
const p = wecomReportPeriod('monthly', new Date('2026-09-01T09:00:00+08:00'));
expect(p.periodKey).toBe('2026-08');
expect(p.title).toBe('月报(2026年8月)');
expect(p.endExclusive.toISOString()).toBe(new Date('2026-09-01T00:00:00+08:00').toISOString());
});
});
describe('wecomReportCutoff', () => {
it('caps an in-progress daily period at now', () => {
it('daily closes at send-day midnight, not send clock time', () => {
const now = new Date('2026-09-02T20:00:00+08:00');
const p = wecomReportPeriod('daily', now);
expect(wecomReportCutoff(p, now).getTime()).toBe(now.getTime());
expect(wecomReportCutoff(p).getTime()).toBe(new Date('2026-09-02T00:00:00+08:00').getTime());
});
it('uses period end for a completed week', () => {
const now = new Date('2026-09-02T09:00:00+08:00');
const p = wecomReportPeriod('weekly', now);
expect(wecomReportCutoff(p, now).getTime()).toBe(p.endExclusive.getTime());
expect(wecomReportCutoff(p).getTime()).toBe(p.endExclusive.getTime());
});
});
@@ -86,7 +89,7 @@ describe('wecomReportShouldFire', () => {
expect(
wecomReportShouldFire(
'daily',
{ ...base, lastSentPeriod: '2026-09-02' },
{ ...base, lastSentPeriod: '2026-09-01' },
new Date('2026-09-02T21:00:00+08:00'),
),
).toBe(false);
@@ -125,7 +128,7 @@ describe('formatWecomReportMarkdown', () => {
it('renders stock plus increment lines', () => {
const p = wecomReportPeriod('daily', new Date('2026-09-02T20:00:00+08:00'));
const md = formatWecomReportMarkdown(p, emptyStats);
expect(md).toContain('**杜康好客 · 日报(2026-09-02**');
expect(md).toContain('**杜康好客 · 日报(2026-09-01**');
expect(md).toContain('用户数量:10(当日新增 2');
expect(md).toContain('订单金额:1000.00(当日新增 80.50');
expect(md).toContain('核销单数量:8(当日新增 3)');
+14 -8
View File
@@ -67,15 +67,21 @@ function lastDayOfShanghaiMonth(year: number, month: number): number {
return Number(shanghaiYmd(new Date(shanghaiMonthRange(year, month).endExclusive.getTime() - 1)).slice(8, 10));
}
/** 日报=当天;周报=上一自然周;月报=上一自然月(北京日历) */
/** 发送日北京 0 点 = 前一天 24 点,账期不含发送当天 */
export function wecomReportAsOf(now = new Date()): Date {
return startOfShanghaiDay(now);
}
/** 日报=昨日;周报=上一自然周;月报=上一自然月。期末均为某日 0 点。 */
export function wecomReportPeriod(kind: WecomReportKind, now = new Date()): WecomReportPeriod {
const asOf = wecomReportAsOf(now);
if (kind === 'daily') {
const start = startOfShanghaiDay(now);
const start = addShanghaiDays(asOf, -1);
const ymd = shanghaiYmd(start);
return {
kind,
start,
endExclusive: addShanghaiDays(start, 1),
endExclusive: asOf,
periodKey: ymd,
title: `日报(${ymd}`,
rangeLabel: ymd,
@@ -83,7 +89,7 @@ export function wecomReportPeriod(kind: WecomReportKind, now = new Date()): Weco
};
}
if (kind === 'weekly') {
const { start, endExclusive } = previousShanghaiWeek(now);
const { start, endExclusive } = previousShanghaiWeek(asOf);
const from = shanghaiYmd(start);
const to = shanghaiYmd(new Date(endExclusive.getTime() - 1));
return {
@@ -96,7 +102,7 @@ export function wecomReportPeriod(kind: WecomReportKind, now = new Date()): Weco
incrementLabel: '本期新增',
};
}
const { year, month } = previousShanghaiMonth(now);
const { year, month } = previousShanghaiMonth(asOf);
const { start, endExclusive } = shanghaiMonthRange(year, month);
return {
kind,
@@ -109,9 +115,9 @@ export function wecomReportPeriod(kind: WecomReportKind, now = new Date()): Weco
};
}
/** 进行中的周期截到 now,已结束的周期用期末 */
export function wecomReportCutoff(period: WecomReportPeriod, now = new Date()): Date {
return now.getTime() < period.endExclusive.getTime() ? now : period.endExclusive;
/** 账期期末:发送日 0 点或上一周/月结束 0 点,不含发送当天发生额 */
export function wecomReportCutoff(period: WecomReportPeriod): Date {
return period.endExclusive;
}
export function wecomReportDueAt(kind: WecomReportKind, schedule: WecomReportSchedule, now = new Date()): Date {