Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated: Validations of order status changes while changing order status using bulk action #1103

Merged
merged 2 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions classes/order/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -2688,4 +2688,133 @@ public function setWsTransactionId($transactionId)
{
$this->transaction_id = $transactionId;
}

/**
* Validate and change order status
* @return array of status, errors, has_mail_error(if order status is changes but mail error occurs while sending mail)
*/
public function ChangeOrderStatus()
{
$result = array();
$result['status'] = false;
$result['has_mail_error'] = false;
$result['errors'] = array();
$objNewOrderState = new OrderState(Tools::getValue('id_order_state'));
if (!Validate::isLoadedObject($objNewOrderState)) {
$result['errors'][] = Tools::displayError('The new order status is invalid.');
} else {
$objHotelBooking = new HotelBookingDetail();
$objCurrentOrderState = $this->getCurrentOrderState();

if ($objCurrentOrderState->id == Configuration::get('PS_OS_REFUND')) {
$result['errors'][] = Tools::displayError('Order status can not be changed once order status is set to Refunded.');
} elseif ($objCurrentOrderState->id == Configuration::get('PS_OS_CANCELED')) {
$result['errors'][] = Tools::displayError('Order status can not be changed once order status is set to Cancelled.');
} elseif (in_array($objNewOrderState->id, array (Configuration::get('PS_OS_OVERBOOKING_PAID'), Configuration::get('PS_OS_OVERBOOKING_UNPAID'), Configuration::get('PS_OS_OVERBOOKING_PARTIAL_PAID')))) {
if (!$objHotelBooking->getOverbookedRooms($this->id)) {
$result['errors'][] = Tools::displayError('Order status can not be changed to any overbooking status as there are no overbooked rooms in the order.');
}
} elseif ($objNewOrderState->id == Configuration::get('PS_OS_REFUND')
&& !$this->hasCompletelyRefunded(Order::ORDER_COMPLETE_REFUND_FLAG)
) {
$result['errors'][] = Tools::displayError('Order status can not be set to Refunded until all bookings in the order are completely refunded.');
} elseif ($objNewOrderState->id == Configuration::get('PS_OS_CANCELED')
&& !$this->hasCompletelyRefunded(Order::ORDER_COMPLETE_CANCELLATION_FLAG)
) {
$result['errors'][] = Tools::displayError('Order status can not be set to Cancelled until all bookings in the order are cancelled.');
} elseif ($objCurrentOrderState->id == Configuration::get('PS_OS_ERROR') && !($objNewOrderState->id == Configuration::get('PS_OS_ERROR'))) {
// All rooms must be available before changing status from Payment Error to Other status in which rooms are getting blocked again
if ($orderBookings = $objHotelBooking->getOrderCurrentDataByOrderId($this->id)) {
foreach ($orderBookings as $orderBooking) {
// If booking is refunded then no need to check inventory
if ((OrderReturn::getOrdersReturnDetail($this->id, 0, $orderBooking['id']) && $orderBooking['is_refunded'])
|| ($orderBooking['is_cancelled'] && $orderBooking['is_refunded'])
) {
continue;
} else {
// if inventory is available for that booking
$bookingParams = array(
'date_from' => $orderBooking['date_from'],
'date_to' => $orderBooking['date_to'],
'hotel_id' => $orderBooking['id_hotel'],
'id_room_type' => $orderBooking['id_product'],
'only_search_data' => 1
);

$objHotelBookingDetail = new HotelBookingDetail($orderBooking['id']);
if ($searchRoomsInfo = $objHotelBooking->getBookingData($bookingParams)) {
if (isset($searchRoomsInfo['rm_data'][$orderBooking['id_product']]['data']['available'])
&& $searchRoomsInfo['rm_data'][$orderBooking['id_product']]['data']['available']
) {
$availableRoomsInfo = $searchRoomsInfo['rm_data'][$orderBooking['id_product']]['data']['available'];
if ($roomIdsAvailable = array_column($availableRoomsInfo, 'id_room')) {
// Check If room is still there in the available rooms list
if (!in_array($orderBooking['id_room'], $roomIdsAvailable)) {
$result['errors'][] = Tools::displayError('You can not change the order status as some rooms are not available now in this order. You can reallocate/swap rooms with other rooms to make rooms available and then change the order status.');

break;
} else {
$objHotelBookingDetail->is_refunded = 0;
$objHotelBookingDetail->save();
}
} else {
$result['errors'][] = Tools::displayError('You can not change the order status as some rooms are not available now in this order. You can reallocate/swap rooms with other rooms to make rooms available and then change the order status.');
break;
}
}
} else {
$result['errors'][] = Tools::displayError('You can not change the order status as some rooms are not available now in this order. You can reallocate/swap rooms with other rooms to make rooms available and then change the order status.');

break;
}
}
}
}
} elseif ($objCurrentOrderState->id == $objNewOrderState->id) {
$result['errors'][] = Tools::displayError('The order has already been assigned this status.');
}
}

if (!count($result['errors'])) {
// Create new OrderHistory
$context = Context::getContext();
$history = new OrderHistory();
$history->id_order = $this->id;
$history->id_employee = (int)$context->employee->id;

$useExistingsPayment = false;
if (!$this->hasInvoice()) {
$useExistingsPayment = true;
}
$history->changeIdOrderState((int)$objNewOrderState->id, $this, $useExistingsPayment);

// Save all changes
$templateVars = array();
if ($history->add(true)) {
if (!$history->sendEmail($this, $templateVars)) {
// if an error occurred while sending an email the set has_mail_error to true
$result['has_mail_error'] = true;
$result['errors'][] = Tools::displayError('We were unable to send an email to the customer while changing order status.');
}

// synchronizes quantities if needed..
if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
foreach ($this->getProducts() as $product) {
if (StockAvailable::dependsOnStock($product['product_id'])) {
StockAvailable::synchronize($product['product_id'], (int)$product['id_shop']);
}
}
}
} else {
$result['errors'][] = Tools::displayError('An error occurred while changing order status.');
}
}

// if no errors then return status true
if (!count($result['errors'])) {
$result['status'] = true;
}

return $result;
}
}
142 changes: 12 additions & 130 deletions controllers/admin/AdminOrdersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1045,28 +1045,13 @@ public function processBulkUpdateOrderStatus()
if (!Validate::isLoadedObject($order)) {
$this->errors[] = sprintf(Tools::displayError('Order #%d cannot be loaded'), $id_order);
} else {
$current_order_state = $order->getCurrentOrderState();
if ($current_order_state->id == $order_state->id) {
$this->errors[] = $this->displayWarning(sprintf('Order #%d has already been assigned this status.', $id_order));
} else {
$history = new OrderHistory();
$history->id_order = $order->id;
$history->id_employee = (int)$this->context->employee->id;

$use_existings_payment = !$order->hasInvoice();
$history->changeIdOrderState((int)$order_state->id, $order, $use_existings_payment);

$carrier = new Carrier($order->id_carrier, $order->id_lang);
$templateVars = array();

if ($history->addWithemail(true, $templateVars)) {
if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
foreach ($order->getProducts() as $product) {
if (StockAvailable::dependsOnStock($product['product_id'])) {
StockAvailable::synchronize($product['product_id'], (int)$product['id_shop']);
}
}
}
$result = $order->changeOrderStatus();
if (!$result['status']) {
if (isset($result['has_mail_error']) && $result['has_mail_error']) {
$this->errors[] = sprintf(
Tools::displayError('Unable to send email to the customer while changing order status for order #%d.'),
$id_order
);
} else {
$this->errors[] = sprintf(Tools::displayError('Cannot change status for order #%d.'), $id_order);
}
Expand All @@ -1075,6 +1060,7 @@ public function processBulkUpdateOrderStatus()
}
}
}

if (!count($this->errors)) {
Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$this->token);
}
Expand Down Expand Up @@ -1280,115 +1266,11 @@ public function postProcess()
/* Change order status, add a new entry in order history and send an e-mail to the customer if needed */
elseif (Tools::isSubmit('submitState') && isset($order)) {
if ($this->tabAccess['edit'] === '1') {
$order_state = new OrderState(Tools::getValue('id_order_state'));

if (!Validate::isLoadedObject($order_state)) {
$this->errors[] = Tools::displayError('The new order status is invalid.');
$result = $order->changeOrderStatus();
if ($result['status']) {
Tools::redirectAdmin(self::$currentIndex.'&id_order='.(int)$order->id.'&conf=5&vieworder&token='.$this->token);
} else {
$current_order_state = $order->getCurrentOrderState();

if ($current_order_state->id == Configuration::get('PS_OS_REFUND')) {
$this->errors[] = Tools::displayError('Order status can not be changed once order status is set to Refunded.');
} elseif ($current_order_state->id == Configuration::get('PS_OS_CANCELED')) {
$this->errors[] = Tools::displayError('Order status can not be changed once order status is set to Cancelled.');
} elseif (in_array($order_state->id, array (Configuration::get('PS_OS_OVERBOOKING_PAID'), Configuration::get('PS_OS_OVERBOOKING_UNPAID'), Configuration::get('PS_OS_OVERBOOKING_PARTIAL_PAID')))) {
$objHotelBooking = new HotelBookingDetail();
if (!$objHotelBooking->getOverbookedRooms($order->id)) {
$this->errors[] = Tools::displayError('Order status can not be changed to any overbooking status as there are no overbooked rooms in the order.');
}
} elseif ($order_state->id == Configuration::get('PS_OS_REFUND')
&& !$order->hasCompletelyRefunded(Order::ORDER_COMPLETE_REFUND_FLAG)
) {
$this->errors[] = Tools::displayError('Order status can not be set to Refunded until all bookings in the order are completely refunded.');
} elseif ($order_state->id == Configuration::get('PS_OS_CANCELED')
&& !$order->hasCompletelyRefunded(Order::ORDER_COMPLETE_CANCELLATION_FLAG)
) {
$this->errors[] = Tools::displayError('Order status can not be set to Cancelled until all bookings in the order are cancelled.');
} elseif ($current_order_state->id == Configuration::get('PS_OS_ERROR') && !($order_state->id == Configuration::get('PS_OS_ERROR'))) {
// All rooms must be available before changing status from Payment Error to Other status in which rooms are getting blocked again
$objHotelBooking = new HotelBookingDetail();
if ($orderBookings = $objHotelBooking->getOrderCurrentDataByOrderId($order->id)) {
foreach ($orderBookings as $orderBooking) {
// If booking is refunded then no need to check inventory
if ((OrderReturn::getOrdersReturnDetail($order->id, 0, $orderBooking['id']) && $orderBooking['is_refunded'])
|| ($orderBooking['is_cancelled'] && $orderBooking['is_refunded'])
) {
continue;
} else {
// if inventory is available for that booking
$bookingParams = array(
'date_from' => $orderBooking['date_from'],
'date_to' => $orderBooking['date_to'],
'hotel_id' => $orderBooking['id_hotel'],
'id_room_type' => $orderBooking['id_product'],
'only_search_data' => 1
);

$objHotelBookingDetail = new HotelBookingDetail($orderBooking['id']);
if ($searchRoomsInfo = $objHotelBooking->getBookingData($bookingParams)) {
if (isset($searchRoomsInfo['rm_data'][$orderBooking['id_product']]['data']['available'])
&& $searchRoomsInfo['rm_data'][$orderBooking['id_product']]['data']['available']
) {
$availableRoomsInfo = $searchRoomsInfo['rm_data'][$orderBooking['id_product']]['data']['available'];
if ($roomIdsAvailable = array_column($availableRoomsInfo, 'id_room')) {
// Check If room is still there in the available rooms list
if (!in_array($orderBooking['id_room'], $roomIdsAvailable)) {
$this->errors[] = Tools::displayError('You can not change the order status as some rooms are not available now in this order. You can reallocate/swap rooms with other rooms to make rooms available and then change the order status.');

break;
} else {
$objHotelBookingDetail->is_refunded = 0;
$objHotelBookingDetail->save();
}
} else {
$this->errors[] = Tools::displayError('You can not change the order status as some rooms are not available now in this order. You can reallocate/swap rooms with other rooms to make rooms available and then change the order status.');
break;
}
}
} else {
$this->errors[] = Tools::displayError('You can not change the order status as some rooms are not available now in this order. You can reallocate/swap rooms with other rooms to make rooms available and then change the order status.');

break;
}
}
}
}
} elseif ($current_order_state->id == $order_state->id) {
$this->errors[] = Tools::displayError('The order has already been assigned this status.');
}

// If no errors then we change the order status
if (!count($this->errors)) {
// Create new OrderHistory
$history = new OrderHistory();
$history->id_order = $order->id;
$history->id_employee = (int)$this->context->employee->id;

$use_existings_payment = false;
if (!$order->hasInvoice()) {
$use_existings_payment = true;
}
$history->changeIdOrderState((int)$order_state->id, $order, $use_existings_payment);

$carrier = new Carrier($order->id_carrier, $order->id_lang);
$templateVars = array();

// Save all changes
if ($history->addWithemail(true, $templateVars)) {
// synchronizes quantities if needed..
if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
foreach ($order->getProducts() as $product) {
if (StockAvailable::dependsOnStock($product['product_id'])) {
StockAvailable::synchronize($product['product_id'], (int)$product['id_shop']);
}
}
}

Tools::redirectAdmin(self::$currentIndex.'&id_order='.(int)$order->id.'&conf=5&vieworder&token='.$this->token);
}

$this->errors[] = Tools::displayError('An error occurred while changing order status, or we were unable to send an email to the customer.');
}
$this->errors = array_merge($this->errors, $result['errors']);
}
} else {
$this->errors[] = Tools::displayError('You do not have permission to edit this.');
Expand Down