80 lines
2.9 KiB
PHP
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;
|
|
}
|
|
}
|