# All files / services analysisService.js

0% Statements 0/20
0% Branches 0/8
0% Functions 0/3
0% Lines 0/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82

     /**
     * 프로젝트 분석 서비스
     *
     * 기간별 프로젝트, 작업자, 작업 유형 분석 데이터 처리
     *
     * @author TK-FB-Project
     * @since 2025-12-11
     */

    const analysisModel = require('../models/analysisModel');
    const { ValidationError, DatabaseError } = require('../utils/errors');
    const logger = require('../utils/logger');

    /**
     * 기간별 프로젝트 분석 데이터 조회
     *
     * @param {string} startDate - 시작일 (YYYY-MM-DD)
     * @param {string} endDate - 종료일 (YYYY-MM-DD)
     * @returns {Promise<object>} 가공된 분석 데이터
     */
    const getAnalysisService = async (startDate, endDate) => {
      // 필수 필드 검증
      if (!startDate || !endDate) {
        throw new ValidationError('시작일과 종료일이 필요합니다', {
          required: ['startDate', 'endDate'],
          received: { startDate, endDate }
        });
      }

      logger.info('분석 데이터 조회 요청', { startDate, endDate });

      try {
        const analysisData = await analysisModel.getAnalysis(startDate, endDate);

        const { summary, byProject, byWorker, byTask, details } = analysisData;
        const totalHours = summary.totalHours || 0;

        // 비율(percentage) 계산 헬퍼 함수
        const addPercentage = (item) => ({
          ...item,
          hours: parseFloat(item.hours.toFixed(1)),
          percentage: totalHours > 0 ? parseFloat((item.hours / totalHours * 100).toFixed(1)) : 0
        });

        const result = {
          summary: {
            ...summary,
            totalHours: parseFloat(totalHours.toFixed(1))
          },
          byProject: byProject.map(addPercentage),
          byWorker: byWorker.map(addPercentage),
          byTask: byTask.map(addPercentage),
          details: details.map(d => ({
            ...d,
            work_hours: parseFloat(d.work_hours.toFixed(1))
          }))
        };

        logger.info('분석 데이터 조회 성공', {
          startDate,
          endDate,
          totalHours: result.summary.totalHours,
          projectCount: result.byProject.length,
          workerCount: result.byWorker.length,
          detailCount: result.details.length
        });

        return result;
      } catch (error) {
        logger.error('분석 데이터 조회 실패', {
          startDate,
          endDate,
          error: error.message
        });
        throw new DatabaseError('분석 데이터 조회 중 오류가 발생했습니다');
      }
    };

    module.exports = {
      getAnalysisService
    };