시드 생성
This commit is contained in:
@@ -156,8 +156,8 @@ exports.createClub = async (req, res) => {
|
||||
// 클럽 정보 업데이트
|
||||
exports.updateClub = async (req, res) => {
|
||||
try {
|
||||
const { clubId, name, location, description, contact, ownerEmail, status } = req.body;
|
||||
|
||||
const { id, name, location, description, contact, ownerEmail, status } = req.body;
|
||||
const clubId = id || req.params.id;
|
||||
const club = await Club.findByPk(clubId);
|
||||
|
||||
if (!club) {
|
||||
@@ -519,7 +519,6 @@ exports.getNextMeeting = async (req, res) => {
|
||||
},
|
||||
include: [{
|
||||
model: EventParticipant,
|
||||
as: 'participants',
|
||||
where: {
|
||||
status: { [Op.ne]: '취소' }
|
||||
},
|
||||
@@ -563,7 +562,6 @@ exports.getLastMeeting = async (req, res) => {
|
||||
},
|
||||
include: [{
|
||||
model: EventParticipant,
|
||||
as: 'participants',
|
||||
where: {
|
||||
status: { [Op.ne]: '취소' }
|
||||
},
|
||||
@@ -611,10 +609,8 @@ exports.getScoreStats = async (req, res) => {
|
||||
},
|
||||
include: [{
|
||||
model: EventParticipant,
|
||||
as: 'participants',
|
||||
include: [{
|
||||
model: EventScore,
|
||||
as: 'scores'
|
||||
model: EventScore
|
||||
}]
|
||||
}]
|
||||
});
|
||||
@@ -690,7 +686,6 @@ exports.getRecentMeetings = async (req, res) => {
|
||||
},
|
||||
include: [{
|
||||
model: EventParticipant,
|
||||
as: 'participants',
|
||||
where: {
|
||||
status: { [Op.ne]: '취소' }
|
||||
},
|
||||
@@ -796,10 +791,8 @@ exports.getStatistics = async (req, res) => {
|
||||
},
|
||||
include: [{
|
||||
model: EventParticipant,
|
||||
as: 'participants',
|
||||
include: [{
|
||||
model: EventScore,
|
||||
as: 'scores'
|
||||
model: EventScore
|
||||
}]
|
||||
}]
|
||||
});
|
||||
|
||||
@@ -27,7 +27,6 @@ exports.getAllEvents = async (req, res) => {
|
||||
},
|
||||
{
|
||||
model: EventParticipant,
|
||||
as: 'participants',
|
||||
attributes: ['id', 'status', 'paymentStatus'],
|
||||
where: {
|
||||
status: { [Op.ne]: '취소' }
|
||||
@@ -79,16 +78,15 @@ exports.getEventById = async (req, res) => {
|
||||
},
|
||||
{
|
||||
model: EventParticipant,
|
||||
as: 'participants',
|
||||
attributes: ['id', 'status', 'paymentStatus'],
|
||||
where: {
|
||||
status: { [Op.ne]: '취소' }
|
||||
},
|
||||
attributes: ['id', 'status', 'paymentStatus', 'teamNumber'],
|
||||
where: { status: { [Op.ne]: '취소' } },
|
||||
required: false,
|
||||
include: [{
|
||||
model: Member,
|
||||
attributes: ['id', 'name']
|
||||
}]
|
||||
include: [
|
||||
{
|
||||
model: Member,
|
||||
attributes: ['id', 'name', 'average']
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
@@ -244,7 +242,6 @@ exports.updateEvent = async (req, res) => {
|
||||
},
|
||||
{
|
||||
model: EventParticipant,
|
||||
as: 'participants',
|
||||
attributes: ['id', 'status'],
|
||||
where: {
|
||||
status: { [Op.ne]: '취소' }
|
||||
@@ -355,7 +352,6 @@ exports.getEventScores = async (req, res) => {
|
||||
include: [
|
||||
{
|
||||
model: EventParticipant,
|
||||
as: 'participant',
|
||||
attributes: ['id', 'status'],
|
||||
include: [{
|
||||
model: Member,
|
||||
@@ -618,7 +614,6 @@ exports.deleteEventScore = async (req, res) => {
|
||||
include: [
|
||||
{
|
||||
model: EventParticipant,
|
||||
as: 'participant',
|
||||
attributes: ['id', 'status'],
|
||||
include: [{
|
||||
model: Member,
|
||||
@@ -702,7 +697,6 @@ exports.getEventStats = async (req, res) => {
|
||||
],
|
||||
include: [{
|
||||
model: EventParticipant,
|
||||
as: 'participant',
|
||||
attributes: [],
|
||||
include: [{
|
||||
model: Member,
|
||||
@@ -934,7 +928,6 @@ exports.getUserEvents = async (req, res) => {
|
||||
include: [
|
||||
{
|
||||
model: EventParticipant,
|
||||
as: 'participants',
|
||||
where: { userId },
|
||||
attributes: []
|
||||
},
|
||||
@@ -983,7 +976,7 @@ exports.getEventParticipants = async (req, res) => {
|
||||
include: [
|
||||
{
|
||||
model: Member,
|
||||
attributes: ['id', 'name', 'email', 'phone', 'memberType']
|
||||
attributes: ['id', 'name', 'email', 'phone', 'memberType', 'average']
|
||||
}
|
||||
],
|
||||
order: [
|
||||
|
||||
@@ -78,7 +78,6 @@ exports.getActiveFeatures = async (req, res) => {
|
||||
},
|
||||
include: [{
|
||||
model: Feature,
|
||||
as: 'feature',
|
||||
attributes: ['name', 'description']
|
||||
}],
|
||||
attributes: ['id', 'featureId', 'purchaseDate', 'expiryDate']
|
||||
@@ -106,7 +105,6 @@ exports.getFeaturePayments = async (req, res) => {
|
||||
},
|
||||
include: [{
|
||||
model: Feature,
|
||||
as: 'feature',
|
||||
attributes: ['name']
|
||||
}],
|
||||
attributes: [
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { Menu, Feature, ClubFeature, ClubSubscription, SubscriptionPlan, Member } = require('../models');
|
||||
const { Menu, Member } = require('../models');
|
||||
const { Op } = require('sequelize');
|
||||
|
||||
/**
|
||||
@@ -42,125 +42,31 @@ exports.getUserMenus = async (req, res) => {
|
||||
/**
|
||||
* 사용자 권한과 클럽의 구독/기능 상태에 따라 접근 가능한 메뉴 목록을 조회합니다.
|
||||
*/
|
||||
const { clubHasFeature } = require('../utils/featureAccess');
|
||||
|
||||
async function getAccessibleMenus(clubId, userRole, member) {
|
||||
try {
|
||||
// 1. 클럽의 현재 구독 정보 조회
|
||||
const clubSubscription = await ClubSubscription.findOne({
|
||||
where: {
|
||||
clubId,
|
||||
status: 'active',
|
||||
endDate: {
|
||||
[Op.gt]: new Date()
|
||||
}
|
||||
},
|
||||
include: [{
|
||||
model: SubscriptionPlan,
|
||||
attributes: ['name']
|
||||
}]
|
||||
});
|
||||
// 1. 모든 visible 메뉴 조회
|
||||
const allMenus = await Menu.findAll({ where: { visible: true }, order: [['order', 'ASC']] });
|
||||
|
||||
// 2. 클럽의 활성화된 기능 목록 조회
|
||||
const activeFeatures = await ClubFeature.findAll({
|
||||
where: {
|
||||
clubId,
|
||||
enabled: true,
|
||||
[Op.or]: [
|
||||
{ expiryDate: null },
|
||||
{ expiryDate: { [Op.gt]: new Date() } }
|
||||
]
|
||||
},
|
||||
include: [{
|
||||
model: Feature,
|
||||
as: 'feature',
|
||||
attributes: ['code']
|
||||
}]
|
||||
});
|
||||
|
||||
const activeFeatureCodes = activeFeatures.map(f => f.feature.code);
|
||||
const subscriptionTier = clubSubscription ? clubSubscription.SubscriptionPlan.name.toLowerCase() : 'basic';
|
||||
|
||||
// 3. 메뉴 조회 및 필터링
|
||||
const allMenus = await Menu.findAll({
|
||||
where: {
|
||||
visible: true,
|
||||
[Op.and]: [
|
||||
// 역할 기반 필터링
|
||||
{
|
||||
[Op.or]: [
|
||||
{ role: userRole },
|
||||
{ role: 'user' }
|
||||
]
|
||||
},
|
||||
// 구독 등급 기반 필터링
|
||||
{
|
||||
[Op.or]: [
|
||||
{ requiredSubscriptionTier: null },
|
||||
{ requiredSubscriptionTier: subscriptionTier }
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
include: [{
|
||||
model: Menu,
|
||||
as: 'children',
|
||||
required: false
|
||||
}],
|
||||
order: [
|
||||
['order', 'ASC'],
|
||||
[{ model: Menu, as: 'children' }, 'order', 'ASC']
|
||||
]
|
||||
});
|
||||
|
||||
// 4. 기능 코드 기반 필터링 및 메뉴 구조화
|
||||
const processMenu = (menu) => {
|
||||
// 기능 코드가 있는 경우 접근 권한 확인
|
||||
if (menu.featureCode && !activeFeatureCodes.includes(menu.featureCode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const processedMenu = {
|
||||
id: menu.id,
|
||||
title: menu.title,
|
||||
icon: menu.icon,
|
||||
to: menu.to,
|
||||
order: menu.order
|
||||
};
|
||||
|
||||
// 하위 메뉴 처리
|
||||
if (menu.children && menu.children.length > 0) {
|
||||
const children = menu.children
|
||||
.map(processMenu)
|
||||
.filter(child => child !== null);
|
||||
|
||||
if (children.length > 0) {
|
||||
processedMenu.children = children;
|
||||
}
|
||||
}
|
||||
|
||||
return processedMenu;
|
||||
};
|
||||
|
||||
// 최상위 메뉴만 필터링 (parentId가 null인 항목)
|
||||
const rootMenus = allMenus
|
||||
.filter(menu => !menu.parentId)
|
||||
.map(processMenu)
|
||||
.filter(menu => menu !== null);
|
||||
|
||||
// 구독 관리 메뉴 추가 (모임장, 운영진만 접근 가능)
|
||||
if (member && (member.memberType === '모임장' || member.memberType === '운영진')) {
|
||||
rootMenus.push({
|
||||
id: 'subscription',
|
||||
title: '구독/결제 관리',
|
||||
icon: 'pi pi-credit-card',
|
||||
to: '/club/subscription',
|
||||
order: 90,
|
||||
children: []
|
||||
});
|
||||
}
|
||||
|
||||
return rootMenus;
|
||||
} catch (error) {
|
||||
console.error('메뉴 조회 중 오류 발생:', error);
|
||||
throw error;
|
||||
// 2. 각 메뉴별로 featureCode가 있으면 clubHasFeature로 체크
|
||||
async function isAccessible(menu) {
|
||||
if (!menu.featureCode) return true;
|
||||
return await clubHasFeature(clubId, menu.featureCode);
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 트리 구조로 접근 가능한 메뉴만 반환
|
||||
async function buildMenuTree(parentId = null) {
|
||||
const filteredMenus = [];
|
||||
for (const menu of allMenus.filter(m => m.parentId === parentId)) {
|
||||
if (await isAccessible(menu)) {
|
||||
const children = await buildMenuTree(menu.id);
|
||||
filteredMenus.push({ ...menu.toJSON(), children });
|
||||
}
|
||||
}
|
||||
return filteredMenus;
|
||||
}
|
||||
|
||||
return await buildMenuTree();
|
||||
}
|
||||
|
||||
exports.getAccessibleMenus = getAccessibleMenus;
|
||||
Reference in New Issue
Block a user