diff --git a/FIX_AND_MIGRATE.php b/FIX_AND_MIGRATE.php new file mode 100644 index 0000000..056505b --- /dev/null +++ b/FIX_AND_MIGRATE.php @@ -0,0 +1,76 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + echo "--- ๐Ÿ›  ์‹ฌ์ธต ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋ฐ ๋ฐ์ดํ„ฐ ๋ณต๊ตฌ ์‹œ์ž‘ ---\n"; + + // 1. ์Šคํ‚ค๋งˆ ๊ฐ•์ œ ๋ณด์ • + $newColumns = [ + 'disposal_recipient' => 'TEXT', + 'disposal_date' => 'TEXT', + 'real_user' => 'TEXT', + 'disposal_user_id' => 'INTEGER' + ]; + foreach ($newColumns as $col => $type) { + try { + $db->exec("ALTER TABLE laptop_assets ADD COLUMN $col $type"); + echo "โœ… ์ปฌ๋Ÿผ ๋ณด์ •: $col\n"; + } catch (PDOException $e) { + // Already exists or other error + } + } + + // 2. ์ธ์ฝ”๋”ฉ ๋ณต๊ตฌ (URL-Encoded ๋ฐ์ดํ„ฐ๊ฐ€ ์‹๋ณ„๋˜์–ด ์ˆ˜์ • ์‹œ๋„) + $stmt = $db->query("SELECT id, assigned_user_name, disposal_recipient FROM laptop_assets"); + $assets = $stmt->fetchAll(PDO::FETCH_ASSOC); + + $fixCount = 0; + $updateStmt = $db->prepare("UPDATE laptop_assets SET assigned_user_name = ?, disposal_recipient = ? WHERE id = ?"); + + foreach ($assets as $asset) { + $uName = $asset['assigned_user_name']; + $dRec = $asset['disposal_recipient']; + + $newUName = $uName; + $newDRec = $dRec; + + // URL ์ธ์ฝ”๋”ฉ ํƒ์ง€ ๋ฐ ๋ณ€ํ™˜ + if ($uName && strpos($uName, '%') !== false) { + $newUName = urldecode($uName); + } + if ($dRec && strpos($dRec, '%') !== false) { + $newDRec = urldecode($dRec); + } + + if ($newUName !== $uName || $newDRec !== $dRec) { + $updateStmt->execute([$newUName, $newDRec, $asset['id']]); + $fixCount++; + } + } + echo "โœ… Mojibake/URL-Encoding ๋ฐ์ดํ„ฐ ๋ณต๊ตฌ: {$fixCount}๊ฑด ์ˆ˜์ • ์™„๋ฃŒ.\n"; + + // 3. STOCK ์ž์‚ฐ ๋ช…์น™ ๋™๊ธฐํ™” + $stmtStock = $db->prepare("UPDATE laptop_assets SET assigned_user_name = '์—…๋ฌด์šฉ(TEMP_44666b)', current_user_id = NULL WHERE status = 'stock'"); + $stmtStock->execute(); + echo "โœ… ์žฌ๊ณ (STOCK) ๋ช…์นญ ๋™๊ธฐํ™” ์™„๋ฃŒ.\n"; + + echo "--- ๐ŸŽ‰ ๋ชจ๋“  ๋ณต๊ตฌ ๋ฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ---"; + +} catch (Exception $e) { + echo "โŒ ์˜ค๋ฅ˜: " . $e->getMessage() . "\n"; +} +?> \ No newline at end of file diff --git a/RECOVER_MIGRATE.php b/RECOVER_MIGRATE.php new file mode 100644 index 0000000..61785d0 --- /dev/null +++ b/RECOVER_MIGRATE.php @@ -0,0 +1,89 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + echo "--- [๋ณต๊ตฌ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹œ์ž‘] ๋…ธํŠธ๋ถ ์ž์‚ฐ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ v2.1 ---\n\n"; + + // 2. ๋ฐฑ์—… ์ƒ์„ฑ + $backupPath = $dbPath . '.bak_' . date('Ymd_His'); + if (!copy($dbPath, $backupPath)) { + throw new Exception("๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ฐฑ์—… ์ƒ์„ฑ ์‹คํŒจ"); + } + echo "๐Ÿ›ก๏ธ ๋ฐ์ดํ„ฐ ์•ˆ์ „: ์ž‘์—… ์ „ ์›๋ณธ ๋ฐฑ์—…์ด ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ($backupPath)\n"; + + // 3. ์Šคํ‚ค๋งˆ ํ™•์žฅ (์‹ ๊ทœ ๊ทœ๊ฒฉ ์ปฌ๋Ÿผ ์ถ”๊ฐ€) + $newColumns = [ + 'disposal_recipient' => 'TEXT', + 'disposal_date' => 'TEXT', + 'real_user' => 'TEXT', + 'disposal_user_id' => 'INTEGER' + ]; + + foreach ($newColumns as $col => $type) { + try { + $db->exec("ALTER TABLE laptop_assets ADD COLUMN $col $type"); + echo "โœ… ์ปฌ๋Ÿผ ๋ณด์ • ์„ฑ๊ณต: $col\n"; + } catch (PDOException $e) { + if (strpos($e->getMessage(), 'duplicate column name') !== false) { + echo "โ„น๏ธ ์ด๋ฏธ ์กด์žฌํ•จ: $col (์Šคํ‚ค๋งˆ ์œ ์ง€)\n"; + } else { + throw $e; + } + } + } + + // 4. ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ - STOCK ์ž์‚ฐ '์—…๋ฌด์šฉ' ๋ช…์นญ ํ†ตํ•ฉ + $stmtStock = $db->prepare(" + UPDATE laptop_assets + SET assigned_user_name = '์—…๋ฌด์šฉ(TEMP_44666b)', + current_user_id = NULL + WHERE status = 'stock' + AND (assigned_user_name != '์—…๋ฌด์šฉ(TEMP_44666b)' OR assigned_user_name IS NULL) + "); + $stmtStock->execute(); + $affectedStock = $stmtStock->rowCount(); + echo "โœ… ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ: STOCK ์ž์‚ฐ $affectedStock ๊ฑด์˜ ์ž…๋ ฅ์„ '์—…๋ฌด์šฉ'์œผ๋กœ ํ†ต์ผํ–ˆ์Šต๋‹ˆ๋‹ค.\n"; + + // 5. ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ - ๋งค๊ฐ ๋Œ€์ƒ์ž ID ๋ณต๊ตฌ (์ง์› DB ๋Œ€์กฐ) + $allDisposed = $db->query(" + SELECT id, disposal_recipient + FROM laptop_assets + WHERE status = 'disposed' + AND disposal_recipient IS NOT NULL + AND disposal_user_id IS NULL + ")->fetchAll(PDO::FETCH_ASSOC); + + $idRestored = 0; + $userFinder = $db->prepare("SELECT id FROM users WHERE name = ? LIMIT 1"); + $idUpdater = $db->prepare("UPDATE laptop_assets SET disposal_user_id = ? WHERE id = ?"); + + foreach ($allDisposed as $row) { + $userFinder->execute([$row['disposal_recipient']]); + $uid = $userFinder->fetchColumn(); + if ($uid) { + $idUpdater->execute([$uid, $row['id']]); + $idRestored++; + } + } + echo "โœ… ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ: DISPOSED ์ž์‚ฐ $idRestored ๊ฑด์˜ ์‚ฌ์› ๋งคํ•‘์„ ์™„๋ฃŒํ–ˆ์Šต๋‹ˆ๋‹ค.\n\n"; + + echo "--- [๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์„ฑ๊ณต] ๋ณต๊ตฌ๋œ DB๊ฐ€ ์ตœ์‹  ๊ทœ๊ฒฉ์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ---\n"; + +} catch (Exception $e) { + echo "\nโŒ [๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹คํŒจ] ์˜ค๋ฅ˜ ๋‚ด์šฉ: " . $e->getMessage() . "\n"; +} diff --git a/api.php b/api.php index ffc57a2..e2e792d 100644 --- a/api.php +++ b/api.php @@ -669,34 +669,62 @@ LIMIT 1")->fetchColumn(); } $updates = []; $params = []; + $log_msg = ""; + if ($newStatus) { $updates[] = "status = ?"; $params[] = $newStatus; - // ๋งŒ์•ฝ ์ƒํƒœ๋ฅผ 'stock'(์žฌ๊ณ )์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ '์—…๋ฌด์šฉ'์œผ๋กœ ์„ค์ •, 'disposed'(๋งค๊ฐ)์ธ ๊ฒฝ์šฐ ์™„์ „ ์ดˆ๊ธฐํ™” if ($newStatus === 'stock') { $updates[] = "current_user_id = NULL"; $updates[] = "assigned_user_name = '์—…๋ฌด์šฉ(TEMP_44666b)'"; + $log_msg = "์ผ๊ด„ ์ƒํƒœ ๋ณ€๊ฒฝ: ์žฌ๊ณ  (์—…๋ฌด์šฉ ์ง€์ •)"; } elseif ($newStatus === 'disposed') { $updates[] = "current_user_id = NULL"; $updates[] = "assigned_user_name = NULL"; $updates[] = "disposal_date = '" . date('Y-m-d') . "'"; + $log_msg = "์ผ๊ด„ ์ƒํƒœ ๋ณ€๊ฒฝ: ๋งค๊ฐ๋จ"; + } elseif ($newStatus === 'assigned') { + $log_msg = "์ผ๊ด„ ์ƒํƒœ ๋ณ€๊ฒฝ: ์ง์›๋ฐฐ์ •"; } } if ($newModelId) { $updates[] = "model_id = ?"; $params[] = $newModelId; + $log_msg .= ($log_msg ? ", " : "") . "์ผ๊ด„ ๋ชจ๋ธ ๋ณ€๊ฒฝ(ID: $newModelId)"; } + if (empty($updates)) { echo json_encode(['success' => false, 'error' => 'No updates specified']); break; } - $sql = "UPDATE laptop_assets SET " . implode(", ", $updates) . " WHERE id IN (" . implode(",", array_fill( - 0, - count($ids), - "?" - )) . ")"; + + $placeholders = implode(",", array_fill(0, count($ids), "?")); + $sql = "UPDATE laptop_assets SET " . implode(", ", $updates) . " WHERE id IN ($placeholders)"; $stmt = $db->prepare($sql); $stmt->execute(array_merge($params, $ids)); + + // ํžˆ์Šคํ† ๋ฆฌ ์ผ๊ด„ ๊ธฐ๋ก + if ($log_msg) { + $history_sql = "INSERT INTO asset_history (asset_id, log_type, user_name, action_date, note) VALUES (?, 'bulk_update', '์‹œ์Šคํ…œ(์ผ๊ด„)', ?, ?)"; + $h_stmt = $db->prepare($history_sql); + foreach ($ids as $id) { + $h_stmt->execute([$id, date('Y-m-d'), $log_msg]); + } + } + + echo json_encode(['success' => true]); + break; + + case 'bulk_delete_laptops': + $data = json_decode(file_get_contents('php://input'), true); + $ids = $data['ids']; + if (empty($ids)) { + echo json_encode(['success' => false, 'error' => 'No items selected']); + break; + } + $placeholders = implode(",", array_fill(0, count($ids), "?")); + $db->prepare("DELETE FROM laptop_assets WHERE id IN ($placeholders)")->execute($ids); + // ๊ด€๋ จ ํžˆ์Šคํ† ๋ฆฌ๋„ ์‚ญ์ œ? ๋ณดํ†ต ์ž์‚ฐ ์‚ญ์ œ์‹œ์—๋Š” ํžˆ์Šคํ† ๋ฆฌ๋„ ํ•จ๊ป˜ ๋‚ ๋ฆฌ๊ฑฐ๋‚˜ ๋‚จ๊น€. ์—ฌ๊ธฐ์„  DB ์ •ํ•ฉ์„ฑ์„ ์œ„ํ•ด ์—ฐ์‡„ ์‚ญ์ œ๋Š” ์•ˆํ•˜๋”๋ผ๋„ ์ž์‚ฐ์€ ์‚ฌ๋ผ์ง. echo json_encode(['success' => true]); break; @@ -799,6 +827,33 @@ LIMIT 1")->fetchColumn(); echo json_encode(['success' => true]); break; + case 'bulk_delete_models': + $data = json_decode(file_get_contents('php://input'), true); + $ids = $data['ids']; + if (empty($ids)) { + echo json_encode(['success' => false, 'error' => 'No items selected']); + break; + } + try { + $db->beginTransaction(); + $placeholders = implode(",", array_fill(0, count($ids), "?")); + + // 1. ํ•ด๋‹น ๋ชจ๋ธ์„ ์ฐธ์กฐ ์ค‘์ธ ์ž์‚ฐ๋“ค์˜ ์—ฐ๊ฒฐ ๊ณ ๋ฆฌ ํ•ด์ œ (ID ์ฐธ์กฐ๋ฅผ NULL๋กœ ๋ณ€๊ฒฝ) + $stmt1 = $db->prepare("UPDATE laptop_assets SET model_id = NULL WHERE model_id IN ($placeholders)"); + $stmt1->execute($ids); + + // 2. ๋…ธํŠธ๋ถ ๋ชจ๋ธ ๋งˆ์Šคํ„ฐ ์ •๋ณด ์‚ญ์ œ + $stmt2 = $db->prepare("DELETE FROM laptop_models WHERE id IN ($placeholders)"); + $stmt2->execute($ids); + + $db->commit(); + echo json_encode(['success' => true]); + } catch (Exception $e) { + $db->rollBack(); + echo json_encode(['success' => false, 'error' => $e->getMessage()]); + } + break; + case 'bulk_update_users': $data = json_decode(file_get_contents('php://input'), true); $userIds = $data['user_ids']; @@ -1033,6 +1088,20 @@ ORDER BY r.id DESC"; } break; + case 'get_settings': + $settings = $db->query("SELECT key_name, value FROM system_settings")->fetchAll(PDO::FETCH_KEY_PAIR); + echo json_encode(['success' => true, 'settings' => $settings]); + break; + + case 'update_settings': + $data = json_decode(file_get_contents('php://input'), true); + $stmt = $db->prepare("INSERT OR REPLACE INTO system_settings (key_name, value) VALUES (?, ?)"); + foreach ($data['settings'] as $key => $value) { + $stmt->execute([$key, (string) $value]); + } + echo json_encode(['success' => true]); + break; + case 'return_general_rental': $data = json_decode(file_get_contents('php://input'), true); $returnDate = date('Y-m-d'); diff --git a/check_schema.php b/check_schema.php index 7a18594..74ae34a 100644 --- a/check_schema.php +++ b/check_schema.php @@ -1,4 +1,19 @@ query("PRAGMA table_info(laptop_assets)")->fetchAll(PDO::FETCH_ASSOC); -echo json_encode($cols, JSON_PRETTY_PRINT); \ No newline at end of file +try { + $db = new PDO('sqlite:d:/Docker/jasan/dda/assets.db'); + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + echo "--- LAPTOP_ASSETS SCHEMA ---\n"; + $res = $db->query('PRAGMA table_info(laptop_assets)')->fetchAll(); + foreach ($res as $col) { + echo "{$col['name']} ({$col['type']})\n"; + } + + echo "\n--- LAPTOP_MODELS SCHEMA ---\n"; + $res = $db->query('PRAGMA table_info(laptop_models)')->fetchAll(); + foreach ($res as $col) { + echo "{$col['name']} ({$col['type']})\n"; + } +} catch (Exception $e) { + echo $e->getMessage(); +} \ No newline at end of file diff --git a/check_tables.php b/check_tables.php new file mode 100644 index 0000000..7f7d961 --- /dev/null +++ b/check_tables.php @@ -0,0 +1,9 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $tables = $db->query("SELECT name FROM sqlite_master WHERE type='table'")->fetchAll(PDO::FETCH_COLUMN); + print_r($tables); +} catch (Exception $e) { + echo $e->getMessage(); +} diff --git a/dda/assets.db b/dda/assets.db index 7d42aaf..752be65 100644 Binary files a/dda/assets.db and b/dda/assets.db differ diff --git a/dda/assets.db.back b/dda/assets.db.back new file mode 100644 index 0000000..7d42aaf Binary files /dev/null and b/dda/assets.db.back differ diff --git a/dda/assets.db.bak_20260304_122706 b/dda/assets.db.bak_20260304_122706 new file mode 100644 index 0000000..7d42aaf Binary files /dev/null and b/dda/assets.db.bak_20260304_122706 differ diff --git a/dda/assets.db.bak_20260304_122901 b/dda/assets.db.bak_20260304_122901 new file mode 100644 index 0000000..7d42aaf Binary files /dev/null and b/dda/assets.db.bak_20260304_122901 differ diff --git a/debug_db.php b/debug_db.php new file mode 100644 index 0000000..e622bea --- /dev/null +++ b/debug_db.php @@ -0,0 +1,5 @@ +query("SELECT id, asset_tag, status, assigned_user_name FROM laptop_assets LIMIT 50")->fetchAll(PDO::FETCH_ASSOC); +echo json_encode($rows, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); +?> \ No newline at end of file diff --git a/general_rental.php b/general_rental.php index 0cde8fd..261225b 100644 --- a/general_rental.php +++ b/general_rental.php @@ -67,102 +67,118 @@ - -
-