', '
', '
'], "\n", $body)); $mail->send(); return ['ok' => true, 'msg' => $data['contact_email']]; } catch (\Exception $e) { return ['ok' => false, 'msg' => $e->getMessage()]; } } // FUNGSI UTOMATISASI DETAIL BANDARA DARURAT / SINKRONISASI FLIGHT DETAILS function get_airport_details($code) { $airports_map = [ 'CGK' => ['Jakarta (CGK)', 'Soekarno Hatta Intl. Airport Terminal 3'], 'SIN' => ['Singapore (SIN)', 'Changi International Airport Terminal 4'], 'DPS' => ['Denpasar (DPS)', 'Ngurah Rai Intl. Airport Terminal Domestic'], 'SUB' => ['Surabaya (SUB)', 'Juanda International Airport Terminal 1'], 'KUL' => ['Kuala Lumpur (KUL)', 'Kuala Lumpur International Airport T2'], ]; $code = strtoupper(trim($code)); return [ 'name' => $airports_map[$code][0] ?? "Airport " . $code, 'detail' => $airports_map[$code][1] ?? "Departures/Arrivals Terminal" ]; } // FUNGSI OTOMATISASI LOGO MASKAPAI (PHP) - MENGGUNAKAN PNG FORMAT DARI KIWI.COM AGAR DAPAT DICETAK CANVAS function get_airline_logo($carrier_name) { $carrier_name = strtolower(trim($carrier_name)); if (empty($carrier_name)) return ''; $code = ''; if (strpos($carrier_name, 'garuda') !== false) $code = 'GA'; elseif (strpos($carrier_name, 'singapore') !== false) $code = 'SQ'; elseif (strpos($carrier_name, 'batik') !== false) $code = 'ID'; elseif (strpos($carrier_name, 'lion') !== false) $code = 'JT'; elseif (strpos($carrier_name, 'airasia') !== false || strpos($carrier_name, 'air asia') !== false) $code = 'AK'; elseif (strpos($carrier_name, 'citilink') !== false) $code = 'QG'; elseif (strpos($carrier_name, 'wings') !== false) $code = 'IW'; elseif (strpos($carrier_name, 'sriwijaya') !== false) $code = 'SJ'; elseif (strpos($carrier_name, 'malaysia') !== false) $code = 'MH'; elseif (strpos($carrier_name, 'ana') !== false || strpos($carrier_name, 'all nippon') !== false) $code = 'NH'; elseif (strpos($carrier_name, 'japan') !== false) $code = 'JL'; elseif (strpos($carrier_name, 'emirates') !== false) $code = 'EK'; elseif (strpos($carrier_name, 'qatar') !== false) $code = 'QR'; elseif (strpos($carrier_name, 'cathay') !== false) $code = 'CX'; elseif (strpos($carrier_name, 'saudia') !== false || strpos($carrier_name, 'saudi') !== false) $code = 'SV'; elseif (strpos($carrier_name, 'thai') !== false) $code = 'TG'; elseif (strpos($carrier_name, 'scoot') !== false) $code = 'TR'; elseif (strpos($carrier_name, 'pelita') !== false) $code = 'IP'; elseif (strpos($carrier_name, 'transnusa') !== false) $code = '8B'; else { preg_match('/\b[A-Z0-9]{2}\b/', strtoupper($carrier_name), $matches); if (!empty($matches[0])) { $code = $matches[0]; } else { $code = strtoupper(substr($carrier_name, 0, 2)); } } return "https://images.kiwi.com/airlines/64/{$code}.png"; } // 3. AUTO-INITIALIZE TABEL & DATA DEFAULT try { // A. Buat Tabel Master Settings $pdo->exec("CREATE TABLE IF NOT EXISTS invoice_master_settings ( id INT PRIMARY KEY, invoice_logo_url TEXT NULL, company_name VARCHAR(255) NULL, company_address TEXT NULL, footer_no_print_title VARCHAR(255) NULL, footer_no_print_desc VARCHAR(255) NULL, footer_support_phone VARCHAR(100) NULL, footer_support_email VARCHAR(100) NULL, footer_support_web VARCHAR(100) NULL, footer_eco_title VARCHAR(100) NULL, footer_eco_sub VARCHAR(100) NULL, ticket_pnr VARCHAR(50) NULL, ticket_number VARCHAR(100) NULL, airline_code VARCHAR(50) NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); // Pastikan kolom baru terbuat jika tabel lama belum memilikinya try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN ticket_pnr VARCHAR(50) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN ticket_number VARCHAR(100) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN airline_code VARCHAR(50) NULL"); } catch (PDOException $e) {} // Migrasi fail-silent kolom rekening bank master try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN bank_bri_name VARCHAR(100) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN bank_bri_holder VARCHAR(255) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN bank_bri_norek VARCHAR(100) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN bank_mandiri_name VARCHAR(100) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN bank_mandiri_holder VARCHAR(255) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN bank_mandiri_norek VARCHAR(100) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN bank_cimb_name VARCHAR(100) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN bank_cimb_holder VARCHAR(255) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN bank_cimb_norek VARCHAR(100) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN bank_bca_name VARCHAR(100) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN bank_bca_holder VARCHAR(255) NULL"); } catch (PDOException $e) {} try { $pdo->exec("ALTER TABLE invoice_master_settings ADD COLUMN bank_bca_norek VARCHAR(100) NULL"); } catch (PDOException $e) {} // Seed Data Master Default jika kosong $stmt_m_count = $pdo->query("SELECT COUNT(*) FROM invoice_master_settings WHERE id = 1"); if ($stmt_m_count->fetchColumn() == 0) { $stmt_m_ins = $pdo->prepare("INSERT INTO invoice_master_settings ( id, invoice_logo_url, company_name, company_address, footer_no_print_title, footer_no_print_desc, footer_support_phone, footer_support_email, footer_support_web, footer_eco_title, footer_eco_sub, ticket_pnr, ticket_number, airline_code, bank_bri_name, bank_bri_holder, bank_bri_norek, bank_mandiri_name, bank_mandiri_holder, bank_mandiri_norek, bank_cimb_name, bank_cimb_holder, bank_cimb_norek, bank_bca_name, bank_bca_holder, bank_bca_norek ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt_m_ins->execute([ 1, 'https://plain-apac-prod-public.komododecks.com/202606/20/zBiz1pT76LPgsDgGiz3k/image.png', 'PT HYTRAVELLERS', "Ruko Keprimall No.46, Sukajadi, Kec. Batam Kota, Kota Batam,\nKepulauan Riau 29444, Indonesia", 'Tidak perlu cetak!', 'E-tiket dapat langsung ditunjukkan melalui HP.', '0823 7456 4489 (24 jam)', 'support@hytravellers.asia', 'https://hytravellers.asia', 'HYTRAVELLERS.ASIA', 'Peduli lingkungan', 'Payment Not Verified', 'Payment Not Verified', 'GA-123', 'BANK BRI (BRIVA)', 'PT HYTRAVELLERS', '2570833000117296', 'BANK MANDIRI', 'PT HYTRAVELLERS', '8980833000117296', 'BANK CIMB NIAGA', 'PT HYTRAVELLERS', '8429033000117296', 'Masuk Menu TFR Virtual Account BCA', 'PT HYTRAVELLERS', '3000833000117296' ]); } else { // FIX: Sinkronisasi nama perusahaan dari Hilton ke HYTRAVELLERS untuk database lama $pdo->exec("UPDATE invoice_master_settings SET company_name = 'PT HYTRAVELLERS' WHERE id = 1 AND (company_name = 'PT Hilton Tours Travel' OR company_name IS NULL OR company_name = '')"); // Sinkronisasi data default untuk database lama yang baru melakukan update kolom $pdo->exec("UPDATE invoice_master_settings SET ticket_pnr = 'Payment Not Verified' WHERE id = 1 AND (ticket_pnr IS NULL OR ticket_pnr = '')"); $pdo->exec("UPDATE invoice_master_settings SET ticket_number = 'Payment Not Verified' WHERE id = 1 AND (ticket_number IS NULL OR ticket_number = '')"); $pdo->exec("UPDATE invoice_master_settings SET airline_code = 'GA-123' WHERE id = 1 AND (airline_code IS NULL OR airline_code = '')"); // Sync bank details jika kosong $pdo->exec("UPDATE invoice_master_settings SET bank_bri_name = 'BANK BRI (BRIVA)', bank_bri_holder = 'PT HYTRAVELLERS', bank_bri_norek = '2570833000117296', bank_mandiri_name = 'BANK MANDIRI', bank_mandiri_holder = 'PT HYTRAVELLERS', bank_mandiri_norek = '8980833000117296', bank_cimb_name = 'BANK CIMB NIAGA', bank_cimb_holder = 'PT HYTRAVELLERS', bank_cimb_norek = '8429033000117296', bank_bca_name = 'Masuk Menu TFR Virtual Account BCA', bank_bca_holder = 'PT HYTRAVELLERS', bank_bca_norek = '3000833000117296' WHERE id = 1 AND (bank_bri_name IS NULL OR bank_bri_name = '')"); } // Ambil Data Master Global $stmt_m = $pdo->query("SELECT * FROM invoice_master_settings WHERE id = 1"); $master_data = $stmt_m->fetch(); // B. Buat Tabel Invoice Settings (Individual) $pdo->exec("CREATE TABLE IF NOT EXISTS invoice_settings ( id INT PRIMARY KEY, invoice_logo_url TEXT NULL, company_name VARCHAR(255) NULL, company_address TEXT NULL, footer_no_print_title VARCHAR(255) NULL, footer_no_print_desc VARCHAR(255) NULL, footer_support_phone VARCHAR(100) NULL, footer_support_email VARCHAR(100) NULL, footer_support_web VARCHAR(100) NULL, footer_eco_title VARCHAR(100) NULL, footer_eco_sub VARCHAR(100) NULL, invoice_id VARCHAR(100) NOT NULL, booking_id VARCHAR(100) NOT NULL, booking_date VARCHAR(100) NOT NULL, issue_date VARCHAR(100) NOT NULL, payment_method VARCHAR(100) NOT NULL, payment_status VARCHAR(50) NOT NULL, contact_name VARCHAR(255) NOT NULL, contact_email VARCHAR(255) NOT NULL, contact_phone VARCHAR(50) NOT NULL, passenger_name VARCHAR(255) NOT NULL, passenger_type VARCHAR(50) NOT NULL, passenger_identity VARCHAR(100) NOT NULL, f1_carrier VARCHAR(100) NOT NULL, f1_code VARCHAR(50) NOT NULL, f1_class VARCHAR(100) NOT NULL, f1_from_code VARCHAR(10) NOT NULL, f1_from_name VARCHAR(255) NOT NULL, f1_from_detail VARCHAR(255) NOT NULL, f1_to_code VARCHAR(10) NOT NULL, f1_to_name VARCHAR(255) NOT NULL, f1_to_detail VARCHAR(255) NOT NULL, f1_date VARCHAR(100) NOT NULL, f1_time VARCHAR(100) NOT NULL, f1_duration VARCHAR(100) NOT NULL, f1_baggage VARCHAR(50) NOT NULL, f2_carrier VARCHAR(100) NOT NULL, f2_code VARCHAR(50) NOT NULL, f2_class VARCHAR(100) NOT NULL, f2_from_code VARCHAR(10) NOT NULL, f2_from_name VARCHAR(255) NOT NULL, f2_from_detail VARCHAR(255) NOT NULL, f2_to_code VARCHAR(10) NOT NULL, f2_to_name VARCHAR(255) NOT NULL, f2_to_detail VARCHAR(255) NOT NULL, f2_date VARCHAR(100) NOT NULL, f2_time VARCHAR(100) NOT NULL, f2_duration VARCHAR(100) NOT NULL, f2_baggage VARCHAR(50) NOT NULL, ticket_pnr VARCHAR(50) NOT NULL, ticket_number VARCHAR(100) NOT NULL, airline_code VARCHAR(50) NOT NULL, price_basic DECIMAL(12,2) NOT NULL, price_tax DECIMAL(12,2) NOT NULL, price_other DECIMAL(12,2) NOT NULL, price_fee DECIMAL(12,2) NOT NULL, price_total DECIMAL(12,2) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"); // Periksa data bawaan (ID = 1) $stmt = $pdo->prepare("SELECT COUNT(*) FROM invoice_settings WHERE id = 1"); $stmt->execute(); if ($stmt->fetchColumn() == 0) { $stmt_ins = $pdo->prepare("INSERT INTO invoice_settings ( id, invoice_logo_url, company_name, company_address, footer_no_print_title, footer_no_print_desc, footer_support_phone, footer_support_email, footer_support_web, footer_eco_title, footer_eco_sub, invoice_id, booking_id, booking_date, issue_date, payment_method, payment_status, contact_name, contact_email, contact_phone, passenger_name, passenger_type, passenger_identity, f1_carrier, f1_code, f1_class, f1_from_code, f1_from_name, f1_from_detail, f1_to_code, f1_to_name, f1_to_detail, f1_date, f1_time, f1_duration, f1_baggage, f2_carrier, f2_code, f2_class, f2_from_code, f2_from_name, f2_from_detail, f2_to_code, f2_to_name, f2_to_detail, f2_date, f2_time, f2_duration, f2_baggage, ticket_pnr, ticket_number, airline_code, price_basic, price_tax, price_other, price_fee, price_total ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt_ins->execute([ 1, $master_data['invoice_logo_url'], $master_data['company_name'], $master_data['company_address'], $master_data['footer_no_print_title'], $master_data['footer_no_print_desc'], $master_data['footer_support_phone'], $master_data['footer_support_email'], $master_data['footer_support_web'], $master_data['footer_eco_title'], $master_data['footer_eco_sub'], 'INV/20260620/HT/000013', '13', '20 Jun 2026, 12:18', '20 Jun 2026, 12:18', 'Bank Transfer', 'PENDING', 'ANDI HANDIKA', 'ikawahyuni244@gmail.com', '+6289520877877', 'ANDI HANDIKA', 'Adult', 'Identity Document Uploaded', 'Garuda Indonesia', 'GA-123', 'Economy (Promo)', 'CGK', 'Jakarta (CGK)', 'Soekarno Hatta Intl. Airport Terminal 3', 'KNO', 'Medan (KNO)', 'Kualanamu Intl. Airport Arrivals', 'Wed, 26 Jun 2026', '19:15 - 21:40', 'Duration 2h 25m', 'Baggage 23 kg', '', '', '', '', '', '', '', '', '', '', '', '', $master_data['ticket_pnr'], $master_data['ticket_number'], $master_data['airline_code'], 1893321, 212036, 0, 15000, 2120357 ]); } // FIX: Sinkronisasi nama perusahaan lama di invoice_settings (ID=1 mock) dari Hilton ke HYTravellers $pdo->exec("UPDATE invoice_settings SET company_name = 'PT HYTRAVELLERS' WHERE id = 1 AND company_name = 'PT Hilton Tours Travel'"); } catch (PDOException $e) { die("Gagal inisialisasi tabel: " . $e->getMessage()); } $success_msg = ""; $error_msg = ""; // ======================================================== // 4. PROSES SIMPAN PERUBAHAN CONFIG MASTER // ======================================================== if (isset($_POST['update_master_settings'])) { try { $stmt_up_m = $pdo->prepare("UPDATE invoice_master_settings SET invoice_logo_url = ?, company_name = ?, company_address = ?, footer_no_print_title = ?, footer_no_print_desc = ?, footer_support_phone = ?, footer_support_email = ?, footer_support_web = ?, footer_eco_title = ?, footer_eco_sub = ?, ticket_pnr = ?, ticket_number = ?, airline_code = ?, bank_bri_name = ?, bank_bri_holder = ?, bank_bri_norek = ?, bank_mandiri_name = ?, bank_mandiri_holder = ?, bank_mandiri_norek = ?, bank_cimb_name = ?, bank_cimb_holder = ?, bank_cimb_norek = ?, bank_bca_name = ?, bank_bca_holder = ?, bank_bca_norek = ? WHERE id = 1"); $stmt_up_m->execute([ $_POST['m_invoice_logo_url'], $_POST['m_company_name'], $_POST['m_company_address'], $_POST['m_footer_no_print_title'], $_POST['m_footer_no_print_desc'], $_POST['m_footer_support_phone'], $_POST['m_footer_support_email'], $_POST['m_footer_support_web'], $_POST['m_footer_eco_title'], $_POST['m_footer_eco_sub'], $_POST['m_ticket_pnr'], $_POST['m_ticket_number'], $_POST['m_airline_code'], $_POST['m_bank_bri_name'], $_POST['m_bank_bri_holder'], $_POST['m_bank_bri_norek'], $_POST['m_bank_mandiri_name'], $_POST['m_bank_mandiri_holder'], $_POST['m_bank_mandiri_norek'], $_POST['m_bank_cimb_name'], $_POST['m_bank_cimb_holder'], $_POST['m_bank_cimb_norek'], $_POST['m_bank_bca_name'], $_POST['m_bank_bca_holder'], $_POST['m_bank_bca_norek'] ]); // FIX: Setelah master diperbarui, sinkronisasi company_name ke SEMUA invoice_settings yang ada $new_company_name = $_POST['m_company_name']; $new_logo = $_POST['m_invoice_logo_url']; $new_address = $_POST['m_company_address']; $new_footer_no_print_title = $_POST['m_footer_no_print_title']; $new_footer_no_print_desc = $_POST['m_footer_no_print_desc']; $new_footer_support_phone = $_POST['m_footer_support_phone']; $new_footer_support_email = $_POST['m_footer_support_email']; $new_footer_support_web = $_POST['m_footer_support_web']; $new_footer_eco_title = $_POST['m_footer_eco_title']; $new_footer_eco_sub = $_POST['m_footer_eco_sub']; $new_ticket_pnr = $_POST['m_ticket_pnr']; $new_ticket_number = $_POST['m_ticket_number']; $new_airline_code = $_POST['m_airline_code']; $stmt_sync_all = $pdo->prepare("UPDATE invoice_settings SET invoice_logo_url = ?, company_name = ?, company_address = ?, footer_no_print_title = ?, footer_no_print_desc = ?, footer_support_phone = ?, footer_support_email = ?, footer_support_web = ?, footer_eco_title = ?, footer_eco_sub = ?, ticket_pnr = ?, ticket_number = ?, airline_code = ?" ); $stmt_sync_all->execute([ $new_logo, $new_company_name, $new_address, $new_footer_no_print_title, $new_footer_no_print_desc, $new_footer_support_phone, $new_footer_support_email, $new_footer_support_web, $new_footer_eco_title, $new_footer_eco_sub, $new_ticket_pnr, $new_ticket_number, $new_airline_code ]); $success_msg = "Pengaturan Master Header, Footer, E-Tiket & Detail Rekening tujuan berhasil diperbarui."; // Refresh master data secara instan $stmt_m = $pdo->query("SELECT * FROM invoice_master_settings WHERE id = 1"); $master_data = $stmt_m->fetch(); } catch (PDOException $e) { $error_msg = "Gagal memperbarui Pengaturan Master: " . $e->getMessage(); } } // 5. PROSES SIMPAN PERUBAHAN INVOICE / TIKET SPESIFIK if (isset($_POST['update_invoice'])) { $target_id = isset($_POST['target_booking_id']) ? (int)$_POST['target_booking_id'] : 1; $submitted_total_pax = isset($_POST['total_pax']) ? (int)$_POST['total_pax'] : 1; try { // Melakukan update tiket dengan melampirkan nilai default yang dikunci dari master_data $stmt = $pdo->prepare("UPDATE invoice_settings SET invoice_logo_url = ?, company_name = ?, company_address = ?, footer_no_print_title = ?, footer_no_print_desc = ?, footer_support_phone = ?, footer_support_email = ?, footer_support_web = ?, footer_eco_title = ?, footer_eco_sub = ?, invoice_id = ?, booking_id = ?, booking_date = ?, issue_date = ?, payment_method = ?, payment_status = ?, contact_name = ?, contact_email = ?, contact_phone = ?, passenger_name = ?, passenger_type = ?, passenger_identity = ?, f1_carrier = ?, f1_code = ?, f1_class = ?, f1_from_code = ?, f1_from_name = ?, f1_from_detail = ?, f1_to_code = ?, f1_to_name = ?, f1_to_detail = ?, f1_date = ?, f1_time = ?, f1_duration = ?, f1_baggage = ?, f2_carrier = ?, f2_code = ?, f2_class = ?, f2_from_code = ?, f2_from_name = ?, f2_from_detail = ?, f2_to_code = ?, f2_to_name = ?, f2_to_detail = ?, f2_date = ?, f2_time = ?, f2_duration = ?, f2_baggage = ?, ticket_pnr = ?, ticket_number = ?, airline_code = ?, price_basic = ?, price_tax = ?, price_other = ?, price_fee = ?, price_total = ? WHERE id = ?"); $stmt->execute([ $master_data['invoice_logo_url'], $master_data['company_name'], $master_data['company_address'], $master_data['footer_no_print_title'], $master_data['footer_no_print_desc'], $master_data['footer_support_phone'], $master_data['footer_support_email'], $master_data['footer_support_web'], $master_data['footer_eco_title'], $master_data['footer_eco_sub'], $_POST['invoice_id'], $_POST['booking_id'], $_POST['booking_date'], $_POST['issue_date'], $_POST['payment_method'], $_POST['payment_status'], $_POST['contact_name'], $_POST['contact_email'], $_POST['contact_phone'], $_POST['passenger_name'], $_POST['passenger_type'], $_POST['passenger_identity'], $_POST['f1_carrier'], $_POST['f1_code'], $_POST['f1_class'], $_POST['f1_from_code'], $_POST['f1_from_name'], $_POST['f1_from_detail'], $_POST['f1_to_code'], $_POST['f1_to_name'], $_POST['f1_to_detail'], $_POST['f1_date'], $_POST['f1_time'], $_POST['f1_duration'], $_POST['f1_baggage'], $_POST['f2_carrier'], $_POST['f2_code'], $_POST['f2_class'], $_POST['f2_from_code'], $_POST['f2_from_name'], $_POST['f2_from_detail'], $_POST['f2_to_code'], $_POST['f2_to_name'], $_POST['f2_to_detail'], $_POST['f2_date'], $_POST['f2_time'], $_POST['f2_duration'], $_POST['f2_baggage'], $master_data['ticket_pnr'], $master_data['ticket_number'], $master_data['airline_code'], $_POST['price_basic'], $_POST['price_tax'], $_POST['price_other'], $_POST['price_fee'], $_POST['price_total'], $target_id ]); $clean_p_status = strtolower(trim($_POST['payment_status'])); $sync_status = 'pending'; if ($clean_p_status === 'paid' || $clean_p_status === 'berhasil' || $clean_p_status === 'sukses') { $sync_status = 'completed'; } // FIX: Sinkronisasi email, nama, dan HP ke tabel bookings agar perubahan kontak ter-update otomatis $stmt_sync = $pdo->prepare("UPDATE bookings SET price = ?, status = ?, guest_qty = ?, customer_name = ?, customer_email = ?, customer_phone = ? WHERE id = ?"); $stmt_sync->execute([$_POST['price_total'], $sync_status, $submitted_total_pax, $_POST['contact_name'], $_POST['contact_email'], $_POST['contact_phone'], $target_id]); $success_msg = "Invoice ID #$target_id berhasil diperbarui."; // ============================================================ // EMAIL OTOMATIS — simpan info dulu, kirim di akhir script (non-blocking) // ============================================================ $email_to = trim($_POST['contact_email'] ?? ''); $pending_email_data = null; if (!empty($email_to) && filter_var($email_to, FILTER_VALIDATE_EMAIL)) { $pending_email_data = [ 'contact_name' => $_POST['contact_name'], 'contact_email' => $email_to, 'invoice_id' => $_POST['invoice_id'], 'price_total' => $_POST['price_total'], 'payment_status' => $_POST['payment_status'], 'f1_carrier' => $_POST['f1_carrier'], 'f1_from_code' => $_POST['f1_from_code'], 'f1_to_code' => $_POST['f1_to_code'], 'f1_date' => $_POST['f1_date'], 'f1_time' => $_POST['f1_time'], ]; } } catch (PDOException $e) { $error_msg = "Gagal memperbarui dokumen: " . $e->getMessage(); } } // 6. AMBIL SEMUA DAFTAR BOOKING DARI DATABASE UNTUK SIDEBAR $active_bookings = []; try { $stmt_b = $pdo->query("SELECT id, customer_name, product_title, price, status, departure_date FROM bookings ORDER BY id DESC"); $active_bookings = $stmt_b->fetchAll(); } catch (PDOException $e) { // Fail-silent } // 7. TENTUKAN INVOICE MANA YANG SEDANG DIEDIT $selected_booking_id = isset($_GET['booking_id']) ? (int)$_GET['booking_id'] : null; if ($selected_booking_id === null && !empty($active_bookings)) { $selected_booking_id = (int)$active_bookings[0]['id']; } if ($selected_booking_id === null) { $selected_booking_id = 1; } try { $stmt = $pdo->prepare("SELECT * FROM invoice_settings WHERE id = ?"); $stmt->execute([$selected_booking_id]); $data = $stmt->fetch(); if (!$data && $selected_booking_id !== 1) { $stmt_emergency = $pdo->prepare("SELECT * FROM bookings WHERE id = ?"); $stmt_emergency->execute([$selected_booking_id]); $em_row = $stmt_emergency->fetch(); if ($em_row) { $price_total = floatval($em_row['price']); $price_fee = 15000; $price_tax = round($price_total * 0.10); $price_basic = $price_total - $price_fee - $price_tax; $invoice_id = "INV/" . date('Ymd') . "/HT/" . str_pad($em_row['id'], 6, '0', STR_PAD_LEFT); $is_roundtrip = !empty($em_row['return_date']); // Menerapkan penemuan detail rute bandara secara presisi $f1_from = get_airport_details($em_row['from_route']); $f1_to = get_airport_details($em_row['dest_route']); $f2_from = get_airport_details($em_row['dest_route']); $f2_to = get_airport_details($em_row['from_route']); $stmt_ins_em = $pdo->prepare("INSERT INTO invoice_settings ( id, invoice_logo_url, company_name, company_address, footer_no_print_title, footer_no_print_desc, footer_support_phone, footer_support_email, footer_support_web, footer_eco_title, footer_eco_sub, invoice_id, booking_id, booking_date, issue_date, payment_method, payment_status, contact_name, contact_email, contact_phone, passenger_name, passenger_type, passenger_identity, f1_carrier, f1_code, f1_class, f1_from_code, f1_from_name, f1_from_detail, f1_to_code, f1_to_name, f1_to_detail, f1_date, f1_time, f1_duration, f1_baggage, f2_carrier, f2_code, f2_class, f2_from_code, f2_from_name, f2_from_detail, f2_to_code, f2_to_name, f2_to_detail, f2_date, f2_time, f2_duration, f2_baggage, ticket_pnr, ticket_number, airline_code, price_basic, price_tax, price_other, price_fee, price_total ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt_ins_em->execute([ $selected_booking_id, $master_data['invoice_logo_url'], $master_data['company_name'], $master_data['company_address'], $master_data['footer_no_print_title'], $master_data['footer_no_print_desc'], $master_data['footer_support_phone'], $master_data['footer_support_email'], $master_data['footer_support_web'], $master_data['footer_eco_title'], $master_data['footer_eco_sub'], $invoice_id, (string)$selected_booking_id, $em_row['departure_date'], date('d M Y, H:i'), 'Bank Transfer', 'PENDING', $em_row['customer_name'], $em_row['customer_email'], $em_row['customer_phone'], $em_row['customer_name'], 'Adult', 'Identity Document Uploaded', $em_row['product_title'], 'GA-' . rand(100, 999), 'Economy (Promo)', $em_row['from_route'], $f1_from['name'], $f1_from['detail'], $em_row['dest_route'], $f1_to['name'], $f1_to['detail'], $em_row['departure_date'], date('H:i'), 'Duration 2h', 'Baggage 23 kg', $is_roundtrip ? $em_row['product_title'] : '', $is_roundtrip ? 'GA-' . rand(100, 999) : '', $is_roundtrip ? 'Economy (Promo)' : '', $is_roundtrip ? $em_row['dest_route'] : '', $is_roundtrip ? $f2_from['name'] : '', $is_roundtrip ? $f2_from['detail'] : '', $is_roundtrip ? $em_row['from_route'] : '', $is_roundtrip ? $f2_to['name'] : '', $is_roundtrip ? $f2_to['detail'] : '', $is_roundtrip ? $em_row['return_date'] : '', $is_roundtrip ? date('H:i') : '', $is_roundtrip ? 'Duration 2h' : '', $is_roundtrip ? 'Baggage 23 kg' : '', $master_data['ticket_pnr'], $master_data['ticket_number'], $master_data['airline_code'], $price_basic, $price_tax, 0, $price_fee, $price_total ]); $stmt->execute([$selected_booking_id]); $data = $stmt->fetch(); } } if (!$data) { $stmt->execute([1]); $data = $stmt->fetch(); } } catch (PDOException $e) { die("Gagal mengambil data dari database: " . $e->getMessage()); } // AMBIL TOTAL PAX (GUEST_QTY) DARI TABEL BOOKINGS $guest_qty = 1; try { $stmt_g = $pdo->prepare("SELECT guest_qty FROM bookings WHERE id = ?"); $stmt_g->execute([$selected_booking_id]); $b_row = $stmt_g->fetch(); if ($b_row) { $guest_qty = (int)$b_row['guest_qty']; } } catch (Exception $e) { // Fallback silent } ?>
Berhasil
Kesalahan Terjadi
Daftar Invoice Aktif
Editor E-Tiket & Master
Ubah detail tiket individual atau konfigurasi global master header/footer.
Pratinjau E-Tiket & Invoice
Tampilan cetak dokumen dinamis dan presisi.
Geser pratinjau ke kanan untuk melihat rincian penuh