prepare(" SELECT start_date, end_date FROM edu_contents WHERE category_code = 'CA10003' AND base_year = ? GROUP BY start_date, end_date LIMIT 1 "); $stmt->execute([$selected_year]); $period = $stmt->fetch(PDO::FETCH_ASSOC); if ($period && !empty($period['start_date']) && !empty($period['end_date'])) { // 날짜 포맷: YYYY.MM.DD $start = date('Y.m.d', strtotime($period['start_date'])); $end = date('Y.m.d', strtotime($period['end_date'])); $legal_edu_period = "{$start} ~ {$end}"; // 전체 학습자 수 표시 퇴사자 제외 $stmt_qty = $pdo->prepare(" SELECT COUNT(member_id) as qty FROM edu_users WHERE (end_date IS NULL OR end_date > CURDATE()) AND sys_comp_code = working_comp "); $stmt_qty->execute(); $user_qty = $stmt_qty->fetchColumn(); } } catch (Exception $e) { // 법정의무교육 기간 조회 실패 시 기본값 유지 } // 법인 리스트 가져오기 (프로시저 사용) $pdo = db_conn(); $stmt_corp = $pdo->query("CALL proc_get_code2_list('CO100')"); $companies = $stmt_corp->fetchAll(PDO::FETCH_ASSOC); while ($stmt_corp->nextRowset()) { } unset($stmt_corp); // 법인별 학습인원 현황 (재직 중인 인원 수) $learner_count_query = $pdo->prepare(" SELECT c.code_name, COUNT(DISTINCT b.member_id) as learner_count FROM edu_codes c LEFT JOIN edu_users b ON c.code = b.belong_comp AND b.end_date IS NULL WHERE c.group_code = 'CO100' AND c.is_active = '1' GROUP BY c.code, c.code_name ORDER BY c.code ASC "); $learner_count_query->execute(); $learner_counts = $learner_count_query->fetchAll(); // 법인별 통계 (총 학습시간) $total_time_query = $pdo->prepare(" SELECT c.code, c.code_name, CONCAT( LPAD(FLOOR(IFNULL(SUM(CASE WHEN a.completed_at IS NULL THEN a.watch_tm ELSE a.content_tm END), 0) / 3600), 2, '0'), '시간 ', LPAD(FLOOR((IFNULL(SUM(CASE WHEN a.completed_at IS NULL THEN a.watch_tm ELSE a.content_tm END), 0) % 3600) / 60), 2, '0'), '분' ) AS formatted_total_tm FROM edu_codes c LEFT JOIN edu_users b ON c.code = b.sys_comp_code LEFT JOIN edu_learning_histories a ON b.member_id = a.member_id AND b.sys_comp_code = a.sys_comp_code AND a.last_viewed_at BETWEEN ? AND ? WHERE c.group_code = 'CO100' AND c.is_active = '1' GROUP BY c.code, c.code_name ORDER BY c.code ASC "); $total_time_query->execute(["$stat_fr_date 00:00:00", "$stat_to_date 23:59:59"]); $total_times = $total_time_query->fetchAll(); // 법인별 통계 (평균 학습횟수) $avg_count_query = $pdo->prepare(" SELECT c.code, c.code_name, CONCAT( IFNULL( ROUND( COUNT(a.content_id) , 1 ), 0 ), '회' ) AS avg_view_count FROM edu_codes c LEFT JOIN edu_users b ON c.code = b.sys_comp_code LEFT JOIN edu_learning_histories a ON b.member_id = a.member_id AND b.sys_comp_code = a.sys_comp_code AND a.last_viewed_at BETWEEN ? AND ? WHERE c.group_code = 'CO100' AND c.is_active = '1' GROUP BY c.code, c.code_name ORDER BY c.code ASC "); $avg_count_query->execute(["$stat_fr_date 00:00:00", "$stat_to_date 23:59:59"]); $avg_counts = $avg_count_query->fetchAll(); // 법인별 접속 추이 (월별) $access_trend_query = $pdo->prepare(" SELECT MONTH(accessed_at) as month, COUNT(al.member_id) as access_count FROM edu_access_logs al WHERE al.accessed_at BETWEEN ? AND ? AND (? = '' OR EXISTS ( SELECT 1 FROM edu_users u WHERE u.member_id = al.member_id AND u.sys_comp_code = ? )) GROUP BY MONTH(al.accessed_at) ORDER BY MONTH(al.accessed_at) ASC "); $access_trend_query->execute(["$access_fr_date 00:00:00", "$access_to_date 23:59:59", $selected_access_comp, $selected_access_comp]); $access_trends = $access_trend_query->fetchAll(); // 가장 많이 본 영상 (카테고리별 top5) $popular_videos_query = $pdo->prepare(" SELECT b.category_code, b.title AS content_title, COUNT(a.content_id) as view_count FROM edu_learning_histories a JOIN edu_contents b ON a.content_id = b.content_id WHERE a.last_viewed_at BETWEEN ? AND ? GROUP BY b.category_code, b.content_id, b.title ORDER BY b.category_code, view_count DESC "); $popular_videos_query->execute(["$video_fr_date 00:00:00", "$video_to_date 23:59:59"]); $popular_videos = $popular_videos_query->fetchAll(); // 배움터 학습 랭킹 $ranking_sql = " SELECT a.sys_comp_code, a.name, a.dept_name, c.code_name as company_name, SUM(CASE WHEN b.completed_at IS NULL THEN b.watch_tm ELSE b.content_tm END) / 3600 as total_hours FROM edu_users a JOIN edu_learning_histories b ON a.member_id = b.member_id AND a.sys_comp_code = b.sys_comp_code JOIN edu_codes c ON a.belong_comp = c.code WHERE b.last_viewed_at BETWEEN ? AND ? AND c.group_code = 'CO100' AND (? = '' OR a.belong_comp = ?) "; if ($exclude_admin) { $ranking_sql .= " AND a.auth_level NOT IN ('LE10001', 'LE10002') "; } $ranking_sql .= " GROUP BY a.sys_comp_code, a.member_id, a.name, a.dept_name, c.code_name ORDER BY total_hours DESC LIMIT 20 "; $ranking_query = $pdo->prepare($ranking_sql); $ranking_query->execute(["$rank_fr_date 00:00:00", "$rank_to_date 23:59:59", $selected_ranking_comp, $selected_ranking_comp]); $rankings = $ranking_query->fetchAll(); ?>

전체학습현황 전체 학습자 수:

법정의무교육 기간:

법인별 학습인원 현황

$max_count) $max_count = $val; } // 스케일 계산: 데이터가 있으면 500 단위로 올림, 없으면 기본 100 $y_max = $max_count > 0 ? ceil($max_count / 500) * 500 : 500; if ($y_max < 1) $y_max = 100; $y_step_count = 4; $y_unit = $y_max / $y_step_count; $scale = 165 / $y_max; $bar_width = 30; $gap = 12; $start_x = 45; ?>
/> $data) { if ($index >= 7) break; // 차트 공간상 7개까지만 표시 $val = (int) $data['learner_count']; $height = $val * $scale; $y = 175 - $height; $x = $start_x + $index * ($bar_width + $gap); $color = $index < 4 ? '#114b3d' : '#1d6b56'; echo "\n"; $text_x = $x + $bar_width / 2; $short_name = mb_substr($data['code_name'], 0, 4); // 이름이 길면 자름 echo "{$short_name}\n"; } ?>

법인별 통계

법인별 접속 추이(로그인 법인)

0 ? 165 / $y_trend_max : 0; ?> />

가장 많이 본 영상

~
'마이클래스', 'CA10002' => '온보딩', 'CA10003' => '법정교육', 'CA10004' => '리더십', 'CA10005' => '인사이트', 'CA10006' => '비즈트렌드']; foreach ($categories as $cat_code => $cat_name): $videos = array_filter($popular_videos, function ($v) use ($cat_code) { return $v['category_code'] == $cat_code; }); usort($videos, function ($a, $b) { return $b['view_count'] - $a['view_count']; }); $top5 = array_slice($videos, 0, 20); ?>
$video): ?>

시청수:

배움터 학습 랭킹

~
$rank): $level = $rank['total_hours'] >= 40 ? 'Master' : ($rank['total_hours'] >= 20 ? 'Elite' : ($rank['total_hours'] >= 8 ? 'Learner' : 'Rookie')); $level_color = $level == 'Master' ? 'purple' : ($level == 'Elite' ? 'blue' : ($level == 'Learner' ? 'green' : 'gray')); ?>

시간