Initial commit: 교육 프로젝트 배포
This commit is contained in:
@@ -0,0 +1,268 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../db_conn.php';
|
||||
|
||||
function json_exit(array $payload, int $status = 200): void {
|
||||
http_response_code($status);
|
||||
echo json_encode($payload, JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
|
||||
function resolve_member_and_company(PDO $pdo): array {
|
||||
$sessionMemberId = trim((string)($_SESSION['ss_mb_id'] ?? $_SESSION['member_id'] ?? ''));
|
||||
$memberId = $sessionMemberId !== '' ? $sessionMemberId : 'U001';
|
||||
|
||||
$stmtUser = $pdo->prepare('SELECT sys_comp_code FROM edu_users WHERE member_id = ? ORDER BY sys_comp_code LIMIT 1');
|
||||
$stmtUser->execute([$memberId]);
|
||||
$sysCompCode = (string)($stmtUser->fetchColumn() ?: '');
|
||||
|
||||
if ($sysCompCode === '') {
|
||||
json_exit([
|
||||
'success' => false,
|
||||
'message' => 'edu_users에 회원 정보가 없어 마이클래스 상태를 조회할 수 없습니다.',
|
||||
'data' => ['member_id' => $memberId],
|
||||
], 400);
|
||||
}
|
||||
|
||||
return [$memberId, $sysCompCode];
|
||||
}
|
||||
|
||||
function ensure_goal_contents(PDO $pdo, string $goalCode, string $quarter, string $actor): int {
|
||||
$stmtCnt = $pdo->prepare("SELECT COUNT(*) FROM edu_goal_contents WHERE goal_code = ? AND (is_active = '1' OR is_active IS NULL)");
|
||||
$stmtCnt->execute([$goalCode]);
|
||||
$existing = (int)$stmtCnt->fetchColumn();
|
||||
if ($existing >= 6) {
|
||||
return $existing;
|
||||
}
|
||||
|
||||
$stmtCandidates = $pdo->prepare(
|
||||
"SELECT c.content_id
|
||||
FROM edu_contents c
|
||||
WHERE (c.is_active = '1' OR c.is_active IS NULL)
|
||||
AND (c.goal_code = :goal_code OR c.category_group = :quarter)
|
||||
ORDER BY
|
||||
CASE WHEN c.sort_order IS NULL THEN 1 ELSE 0 END,
|
||||
c.sort_order ASC,
|
||||
c.content_id ASC
|
||||
LIMIT 6"
|
||||
);
|
||||
$stmtCandidates->execute([
|
||||
':goal_code' => $goalCode,
|
||||
':quarter' => $quarter,
|
||||
]);
|
||||
$candidateIds = $stmtCandidates->fetchAll(PDO::FETCH_COLUMN);
|
||||
|
||||
if (count($candidateIds) < 6) {
|
||||
$stmtFallback = $pdo->prepare(
|
||||
"SELECT c.content_id
|
||||
FROM edu_contents c
|
||||
WHERE (c.is_active = '1' OR c.is_active IS NULL)
|
||||
ORDER BY
|
||||
CASE WHEN c.sort_order IS NULL THEN 1 ELSE 0 END,
|
||||
c.sort_order ASC,
|
||||
c.content_id ASC
|
||||
LIMIT 6"
|
||||
);
|
||||
$stmtFallback->execute();
|
||||
$candidateIds = $stmtFallback->fetchAll(PDO::FETCH_COLUMN);
|
||||
}
|
||||
|
||||
$candidateIds = array_values(array_unique(array_filter(array_map('strval', $candidateIds))));
|
||||
|
||||
$stmtUpsert = $pdo->prepare(
|
||||
"INSERT INTO edu_goal_contents
|
||||
(goal_code, content_id, index_id, is_active, sort_order, created_by, created_at, updated_by, updated_at)
|
||||
VALUES
|
||||
(?, ?, ?, '1', ?, ?, NOW(), ?, NOW())
|
||||
ON DUPLICATE KEY UPDATE
|
||||
is_active = VALUES(is_active),
|
||||
sort_order = VALUES(sort_order),
|
||||
updated_by = VALUES(updated_by),
|
||||
updated_at = NOW()"
|
||||
);
|
||||
|
||||
foreach ($candidateIds as $idx => $contentId) {
|
||||
$order = $idx + 1;
|
||||
$stmtUpsert->execute([$goalCode, $contentId, $order, $order, $actor, $actor]);
|
||||
}
|
||||
|
||||
$stmtCnt->execute([$goalCode]);
|
||||
return (int)$stmtCnt->fetchColumn();
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = db_conn();
|
||||
[$memberId, $sysCompCode] = resolve_member_and_company($pdo);
|
||||
|
||||
$stmtGoals = $pdo->query(
|
||||
"SELECT goal_code, title, quarter, goal_no, sort_order
|
||||
FROM edu_learning_goals
|
||||
WHERE (is_active = '1' OR is_active IS NULL)
|
||||
ORDER BY base_year DESC, quarter ASC, goal_no ASC, goal_code ASC"
|
||||
);
|
||||
$goals = $stmtGoals->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$goals) {
|
||||
json_exit(['success' => true, 'data' => ['goals' => [], 'videos' => []]]);
|
||||
}
|
||||
|
||||
$stmtSelected = $pdo->prepare(
|
||||
"SELECT ug.goal_code, ug.quarter, ug.completed_date, ug.updated_at, lg.title
|
||||
FROM edu_user_learning_goals ug
|
||||
LEFT JOIN edu_learning_goals lg ON lg.goal_code = ug.goal_code
|
||||
WHERE ug.member_id = ?
|
||||
AND ug.sys_comp_code = ?
|
||||
AND (ug.is_active = '1' OR ug.is_active IS NULL)
|
||||
ORDER BY ug.updated_at DESC, ug.goal_code DESC"
|
||||
);
|
||||
$stmtSelected->execute([$memberId, $sysCompCode]);
|
||||
$selectedGoals = $stmtSelected->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$requestedGoalCode = trim((string)($_GET['goal_code'] ?? ''));
|
||||
$activeGoalCode = $requestedGoalCode;
|
||||
if ($activeGoalCode === '' && !empty($selectedGoals)) {
|
||||
$activeGoalCode = (string)$selectedGoals[0]['goal_code'];
|
||||
}
|
||||
if ($activeGoalCode === '') {
|
||||
$activeGoalCode = (string)$goals[0]['goal_code'];
|
||||
}
|
||||
|
||||
$goalIndex = [];
|
||||
foreach ($goals as $g) {
|
||||
$goalIndex[(string)$g['goal_code']] = $g;
|
||||
}
|
||||
|
||||
if (!isset($goalIndex[$activeGoalCode])) {
|
||||
$activeGoalCode = (string)$goals[0]['goal_code'];
|
||||
}
|
||||
|
||||
$activeQuarter = (string)($goalIndex[$activeGoalCode]['quarter'] ?? '');
|
||||
ensure_goal_contents($pdo, $activeGoalCode, $activeQuarter, $memberId);
|
||||
|
||||
$stmtVideos = $pdo->prepare(
|
||||
"SELECT
|
||||
gc.goal_code,
|
||||
gc.content_id,
|
||||
gc.sort_order,
|
||||
gc.index_id,
|
||||
c.title,
|
||||
c.description,
|
||||
c.description2,
|
||||
c.content_url,
|
||||
c.thumbnail_url,
|
||||
c.category_code,
|
||||
c.category_group,
|
||||
lh.watch_tm,
|
||||
lh.content_tm,
|
||||
lh.completed_at
|
||||
FROM edu_goal_contents gc
|
||||
JOIN edu_contents c ON c.content_id = gc.content_id
|
||||
LEFT JOIN edu_learning_histories lh
|
||||
ON lh.member_id = ?
|
||||
AND lh.sys_comp_code = ?
|
||||
AND lh.content_id = gc.content_id
|
||||
WHERE gc.goal_code = ?
|
||||
AND (gc.is_active = '1' OR gc.is_active IS NULL)
|
||||
ORDER BY
|
||||
CASE WHEN gc.sort_order IS NULL THEN 1 ELSE 0 END,
|
||||
gc.sort_order ASC,
|
||||
CASE WHEN gc.index_id IS NULL THEN 1 ELSE 0 END,
|
||||
gc.index_id ASC,
|
||||
gc.content_id ASC
|
||||
LIMIT 6"
|
||||
);
|
||||
$stmtVideos->execute([$memberId, $sysCompCode, $activeGoalCode]);
|
||||
$videos = $stmtVideos->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$contentIds = array_values(array_unique(array_filter(array_map(static function ($r) {
|
||||
return (string)($r['content_id'] ?? '');
|
||||
}, $videos))));
|
||||
|
||||
$memoMap = [];
|
||||
if (!empty($contentIds)) {
|
||||
$in = implode(',', array_fill(0, count($contentIds), '?'));
|
||||
$stmtMemo = $pdo->prepare(
|
||||
"SELECT content_id, seq, title
|
||||
FROM edu_content_memos
|
||||
WHERE content_id IN ($in)
|
||||
AND (is_active = '1' OR is_active IS NULL)
|
||||
ORDER BY content_id ASC, seq ASC"
|
||||
);
|
||||
$stmtMemo->execute($contentIds);
|
||||
$memoRows = $stmtMemo->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach ($memoRows as $m) {
|
||||
$cid = (string)$m['content_id'];
|
||||
if (!isset($memoMap[$cid])) {
|
||||
$memoMap[$cid] = [];
|
||||
}
|
||||
$memoTitle = trim((string)($m['title'] ?? ''));
|
||||
if ($memoTitle !== '') {
|
||||
$memoMap[$cid][] = $memoTitle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($videos as $idx => $video) {
|
||||
$cid = (string)$video['content_id'];
|
||||
$videos[$idx]['memos'] = $memoMap[$cid] ?? [];
|
||||
$videos[$idx]['is_completed'] = !empty($video['completed_at']);
|
||||
$videos[$idx]['slot_no'] = $idx + 1;
|
||||
}
|
||||
|
||||
$stmtProgress = $pdo->prepare(
|
||||
"SELECT
|
||||
ug.goal_code,
|
||||
COUNT(gc.content_id) AS total_count,
|
||||
SUM(CASE WHEN lh.completed_at IS NOT NULL THEN 1 ELSE 0 END) AS completed_count
|
||||
FROM edu_user_learning_goals ug
|
||||
LEFT JOIN edu_goal_contents gc
|
||||
ON gc.goal_code = ug.goal_code
|
||||
AND (gc.is_active = '1' OR gc.is_active IS NULL)
|
||||
LEFT JOIN edu_learning_histories lh
|
||||
ON lh.member_id = ug.member_id
|
||||
AND lh.sys_comp_code = ug.sys_comp_code
|
||||
AND lh.content_id = gc.content_id
|
||||
WHERE ug.member_id = ?
|
||||
AND ug.sys_comp_code = ?
|
||||
AND (ug.is_active = '1' OR ug.is_active IS NULL)
|
||||
GROUP BY ug.goal_code"
|
||||
);
|
||||
$stmtProgress->execute([$memberId, $sysCompCode]);
|
||||
$progressRows = $stmtProgress->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$goalProgress = [];
|
||||
foreach ($progressRows as $row) {
|
||||
$total = (int)($row['total_count'] ?? 0);
|
||||
$completed = (int)($row['completed_count'] ?? 0);
|
||||
$goalProgress[(string)$row['goal_code']] = [
|
||||
'total_count' => $total,
|
||||
'completed_count' => $completed,
|
||||
'is_completed' => $total > 0 && $completed >= $total,
|
||||
];
|
||||
}
|
||||
|
||||
json_exit([
|
||||
'success' => true,
|
||||
'data' => [
|
||||
'member_id' => $memberId,
|
||||
'sys_comp_code' => $sysCompCode,
|
||||
'active_goal_code' => $activeGoalCode,
|
||||
'goals' => $goals,
|
||||
'selected_goals' => $selectedGoals,
|
||||
'goal_progress' => $goalProgress,
|
||||
'videos' => $videos,
|
||||
],
|
||||
]);
|
||||
} catch (Throwable $e) {
|
||||
json_exit([
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
Reference in New Issue
Block a user