feat: 알림 시스템 및 시설설비 관리 기능 구현
- 알림 시스템 구축 (navbar 알림 아이콘, 드롭다운) - 알림 수신자 설정 기능 (계정관리 페이지) - 시설설비 관리 페이지 추가 (수리 워크플로우) - 수리 신청 → 접수 → 처리중 → 완료 상태 관리 - 사이드바 메뉴 구조 개선 (공장 관리 카테고리) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -903,6 +903,42 @@ const EquipmentController = {
|
||||
message: '서버 오류가 발생했습니다.'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// ADD REPAIR CATEGORY - 새 수리 항목 추가
|
||||
addRepairCategory: (req, res) => {
|
||||
try {
|
||||
const { item_name } = req.body;
|
||||
|
||||
if (!item_name || !item_name.trim()) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '수리 유형 이름을 입력하세요.'
|
||||
});
|
||||
}
|
||||
|
||||
EquipmentModel.addRepairCategory(item_name.trim(), (error, result) => {
|
||||
if (error) {
|
||||
console.error('수리 항목 추가 오류:', error);
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: '수리 항목 추가 중 오류가 발생했습니다.'
|
||||
});
|
||||
}
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
message: result.isNew ? '새 수리 유형이 추가되었습니다.' : '기존 수리 유형을 사용합니다.',
|
||||
data: result
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('수리 항목 추가 오류:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '서버 오류가 발생했습니다.'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
165
api.hyungi.net/controllers/notificationController.js
Normal file
165
api.hyungi.net/controllers/notificationController.js
Normal file
@@ -0,0 +1,165 @@
|
||||
// controllers/notificationController.js
|
||||
const notificationModel = require('../models/notificationModel');
|
||||
|
||||
const notificationController = {
|
||||
// 읽지 않은 알림 조회
|
||||
async getUnread(req, res) {
|
||||
try {
|
||||
const userId = req.user?.id || null;
|
||||
const notifications = await notificationModel.getUnread(userId);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: notifications
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('읽지 않은 알림 조회 오류:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '알림 조회 중 오류가 발생했습니다.'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 전체 알림 조회
|
||||
async getAll(req, res) {
|
||||
try {
|
||||
const userId = req.user?.id || null;
|
||||
const page = parseInt(req.query.page) || 1;
|
||||
const limit = parseInt(req.query.limit) || 20;
|
||||
|
||||
const result = await notificationModel.getAll(userId, page, limit);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result.notifications,
|
||||
pagination: {
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
limit: result.limit,
|
||||
totalPages: Math.ceil(result.total / result.limit)
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('알림 목록 조회 오류:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '알림 조회 중 오류가 발생했습니다.'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 읽지 않은 알림 개수
|
||||
async getUnreadCount(req, res) {
|
||||
try {
|
||||
const userId = req.user?.id || null;
|
||||
const count = await notificationModel.getUnreadCount(userId);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: { count }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('알림 개수 조회 오류:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '알림 개수 조회 중 오류가 발생했습니다.'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 알림 읽음 처리
|
||||
async markAsRead(req, res) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const success = await notificationModel.markAsRead(id);
|
||||
|
||||
res.json({
|
||||
success,
|
||||
message: success ? '알림을 읽음 처리했습니다.' : '알림을 찾을 수 없습니다.'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('알림 읽음 처리 오류:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '알림 처리 중 오류가 발생했습니다.'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 모든 알림 읽음 처리
|
||||
async markAllAsRead(req, res) {
|
||||
try {
|
||||
const userId = req.user?.id || null;
|
||||
const count = await notificationModel.markAllAsRead(userId);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: `${count}개의 알림을 읽음 처리했습니다.`,
|
||||
data: { count }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('전체 읽음 처리 오류:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '알림 처리 중 오류가 발생했습니다.'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 알림 삭제
|
||||
async delete(req, res) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
const success = await notificationModel.delete(id);
|
||||
|
||||
res.json({
|
||||
success,
|
||||
message: success ? '알림을 삭제했습니다.' : '알림을 찾을 수 없습니다.'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('알림 삭제 오류:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '알림 삭제 중 오류가 발생했습니다.'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 알림 생성 (시스템용)
|
||||
async create(req, res) {
|
||||
try {
|
||||
const { type, title, message, link_url, user_id } = req.body;
|
||||
|
||||
if (!title) {
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: '알림 제목은 필수입니다.'
|
||||
});
|
||||
}
|
||||
|
||||
const notificationId = await notificationModel.create({
|
||||
user_id,
|
||||
type,
|
||||
title,
|
||||
message,
|
||||
link_url,
|
||||
created_by: req.user?.id
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
message: '알림이 생성되었습니다.',
|
||||
data: { notification_id: notificationId }
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('알림 생성 오류:', error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: '알림 생성 중 오류가 발생했습니다.'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = notificationController;
|
||||
@@ -0,0 +1,91 @@
|
||||
// controllers/notificationRecipientController.js
|
||||
const notificationRecipientModel = require('../models/notificationRecipientModel');
|
||||
|
||||
const notificationRecipientController = {
|
||||
// 알림 유형 목록
|
||||
getTypes: async (req, res) => {
|
||||
try {
|
||||
const types = notificationRecipientModel.getTypes();
|
||||
res.json({ success: true, data: types });
|
||||
} catch (error) {
|
||||
console.error('알림 유형 조회 오류:', error);
|
||||
res.status(500).json({ success: false, error: '알림 유형 조회 실패' });
|
||||
}
|
||||
},
|
||||
|
||||
// 전체 수신자 목록 (유형별 그룹화)
|
||||
getAll: async (req, res) => {
|
||||
try {
|
||||
console.log('🔔 알림 수신자 목록 조회 시작');
|
||||
const recipients = await notificationRecipientModel.getAll();
|
||||
console.log('✅ 알림 수신자 목록 조회 완료:', recipients);
|
||||
res.json({ success: true, data: recipients });
|
||||
} catch (error) {
|
||||
console.error('❌ 수신자 목록 조회 오류:', error.message);
|
||||
console.error('❌ 스택:', error.stack);
|
||||
res.status(500).json({ success: false, error: '수신자 목록 조회 실패', detail: error.message });
|
||||
}
|
||||
},
|
||||
|
||||
// 유형별 수신자 조회
|
||||
getByType: async (req, res) => {
|
||||
try {
|
||||
const { type } = req.params;
|
||||
const recipients = await notificationRecipientModel.getByType(type);
|
||||
res.json({ success: true, data: recipients });
|
||||
} catch (error) {
|
||||
console.error('수신자 조회 오류:', error);
|
||||
res.status(500).json({ success: false, error: '수신자 조회 실패' });
|
||||
}
|
||||
},
|
||||
|
||||
// 수신자 추가
|
||||
add: async (req, res) => {
|
||||
try {
|
||||
const { notification_type, user_id } = req.body;
|
||||
|
||||
if (!notification_type || !user_id) {
|
||||
return res.status(400).json({ success: false, error: '알림 유형과 사용자 ID가 필요합니다.' });
|
||||
}
|
||||
|
||||
await notificationRecipientModel.add(notification_type, user_id, req.user?.user_id);
|
||||
res.json({ success: true, message: '수신자가 추가되었습니다.' });
|
||||
} catch (error) {
|
||||
console.error('수신자 추가 오류:', error);
|
||||
res.status(500).json({ success: false, error: '수신자 추가 실패' });
|
||||
}
|
||||
},
|
||||
|
||||
// 수신자 제거
|
||||
remove: async (req, res) => {
|
||||
try {
|
||||
const { type, userId } = req.params;
|
||||
|
||||
await notificationRecipientModel.remove(type, userId);
|
||||
res.json({ success: true, message: '수신자가 제거되었습니다.' });
|
||||
} catch (error) {
|
||||
console.error('수신자 제거 오류:', error);
|
||||
res.status(500).json({ success: false, error: '수신자 제거 실패' });
|
||||
}
|
||||
},
|
||||
|
||||
// 유형별 수신자 일괄 설정
|
||||
setRecipients: async (req, res) => {
|
||||
try {
|
||||
const { type } = req.params;
|
||||
const { user_ids } = req.body;
|
||||
|
||||
if (!Array.isArray(user_ids)) {
|
||||
return res.status(400).json({ success: false, error: 'user_ids 배열이 필요합니다.' });
|
||||
}
|
||||
|
||||
await notificationRecipientModel.setRecipients(type, user_ids, req.user?.user_id);
|
||||
res.json({ success: true, message: '수신자가 설정되었습니다.' });
|
||||
} catch (error) {
|
||||
console.error('수신자 설정 오류:', error);
|
||||
res.status(500).json({ success: false, error: '수신자 설정 실패' });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = notificationRecipientController;
|
||||
Reference in New Issue
Block a user