feat(admin): Phase 7 计费审计+4层额度策略 — 流水浏览/手动调额/额度策略CRUD+拦截
后端:adminpanel ledgers(全局流水+筛)+ adjust(手动调额,落 ADJUSTMENT)+ quota-policies CRUD; 额度拦截 _enforce_quota_policy(单任务/月度/项目)接入 reserve_credit,仅团队有 active 策略才生效(无策略零回归); adjust_credit helper。修真 bug:log_admin_action 加 savepoint + JSON 安全化(UUID/Decimal), 修复传 serializer.data 致审计报错污染外层事务 → TransactionManagementError。 前端:adminApi 计费/额度系列;计费审计页(流水表+手动调额弹窗)+ 额度策略页(CRUD 弹窗,团队下拉+三类上限+启用)。 测试:adminpanel 44 + billing + accounts = 70 单测过(调额±/超额拒/额度拦截 per_task+monthly/无策略零回归); 无头 e2e _admin-p7.mjs 6 断言过 + 0 console error(一次性团队,不动 demo 余额);tsc+build 绿。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ca1e50d32c
commit
39b4467258
@@ -1,5 +1,7 @@
|
||||
import type {
|
||||
AdminLedger,
|
||||
AdminQualityWord,
|
||||
AdminQuotaPolicy,
|
||||
AdminReviewAsset,
|
||||
AdminTask,
|
||||
AdminTaskDetail,
|
||||
@@ -618,5 +620,33 @@ export const adminApi = {
|
||||
},
|
||||
retryTask(id: string) {
|
||||
return request<{ retried: boolean; task_id: string }>(`/api/admin/tasks/${id}/retry/`, { method: "POST" });
|
||||
},
|
||||
ledgers(params?: { ledger_type?: string; team?: string; page?: number; page_size?: number }) {
|
||||
const qs = new URLSearchParams();
|
||||
if (params?.ledger_type) qs.set("ledger_type", params.ledger_type);
|
||||
if (params?.team) qs.set("team", params.team);
|
||||
if (params?.page) qs.set("page", String(params.page));
|
||||
if (params?.page_size) qs.set("page_size", String(params.page_size));
|
||||
const q = qs.toString();
|
||||
return request<Paginated<AdminLedger>>(`/api/admin/ledgers/${q ? `?${q}` : ""}`);
|
||||
},
|
||||
adjustCredit(payload: { team: string; amount: string; reason: string }) {
|
||||
return request<AdminLedger>("/api/admin/ledgers/adjust/", { method: "POST", body: JSON.stringify(payload) });
|
||||
},
|
||||
quotaPolicies(params?: { team?: string; page_size?: number }) {
|
||||
const qs = new URLSearchParams();
|
||||
if (params?.team) qs.set("team", params.team);
|
||||
if (params?.page_size) qs.set("page_size", String(params.page_size));
|
||||
const q = qs.toString();
|
||||
return request<Paginated<AdminQuotaPolicy>>(`/api/admin/quota-policies/${q ? `?${q}` : ""}`);
|
||||
},
|
||||
createQuotaPolicy(payload: { team: string; monthly_limit?: string | null; project_limit?: string | null; per_task_limit?: string | null; is_active?: boolean }) {
|
||||
return request<AdminQuotaPolicy>("/api/admin/quota-policies/", { method: "POST", body: JSON.stringify(payload) });
|
||||
},
|
||||
updateQuotaPolicy(id: string, payload: { monthly_limit?: string | null; project_limit?: string | null; per_task_limit?: string | null; is_active?: boolean }) {
|
||||
return request<AdminQuotaPolicy>(`/api/admin/quota-policies/${id}/`, { method: "PATCH", body: JSON.stringify(payload) });
|
||||
},
|
||||
deleteQuotaPolicy(id: string) {
|
||||
return request<void>(`/api/admin/quota-policies/${id}/`, { method: "DELETE" });
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user