|
|
@@ -210,6 +210,68 @@ func recommendCompare(c Case, lg, tg *SideResult) ([]Diff, []Assertion) {
|
|
|
lgOK, c.ExpectLegacySuccess, errOf(lg.Calls), tgOK, c.ExpectTargetSuccess, errOf(tg.Calls)),
|
|
|
})
|
|
|
|
|
|
+ // ---- 课酬域:两个用户**各自**被核销一次 ----
|
|
|
+ if c.Arrears != nil {
|
|
|
+ d2, a2 := recommendArrearsAssertions(c, lg, tg)
|
|
|
+ diffs = append(diffs, d2...)
|
|
|
+ asserts = append(asserts, a2...)
|
|
|
+ }
|
|
|
+
|
|
|
+ return diffs, asserts
|
|
|
+}
|
|
|
+
|
|
|
+// recommendArrearsAssertions 是老带新里"两次核销"的断言(W4-C)。
|
|
|
+//
|
|
|
+// 期望值由 `arrearsExpectedDeltas` 按**每个用户各自的 `remaining`** 算 ——
|
|
|
+// 两个 CALL 的上限都是 `activityMoney`(同一个 m),但候选行互不相干。
|
|
|
+// 用一个全局 remaining 会把两人的额度串成一份:第一人吃满后第二人一分不核,
|
|
|
+// 而那**看起来完全像"第二个 CALL 没执行"**(又一个"红得像实现缺陷"的形态)。
|
|
|
+//
|
|
|
+// ⚠ **不钉顺序**:核销改 `t_courses_student`、入账改 `t_user_expense*`,两域互不依赖,
|
|
|
+// 换序终态相同 ⇒ 顺序只在 SQL trace 里可见。本块钉的是"两件事都发生、金额各为 m"。
|
|
|
+func recommendArrearsAssertions(c Case, lg, tg *SideResult) ([]Diff, []Assertion) {
|
|
|
+ var diffs []Diff
|
|
|
+ var asserts []Assertion
|
|
|
+ add := func(item, l, t string, equal bool, note string) {
|
|
|
+ diffs = append(diffs, Diff{Item: item, Legacy: l, Target: t, Equal: equal, Note: note})
|
|
|
+ }
|
|
|
+ lgD, lgErr := arrearsSnapshotDeltas(lg.Before, lg.After, "legacy")
|
|
|
+ tgD, tgErr := arrearsSnapshotDeltas(tg.Before, tg.After, "target")
|
|
|
+ if lgErr != nil || tgErr != nil {
|
|
|
+ asserts = append(asserts, Assertion{Kind: AssertionInfrastructure,
|
|
|
+ Name: "课酬域快照可归并(before/after 的 biz_no 集合一致)",
|
|
|
+ Pass: false, Detail: fmt.Sprintf("legacy=%v | target=%v", lgErr, tgErr)})
|
|
|
+ return diffs, asserts
|
|
|
+ }
|
|
|
+ want := arrearsExpectedDeltas(c)
|
|
|
+ var lgNet, tgNet int64
|
|
|
+ for _, e := range c.Arrears.flatRows() {
|
|
|
+ biz := e.Row.BizNo
|
|
|
+ w := want[biz]
|
|
|
+ l, t := lgD[biz], tgD[biz]
|
|
|
+ lgNet += l.NetDelta
|
|
|
+ tgNet += t.NetDelta
|
|
|
+ add("W4-C·核销 "+biz+" Δnet_receipts",
|
|
|
+ fmt.Sprintf("%+d", l.NetDelta), fmt.Sprintf("%+d", t.NetDelta),
|
|
|
+ l.NetDelta == t.NetDelta, "分")
|
|
|
+ asserts = append(asserts, Assertion{Kind: AssertionBusiness,
|
|
|
+ Name: fmt.Sprintf("W4-C 核销 %s:两侧都按 `min(剩余应收, 本人上限)` 核(user=%d)", biz, e.User),
|
|
|
+ Pass: l.NetDelta == w.NetDelta && t.NetDelta == w.NetDelta &&
|
|
|
+ l.RemDelta == w.RemDelta && t.RemDelta == w.RemDelta,
|
|
|
+ Detail: fmt.Sprintf("实测 legacy net %+d / rem %+d | target net %+d / rem %+d | 期望 net %+d / rem %+d"+
|
|
|
+ "(剩余应收 %d,本人上限 m=%d)",
|
|
|
+ l.NetDelta, l.RemDelta, t.NetDelta, t.RemDelta, w.NetDelta, w.RemDelta,
|
|
|
+ e.Row.RemainderReceivableCents, c.AmountCents),
|
|
|
+ })
|
|
|
+ }
|
|
|
+ // 正向断言:**两个用户各核了一笔**。少了它,"两侧都 0"会全绿 ——
|
|
|
+ // 而那正是"第二个 CALL 没执行"或"两个用户共用一个额度"的形态。
|
|
|
+ asserts = append(asserts, Assertion{Kind: AssertionBusiness,
|
|
|
+ Name: "W4-C 课酬核销总额两侧都 > 0(两个用户**各自**被核销过;全 0 ⇒ FAIL)",
|
|
|
+ Pass: lgNet > 0 && tgNet > 0,
|
|
|
+ Detail: fmt.Sprintf("legacy ΣΔnet=%+d | target ΣΔnet=%+d。"+
|
|
|
+ "若为 0:先查两个用户是否都有 `ByUser` 行、`confirm_discount_userid>0` 是否都为真", lgNet, tgNet),
|
|
|
+ })
|
|
|
return diffs, asserts
|
|
|
}
|
|
|
|