实现 P2 管理端:租户生命周期、套餐与运维真实 API
- 租户开通自动创建管理员账号与网页渠道,支持暂停/恢复/编辑 - 运营概览返回月收入估算、套餐分布与真实操作日志 - 套餐上下架/新建,公告与操作日志前后端打通 - 补充管理端生命周期集成测试
This commit is contained in:
@@ -623,3 +623,62 @@ func TestCustomerAndKnowledgeCRUD(t *testing.T) {
|
||||
t.Fatalf("创建知识条目失败: %s", createEntryRec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdminTenantLifecycleAndPlanToggle(t *testing.T) {
|
||||
router := setupRouter(t)
|
||||
platform := createUser(t, 0, "platform-ops", "platform_admin")
|
||||
plan := model.Plan{Name: "测试套餐", PriceMonthly: 199, Seats: 3, StorageDays: 30, KBLimit: 20, Status: "active"}
|
||||
if err := model.DB.Create(&plan).Error; err != nil {
|
||||
t.Fatalf("创建套餐失败: %v", err)
|
||||
}
|
||||
|
||||
createRec := httptest.NewRecorder()
|
||||
body := fmt.Sprintf(`{"name":"新开租户A","contact_name":"王经理","contact_phone":"13800138001","plan_id":%d,"seat_count":5,"duration_months":6}`, plan.ID)
|
||||
router.ServeHTTP(createRec, bearerRequest(t, http.MethodPost, "/api/admin/tenants", []byte(body), platform))
|
||||
if createRec.Code != http.StatusOK {
|
||||
t.Fatalf("开通租户失败: %s", createRec.Body.String())
|
||||
}
|
||||
var createResp struct {
|
||||
Data struct {
|
||||
Tenant struct {
|
||||
ID uint `json:"id"`
|
||||
} `json:"tenant"`
|
||||
AdminUsername string `json:"admin_username"`
|
||||
} `json:"data"`
|
||||
}
|
||||
if err := json.Unmarshal(createRec.Body.Bytes(), &createResp); err != nil || createResp.Data.Tenant.ID == 0 || createResp.Data.AdminUsername == "" {
|
||||
t.Fatalf("解析开通响应失败: %v body=%s", err, createRec.Body.String())
|
||||
}
|
||||
|
||||
suspendRec := httptest.NewRecorder()
|
||||
router.ServeHTTP(suspendRec, bearerRequest(t, http.MethodPost, fmt.Sprintf("/api/admin/tenants/%d/suspend", createResp.Data.Tenant.ID), []byte(`{}`), platform))
|
||||
if suspendRec.Code != http.StatusOK {
|
||||
t.Fatalf("暂停失败: %s", suspendRec.Body.String())
|
||||
}
|
||||
var tenant model.Tenant
|
||||
model.DB.First(&tenant, createResp.Data.Tenant.ID)
|
||||
if tenant.Status != "suspended" {
|
||||
t.Fatalf("租户状态应为 suspended: %+v", tenant)
|
||||
}
|
||||
|
||||
resumeRec := httptest.NewRecorder()
|
||||
router.ServeHTTP(resumeRec, bearerRequest(t, http.MethodPost, fmt.Sprintf("/api/admin/tenants/%d/resume", createResp.Data.Tenant.ID), []byte(`{}`), platform))
|
||||
if resumeRec.Code != http.StatusOK {
|
||||
t.Fatalf("恢复失败: %s", resumeRec.Body.String())
|
||||
}
|
||||
model.DB.First(&tenant, createResp.Data.Tenant.ID)
|
||||
if tenant.Status != "normal" {
|
||||
t.Fatalf("恢复后状态应为 normal: %+v", tenant)
|
||||
}
|
||||
|
||||
planRec := httptest.NewRecorder()
|
||||
router.ServeHTTP(planRec, bearerRequest(t, http.MethodPut, fmt.Sprintf("/api/admin/plans/%d", plan.ID), []byte(`{"status":"inactive"}`), platform))
|
||||
if planRec.Code != http.StatusOK {
|
||||
t.Fatalf("套餐下架失败: %s", planRec.Body.String())
|
||||
}
|
||||
var updatedPlan model.Plan
|
||||
model.DB.First(&updatedPlan, plan.ID)
|
||||
if updatedPlan.Status != "inactive" {
|
||||
t.Fatalf("套餐状态未更新: %+v", updatedPlan)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user