/** * 이슈 유형 관리 서비스 * * 이슈 유형(카테고리/서브카테고리) 관련 비즈니스 로직 처리 * * @author TK-FB-Project * @since 2025-12-11 */ const issueTypeModel = require('../models/issueTypeModel'); const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors'); const logger = require('../utils/logger'); /** * 이슈 유형 생성 */ const createIssueTypeService = async (issueTypeData) => { const { category, subcategory } = issueTypeData; // 필수 필드 검증 if (!category || !subcategory) { throw new ValidationError('카테고리와 서브카테고리가 필요합니다', { required: ['category', 'subcategory'], received: { category, subcategory } }); } logger.info('이슈 유형 생성 요청', { category, subcategory }); try { const insertId = await new Promise((resolve, reject) => { issueTypeModel.create({ category, subcategory }, (err, id) => { if (err) reject(err); else resolve(id); }); }); logger.info('이슈 유형 생성 성공', { issue_type_id: insertId }); return { issue_type_id: insertId }; } catch (error) { logger.error('이슈 유형 생성 실패', { category, subcategory, error: error.message }); throw new DatabaseError('이슈 유형 생성 중 오류가 발생했습니다'); } }; /** * 전체 이슈 유형 조회 */ const getAllIssueTypesService = async () => { logger.info('이슈 유형 목록 조회 요청'); try { const rows = await new Promise((resolve, reject) => { issueTypeModel.getAll((err, data) => { if (err) reject(err); else resolve(data); }); }); logger.info('이슈 유형 목록 조회 성공', { count: rows.length }); return rows; } catch (error) { logger.error('이슈 유형 목록 조회 실패', { error: error.message }); throw new DatabaseError('이슈 유형 목록 조회 중 오류가 발생했습니다'); } }; /** * 이슈 유형 수정 */ const updateIssueTypeService = async (id, issueTypeData) => { const { category, subcategory } = issueTypeData; // ID 검증 if (!id || isNaN(id)) { throw new ValidationError('유효하지 않은 이슈 유형 ID입니다'); } // 필수 필드 검증 if (!category || !subcategory) { throw new ValidationError('카테고리와 서브카테고리가 필요합니다', { required: ['category', 'subcategory'], received: { category, subcategory } }); } logger.info('이슈 유형 수정 요청', { issue_type_id: id, category, subcategory }); try { const affectedRows = await new Promise((resolve, reject) => { issueTypeModel.update(id, { category, subcategory }, (err, rows) => { if (err) reject(err); else resolve(rows); }); }); if (affectedRows === 0) { logger.warn('이슈 유형을 찾을 수 없음', { issue_type_id: id }); throw new NotFoundError('이슈 유형을 찾을 수 없습니다'); } logger.info('이슈 유형 수정 성공', { issue_type_id: id, affectedRows }); return { changes: affectedRows }; } catch (error) { if (error instanceof NotFoundError) { throw error; } logger.error('이슈 유형 수정 실패', { issue_type_id: id, error: error.message }); throw new DatabaseError('이슈 유형 수정 중 오류가 발생했습니다'); } }; /** * 이슈 유형 삭제 */ const removeIssueTypeService = async (id) => { // ID 검증 if (!id || isNaN(id)) { throw new ValidationError('유효하지 않은 이슈 유형 ID입니다'); } logger.info('이슈 유형 삭제 요청', { issue_type_id: id }); try { const affectedRows = await new Promise((resolve, reject) => { issueTypeModel.remove(id, (err, rows) => { if (err) reject(err); else resolve(rows); }); }); if (affectedRows === 0) { logger.warn('이슈 유형을 찾을 수 없음', { issue_type_id: id }); throw new NotFoundError('이슈 유형을 찾을 수 없습니다'); } logger.info('이슈 유형 삭제 성공', { issue_type_id: id, affectedRows }); return { changes: affectedRows }; } catch (error) { if (error instanceof NotFoundError) { throw error; } logger.error('이슈 유형 삭제 실패', { issue_type_id: id, error: error.message }); throw new DatabaseError('이슈 유형 삭제 중 오류가 발생했습니다'); } }; module.exports = { createIssueTypeService, getAllIssueTypesService, updateIssueTypeService, removeIssueTypeService };