|
|
@@ -600,6 +600,57 @@ func DefaultCases(_ string) []Case {
|
|
|
},
|
|
|
)
|
|
|
|
|
|
+ // ---- 批 3a:W3 中两条(赠送额度的退回)----
|
|
|
+ //
|
|
|
+ // ⚠ 用**真实欠费行**的旧 UUID `f2166ec3c06204401c19e6a9647b5ead`
|
|
|
+ // (studentid 68556 / remainder 8280.000 / net_receipts 0.000 / **该单号负 log 数 0**)。
|
|
|
+ // ⚠ `user_discount_refund` 的游标**没有 userid 过滤**
|
|
|
+ // (`WHERE courses_studentid=? AND discount_amount_used<0 ORDER BY id DESC`)——
|
|
|
+ // 所以 `countOtherDiscountLogLegacy` 那条前置断言在这一支才第一次真正起作用。
|
|
|
+ // 它若红了,先读文案:那是「数据碰撞,不是实现错」,别去改实现。
|
|
|
+ drStuCourse := "f2166ec3c06204401c19e6a9647b5ead"
|
|
|
+ out = append(out,
|
|
|
+ Case{
|
|
|
+ Name: "DR-1 退回赠送额度·正常部分退回(log 一条 **+**m)",
|
|
|
+ Op: OpUserDiscountRefund, LegacyUserID: actUser, InstitutionID: 63317, CampusID: 5,
|
|
|
+ SelfSupport: true, AmountCents: 1000,
|
|
|
+ StuCourseID: drStuCourse, StuCourseNumericID: 1, Remark: "W3 退回赠送",
|
|
|
+ Activity: &ActivitySeed{
|
|
|
+ Items: []ActivityItem{
|
|
|
+ {Type: 2, InstitutionID: 63317, CampusID: 5, SignedStatus: -1, MoneyCents: 0},
|
|
|
+ },
|
|
|
+ Discounts: []DiscountSeed{{ActivityIndex: 0, AmountCents: 10000, UsedCents: 3000}},
|
|
|
+ DiscountLogs: []DiscountLogSeed{
|
|
|
+ {DiscountIndex: 0, MoneyCents: -3000, Memo: "W3 使用赠送"},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ExpectTargetSuccess: true, ExpectLegacySuccess: true,
|
|
|
+ Note: "已用 30.00(池行 used=30.00,另有一条 −30.00 的消费流水),退 10.00。" +
|
|
|
+ "dump:`discount_amount_used -= tempAmount` + `_log` 写 **+tempAmount**;默认备注「退回赠送金额」。" +
|
|
|
+ "⚠ 不种那条负值流水,游标空转 ⇒ 两侧都 no-op ⇒ 空过",
|
|
|
+ },
|
|
|
+ Case{
|
|
|
+ Name: "DR-2 退回赠送额度·退超(只退到 0 为止,剩余不退)",
|
|
|
+ Op: OpUserDiscountRefund, LegacyUserID: actUser, InstitutionID: 63317, CampusID: 5,
|
|
|
+ SelfSupport: true, AmountCents: 5000,
|
|
|
+ StuCourseID: drStuCourse, StuCourseNumericID: 1, Remark: "W3 退超",
|
|
|
+ Activity: &ActivitySeed{
|
|
|
+ Items: []ActivityItem{
|
|
|
+ {Type: 2, InstitutionID: 63317, CampusID: 5, SignedStatus: -1, MoneyCents: 0},
|
|
|
+ },
|
|
|
+ Discounts: []DiscountSeed{{ActivityIndex: 0, AmountCents: 10000, UsedCents: 3000}},
|
|
|
+ DiscountLogs: []DiscountLogSeed{
|
|
|
+ {DiscountIndex: 0, MoneyCents: -3000, Memo: "W3 使用赠送"},
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ExpectTargetSuccess: true, ExpectLegacySuccess: true,
|
|
|
+ Note: "已用 30.00,**申请退 50.00**(> 可退)。dump 的算法是「取较小值」:" +
|
|
|
+ "`IF discountAmountUsed>=inputAmount THEN tempAmount=inputAmount ELSE tempAmount=discountAmountUsed` " +
|
|
|
+ "⇒ tempAmount=30.00 ⇒ 池行 used 归 **0.00**、log 一条 **+30.00**,**剩余 20.00 不退、也不报错**。" +
|
|
|
+ "⚠ 注意它**不是**「退成负数」——期望要写成「只退到 0 为止」,写成负数会与实现无关地红",
|
|
|
+ },
|
|
|
+ )
|
|
|
+
|
|
|
// ---- 消费(第二批已做,留作回归)----
|
|
|
base := Case{
|
|
|
Op: OpExpenditure, LegacyUserID: 17735, InstitutionID: 63317, CampusID: 5,
|
|
|
@@ -771,6 +822,25 @@ func RunOne(ctx context.Context, cfg Config, c Case) (*CaseResult, error) {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+ // ①-b 赠送额度的退回:游标**按订单号**、**不带 userid**
|
|
|
+ //(`WHERE courses_studentid=? AND discount_amount_used<0 ORDER BY id DESC`)。
|
|
|
+ // 旧库真有 162 行额度流水,只要订单号撞上真实行,两侧看到的行集天然不同 ——
|
|
|
+ // 那种红是【数据碰撞】,不是 SP 行为错。所以在 case 开始就把"污染源为 0"钉住,
|
|
|
+ // 并且**文案里必须写清"这是数据碰撞,不是实现错"**,否则看红的人第一反应是去改实现。
|
|
|
+ if c.Op == OpUserDiscountRefund || c.Op == OpUserDiscountRefundByActivity {
|
|
|
+ n, err := countOtherDiscountLogLegacy(ctx, legacyDB, c.StuCourseID, nil)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ res.Assertions = append(res.Assertions, Assertion{Kind: AssertionInfrastructure,
|
|
|
+ Name: "case 有效性前提:该订单号在旧库里**没有别的负额度流水**(游标不带 userid)",
|
|
|
+ Pass: n == 0,
|
|
|
+ Detail: fmt.Sprintf("订单号 %q 在旧库另有 %d 条负额度流水 ⇒ 若 >0,两侧游标看到的行集天然不同 —— "+
|
|
|
+ "这是【数据碰撞】不是实现错;处置:换一个订单号,或把那些流水一并纳入本 case 的 plan",
|
|
|
+ c.StuCourseID, n),
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
// ② 旧库里如果还有"本 case 之外、同样可被失效"的报名行,legacy 会多失效几条,
|
|
|
// 而 target 侧没有那些活动(活动域还没迁移)—— 两侧失效集合天然不同。
|
|
|
// 那种差异是"数据没搬全",不是"SP 行为不对"。与其让它以一个看不懂的差异出现,
|