This commit is contained in:
张成
2026-03-24 16:07:02 +08:00
commit aa8eaa6ccd
121 changed files with 34042 additions and 0 deletions

View File

@@ -0,0 +1,110 @@
const baseModel = require("../../middleware/baseModel");
const { op } = baseModel;
function currentStatMonth(d = new Date()) {
const y = d.getFullYear();
const m = String(d.getMonth() + 1).padStart(2, "0");
return `${y}-${m}`;
}
function num(v) {
if (v === null || v === undefined || v === "") return 0;
const n = Number(v);
return Number.isNaN(n) ? 0 : n;
}
/** 0 表示无限制(不校验) */
function quotaExceeded(used, limit) {
const li = num(limit);
if (li <= 0) return false;
return num(used) >= li;
}
/**
* 取或创建当月用量行
*/
async function getOrCreateUsage(userId, planId, statMonth) {
const [row] = await baseModel.biz_usage_monthly.findOrCreate({
where: { user_id: userId, stat_month: statMonth },
defaults: {
user_id: userId,
plan_id: planId,
stat_month: statMonth,
msg_count: 0,
mass_count: 0,
friend_count: 0,
sns_count: 0,
active_user_count: 0,
},
});
if (num(row.plan_id) !== num(planId)) {
await row.update({ plan_id: planId });
}
return row;
}
async function applyDelta(userId, planId, statMonth, delta) {
const row = await getOrCreateUsage(userId, planId, statMonth);
const next = {
msg_count: num(row.msg_count) + num(delta.msg),
mass_count: num(row.mass_count) + num(delta.mass),
friend_count: num(row.friend_count) + num(delta.friend),
sns_count: num(row.sns_count) + num(delta.sns),
active_user_count: num(row.active_user_count) + num(delta.active_user),
};
await row.update(next);
return row.reload();
}
/**
* 校验「增量」后是否超限(与套餐额度对比)
* feature: msg | mass | friend | sns | active_user
*/
function checkQuotaAfterDelta(plan, usageRow, delta) {
const checks = [
["msg", "msg_count", "msg_quota"],
["mass", "mass_count", "mass_quota"],
["friend", "friend_count", "friend_quota"],
["sns", "sns_count", "sns_quota"],
["active_user", "active_user_count", "active_user_limit"],
];
for (const [key, uCol, pCol] of checks) {
const add = num(delta[key]);
if (add <= 0) continue;
const used = num(usageRow[uCol]) + add;
if (quotaExceeded(used, plan[pCol])) {
return { ok: false, error_code: "QUOTA_EXCEEDED", message: `额度不足: ${key}` };
}
}
return { ok: true };
}
/**
* 为当前月所有有效订阅补用量行(月结/初始化)
*/
async function ensureUsageRowsForCurrentMonth() {
const statMonth = currentStatMonth();
const now = new Date();
const subs = await baseModel.biz_subscription.findAll({
where: {
status: "active",
start_time: { [op.lte]: now },
end_time: { [op.gte]: now },
},
});
let n = 0;
for (const s of subs) {
await getOrCreateUsage(s.user_id, s.plan_id, statMonth);
n += 1;
}
return n;
}
module.exports = {
currentStatMonth,
getOrCreateUsage,
applyDelta,
checkQuotaAfterDelta,
ensureUsageRowsForCurrentMonth,
num,
};