Initial commit: 교육 프로젝트 배포
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
require_once __DIR__ . '/../../bbs/db_conn.php';
|
||||
require_once __DIR__ . '/../../bbs/auth.php';
|
||||
edu_require_login();
|
||||
|
||||
$pdo = db_conn();
|
||||
|
||||
$year = $_GET['year'] ?? date('Y');
|
||||
$quarter_raw = $_GET['quarter'] ?? ceil(date('n') / 3);
|
||||
|
||||
// Convert quarter code (e.g., CA200Q01, CA200001) to integer 1~4
|
||||
if (is_string($quarter_raw) && strpos($quarter_raw, 'CA200') === 0) {
|
||||
$quarter = (int) substr($quarter_raw, -1);
|
||||
} else {
|
||||
$quarter = (int) $quarter_raw;
|
||||
}
|
||||
if ($quarter < 1 || $quarter > 4)
|
||||
$quarter = 1;
|
||||
|
||||
// Calculate start and end dates for the quarter
|
||||
$p_fr_dt = $year . '-' . sprintf('%02d', ($quarter - 1) * 3 + 1) . '-01';
|
||||
$p_to_dt = date('Y-m-t', strtotime($year . '-' . sprintf('%02d', $quarter * 3) . '-01'));
|
||||
$p_fr_dt_full = $p_fr_dt . ' 00:00:00';
|
||||
$p_to_dt_full = $p_to_dt . ' 23:59:59';
|
||||
|
||||
$response = [
|
||||
'success' => true,
|
||||
'data' => []
|
||||
];
|
||||
|
||||
try {
|
||||
// 1. KPI
|
||||
$stmt_kpi = $pdo->prepare("CALL proc_get_dashboard_kpi(?, ?)");
|
||||
$stmt_kpi->execute([$year, $quarter]);
|
||||
$kpi = $stmt_kpi->fetch(PDO::FETCH_ASSOC);
|
||||
while ($stmt_kpi->nextRowset()) {
|
||||
} // Clear extra rowsets
|
||||
$stmt_kpi->closeCursor();
|
||||
|
||||
// Ensure all variables exist, with defaults
|
||||
$kpi = $kpi ?: [];
|
||||
// DEBUG: Write kpi to file
|
||||
file_put_contents(__DIR__ . '/kpi_debug.json', json_encode($kpi, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||
|
||||
$kpi = array_change_key_case($kpi, CASE_LOWER);
|
||||
|
||||
// Add computed metrics for KPI based on User's input
|
||||
$access_qty = isset($kpi['access_qty']) ? (float) $kpi['access_qty'] : 0;
|
||||
$completed_qty = isset($kpi['completed_qty']) ? (float) $kpi['completed_qty'] : 0;
|
||||
$access_qty_u = isset($kpi['access_qty_u']) ? (float) $kpi['access_qty_u'] : 0;
|
||||
$completed_qty_u = isset($kpi['completed_qty_u']) ? (float) $kpi['completed_qty_u'] : 0;
|
||||
|
||||
$kpi['computed_content_per_user'] = $access_qty > 0 ? round($completed_qty / $access_qty, 1) : 0;
|
||||
$prev_content_per_user = $access_qty_u > 0 ? round($completed_qty_u / $access_qty_u, 1) : 0;
|
||||
$kpi['computed_content_per_user_diff'] = round($kpi['computed_content_per_user'] - $prev_content_per_user, 1);
|
||||
|
||||
$legal_qty_all = isset($kpi['legal_qty_all']) ? (int) $kpi['legal_qty_all'] : 0;
|
||||
$legal_qty_y = isset($kpi['legal_qty_y']) ? (int) $kpi['legal_qty_y'] : 0;
|
||||
$kpi['computed_legal_uncompleted'] = $legal_qty_all - $legal_qty_y;
|
||||
$kpi['computed_legal_rate'] = $legal_qty_all > 0 ? round(($legal_qty_y / $legal_qty_all) * 100) : 0;
|
||||
|
||||
$quarter_qty = isset($kpi['quarter_qty']) ? (int) $kpi['quarter_qty'] : 0;
|
||||
$goals_qty = isset($kpi['goals_qty']) ? (int) $kpi['goals_qty'] : (isset($kpi['goal_qty']) ? (int) $kpi['goal_qty'] : 0);
|
||||
$goals_completed_qty = isset($kpi['goals_completed_qty']) ? (int) $kpi['goals_completed_qty'] : (isset($kpi['goal_completed_qty']) ? (int) $kpi['goal_completed_qty'] : 0);
|
||||
|
||||
$kpi['myclass_target_qty'] = $goals_qty;
|
||||
$kpi['myclass_target_rate'] = $quarter_qty > 0 ? round(($goals_qty / $quarter_qty) * 100) : 0;
|
||||
|
||||
$kpi['myclass_achieve_qty'] = $goals_completed_qty;
|
||||
$kpi['myclass_achieve_rate'] = $goals_qty > 0 ? round(($goals_completed_qty / $goals_qty) * 100) : 0;
|
||||
|
||||
$response['data']['kpi'] = $kpi;
|
||||
|
||||
// 2. 법인별 접속률
|
||||
$stmt_corp = $pdo->prepare("
|
||||
SELECT c.code_name
|
||||
, COUNT(DISTINCT b.member_id) as all_qty
|
||||
, IFNULL(d.access_qty, 0) AS access_qty
|
||||
, IFNULL(ROUND(IFNULL(d.access_qty, 0) / NULLIF(COUNT(DISTINCT b.member_id), 0) * 100,0),0) as access_rate
|
||||
, IFNULL(COUNT(DISTINCT b.member_id) - IFNULL(d.access_qty, 0),0) AS no_access_qty
|
||||
FROM edu_codes c
|
||||
LEFT JOIN edu_users b ON c.code = b.sys_comp_code AND (b.end_date IS NULL OR b.end_date > CURDATE())
|
||||
LEFT JOIN (SELECT COUNT(0) AS access_qty , sys_comp_code
|
||||
FROM (SELECT a.member_id, a.sys_comp_code
|
||||
FROM edu_access_logs a
|
||||
WHERE 1=1
|
||||
AND accessed_at >= ?
|
||||
AND accessed_at <= ?
|
||||
GROUP BY a.member_id, a.sys_comp_code) x
|
||||
GROUP BY sys_comp_code ) d ON c.code = d.sys_comp_code
|
||||
WHERE c.group_code = 'CO100' AND c.is_active = '1'
|
||||
GROUP BY c.code, c.code_name
|
||||
ORDER BY c.code ASC
|
||||
");
|
||||
$stmt_corp->execute([$p_fr_dt, $p_to_dt]);
|
||||
$response['data']['corp_access_rate'] = $stmt_corp->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// 3. 학습자 접속 빈도
|
||||
$stmt_freq = $pdo->prepare("
|
||||
SELECT
|
||||
SUM(CASE WHEN IFNULL(a.qty, 0) >= 12 THEN 1 ELSE 0 END) AS active_lv01,
|
||||
SUM(CASE WHEN IFNULL(a.qty, 0) BETWEEN 5 AND 11 THEN 1 ELSE 0 END) AS normal_lv02,
|
||||
SUM(CASE WHEN IFNULL(a.qty, 0) BETWEEN 1 AND 4 THEN 1 ELSE 0 END) AS low_lv03,
|
||||
SUM(CASE WHEN IFNULL(a.qty, 0) = 0 THEN 1 ELSE 0 END) AS none_lv04
|
||||
FROM edu_users u
|
||||
LEFT JOIN (
|
||||
SELECT member_id, sys_comp_code, COUNT(DISTINCT DATE(accessed_at)) AS qty
|
||||
FROM edu_access_logs
|
||||
WHERE accessed_at BETWEEN ? AND ?
|
||||
GROUP BY member_id, sys_comp_code
|
||||
) a ON u.member_id = a.member_id AND u.sys_comp_code = a.sys_comp_code
|
||||
WHERE 1=1
|
||||
AND (end_date IS NULL OR end_date > CURDATE())
|
||||
");
|
||||
$stmt_freq->execute([$p_fr_dt, $p_to_dt]);
|
||||
$response['data']['access_freq'] = $stmt_freq->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// 4. 접속 시간대
|
||||
$stmt_time = $pdo->prepare("
|
||||
SELECT
|
||||
SUM(CASE WHEN substring(accessed_at,12,5)>= '09:00' AND substring(accessed_at,12,5)<= '17:00' THEN 1 ELSE 0 END)-
|
||||
SUM(CASE WHEN substring(accessed_at,12,5)>= '11:30' AND substring(accessed_at,12,5)<= '13:30' THEN 1 ELSE 0 END) AS worktime
|
||||
, SUM(CASE WHEN substring(accessed_at,12,5)>= '11:30' AND substring(accessed_at,12,5)<= '13:30' THEN 1 ELSE 0 END) AS lunchtime
|
||||
, SUM(CASE WHEN substring(accessed_at,12,5) < '09:00' or substring(accessed_at,12,5) > '17:00' THEN 1 ELSE 0 END) AS outtime
|
||||
, SUM(CASE WHEN 1=1 THEN 1 ELSE 0 END) AS alltime
|
||||
FROM edu_access_logs
|
||||
WHERE 1=1
|
||||
AND accessed_at BETWEEN ? AND ?
|
||||
");
|
||||
$stmt_time->execute([$p_fr_dt_full, $p_to_dt_full]);
|
||||
$response['data']['access_time'] = $stmt_time->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// 5. 접속 방법
|
||||
$stmt_device = $pdo->prepare("
|
||||
SELECT
|
||||
SUM(CASE WHEN device_type = 'PC' THEN 1 ELSE 0 END) AS pc
|
||||
, SUM(CASE WHEN device_type = 'Mobile' THEN 1 ELSE 0 END) AS mobile
|
||||
, SUM(CASE WHEN 1=1 THEN 1 ELSE 0 END) AS alldevice
|
||||
FROM edu_access_logs
|
||||
WHERE 1=1
|
||||
AND accessed_at BETWEEN ? AND ?
|
||||
");
|
||||
$stmt_device->execute([$p_fr_dt_full, $p_to_dt_full]);
|
||||
$response['data']['access_device'] = $stmt_device->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// 6. 카테고리별 이용현황
|
||||
$stmt_usage = $pdo->prepare("
|
||||
SELECT
|
||||
SUM(CASE WHEN 1=1 THEN 1 ELSE 0 END) AS tot_qty
|
||||
, SUM(CASE WHEN a.category_code = 'CA10001' THEN 1 ELSE 0 END) AS myclass_use_qty
|
||||
, SUM(CASE WHEN a.category_code = 'CA10004' THEN 1 ELSE 0 END) AS leader_use_qty
|
||||
, SUM(CASE WHEN a.category_code = 'CA10005' THEN 1 ELSE 0 END) AS insight_use_qty
|
||||
, SUM(CASE WHEN a.category_code = 'CA10006' THEN 1 ELSE 0 END) AS biz_use_qty
|
||||
FROM edu_contents a
|
||||
JOIN edu_learning_histories b ON a.content_id = b.content_id
|
||||
WHERE 1=1
|
||||
AND b.last_viewed_at BETWEEN ? AND ?
|
||||
AND a.category_code IN('CA10001','CA10004','CA10005','CA10006')
|
||||
");
|
||||
$stmt_usage->execute([$p_fr_dt_full, $p_to_dt_full]);
|
||||
$response['data']['content_usage'] = $stmt_usage->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// 7. 이번분기 신규콘텐츠 등록수량
|
||||
$stmt_new = $pdo->prepare("
|
||||
SELECT
|
||||
IFNULL(SUM(category_code = 'CA10001'), 0) AS myclass_new_qty,
|
||||
IFNULL(SUM(category_code = 'CA10004'), 0) AS leader_new_qty,
|
||||
IFNULL(SUM(category_code = 'CA10005'), 0) AS insight_new_qty,
|
||||
IFNULL(SUM(category_code = 'CA10006'), 0) AS biz_new_qty
|
||||
FROM edu_contents
|
||||
WHERE created_at BETWEEN ? AND ?
|
||||
");
|
||||
$stmt_new->execute([$p_fr_dt_full, $p_to_dt_full]);
|
||||
$response['data']['new_content_qty'] = $stmt_new->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
// 8. 가장 많이 본 콘텐츠
|
||||
$stmt_popular = $pdo->prepare("
|
||||
SELECT
|
||||
b.category_code
|
||||
, fn_get_code_name(b.category_code) AS category_name
|
||||
, b.title AS content_title
|
||||
, COUNT(a.content_id) as view_count
|
||||
, SUM(CASE WHEN a.completed_at IS NOT NULL OR a.watch_tm/a.content_tm >= 0.7 THEN 1 ELSE 0 END)/COUNT(a.content_id)*100 AS completed_rate
|
||||
, c.comment_cnt
|
||||
FROM edu_learning_histories a
|
||||
JOIN edu_contents b ON a.content_id = b.content_id
|
||||
LEFT JOIN ( SELECT y.category_code , x.content_id , COUNT(0) AS comment_cnt
|
||||
FROM edu_comments x
|
||||
JOIN edu_contents y ON x.content_id = y.content_id
|
||||
WHERE x.created_at BETWEEN ? AND ?
|
||||
GROUP BY y.category_code , x.content_id) c ON a.content_id = c.content_id
|
||||
WHERE 1=1
|
||||
AND b.category_code IN('CA10001','CA10004','CA10005','CA10006')
|
||||
AND a.last_viewed_at BETWEEN ? AND ?
|
||||
GROUP BY b.category_code, b.content_id, b.title
|
||||
ORDER BY COUNT(a.content_id) DESC
|
||||
LIMIT 50
|
||||
");
|
||||
$stmt_popular->execute([$p_fr_dt_full, $p_to_dt_full, $p_fr_dt_full, $p_to_dt_full]);
|
||||
$response['data']['popular_contents'] = $stmt_popular->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
} catch (Throwable $e) {
|
||||
$response['success'] = false;
|
||||
$response['message'] = $e->getMessage();
|
||||
$response['trace'] = $e->getTraceAsString();
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
Reference in New Issue
Block a user