Edit file File name : api.php Content :<?php session_start(); date_default_timezone_set('America/Belize'); require_once '_helpers.php'; header('Content-Type: application/json'); function send_json_error($message, $code = 400) { error_log("API Error: " . $message); http_response_code($code); echo json_encode(['success' => false, 'message' => $message]); exit(); } function send_json_success($data = []) { echo json_encode(['success' => true, 'data' => $data]); exit(); } // Function to update invoice status based on payments from the 'payments' table function update_invoice_status($conn, $invoice_id) { $stmt = $conn->prepare("SELECT total, due_date, status FROM invoices WHERE id = ?"); $stmt->bind_param("s", $invoice_id); $stmt->execute(); $invoice_res = fetch_all_assoc($stmt); $stmt->close(); if (empty($invoice_res)) return; // Invoice not found $invoice = $invoice_res[0]; // Recalculate total amount paid from the payments table $stmt = $conn->prepare("SELECT SUM(amount) as total_paid FROM payments WHERE invoice_id = ?"); $stmt->bind_param("s", $invoice_id); $stmt->execute(); $payment_res = fetch_all_assoc($stmt); $stmt->close(); $amount_paid = (float)($payment_res[0]['total_paid'] ?? 0); // Determine the new status $new_status = $invoice['status']; // Default to current if ($invoice['status'] !== 'Draft') { // Don't auto-update Draft status if (abs($amount_paid - (float)$invoice['total']) < 0.01) { // Floating point comparison $new_status = 'Paid'; } elseif ($amount_paid > 0) { $new_status = 'Partially Paid'; } else { $new_status = (new DateTime() > new DateTime($invoice['due_date'])) ? 'Overdue' : 'Due'; } } // Corrected query to only update columns that exist in the 'invoices' table. $stmt_update = $conn->prepare("UPDATE invoices SET status = ?, amount_paid = ? WHERE id = ?"); $stmt_update->bind_param("sds", $new_status, $amount_paid, $invoice_id); $stmt_update->execute(); $stmt_update->close(); } $conn = get_db_connection(); $action = $_POST['action'] ?? ''; if (empty($action)) { send_json_error('No action specified.'); } switch ($action) { case 'record_payment': $invoice_id = $_POST['invoice_id'] ?? null; $payment_date = $_POST['payment_date'] ?? date('Y-m-d'); $method = $_POST['method'] ?? null; $account = $_POST['account'] ?? null; $amount = (float)($_POST['amount'] ?? 0); $notes = $_POST['notes'] ?? ''; if (!$invoice_id || $amount <= 0) { send_json_error('Invoice ID and a positive payment amount are required.'); } $conn->begin_transaction(); try { $stmt = $conn->prepare("INSERT INTO payments (invoice_id, payment_date, amount, method, account, notes) VALUES (?, ?, ?, ?, ?, ?)"); $stmt->bind_param("ssdsss", $invoice_id, $payment_date, $amount, $method, $account, $notes); if ($stmt->execute()) { $stmt->close(); update_invoice_status($conn, $invoice_id); $conn->commit(); send_json_success(['message' => 'Payment recorded.']); } else { throw new Exception('Failed to record payment: ' . $stmt->error); } } catch (Exception $e) { $conn->rollback(); send_json_error($e->getMessage(), 500); } break; case 'remove_payment': $payment_id = $_POST['payment_id'] ?? null; $invoice_id = $_POST['invoice_id'] ?? null; if (!$payment_id || !$invoice_id) { send_json_error('Payment ID and Invoice ID are required.'); } $conn->begin_transaction(); try { $stmt = $conn->prepare("DELETE FROM payments WHERE id = ? AND invoice_id = ?"); $stmt->bind_param("ss", $payment_id, $invoice_id); if ($stmt->execute()) { $stmt->close(); update_invoice_status($conn, $invoice_id); $conn->commit(); send_json_success(['message' => "Payment removed successfully."]); } else { throw new Exception('Failed to remove payment record: ' . $stmt->error); } } catch (Exception $e) { $conn->rollback(); send_json_error($e->getMessage(), 500); } break; // ... other cases default: // Handle other actions or default error send_json_error('Invalid action specified.'); break; } $conn->close(); ?> Save