mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
@@ -0,0 +1,136 @@
|
||||
'use strict';
|
||||
|
||||
const mdl_TierCategories = require('../../models/tiers/tier_categories.mdl');
|
||||
const mdl_TierPlans = require('../../models/tiers/tier_plans.mdl');
|
||||
const Asset = require('../../models/assets/assets.mdl');
|
||||
const R = require('../../utils/response.util');
|
||||
const logActivity = require('../../utils/logActivity.util');
|
||||
|
||||
require('../../models/tiers/tier.associations');
|
||||
|
||||
const ASSET_ATTRS = ['asset_id', 'file_url', 'display_name', 'mime_type'];
|
||||
|
||||
const withBadge = [{ model: Asset, as: 'badgeAsset', attributes: ASSET_ATTRS, required: false }];
|
||||
|
||||
// ─── GET /admin/tiers/categories ─────────────────────────────────────────────
|
||||
|
||||
exports.getCategories = async (req, res) => {
|
||||
try {
|
||||
const categories = await mdl_TierCategories.findAll({
|
||||
include: withBadge,
|
||||
order: [['rank', 'ASC']],
|
||||
});
|
||||
return R.success(res, 'Tier categories retrieved.', categories);
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][GET TIER CATEGORIES]', err);
|
||||
return R.error(res, 'Could not retrieve tier categories.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
// ─── GET /admin/tiers/categories/:id ─────────────────────────────────────────
|
||||
|
||||
exports.getCategory = async (req, res) => {
|
||||
try {
|
||||
const cat = await mdl_TierCategories.findByPk(req.params.id, { include: withBadge });
|
||||
if (!cat) return R.error(res, 'Tier category not found.', 404);
|
||||
return R.success(res, 'Tier category retrieved.', cat);
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][GET TIER CATEGORY]', err);
|
||||
return R.error(res, 'Could not retrieve tier category.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
// ─── POST /admin/tiers/categories ────────────────────────────────────────────
|
||||
|
||||
exports.createCategory = async (req, res) => {
|
||||
try {
|
||||
const { slug, name, description, rank, color, badge_asset_id, badge_icon, badge_label } = req.body;
|
||||
if (!slug || !name) return R.error(res, 'slug and name are required.', 400);
|
||||
|
||||
const parsedRank = Number(rank ?? 1);
|
||||
if (parsedRank <= 0) return R.error(res, 'Non-default tier categories must have rank greater than 0.', 400);
|
||||
|
||||
const exists = await mdl_TierCategories.findOne({ where: { slug } });
|
||||
if (exists) return R.error(res, `A tier category with slug "${slug}" already exists.`, 409);
|
||||
|
||||
const cat = await mdl_TierCategories.create({
|
||||
slug, name,
|
||||
description: description ?? null,
|
||||
rank: parsedRank,
|
||||
color: color || 'purple',
|
||||
badge_asset_id: badge_asset_id || null,
|
||||
badge_icon: badge_icon || null,
|
||||
badge_label: badge_label ?? null,
|
||||
is_default: false,
|
||||
is_active: true,
|
||||
});
|
||||
|
||||
logActivity(req.user?.user_id, 'create_tier_category', { entityType: 'tier_category', details: { slug, name } });
|
||||
|
||||
const result = await mdl_TierCategories.findByPk(cat.tier_category_id, { include: withBadge });
|
||||
return R.success(res, 'Tier category created.', result, 201);
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][CREATE TIER CATEGORY]', err);
|
||||
return R.error(res, 'Could not create tier category.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
// ─── PUT /admin/tiers/categories/:id ─────────────────────────────────────────
|
||||
|
||||
exports.updateCategory = async (req, res) => {
|
||||
try {
|
||||
const cat = await mdl_TierCategories.findByPk(req.params.id);
|
||||
if (!cat) return R.error(res, 'Tier category not found.', 404);
|
||||
|
||||
const { name, description, rank, color, badge_asset_id, badge_icon, badge_label, is_active } = req.body;
|
||||
|
||||
if (!cat.is_default && rank !== undefined) {
|
||||
const parsedRank = Number(rank);
|
||||
if (parsedRank <= 0) return R.error(res, 'Non-default tier categories must have rank greater than 0.', 400);
|
||||
}
|
||||
|
||||
await cat.update({
|
||||
name: name ?? cat.name,
|
||||
description: description !== undefined ? (description || null) : cat.description,
|
||||
rank: rank !== undefined ? Number(rank) : cat.rank,
|
||||
color: color !== undefined ? (color || cat.color) : cat.color,
|
||||
badge_asset_id: badge_asset_id !== undefined ? (badge_asset_id || null) : cat.badge_asset_id,
|
||||
badge_icon: badge_icon !== undefined ? (badge_icon || null) : cat.badge_icon,
|
||||
badge_label: badge_label !== undefined ? (badge_label || null) : cat.badge_label,
|
||||
// Default category (free) cannot be deactivated
|
||||
is_active: (!cat.is_default && is_active !== undefined) ? is_active : cat.is_active,
|
||||
});
|
||||
|
||||
logActivity(req.user?.user_id, 'update_tier_category', { entityType: 'tier_category', details: { id: cat.tier_category_id, slug: cat.slug } });
|
||||
|
||||
const result = await mdl_TierCategories.findByPk(cat.tier_category_id, { include: withBadge });
|
||||
return R.success(res, 'Tier category updated.', result);
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][UPDATE TIER CATEGORY]', err);
|
||||
return R.error(res, 'Could not update tier category.', 500);
|
||||
}
|
||||
};
|
||||
|
||||
// ─── DELETE /admin/tiers/categories/:id ──────────────────────────────────────
|
||||
|
||||
exports.deleteCategory = async (req, res) => {
|
||||
try {
|
||||
const cat = await mdl_TierCategories.findByPk(req.params.id);
|
||||
if (!cat) return R.error(res, 'Tier category not found.', 404);
|
||||
if (cat.is_default) return R.error(res, 'The default (Free) tier category cannot be deleted.', 400);
|
||||
|
||||
// Block deletion if active plans still reference this category
|
||||
const activePlans = await mdl_TierPlans.count({
|
||||
where: { tier_category_id: cat.tier_category_id, is_active: true },
|
||||
});
|
||||
if (activePlans > 0)
|
||||
return R.error(res, `Cannot delete — ${activePlans} active plan(s) belong to this category. Archive or reassign them first.`, 409);
|
||||
|
||||
await cat.destroy();
|
||||
logActivity(req.user?.user_id, 'delete_tier_category', { entityType: 'tier_category', details: { slug: cat.slug } });
|
||||
return R.success(res, 'Tier category deleted.');
|
||||
} catch (err) {
|
||||
console.error('[ADMIN][DELETE TIER CATEGORY]', err);
|
||||
return R.error(res, 'Could not delete tier category.', 500);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user