tier plans improving

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-08-01 23:02:31 +08:00
parent cae958b5d5
commit c5052fda4c
15 changed files with 371 additions and 41 deletions
+46 -3
View File
@@ -28,6 +28,9 @@ const R = require('../../utils/response.util');
const { paginate } = require('../../utils/paginate.util');
const { getFieldValues } = require('../../utils/fieldValues.util');
const logActivity = require('../../utils/logActivity.util');
const UserNotification = require('../../models/notifications/user_notification.mdl');
const { NOTIFICATION_REGISTRY } = require('../../data/notifications.data');
const { resolveTierPlanUserIds } = require('../../utils/audienceResolver.util');
const {
excludeAttributes: plansExclude,
@@ -75,6 +78,7 @@ exports.getPlans = async (req, res) => {
jsonbSchemas: plansSchemas,
computedAttributes: plansComputed,
context: archived ? 'archived' : 'list',
auditOptions: { mdl_Users, parentAlias: 'TierPlan' },
findOptions: archived ? {
paranoid: false,
where: { deletedAt: { [Op.ne]: null } },
@@ -108,7 +112,7 @@ function computeDurationDays(value, unit) {
exports.createPlan = async (req, res) => {
try {
const { tier_category_id, label, description, features, duration_value, duration_unit = 'day', price, currency } = req.body;
const { tier_category_id, label, description, features, duration_value, duration_unit = 'day', price, currency, createdBy } = req.body;
if (!tier_category_id || !label || !duration_value || !price)
return R.error(res, 'tier_category_id, label, duration_value, and price are required.', 400);
@@ -125,6 +129,7 @@ exports.createPlan = async (req, res) => {
tier_category_id: category.tier_category_id,
tier: category.slug,
label, description, features, duration_days, duration_unit, price, currency,
createdBy: createdBy ?? req.user?.user_id ?? null,
});
const plain = plan.get({ plain: true });
logActivity(req.user?.user_id, 'create_tier_plan', { entityType: 'tier_plan', details: { label: plain.label, tier: plain.tier } });
@@ -145,6 +150,7 @@ exports.updatePlan = async (req, res) => {
for (const k of allowed) {
if (req.body[k] !== undefined) updates[k] = req.body[k];
}
updates.updatedBy = req.body.updatedBy ?? req.user?.user_id ?? null;
// Recompute duration_days when value or unit changes
const { duration_value, duration_unit } = req.body;
@@ -197,8 +203,23 @@ exports.archivePlan = async (req, res) => {
if (!plan) return R.error(res, 'Plan not found.', 404);
if (plan.deletedAt) return R.error(res, 'Plan is already archived.', 400);
await plan.update({ is_active: false });
await plan.update({ is_active: false, deletedBy: req.user?.user_id ?? null });
await plan.destroy();
try {
const userIds = await resolveTierPlanUserIds(plan.plan_id);
if (userIds.length) {
const now = new Date();
const notify = NOTIFICATION_REGISTRY.tier_plan_archived.build({ label: plan.label, planId: plan.plan_id });
await UserNotification.bulkCreate(
userIds.map((user_id) => ({ user_id, ...notify, seen: false, createdAt: now, updatedAt: now })),
{ validate: false }
);
}
} catch (notifyErr) {
console.error('[ADMIN][ARCHIVE PLAN][NOTIFY]', notifyErr);
}
logActivity(req.user?.user_id, 'archive_tier_plan', { entityType: 'tier_plan', details: { label: plan.label } });
return R.success(res, 'Plan archived successfully.');
} catch (err) {
@@ -222,9 +243,31 @@ exports.bulkArchivePlans = async (req, res) => {
const activeIds = activePlans.map((p) => p.plan_id);
await mdl_TierPlans.update({ is_active: false }, { where: { plan_id: activeIds } });
await mdl_TierPlans.update({ is_active: false, deletedBy: req.user?.user_id ?? null }, { where: { plan_id: activeIds } });
await mdl_TierPlans.destroy({ where: { plan_id: activeIds } });
try {
const holders = await mdl_UserTiers.findAll({
attributes: ['user_id', 'plan_id'],
where: { plan_id: activeIds, status: 'active' },
raw: true,
});
if (holders.length) {
const now = new Date();
const labelByPlanId = new Map(activePlans.map((p) => [String(p.plan_id), p.label]));
const notifications = holders.map(({ user_id, plan_id }) => ({
user_id,
...NOTIFICATION_REGISTRY.tier_plan_archived.build({ label: labelByPlanId.get(String(plan_id)), planId: plan_id }),
seen: false,
createdAt: now,
updatedAt: now,
}));
await UserNotification.bulkCreate(notifications, { validate: false });
}
} catch (notifyErr) {
console.error('[ADMIN][BULK ARCHIVE PLANS][NOTIFY]', notifyErr);
}
logActivity(req.user?.user_id, 'bulk_archive_tier_plans', { entityType: 'tier_plan', details: { ids: activeIds, count: activeIds.length } });
return R.success(res, `${activeIds.length} plan(s) archived successfully.`, {
archived_ids: activeIds,