commit
This commit is contained in:
1
kngil/bbs/.htaccess
Normal file
1
kngil/bbs/.htaccess
Normal file
@@ -0,0 +1 @@
|
||||
Options -Indexes
|
||||
165
kngil/bbs/adm.php
Normal file
165
kngil/bbs/adm.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/db_conn.php';
|
||||
|
||||
/* =================================================
|
||||
0. 로그인 / 권한 체크
|
||||
================================================= */
|
||||
if (!isset($_SESSION['login'])) {
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => '로그인이 필요합니다.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$auth = $_SESSION['login']['auth_bc'] ?? '';
|
||||
|
||||
if (!in_array($auth, ['BS100100', 'BS100200'])) {
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => '접근 권한이 없습니다.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =================================================
|
||||
공통 입력
|
||||
================================================= */
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?? [];
|
||||
$action = $_GET['action'] ?? $input['action'] ?? 'list';
|
||||
|
||||
try {
|
||||
|
||||
switch ($action) {
|
||||
|
||||
case 'user_list':
|
||||
|
||||
// 🔥 상단에서 선택한 회사
|
||||
$target_member_id = $_GET['member_id'] ?? '';
|
||||
|
||||
if (!$target_member_id) {
|
||||
throw new Exception('member_id 누락');
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT *
|
||||
FROM kngil.sp_users_r(
|
||||
:member_id,
|
||||
'',
|
||||
'',
|
||||
''
|
||||
)
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
':member_id' => $target_member_id
|
||||
]);
|
||||
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
foreach ($rows as $i => &$r) {
|
||||
$r['recid'] = $i + 1;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'records' => $rows
|
||||
]);
|
||||
break;
|
||||
|
||||
/* =================================================
|
||||
1. 통합 회원 목록 조회
|
||||
- 모든 회사(member) 조회
|
||||
================================================= */
|
||||
case 'list':
|
||||
|
||||
$sql = "SELECT * FROM kngil.sp_member_sys_r('', '', '');";
|
||||
$rows = $pdo->query($sql)->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$i = 1;
|
||||
foreach ($rows as &$r) {
|
||||
$r['recid'] = $i++;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'records' => $rows
|
||||
]);
|
||||
break;
|
||||
|
||||
/* =================================================
|
||||
2. 회원 정보 수정 (회사 단위)
|
||||
- tel / email / 사업자번호 / 회사명
|
||||
================================================= */
|
||||
case 'save':
|
||||
|
||||
$updates = $input['updates'] ?? [];
|
||||
if (!$updates) {
|
||||
throw new Exception('저장할 데이터가 없습니다.');
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
$stmtU = $pdo->prepare("
|
||||
SELECT kngil.sp_member_sys_u(
|
||||
:member_id::varchar,
|
||||
:tel_no::varchar,
|
||||
:email::varchar,
|
||||
:bs_no::varchar,
|
||||
:co_nm::varchar,
|
||||
:mid::varchar
|
||||
) AS result
|
||||
");
|
||||
|
||||
foreach ($updates as $r) {
|
||||
|
||||
if (empty($r['member_id'])) {
|
||||
throw new Exception('member_id 누락');
|
||||
}
|
||||
|
||||
$stmtU->execute([
|
||||
':member_id' => $r['member_id'],
|
||||
':tel_no' => $r['tel_no'] ?? null,
|
||||
':email' => $r['email'] ?? null,
|
||||
':bs_no' => $r['bs_no'] ?? null,
|
||||
':co_nm' => $r['co_nm'] ?? null,
|
||||
':mid' => $_SESSION['login']['user_id']
|
||||
]);
|
||||
|
||||
$result = $stmtU->fetchColumn();
|
||||
|
||||
if (strpos($result, 'ERROR') === 0) {
|
||||
throw new Exception($result);
|
||||
}
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success'
|
||||
]);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception('Invalid action');
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
261
kngil/bbs/adm_comp copy.php
Normal file
261
kngil/bbs/adm_comp copy.php
Normal file
@@ -0,0 +1,261 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
/* =========================
|
||||
로그인 / 권한 가드
|
||||
========================= */
|
||||
require_once __DIR__ . '/adm_guard.php';
|
||||
require_once __DIR__ . '/db_conn.php';
|
||||
|
||||
/* =========================
|
||||
세션 기준 값 (중요)
|
||||
========================= */
|
||||
$login = $_SESSION['login'];
|
||||
$auth_bc = $login['auth_bc']; // 권한코드
|
||||
$member_id = $login['member_id']; // 회사ID
|
||||
|
||||
/* =========================
|
||||
입력
|
||||
========================= */
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?? [];
|
||||
$action = $_GET['action'] ?? $input['action'] ?? 'list';
|
||||
|
||||
/* =========================
|
||||
권한 플래그
|
||||
========================= */
|
||||
$isAdmin = in_array($auth_bc, ['BS100100','BS100200','BS100300'], true);
|
||||
|
||||
try {
|
||||
|
||||
switch ($action) {
|
||||
|
||||
/* =========================
|
||||
0. 공통코드 조회 (콤보)
|
||||
========================= */
|
||||
case 'base_code':
|
||||
|
||||
$main_cd = $_GET['main_cd'] ?? $input['main_cd'] ?? '';
|
||||
|
||||
if (!$main_cd) {
|
||||
throw new Exception('main_cd가 필요합니다.');
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT *
|
||||
FROM kngil.fn_base_cd(:main_cd)
|
||||
");
|
||||
$stmt->execute([
|
||||
':main_cd' => $main_cd
|
||||
]);
|
||||
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'items' => $rows // [{id, text}]
|
||||
]);
|
||||
break;
|
||||
|
||||
|
||||
/* =========================
|
||||
1. 사용자 목록 조회
|
||||
========================= */
|
||||
case 'list':
|
||||
|
||||
$schType = $_GET['sch_type'] ?? '';
|
||||
$schKeyword = $_GET['sch_keyword'] ?? '';
|
||||
$schUseYn = $_GET['sch_use_yn'] ?? '';
|
||||
|
||||
// 기본값
|
||||
$sch_id = '';
|
||||
$sch_nm = '';
|
||||
$sch_dept = '';
|
||||
|
||||
if ($schKeyword !== '') {
|
||||
switch ($schType) {
|
||||
case 'id':
|
||||
$sch_id = $schKeyword;
|
||||
break;
|
||||
case 'name':
|
||||
$sch_nm = $schKeyword;
|
||||
break;
|
||||
case 'dept':
|
||||
$sch_dept = $schKeyword;
|
||||
break;
|
||||
|
||||
default: // 전체
|
||||
$sch_id = $schKeyword;
|
||||
$sch_nm = $schKeyword;
|
||||
$sch_dept = $schKeyword;
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "
|
||||
SELECT *
|
||||
FROM kngil.sp_users_r(
|
||||
:member_id,
|
||||
:user_nm,
|
||||
:dept_nm,
|
||||
:use_yn
|
||||
);
|
||||
";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([
|
||||
':member_id' => $member_id,
|
||||
':user_nm' => $_GET['user_nm'] ?? '',
|
||||
':dept_nm' => $_GET['dept_nm'] ?? '',
|
||||
':use_yn' => $_GET['use_yn'] ?? ''
|
||||
]);
|
||||
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$i = 1;
|
||||
foreach ($rows as &$r) {
|
||||
$r['recid'] = $i++;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'member_id' => $member_id,
|
||||
'records' => $rows
|
||||
]);
|
||||
break;
|
||||
|
||||
|
||||
/* =========================
|
||||
2. 사용자 저장
|
||||
========================= */
|
||||
case 'save':
|
||||
|
||||
$inserts = $input['inserts'] ?? [];
|
||||
$updates = $input['updates'] ?? [];
|
||||
|
||||
if (!$inserts && !$updates) {
|
||||
throw new Exception('저장할 데이터가 없습니다.');
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// INSERT
|
||||
if ($inserts) {
|
||||
$stmtI = $pdo->prepare("
|
||||
SELECT kngil.sp_users_i(
|
||||
:member_id,:user_id,:user_pw,:user_nm,:dept_nm,
|
||||
:posit_nm,:tel_no,:email,:auth_bc,:use_yn,:rmks,:cid
|
||||
)
|
||||
");
|
||||
|
||||
foreach ($inserts as $r) {
|
||||
$stmtI->execute([
|
||||
':member_id' => $member_id,
|
||||
':user_id' => $r['user_id'],
|
||||
':user_pw' => $r['user_pw'] ?? '0000',
|
||||
':user_nm' => $r['user_nm'],
|
||||
':dept_nm' => $r['dept_nm'],
|
||||
':posit_nm' => $r['posit_nm'] ?? '',
|
||||
':tel_no' => $r['tel_no'],
|
||||
':email' => $r['email'],
|
||||
':auth_bc' => $r['auth_bc'],
|
||||
':use_yn' => $r['use_yn'],
|
||||
':rmks' => $r['rmks'] ?? '',
|
||||
':cid' => $r['cid'] ?? 'SYSTEM'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// UPDATE
|
||||
if ($updates) {
|
||||
$stmtU = $pdo->prepare("
|
||||
SELECT kngil.sp_users_u(
|
||||
:member_id,:user_id,:user_pw,:user_nm,:dept_nm,
|
||||
:posit_nm,:tel_no,:email,:auth_bc,:use_yn,:rmks,:mid
|
||||
)
|
||||
");
|
||||
|
||||
foreach ($updates as $r) {
|
||||
$stmtU->execute([
|
||||
':member_id' => $member_id,
|
||||
':user_id' => $r['user_id'],
|
||||
':user_pw' => null,
|
||||
':user_nm' => $r['user_nm'],
|
||||
':dept_nm' => $r['dept_nm'],
|
||||
':posit_nm' => $r['posit_nm'] ?? '',
|
||||
':tel_no' => $r['tel_no'],
|
||||
':email' => $r['email'],
|
||||
':auth_bc' => $r['auth_bc'],
|
||||
':use_yn' => $r['use_yn'],
|
||||
':rmks' => $r['rmks'] ?? '',
|
||||
':mid' => $r['mid'] ?? 'SYSTEM'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
echo json_encode(['status'=>'success']);
|
||||
break;
|
||||
|
||||
|
||||
|
||||
/* =========================
|
||||
3. 사용자 삭제 (비활성)
|
||||
========================= */
|
||||
case 'delete':
|
||||
|
||||
$ids = $input['ids'] ?? [];
|
||||
if (!$ids) throw new Exception('삭제 대상이 없습니다.');
|
||||
|
||||
$sql = "SELECT kngil.sp_users_d(:member_id, :user_id)";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
foreach ($ids as $uid) {
|
||||
$stmt->execute([
|
||||
':member_id' => $member_id,
|
||||
':user_id' => $uid
|
||||
]);
|
||||
}
|
||||
|
||||
echo json_encode(['status'=>'success']);
|
||||
break;
|
||||
/* =========================
|
||||
4. 회원 총 구매 면적 조회
|
||||
========================= */
|
||||
case 'total_area':
|
||||
|
||||
$sql = "
|
||||
SELECT COALESCE(SUM(sum_area), 0) AS total_area
|
||||
FROM kngil.sp_buy_item_history_r(:member_id, '', NULL, NULL)
|
||||
";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([
|
||||
':member_id' => $member_id
|
||||
]);
|
||||
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'member_id' => $member_id,
|
||||
'total_area' => (int)$row['total_area']
|
||||
]);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception('잘못된 요청');
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
393
kngil/bbs/adm_comp.php
Normal file
393
kngil/bbs/adm_comp.php
Normal file
@@ -0,0 +1,393 @@
|
||||
<?php
|
||||
ini_set('display_errors', 0);
|
||||
error_reporting(0);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
/* =========================
|
||||
로그인 / 권한 가드
|
||||
========================= */
|
||||
require_once __DIR__ . '/adm_guard.php';
|
||||
require_once __DIR__ . '/db_conn.php';
|
||||
|
||||
/* =========================
|
||||
세션 기준 값
|
||||
========================= */
|
||||
$login = $_SESSION['login'];
|
||||
$auth_bc = $login['auth_bc']; // 권한코드
|
||||
$member_id = $login['member_id']; // 회사ID
|
||||
$user_id = $login['user_id'] ?? 'SYSTEM';
|
||||
|
||||
/* =========================
|
||||
권한 정의 (단순화 버전)
|
||||
========================= */
|
||||
$isAdmin = in_array(
|
||||
$auth_bc,
|
||||
['BS100100','BS100200','BS100300','BS100400'],
|
||||
true
|
||||
);
|
||||
|
||||
/* =========================
|
||||
입력
|
||||
========================= */
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?? [];
|
||||
$action = $_GET['action'] ?? $input['action'] ?? 'list';
|
||||
|
||||
try {
|
||||
|
||||
switch ($action) {
|
||||
|
||||
/* =========================
|
||||
0. 공통코드 조회
|
||||
========================= */
|
||||
case 'base_code':
|
||||
|
||||
$main_cd = $_GET['main_cd'] ?? $input['main_cd'] ?? '';
|
||||
if (!$main_cd) {
|
||||
throw new Exception('main_cd가 필요합니다.');
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT *
|
||||
FROM kngil.fn_base_cd(:main_cd)
|
||||
");
|
||||
$stmt->execute([':main_cd' => $main_cd]);
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'items' => $stmt->fetchAll(PDO::FETCH_ASSOC)
|
||||
]);
|
||||
break;
|
||||
|
||||
/* =========================
|
||||
1. 사용자 목록 조회
|
||||
========================= */
|
||||
case 'list':
|
||||
|
||||
// 조회 대상 member_id 결정
|
||||
$target_member_id = $member_id; // 기본: 세션 기준
|
||||
|
||||
// 관리자 / 개발자만 GET member_id 허용
|
||||
if ($isAdmin && !empty($_GET['member_id'])) {
|
||||
$target_member_id = $_GET['member_id'];
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT *
|
||||
FROM kngil.sp_users_r(
|
||||
:member_id,
|
||||
:user_nm,
|
||||
:dept_nm,
|
||||
:use_yn
|
||||
)
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
':member_id' => $target_member_id,
|
||||
':user_nm' => $_GET['user_nm'] ?? '',
|
||||
':dept_nm' => $_GET['dept_nm'] ?? '',
|
||||
':use_yn' => $_GET['use_yn'] ?? ''
|
||||
]);
|
||||
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
foreach ($rows as $i => &$r) {
|
||||
$r['recid'] = $i + 1;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'member_id' => $target_member_id,
|
||||
'records' => $rows
|
||||
]);
|
||||
break;
|
||||
|
||||
/* =========================
|
||||
2. 사용자 저장
|
||||
========================= */
|
||||
case 'save':
|
||||
|
||||
if (!$isAdmin) {
|
||||
throw new Exception('저장 권한이 없습니다.');
|
||||
}
|
||||
|
||||
$inserts = $input['inserts'] ?? [];
|
||||
$updates = $input['updates'] ?? [];
|
||||
|
||||
if (!$inserts && !$updates) {
|
||||
throw new Exception('저장할 데이터가 없습니다.');
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
/* ---------- INSERT ---------- */
|
||||
if ($inserts) {
|
||||
|
||||
$stmtI = $pdo->prepare("
|
||||
SELECT kngil.sp_users_i(
|
||||
:member_id,:user_id,:user_pw,:user_nm,:dept_nm,
|
||||
:posit_nm,:tel_no,:email,:auth_bc,:use_yn,:rmks,:cid
|
||||
)
|
||||
");
|
||||
|
||||
foreach ($inserts as $r) {
|
||||
$stmtI->execute([
|
||||
':member_id' => $member_id,
|
||||
':user_id' => $r['user_id'],
|
||||
':user_pw' => $r['user_pw'] ?? '0000',
|
||||
':user_nm' => $r['user_nm'],
|
||||
':dept_nm' => $r['dept_nm'],
|
||||
':posit_nm' => $r['posit_nm'] ?? '',
|
||||
':tel_no' => $r['tel_no'],
|
||||
':email' => $r['email'],
|
||||
':auth_bc' => is_array($r['auth_bc'])
|
||||
? ($r['auth_bc']['id'] ?? '')
|
||||
: $r['auth_bc'],
|
||||
':use_yn' => is_array($r['use_yn'])
|
||||
? ($r['use_yn']['id'] ?? 'Y')
|
||||
: $r['use_yn'],
|
||||
':rmks' => $r['rmks'] ?? '',
|
||||
':cid' => $user_id
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- UPDATE ---------- */
|
||||
if ($updates) {
|
||||
|
||||
$stmtChk = $pdo->prepare("
|
||||
SELECT 1
|
||||
FROM kngil.users
|
||||
WHERE member_id = :member_id
|
||||
AND user_id = :user_id
|
||||
");
|
||||
|
||||
$stmtU = $pdo->prepare("
|
||||
SELECT kngil.sp_users_u(
|
||||
:member_id,:user_id,NULL,:user_nm,:dept_nm,
|
||||
:posit_nm,:tel_no,:email,:auth_bc,:use_yn,:rmks,:mid
|
||||
)
|
||||
");
|
||||
|
||||
foreach ($updates as $r) {
|
||||
|
||||
// 회사 탈출 방지
|
||||
$stmtChk->execute([
|
||||
':member_id' => $member_id,
|
||||
':user_id' => $r['user_id']
|
||||
]);
|
||||
|
||||
if (!$stmtChk->fetchColumn()) {
|
||||
throw new Exception('권한 없는 사용자 수정 시도');
|
||||
}
|
||||
|
||||
$stmtU->execute([
|
||||
':member_id' => $member_id,
|
||||
':user_id' => $r['user_id'],
|
||||
':user_nm' => $r['user_nm'],
|
||||
':dept_nm' => $r['dept_nm'],
|
||||
':posit_nm' => $r['posit_nm'] ?? '',
|
||||
':tel_no' => $r['tel_no'],
|
||||
':email' => $r['email'],
|
||||
':auth_bc' => $r['auth_bc'],
|
||||
':use_yn' => $r['use_yn'],
|
||||
':rmks' => $r['rmks'] ?? '',
|
||||
':mid' => $user_id
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
echo json_encode(['status' => 'success']);
|
||||
break;
|
||||
|
||||
/* =========================
|
||||
3. 사용자 삭제 (비활성)
|
||||
========================= */
|
||||
case 'delete':
|
||||
|
||||
if (!$isAdmin) {
|
||||
throw new Exception('삭제 권한이 없습니다.');
|
||||
}
|
||||
|
||||
$ids = $input['ids'] ?? [];
|
||||
if (!$ids) {
|
||||
throw new Exception('삭제 대상이 없습니다.');
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT kngil.sp_users_d(:member_id, :user_id)
|
||||
");
|
||||
|
||||
foreach ($ids as $uid) {
|
||||
$stmt->execute([
|
||||
':member_id' => $member_id,
|
||||
':user_id' => $uid
|
||||
]);
|
||||
}
|
||||
|
||||
echo json_encode(['status' => 'success']);
|
||||
break;
|
||||
|
||||
/* =========================
|
||||
4. 회원 총 구매 면적
|
||||
========================= */
|
||||
case 'total_area':
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT COALESCE(SUM(sum_area),0)
|
||||
FROM kngil.sp_buy_item_history_r(:member_id, '', NULL, NULL)
|
||||
");
|
||||
$stmt->execute([':member_id' => $member_id]);
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'total_area' => (int)$stmt->fetchColumn()
|
||||
]);
|
||||
break;
|
||||
|
||||
/* =========================
|
||||
5. CSV 일괄 계정생성
|
||||
========================= */
|
||||
|
||||
|
||||
case 'bulk_create':
|
||||
|
||||
if (!$isAdmin) {
|
||||
throw new Exception('일괄 생성 권한이 없습니다.');
|
||||
}
|
||||
|
||||
$target_member_id = $input['member_id'] ?? '';
|
||||
$csv_url = $input['csv_url'] ?? '';
|
||||
|
||||
if (!$target_member_id || !$csv_url) {
|
||||
throw new Exception('필수 파라미터 누락');
|
||||
}
|
||||
|
||||
// CSV 다운로드
|
||||
$csv = @file_get_contents($csv_url);
|
||||
if ($csv === false) {
|
||||
throw new Exception('CSV 파일을 불러올 수 없습니다.');
|
||||
}
|
||||
|
||||
$lines = array_map('str_getcsv', explode("\n", trim($csv)));
|
||||
|
||||
// 헤더 제거 (첫 줄)
|
||||
array_shift($lines);
|
||||
|
||||
$success = 0;
|
||||
$fail = 0;
|
||||
$errors = [];
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT kngil.sp_users_i(
|
||||
:member_id,:user_id,:user_pw,:user_nm,:dept_nm,
|
||||
'',:tel_no,:email,:auth_bc,:use_yn,'',
|
||||
:cid
|
||||
)
|
||||
");
|
||||
|
||||
foreach ($lines as $i => $row) {
|
||||
|
||||
if (count($row) < 8) {
|
||||
$fail++;
|
||||
$errors[] = "라인 ".($i+2).": 컬럼 수 부족";
|
||||
continue;
|
||||
}
|
||||
|
||||
[
|
||||
$user_id,
|
||||
$user_pw,
|
||||
$user_nm,
|
||||
$tel_no,
|
||||
$email,
|
||||
$dept_nm,
|
||||
$use_txt,
|
||||
$auth_txt
|
||||
] = array_map('trim', $row);
|
||||
|
||||
/* ---------- 값 정규화 ---------- */
|
||||
|
||||
$use_yn = 'Y'; // 항상 사용
|
||||
$auth_bc = 'BS100500'; // 일반 권한
|
||||
|
||||
/* ---------- 중복 체크 ---------- */
|
||||
|
||||
// ID 중복 (대소문자 무시)
|
||||
$chk = $pdo->prepare("
|
||||
SELECT 1 FROM kngil.users
|
||||
WHERE LOWER(user_id) = LOWER(:uid)
|
||||
");
|
||||
$chk->execute([':uid' => $user_id]);
|
||||
if ($chk->fetchColumn()) {
|
||||
$fail++;
|
||||
$errors[] = "라인 ".($i+2).": ID 중복 ($user_id)";
|
||||
continue;
|
||||
}
|
||||
|
||||
// 전화번호 중복
|
||||
$chk = $pdo->prepare("
|
||||
SELECT 1 FROM kngil.users
|
||||
WHERE tel_no = :tel
|
||||
");
|
||||
$chk->execute([':tel' => $tel_no]);
|
||||
if ($chk->fetchColumn()) {
|
||||
$fail++;
|
||||
$errors[] = "라인 ".($i+2).": 연락처 중복 ($tel_no)";
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ---------- 프로시저 호출 ---------- */
|
||||
try {
|
||||
$stmt->execute([
|
||||
':member_id' => $target_member_id,
|
||||
':user_id' => $user_id,
|
||||
':user_pw' => $user_pw ?: '0000',
|
||||
':user_nm' => $user_nm,
|
||||
':dept_nm' => $dept_nm,
|
||||
':tel_no' => $tel_no,
|
||||
':email' => $email,
|
||||
':auth_bc' => $auth_bc,
|
||||
':use_yn' => $use_yn,
|
||||
':cid' => $user_id // 생성자
|
||||
]);
|
||||
$result = $stmt->fetchColumn(); // ⭐ 필수
|
||||
|
||||
if ($result !== 'SUCCESS') {
|
||||
$fail++;
|
||||
$errors[] = "라인 ".($i+2).": ".$result;
|
||||
continue;
|
||||
}
|
||||
|
||||
$success++;
|
||||
|
||||
} catch (Exception $e) {
|
||||
$fail++;
|
||||
$errors[] = "라인 ".($i+2).": ".$e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'success_cnt' => $success,
|
||||
'fail_cnt' => $fail,
|
||||
'errors' => $errors
|
||||
]);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
throw new Exception('잘못된 요청');
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
27
kngil/bbs/adm_faq_popup.php
Normal file
27
kngil/bbs/adm_faq_popup.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
// 1. DB 연결 (절대 경로 혹은 상대 경로 확인)
|
||||
require_once 'db_conn.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
try {
|
||||
// 2. 프로시저 호출 (컬럼명: itm_cd, itm_nm, area, itm_amt 등)
|
||||
$stmt = $pdo->prepare("SELECT * FROM kngil.sp_fa_comments_r()");
|
||||
$stmt->execute();
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// 3. W2UI를 위해 각 행에 'recid' 필드 강제 주입
|
||||
$records = [];
|
||||
foreach ($rows as $row) {
|
||||
$row['recid'] = $row['fa_id']; // 상품코드를 고유 키로 지정
|
||||
$records[] = $row;
|
||||
}
|
||||
|
||||
// 4. 순수 JSON만 출력 (다른 echo나 공백이 섞이면 에러 발생)
|
||||
echo json_encode($records);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
// 에러 발생 시 그리드가 이해할 수 있게 JSON으로 출력
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
?>
|
||||
58
kngil/bbs/adm_faq_popup_delete.php
Normal file
58
kngil/bbs/adm_faq_popup_delete.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
/* =========================
|
||||
로그인 / 권한 가드
|
||||
========================= */
|
||||
require_once __DIR__ . '/adm_guard.php';
|
||||
require_once __DIR__ . '/db_conn.php';
|
||||
|
||||
/* =========================
|
||||
세션 기준 값
|
||||
========================= */
|
||||
$login = $_SESSION['login'];
|
||||
$auth_bc = $login['auth_bc']; // 권한코드
|
||||
$member_id = $login['member_id']; // 회사ID
|
||||
$user_id = $login['user_id'] ?? 'SYSTEM';
|
||||
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// JSON 데이터 읽기
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
try {
|
||||
// 2. $pdo 변수가 있는지 확인 (DB 연결 확인)
|
||||
if (!isset($pdo)) {
|
||||
throw new Exception('데이터베이스 연결 설정($pdo)을 찾을 수 없습니다.');
|
||||
}
|
||||
|
||||
$ids = $input['ids'] ?? [];
|
||||
if (empty($ids)) {
|
||||
throw new Exception('삭제 대상이 없습니다.');
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// 3. 삭제 실행
|
||||
$stmt = $pdo->prepare("SELECT kngil.sp_fa_comments_d(:fa_id)");
|
||||
|
||||
foreach ($ids as $code) {
|
||||
$stmt->execute([':fa_id' => $code]);
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
echo json_encode(['status' => 'success']);
|
||||
|
||||
} catch (Exception $e) {
|
||||
if (isset($pdo) && $pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
// 기존 출력물 제거 후 깨끗한 JSON만 출력
|
||||
if (ob_get_length()) ob_clean();
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
?>
|
||||
94
kngil/bbs/adm_faq_popup_save.php
Normal file
94
kngil/bbs/adm_faq_popup_save.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
/* =========================
|
||||
로그인 / 권한 가드
|
||||
========================= */
|
||||
require_once __DIR__ . '/adm_guard.php';
|
||||
require_once __DIR__ . '/db_conn.php';
|
||||
|
||||
/* =========================
|
||||
세션 기준 값
|
||||
========================= */
|
||||
$login = $_SESSION['login'];
|
||||
$auth_bc = $login['auth_bc']; // 권한코드
|
||||
$member_id = $login['member_id']; // 회사ID
|
||||
$user_id = $login['user_id'] ?? 'SYSTEM';
|
||||
|
||||
|
||||
/* =========================
|
||||
입력
|
||||
========================= */
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?? [];
|
||||
$action = $_GET['action'] ?? $input['action'] ?? 'list';
|
||||
|
||||
try {
|
||||
|
||||
switch ($action) {
|
||||
|
||||
case 'save':
|
||||
// $isAdmin 에러를 방지하기 위해 잠시 주석 처리하거나 true로 설정
|
||||
// if (!$isAdmin) throw new Exception('권한이 없습니다.');
|
||||
|
||||
$inserts = $input['inserts'] ?? [];
|
||||
$updates = $input['updates'] ?? [];
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
/* ---------- 신규 추가(INSERT) ---------- */
|
||||
if ($inserts) {
|
||||
// 호출 시 파라미터 개수와 이름을 정확히 맞춤
|
||||
$stmtI = $pdo->prepare("SELECT kngil.sp_fa_comments_i(:fa_subject, :fa_content, :sq_no, :use_yn, :cid)");
|
||||
|
||||
foreach ($inserts as $r) {
|
||||
$stmtI->execute([
|
||||
':fa_subject' => $r['fa_subject'] ?? '', // 데이터가 없으면 빈 글자라도 보냄
|
||||
':fa_content' => $r['fa_content'] ?? '',
|
||||
':sq_no' => $r['sq_no'] ?? 0,
|
||||
':use_yn' => $r['use_yn'] ?? 'Y',
|
||||
':cid' => $user_id
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- 수정(UPDATE) ---------- */
|
||||
if ($updates) {
|
||||
$stmtU = $pdo->prepare("SELECT kngil.sp_fa_comments_u(:fa_id, :fa_subject, :fa_content, :sq_no, :use_yn, :mid)");
|
||||
|
||||
foreach ($updates as $r) {
|
||||
$stmtU->execute([
|
||||
':fa_id' => $r['fa_id'] ?? '',
|
||||
':fa_subject' => $r['fa_subject'] ?? '', // 데이터가 없으면 빈 글자라도 보냄
|
||||
':fa_content' => $r['fa_content'] ?? '',
|
||||
':sq_no' => $r['sq_no'] ?? 0,
|
||||
':use_yn' => $r['use_yn'] ?? 'Y',
|
||||
':mid' => $user_id
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
echo json_encode(['status' => 'success']);
|
||||
break;
|
||||
default:
|
||||
throw new Exception('잘못된 요청');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
catch (Exception $e) {
|
||||
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
|
||||
36
kngil/bbs/adm_guard.php
Normal file
36
kngil/bbs/adm_guard.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
/* =========================
|
||||
1. 로그인 체크
|
||||
========================= */
|
||||
if (empty($_SESSION['login'])) {
|
||||
header('Location: /kngil/skin/index.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
2. 권한 체크
|
||||
========================= */
|
||||
$auth_bc = $_SESSION['login']['auth_bc'] ?? '';
|
||||
|
||||
$ALLOW_AUTH = [
|
||||
'BS100100', // 개발자
|
||||
'BS100200', // 관리자
|
||||
'BS100300', // 메인
|
||||
'BS100400', // 서브
|
||||
];
|
||||
|
||||
if (!in_array($auth_bc, $ALLOW_AUTH, true)) {
|
||||
http_response_code(403);
|
||||
echo '접근 권한이 없습니다.';
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
3. 권한 플래그 (중요)
|
||||
========================= */
|
||||
define('IS_SUPER_ADMIN', in_array($auth_bc, ['BS100100','BS100200'], true));
|
||||
define('IS_COMPANY_ADMIN', in_array($auth_bc, ['BS100300','BS100400'], true));
|
||||
27
kngil/bbs/adm_product_popup.php
Normal file
27
kngil/bbs/adm_product_popup.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
// 1. DB 연결 (절대 경로 혹은 상대 경로 확인)
|
||||
require_once 'db_conn.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
try {
|
||||
// 2. 프로시저 호출 (컬럼명: itm_cd, itm_nm, area, itm_amt 등)
|
||||
$stmt = $pdo->prepare("SELECT * FROM kngil.sp_item_r()");
|
||||
$stmt->execute();
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// 3. W2UI를 위해 각 행에 'recid' 필드 강제 주입
|
||||
$records = [];
|
||||
foreach ($rows as $row) {
|
||||
$row['recid'] = $row['itm_cd']; // 상품코드를 고유 키로 지정
|
||||
$records[] = $row;
|
||||
}
|
||||
|
||||
// 4. 순수 JSON만 출력 (다른 echo나 공백이 섞이면 에러 발생)
|
||||
echo json_encode($records);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
// 에러 발생 시 그리드가 이해할 수 있게 JSON으로 출력
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
?>
|
||||
58
kngil/bbs/adm_product_popup_delete.php
Normal file
58
kngil/bbs/adm_product_popup_delete.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
/* =========================
|
||||
로그인 / 권한 가드
|
||||
========================= */
|
||||
require_once __DIR__ . '/adm_guard.php';
|
||||
require_once __DIR__ . '/db_conn.php';
|
||||
|
||||
/* =========================
|
||||
세션 기준 값
|
||||
========================= */
|
||||
$login = $_SESSION['login'];
|
||||
$auth_bc = $login['auth_bc']; // 권한코드
|
||||
$member_id = $login['member_id']; // 회사ID
|
||||
$user_id = $login['user_id'] ?? 'SYSTEM';
|
||||
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// JSON 데이터 읽기
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
try {
|
||||
// 2. $pdo 변수가 있는지 확인 (DB 연결 확인)
|
||||
if (!isset($pdo)) {
|
||||
throw new Exception('데이터베이스 연결 설정($pdo)을 찾을 수 없습니다.');
|
||||
}
|
||||
|
||||
$ids = $input['ids'] ?? [];
|
||||
if (empty($ids)) {
|
||||
throw new Exception('삭제 대상이 없습니다.');
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// 3. 삭제 실행
|
||||
$stmt = $pdo->prepare("SELECT kngil.sp_item_d(:itm_cd)");
|
||||
|
||||
foreach ($ids as $code) {
|
||||
$stmt->execute([':itm_cd' => $code]);
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
echo json_encode(['status' => 'success']);
|
||||
|
||||
} catch (Exception $e) {
|
||||
if (isset($pdo) && $pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
// 기존 출력물 제거 후 깨끗한 JSON만 출력
|
||||
if (ob_get_length()) ob_clean();
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
?>
|
||||
97
kngil/bbs/adm_product_popup_save.php
Normal file
97
kngil/bbs/adm_product_popup_save.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
/* =========================
|
||||
로그인 / 권한 가드
|
||||
========================= */
|
||||
require_once __DIR__ . '/adm_guard.php';
|
||||
require_once __DIR__ . '/db_conn.php';
|
||||
|
||||
/* =========================
|
||||
세션 기준 값
|
||||
========================= */
|
||||
$login = $_SESSION['login'];
|
||||
$auth_bc = $login['auth_bc']; // 권한코드
|
||||
$member_id = $login['member_id']; // 회사ID
|
||||
$user_id = $login['user_id'] ?? 'SYSTEM';
|
||||
|
||||
|
||||
/* =========================
|
||||
입력
|
||||
========================= */
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?? [];
|
||||
$action = $_GET['action'] ?? $input['action'] ?? 'list';
|
||||
|
||||
try {
|
||||
|
||||
switch ($action) {
|
||||
|
||||
case 'save':
|
||||
// $isAdmin 에러를 방지하기 위해 잠시 주석 처리하거나 true로 설정
|
||||
// if (!$isAdmin) throw new Exception('권한이 없습니다.');
|
||||
|
||||
$inserts = $input['inserts'] ?? [];
|
||||
$updates = $input['updates'] ?? [];
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
/* ---------- 신규 추가(INSERT) ---------- */
|
||||
if ($inserts) {
|
||||
// 호출 시 파라미터 개수와 이름을 정확히 맞춤
|
||||
$stmtI = $pdo->prepare("SELECT kngil.sp_item_i(:itm_cd, :itm_nm, :area, :itm_amt, :use_yn, :rmks, :cid)");
|
||||
|
||||
foreach ($inserts as $r) {
|
||||
$stmtI->execute([
|
||||
':itm_cd' => $r['itm_cd'] ?? '', // 데이터가 없으면 빈 글자라도 보냄
|
||||
':itm_nm' => $r['itm_nm'] ?? '',
|
||||
':area' => $r['area'] ?? 0,
|
||||
':itm_amt' => $r['itm_amt'] ?? 0,
|
||||
':use_yn' => $r['use_yn'] ?? 'Y',
|
||||
':rmks' => $r['rmks'] ?? '',
|
||||
':cid' => $user_id
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- 수정(UPDATE) ---------- */
|
||||
if ($updates) {
|
||||
$stmtU = $pdo->prepare("SELECT kngil.sp_item_u(:itm_cd, :itm_nm, :area, :itm_amt, :use_yn, :rmks, :mid)");
|
||||
|
||||
foreach ($updates as $r) {
|
||||
$stmtU->execute([
|
||||
':itm_cd' => $r['itm_cd'] ?? '',
|
||||
':itm_nm' => $r['itm_nm'] ?? '',
|
||||
':area' => $r['area'] ?? 0,
|
||||
':itm_amt' => $r['itm_amt'] ?? 0,
|
||||
':use_yn' => $r['use_yn'] ?? 'Y',
|
||||
':rmks' => $r['rmks'] ?? '',
|
||||
':mid' => $user_id
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
echo json_encode(['status' => 'success']);
|
||||
break;
|
||||
default:
|
||||
throw new Exception('잘못된 요청');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
catch (Exception $e) {
|
||||
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
|
||||
45
kngil/bbs/adm_purch_popup.php
Normal file
45
kngil/bbs/adm_purch_popup.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
// 1. DB 연결
|
||||
require_once 'db_conn.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
try {
|
||||
// 클라이언트(JS)로부터 전달받은 검색 조건 (POST 또는 GET 방식에 맞춰 수정)
|
||||
$p_member_id = $_POST['member_id'] ?? '';
|
||||
$p_member_nm = $_POST['member_nm'] ?? '';
|
||||
|
||||
// 날짜가 빈 값('')으로 오면 반드시 null로 치환해야 PostgreSQL date 타입 에러가 안 납니다.
|
||||
$p_fbuy_dt = (!empty($_POST['fbuy_dt'])) ? $_POST['fbuy_dt'] : null;
|
||||
$p_tbuy_dt = (!empty($_POST['tbuy_dt'])) ? $_POST['tbuy_dt'] : null;
|
||||
|
||||
// 2. 프로시저 호출 - 파라미터 자리에 ?를 사용합니다.
|
||||
$stmt = $pdo->prepare("SELECT * FROM kngil.sp_buy_item_history_r(?, ?, ?, ?)");
|
||||
|
||||
// 파라미터 순서대로 배열에 담아 실행합니다.
|
||||
$stmt->execute([
|
||||
$p_member_id,
|
||||
$p_member_nm,
|
||||
$p_fbuy_dt,
|
||||
$p_tbuy_dt
|
||||
]);
|
||||
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// 3. W2UI를 위해 각 행에 'recid' 필드 강제 주입
|
||||
$records = [];
|
||||
foreach ($rows as $row) {
|
||||
// 복합키(member_id + sp_no)를 조합하여 유일한 recid 생성
|
||||
$row['recid'] = $row['member_id'] . '_' . $row['sq_no'];
|
||||
$records[] = $row;
|
||||
}
|
||||
|
||||
// 4. 결과 출력
|
||||
echo json_encode($records);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
// HTTP 상태 코드를 500으로 설정하여 클라이언트가 에러임을 인지하게 할 수 있습니다.
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
?>
|
||||
209
kngil/bbs/adm_service.php
Normal file
209
kngil/bbs/adm_service.php
Normal file
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
require_once __DIR__ . '/db_conn.php';
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$action = $input['action'] ?? '';
|
||||
$member_id = $input['member_id'] ?? '';
|
||||
|
||||
if (!$action || !$member_id) {
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => '필수값 누락'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
/* =========================
|
||||
조회 (R)
|
||||
========================= */
|
||||
if ($action === 'list') {
|
||||
|
||||
$buy_date = $input['buy_date'] ?? '';
|
||||
if (!$buy_date) {
|
||||
throw new Exception('구매일 누락');
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT *
|
||||
FROM kngil.sp_buy_item_r(:member_id, :buy_date)
|
||||
");
|
||||
$stmt->execute([
|
||||
'member_id' => $member_id,
|
||||
'buy_date' => $buy_date
|
||||
]);
|
||||
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$i = 1;
|
||||
foreach ($rows as &$r) {
|
||||
$r['recid'] = $i++;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'records' => $rows
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
즉시 삭제 (D)
|
||||
========================= */
|
||||
if ($action === 'delete') {
|
||||
|
||||
$sq_no = $input['sq_no'] ?? null;
|
||||
if (!$sq_no) {
|
||||
throw new Exception('삭제 대상 누락');
|
||||
}
|
||||
|
||||
$pdo->prepare("
|
||||
SELECT kngil.sp_buy_item_d(
|
||||
:member_id,
|
||||
:sq_no
|
||||
)
|
||||
")->execute([
|
||||
'member_id' => $member_id,
|
||||
'sq_no' => $sq_no
|
||||
]);
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
저장 (C / U)
|
||||
========================= */
|
||||
if ($action === 'save') {
|
||||
|
||||
$buy_date = $input['buy_date'] ?? '';
|
||||
$items = $input['items'] ?? [];
|
||||
|
||||
if (!$buy_date) {
|
||||
throw new Exception('구매일 누락');
|
||||
}
|
||||
|
||||
$pdo->beginTransaction();
|
||||
|
||||
foreach ($items as $row) {
|
||||
|
||||
$end_dt = empty($row['end_dt']) ? null : $row['end_dt'];
|
||||
|
||||
// INSERT
|
||||
if (!empty($row['_new'])) {
|
||||
|
||||
$pdo->prepare("
|
||||
SELECT kngil.sp_buy_item_i(
|
||||
:member_id::character varying,
|
||||
:buy_dt::date,
|
||||
:itm_cd::character varying,
|
||||
:itm_qty::numeric,
|
||||
:itm_area::numeric,
|
||||
:add_area::numeric,
|
||||
(:itm_area + :add_area)::numeric,
|
||||
:itm_amt::numeric,
|
||||
:dis_rt::numeric,
|
||||
:buy_amt::numeric,
|
||||
:vat_amt::numeric,
|
||||
:sum_amt::numeric,
|
||||
:end_dt::date,
|
||||
:ok_yn::character varying,
|
||||
:rmks::character varying,
|
||||
:cid::character varying
|
||||
)
|
||||
")->execute([
|
||||
'member_id' => $member_id,
|
||||
'buy_dt' => $buy_date,
|
||||
'itm_cd' => $row['itm_cd'],
|
||||
'itm_qty' => $row['itm_qty'],
|
||||
'itm_area' => $row['itm_area'],
|
||||
'add_area' => $row['add_area'] ?? 0,
|
||||
'itm_amt' => $row['itm_amt'],
|
||||
'dis_rt' => $row['dis_rt'],
|
||||
'buy_amt' => $row['buy_amt'],
|
||||
'vat_amt' => $row['vat_amt'],
|
||||
'sum_amt' => $row['sum_amt'],
|
||||
'end_dt' => $end_dt,
|
||||
'ok_yn' => $row['ok_yn'],
|
||||
'rmks' => $row['rmks'] ?? '',
|
||||
'cid' => 'ADMIN'
|
||||
]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// UPDATE
|
||||
if (!empty($row['_existing']) && !empty($row['sq_no'])) {
|
||||
|
||||
$pdo->prepare("
|
||||
SELECT kngil.sp_buy_item_u(
|
||||
:member_id::character varying,
|
||||
:sq_no::integer,
|
||||
:buy_dt::date,
|
||||
:itm_cd::character varying,
|
||||
:itm_qty::numeric,
|
||||
:itm_area::numeric,
|
||||
:add_area::numeric,
|
||||
(:itm_area + :add_area)::numeric,
|
||||
:itm_amt::numeric,
|
||||
:dis_rt::numeric,
|
||||
:buy_amt::numeric,
|
||||
:vat_amt::numeric,
|
||||
:sum_amt::numeric,
|
||||
:end_dt::date,
|
||||
:ok_yn::character varying,
|
||||
:rmks::character varying,
|
||||
:mid::character varying
|
||||
)
|
||||
")->execute([
|
||||
'member_id' => $member_id,
|
||||
'sq_no' => $row['sq_no'],
|
||||
'buy_dt' => $buy_date,
|
||||
'itm_cd' => $row['itm_cd'],
|
||||
'itm_qty' => $row['itm_qty'],
|
||||
'itm_area' => $row['itm_area'],
|
||||
'add_area' => $row['add_area'] ?? 0,
|
||||
'itm_amt' => $row['itm_amt'],
|
||||
'dis_rt' => $row['dis_rt'],
|
||||
'buy_amt' => $row['buy_amt'],
|
||||
'vat_amt' => $row['vat_amt'],
|
||||
'sum_amt' => $row['sum_amt'],
|
||||
'end_dt' => $end_dt,
|
||||
'ok_yn' => $row['ok_yn'],
|
||||
'rmks' => $row['rmks'] ?? '',
|
||||
'mid' => 'ADMIN'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
throw new Exception('Invalid action');
|
||||
|
||||
} catch (Exception $e) {
|
||||
|
||||
if ($pdo->inTransaction()) {
|
||||
$pdo->rollBack();
|
||||
}
|
||||
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
41
kngil/bbs/adm_use_history.php
Normal file
41
kngil/bbs/adm_use_history.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
// 1. DB 연결
|
||||
require_once 'db_conn.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
try {
|
||||
// JS의 URLSearchParams에서 보낸 키값과 일치시켜야 합니다.
|
||||
$p_member_id = $_POST['member_id'] ?? '';
|
||||
$p_user_nm = $_POST['user_nm'] ?? '';
|
||||
$p_dept_nm = $_POST['dept_nm'] ?? '';
|
||||
|
||||
// 2. 프로시저 호출
|
||||
// PostgreSQL 함수 호출 시 파라미터가 비어있으면 전체 조회가 되도록 설계됨
|
||||
$stmt = $pdo->prepare("SELECT * FROM kngil.sp_use_history(?, ?, ?)");
|
||||
|
||||
$stmt->execute([
|
||||
$p_member_id,
|
||||
$p_user_nm,
|
||||
$p_dept_nm
|
||||
]);
|
||||
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// 3. W2UI를 위해 각 행에 'recid' 필드 주입
|
||||
$records = [];
|
||||
foreach ($rows as $index => $row) {
|
||||
// user_id와 sq_no 조합으로 유일키 생성 (권장)
|
||||
// 만약 데이터가 없을 경우를 대비해 $index를 활용할 수도 있음
|
||||
$row['recid'] = ($row['user_id'] ?? 'unknown') . '_' . ($row['sq_no'] ?? $index);
|
||||
$records[] = $row;
|
||||
}
|
||||
|
||||
// 4. 결과 출력
|
||||
echo json_encode($records, JSON_UNESCAPED_UNICODE); // 한글 깨짐 방지
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
?>
|
||||
13
kngil/bbs/db_conn.php
Normal file
13
kngil/bbs/db_conn.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
$dsn = "pgsql:host=172.16.9.44;port=5432;dbname=KNGIL";
|
||||
$user = "postgres";
|
||||
$pass = "erpteam1!";
|
||||
|
||||
try {
|
||||
$pdo = new PDO($dsn, $user, $pass, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
|
||||
]);
|
||||
// echo "PostgreSQL 연결 성공 🎉";
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
23
kngil/bbs/get_base_cd.php
Normal file
23
kngil/bbs/get_base_cd.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
require_once 'db_conn.php';
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// URL 파라미터로 group_id를 받습니다. (예: get_base_cd.php?group_id=BS210)
|
||||
$group_id = isset($_GET['group_id']) ? $_GET['group_id'] : '';
|
||||
|
||||
if (empty($group_id)) {
|
||||
echo json_encode([]);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
// 파라미터(? 처리)를 사용하여 보안을 강화하고 재사용성을 높입니다.
|
||||
$stmt = $pdo->prepare("SELECT id, text FROM kngil.fn_base_cd(?)");
|
||||
$stmt->execute([$group_id]);
|
||||
$items = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
echo json_encode($items);
|
||||
} catch (PDOException $e) {
|
||||
echo json_encode(['status' => 'error', 'message' => $e->getMessage()]);
|
||||
}
|
||||
?>
|
||||
160
kngil/bbs/join copy.php
Normal file
160
kngil/bbs/join copy.php
Normal file
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$action = $data['action'] ?? '';
|
||||
|
||||
/* =================================================
|
||||
아이디 중복확인 (fn_user_id_check 사용)
|
||||
================================================= */
|
||||
if ($action === 'check_id') {
|
||||
|
||||
$userId = trim($data['userId'] ?? '');
|
||||
|
||||
if (!preg_match('/^[a-zA-Z][a-zA-Z0-9]{3,11}$/', $userId)) {
|
||||
echo json_encode([
|
||||
'available' => false,
|
||||
'message' => '아이디 형식 오류'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT kngil.fn_user_id_check(:user_id)
|
||||
");
|
||||
$stmt->execute([
|
||||
':user_id' => $userId
|
||||
]);
|
||||
|
||||
$result = trim($stmt->fetchColumn());
|
||||
|
||||
if (strpos($result, 'SUCCESS') === 0) {
|
||||
echo json_encode([
|
||||
'available' => true,
|
||||
'message' => '사용 가능한 아이디입니다.'
|
||||
]);
|
||||
} else {
|
||||
echo json_encode([
|
||||
'available' => false,
|
||||
'message' => '이미 존재하는 아이디입니다.'
|
||||
]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/* =================================================
|
||||
1. 필수값 검증
|
||||
================================================= */
|
||||
$required = [
|
||||
'memberType', // 회원유형
|
||||
'userId',
|
||||
'password',
|
||||
'userName',
|
||||
'email',
|
||||
'phone'
|
||||
];
|
||||
|
||||
foreach ($required as $k) {
|
||||
if (empty($data[$k])) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => '필수 항목이 누락되었습니다.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* =================================================
|
||||
2. 회원유형 → co_bc 매핑
|
||||
================================================= */
|
||||
/*
|
||||
기업회원 : '1'
|
||||
개인회원 : '2'
|
||||
→ 실제 코드값은 여기서 통제
|
||||
*/
|
||||
$co_bc = ($data['memberType'] === '1')
|
||||
? 'CB100100' // 기업
|
||||
: 'CB100200'; // 개인
|
||||
|
||||
/* =================================================
|
||||
3. 비밀번호 규칙 + 암호화
|
||||
================================================= */
|
||||
if (!preg_match('/^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*]).{12,}$/', $data['password'])) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => '비밀번호 규칙이 올바르지 않습니다.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$hashedPw = password_hash($data['password'], PASSWORD_DEFAULT);
|
||||
|
||||
/* =================================================
|
||||
4. 이메일 형식
|
||||
================================================= */
|
||||
if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => '이메일 형식 오류'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =================================================
|
||||
5. 프로시저 호출
|
||||
================================================= */
|
||||
try {
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT kngil.sp_member_i(
|
||||
:p_co_bc,
|
||||
:p_member_id,
|
||||
:p_user_pw,
|
||||
:p_member_nm,
|
||||
:p_email,
|
||||
:p_tel_no,
|
||||
:p_co_nm,
|
||||
:p_dept_nm,
|
||||
:p_cid
|
||||
) AS result
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
':p_co_bc' => $co_bc,
|
||||
':p_member_id' => $data['userId'],
|
||||
':p_user_pw' => $hashedPw,
|
||||
':p_member_nm' => $data['userName'],
|
||||
':p_email' => $data['email'],
|
||||
':p_tel_no' => $data['phone'],
|
||||
':p_co_nm' => $data['company'] ?? null,
|
||||
':p_dept_nm' => $data['department'] ?? null,
|
||||
':p_cid' => $data['userId']
|
||||
]);
|
||||
|
||||
$result = $stmt->fetchColumn();
|
||||
|
||||
if ($result === 'SUCCESS') {
|
||||
echo json_encode([
|
||||
'success' => true
|
||||
]);
|
||||
} else {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => '서버 오류'
|
||||
]);
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Invalid action'
|
||||
]);
|
||||
exit;
|
||||
203
kngil/bbs/join.php
Normal file
203
kngil/bbs/join.php
Normal file
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
|
||||
header('Content-Type: application/json');
|
||||
|
||||
/* =========================
|
||||
로그 함수
|
||||
========================= */
|
||||
function join_log($label, $data = null) {
|
||||
$logFile = $_SERVER['DOCUMENT_ROOT'].'/kngil/log/join.log';
|
||||
$time = date('Y-m-d H:i:s');
|
||||
|
||||
$log = "[$time] $label\n";
|
||||
if ($data !== null) {
|
||||
$log .= print_r($data, true);
|
||||
}
|
||||
$log .= "\n-----------------------------\n";
|
||||
|
||||
file_put_contents($logFile, $log, FILE_APPEND);
|
||||
}
|
||||
|
||||
/* =========================
|
||||
JSON 입력 파싱
|
||||
========================= */
|
||||
$raw = file_get_contents('php://input');
|
||||
$data = json_decode($raw, true);
|
||||
|
||||
join_log('RAW INPUT', $raw);
|
||||
join_log('PARSED DATA', $data);
|
||||
|
||||
$action = $data['action'] ?? null;
|
||||
join_log('ACTION', $action);
|
||||
|
||||
if (!$action) {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Invalid action'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =================================================
|
||||
1. 아이디 중복확인
|
||||
================================================= */
|
||||
if ($action === 'check_id') {
|
||||
|
||||
$userId = trim($data['userId'] ?? '');
|
||||
join_log('CHECK_ID userId', $userId);
|
||||
|
||||
if (!preg_match('/^[a-zA-Z][a-zA-Z0-9]{3,11}$/', $userId)) {
|
||||
echo json_encode([
|
||||
'available' => false,
|
||||
'message' => '아이디 형식 오류'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT kngil.fn_user_id_check(:user_id)
|
||||
");
|
||||
$stmt->execute([':user_id' => $userId]);
|
||||
|
||||
$result = trim($stmt->fetchColumn());
|
||||
join_log('CHECK_ID RESULT', $result);
|
||||
|
||||
if (strpos($result, 'SUCCESS') === 0) {
|
||||
echo json_encode([
|
||||
'available' => true,
|
||||
'message' => '사용 가능한 아이디입니다.'
|
||||
]);
|
||||
} else {
|
||||
echo json_encode([
|
||||
'available' => false,
|
||||
'message' => '이미 존재하는 아이디입니다.'
|
||||
]);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =================================================
|
||||
2. 회원가입
|
||||
================================================= */
|
||||
if ($action !== 'signup') {
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Invalid action'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =================================================
|
||||
3. 필수값 검증
|
||||
================================================= */
|
||||
$required = ['memberType','userId','password','userName','email','phone'];
|
||||
|
||||
foreach ($required as $k) {
|
||||
if (empty($data[$k])) {
|
||||
join_log('REQUIRED MISSING', $k);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => '필수 항목이 누락되었습니다.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* =================================================
|
||||
4. 회원유형 → co_bc
|
||||
================================================= */
|
||||
$memberType = $data['memberType'] ?? '2';
|
||||
$co_bc = ($memberType === '1') ? 'CB100100' : 'CB100200';
|
||||
|
||||
join_log('co_bc', $co_bc);
|
||||
|
||||
/* =================================================
|
||||
5. 비밀번호 규칙 (8자)
|
||||
================================================= */
|
||||
if (!preg_match('/^(?=.*[A-Za-z])(?=.*\d)(?=.*[!@#$%^&*]).{8,}$/', $data['password'])) {
|
||||
join_log('PASSWORD INVALID');
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => '비밀번호 규칙이 올바르지 않습니다.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$userPw = $data['password'];
|
||||
|
||||
/* =================================================
|
||||
6. 이메일 검증
|
||||
================================================= */
|
||||
if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
|
||||
join_log('EMAIL INVALID', $data['email']);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => '이메일 형식 오류'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =================================================
|
||||
7. 프로시저 호출
|
||||
================================================= */
|
||||
try {
|
||||
|
||||
join_log('SIGNUP PARAMS', [
|
||||
'memberType' => $memberType,
|
||||
'userId' => $data['userId'],
|
||||
'userName' => $data['userName'],
|
||||
'email' => $data['email'],
|
||||
'phone' => $data['phone'],
|
||||
'company' => $data['company'] ?? null,
|
||||
'department' => $data['department'] ?? null,
|
||||
]);
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT kngil.sp_member_i(
|
||||
:p_co_bc,
|
||||
:p_member_id,
|
||||
:p_user_pw,
|
||||
:p_member_nm,
|
||||
:p_email,
|
||||
:p_tel_no,
|
||||
:p_co_nm,
|
||||
:p_dept_nm,
|
||||
:p_cid
|
||||
)
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
':p_co_bc' => $co_bc,
|
||||
':p_member_id' => $data['userId'],
|
||||
':p_user_pw' => $userPw,
|
||||
':p_member_nm' => $data['userName'],
|
||||
':p_email' => $data['email'],
|
||||
':p_tel_no' => $data['phone'],
|
||||
':p_co_nm' => $data['company'] ?? null,
|
||||
':p_dept_nm' => $data['department'] ?? null,
|
||||
':p_cid' => $data['userId']
|
||||
]);
|
||||
|
||||
$result = trim($stmt->fetchColumn());
|
||||
join_log('PROC RESULT', $result);
|
||||
|
||||
if ($result === 'SUCCESS') {
|
||||
join_log('SIGNUP SUCCESS', $data['userId']);
|
||||
echo json_encode(['success' => true]);
|
||||
} else {
|
||||
join_log('SIGNUP FAIL', $result);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
} catch (Throwable $e) {
|
||||
join_log('EXCEPTION', $e->getMessage());
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => '서버 오류'
|
||||
]);
|
||||
}
|
||||
|
||||
exit;
|
||||
68
kngil/bbs/login.php
Normal file
68
kngil/bbs/login.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$id = trim($input['id'] ?? '');
|
||||
$pw = trim($input['pw'] ?? '');
|
||||
|
||||
if ($id === '' || $pw === '') {
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => '아이디와 비밀번호를 입력하세요.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT
|
||||
u.member_id,
|
||||
u.user_id,
|
||||
u.user_pw,
|
||||
u.user_nm,
|
||||
u.auth_bc,
|
||||
u.dept_nm,
|
||||
m.co_nm,
|
||||
u.tel_no,
|
||||
u.email
|
||||
FROM kngil.users u
|
||||
LEFT JOIN kngil.members m
|
||||
ON u.member_id = m.member_id
|
||||
WHERE LOWER(u.user_id) = LOWER(:id)
|
||||
AND u.use_yn = 'Y'
|
||||
LIMIT 1
|
||||
");
|
||||
$stmt->execute([':id' => $id]);
|
||||
|
||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$user) {
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => '존재하지 않는 아이디입니다.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 현재 구조상 평문 비교
|
||||
if ($user['user_pw'] !== $pw) {
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => '비밀번호가 올바르지 않습니다.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ✅ 로그인 성공
|
||||
$_SESSION['login'] = [
|
||||
'member_id' => $user['member_id'],
|
||||
'user_id' => $user['user_id'],
|
||||
'user_nm' => $user['user_nm'],
|
||||
'auth_bc' => $user['auth_bc'],
|
||||
'co_nm' => $user['co_nm'] ?? null,
|
||||
'dept_nm' => $user['dept_nm'] ?? null,
|
||||
'tel_no' => $user['tel_no'] ?? null,
|
||||
'email' => $user['email'] ?? null
|
||||
];
|
||||
|
||||
echo json_encode(['status' => 'success']);
|
||||
179
kngil/bbs/login_sms copy.php
Normal file
179
kngil/bbs/login_sms copy.php
Normal file
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
/**
|
||||
* Sentinel SMS 매직링크 테스트 (PHP)
|
||||
* - phoneNumber: 01086270921 (고정)
|
||||
* - system: kngil
|
||||
* - secret_key: MY_SECRET_KEY
|
||||
*/
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
/* =========================
|
||||
설정값
|
||||
========================= */
|
||||
$AUTH_SERVER = 'http://61.98.205.242:8075';
|
||||
$SYSTEM = 'kngil';
|
||||
$SECRET_KEY = '9f3b2e7a0a4f1f25c41c8c2367d04d54a89a2a5b2b189d63a99a0b874db4b27f';
|
||||
$PHONE = '01086270921';
|
||||
|
||||
/* =========================
|
||||
JWT 생성 (HS256)
|
||||
========================= */
|
||||
function base64url_encode($data) {
|
||||
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
function create_jwt($payload, $secret) {
|
||||
$header = ['alg'=>'HS256','typ'=>'JWT'];
|
||||
|
||||
$segments = [];
|
||||
$segments[] = base64url_encode(json_encode($header));
|
||||
$segments[] = base64url_encode(json_encode($payload));
|
||||
|
||||
$signing_input = implode('.', $segments);
|
||||
$signature = hash_hmac('sha256', $signing_input, $secret, true);
|
||||
|
||||
$segments[] = base64url_encode($signature);
|
||||
|
||||
return implode('.', $segments);
|
||||
}
|
||||
|
||||
/* =========================
|
||||
cURL 요청 함수
|
||||
========================= */
|
||||
function curl_json($url, $method='GET', $headers=[], $body=null) {
|
||||
$ch = curl_init($url);
|
||||
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_CUSTOMREQUEST => $method,
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_POSTFIELDS => $body,
|
||||
CURLOPT_TIMEOUT => 10
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$err = curl_error($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
if ($err) {
|
||||
throw new Exception($err);
|
||||
}
|
||||
|
||||
return [$code, $response];
|
||||
}
|
||||
|
||||
/* =========================
|
||||
MODE 분기
|
||||
========================= */
|
||||
$mode = $_GET['mode'] ?? 'request';
|
||||
|
||||
try {
|
||||
|
||||
/* =========================
|
||||
1️⃣ 매직링크 발급 요청
|
||||
========================= */
|
||||
if ($mode === 'request') {
|
||||
|
||||
// JWT payload (3분 유효)
|
||||
$payload = [
|
||||
'system' => $SYSTEM,
|
||||
'iat' => time(),
|
||||
'exp' => time() + 180
|
||||
];
|
||||
|
||||
$jwt = create_jwt($payload, $SECRET_KEY);
|
||||
|
||||
[$code, $res] = curl_json(
|
||||
$AUTH_SERVER.'/auth/sentinel',
|
||||
'POST',
|
||||
[
|
||||
'Authorization: Bearer '.$jwt,
|
||||
'Content-Type: application/json'
|
||||
],
|
||||
json_encode([
|
||||
'phoneNumber' => $PHONE
|
||||
])
|
||||
);
|
||||
|
||||
echo json_encode([
|
||||
'step' => 'sentinel_request',
|
||||
'http_code' => $code,
|
||||
'response' => json_decode($res, true)
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
2️⃣ 매직링크 상태 확인
|
||||
========================= */
|
||||
if ($mode === 'status') {
|
||||
|
||||
$token = $_GET['token'] ?? '';
|
||||
if (!$token) {
|
||||
throw new Exception('token 필요');
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'system' => $SYSTEM,
|
||||
'iat' => time(),
|
||||
'exp' => time() + 180
|
||||
];
|
||||
|
||||
$jwt = create_jwt($payload, $SECRET_KEY);
|
||||
|
||||
[$code, $res] = curl_json(
|
||||
$AUTH_SERVER.'/auth/status?token='.$token,
|
||||
'GET',
|
||||
[
|
||||
'Authorization: Bearer '.$jwt
|
||||
]
|
||||
);
|
||||
|
||||
$data = json_decode($res, true);
|
||||
|
||||
// 🔴 여기부터가 "로그인 처리"
|
||||
if (!empty($data['loggedIn'])) {
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT member_id, user_id, user_nm, auth_bc
|
||||
FROM kngil.users
|
||||
WHERE REPLACE(tel_no, '-', '') = :phone
|
||||
AND use_yn = 'Y'
|
||||
LIMIT 1
|
||||
");
|
||||
$stmt->execute([':phone' => $PHONE]);
|
||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$user) {
|
||||
throw new Exception('해당 번호로 등록된 사용자 없음');
|
||||
}
|
||||
|
||||
$_SESSION['login'] = [
|
||||
'member_id' => $user['member_id'],
|
||||
'user_id' => $user['user_id'],
|
||||
'user_nm' => $user['user_nm'],
|
||||
'auth_bc' => $user['auth_bc']
|
||||
];
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'message' => '자동 로그인 완료'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'pending'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo json_encode([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
212
kngil/bbs/login_sms.php
Normal file
212
kngil/bbs/login_sms.php
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
/**
|
||||
* Sentinel SMS 매직링크 로그인 (PHP)
|
||||
* - system: kngil
|
||||
* - secret_key: MY_SECRET_KEY
|
||||
*/
|
||||
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
/* =========================
|
||||
설정값
|
||||
========================= */
|
||||
$AUTH_SERVER = 'http://61.98.205.242:8075';
|
||||
$SYSTEM = 'kngil';
|
||||
$SECRET_KEY = '9f3b2e7a0a4f1f25c41c8c2367d04d54a89a2a5b2b189d63a99a0b874db4b27f';
|
||||
|
||||
/* =========================
|
||||
입력 처리
|
||||
========================= */
|
||||
$input = json_decode(file_get_contents('php://input'), true) ?? [];
|
||||
$mode = $_GET['mode'] ?? $input['mode'] ?? '';
|
||||
|
||||
/* =========================
|
||||
JWT 생성 (HS256)
|
||||
========================= */
|
||||
function base64url_encode($data) {
|
||||
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
function create_jwt($payload, $secret) {
|
||||
$header = ['alg' => 'HS256', 'typ' => 'JWT'];
|
||||
|
||||
$segments = [];
|
||||
$segments[] = base64url_encode(json_encode($header));
|
||||
$segments[] = base64url_encode(json_encode($payload));
|
||||
|
||||
$signing_input = implode('.', $segments);
|
||||
$signature = hash_hmac('sha256', $signing_input, $secret, true);
|
||||
|
||||
$segments[] = base64url_encode($signature);
|
||||
return implode('.', $segments);
|
||||
}
|
||||
|
||||
/* =========================
|
||||
cURL JSON 요청
|
||||
========================= */
|
||||
function curl_json($url, $method = 'GET', $headers = [], $body = null) {
|
||||
$ch = curl_init($url);
|
||||
|
||||
curl_setopt_array($ch, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_CUSTOMREQUEST => $method,
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_POSTFIELDS => $body,
|
||||
CURLOPT_TIMEOUT => 10
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$err = curl_error($ch);
|
||||
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
if ($err) {
|
||||
throw new Exception($err);
|
||||
}
|
||||
|
||||
return [$code, $response];
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
/* =========================
|
||||
1️⃣ 매직링크 발급 요청
|
||||
========================= */
|
||||
if ($mode === 'request') {
|
||||
|
||||
$rawPhone = $input['phone'] ?? '';
|
||||
$phone = preg_replace('/[^0-9]/', '', $rawPhone);
|
||||
|
||||
if (!$phone) {
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => '휴대폰 번호를 입력하세요.'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// JWT payload (3분 유효)
|
||||
$payload = [
|
||||
'system' => $SYSTEM,
|
||||
'iat' => time(),
|
||||
'exp' => time() + 180
|
||||
];
|
||||
|
||||
$jwt = create_jwt($payload, $SECRET_KEY);
|
||||
|
||||
[$code, $res] = curl_json(
|
||||
$AUTH_SERVER . '/auth/sentinel',
|
||||
'POST',
|
||||
[
|
||||
'Authorization: Bearer ' . $jwt,
|
||||
'Content-Type: application/json'
|
||||
],
|
||||
json_encode([
|
||||
'phoneNumber' => $phone
|
||||
])
|
||||
);
|
||||
|
||||
$result = json_decode($res, true);
|
||||
|
||||
if (empty($result['token'])) {
|
||||
throw new Exception('Sentinel token 발급 실패');
|
||||
}
|
||||
|
||||
// ✅ token 반드시 저장
|
||||
$_SESSION['sms_login'] = [
|
||||
'phone' => $phone,
|
||||
'token' => $result['token']
|
||||
];
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success'
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
2️⃣ 매직링크 상태 확인 → 자동 로그인
|
||||
========================= */
|
||||
if ($mode === 'status') {
|
||||
|
||||
if (
|
||||
empty($_SESSION['sms_login']['token']) ||
|
||||
empty($_SESSION['sms_login']['phone'])
|
||||
) {
|
||||
echo json_encode(['status' => 'pending']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$token = $_SESSION['sms_login']['token'];
|
||||
$phone = $_SESSION['sms_login']['phone'];
|
||||
|
||||
$payload = [
|
||||
'system' => $SYSTEM,
|
||||
'iat' => time(),
|
||||
'exp' => time() + 180
|
||||
];
|
||||
|
||||
$jwt = create_jwt($payload, $SECRET_KEY);
|
||||
|
||||
[$code, $res] = curl_json(
|
||||
$AUTH_SERVER . '/auth/status?token=' . $token,
|
||||
'GET',
|
||||
[
|
||||
'Authorization: Bearer ' . $jwt
|
||||
]
|
||||
);
|
||||
|
||||
$data = json_decode($res, true);
|
||||
|
||||
// 🔴 인증 완료 시 로그인 처리
|
||||
if (!empty($data['loggedIn'])) {
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT
|
||||
member_id,
|
||||
user_id,
|
||||
user_nm,
|
||||
auth_bc
|
||||
FROM kngil.users
|
||||
WHERE REPLACE(tel_no, '-', '') = :phone
|
||||
AND use_yn = 'Y'
|
||||
LIMIT 1
|
||||
");
|
||||
$stmt->execute([':phone' => $phone]);
|
||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$user) {
|
||||
throw new Exception('해당 번호로 등록된 사용자 없음');
|
||||
}
|
||||
|
||||
// ✅ 기존 PW 로그인과 동일
|
||||
$_SESSION['login'] = [
|
||||
'member_id' => $user['member_id'],
|
||||
'user_id' => $user['user_id'],
|
||||
'user_nm' => $user['user_nm'],
|
||||
'auth_bc' => $user['auth_bc']
|
||||
];
|
||||
|
||||
unset($_SESSION['sms_login']);
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'message' => '자동 로그인 완료'
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['status' => 'pending']);
|
||||
exit;
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo json_encode([
|
||||
'error' => true,
|
||||
'message' => $e->getMessage()
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
6
kngil/bbs/logout.php
Normal file
6
kngil/bbs/logout.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
session_start();
|
||||
session_destroy();
|
||||
|
||||
header('Location: /kngil/skin/index.php');
|
||||
exit;
|
||||
40
kngil/bbs/mypage01.php
Normal file
40
kngil/bbs/mypage01.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
//mypage01.php
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
|
||||
|
||||
if (!isset($_SESSION['login'])) {
|
||||
http_response_code(401);
|
||||
echo json_encode(['status' => 'error', 'message' => '로그인이 필요합니다.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$pw = trim($input['pw'] ?? '');
|
||||
|
||||
if ($pw === '') {
|
||||
echo json_encode(['status' => 'error', 'message' => '비밀번호를 입력하세요.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$userId = $_SESSION['login']['user_id'];
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT user_pw
|
||||
FROM kngil.users
|
||||
WHERE user_id = :user_id
|
||||
AND use_yn = 'Y'
|
||||
");
|
||||
$stmt->execute([':user_id' => $userId]);
|
||||
|
||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$user || $user['user_pw'] !== $pw) {
|
||||
echo json_encode(['status' => 'error', 'message' => '비밀번호가 올바르지 않습니다.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// ✅ 비밀번호 재인증 성공
|
||||
$_SESSION['mypage_verified'] = true;
|
||||
|
||||
echo json_encode(['status' => 'success']);
|
||||
90
kngil/bbs/mypage02.php
Normal file
90
kngil/bbs/mypage02.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isset($_SESSION['login'])) {
|
||||
http_response_code(401);
|
||||
echo json_encode(['status' => 'error', 'message' => '로그인이 필요합니다.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (empty($_SESSION['mypage_verified'])) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['status' => 'error', 'message' => '마이페이지 인증이 필요합니다.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$userId = $_SESSION['login']['user_id'];
|
||||
|
||||
/* =========================
|
||||
페이징 파라미터
|
||||
========================= */
|
||||
$page = max(1, intval($_GET['page'] ?? 1));
|
||||
$pageSize = 5;
|
||||
$offset = ($page - 1) * $pageSize;
|
||||
|
||||
try {
|
||||
|
||||
/* =========================
|
||||
1. 내 정보
|
||||
========================= */
|
||||
$stmt = $pdo->prepare("SELECT * FROM kngil.sp_users_my_r(:user_id)");
|
||||
$stmt->execute([':user_id' => $userId]);
|
||||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$user) {
|
||||
echo json_encode(['status' => 'error', 'message' => '사용자 정보 없음']);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =========================
|
||||
2. 전체 건수
|
||||
========================= */
|
||||
$cntStmt = $pdo->prepare("
|
||||
SELECT COUNT(*)
|
||||
FROM kngil.use_history
|
||||
WHERE user_id = :user_id
|
||||
");
|
||||
$cntStmt->execute([':user_id' => $userId]);
|
||||
$totalCount = (int)$cntStmt->fetchColumn();
|
||||
|
||||
$totalPages = (int)ceil($totalCount / $pageSize);
|
||||
|
||||
/* =========================
|
||||
3. 현재 페이지 데이터
|
||||
========================= */
|
||||
$histStmt = $pdo->prepare("
|
||||
SELECT *
|
||||
FROM kngil.sp_users_my_history(:user_id)
|
||||
OFFSET :offset
|
||||
LIMIT :limit
|
||||
");
|
||||
$histStmt->bindValue(':user_id', $userId, PDO::PARAM_STR);
|
||||
$histStmt->bindValue(':offset', $offset, PDO::PARAM_INT);
|
||||
$histStmt->bindValue(':limit', $pageSize, PDO::PARAM_INT);
|
||||
$histStmt->execute();
|
||||
|
||||
$history = $histStmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'user' => $user,
|
||||
'history' => $history,
|
||||
'pagination' => [
|
||||
'page' => $page,
|
||||
'pageSize' => $pageSize,
|
||||
'totalCount' => $totalCount,
|
||||
'totalPages' => $totalPages
|
||||
]
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => '서버 오류',
|
||||
'detail' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
139
kngil/bbs/mypage03.php
Normal file
139
kngil/bbs/mypage03.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// 로그인 체크
|
||||
if (!isset($_SESSION['login'])) {
|
||||
http_response_code(401);
|
||||
echo json_encode(['status' => 'error', 'message' => '로그인이 필요합니다.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 2차 인증 체크
|
||||
if (empty($_SESSION['mypage_verified'])) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['status' => 'error', 'message' => '마이페이지 인증이 필요합니다.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$userId = $_SESSION['login']['user_id'];
|
||||
$memberId = $_SESSION['login']['member_id'];
|
||||
|
||||
/* ==================================================
|
||||
GET : 회원정보 조회 (mypage03 열릴 때)
|
||||
================================================== */
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT *
|
||||
FROM kngil.sp_users_r(
|
||||
:member_id,
|
||||
'',
|
||||
'',
|
||||
'Y'
|
||||
)
|
||||
WHERE user_id = :user_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
':member_id' => $memberId,
|
||||
':user_id' => $userId
|
||||
]);
|
||||
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$row) {
|
||||
echo json_encode(['status' => 'error', 'message' => '회원정보를 찾을 수 없습니다.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'success',
|
||||
'data' => $row
|
||||
]);
|
||||
exit;
|
||||
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => '조회 중 오류 발생',
|
||||
'detail' => $e->getMessage()
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* ==================================================
|
||||
POST : 회원정보 수정
|
||||
================================================== */
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$userPw = trim($input['password'] ?? '');
|
||||
$email = trim($input['email'] ?? '');
|
||||
$deptNm = trim($input['dept_nm'] ?? '');
|
||||
|
||||
// 전화번호는 이번 단계에서 수정 안 함
|
||||
$tel_no = trim($input['tel_no'] ?? '');
|
||||
|
||||
if ($email === '') {
|
||||
echo json_encode(['status' => 'error', 'message' => '이메일은 필수입니다.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($userPw !== '' && strlen($userPw) < 8) {
|
||||
echo json_encode(['status' => 'error', 'message' => '비밀번호는 8자 이상이어야 합니다.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT kngil.sp_users_my_u(
|
||||
:user_id,
|
||||
:user_pw,
|
||||
:email,
|
||||
:tel_no,
|
||||
:dept_nm,
|
||||
:mid
|
||||
)
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
':user_id' => $userId,
|
||||
':user_pw' => $userPw,
|
||||
':email' => $email,
|
||||
':tel_no' => $tel_no,
|
||||
':dept_nm' => $deptNm,
|
||||
':mid' => $userId
|
||||
]);
|
||||
|
||||
$result = $stmt->fetchColumn();
|
||||
|
||||
if ($result !== 'SUCCESS') {
|
||||
echo json_encode(['status' => 'error', 'message' => $result]);
|
||||
exit;
|
||||
}
|
||||
|
||||
echo json_encode(['status' => 'success']);
|
||||
exit;
|
||||
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => '저장 중 오류 발생',
|
||||
'detail' => $e->getMessage()
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// 허용되지 않은 메서드
|
||||
http_response_code(405);
|
||||
echo json_encode(['status' => 'error', 'message' => 'Invalid request']);
|
||||
110
kngil/bbs/qa_comment.php
Normal file
110
kngil/bbs/qa_comment.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
session_start();
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (empty($_SESSION['login'])) {
|
||||
echo json_encode(['status'=>'error','message'=>'로그인 필요']);
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once __DIR__.'/db_conn.php';
|
||||
|
||||
$postId = (int)($_POST['postId'] ?? 0);
|
||||
$content = trim($_POST['comment'] ?? '');
|
||||
|
||||
if ($postId < 1 || ($content === '' && empty($_FILES['images']))) {
|
||||
echo json_encode(['status'=>'error','message'=>'내용 없음']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$user = $_SESSION['login'];
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
/* =========================
|
||||
1) 댓글 INSERT
|
||||
========================= */
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO kngil.qa_comments
|
||||
(post_id, commenter, user_nm, content, cdt_dt)
|
||||
VALUES
|
||||
(:post_id, :commenter, :user_nm, :content, NOW())
|
||||
RETURNING comment_id
|
||||
");
|
||||
$stmt->execute([
|
||||
':post_id' => $postId,
|
||||
':commenter' => $user['user_id'],
|
||||
':user_nm' => $user['user_nm'],
|
||||
':content' => $content
|
||||
]);
|
||||
|
||||
$commentId = $stmt->fetchColumn();
|
||||
|
||||
/* =========================
|
||||
2) 이미지 업로드
|
||||
========================= */
|
||||
$images = [];
|
||||
|
||||
if (!empty($_FILES['images']['name'][0])) {
|
||||
|
||||
$uploadDir = $_SERVER['DOCUMENT_ROOT'].'/kngil/uploads/comment/';
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
|
||||
foreach ($_FILES['images']['name'] as $i => $name) {
|
||||
|
||||
if ($_FILES['images']['error'][$i] !== UPLOAD_ERR_OK) continue;
|
||||
|
||||
$tmp = $_FILES['images']['tmp_name'][$i];
|
||||
$size = $_FILES['images']['size'][$i];
|
||||
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
|
||||
|
||||
$save = time().'_'.bin2hex(random_bytes(4)).'.'.$ext;
|
||||
$fullPath = $uploadDir.$save;
|
||||
move_uploaded_file($tmp, $fullPath);
|
||||
|
||||
$path = '/kngil/uploads/comment/'.$save;
|
||||
|
||||
// 🔥 DB 구조에 맞게 INSERT
|
||||
$pdo->prepare("
|
||||
INSERT INTO kngil.qa_comment_images
|
||||
(comment_id, file_name, file_path, thumb_path, file_size, uploaded_at)
|
||||
VALUES
|
||||
(:comment_id, :file_name, :file_path, :thumb_path, :file_size, NOW())
|
||||
")->execute([
|
||||
':comment_id' => $commentId,
|
||||
':file_name' => $name,
|
||||
':file_path' => $path,
|
||||
':thumb_path' => $path, // 지금은 동일 (추후 썸네일 분리 가능)
|
||||
':file_size' => $size
|
||||
]);
|
||||
|
||||
$images[] = [
|
||||
'thumb' => $path,
|
||||
'full' => $path,
|
||||
'name' => $name
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
echo json_encode([
|
||||
'status' => 'ok',
|
||||
'comment_id' => $commentId,
|
||||
'comment_text' => $content,
|
||||
'user_name' => $user['user_nm'],
|
||||
'login_id' => $user['user_id'],
|
||||
'created_at' => date('Y-m-d H:i'),
|
||||
'images' => $images
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
$pdo->rollBack();
|
||||
echo json_encode([
|
||||
'status' => 'error',
|
||||
'message' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
33
kngil/bbs/qa_comment_delete.php
Normal file
33
kngil/bbs/qa_comment_delete.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
session_start();
|
||||
header('Content-Type: application/json');
|
||||
|
||||
require_once __DIR__.'/db_conn.php';
|
||||
|
||||
if (empty($_SESSION['login'])) {
|
||||
echo json_encode(['status'=>'error','message'=>'로그인 필요']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = (int)($_POST['commentId'] ?? 0);
|
||||
$userId = $_SESSION['login']['user_id'];
|
||||
|
||||
if ($id < 1) {
|
||||
echo json_encode(['status'=>'error','message'=>'잘못된 요청']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 관리자 or 본인
|
||||
$isAdmin = function_exists('is_qna_admin') && is_qna_admin();
|
||||
|
||||
$sql = $isAdmin
|
||||
? "DELETE FROM kngil.qa_comments WHERE comment_id = :id"
|
||||
: "DELETE FROM kngil.qa_comments WHERE comment_id = :id AND commenter = :user";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$params = [':id'=>$id];
|
||||
if (!$isAdmin) $params[':user'] = $userId;
|
||||
|
||||
$stmt->execute($params);
|
||||
|
||||
echo json_encode(['status'=>'ok']);
|
||||
34
kngil/bbs/qa_comment_update.php
Normal file
34
kngil/bbs/qa_comment_update.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
session_start();
|
||||
header('Content-Type: application/json');
|
||||
|
||||
require_once __DIR__.'/db_conn.php';
|
||||
|
||||
if (empty($_SESSION['login'])) {
|
||||
echo json_encode(['status'=>'error','message'=>'로그인 필요']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$id = (int)($_POST['commentId'] ?? 0);
|
||||
$content = trim($_POST['comment'] ?? '');
|
||||
|
||||
if ($id < 1 || $content === '') {
|
||||
echo json_encode(['status'=>'error','message'=>'잘못된 요청']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// 본인 댓글만 수정
|
||||
$stmt = $pdo->prepare("
|
||||
UPDATE kngil.qa_comments
|
||||
SET content = :content,
|
||||
mdt_dt = NOW()
|
||||
WHERE comment_id = :id
|
||||
AND commenter = :user
|
||||
");
|
||||
$stmt->execute([
|
||||
':content' => $content,
|
||||
':id' => $id,
|
||||
':user' => $_SESSION['login']['user_id']
|
||||
]);
|
||||
|
||||
echo json_encode(['status'=>'ok']);
|
||||
233
kngil/bbs/qa_detail.php
Normal file
233
kngil/bbs/qa_detail.php
Normal file
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
// kngil/bbs/qa_detail.php
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
/* ===============================
|
||||
1. 세션 & 로그인 체크
|
||||
=============================== */
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
if (empty($_SESSION['login'])) {
|
||||
echo "<script>
|
||||
alert('로그인 후 이용 가능합니다.');
|
||||
location.href = '/kngil/skin/qa_list.skin.php';
|
||||
</script>";
|
||||
exit;
|
||||
}
|
||||
|
||||
$login = $_SESSION['login'];
|
||||
$me = $login['user_id'] ?? '';
|
||||
$auth = $login['auth_bc'] ?? '';
|
||||
|
||||
$isAdmin = in_array($auth, ['BS100100', 'BS100200']); // 개발자/관리자
|
||||
|
||||
/* ===============================
|
||||
2. DB 연결 (PostgreSQL)
|
||||
=============================== */
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
|
||||
|
||||
/* ===============================
|
||||
4. 삭제 처리
|
||||
=============================== */
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delete') {
|
||||
|
||||
$postId = (int)($_POST['post_id'] ?? 0);
|
||||
if ($postId < 1) {
|
||||
die('잘못된 요청입니다.');
|
||||
}
|
||||
|
||||
// 글 조회
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT post_id, user_id, stat_bc
|
||||
FROM kngil.qa_posts
|
||||
WHERE post_id = :pid
|
||||
");
|
||||
$stmt->execute([':pid' => $postId]);
|
||||
$post = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$post) {
|
||||
die('존재하지 않는 글입니다.');
|
||||
}
|
||||
|
||||
// 상태 제한 (검토중 / 완료면 삭제 불가)
|
||||
if (in_array($post['stat_bc'], ['REVIEW', 'DONE']) && !$isAdmin) {
|
||||
die('검토중이거나 답변 완료된 글은 삭제할 수 없습니다.');
|
||||
}
|
||||
|
||||
// 권한 체크 (본인 or 관리자)
|
||||
if (!$isAdmin && $post['user_id'] !== $loginUser['user_id']) {
|
||||
die('삭제 권한이 없습니다.');
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// 1️⃣ 첨부파일 삭제
|
||||
$fs = $pdo->prepare("
|
||||
SELECT save_path
|
||||
FROM kngil.qa_attachments
|
||||
WHERE post_id = :pid
|
||||
");
|
||||
$fs->execute([':pid' => $postId]);
|
||||
|
||||
foreach ($fs->fetchAll() as $f) {
|
||||
$file = $_SERVER['DOCUMENT_ROOT'] . $f['save_path'];
|
||||
if (is_file($file)) unlink($file);
|
||||
}
|
||||
|
||||
$pdo->prepare("DELETE FROM kngil.qa_attachments WHERE post_id = ?")
|
||||
->execute([$postId]);
|
||||
|
||||
// 2️⃣ 댓글 삭제
|
||||
$pdo->prepare("DELETE FROM kngil.qa_comments WHERE post_id = ?")
|
||||
->execute([$postId]);
|
||||
|
||||
// 3️⃣ 본문 삭제
|
||||
$pdo->prepare("DELETE FROM kngil.qa_posts WHERE post_id = ?")
|
||||
->execute([$postId]);
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
header("Location: /kngil/skin/qa_list.skin.php");
|
||||
exit;
|
||||
|
||||
} catch (Exception $e) {
|
||||
$pdo->rollBack();
|
||||
die('삭제 중 오류 발생: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/* ===============================
|
||||
3. post_id 검증
|
||||
=============================== */
|
||||
$postId = (int)($_GET['id'] ?? 0);
|
||||
if ($postId < 1) {
|
||||
exit('잘못된 접근입니다.');
|
||||
}
|
||||
|
||||
|
||||
/* ===============================
|
||||
5. 글 조회
|
||||
=============================== */
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT
|
||||
p.post_id,
|
||||
p.user_id,
|
||||
p.user_nm,
|
||||
p.tel_no,
|
||||
p.category,
|
||||
p.co_nm,
|
||||
p.dept_nm,
|
||||
p.title,
|
||||
p.content,
|
||||
p.attachment,
|
||||
p.stat_bc,
|
||||
p.is_secret,
|
||||
p.complete_form,
|
||||
p.cdt_dt,
|
||||
p.mid_dt,
|
||||
p.is_read_admin,
|
||||
|
||||
u.email
|
||||
|
||||
FROM kngil.qa_posts p
|
||||
LEFT JOIN kngil.users u
|
||||
ON p.user_id = u.user_id
|
||||
WHERE p.post_id = :pid
|
||||
");
|
||||
$stmt->execute([':pid' => $postId]);
|
||||
$post = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$post) {
|
||||
exit('존재하지 않는 글입니다.');
|
||||
}
|
||||
|
||||
/* ===============================
|
||||
6. 비밀글 접근 제어
|
||||
=============================== */
|
||||
if ($post['is_secret'] === 'Y' && $post['user_id'] !== $me && !$isAdmin) {
|
||||
exit('⚠️ 비밀글은 작성자 또는 관리자만 확인할 수 있습니다.');
|
||||
}
|
||||
|
||||
/* ===============================
|
||||
7. 관리자 열람 처리
|
||||
=============================== */
|
||||
if ($isAdmin && $post['is_read_admin'] === 'N') {
|
||||
$pdo->prepare("
|
||||
UPDATE kngil.qa_posts
|
||||
SET is_read_admin = 'Y'
|
||||
WHERE post_id = :pid
|
||||
")->execute([':pid' => $postId]);
|
||||
}
|
||||
|
||||
/* ===============================
|
||||
8. 라벨 매핑
|
||||
=============================== */
|
||||
$STATUS_LABELS = [
|
||||
'WAIT' => '문의접수',
|
||||
'REVIEW'=> '검토중',
|
||||
'DONE' => '답변완료'
|
||||
];
|
||||
|
||||
$CATEGORY_LABELS = [
|
||||
'general' => '일반문의',
|
||||
'improvement' => '개선문의',
|
||||
'error' => '오류문의',
|
||||
'notice' => '공지사항'
|
||||
];
|
||||
|
||||
$post['status_label'] = $STATUS_LABELS[$post['stat_bc']] ?? $post['stat_bc'];
|
||||
$post['category_label'] = $CATEGORY_LABELS[$post['category']] ?? $post['category'];
|
||||
$post['display_name'] = $post['user_nm'];
|
||||
|
||||
/* ===============================
|
||||
9. 첨부파일 조회
|
||||
=============================== */
|
||||
$af = $pdo->prepare("
|
||||
SELECT
|
||||
id,
|
||||
ori_name,
|
||||
save_path,
|
||||
file_size,
|
||||
uploaded_at
|
||||
FROM kngil.qa_attachments
|
||||
WHERE post_id = :pid
|
||||
ORDER BY id ASC
|
||||
");
|
||||
$af->execute([':pid' => $postId]);
|
||||
$attachments = $af->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
/* ===============================
|
||||
10. 댓글 조회 (일단 구조만)
|
||||
=============================== */
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT
|
||||
comment_id,
|
||||
post_id,
|
||||
commenter,
|
||||
content,
|
||||
user_nm,
|
||||
cdt_dt
|
||||
FROM kngil.qa_comments
|
||||
WHERE post_id = :post_id
|
||||
ORDER BY cdt_dt ASC
|
||||
");
|
||||
$stmt->execute([
|
||||
':post_id' => $postId
|
||||
]);
|
||||
|
||||
$comments = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
/* ===============================
|
||||
11. 소유자 여부 (수정 버튼용)
|
||||
=============================== */
|
||||
$isOwner = ($post['user_id'] === $me);
|
||||
|
||||
/* ===============================
|
||||
12. 스킨 렌더링
|
||||
=============================== */
|
||||
include $_SERVER['DOCUMENT_ROOT'].'/kngil/skin/qa_detail.skin.php';
|
||||
152
kngil/bbs/qa_list.php
Normal file
152
kngil/bbs/qa_list.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/**
|
||||
* Q&A 리스트 컨트롤러
|
||||
* - 스킨: /kngil/skin/qa_list.skin.php
|
||||
*/
|
||||
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
|
||||
|
||||
/* =========================
|
||||
1. 입력값 정리
|
||||
========================= */
|
||||
$page = max(1, (int)($_GET['page'] ?? 1));
|
||||
$pageSize = 15;
|
||||
$offset = ($page - 1) * $pageSize;
|
||||
|
||||
$search = trim($_GET['q'] ?? '');
|
||||
$cats = $_GET['cat'] ?? []; // 배열
|
||||
$writer = $_GET['writer'] ?? ''; // me
|
||||
$status = $_GET['status'] ?? 'all'; // 상태
|
||||
|
||||
$isLogin = !empty($_SESSION['login']);
|
||||
$loginUserId = $_SESSION['login']['user_id'] ?? null;
|
||||
|
||||
/* =========================
|
||||
2. WHERE 조건 구성
|
||||
========================= */
|
||||
$where = [];
|
||||
$params = [];
|
||||
|
||||
/* 카테고리 */
|
||||
if (!empty($cats) && !in_array('all', $cats, true)) {
|
||||
$catKeys = [];
|
||||
foreach ($cats as $i => $cat) {
|
||||
$key = ":cat{$i}";
|
||||
$catKeys[] = $key;
|
||||
$params[$key] = $cat;
|
||||
}
|
||||
$where[] = "p.category IN (" . implode(',', $catKeys) . ")";
|
||||
}
|
||||
|
||||
/* 내가 작성한 글 */
|
||||
if ($writer === 'me' && $loginUserId) {
|
||||
$where[] = "p.user_id = :me";
|
||||
$params[':me'] = $loginUserId;
|
||||
}
|
||||
|
||||
/* 상태 */
|
||||
if ($status !== 'all') {
|
||||
$where[] = "p.stat_bc = :status";
|
||||
$params[':status'] = $status;
|
||||
}
|
||||
|
||||
/* 검색 (제목 + 내용) */
|
||||
if ($search !== '') {
|
||||
$where[] = "(p.title ILIKE :q OR p.content ILIKE :q)";
|
||||
$params[':q'] = "%{$search}%";
|
||||
}
|
||||
|
||||
$whereSql = $where ? 'WHERE ' . implode(' AND ', $where) : '';
|
||||
|
||||
/* =========================
|
||||
3. 전체 건수
|
||||
========================= */
|
||||
$countSql = "
|
||||
SELECT COUNT(*)
|
||||
FROM kngil.qa_posts p
|
||||
{$whereSql}
|
||||
";
|
||||
$stmt = $pdo->prepare($countSql);
|
||||
$stmt->execute($params);
|
||||
$totalCount = (int)$stmt->fetchColumn();
|
||||
|
||||
/* =========================
|
||||
4. 리스트 조회
|
||||
========================= */
|
||||
$listSql = "
|
||||
SELECT
|
||||
p.post_id,
|
||||
p.category,
|
||||
p.title,
|
||||
p.user_nm,
|
||||
p.co_nm,
|
||||
p.dept_nm,
|
||||
p.stat_bc AS status,
|
||||
p.is_secret,
|
||||
p.cdt_dt AS created_at,
|
||||
|
||||
-- 댓글 수
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM kngil.qa_comments c
|
||||
WHERE c.post_id = p.post_id
|
||||
) AS comment_count,
|
||||
|
||||
-- 첨부파일 수
|
||||
(
|
||||
SELECT COUNT(*)
|
||||
FROM kngil.qa_attachments a
|
||||
WHERE a.post_id = p.post_id
|
||||
) AS file_count
|
||||
|
||||
FROM kngil.qa_posts p
|
||||
{$whereSql}
|
||||
ORDER BY
|
||||
(p.category = 'notice') DESC,
|
||||
p.post_id DESC
|
||||
LIMIT :limit OFFSET :offset
|
||||
";
|
||||
|
||||
$stmt = $pdo->prepare($listSql);
|
||||
|
||||
/* 바인딩 */
|
||||
foreach ($params as $k => $v) {
|
||||
$stmt->bindValue($k, $v);
|
||||
}
|
||||
$stmt->bindValue(':limit', $pageSize, PDO::PARAM_INT);
|
||||
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
|
||||
|
||||
$stmt->execute();
|
||||
$posts = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
/* =========================
|
||||
5. 표시용 가공
|
||||
========================= */
|
||||
foreach ($posts as &$row) {
|
||||
// 회사 표시
|
||||
$row['display_company'] = $row['co_nm'] ?? '';
|
||||
|
||||
// 작성자 표시
|
||||
$row['display_name'] = $row['user_nm'] ?? $row['user_id'];
|
||||
|
||||
// 날짜 포맷
|
||||
$row['created_at'] = substr($row['created_at'], 0, 10);
|
||||
}
|
||||
unset($row);
|
||||
|
||||
/* =========================
|
||||
6. 페이징 계산
|
||||
========================= */
|
||||
$totalPages = (int)ceil($totalCount / $pageSize);
|
||||
|
||||
/* =========================
|
||||
7. 스킨 렌더링
|
||||
========================= */
|
||||
include $_SERVER['DOCUMENT_ROOT'].'/kngil/skin/qa_list.skin.php';
|
||||
50
kngil/bbs/qa_status.php
Normal file
50
kngil/bbs/qa_status.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/adm_guard.php';
|
||||
|
||||
/* =========================
|
||||
1. 관리자 권한 체크
|
||||
========================= */
|
||||
if (!defined('IS_SUPER_ADMIN') || !IS_SUPER_ADMIN) {
|
||||
http_response_code(403);
|
||||
exit('권한이 없습니다.');
|
||||
}
|
||||
|
||||
/* =========================
|
||||
2. 파라미터 체크
|
||||
========================= */
|
||||
$postId = (int)($_POST['post_id'] ?? 0);
|
||||
$status = $_POST['status'] ?? '';
|
||||
|
||||
$ALLOW_STATUS = ['new','review','deep','patch','done'];
|
||||
|
||||
if ($postId < 1 || !in_array($status, $ALLOW_STATUS, true)) {
|
||||
exit('잘못된 요청입니다.');
|
||||
}
|
||||
|
||||
/* =========================
|
||||
3. 상태 업데이트
|
||||
========================= */
|
||||
try {
|
||||
$stmt = $pdo->prepare("
|
||||
UPDATE kngil.qa_posts
|
||||
SET stat_bc = :status,
|
||||
mid_dt = NOW()
|
||||
WHERE post_id = :pid
|
||||
");
|
||||
$stmt->execute([
|
||||
':status' => $status,
|
||||
':pid' => $postId
|
||||
]);
|
||||
|
||||
// 상세 페이지로 복귀
|
||||
header("Location: /kngil/bbs/qa_detail.php?id={$postId}");
|
||||
exit;
|
||||
|
||||
} catch (Exception $e) {
|
||||
exit('DB 오류: '.$e->getMessage());
|
||||
}
|
||||
231
kngil/bbs/qa_write.php
Normal file
231
kngil/bbs/qa_write.php
Normal file
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
|
||||
|
||||
/* ===============================
|
||||
1. 세션 & 로그인 체크
|
||||
=============================== */
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
// echo '<pre>';
|
||||
// var_dump($_SESSION['login']);
|
||||
// exit;
|
||||
|
||||
if (empty($_SESSION['login'])) {
|
||||
echo "<script>
|
||||
alert('로그인이 필요합니다.');
|
||||
location.href = '/kngil/skin/qa_list.skin.php';
|
||||
</script>";
|
||||
exit;
|
||||
}
|
||||
|
||||
$loginUser = $_SESSION['login'];
|
||||
|
||||
/* ===============================
|
||||
2. DB 연결
|
||||
=============================== */
|
||||
require_once $_SERVER['DOCUMENT_ROOT'].'/kngil/bbs/db_conn.php';
|
||||
|
||||
/* ===============================
|
||||
3. 수정 여부 판단
|
||||
=============================== */
|
||||
$postId = isset($_GET['id']) ? (int)$_GET['id'] : 0;
|
||||
$isEdit = $postId > 0;
|
||||
|
||||
/* ===============================
|
||||
4. 수정 모드 – 기존 글 로드
|
||||
=============================== */
|
||||
$post = [
|
||||
'category' => '',
|
||||
'title' => '',
|
||||
'content' => '',
|
||||
'is_secret' => 'N',
|
||||
];
|
||||
|
||||
if ($isEdit) {
|
||||
$stmt = $pdo->prepare("SELECT * FROM kngil.qa_posts WHERE post_id = :pid");
|
||||
$stmt->execute([':pid' => $postId]);
|
||||
$post = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$post) {
|
||||
die('존재하지 않는 글입니다.');
|
||||
}
|
||||
|
||||
// 작성자 본인만 수정 가능
|
||||
if ($post['user_id'] !== ($loginUser['user_id'] ?? '')) {
|
||||
die('수정 권한이 없습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
/* ===============================
|
||||
5. 첨부파일 업로드
|
||||
=============================== */
|
||||
function handle_file_uploads(PDO $pdo, int $postId)
|
||||
{
|
||||
if (empty($_FILES['attach']['name'][0])) return;
|
||||
|
||||
$uploadDir = $_SERVER['DOCUMENT_ROOT'] . '/kngil/uploads/qa/';
|
||||
if (!is_dir($uploadDir)) {
|
||||
mkdir($uploadDir, 0777, true);
|
||||
}
|
||||
|
||||
$allowExt = ['jpg','jpeg','png','gif','pdf','hwp','doc','docx','xls','xlsx','zip'];
|
||||
|
||||
foreach ($_FILES['attach']['name'] as $i => $oriName) {
|
||||
|
||||
if ($_FILES['attach']['error'][$i] !== UPLOAD_ERR_OK) continue;
|
||||
|
||||
$tmp = $_FILES['attach']['tmp_name'][$i];
|
||||
$size = $_FILES['attach']['size'][$i];
|
||||
$ext = strtolower(pathinfo($oriName, PATHINFO_EXTENSION));
|
||||
|
||||
if (!in_array($ext, $allowExt)) continue;
|
||||
if ($size > 30 * 1024 * 1024) continue;
|
||||
|
||||
$saveName = time() . '_' . bin2hex(random_bytes(6)) . '.' . $ext;
|
||||
$savePath = $uploadDir . $saveName;
|
||||
|
||||
if (!move_uploaded_file($tmp, $savePath)) continue;
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO kngil.qa_attachments (
|
||||
post_id,
|
||||
ori_name,
|
||||
save_path,
|
||||
file_size,
|
||||
uploaded_at
|
||||
) VALUES (
|
||||
:post_id,
|
||||
:ori_name,
|
||||
:save_path,
|
||||
:file_size,
|
||||
NOW()
|
||||
)
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
':post_id' => $postId,
|
||||
':ori_name' => $oriName,
|
||||
':save_path' => '/kngil/uploads/qa/' . $saveName,
|
||||
':file_size' => $size
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ===============================
|
||||
6. POST 처리 (등록 / 수정)
|
||||
=============================== */
|
||||
$errors = [];
|
||||
|
||||
$secret = 'N';
|
||||
$category = '';
|
||||
$title = '';
|
||||
$content = '';
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
|
||||
$category = trim($_POST['category'] ?? '');
|
||||
$title = trim($_POST['title'] ?? '');
|
||||
$content = trim($_POST['content'] ?? '');
|
||||
$secret = isset($_POST['secret']) ? 'Y' : 'N';
|
||||
|
||||
if ($category === '') $errors[] = '구분을 선택하세요.';
|
||||
if ($title === '') $errors[] = '제목을 입력하세요.';
|
||||
if ($content === '') $errors[] = '내용을 입력하세요.';
|
||||
|
||||
// 첨부파일명만 저장 (실파일 저장은 추후 분리 가능)
|
||||
$attachment = null;
|
||||
if (!empty($_FILES['attach']['name'][0])) {
|
||||
$attachment = implode(',', $_FILES['attach']['name']);
|
||||
}
|
||||
|
||||
if (empty($errors)) {
|
||||
try {
|
||||
|
||||
if ($isEdit) {
|
||||
/* ---------- UPDATE ---------- */
|
||||
$stmt = $pdo->prepare("
|
||||
UPDATE kngil.qa_posts
|
||||
SET category = :category,
|
||||
title = :title,
|
||||
content = :content,
|
||||
is_secret = :is_secret,
|
||||
mid_dt = NOW()
|
||||
WHERE post_id = :pid
|
||||
");
|
||||
$stmt->execute([
|
||||
':category' => $category,
|
||||
':title' => $title,
|
||||
':content' => $content,
|
||||
':is_secret' => $secret, // 'Y' or 'N'
|
||||
':pid' => $postId
|
||||
]);
|
||||
handle_file_uploads($pdo, $postId);
|
||||
|
||||
} else {
|
||||
/* ---------- INSERT ---------- */
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO kngil.qa_posts (
|
||||
user_id,
|
||||
user_nm,
|
||||
tel_no,
|
||||
co_nm,
|
||||
dept_nm,
|
||||
category,
|
||||
title,
|
||||
content,
|
||||
is_secret,
|
||||
stat_bc,
|
||||
is_read_admin,
|
||||
cdt_dt
|
||||
) VALUES (
|
||||
:user_id,
|
||||
:user_nm,
|
||||
:tel_no,
|
||||
:co_nm,
|
||||
:dept_nm,
|
||||
:category,
|
||||
:title,
|
||||
:content,
|
||||
:is_secret,
|
||||
'wait',
|
||||
'N',
|
||||
NOW()
|
||||
)
|
||||
RETURNING post_id
|
||||
");
|
||||
// var_dump($loginUser);
|
||||
// exit;
|
||||
$stmt->execute([
|
||||
':user_id' => $loginUser['user_id'],
|
||||
':user_nm' => $loginUser['user_nm'],
|
||||
':tel_no' => $loginUser['tel_no'] ?? null,
|
||||
':co_nm' => $loginUser['co_nm'] ?? null,
|
||||
':dept_nm' => $loginUser['dept_nm'] ?? null,
|
||||
':category' => $category,
|
||||
':title' => $title,
|
||||
':content' => $content,
|
||||
':is_secret' => $secret
|
||||
]);
|
||||
|
||||
$postId = $stmt->fetchColumn();
|
||||
handle_file_uploads($pdo, $postId);
|
||||
}
|
||||
|
||||
header("Location: /kngil/bbs/qa_detail.php?id={$postId}");
|
||||
exit;
|
||||
|
||||
} catch (Exception $e) {
|
||||
$errors[] = 'DB 오류: ' . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ===============================
|
||||
7. 화면 출력
|
||||
=============================== */
|
||||
include $_SERVER['DOCUMENT_ROOT'].'/kngil/skin/qa_write.skin.php';
|
||||
223
kngil/bbs/sales_results.php
Normal file
223
kngil/bbs/sales_results.php
Normal file
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
ini_set('display_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
header("Content-Type: application/json; charset=utf-8");
|
||||
|
||||
/* -----------------------------------------------------
|
||||
🔵 DB 연결
|
||||
----------------------------------------------------- */
|
||||
try {
|
||||
$pdo = new PDO(
|
||||
"mysql:host=localhost;dbname=egbim;charset=utf8mb4",
|
||||
"egbim",
|
||||
"baron3840!!",
|
||||
[
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
|
||||
]
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(["status" => "fail", "message" => "DB 연결 실패"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
🔵 공통 날짜 변환 함수 (MM/DD/YYYY → YYYY-MM-DD)
|
||||
----------------------------------------------------- */
|
||||
function normalize_date($dateStr) {
|
||||
if (!$dateStr) return null;
|
||||
|
||||
// 이미 YYYY-MM-DD라면 그대로 반환
|
||||
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $dateStr)) {
|
||||
return $dateStr;
|
||||
}
|
||||
|
||||
// MM/DD/YYYY → YYYY-MM-DD (한자리/두자리 모두 허용)
|
||||
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/', $dateStr, $m)) {
|
||||
$month = str_pad($m[1], 2, '0', STR_PAD_LEFT);
|
||||
$day = str_pad($m[2], 2, '0', STR_PAD_LEFT);
|
||||
return "{$m[3]}-$month-$day";
|
||||
}
|
||||
|
||||
// 형식 이상하면 null 리턴
|
||||
return null;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------
|
||||
🔵 요청 액션
|
||||
----------------------------------------------------- */
|
||||
$action = $_POST['action'] ?? $_GET['action'] ?? "";
|
||||
|
||||
/* =====================================================
|
||||
1) LIST
|
||||
===================================================== */
|
||||
if ($action === "list") {
|
||||
$stmt = $pdo->query("
|
||||
SELECT r.*, m.emp_name
|
||||
FROM sales_results r
|
||||
LEFT JOIN sales_members m ON r.emp_no = m.emp_no
|
||||
ORDER BY r.seq_no DESC
|
||||
");
|
||||
|
||||
echo json_encode([
|
||||
"status" => "ok",
|
||||
"records" => $stmt->fetchAll()
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =====================================================
|
||||
2) INSERT (seq_no 자동 증가)
|
||||
===================================================== */
|
||||
if ($action === "insert") {
|
||||
|
||||
$sales_date = normalize_date($_POST['sales_date']);
|
||||
|
||||
if (!$sales_date) {
|
||||
echo json_encode([
|
||||
"status" => "error",
|
||||
"message" => "실적일(sales_date) 형식 오류. YYYY-MM-DD 또는 MM/DD/YYYY 로 입력하세요."
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$next_seq = $pdo->query("SELECT IFNULL(MAX(seq_no), 0) + 1 FROM sales_results")->fetchColumn();
|
||||
|
||||
// 🔥 서버에서 총금액 계산
|
||||
$qty = (int)($_POST['quantity'] ?? 0);
|
||||
$unit = (int)($_POST['unit_price'] ?? 0);
|
||||
$discount = (int)($_POST['discount'] ?? 0);
|
||||
|
||||
$total_amount = ($qty * $unit) - $discount;
|
||||
if ($total_amount < 0) $total_amount = 0;
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
INSERT INTO sales_results
|
||||
(seq_no, sales_date, emp_no, client_code, product_code, quantity, unit_price, discount, total_amount, remarks)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
");
|
||||
|
||||
$stmt->execute([
|
||||
$next_seq,
|
||||
$sales_date,
|
||||
$_POST['emp_no'],
|
||||
$_POST['client_code'],
|
||||
$_POST['product_code'],
|
||||
$qty,
|
||||
$unit,
|
||||
$discount,
|
||||
$total_amount, // 🔥 클라이언트 값 무시, 서버 계산값 넣기
|
||||
$_POST['remarks']
|
||||
]);
|
||||
|
||||
echo json_encode(["status" => "ok"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
/* =====================================================
|
||||
3) UPDATE
|
||||
===================================================== */
|
||||
if ($action === "update") {
|
||||
|
||||
$seq_no = $_POST['seq_no'] ?? '';
|
||||
if (!$seq_no) {
|
||||
echo json_encode(["status" => "error", "message" => "seq_no 누락"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
unset($_POST['action'], $_POST['seq_no']);
|
||||
|
||||
/* -----------------------------
|
||||
🔵 날짜 변환 (MM/DD/YYYY → YYYY-MM-DD)
|
||||
----------------------------- */
|
||||
if (!empty($_POST['sales_date'])) {
|
||||
$date = normalize_date($_POST['sales_date']);
|
||||
if (!$date) {
|
||||
echo json_encode(["status" => "error", "message" => "실적일(sales_date) 형식 오류"]);
|
||||
exit;
|
||||
}
|
||||
$_POST['sales_date'] = $date;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------
|
||||
🔥 quantity / unit_price / discount 변경 여부 확인
|
||||
----------------------------------------------------- */
|
||||
$qtyChanged = array_key_exists('quantity', $_POST);
|
||||
$unitChanged = array_key_exists('unit_price', $_POST);
|
||||
$discountChanged = array_key_exists('discount', $_POST);
|
||||
|
||||
if ($qtyChanged || $unitChanged || $discountChanged) {
|
||||
|
||||
// 기존 값 가져오기
|
||||
$old = $pdo->prepare("
|
||||
SELECT quantity, unit_price, discount
|
||||
FROM sales_results
|
||||
WHERE seq_no = ?
|
||||
");
|
||||
$old->execute([$seq_no]);
|
||||
$oldData = $old->fetch();
|
||||
|
||||
// 새 값이 있으면 새 값 사용, 없으면 기존 값 사용
|
||||
$qty = isset($_POST['quantity']) ? (int)$_POST['quantity'] : (int)$oldData['quantity'];
|
||||
$unit = isset($_POST['unit_price']) ? (int)$_POST['unit_price'] : (int)$oldData['unit_price'];
|
||||
$discount = isset($_POST['discount']) ? (int)$_POST['discount'] : (int)$oldData['discount'];
|
||||
|
||||
// 서버에서 총금액 재계산
|
||||
$total_amount = ($qty * $unit) - $discount;
|
||||
if ($total_amount < 0) $total_amount = 0;
|
||||
|
||||
$_POST['total_amount'] = $total_amount; // 🔥 강제 반영
|
||||
}
|
||||
|
||||
/* -----------------------------
|
||||
🔵 Partial Update (빈값은 무시)
|
||||
----------------------------- */
|
||||
$fields = [];
|
||||
$params = [];
|
||||
|
||||
foreach ($_POST as $key => $val) {
|
||||
|
||||
// NULL, 빈문자, undefined는 UPDATE 안함
|
||||
if ($val === '' || $val === null || $val === 'undefined') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$fields[] = "$key = ?";
|
||||
$params[] = $val;
|
||||
}
|
||||
|
||||
if (!empty($fields)) {
|
||||
$sql = "UPDATE sales_results SET "
|
||||
. implode(", ", $fields)
|
||||
. ", updated_at = NOW()
|
||||
WHERE seq_no = ?";
|
||||
$params[] = $seq_no;
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
}
|
||||
|
||||
echo json_encode(["status" => "ok"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/* =====================================================
|
||||
4) DELETE
|
||||
===================================================== */
|
||||
if ($action === "delete") {
|
||||
|
||||
$stmt = $pdo->prepare("DELETE FROM sales_results WHERE seq_no = ?");
|
||||
$stmt->execute([$_POST['seq_no']]);
|
||||
|
||||
echo json_encode(["status" => "ok"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
/* =====================================================
|
||||
요청 없음
|
||||
===================================================== */
|
||||
echo json_encode(["status" => "fail", "message" => "잘못된 요청"]);
|
||||
exit;
|
||||
?>
|
||||
Reference in New Issue
Block a user