feat(billing): add formula A/B admin UI and subscription renew status
Expose dual metering formula editing with batch user assignment, show auto-renew and pending-recharge states in subscriptions, and document billing acceptance checks for production rollout. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+21
-5
@@ -660,11 +660,12 @@ export function createAdminApp(services) {
|
||||
res.json(await skillRuntimeConfigService.getPublicRuntimeConfig());
|
||||
});
|
||||
|
||||
adminApi.get('/billing/config', requireAdmin, async (_req, res) => {
|
||||
adminApi.get('/billing/config', requireAdmin, async (req, res) => {
|
||||
if (!billingConfigService?.getAdminConfig) {
|
||||
return res.status(503).json({ message: '计费公式配置服务未启用' });
|
||||
}
|
||||
return res.json(await billingConfigService.getAdminConfig());
|
||||
const formula = req.query.formula ? String(req.query.formula) : undefined;
|
||||
return res.json(await billingConfigService.getAdminConfig({ formula }));
|
||||
});
|
||||
|
||||
const updateBillingConfig = async (req, res) => {
|
||||
@@ -672,9 +673,10 @@ export function createAdminApp(services) {
|
||||
return res.status(503).json({ message: '计费公式配置服务未启用' });
|
||||
}
|
||||
try {
|
||||
const formula = req.body?.formula ? String(req.body.formula) : undefined;
|
||||
return res.json(await billingConfigService.updateAdminConfig(
|
||||
req.body?.config ?? req.body ?? {},
|
||||
{ updatedBy: req.currentUser.id },
|
||||
{ updatedBy: req.currentUser.id, formula },
|
||||
));
|
||||
} catch (error) {
|
||||
if (error?.code === 'BILLING_CONFIG_ENV_LOCKED') {
|
||||
@@ -687,11 +689,25 @@ export function createAdminApp(services) {
|
||||
adminApi.put('/billing/config', requireAdmin, updateBillingConfig);
|
||||
adminApi.patch('/billing/config', requireAdmin, updateBillingConfig);
|
||||
|
||||
adminApi.get('/billing/runtime', requireAdmin, async (_req, res) => {
|
||||
adminApi.post('/billing/formula-assignments', requireAdmin, async (req, res) => {
|
||||
if (!billingConfigService?.assignBillingFormula) {
|
||||
return res.status(503).json({ message: '计费公式配置服务未启用' });
|
||||
}
|
||||
const { userIds, formula } = req.body ?? {};
|
||||
const result = await billingConfigService.assignBillingFormula(userIds, formula);
|
||||
if (!result.ok) {
|
||||
return res.status(400).json(result);
|
||||
}
|
||||
return res.json(result);
|
||||
});
|
||||
|
||||
adminApi.get('/billing/runtime', requireAdmin, async (req, res) => {
|
||||
if (!billingConfigService?.getRuntimeState) {
|
||||
return res.status(503).json({ message: '计费公式配置服务未启用' });
|
||||
}
|
||||
return res.json(await billingConfigService.getRuntimeState());
|
||||
const formula = req.query.formula ? String(req.query.formula) : undefined;
|
||||
const userId = req.query.userId ? String(req.query.userId) : undefined;
|
||||
return res.json(await billingConfigService.getRuntimeState({ formula, userId }));
|
||||
});
|
||||
|
||||
adminApi.get('/system-tests/accounts', requireAdmin, async (_req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user