Initial commit: 교육 프로젝트 배포

This commit is contained in:
송대일
2026-07-01 18:32:42 +09:00
commit be6dccd120
1483 changed files with 5082202 additions and 0 deletions
+214
View File
@@ -0,0 +1,214 @@
<?php
/**
* get_legal_cert_print.php - 수료증 정보 조회 API
*/
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
header('Content-Type: application/json; charset=utf-8');
require_once __DIR__ . '/../../bbs/db_conn.php';
require_once __DIR__ . '/../../bbs/auth.php';
edu_require_login();
$year = $_GET['year'] ?? $_GET['_YEAR'] ?? '';
$comp = $_GET['comp'] ?? $_GET['_COMP'] ?? '';
$member_id = $_GET['member_id'] ?? $_GET['_MEMBER_ID'] ?? '';
$category_group = $_GET['category_group'] ?? $_GET['_CATEGORY_GROUP'] ?? '';
if (empty($year) || empty($comp) || empty($member_id) || empty($category_group)) {
echo json_encode([
'success' => false,
'message' => '필수 파라미터가 부족합니다. (year, comp, member_id, category_group)'
], JSON_UNESCAPED_UNICODE);
exit;
}
try {
$pdo = db_conn();
$category_groups = explode(',', $category_group);
$decodedItems = [];
$calls_log = [];
foreach ($category_groups as $cat) {
$cat = trim($cat);
if (empty($cat))
continue;
$member_ids = [];
if ($member_id === 'ALL') {
// 1. Get total active legal contents count for the category group
$stmt_cnt = $pdo->prepare("
SELECT COUNT(0) AS cnt
FROM edu_contents
WHERE base_year = ?
AND category_code = 'CA10003'
AND category_group = ?
AND is_active = '1';
");
$stmt_cnt->execute([$year, $cat]);
$total_legal_cnt = (int)$stmt_cnt->fetchColumn();
if ($total_legal_cnt > 0) {
// 2. Query completed users using the SQL logic from 개발.md
$stmt_users = $pdo->prepare("
SELECT b.member_id
FROM edu_learning_histories b
INNER JOIN edu_contents a ON a.content_id = b.content_id
INNER JOIN edu_users c ON b.member_id = c.member_id AND b.sys_comp_code = c.sys_comp_code
WHERE a.base_year = ?
AND a.category_code = 'CA10003'
AND a.is_active = '1'
AND b.completed_at IS NOT NULL
AND a.category_group = ?
AND (? = '' OR c.belong_comp = ?)
GROUP BY b.member_id, c.belong_comp
HAVING COUNT(b.content_id) = ?;
");
$stmt_users->execute([$year, $cat, $comp, $comp, $total_legal_cnt]);
$member_ids = $stmt_users->fetchAll(PDO::FETCH_COLUMN);
}
} else {
$member_ids = [$member_id];
}
foreach ($member_ids as $m_id) {
$calls_log[] = [
'proc' => 'proc_get_legal_education_certificate',
'params' => [
'year' => $year,
'comp' => $comp,
'member_id' => $m_id,
'category_group' => $cat
]
];
$stmt = $pdo->prepare("CALL proc_get_legal_education_certificate(?, ?, ?, ?);");
$stmt->execute([
$year,
$comp,
$m_id,
$cat
]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
while ($stmt->nextRowset()) {
} // 소진
if ($row) {
$decodedRow = [];
foreach ($row as $key => $val) {
$decodedKey = strtolower($key);
if (is_object($val) && isset($val->type) && $val->type === 'Buffer') {
$decodedRow[$decodedKey] = pack('C*', ...$val->data);
} else {
$decodedRow[$decodedKey] = $val;
}
}
// 각 아이템별 동적 스탬프 및 로고 워터마크 이미지 검증 (admin/file 경로 우선, 기존 img 경로 차선 Fallback)
$belong_comp_code = $decodedRow['belong_comp_code'] ?? $decodedRow['sys_comp_code'] ?? $comp;
$logo_url = "";
$stamp_url = "";
if (!empty($belong_comp_code)) {
// /www/admin/file/logo 및 /www/admin/file/stamp 컨테이너 내 절대 파일 경로
$abs_logo_svg = '/www/admin/file/logo/' . $belong_comp_code . '_logo.svg';
$abs_logo_png = '/www/admin/file/logo/' . $belong_comp_code . '_logo.png';
$abs_stamp_svg = '/www/admin/file/stamp/' . $belong_comp_code . '_stamp.svg';
$abs_stamp_png = '/www/admin/file/stamp/' . $belong_comp_code . '_stamp.png';
// 로컬 상대 파일 경로 (__DIR__ 기준 fallback)
$admin_logo_svg = __DIR__ . '/../file/logo/' . $belong_comp_code . '_logo.svg';
$admin_logo_png = __DIR__ . '/../file/logo/' . $belong_comp_code . '_logo.png';
$admin_stamp_svg = __DIR__ . '/../file/stamp/' . $belong_comp_code . '_stamp.svg';
$admin_stamp_png = __DIR__ . '/../file/stamp/' . $belong_comp_code . '_stamp.png';
// 기존 img/ 절대 파일 경로
$img_logo_svg = __DIR__ . '/../../img/' . $belong_comp_code . '_logo.svg';
$img_logo_png = __DIR__ . '/../../img/' . $belong_comp_code . '_logo.png';
$img_stamp_svg = __DIR__ . '/../../img/' . $belong_comp_code . '_stamp.svg';
$img_stamp_png = __DIR__ . '/../../img/' . $belong_comp_code . '_stamp.png';
// 로고 매핑 (절대경로 및 로컬경로 존재 확인 후 웹 URL 설정 - /admin/file/logo/ 우선)
if (file_exists($abs_logo_svg)) {
$logo_url = "/admin/file/logo/" . $belong_comp_code . "_logo.svg";
} elseif (file_exists($admin_logo_svg)) {
$logo_url = "/admin/file/logo/" . $belong_comp_code . "_logo.svg";
} elseif (file_exists($abs_logo_png)) {
$logo_url = "/admin/file/logo/" . $belong_comp_code . "_logo.png";
} elseif (file_exists($admin_logo_png)) {
$logo_url = "/admin/file/logo/" . $belong_comp_code . "_logo.png";
} elseif (file_exists($img_logo_svg)) {
$logo_url = "/img/" . $belong_comp_code . "_logo.svg";
} elseif (file_exists($img_logo_png)) {
$logo_url = "/img/" . $belong_comp_code . "_logo.png";
}
// 직인 매핑 (절대경로 및 로컬경로 존재 확인 후 웹 URL 설정 - /admin/file/stamp/ 우선)
if (file_exists($abs_stamp_svg)) {
$stamp_url = "/admin/file/stamp/" . $belong_comp_code . "_stamp.svg";
} elseif (file_exists($admin_stamp_svg)) {
$stamp_url = "/admin/file/stamp/" . $belong_comp_code . "_stamp.svg";
} elseif (file_exists($abs_stamp_png)) {
$stamp_url = "/admin/file/stamp/" . $belong_comp_code . "_stamp.png";
} elseif (file_exists($admin_stamp_png)) {
$stamp_url = "/admin/file/stamp/" . $belong_comp_code . "_stamp.png";
} elseif (file_exists($img_stamp_svg)) {
$stamp_url = "/img/" . $belong_comp_code . "_stamp.svg";
} elseif (file_exists($img_stamp_png)) {
$stamp_url = "/img/" . $belong_comp_code . "_stamp.png";
}
}
$decodedRow['logo_url'] = $logo_url;
$decodedRow['stamp_url'] = $stamp_url;
$decodedItems[] = $decodedRow;
}
}
}
if (empty($decodedItems)) {
echo json_encode([
'success' => false,
'message' => '해당 조건의 수료 정보가 존재하지 않습니다.',
'debug' => [
'api_params' => [
'year' => $year,
'comp' => $comp,
'member_id' => $member_id,
'category_group' => $category_group
],
'processed_categories' => $category_groups,
'total_legal_cnt' => $total_legal_cnt ?? null,
'matched_member_ids' => $member_ids ?? [],
'procedure_calls' => $calls_log,
'step_info' => 'No certificates could be loaded or formatted.'
]
], JSON_UNESCAPED_UNICODE);
exit;
}
echo json_encode([
'success' => true,
'data' => $decodedItems,
'debug' => [
'procedure_calls' => $calls_log
]
], JSON_UNESCAPED_UNICODE);
} catch (Exception $e) {
error_log('[get_legal_cert_print] Error: ' . $e->getMessage());
echo json_encode([
'success' => false,
'message' => '서버 내부 오류가 발생했습니다.',
'detail' => $e->getMessage(),
'debug' => [
'procedure_calls' => $calls_log ?? []
]
], JSON_UNESCAPED_UNICODE);
exit;
}