init
This commit is contained in:
130
api/service/biz_subscription_logic.js
Normal file
130
api/service/biz_subscription_logic.js
Normal file
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* 订阅开通 / 升级 / 续费 / 取消 / 到期扫描 / 支付确认
|
||||
*/
|
||||
const baseModel = require("../../middleware/baseModel");
|
||||
const { op } = baseModel;
|
||||
|
||||
async function assertUserActive(userId) {
|
||||
const u = await baseModel.biz_user.findByPk(userId);
|
||||
if (!u) throw new Error("用户不存在");
|
||||
if (u.status !== "active") throw new Error("用户已禁用");
|
||||
return u;
|
||||
}
|
||||
|
||||
async function assertPlanActive(planId) {
|
||||
const p = await baseModel.biz_plan.findByPk(planId);
|
||||
if (!p) throw new Error("套餐不存在");
|
||||
if (p.status !== "active") throw new Error("套餐未上线");
|
||||
return p;
|
||||
}
|
||||
|
||||
async function openSubscription(body) {
|
||||
const {
|
||||
user_id,
|
||||
plan_id,
|
||||
start_time,
|
||||
end_time,
|
||||
status = "pending",
|
||||
renew_mode = "manual",
|
||||
payment_channel,
|
||||
payment_ref,
|
||||
} = body;
|
||||
await assertUserActive(user_id);
|
||||
await assertPlanActive(plan_id);
|
||||
const row = await baseModel.biz_subscription.create({
|
||||
user_id,
|
||||
plan_id,
|
||||
status,
|
||||
start_time,
|
||||
end_time,
|
||||
renew_mode,
|
||||
payment_channel: payment_channel || null,
|
||||
payment_ref: payment_ref || null,
|
||||
});
|
||||
return row;
|
||||
}
|
||||
|
||||
async function upgradeSubscription(body) {
|
||||
const { subscription_id, new_plan_id, start_time, end_time } = body;
|
||||
const sub = await baseModel.biz_subscription.findByPk(subscription_id);
|
||||
if (!sub) throw new Error("订阅不存在");
|
||||
await assertPlanActive(new_plan_id);
|
||||
await sub.update({
|
||||
plan_id: new_plan_id,
|
||||
start_time: start_time || sub.start_time,
|
||||
end_time: end_time || sub.end_time,
|
||||
});
|
||||
return sub;
|
||||
}
|
||||
|
||||
async function renewSubscription(body) {
|
||||
const { subscription_id, end_time } = body;
|
||||
const sub = await baseModel.biz_subscription.findByPk(subscription_id);
|
||||
if (!sub) throw new Error("订阅不存在");
|
||||
await sub.update({
|
||||
end_time,
|
||||
status: "active",
|
||||
});
|
||||
return sub;
|
||||
}
|
||||
|
||||
async function cancelSubscription(body) {
|
||||
const { subscription_id } = body;
|
||||
const sub = await baseModel.biz_subscription.findByPk(subscription_id);
|
||||
if (!sub) throw new Error("订阅不存在");
|
||||
await sub.update({ status: "cancelled" });
|
||||
return sub;
|
||||
}
|
||||
|
||||
/** 每天扫描:将已过期且仍为 active 的订阅置为 expired */
|
||||
async function expireDueSubscriptions() {
|
||||
const now = new Date();
|
||||
const [n] = await baseModel.biz_subscription.update(
|
||||
{ status: "expired" },
|
||||
{
|
||||
where: {
|
||||
status: "active",
|
||||
end_time: { [op.lt]: now },
|
||||
},
|
||||
}
|
||||
);
|
||||
return n;
|
||||
}
|
||||
|
||||
/** 线下确认:pending -> active,写入 payment_ref */
|
||||
async function confirmOfflinePayment(body) {
|
||||
const { subscription_id, payment_ref } = body;
|
||||
if (!subscription_id) throw new Error("缺少 subscription_id");
|
||||
const sub = await baseModel.biz_subscription.findByPk(subscription_id);
|
||||
if (!sub) throw new Error("订阅不存在");
|
||||
await sub.update({
|
||||
status: "active",
|
||||
payment_channel: "offline",
|
||||
payment_ref: payment_ref || sub.payment_ref,
|
||||
});
|
||||
return sub;
|
||||
}
|
||||
|
||||
/** 链接支付确认(MVP:与线下类似,仅标记渠道) */
|
||||
async function confirmLinkPayment(body) {
|
||||
const { subscription_id, payment_ref } = body;
|
||||
if (!subscription_id) throw new Error("缺少 subscription_id");
|
||||
const sub = await baseModel.biz_subscription.findByPk(subscription_id);
|
||||
if (!sub) throw new Error("订阅不存在");
|
||||
await sub.update({
|
||||
status: "active",
|
||||
payment_channel: "pay_link",
|
||||
payment_ref: payment_ref || sub.payment_ref,
|
||||
});
|
||||
return sub;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
openSubscription,
|
||||
upgradeSubscription,
|
||||
renewSubscription,
|
||||
cancelSubscription,
|
||||
expireDueSubscriptions,
|
||||
confirmOfflinePayment,
|
||||
confirmLinkPayment,
|
||||
};
|
||||
Reference in New Issue
Block a user