package store import ( "context" "testing" "time" ) // 暂停租户是个真管控,不能是空开关:TenantSuspended 必须如实反映 status。 func TestTenantSuspended(t *testing.T) { p := newTestStore(t) ctx := context.Background() seedTenant(t, p, "t1") // seedTenant 建的是 active if p.TenantSuspended(ctx, "t1") { t.Fatal("active 租户不该报暂停") } if err := p.SetTenantStatus(ctx, "t1", "suspended"); err != nil { t.Fatalf("置暂停失败: %v", err) } if !p.TenantSuspended(ctx, "t1") { t.Fatal("suspended 租户应报暂停") } // 查不到的租户按未暂停处理(宁放行不误封)。 if p.TenantSuspended(ctx, "nope") { t.Fatal("不存在的租户不该报暂停") } } // 金额不符挂起:CAS 只挂一次,且不动已 paid 单。 func TestMarkOrderDisputed_CAS(t *testing.T) { p := newTestStore(t) ctx := context.Background() seedTenant(t, p, "t1") o := &PaymentOrder{TenantID: "t1", UserID: "u1", AmountFen: 990, Channel: ChannelWechat, Status: OrderPending} if err := p.CreateOrder(ctx, o); err != nil { t.Fatalf("建单失败: %v", err) } changed, err := p.MarkOrderDisputed(ctx, o.ID) if err != nil || !changed { t.Fatalf("首次挂起应 changed=true: %v %v", changed, err) } again, _ := p.MarkOrderDisputed(ctx, o.ID) if again { t.Fatal("重复挂起应 changed=false(审计只写一次)") } got, _ := p.GetOrder(ctx, o.ID) if got.Status != OrderDisputed { t.Fatalf("状态应 disputed,得 %q", got.Status) } // 已 paid 的单不能被挂起(CAS 只认 pending)。 paid := &PaymentOrder{TenantID: "t1", UserID: "u1", AmountFen: 990, Channel: ChannelWechat, Status: OrderPaid} p.CreateOrder(ctx, paid) if c, _ := p.MarkOrderDisputed(ctx, paid.ID); c { t.Fatal("已 paid 单不该能挂起") } } // 有效邀请码列表要滤掉过期/满员,否则误导邀请人。 func TestListInvites_FiltersDeadCodes(t *testing.T) { p := newTestStore(t) ctx := context.Background() seedTenant(t, p, "t1") good, _ := p.CreateInvite(ctx, "t1", "inv", RoleMember, time.Now().Add(time.Hour), 0) expired, _ := p.CreateInvite(ctx, "t1", "inv", RoleMember, time.Now().Add(-time.Hour), 0) full, _ := p.CreateInvite(ctx, "t1", "inv", RoleMember, time.Now().Add(time.Hour), 1) // 把 full 灌满 p.db.Model(&TenantInvite{}).Where("id = ?", full.ID).UpdateColumn("used_count", 1) active := p.ListInvites(ctx, "t1", true) if len(active) != 1 || active[0].ID != good.ID { ids := make([]string, len(active)) for i, a := range active { ids[i] = a.ID } t.Fatalf("有效列表应只剩 good(%s),得 %v", good.ID, ids) } _ = expired // onlyActive=false 仍应看到全部三条(管理/审计用途)。 if all := p.ListInvites(ctx, "t1", false); len(all) != 3 { t.Fatalf("全量列表应 3 条,得 %d", len(all)) } }