fix(insights): 数据面板「每日回答数」按 answered_at 分组,而非 created_at
BoxTrend 的回答那条 SQL 复用了 d.day(基于 created_at 的日期表达式)做 GROUP BY, 但 WHERE 过滤用的是 answered_at。于是「40 天前创建、昨天才回答」的提问被排除在 窗口外(created_at < from),昨天的回答数里不出现;「今天创建、明天回答」的又 被记到今天。趋势图里的「每日回答数」根本不是「某天被回答了多少」。 单独构造 answerDay(基于 COALESCE(answered_at, updated_at)),WHERE / GROUP BY / SELECT 三者口径一致。PG 用 to_char(... AT TIME ZONE INTERVAL ...),MySQL 用 CONVERT_TZ,与 analyticsDialectFor 对 created_at 的处理对称。 新增 box_analytics_test.go:构造「40 天前创建、昨天回答」的提问,断言计入昨天, 并做变异验证(改回 d.day → 测试失败)。
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
// Copyright 2026 tamakyi. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// TestBoxTrendAnswerByAnsweredDate 验证「每日回答数」按 answered_at 分组,
|
||||
// 而不是按 created_at。
|
||||
//
|
||||
// 背景:BoxTrend 一度两条 SQL 都复用 created_at 的日期表达式,导致「40 天前创建、
|
||||
// 昨天才回答」的提问被排除在窗口外(created_at < from),昨天/今天的回答数里
|
||||
// 根本不出现;「今天创建、明天回答」的又会被记到今天。本测试构造一条
|
||||
// 「创建日远早于窗口、回答日落在窗口内」的提问,断言它出现在回答日那天。
|
||||
func TestBoxTrendAnswerByAnsweredDate(t *testing.T) {
|
||||
db, cleanup := newTestDB(t)
|
||||
ctx := context.Background()
|
||||
store := NewBoxAnalyticsStore(db)
|
||||
|
||||
t.Cleanup(func() {
|
||||
_ = cleanup("questions")
|
||||
})
|
||||
|
||||
now := time.Now()
|
||||
// 窗口 = 最近 7 天
|
||||
from := now.AddDate(0, 0, -6)
|
||||
to := now
|
||||
|
||||
// 一条 40 天前创建、昨天才回答的提问
|
||||
answeredAt := now.AddDate(0, 0, -1)
|
||||
createdAt := now.AddDate(0, 0, -40)
|
||||
q := &Question{
|
||||
UserID: 9,
|
||||
Content: "很久以前问的,昨天才回答",
|
||||
Answer: "这是回答",
|
||||
AnsweredAt: &answeredAt,
|
||||
}
|
||||
// 直接写 created_at / answered_at,绕过 Create 的自动时间戳
|
||||
require.NoError(t, db.Model(&Question{}).Create(q).Error)
|
||||
require.NoError(t, db.Model(&Question{}).Where("id = ?", q.ID).
|
||||
Updates(map[string]interface{}{
|
||||
"created_at": createdAt,
|
||||
"answered_at": answeredAt,
|
||||
"updated_at": answeredAt,
|
||||
}).Error)
|
||||
|
||||
trend, err := store.BoxTrend(ctx, 9, from, to)
|
||||
require.NoError(t, err)
|
||||
|
||||
// 找到回答日那天(昨天)的计数,答案数应 >= 1
|
||||
var found bool
|
||||
for _, d := range trend {
|
||||
if d.Day.Year() == answeredAt.Year() &&
|
||||
d.Day.Month() == answeredAt.Month() &&
|
||||
d.Day.Day() == answeredAt.Day() {
|
||||
require.GreaterOrEqual(t, d.Answers, int64(1),
|
||||
"回答应计入 answered_at 那一天,而不是按 created_at 被排除")
|
||||
found = true
|
||||
}
|
||||
// 创建日(40 天前)不应出现在窗口内
|
||||
if d.Day.Year() == createdAt.Year() &&
|
||||
d.Day.Month() == createdAt.Month() &&
|
||||
d.Day.Day() == createdAt.Day() {
|
||||
t.Errorf("创建日在窗口外,不应出现在趋势里")
|
||||
}
|
||||
}
|
||||
require.True(t, found, "回答日应出现在趋势结果里")
|
||||
}
|
||||
Reference in New Issue
Block a user