:: **Zploit** v1.0 | Current Path: **/home/kreativepixelz/www/crm/quatation/**
:: Editing File: update_po.php
<?php // update_po.php — Adapted from save_po.php to handle updates include 'db.php'; include_once("session.php"); // Only accept POST if ($_SERVER['REQUEST_METHOD'] !== 'POST') { header('Location: po_list.php'); exit; } // Get the PO ID to update. This is critical. $po_id = isset($_POST['po_id']) ? (int)$_POST['po_id'] : 0; if ($po_id <= 0) { $_SESSION['error'] = "Invalid Purchase Order ID."; header("Location: po_list.php"); exit; } // small helper (from save_po.php) function refValues($arr) { $refs = []; foreach ($arr as $key => $value) { $refs[$key] = &$arr[$key]; } return $refs; } // Paths for file handling $upload_dir = __DIR__ . '/uploads/po_receipts/'; $new_file_full_path = null; // Full server path to a NEWLY uploaded file (for unlinking on error) try { // ---------- 1) Collect & sanitize input ---------- $user_id = isset($_POST['user_id']) ? (int)$_POST['user_id'] : 0; $po_date = trim($_POST['po_date'] ?? ''); $po_no = trim($_POST['po_no'] ?? ''); $po_req_no = trim($_POST['po_req_no'] ?? ''); $po_status = trim($_POST['po_status'] ?? ''); $po_contact_ref = trim($_POST['po_contact_ref'] ?? ''); $po_email = trim($_POST['po_email'] ?? ''); $po_contact = trim($_POST['po_contact'] ?? ''); $vendor_id = isset($_POST['vendor_id']) ? (int)$_POST['vendor_id'] : 0; $billing_id = isset($_POST['billing_id']) ? (int)$_POST['billing_id'] : 0; $delivery_id= isset($_POST['delivery_id']) ? (int)$_POST['delivery_id'] : 0; $terms = trim($_POST['terms'] ?? ''); $incoterms = trim($_POST['incoterms'] ?? ''); $product_name = trim($_POST['product_name'] ?? ''); $remark = trim($_POST['remark'] ?? ''); $driver_name= trim($_POST['driver_name'] ?? ''); $driver_no = trim($_POST['driver_no'] ?? ''); $vehicle_no = trim($_POST['vehicle_no'] ?? ''); $total_box = isset($_POST['total_box']) ? (int)$_POST['total_box'] : 0; // Current file path (from hidden input) $current_purchase_receipt = trim($_POST['current_purchase_receipt'] ?? ''); // This will be the value stored in the DB. Start by assuming it's the old one. $receipt_path_for_db = $current_purchase_receipt; // Taxes (IDs) $tax_cgst_id = (isset($_POST['tax_cgst']) && $_POST['tax_cgst'] !== '') ? (int)$_POST['tax_cgst'] : null; $tax_sgst_id = (isset($_POST['tax_sgst']) && $_POST['tax_sgst'] !== '') ? (int)$_POST['tax_sgst'] : null; // Items arrays $item_descriptions = $_POST['item_description'] ?? []; $pack_types = $_POST['pack_type'] ?? []; $quantities = $_POST['quantity'] ?? []; $rates = $_POST['rate'] ?? []; // Basic validation $errors = []; if ($user_id <= 0) $errors[] = "Invalid user."; if (empty($po_no)) $errors[] = "PO No is required."; if (empty($po_date)) $errors[] = "PO Date is required."; if ($vendor_id <= 0) $errors[] = "Please select a vendor."; if ($billing_id <= 0) $errors[] = "Please select a billing company."; $hasValidItem = false; for ($i = 0; $i < count($item_descriptions); $i++) { if (trim($item_descriptions[$i] ?? '') !== '') { $hasValidItem = true; break; } } if (!$hasValidItem) $errors[] = "Please add at least one PO item."; if (!empty($errors)) { $_SESSION['error'] = implode(' ', $errors); // Redirect back to the EDIT page header("Location: edit_po.php?id=" . $po_id); exit; } // ---------- 2) File upload (optional) ---------- // Check if a NEW file was uploaded if (isset($_FILES['purchase_receipt']) && $_FILES['purchase_receipt']['error'] === UPLOAD_ERR_OK) { if (!is_dir($upload_dir) && !mkdir($upload_dir, 0777, true) && !is_dir($upload_dir)) { throw new Exception("Failed to create upload directory."); } $orig = basename($_FILES['purchase_receipt']['name']); $ext = strtolower(pathinfo($orig, PATHINFO_EXTENSION)); $allowed = ['pdf','jpg','jpeg','png']; if (!in_array($ext, $allowed)) throw new Exception("Invalid file type. Allowed: PDF, JPG, PNG."); $safe_po_no = preg_replace('/[^A-Za-z0-9_\-]/', '_', $po_no); $new_name = "po_{$safe_po_no}_" . time() . "_" . bin2hex(random_bytes(6)) . "." . $ext; $dest = $upload_dir . $new_name; if (!move_uploaded_file($_FILES['purchase_receipt']['tmp_name'], $dest)) { throw new Exception("Failed to move uploaded file."); } // This is the full server path to the NEW file. Used for cleanup on error. $new_file_full_path = $dest; // This is the relative path to store in the DB. $receipt_path_for_db = 'uploads/po_receipts/' . $new_name; } // ---------- 3) Server-side compute sub_total and prepare items ---------- // (This logic is identical to save_po.php) $items_to_insert = []; $sub_total = 0.0; $count_items = count($item_descriptions); for ($i = 0; $i < $count_items; $i++) { $desc = trim($item_descriptions[$i] ?? ''); $pack = trim($pack_types[$i] ?? ''); $qty = is_numeric($quantities[$i] ?? null) ? (float)$quantities[$i] : 0.0; $rate = is_numeric($rates[$i] ?? null) ? (float)$rates[$i] : 0.0; if ($desc === '' && $qty <= 0 && $rate <= 0) continue; $amount = round($qty * $rate, 2); $sub_total += $amount; $items_to_insert[] = [ 'description' => $desc, 'pack_type' => $pack, 'quantity' => $qty, 'rate' => $rate, 'amount' => $amount ]; } if (count($items_to_insert) === 0) { throw new Exception("No valid items to save."); } // ---------- 4) Lookup taxes percentages (if provided) ---------- // (This logic is identical to save_po.php) $cgst_perc = 0.0; $sgst_perc = 0.0; if ($tax_cgst_id) { $tstmt = mysqli_prepare($conn, "SELECT tax_percentage FROM taxes WHERE id = ? LIMIT 1"); if ($tstmt) { mysqli_stmt_bind_param($tstmt, "i", $tax_cgst_id); mysqli_stmt_execute($tstmt); mysqli_stmt_bind_result($tstmt, $tp); if (mysqli_stmt_fetch($tstmt)) $cgst_perc = (float)$tp; mysqli_stmt_close($tstmt); } } if ($tax_sgst_id) { $tstmt = mysqli_prepare($conn, "SELECT tax_percentage FROM taxes WHERE id = ? LIMIT 1"); if ($tstmt) { mysqli_stmt_bind_param($tstmt, "i", $tax_sgst_id); mysqli_stmt_execute($tstmt); mysqli_stmt_bind_result($tstmt, $tp2); if (mysqli_stmt_fetch($tstmt)) $sgst_perc = (float)$tp2; mysqli_stmt_close($tstmt); } } $cgst_amount = round(($sub_total * $cgst_perc) / 100, 2); $sgst_amount = round(($sub_total * $sgst_perc) / 100, 2); $grand_total_final = round($sub_total + $cgst_amount + $sgst_amount, 2); // ---------- 5) Begin transaction ---------- if (!mysqli_begin_transaction($conn)) { throw new Exception("Failed to start transaction: " . mysqli_error($conn)); } // ---------- 6) UPDATE purchase (master) ---------- // Note: 'updated_at' column assumed to exist or be handled by DB trigger $sql_purchase_update = "UPDATE purchase SET po_status = ?, user_id = ?, vendor_id = ?, billing_id = ?, delivery_id = ?, po_no = ?, po_date = ?, po_contact_ref = ?, po_email = ?, po_contact = ?, po_req_no = ?, terms = ?, incoterms = ?, product_name = ?, sub_total = ?, tax_cgst_id = ?, tax_sgst_id = ?, cgst_amount = ?, sgst_amount = ?, grand_total = ?, remark = ?, driver_name = ?, driver_no = ?, total_box = ?, vehicle_no = ?, purchase_receipt = ?, updated_at = NOW() WHERE id = ?"; // 27 fields + 1 ID $stmt = mysqli_prepare($conn, $sql_purchase_update); if (!$stmt) throw new Exception("Prepare failed (purchase update): " . mysqli_error($conn)); $params = [ $po_status, $user_id, $vendor_id, $billing_id, $delivery_id, $po_no, $po_date, $po_contact_ref, $po_email, $po_contact, $po_req_no, $terms, $incoterms, $product_name, number_format($sub_total, 2, '.', ''), $tax_cgst_id ?? null, $tax_sgst_id ?? null, number_format($cgst_amount, 2, '.', ''), number_format($sgst_amount, 2, '.', ''), number_format($grand_total_final, 2, '.', ''), $remark, $driver_name, $driver_no, $total_box, $vehicle_no, $receipt_path_for_db ?? '', $po_id // The ID for the WHERE clause ]; // Build bind types string dynamically $types = ''; foreach ($params as $p) { if (is_int($p)) $types .= 'i'; elseif (is_float($p) || is_numeric($p) && strpos((string)$p, '.') !== false) $types .= 'd'; elseif (is_null($p)) $types .= 's'; // Send NULL as string 's' (mysqli handles this) else $types .= 's'; } $bind = array_merge([$types], $params); $bindRefs = refValues($bind); if (!call_user_func_array([$stmt, 'bind_param'], $bindRefs)) { throw new Exception("Bind params failed (purchase update): " . mysqli_stmt_error($stmt)); } if (!mysqli_stmt_execute($stmt)) { throw new Exception("Execute failed (purchase update): " . mysqli_stmt_error($stmt)); } mysqli_stmt_close($stmt); // ---------- 7) Update purchase_items (Delete all old, Insert all new) ---------- // 7a) Delete old items $sql_delete_items = "DELETE FROM purchase_items WHERE purchase_id = ?"; $stmt_del = mysqli_prepare($conn, $sql_delete_items); if (!$stmt_del) throw new Exception("Prepare failed (item delete): " . mysqli_error($conn)); if (!mysqli_stmt_bind_param($stmt_del, "i", $po_id)) { throw new Exception("Bind failed (item delete): " . mysqli_stmt_error($stmt_del)); } if (!mysqli_stmt_execute($stmt_del)) { throw new Exception("Execute failed (item delete): " . mysqli_stmt_error($stmt_del)); } mysqli_stmt_close($stmt_del); // 7b) Insert new items (just like save_po.php) $sql_item_insert = "INSERT INTO purchase_items (purchase_id, item_description, pack_type, quantity, rate, amount) VALUES (?, ?, ?, ?, ?, ?)"; $stmt_item = mysqli_prepare($conn, $sql_item_insert); if (!$stmt_item) throw new Exception("Prepare failed (item insert): " . mysqli_error($conn)); foreach ($items_to_insert as $it) { $pid = $po_id; // Use the existing PO ID $desc = $it['description']; $pack = $it['pack_type']; $qty = $it['quantity']; $rate = $it['rate']; $amt = $it['amount']; if (!mysqli_stmt_bind_param($stmt_item, "issddd", $pid, $desc, $pack, $qty, $rate, $amt)) { throw new Exception("Bind failed (item insert): " . mysqli_stmt_error($stmt_item)); } if (!mysqli_stmt_execute($stmt_item)) { throw new Exception("Execute failed (item insert): " . mysqli_stmt_error($stmt_item)); } } mysqli_stmt_close($stmt_item); // ---------- 8) Commit ---------- mysqli_commit($conn); // After commit, if a new file was uploaded, delete the old one if ($new_file_full_path && !empty($current_purchase_receipt)) { if (file_exists(__DIR__ . '/' . $current_purchase_receipt)) { @unlink(__DIR__ . '/' . $current_purchase_receipt); } } // optional notification $msg = "✅ Purchase Order #{$po_no} (ID: {$po_id}) updated."; $nstmt = mysqli_prepare($conn, "INSERT INTO notifications (user_id, message, type) VALUES (?, ?, 'success')"); if ($nstmt) { mysqli_stmt_bind_param($nstmt, "is", $user_id, $msg); mysqli_stmt_execute($nstmt); mysqli_stmt_close($nstmt); } $_SESSION['success'] = "Purchase Order updated successfully."; header("Location: po_list.php"); exit; } catch (Exception $e) { // rollback if (isset($conn) && $conn) mysqli_rollback($conn); // delete the NEWLY uploaded file if it exists, since the transaction failed if ($new_file_full_path && file_exists($new_file_full_path)) { @unlink($new_file_full_path); } $_SESSION['error'] = "Error updating Purchase Order: " . $e->getMessage(); // Redirect back to the EDIT page with the ID header("Location: edit_po.php?id=" . $po_id); exit; }