36782-vm/includes/status_updater.php
2025-12-12 14:13:03 +00:00

80 lines
2.9 KiB
PHP

<?php
// includes/status_updater.php
require_once __DIR__ . '/../db/config.php';
/**
* Recalculates and updates the overall order status based on its items' statuses.
*
* @param int $order_id The ID of the order to update.
* @return bool True on success, false on failure or if no update was needed.
*/
function update_order_status($order_id) {
$pdo = db();
try {
// Start a transaction
$pdo->beginTransaction();
// 1. Get the current order status. If it's a terminal state, don't override it.
$stmt = $pdo->prepare("SELECT status FROM orders WHERE id = :order_id FOR UPDATE");
$stmt->execute(['order_id' => $order_id]);
$current_status = $stmt->fetchColumn();
if ($current_status === 'completed' || $current_status === 'cancelled') {
$pdo->commit();
return true; // No action needed
}
// TODO: Later, check payment status here. If pending_payment, we might not want to move to 'in_progress' yet.
// 2. Get counts of item statuses for the order
$stmt = $pdo->prepare("
SELECT
COUNT(*) AS total_items,
SUM(CASE WHEN item_status = 'shipped' THEN 1 ELSE 0 END) AS shipped_items,
SUM(CASE WHEN item_status = 'pending' THEN 1 ELSE 0 END) AS pending_items,
SUM(CASE WHEN item_status = 'in_progress' THEN 1 ELSE 0 END) AS in_progress_items
FROM order_items
WHERE order_id = :order_id
");
$stmt->execute(['order_id' => $order_id]);
$status_counts = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$status_counts || $status_counts['total_items'] == 0) {
$pdo->rollBack();
return false; // No items found
}
$new_status = null;
// 3. Apply status aggregation rules
if ($status_counts['shipped_items'] == $status_counts['total_items']) {
$new_status = 'shipped';
} elseif ($status_counts['pending_items'] > 0 || $status_counts['in_progress_items'] > 0) {
// As long as payment is made, any non-shipped item means work is in progress.
$new_status = 'in_progress';
}
// 4. Update the order status if it has changed
if ($new_status && $new_status !== $current_status) {
$update_stmt = $pdo->prepare("UPDATE orders SET status = :status WHERE id = :order_id");
$update_stmt->execute(['status' => $new_status, 'order_id' => $order_id]);
// TODO: send email when order.status changes to 'shipped'
}
// Commit the transaction
$pdo->commit();
return true;
} catch (Exception $e) {
// Roll back on error
if ($pdo->inTransaction()) {
$pdo->rollBack();
}
// Log error, e.g., error_log('Order status update failed: ' . $e->getMessage());
return false;
}
}