prepare("SELECT * FROM quotations WHERE id = ? AND deleted_at IS NULL"); $stmt->execute([$id]); $quotation = $stmt->fetch(); if ($quotation) { $stmt = db()->prepare("SELECT * FROM quotation_items WHERE quotation_id = ?"); $stmt->execute([$id]); $items = $stmt->fetchAll(); } else { header("Location: quotations.php"); exit; } } // Fetch customers and products for dropdowns $customers = db()->query("SELECT id, name FROM customers WHERE deleted_at IS NULL ORDER BY name ASC")->fetchAll(); $products = db()->query("SELECT id, name, price FROM products WHERE deleted_at IS NULL ORDER BY name ASC")->fetchAll(); if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!validate_csrf($_POST['csrf_token'] ?? '')) { die("CSRF token validation failed"); } $customer_id = $_POST['customer_id']; $issue_date = $_POST['issue_date']; $expiry_date = $_POST['expiry_date']; $status = $_POST['status']; $notes = $_POST['notes']; $subtotal = 0; $form_items = $_POST['items'] ?? []; $processed_items = []; foreach ($form_items as $item) { if (!empty($item['product_id']) && $item['quantity'] > 0) { $total_price = $item['quantity'] * $item['unit_price']; $subtotal += $total_price; $processed_items[] = [ 'product_id' => $item['product_id'], 'quantity' => $item['quantity'], 'unit_price' => $item['unit_price'], 'total_price' => $total_price ]; } } $tax_rate = 0.10; // 10% tax example $tax_amount = $subtotal * $tax_rate; $total_amount = $subtotal + $tax_amount; try { db()->beginTransaction(); if ($id) { $stmt = db()->prepare("UPDATE quotations SET customer_id = ?, issue_date = ?, expiry_date = ?, status = ?, subtotal = ?, tax_amount = ?, total_amount = ?, notes = ? WHERE id = ?"); $stmt->execute([$customer_id, $issue_date, $expiry_date, $status, $subtotal, $tax_amount, $total_amount, $notes, $id]); // Delete old items db()->prepare("DELETE FROM quotation_items WHERE quotation_id = ?")->execute([$id]); } else { // Generate quotation number $q_number = 'QTN-' . date('Ymd') . '-' . strtoupper(bin2hex(random_bytes(2))); $stmt = db()->prepare("INSERT INTO quotations (quotation_number, customer_id, user_id, issue_date, expiry_date, status, subtotal, tax_amount, total_amount, notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->execute([$q_number, $customer_id, $_SESSION['user_id'], $issue_date, $expiry_date, $status, $subtotal, $tax_amount, $total_amount, $notes]); $id = db()->lastInsertId(); } // Insert items $item_stmt = db()->prepare("INSERT INTO quotation_items (quotation_id, product_id, quantity, unit_price, total_price) VALUES (?, ?, ?, ?, ?)"); foreach ($processed_items as $p_item) { $item_stmt->execute([$id, $p_item['product_id'], $p_item['quantity'], $p_item['unit_price'], $p_item['total_price']]); } // Log action $log_stmt = db()->prepare("INSERT INTO audit_logs (user_id, action, entity_type, entity_id, details) VALUES (?, ?, ?, ?, ?)"); $log_stmt->execute([$_SESSION['user_id'], $id ? 'UPDATE' : 'CREATE', 'QUOTATION', $id, "Number: " . ($quotation['quotation_number'] ?? $q_number)]); db()->commit(); $_SESSION['success'] = "Quotation saved successfully."; header("Location: quotations.php"); exit; } catch (Exception $e) { db()->rollBack(); $error = "Error saving quotation: " . $e->getMessage(); } } $default_issue_date = $quotation['issue_date'] ?? date('Y-m-d'); $default_expiry_date = $quotation['expiry_date'] ?? date('Y-m-d', strtotime('+30 days')); ?>