시드 생성

This commit is contained in:
2025-04-24 12:01:51 +09:00
parent beac42d60c
commit 7fa99e6988
42 changed files with 938 additions and 1170 deletions
+4 -11
View File
@@ -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
}]
}]
});
+9 -16
View File
@@ -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: [
-2
View File
@@ -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: [
+26 -120
View File
@@ -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;