"error", "message" => "File konfigurasi database tidak ditemukan."]); exit(); } // Koneksi database $conn = new mysqli( $dbConfig['db_servername'], $dbConfig['db_username'], $dbConfig['db_password'], $dbConfig['db_name'] ); if ($conn->connect_error) { echo json_encode(["status" => "error", "message" => "Koneksi database gagal: " . $conn->connect_error]); exit(); } $request_method = $_SERVER["REQUEST_METHOD"]; $action = $_GET['action'] ?? ''; // 🔥 DEBUG MODE $debug = isset($_GET['debug']) && $_GET['debug'] === 'true'; if ($debug) { error_log("🔧 DEBUG MODE - Request Method: $request_method, Action: $action"); } // 🔥 GET ALL LEGAL DOCUMENTS UNTUK GRID if ($request_method == 'GET' && $action === 'get_all_documents') { if ($debug) error_log("📥 Processing get_all_documents"); // ✅ FIX 1: MENAMBAHKAN KOMA SETELAH `apm.housing_name` DI SELECT CLAUSE $sql = " SELECT tld.*, k.full_name, k.konsumen_code, sp.unit_code, sp.cluster_name, sp.kavling_no, sp.block_no, sp.house_no, apm.housing_name, -- KOMA HILANG DI SINI SEBELUMNYA tld.uncompletedoc FROM trx_legal_document tld LEFT JOIN konsumen k ON tld.client_id = k.id LEFT JOIN trx_sales_property tsp ON k.id = tsp.konsumen_id LEFT JOIN stock_property sp ON tsp.stock_property_id = sp.id LEFT JOIN asset_project_master apm ON sp.project_code = apm.project_code ORDER BY tld.created_at DESC "; $result = $conn->query($sql); $docs = []; if ($result && $result->num_rows > 0) { while ($row = $result->fetch_assoc()) { $docs[] = [ 'id' => (int)$row['id'], 'client_id' => (int)$row['client_id'], 'document_code' => $row['document_code'], 'is_complete' => (bool)$row['is_complete'], 'is_akad_done' => (bool)$row['is_akad_done'], 'notes' => $row['notes'], 'created_at' => $row['created_at'], 'updated_at' => $row['updated_at'], 'full_name' => $row['full_name'] ?? '-', 'konsumen_code' => $row['konsumen_code'] ?? '-', 'unit_code' => $row['unit_code'] ?? '-', 'housing_name' => $row['housing_name'] ?? '-', 'cluster' => $row['cluster_name'] ?? '-', 'cavling' => $row['kavling_no'] ?? '-', // Menggunakan 'cavling' karena service Vue mengharapkan ini 'block' => $row['block_no'] ?? '-', 'house_no' => $row['house_no'] ?? '-', 'date_transaction' => $row['date_transaction'] ?? null, // KOMA HILANG DI SINI SEBELUMNYA 'uncompletedoc' => $row['uncompletedoc'] ?? '' ]; } } if ($debug) error_log("📤 Returning " . count($docs) . " documents"); echo json_encode($docs); exit(); } // 🔥 GET DOCUMENT DETAIL UNTUK FORM EDIT if ($request_method == 'GET' && $action === 'get_document_detail') { $client_id = (int)($_GET['client_id'] ?? 0); if ($debug) error_log("📥 Processing get_document_detail for client_id: $client_id"); if ($client_id === 0) { echo json_encode([]); exit(); } $sql = "SELECT document_code, document_name, is_submitted, notes, file_url FROM trx_legal_document_detail WHERE client_id = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("i", $client_id); $stmt->execute(); $result = $stmt->get_result(); $details = []; while ($row = $result->fetch_assoc()) { $details[] = [ 'document_code' => $row['document_code'], 'document_name' => $row['document_name'], 'is_submitted' => (bool)$row['is_submitted'], 'notes' => $row['notes'], 'file_url' => $row['file_url'] ]; } if ($debug) error_log("📤 Returning " . count($details) . " detail records"); echo json_encode($details); exit(); } // 🔥 GET CLIENTS UNTUK DROPDOWN if ($request_method == 'GET' && $action === 'get_clients') { if ($debug) error_log("📥 Processing get_clients"); $sql = " SELECT k.id AS client_id, k.full_name, k.konsumen_code, sp.unit_code, sp.cluster_name, sp.block_no, sp.kavling_no, sp.house_no, apm.housing_name, tsp.status_sales FROM trx_sales_property tsp INNER JOIN konsumen k ON tsp.konsumen_id = k.id INNER JOIN stock_property sp ON tsp.stock_property_id = sp.id INNER JOIN asset_project_master apm ON sp.project_code = apm.project_code WHERE NOT EXISTS ( SELECT 1 FROM trx_legal_document tld WHERE tld.client_id = k.id ) ORDER BY k.full_name "; $result = $conn->query($sql); $clients = []; if ($result && $result->num_rows > 0) { while ($row = $result->fetch_assoc()) { $clients[] = $row; } } if ($debug) error_log("📤 Returning " . count($clients) . " clients"); echo json_encode($clients); exit(); } // 🔥 GET DOCUMENT TYPES if ($request_method == 'GET' && $action === 'get_documents') { if ($debug) error_log("📥 Processing get_documents"); $sql = "SELECT document_id AS document_code, doc_description AS document_name FROM tbldocument WHERE company_id = 1"; $result = $conn->query($sql); $documents = []; if ($result && $result->num_rows > 0) { while ($row = $result->fetch_assoc()) { $documents[] = $row; } } if ($debug) error_log("📤 Returning " . count($documents) . " document types"); echo json_encode($documents); exit(); } // 🔥 CREATE & UPDATE LEGAL DOCUMENT if ($request_method == 'POST') { $data = json_decode(file_get_contents("php://input"), true); if ($debug) { error_log("📥 POST Request Received"); error_log("📥 Raw POST data: " . file_get_contents("php://input")); error_log("📥 Parsed data: " . json_encode($data)); } // Handle delete if (isset($data['action']) && $data['action'] === 'delete' && isset($data['id'])) { if ($debug) error_log("🗑️ Processing DELETE for ID: " . $data['id']); $conn->begin_transaction(); try { // Delete detail dulu $stmt = $conn->prepare("DELETE FROM trx_legal_document_detail WHERE client_id IN (SELECT client_id FROM trx_legal_document WHERE id = ?)"); $stmt->bind_param("i", $data['id']); $stmt->execute(); // Delete master $stmt = $conn->prepare("DELETE FROM trx_legal_document WHERE id = ?"); $stmt->bind_param("i", $data['id']); if ($stmt->execute()) { $conn->commit(); if ($debug) error_log("✅ DELETE successful"); echo json_encode(['status' => 'success', 'message' => 'Data berhasil dihapus']); } else { throw new Exception("Gagal menghapus data"); } } catch (Exception $e) { $conn->rollback(); if ($debug) error_log("❌ DELETE failed: " . $e->getMessage()); echo json_encode(['status' => 'error', 'message' => 'Gagal menghapus: ' . $e->getMessage()]); } exit(); } // Handle update if (isset($data['action']) && $data['action'] === 'update' && isset($data['id'])) { if ($debug) error_log("📝 Processing UPDATE for ID: " . $data['id']); $conn->begin_transaction(); try { $id = (int)$data['id']; $client_id = (int)$data['client_id']; $date_transaction = $data['date_transaction'] ?? date('Y-m-d'); $is_akad_done = isset($data['is_akad_done']) ? (int)$data['is_akad_done'] : 0; $notes = $data['notes'] ?? ''; if ($debug) { error_log("📝 Update data - Client: $client_id, Akad: $is_akad_done"); error_log("📝 Documents count: " . (isset($data['documents']) ? count($data['documents']) : 0)); } // 1. UPDATE MASTER $stmt = $conn->prepare("UPDATE trx_legal_document SET date_transaction = ?, is_akad_done = ?, notes = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?"); $stmt->bind_param("sisi", $date_transaction, $is_akad_done, $notes, $id); if (!$stmt->execute()) { throw new Exception("Gagal update master: " . $stmt->error); } $stmt->close(); // 2. UPDATE DETAIL - Delete yang lama, insert yang baru // Delete existing details $stmt_delete = $conn->prepare("DELETE FROM trx_legal_document_detail WHERE client_id = ?"); $stmt_delete->bind_param("i", $client_id); $stmt_delete->execute(); $stmt_delete->close(); if ($debug) error_log("✅ Old details deleted"); // Insert new details if (isset($data['documents']) && is_array($data['documents'])) { $stmt_detail = $conn->prepare("INSERT INTO trx_legal_document_detail (company_id, client_id, document_code, document_name, is_submitted, notes) VALUES (1, ?, ?, ?, ?, ?)"); $all_submitted = true; $detail_count = 0; foreach ($data['documents'] as $doc) { $doc_code = $doc['document_code'] ?? ''; $doc_name = $doc['document_name'] ?? 'Unknown'; $is_submitted = isset($doc['is_submitted']) ? (int)$doc['is_submitted'] : 0; $doc_notes = $doc['notes'] ?? ''; if (!$is_submitted) $all_submitted = false; if ($debug) error_log("📝 Inserting detail - Code: $doc_code, Name: $doc_name, Submitted: $is_submitted"); $stmt_detail->bind_param("issis", $client_id, $doc_code, $doc_name, $is_submitted, $doc_notes); if (!$stmt_detail->execute()) { throw new Exception("Gagal update detail: " . $stmt_detail->error); } $detail_count++; } $stmt_detail->close(); if ($debug) error_log("✅ Details inserted - Count: $detail_count, All submitted: " . ($all_submitted ? 'Yes' : 'No')); // Update status complete di master $stmt_update = $conn->prepare("UPDATE trx_legal_document SET is_complete = ? WHERE id = ?"); $complete_status = $all_submitted ? 1 : 0; $stmt_update->bind_param("ii", $complete_status, $id); $stmt_update->execute(); $stmt_update->close(); if ($debug) error_log("✅ Master status updated - Complete: $complete_status"); } $conn->commit(); if ($debug) error_log("✅ UPDATE transaction committed"); echo json_encode([ 'status' => 'success', 'message' => 'Dokumen legal berhasil diupdate', 'data' => ['master_id' => $id] ]); } catch (Exception $e) { $conn->rollback(); if ($debug) error_log("❌ UPDATE transaction failed: " . $e->getMessage()); echo json_encode(['status' => 'error', 'message' => 'Gagal update: ' . $e->getMessage()]); } exit(); } // CREATE NEW DOCUMENT (tanpa action parameter) if ($debug) error_log("🆕 Processing CREATE new document"); $client_id = (int)$data['client_id']; $notes = $data['notes'] ?? ''; $date_transaction = $data['date_transaction'] ?? date('Y-m-d'); $is_akad_done = isset($data['is_akad_done']) ? (int)$data['is_akad_done'] : 0; if ($debug) { error_log("🆕 Create data - Client: $client_id, Akad: $is_akad_done, Notes: $notes"); error_log("🆕 Documents count: " . (isset($data['documents']) ? count($data['documents']) : 0)); if (isset($data['documents'])) { foreach ($data['documents'] as $index => $doc) { error_log("🆕 Document $index: " . json_encode($doc)); } } } $conn->begin_transaction(); try { // 1. INSERT MASTER $document_code = 'LEGAL_' . time() . '_' . $client_id; $stmt = $conn->prepare("INSERT INTO trx_legal_document (company_id, client_id, document_code, notes, is_akad_done, date_transaction) VALUES (1, ?, ?, ?, ?, ?)"); $stmt->bind_param("issis", $client_id, $document_code, $notes, $is_akad_done, $date_transaction); if (!$stmt->execute()) { throw new Exception("Gagal simpan master: " . $stmt->error); } $master_id = $conn->insert_id; $stmt->close(); if ($debug) error_log("✅ Master inserted - ID: $master_id"); // 2. INSERT DETAIL if (isset($data['documents']) && is_array($data['documents'])) { $stmt_detail = $conn->prepare("INSERT INTO trx_legal_document_detail (company_id, client_id, document_code, document_name, is_submitted, notes) VALUES (1, ?, ?, ?, ?, ?)"); $all_submitted = true; $detail_count = 0; foreach ($data['documents'] as $doc) { $doc_code = $doc['document_code'] ?? ''; $doc_name = $doc['document_name'] ?? 'Unknown'; $is_submitted = isset($doc['is_submitted']) ? (int)$doc['is_submitted'] : 0; $doc_notes = $doc['notes'] ?? ''; if (!$is_submitted) $all_submitted = false; if ($debug) error_log("📝 Inserting detail - Code: $doc_code, Name: $doc_name, Submitted: $is_submitted"); $stmt_detail->bind_param("issis", $client_id, $doc_code, $doc_name, $is_submitted, $doc_notes); if (!$stmt_detail->execute()) { throw new Exception("Gagal simpan detail: " . $stmt_detail->error); } $detail_count++; } $stmt_detail->close(); if ($debug) error_log("✅ Details inserted - Count: $detail_count, All submitted: " . ($all_submitted ? 'Yes' : 'No')); // Update status complete $stmt_update = $conn->prepare("UPDATE trx_legal_document SET is_complete = ? WHERE id = ?"); $complete_status = $all_submitted ? 1 : 0; $stmt_update->bind_param("ii", $complete_status, $master_id); $stmt_update->execute(); $stmt_update->close(); if ($debug) error_log("✅ Status updated - Complete: $complete_status"); } else { if ($debug) error_log("⚠️ No documents to insert"); } $conn->commit(); if ($debug) error_log("✅ CREATE transaction committed"); echo json_encode([ 'status' => 'success', 'message' => 'Dokumen legal berhasil dibuat', 'data' => ['master_id' => $master_id] ]); } catch (Exception $e) { $conn->rollback(); if ($debug) error_log("❌ CREATE transaction failed: " . $e->getMessage()); echo json_encode(['status' => 'error', 'message' => 'Gagal menyimpan: ' . $e->getMessage()]); } exit(); } // 🔥 RUN BATCH LEGAL DOCUMENT if ($request_method == 'POST' && $action === 'run_batch') { $type = $_REQUEST['type'] ?? ''; $mode = $_REQUEST['mode'] ?? ''; if ($type !== 'legal') { echo json_encode(['status' => 'error', 'message' => 'Batch type tidak valid']); exit(); } try { if ($mode === 'ALL') { $conn->query("CALL sp_trx_sales_legal_document_batch_all()"); } elseif ($mode === 'MISS') { $conn->query("CALL sp_trx_sales_legal_document_batch_miss()"); } else { echo json_encode(['status' => 'error', 'message' => 'Mode tidak valid: ' . $mode]); exit(); } // Hitung hasil setelah batch $result = $conn->query("SELECT COUNT(*) AS total FROM trx_legal_document WHERE is_deleted = 0"); $row = $result->fetch_assoc(); $count = (int)$row['total']; echo json_encode([ 'success' => true, 'message' => "Batch $mode Legal Document berhasil", 'type' => $type, 'mode' => $mode, 'data' => [ 'rows_processed' => $count, 'executed_at' => date("Y-m-d H:i:s") ] ]); } catch (Exception $e) { echo json_encode(['status' => 'error', 'message' => 'Batch Legal Document gagal: ' . $e->getMessage()]); } exit(); } // 🔥 DEFAULT RESPONSE - JIKA TIDAK ADA ACTION YANG COCOK if ($debug) { error_log("❌ No matching action found"); error_log("❌ Request Method: $request_method"); error_log("❌ Action: $action"); error_log("❌ GET params: " . json_encode($_GET)); } echo json_encode(["status" => "error", "message" => "Endpoint tidak dikenali"]); $conn->close(); ?>