Files
tk-factory-services/user-management/api/models/notificationRecipientModel.js
Hyungi Ahn b1154a8bc7 feat(notifications): 알림 유형 개선 - 카테고리 그룹화 + 구매팀 세분화
- equipment/maintenance 삭제, partner_work/day_labor 신규 추가
- 알림 수신자 관리 UI: 카테고리별 그룹 렌더링 (생산/안전/구매/시스템)
- tkpurchase 컨트롤러 알림 타입 변경
- notification-bell 라벨 및 notifications.html 아이콘 업데이트
- 전 서비스 cache busting 갱신

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 15:29:29 +09:00

168 lines
4.5 KiB
JavaScript

// models/notificationRecipientModel.js
const { getPool } = require('./userModel');
const NOTIFICATION_TYPES = {
repair: '설비수리',
safety: '안전신고',
nonconformity: '부적합 신고',
system: '시스템',
partner_work: '협력업체 작업',
day_labor: '일용공 신청'
};
const NOTIFICATION_CATEGORIES = {
production: {
label: '생산',
icon: 'fa-industry',
types: ['repair', 'nonconformity']
},
safety: {
label: '안전',
icon: 'fa-shield-alt',
types: ['safety']
},
purchase: {
label: '구매',
icon: 'fa-shopping-cart',
types: ['partner_work', 'day_labor']
},
system: {
label: '시스템',
icon: 'fa-server',
types: ['system']
}
};
const notificationRecipientModel = {
// 알림 유형 목록 가져오기
getTypes() {
return { types: NOTIFICATION_TYPES, categories: NOTIFICATION_CATEGORIES };
},
// 유형별 수신자 목록 조회
async getByType(notificationType) {
const db = getPool();
const [rows] = await db.query(
`SELECT nr.*, u.username, u.name as user_name
FROM notification_recipients nr
JOIN sso_users u ON nr.user_id = u.user_id
WHERE nr.notification_type = ? AND nr.is_active = 1
ORDER BY u.name`,
[notificationType]
);
return rows;
},
// 전체 수신자 목록 조회 (유형별 그룹화)
async getAll() {
const db = getPool();
const [rows] = await db.query(
`SELECT nr.*, u.username, u.name as user_name
FROM notification_recipients nr
JOIN sso_users u ON nr.user_id = u.user_id
WHERE nr.is_active = 1
ORDER BY nr.notification_type, u.name`
);
// 유형별로 그룹화
const grouped = {};
for (const type in NOTIFICATION_TYPES) {
grouped[type] = {
label: NOTIFICATION_TYPES[type],
recipients: []
};
}
rows.forEach(row => {
if (grouped[row.notification_type]) {
grouped[row.notification_type].recipients.push(row);
}
});
return grouped;
},
// 수신자 추가
async add(notificationType, userId, createdBy = null) {
const db = getPool();
const [result] = await db.query(
`INSERT INTO notification_recipients (notification_type, user_id, created_by)
VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE is_active = 1`,
[notificationType, userId, createdBy]
);
return result.insertId || result.affectedRows > 0;
},
// 수신자 제거 (soft delete)
async remove(notificationType, userId) {
const db = getPool();
const [result] = await db.query(
`UPDATE notification_recipients SET is_active = 0
WHERE notification_type = ? AND user_id = ?`,
[notificationType, userId]
);
return result.affectedRows > 0;
},
// 수신자 완전 삭제
async delete(notificationType, userId) {
const db = getPool();
const [result] = await db.query(
`DELETE FROM notification_recipients
WHERE notification_type = ? AND user_id = ?`,
[notificationType, userId]
);
return result.affectedRows > 0;
},
// 유형별 수신자 user_id 목록만 가져오기 (알림 생성용)
async getRecipientIds(notificationType) {
const db = getPool();
const [rows] = await db.query(
`SELECT user_id FROM notification_recipients
WHERE notification_type = ? AND is_active = 1`,
[notificationType]
);
return rows.map(r => r.user_id);
},
// 사용자가 특정 유형의 수신자인지 확인
async isRecipient(notificationType, userId) {
const db = getPool();
const [[row]] = await db.query(
`SELECT 1 FROM notification_recipients
WHERE notification_type = ? AND user_id = ? AND is_active = 1`,
[notificationType, userId]
);
return !!row;
},
// 유형별 수신자 일괄 설정
async setRecipients(notificationType, userIds, createdBy = null) {
const db = getPool();
// 기존 수신자 비활성화
await db.query(
`UPDATE notification_recipients SET is_active = 0
WHERE notification_type = ?`,
[notificationType]
);
// 새 수신자 추가
if (userIds && userIds.length > 0) {
const values = userIds.map(userId => [notificationType, userId, createdBy]);
await db.query(
`INSERT INTO notification_recipients (notification_type, user_id, created_by)
VALUES ?
ON DUPLICATE KEY UPDATE is_active = 1`,
[values]
);
}
return true;
}
};
module.exports = notificationRecipientModel;