Reenviar correo de confirmación de pedido en Prestashop

Tanto si eres el gestor de tu tienda Prestashop como si trabajas para clientes que manejen este CMS de venta online, seguro que os ha pasado que en algún momento no les ha llegado a los clientes el correo de confirmación de pedido (plantilla order_conf). De forma nativa Prestashop NO trae esta opción. El problema es que este correo no está asociado a ningún estado de pedido, ni se puede asociar.

Para poder conseguir esta funcionalidad, os traemos una modificación que hemos encontrado en GitHub en un post que preguntaban exactamente lo mismo. Es necesario modificar dos archivos pero en este caso no tiene mucha dificultad.

Qué archivos son necesarios modificar para poder reenviar el correo de confirmación de pedido

En este caso, los ficheros son:

  1. /public_html/CARPETABACKOFFICE/themes/default/template/controllers/orders/helpers/view/view.tpl
  2. /public_html/controllers/admin/AdminOrdersController.php

Recuerda que tienes que sustituir CARPETABACKOFICE por el nombre real de tu acceso al panel de gestión de tu Prestashop.

En el primer fichero hay que añadir el siguiente código donde queramos (esto hará que en el panel de pedido del backoffice tendremos un enlace para lanzar el reenvío del correo):

<a href="{$current_index}&amp;submitResendConf&amp;id_order={$order-&gt;id}&amp;token={$smarty.get.token|escape:'html':'UTF-8'}">
<i class="icon-mail-reply"></i> Resend order confirmation email
</a>

Yo lo suelo añadir en la barra superior izquierda, donde sale la información con el ID del pedido (aprox. línea 115 del fichero). El resultado final quedaría así:

reenviar correo confirmacion prestashop
Podemos apreciar el enlace con el texto «RESEND ORDER CONFIRMATION EMAIL».

El código final del trozo modificado (el div con clase panel-heading), por si lo queréis copiar y pegar y evitar posibles errores, sería este:

<div class="panel-heading">
    <i class="icon-credit-card"></i>
    {l s='Order' d='Admin.Global'}
    <span class="badge">{$order->reference}</span>
    <span class="badge">{l s="#" d='Admin.Orderscustomers.Feature'}{$order->id}</span>
    <a href="{$current_index}&amp;submitResendConf&amp;id_order={$order-&gt;id}&amp;token={$smarty.get.token|escape:'html':'UTF-8'}"><i class="icon-mail-reply"></i>  Resend order confirmation email</a>
    <div class="panel-heading-action">
        <div class="btn-group">
            <a class="btn btn-default{if !$previousOrder} disabled{/if}" href="{$link->getAdminLink('AdminOrders', true, [], ['vieworder' => 1, 'id_order' => $previousOrder|intval])|escape:'html':'UTF-8'}">
                <i class="icon-backward"></i>
            </a>
            <a class="btn btn-default{if !$nextOrder} disabled{/if}" href="{$link->getAdminLink('AdminOrders', true, [], ['vieworder' => 1, 'id_order' => $nextOrder|intval])|escape:'html':'UTF-8'}">
                <i class="icon-forward"></i>
            </a>
        </div>
    </div>
</div>

A continuación pasamos al siguiente fichero. En este caso el cambio es más fácil. Directamente tenéis que buscar la función postProcess y cambiarla por el siguiente código:

protected function _getFormatedAddress(Address $the_address, $line_sep, $fields_style = array())
	{
		return AddressFormat::generateAddress($the_address, array('avoid' => array()), $line_sep, ' ', $fields_style);
	}
 
	public function postProcess()
	{
		// If id_order is sent, we instanciate a new Order object
		if (Tools::isSubmit('id_order') && Tools::getValue('id_order') > 0) {
			$order = new Order(Tools::getValue('id_order'));
			if (!Validate::isLoadedObject($order)) {
				$this->errors[] = $this->trans('The order cannot be found within your database.', array(), 'Admin.Orderscustomers.Notification');
			}
			ShopUrl::cacheMainDomainForShop((int) $order->id_shop);
		}
 
		/* Resend conf email */
		if (Tools::isSubmit('submitResendConf') && isset($order)) {
			if ($this->access('edit')) {
 
				$carrier = new Carrier((int)$order->id_carrier);
				$product_list_txt = '';
				$product_list_html = '';
				$products = $order->getProducts();
 
				$customized_datas = Product::getAllCustomizedDatas((int)$order->id_cart);
				Product::addCustomizationPrice($products, $customized_datas);
				foreach ($products as $key => $product)
				{
					$unit_price = Product::getTaxCalculationMethod($customer->id) == PS_TAX_EXC ? $product['product_price'] : $product['product_price_wt'];
 
					$customization_text = '';
					if (isset($customized_datas[$product['product_id']][$product['product_attribute_id']])) {
						foreach ($customized_datas[$product['product_id']][$product['product_attribute_id']][$order->id_address_delivery] as $customization) {
							if (isset($customization['datas'][Product::CUSTOMIZE_TEXTFIELD])) {
								foreach ($customization['datas'][Product::CUSTOMIZE_TEXTFIELD] as $text) {
									$customization_text .= $text['name'].': '.$text['value'].'<br />';
								}
							}
 
							if (isset($customization['datas'][Product::CUSTOMIZE_FILE])) {
								$customization_text .= count($customization['datas'][Product::CUSTOMIZE_FILE]).' '.$this->trans('image(s)', array(), 'Modules.Mailalerts.Admin').'<br />';
							}
 
							$customization_text .= '---<br />';
						}
						if (method_exists('Tools', 'rtrimString')) {
							$customization_text = Tools::rtrimString($customization_text, '---<br />');
						} else {
							$customization_text = preg_replace('/---<br \/>$/', '', $customization_text);
						}
					}
 
 
					$url = $this->context->link->getProductLink($product['product_id']);
					$product_list_html .=
						'<tr>
							<td style="padding: 10px 0;" width="18%">
								<font size="2" face="Arial, sans-serif" color="#414a56">
									<p style="margin: 0; padding: 0 5px; font-size: 14px">'.$product['product_reference'].'</p>
								</font>
							</td>
							<td style="padding: 10px 0;" width="47%">
								<font size="2" face="Arial, sans-serif" color="#414a56">
									<p class="name-product" style="margin: 0; padding: 0 5px; font-size: 14px; color: #414a56; font-weight: bold;">'.$product['product_name']
 
									.(isset($product['attributes_small']) ? ' '.$product['attributes_small'] : '')
									.(!empty($customization_text) ? '<br />'.$customization_text : '')
 
								 . '</p>
								</font>
							</td>                            
							<td style="padding: 10px 0;" width="15%">
								<font size="2" face="Arial, sans-serif" color="#414a56">
									<p style="margin: 0; padding: 0 5px; font-size: 14px">'.Tools::displayPrice($unit_price, $currency, false).'</p>
								</font>
							</td>
							<td style="padding: 10px 0;" width="5%">
								<font size="2" face="Arial, sans-serif" color="#414a56">
									<p style="margin: 0; padding: 0 5px; font-size: 14px">'.(int)$product['product_quantity'].'</p>
								</font>
							</td>
							<td align="right" style="padding: 10px 0;" width="15%">
								<font size="2" face="Arial, sans-serif" color="#414a56">
									<p style="margin: 0; padding: 0 5px; font-size: 14px">' 
										.Tools::displayPrice(($unit_price * $product['product_quantity']), $currency, false)
									.'</p>
								</font>
							</td>
						</tr>';
 
					$product_list_txt .= $product['product_reference'].' - '.$product['product_name'].' - '	.(isset($product['attributes_small']) ? ' '.$product['attributes_small'] : '')
									.(!empty($customization_text) ? ' - '.$customization_text : '')
 
								.' - '.Tools::displayPrice($unit_price, $currency, false).' - '.(int)$product['product_quantity'].' ks - '
								.Tools::displayPrice(($unit_price * $product['product_quantity']), $currency, false);	
				}
 
 
				// Zjištění slev
 
 
				$cart_rules_list_txt = '';
				$cart_rules_list_html = '';
 
				foreach ($order->getCartRules() as $discount)
				{
 
					$cart_rules_list_html .='<tr class="conf_body">
					<td colspan="3" align="left" style="padding: 10px 0; ">
						<font size="2" face="Arial, sans-serif" color="#414a56">
							<p class="name-product" style="margin: 0; padding: 0 5px; font-size: 14px; color: #414a56; font-weight: bold;">'.$discount['name'].'</p>
						</font>
					</td>
					<td colspan="2" align="right" style="padding: 10px 0; ">
						<font size="2" face="Arial, sans-serif" color="#414a56">
							<p style="margin: 0; padding: 0 5px; font-size: 14px">'.Tools::displayPrice($discount['value'], $currency, false).'</p>
						</font>
					</td>
				</tr>';
 
					$cart_rules_list_txt .=	$discount['name'].' - ' . Tools::displayPrice($discount['value'], $currency, false);
				}
 
 
				$invoice = new Address((int)$order->id_address_invoice);
				$delivery = new Address((int)$order->id_address_delivery);
				$delivery_state = $delivery->id_state ? new State((int)$delivery->id_state) : false;
				$invoice_state = $invoice->id_state ? new State((int)$invoice->id_state) : false;
 
				$data = array(
					// openservis
					'{message}' => $order->getFirstMessage(),
					'{firstname}' => $this->context->customer->firstname,
					'{lastname}' => $this->context->customer->lastname,
					'{email}' => $this->context->customer->email,
					'{delivery_block_txt}' => $this->_getFormatedAddress($delivery, "\n"),
					'{invoice_block_txt}' => $this->_getFormatedAddress($invoice, "\n"),
					'{delivery_block_html}' => $this->_getFormatedAddress($delivery, '<br />', array(
						'firstname' => '<span style="font-weight:bold;">%s</span>',
						'lastname' => '<span style="font-weight:bold;">%s</span>'
					)),
					'{invoice_block_html}' => $this->_getFormatedAddress($invoice, '<br />', array(
						'firstname' => '<span style="font-weight:bold;">%s</span>',
						'lastname' => '<span style="font-weight:bold;">%s</span>'
					)),
					'{delivery_company}' => $delivery->company,
					'{delivery_firstname}' => $delivery->firstname,
					'{delivery_lastname}' => $delivery->lastname,
					'{delivery_address1}' => $delivery->address1,
					'{delivery_address2}' => $delivery->address2,
					'{delivery_city}' => $delivery->city,
					'{delivery_postal_code}' => $delivery->postcode,
					'{delivery_country}' => $delivery->country,
					'{delivery_state}' => $delivery->id_state ? $delivery_state->name : '',
					'{delivery_phone}' => ($delivery->phone) ? $delivery->phone : $delivery->phone_mobile,
					'{delivery_other}' => $delivery->other,
					'{invoice_company}' => $invoice->company,
					'{invoice_vat_number}' => $invoice->vat_number,
					'{invoice_firstname}' => $invoice->firstname,
					'{invoice_lastname}' => $invoice->lastname,
					'{invoice_address2}' => $invoice->address2,
					'{invoice_address1}' => $invoice->address1,
					'{invoice_city}' => $invoice->city,
					'{invoice_postal_code}' => $invoice->postcode,
					'{invoice_country}' => $invoice->country,
					'{invoice_state}' => $invoice->id_state ? $invoice_state->name : '',
					'{invoice_phone}' => ($invoice->phone) ? $invoice->phone : $invoice->phone_mobile,
					'{invoice_other}' => $invoice->other,
					'{order_name}' => $order->getUniqReference(),
					'{date}' => Tools::displayDate($order->date_upd, null , 1),
					// openservis
					'{carrier}' => $carrier->name,
					'{payment}' => Tools::substr($order->payment, 0, 32),
					'{products}' => $product_list_html,
					'{products_txt}' => $product_list_txt,
					'{discounts}' => $cart_rules_list_html,
					'{discounts_txt}' => $cart_rules_list_txt,
					'{total_paid}' => Tools::displayPrice($order->total_paid, $this->context->currency, false),
					'{total_paid_tax_excl}' => Tools::displayPrice($order->total_paid_tax_excl, $this->context->currency, false),
					'{total_products}' => Tools::displayPrice(Product::getTaxCalculationMethod() == PS_TAX_EXC ? $order->total_products : $order->total_products_wt, $this->context->currency, false),
					'{total_discounts}' => Tools::displayPrice($order->total_discounts, $this->context->currency, false),
					'{total_shipping}' => Tools::displayPrice($order->total_shipping, $this->context->currency, false),
					'{total_wrapping}' => Tools::displayPrice($order->total_wrapping, $this->context->currency, false),
					'{total_tax_paid}' => Tools::displayPrice($order->total_paid_tax_incl - $order->total_paid_tax_excl, $this->context->currency, false));
 
 
 
			   if (Validate::isEmail($this->context->customer->email)) {
					Mail::Send(
						(int)$order->id_lang,
						'order_conf',
						Mail::l('Order confirmation', (int)$order->id_lang),
						$data,
						$this->context->customer->email,
						$this->context->customer->firstname . ' ' . $this->context->customer->lastname,
						null,
						null,
						null,
						null, _PS_MAIL_DIR_, false, (int)$order->id_shop
					);
				}
 
 
				Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=10&token='.$this->token);	
			} else {
				$this->errors[] = $this->trans('You do not have permission to edit this.', array(), 'Admin.Notifications.Error');
			}
		}
		/* Resend conf email */
 
		/* Update shipping number and carrier */
		if (Tools::isSubmit('submitShippingNumber') && isset($order)) {
			if ($this->access('edit')) {
				$tracking_number = Tools::getValue('shipping_tracking_number');
				$id_carrier = Tools::getValue('shipping_carrier');
				$old_tracking_number = $order->shipping_number;
 
				$order_carrier = new OrderCarrier(Tools::getValue('id_order_carrier'));
				if (!Validate::isLoadedObject($order_carrier)) {
					$this->errors[] = $this->trans('The order carrier ID is invalid.', array(), 'Admin.Orderscustomers.Notification');
				} elseif (!empty($tracking_number) && !Validate::isTrackingNumber($tracking_number)) {
					$this->errors[] = $this->trans('The tracking number is incorrect.', array(), 'Admin.Orderscustomers.Notification');
				} else {
					//update carrier - ONLY if changed - then refresh shipping cost
					$old_id_carrier = $order_carrier->id_carrier;
					if (!empty($id_carrier) && $old_id_carrier != $id_carrier) {
						$order->id_carrier = (int) $id_carrier;
						$order_carrier->id_carrier = (int) $id_carrier;
						$order_carrier->update();
						$order->refreshShippingCost();
					}
 
					//load fresh order carrier because updated just before
					$order_carrier = new OrderCarrier((int) Tools::getValue('id_order_carrier'));
 
					// update shipping number
					// Keep these two following lines for backward compatibility, remove on 1.6 version
					$order->shipping_number = $tracking_number;
					$order->update();
 
					// Update order_carrier
					$order_carrier->tracking_number = pSQL($tracking_number);
					if ($order_carrier->update()) {
						//send mail only if tracking number is different AND not empty
						if (!empty($tracking_number) && $old_tracking_number != $tracking_number) {
							if ($order_carrier->sendInTransitEmail($order)) {
								$customer = new Customer((int) $order->id_customer);
								$carrier = new Carrier((int) $order->id_carrier, $order->id_lang);
 
								Hook::exec('actionAdminOrdersTrackingNumberUpdate', array(
									'order' => $order,
									'customer' => $customer,
									'carrier' => $carrier,
								), null, false, true, false, $order->id_shop);
 
								Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=4&token=' . $this->token);
							} else {
								$this->errors[] = $this->trans('An error occurred while sending an email to the customer.', array(), 'Admin.Orderscustomers.Notification');
							}
						}
					} else {
						$this->errors[] = $this->trans('The order carrier cannot be updated.', array(), 'Admin.Orderscustomers.Notification');
					}
				}
			} else {
				$this->errors[] = $this->trans('You do not have permission to edit this.', array(), 'Admin.Notifications.Error');
			}
		} elseif (Tools::isSubmit('submitState') && isset($order)) {
			/* Change order status, add a new entry in order history and send an e-mail to the customer if needed */
			if ($this->access('edit')) {
				$order_state = new OrderState(Tools::getValue('id_order_state'));
 
				if (!Validate::isLoadedObject($order_state)) {
					$this->errors[] = $this->trans('The new order status is invalid.', array(), 'Admin.Orderscustomers.Notification');
				} else {
					$current_order_state = $order->getCurrentOrderState();
					if ($current_order_state->id != $order_state->id) {
						// 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();
						if ($history->id_order_state == Configuration::get('PS_OS_SHIPPING') && $order->shipping_number) {
							$templateVars = array('{followup}' => str_replace('@', $order->shipping_number, $carrier->url));
						}
 
						// 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 . '&vieworder&token=' . $this->token);
						}
						$this->errors[] = $this->trans('An error occurred while changing order status, or we were unable to send an email to the customer.', array(), 'Admin.Orderscustomers.Notification');
					} else {
						$this->errors[] = $this->trans('The order has already been assigned this status.', array(), 'Admin.Orderscustomers.Notification');
					}
				}
			} else {
				$this->errors[] = $this->trans('You do not have permission to edit this.', array(), 'Admin.Notifications.Error');
			}
		} elseif (Tools::isSubmit('submitMessage') && isset($order)) {
			// Add a new message for the current order and send an e-mail to the customer if needed
			if ($this->access('edit')) {
				$customer = new Customer(Tools::getValue('id_customer'));
				if (!Validate::isLoadedObject($customer)) {
					$this->errors[] = $this->trans('The customer is invalid.', array(), 'Admin.Orderscustomers.Notification');
				} elseif (!Tools::getValue('message')) {
					$this->errors[] = $this->trans('The message cannot be blank.', array(), 'Admin.Orderscustomers.Notification');
				} else {
					/* Get message rules and and check fields validity */
					$rules = call_user_func(array('Message', 'getValidationRules'), 'Message');
					foreach ($rules['required'] as $field) {
						if (($value = Tools::getValue($field)) == false && (string) $value != '0') {
							if (!Tools::getValue('id_' . $this->table) || $field != 'passwd') {
								$this->errors[] = $this->trans('field %s is required.', array('%s' => $field), 'Admin.Orderscustomers.Notification');
							}
						}
					}
					foreach ($rules['size'] as $field => $maxLength) {
						if (Tools::getValue($field) && Tools::strlen(Tools::getValue($field)) > $maxLength) {
							$this->errors[] = $this->trans(
								'The %1$s field is too long (%2$d chars max).',
								array(
									'%1$s' => $field,
									'%2$d' => $maxLength,
								),
								'Admin.Notifications.Error'
							);
						}
					}
					foreach ($rules['validate'] as $field => $function) {
						if (Tools::getValue($field)) {
							if (!Validate::$function(htmlentities(Tools::getValue($field), ENT_COMPAT, 'UTF-8'))) {
								$this->errors[] = $this->trans('The %s field is invalid.', array('%s' => $field), 'Admin.Notifications.Error');
							}
						}
					}
 
					if (!count($this->errors)) {
						//check if a thread already exist
						$id_customer_thread = CustomerThread::getIdCustomerThreadByEmailAndIdOrder($customer->email, $order->id);
						if (!$id_customer_thread) {
							$customer_thread = new CustomerThread();
							$customer_thread->id_contact = 0;
							$customer_thread->id_customer = (int) $order->id_customer;
							$customer_thread->id_shop = (int) $this->context->shop->id;
							$customer_thread->id_order = (int) $order->id;
							$customer_thread->id_lang = (int) $this->context->language->id;
							$customer_thread->email = $customer->email;
							$customer_thread->status = 'open';
							$customer_thread->token = Tools::passwdGen(12);
							$customer_thread->add();
						} else {
							$customer_thread = new CustomerThread((int) $id_customer_thread);
						}
 
						$customer_message = new CustomerMessage();
						$customer_message->id_customer_thread = $customer_thread->id;
						$customer_message->id_employee = (int) $this->context->employee->id;
						$customer_message->message = Tools::getValue('message');
						$customer_message->private = Tools::getValue('visibility');
 
						if (!$customer_message->add()) {
							$this->errors[] = $this->trans('An error occurred while saving the message.', array(), 'Admin.Notifications.Error');
						} elseif ($customer_message->private) {
							Tools::redirectAdmin(self::$currentIndex . '&id_order=' . (int) $order->id . '&vieworder&conf=11&token=' . $this->token);
						} else {
							$message = $customer_message->message;
							if (Configuration::get('PS_MAIL_TYPE', null, null, $order->id_shop) != Mail::TYPE_TEXT) {
								$message = Tools::nl2br($customer_message->message);
							}
 
							$orderLanguage = new Language((int) $order->id_lang);
							$varsTpl = array(
								'{lastname}' => $customer->lastname,
								'{firstname}' => $customer->firstname,
								'{id_order}' => $order->id,
								'{order_name}' => $order->getUniqReference(),
								'{message}' => $message,
							);
 
							if (
								@Mail::Send(
									(int) $order->id_lang,
									'order_merchant_comment',
									$this->trans(
										'New message regarding your order',
										array(),
										'Emails.Subject',
										$orderLanguage->locale
									),
									$varsTpl,
									$customer->email,
									$customer->firstname . ' ' . $customer->lastname,
									null,
									null,
									null,
									null,
									_PS_MAIL_DIR_,
									true,
									(int) $order->id_shop
								)
							) {
								Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=11' . '&token=' . $this->token);
							}
						}
						$this->errors[] = $this->trans('An error occurred while sending an email to the customer.', array(), 'Admin.Orderscustomers.Notification');
					}
				}
			} else {
				$this->errors[] = $this->trans('You do not have permission to delete this.', array(), 'Admin.Notifications.Error');
			}
		} elseif (Tools::isSubmit('partialRefund') && isset($order)) {
			// Partial refund from order
			if ($this->access('edit')) {
				if (Tools::isSubmit('partialRefundProduct') && ($refunds = Tools::getValue('partialRefundProduct')) && is_array($refunds)) {
					$amount = 0;
					$order_detail_list = array();
					$full_quantity_list = array();
					foreach ($refunds as $id_order_detail => $amount_detail) {
						$quantity = Tools::getValue('partialRefundProductQuantity');
						if (!$quantity[$id_order_detail]) {
							continue;
						}
 
						$full_quantity_list[$id_order_detail] = (int) $quantity[$id_order_detail];
 
						$order_detail_list[$id_order_detail] = array(
							'quantity' => (int) $quantity[$id_order_detail],
							'id_order_detail' => (int) $id_order_detail,
						);
 
						$order_detail = new OrderDetail((int) $id_order_detail);
						if (empty($amount_detail)) {
							$order_detail_list[$id_order_detail]['unit_price'] = (!Tools::getValue('TaxMethod') ? $order_detail->unit_price_tax_excl : $order_detail->unit_price_tax_incl);
							$order_detail_list[$id_order_detail]['amount'] = $order_detail->unit_price_tax_incl * $order_detail_list[$id_order_detail]['quantity'];
						} else {
							$order_detail_list[$id_order_detail]['amount'] = (float) str_replace(',', '.', $amount_detail);
							$order_detail_list[$id_order_detail]['unit_price'] = $order_detail_list[$id_order_detail]['amount'] / $order_detail_list[$id_order_detail]['quantity'];
						}
						$amount += $order_detail_list[$id_order_detail]['amount'];
						if (!$order->hasBeenDelivered() || ($order->hasBeenDelivered() && Tools::isSubmit('reinjectQuantities')) && $order_detail_list[$id_order_detail]['quantity'] > 0) {
							$this->reinjectQuantity($order_detail, $order_detail_list[$id_order_detail]['quantity']);
						}
					}
 
					$shipping_cost_amount = (float) str_replace(',', '.', Tools::getValue('partialRefundShippingCost')) ? (float) str_replace(',', '.', Tools::getValue('partialRefundShippingCost')) : false;
 
					if ($amount == 0 && $shipping_cost_amount == 0) {
						if (!empty($refunds)) {
							$this->errors[] = $this->trans('Please enter a quantity to proceed with your refund.', array(), 'Admin.Orderscustomers.Notification');
						} else {
							$this->errors[] = $this->trans('Please enter an amount to proceed with your refund.', array(), 'Admin.Orderscustomers.Notification');
						}
 
						return false;
					}
 
					$choosen = false;
					$voucher = 0;
 
					if ((int) Tools::getValue('refund_voucher_off') == 1) {
						$amount -= $voucher = (float) Tools::getValue('order_discount_price');
					} elseif ((int) Tools::getValue('refund_voucher_off') == 2) {
						$choosen = true;
						$amount = $voucher = (float) Tools::getValue('refund_voucher_choose');
					}
 
					if ($shipping_cost_amount > 0) {
						if (!Tools::getValue('TaxMethod')) {
							$tax = new Tax();
							$tax->rate = $order->carrier_tax_rate;
							$tax_calculator = new TaxCalculator(array($tax));
							$amount += $tax_calculator->addTaxes($shipping_cost_amount);
						} else {
							$amount += $shipping_cost_amount;
						}
					}
 
					$order_carrier = new OrderCarrier((int) $order->getIdOrderCarrier());
					if (Validate::isLoadedObject($order_carrier)) {
						$order_carrier->weight = (float) $order->getTotalWeight();
						if ($order_carrier->update()) {
							$order->weight = sprintf('%.3f ' . Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight);
						}
					}
 
					if ($amount >= 0) {
						if (!OrderSlip::create(
							$order,
							$order_detail_list,
							$shipping_cost_amount,
							$voucher,
							$choosen,
							(Tools::getValue('TaxMethod') ? false : true)
						)) {
							$this->errors[] = $this->trans('You cannot generate a partial credit slip.', array(), 'Admin.Orderscustomers.Notification');
						} else {
							Hook::exec('actionOrderSlipAdd', array('order' => $order, 'productList' => $order_detail_list, 'qtyList' => $full_quantity_list), null, false, true, false, $order->id_shop);
							$customer = new Customer((int) ($order->id_customer));
							$params['{lastname}'] = $customer->lastname;
							$params['{firstname}'] = $customer->firstname;
							$params['{id_order}'] = $order->id;
							$params['{order_name}'] = $order->getUniqReference();
							$orderLanguage = new Language((int) $order->id_lang);
							@Mail::Send(
								(int) $order->id_lang,
								'credit_slip',
								$this->trans(
									'New credit slip regarding your order',
									array(),
									'Emails.Subject',
									$orderLanguage->locale
								),
								$params,
								$customer->email,
								$customer->firstname . ' ' . $customer->lastname,
								null,
								null,
								null,
								null,
								_PS_MAIL_DIR_,
								true,
								(int) $order->id_shop
							);
						}
 
						foreach ($order_detail_list as &$product) {
							$order_detail = new OrderDetail((int) $product['id_order_detail']);
							if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
								StockAvailable::synchronize($order_detail->product_id);
							}
						}
 
						// Generate voucher
						if (Tools::isSubmit('generateDiscountRefund') && !count($this->errors) && $amount > 0) {
							$cart_rule = new CartRule();
							$cart_rule->description = $this->trans('Credit slip for order #%d', array('#%d' => $order->id), 'Admin.Orderscustomers.Feature');
							$language_ids = Language::getIDs(false);
							foreach ($language_ids as $id_lang) {
								// Define a temporary name
								$cart_rule->name[$id_lang] = sprintf('V0C%1$dO%2$d', $order->id_customer, $order->id);
							}
 
							// Define a temporary code
							$cart_rule->code = sprintf('V0C%1$dO%2$d', $order->id_customer, $order->id);
							$cart_rule->quantity = 1;
							$cart_rule->quantity_per_user = 1;
 
							// Specific to the customer
							$cart_rule->id_customer = $order->id_customer;
							$now = time();
							$cart_rule->date_from = date('Y-m-d H:i:s', $now);
							$cart_rule->date_to = date('Y-m-d H:i:s', strtotime('+1 year'));
							$cart_rule->partial_use = 1;
							$cart_rule->active = 1;
 
							$cart_rule->reduction_amount = $amount;
							$cart_rule->reduction_tax = $order->getTaxCalculationMethod() != PS_TAX_EXC;
							$cart_rule->minimum_amount_currency = $order->id_currency;
							$cart_rule->reduction_currency = $order->id_currency;
 
							if (!$cart_rule->add()) {
								$this->errors[] = $this->trans('You cannot generate a voucher.', array(), 'Admin.Orderscustomers.Notification');
							} else {
								// Update the voucher code and name
								foreach ($language_ids as $id_lang) {
									$cart_rule->name[$id_lang] = sprintf('V%1$dC%2$dO%3$d', $cart_rule->id, $order->id_customer, $order->id);
								}
								$cart_rule->code = sprintf('V%1$dC%2$dO%3$d', $cart_rule->id, $order->id_customer, $order->id);
 
								if (!$cart_rule->update()) {
									$this->errors[] = $this->trans('You cannot generate a voucher.', array(), 'Admin.Orderscustomers.Notification');
								} else {
									$currency = $this->context->currency;
									$customer = new Customer((int) ($order->id_customer));
									$params['{lastname}'] = $customer->lastname;
									$params['{firstname}'] = $customer->firstname;
									$params['{id_order}'] = $order->id;
									$params['{order_name}'] = $order->getUniqReference();
									$params['{voucher_amount}'] = Tools::displayPrice($cart_rule->reduction_amount, $currency, false);
									$params['{voucher_num}'] = $cart_rule->code;
									$orderLanguage = new Language((int) $order->id_lang);
									@Mail::Send(
										(int) $order->id_lang,
										'voucher',
										$this->trans(
											'New voucher for your order #%s',
											array($order->reference),
											'Emails.Subject',
											$orderLanguage->locale
										),
										$params,
										$customer->email,
										$customer->firstname . ' ' . $customer->lastname,
										null,
										null,
										null,
										null,
										_PS_MAIL_DIR_,
										true,
										(int) $order->id_shop
									);
								}
							}
						}
					} else {
						if (!empty($refunds)) {
							$this->errors[] = $this->trans('Please enter a quantity to proceed with your refund.', array(), 'Admin.Orderscustomers.Notification');
						} else {
							$this->errors[] = $this->trans('Please enter an amount to proceed with your refund.', array(), 'Admin.Orderscustomers.Notification');
						}
					}
 
					// Redirect if no errors
					if (!count($this->errors)) {
						Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=30&token=' . $this->token);
					}
				} else {
					$this->errors[] = $this->trans('The partial refund data is incorrect.', array(), 'Admin.Orderscustomers.Notification');
				}
			} else {
				$this->errors[] = $this->trans('You do not have permission to delete this.', array(), 'Admin.Notifications.Error');
			}
		} elseif (Tools::isSubmit('cancelProduct') && isset($order)) {
			// Cancel product from order
			if ($this->access('delete')) {
				if (!Tools::isSubmit('id_order_detail') && !Tools::isSubmit('id_customization')) {
					$this->errors[] = $this->trans('You must select a product.', array(), 'Admin.Orderscustomers.Notification');
				} elseif (!Tools::isSubmit('cancelQuantity') && !Tools::isSubmit('cancelCustomizationQuantity')) {
					$this->errors[] = $this->trans('You must enter a quantity.', array(), 'Admin.Orderscustomers.Notification');
				} else {
					$productList = Tools::getValue('id_order_detail');
					if ($productList) {
						$productList = array_map('intval', $productList);
					}
 
					$customizationList = Tools::getValue('id_customization');
					if ($customizationList) {
						$customizationList = array_map('intval', $customizationList);
					}
 
					$qtyList = Tools::getValue('cancelQuantity');
					if ($qtyList) {
						$qtyList = array_map('intval', $qtyList);
					}
 
					$customizationQtyList = Tools::getValue('cancelCustomizationQuantity');
					if ($customizationQtyList) {
						$customizationQtyList = array_map('intval', $customizationQtyList);
					}
 
					$full_product_list = $productList;
					$full_quantity_list = $qtyList;
 
					if ($customizationList) {
						foreach ($customizationList as $key => $id_order_detail) {
							$full_product_list[(int) $id_order_detail] = $id_order_detail;
							if (isset($customizationQtyList[$key])) {
								$full_quantity_list[(int) $id_order_detail] += $customizationQtyList[$key];
							}
						}
					}
 
					if ($productList || $customizationList) {
						if ($productList) {
							$id_cart = Cart::getCartIdByOrderId($order->id);
							$customization_quantities = Customization::countQuantityByCart($id_cart);
 
							foreach ($productList as $key => $id_order_detail) {
								$qtyCancelProduct = abs($qtyList[$key]);
								if (!$qtyCancelProduct) {
									$this->errors[] = $this->trans('No quantity has been selected for this product.', array(), 'Admin.Orderscustomers.Notification');
								}
 
								$order_detail = new OrderDetail($id_order_detail);
								$customization_quantity = 0;
								if (array_key_exists($order_detail->product_id, $customization_quantities) && array_key_exists($order_detail->product_attribute_id, $customization_quantities[$order_detail->product_id])) {
									$customization_quantity = (int) $customization_quantities[$order_detail->product_id][$order_detail->product_attribute_id];
								}
 
								if (($order_detail->product_quantity - $customization_quantity - $order_detail->product_quantity_refunded - $order_detail->product_quantity_return) < $qtyCancelProduct) {
									$this->errors[] = $this->trans('An invalid quantity was selected for this product.', array(), 'Admin.Orderscustomers.Notification');
								}
							}
						}
						if ($customizationList) {
							$customization_quantities = Customization::retrieveQuantitiesFromIds(array_keys($customizationList));
 
							foreach ($customizationList as $id_customization => $id_order_detail) {
								$qtyCancelProduct = abs($customizationQtyList[$id_customization]);
								$customization_quantity = $customization_quantities[$id_customization];
 
								if (!$qtyCancelProduct) {
									$this->errors[] = $this->trans('No quantity has been selected for this product.', array(), 'Admin.Orderscustomers.Notification');
								}
 
								if ($qtyCancelProduct > ($customization_quantity['quantity'] - ($customization_quantity['quantity_refunded'] + $customization_quantity['quantity_returned']))) {
									$this->errors[] = $this->trans('An invalid quantity was selected for this product.', array(), 'Admin.Orderscustomers.Notification');
								}
							}
						}
 
						if (!count($this->errors) && $productList) {
							foreach ($productList as $key => $id_order_detail) {
								$qty_cancel_product = abs($qtyList[$key]);
								$order_detail = new OrderDetail((int) ($id_order_detail));
 
								if (!$order->hasBeenDelivered() || ($order->hasBeenDelivered() && Tools::isSubmit('reinjectQuantities')) && $qty_cancel_product > 0) {
									$this->reinjectQuantity($order_detail, $qty_cancel_product);
								}
 
								// Delete product
								$order_detail = new OrderDetail((int) $id_order_detail);
								if (!$order->deleteProduct($order, $order_detail, $qty_cancel_product)) {
									$this->errors[] = $this->trans('An error occurred while attempting to delete the product.', array(), 'Admin.Orderscustomers.Notification') . ' <span class="bold">' . $order_detail->product_name . '</span>';
								}
								// Update weight SUM
								$order_carrier = new OrderCarrier((int) $order->getIdOrderCarrier());
								if (Validate::isLoadedObject($order_carrier)) {
									$order_carrier->weight = (float) $order->getTotalWeight();
									if ($order_carrier->update()) {
										$order->weight = sprintf('%.3f ' . Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight);
									}
								}
 
								if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && StockAvailable::dependsOnStock($order_detail->product_id)) {
									StockAvailable::synchronize($order_detail->product_id);
								}
								Hook::exec('actionProductCancel', array('order' => $order, 'id_order_detail' => (int) $id_order_detail), null, false, true, false, $order->id_shop);
							}
						}
						if (!count($this->errors) && $customizationList) {
							foreach ($customizationList as $id_customization => $id_order_detail) {
								$order_detail = new OrderDetail((int) ($id_order_detail));
								$qtyCancelProduct = abs($customizationQtyList[$id_customization]);
								if (!$order->deleteCustomization($id_customization, $qtyCancelProduct, $order_detail)) {
									$this->errors[] = $this->trans('An error occurred while attempting to delete product customization.', array(), 'Admin.Orderscustomers.Notification') . ' ' . $id_customization;
								}
							}
						}
						// E-mail params
						if ((Tools::isSubmit('generateCreditSlip') || Tools::isSubmit('generateDiscount')) && !count($this->errors)) {
							$customer = new Customer((int) ($order->id_customer));
							$params['{lastname}'] = $customer->lastname;
							$params['{firstname}'] = $customer->firstname;
							$params['{id_order}'] = $order->id;
							$params['{order_name}'] = $order->getUniqReference();
						}
 
						// Generate credit slip
						if (Tools::isSubmit('generateCreditSlip') && !count($this->errors)) {
							$product_list = array();
							$amount = $order_detail->unit_price_tax_incl * $full_quantity_list[$id_order_detail];
 
							$choosen = false;
							if ((int) Tools::getValue('refund_total_voucher_off') == 1) {
								$amount -= $voucher = (float) Tools::getValue('order_discount_price');
							} elseif ((int) Tools::getValue('refund_total_voucher_off') == 2) {
								$choosen = true;
								$amount = $voucher = (float) Tools::getValue('refund_total_voucher_choose');
							}
							foreach ($full_product_list as $id_order_detail) {
								$order_detail = new OrderDetail((int) $id_order_detail);
								$product_list[$id_order_detail] = array(
									'id_order_detail' => $id_order_detail,
									'quantity' => $full_quantity_list[$id_order_detail],
									'unit_price' => $order_detail->unit_price_tax_excl,
									'amount' => isset($amount) ? $amount : $order_detail->unit_price_tax_incl * $full_quantity_list[$id_order_detail],
								);
							}
 
							$shipping = Tools::isSubmit('shippingBack') ? null : false;
 
							if (!OrderSlip::create($order, $product_list, $shipping, $voucher, $choosen)) {
								$this->errors[] = $this->trans('A credit slip cannot be generated.', array(), 'Admin.Orderscustomers.Notification');
							} else {
								Hook::exec('actionOrderSlipAdd', array('order' => $order, 'productList' => $full_product_list, 'qtyList' => $full_quantity_list), null, false, true, false, $order->id_shop);
								$orderLanguage = new Language((int) $order->id_lang);
								@Mail::Send(
									(int) $order->id_lang,
									'credit_slip',
									$this->trans(
										'New credit slip regarding your order',
										array(),
										'Emails.Subject',
										$orderLanguage->locale
									),
									$params,
									$customer->email,
									$customer->firstname . ' ' . $customer->lastname,
									null,
									null,
									null,
									null,
									_PS_MAIL_DIR_,
									true,
									(int) $order->id_shop
								);
							}
						}
 
						// Generate voucher
						if (Tools::isSubmit('generateDiscount') && !count($this->errors)) {
							$cartrule = new CartRule();
							$language_ids = Language::getIDs((bool) $order);
							$cartrule->description = $this->trans('Credit card slip for order #%d', array('#%d' => $order->id), 'Admin.Orderscustomers.Feature');
							foreach ($language_ids as $id_lang) {
								// Define a temporary name
								$cartrule->name[$id_lang] = 'V0C' . (int) ($order->id_customer) . 'O' . (int) ($order->id);
							}
							// Define a temporary code
							$cartrule->code = 'V0C' . (int) ($order->id_customer) . 'O' . (int) ($order->id);
 
							$cartrule->quantity = 1;
							$cartrule->quantity_per_user = 1;
							// Specific to the customer
							$cartrule->id_customer = $order->id_customer;
							$now = time();
							$cartrule->date_from = date('Y-m-d H:i:s', $now);
							$cartrule->date_to = date('Y-m-d H:i:s', $now + (3600 * 24 * 365.25)); /* 1 year */
							$cartrule->active = 1;
 
							$products = $order->getProducts(false, $full_product_list, $full_quantity_list);
 
							$total = 0;
							foreach ($products as $product) {
								$total += $product['unit_price_tax_incl'] * $product['product_quantity'];
							}
 
							if (Tools::isSubmit('shippingBack')) {
								$total += $order->total_shipping;
							}
 
							if ((int) Tools::getValue('refund_total_voucher_off') == 1) {
								$total -= (float) Tools::getValue('order_discount_price');
							} elseif ((int) Tools::getValue('refund_total_voucher_off') == 2) {
								$total = (float) Tools::getValue('refund_total_voucher_choose');
							}
 
							$cartrule->reduction_amount = $total;
							$cartrule->reduction_tax = true;
							$cartrule->minimum_amount_currency = $order->id_currency;
							$cartrule->reduction_currency = $order->id_currency;
 
							if (!$cartrule->add()) {
								$this->errors[] = $this->trans('You cannot generate a voucher.', array(), 'Admin.Orderscustomers.Notification');
							} else {
								// Update the voucher code and name
								foreach ($language_ids as $id_lang) {
									$cartrule->name[$id_lang] = 'V' . (int) ($cartrule->id) . 'C' . (int) ($order->id_customer) . 'O' . $order->id;
								}
								$cartrule->code = 'V' . (int) ($cartrule->id) . 'C' . (int) ($order->id_customer) . 'O' . $order->id;
								if (!$cartrule->update()) {
									$this->errors[] = $this->trans('You cannot generate a voucher.', array(), 'Admin.Orderscustomers.Notification');
								} else {
									$currency = $this->context->currency;
									$params['{voucher_amount}'] = Tools::displayPrice($cartrule->reduction_amount, $currency, false);
									$params['{voucher_num}'] = $cartrule->code;
									$orderLanguage = new Language((int) $order->id_lang);
									@Mail::Send(
										(int) $order->id_lang,
										'voucher',
										$this->trans(
											'New voucher for your order #%s',
											array($order->reference),
											'Emails.Subject',
											$orderLanguage->locale
										),
										$params,
										$customer->email,
										$customer->firstname . ' ' . $customer->lastname,
										null,
										null,
										null,
										null,
										_PS_MAIL_DIR_,
										true,
										(int) $order->id_shop
									);
								}
							}
						}
					} else {
						$this->errors[] = $this->trans('No product or quantity has been selected.', array(), 'Admin.Orderscustomers.Notification');
					}
 
					// Redirect if no errors
					if (!count($this->errors)) {
						Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=31&token=' . $this->token);
					}
				}
			} else {
				$this->errors[] = $this->trans('You do not have permission to delete this.', array(), 'Admin.Notifications.Error');
			}
		} elseif (Tools::isSubmit('messageReaded')) {
			Message::markAsReaded(Tools::getValue('messageReaded'), $this->context->employee->id);
		} elseif (Tools::isSubmit('submitAddPayment') && isset($order)) {
			if ($this->access('edit')) {
				$amount = str_replace(',', '.', Tools::getValue('payment_amount'));
				$currency = new Currency(Tools::getValue('payment_currency'));
				$order_has_invoice = $order->hasInvoice();
				if ($order_has_invoice) {
					$order_invoice = new OrderInvoice(Tools::getValue('payment_invoice'));
				} else {
					$order_invoice = null;
				}
 
				if (!Validate::isLoadedObject($order)) {
					$this->errors[] = $this->trans('The order cannot be found', array(), 'Admin.Orderscustomers.Notification');
				} elseif (!Validate::isNegativePrice($amount) || !(float) $amount) {
					$this->errors[] = $this->trans('The amount is invalid.', array(), 'Admin.Orderscustomers.Notification');
				} elseif (!Validate::isGenericName(Tools::getValue('payment_method'))) {
					$this->errors[] = $this->trans('The selected payment method is invalid.', array(), 'Admin.Orderscustomers.Notification');
				} elseif (!Validate::isString(Tools::getValue('payment_transaction_id'))) {
					$this->errors[] = $this->trans('The transaction ID is invalid.', array(), 'Admin.Orderscustomers.Notification');
				} elseif (!Validate::isLoadedObject($currency)) {
					$this->errors[] = $this->trans('The selected currency is invalid.', array(), 'Admin.Orderscustomers.Notification');
				} elseif ($order_has_invoice && !Validate::isLoadedObject($order_invoice)) {
					$this->errors[] = $this->trans('The invoice is invalid.', array(), 'Admin.Orderscustomers.Notification');
				} elseif (!Validate::isDate(Tools::getValue('payment_date'))) {
					$this->errors[] = $this->trans('The date is invalid', array(), 'Admin.Orderscustomers.Notification');
				} else {
					if (!$order->addOrderPayment($amount, Tools::getValue('payment_method'), Tools::getValue('payment_transaction_id'), $currency, Tools::getValue('payment_date'), $order_invoice)) {
						$this->errors[] = $this->trans('An error occurred during payment.', array(), 'Admin.Orderscustomers.Notification');
					} else {
						Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=4&token=' . $this->token);
					}
				}
			} else {
				$this->errors[] = $this->trans('You do not have permission to edit this.', array(), 'Admin.Notifications.Error');
			}
		} elseif (Tools::isSubmit('submitEditNote')) {
			$note = Tools::getValue('note');
			$order_invoice = new OrderInvoice((int) Tools::getValue('id_order_invoice'));
			if (Validate::isLoadedObject($order_invoice) && Validate::isCleanHtml($note)) {
				if ($this->access('edit')) {
					$order_invoice->note = $note;
					if ($order_invoice->save()) {
						Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order_invoice->id_order . '&vieworder&conf=4&token=' . $this->token);
					} else {
						$this->errors[] = $this->trans('The invoice note was not saved.', array(), 'Admin.Orderscustomers.Notification');
					}
				} else {
					$this->errors[] = $this->trans('You do not have permission to edit this.', array(), 'Admin.Notifications.Error');
				}
			} else {
				$this->errors[] = $this->trans('Failed to upload the invoice and edit its note.', array(), 'Admin.Orderscustomers.Notification');
			}
		} elseif (Tools::isSubmit('submitAddOrder') && ($id_cart = Tools::getValue('id_cart')) &&
			($module_name = Tools::getValue('payment_module_name')) &&
			($id_order_state = Tools::getValue('id_order_state')) && Validate::isModuleName($module_name)) {
			if ($this->access('edit')) {
				if (!Configuration::get('PS_CATALOG_MODE')) {
					$payment_module = Module::getInstanceByName($module_name);
				} else {
					$payment_module = new BoOrder();
				}
 
				$cart = new Cart((int) $id_cart);
				Context::getContext()->currency = new Currency((int) $cart->id_currency);
				Context::getContext()->customer = new Customer((int) $cart->id_customer);
 
				$bad_delivery = false;
				if (($bad_delivery = (bool) !Address::isCountryActiveById((int) $cart->id_address_delivery))
					|| !Address::isCountryActiveById((int) $cart->id_address_invoice)) {
					if ($bad_delivery) {
						$this->errors[] = $this->trans('This delivery address country is not active.', array(), 'Admin.Orderscustomers.Notification');
					} else {
						$this->errors[] = $this->trans('This invoice address country is not active.', array(), 'Admin.Orderscustomers.Notification');
					}
				} else {
					$employee = new Employee((int) Context::getContext()->cookie->id_employee);
					$payment_module->validateOrder(
						(int) $cart->id,
						(int) $id_order_state,
						$cart->getOrderTotal(true, Cart::BOTH),
						$payment_module->displayName,
						$this->trans('Manual order -- Employee:', array(), 'Admin.Orderscustomers.Feature') . ' ' .
						substr($employee->firstname, 0, 1) . '. ' . $employee->lastname,
						array(),
						null,
						false,
						$cart->secure_key
					);
					if ($payment_module->currentOrder) {
						Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $payment_module->currentOrder . '&vieworder' . '&token=' . $this->token);
					}
				}
			} else {
				$this->errors[] = $this->trans('You do not have permission to add this.', array(), 'Admin.Notifications.Error');
			}
		} elseif ((Tools::isSubmit('submitAddressShipping') || Tools::isSubmit('submitAddressInvoice')) && isset($order)) {
			if ($this->access('edit')) {
				$address = new Address(Tools::getValue('id_address'));
				$cart = Cart::getCartByOrderId($order->id);
				if (Validate::isLoadedObject($address)) {
					// Update the address on order and cart
					if (Tools::isSubmit('submitAddressShipping')) {
						$order->id_address_delivery = $address->id;
						$cart->id_address_delivery = $address->id;
					} elseif (Tools::isSubmit('submitAddressInvoice')) {
						$order->id_address_invoice = $address->id;
						$cart->id_address_invoice = $address->id;
					}
					$order->update();
					$order->refreshShippingCost();
					$cart->update();
 
					Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=4&token=' . $this->token);
				} else {
					$this->errors[] = $this->trans('This address can\'t be loaded', array(), 'Admin.Orderscustomers.Notification');
				}
			} else {
				$this->errors[] = $this->trans('You do not have permission to edit this.', array(), 'Admin.Notifications.Error');
			}
		} elseif (Tools::isSubmit('submitChangeCurrency') && isset($order)) {
			if ($this->access('edit')) {
				if (Tools::getValue('new_currency') != $order->id_currency && !$order->valid) {
					$old_currency = new Currency($order->id_currency);
					$currency = new Currency(Tools::getValue('new_currency'));
					if (!Validate::isLoadedObject($currency)) {
						throw new PrestaShopException('Can\'t load Currency object');
					}
 
					// Update order detail amount
					foreach ($order->getOrderDetailList() as $row) {
						$order_detail = new OrderDetail($row['id_order_detail']);
						$fields = array(
							'ecotax',
							'product_price',
							'reduction_amount',
							'total_shipping_price_tax_excl',
							'total_shipping_price_tax_incl',
							'total_price_tax_incl',
							'total_price_tax_excl',
							'product_quantity_discount',
							'purchase_supplier_price',
							'reduction_amount',
							'reduction_amount_tax_incl',
							'reduction_amount_tax_excl',
							'unit_price_tax_incl',
							'unit_price_tax_excl',
							'original_product_price',
						);
						foreach ($fields as $field) {
							$order_detail->{$field} = Tools::convertPriceFull($order_detail->{$field}, $old_currency, $currency);
						}
 
						$order_detail->update();
						$order_detail->updateTaxAmount($order);
					}
 
					$id_order_carrier = (int) $order->getIdOrderCarrier();
					if ($id_order_carrier) {
						$order_carrier = $order_carrier = new OrderCarrier((int) $order->getIdOrderCarrier());
						$order_carrier->shipping_cost_tax_excl = (float) Tools::convertPriceFull($order_carrier->shipping_cost_tax_excl, $old_currency, $currency);
						$order_carrier->shipping_cost_tax_incl = (float) Tools::convertPriceFull($order_carrier->shipping_cost_tax_incl, $old_currency, $currency);
						$order_carrier->update();
					}
 
					// Update order && order_invoice amount
					$fields = array(
						'total_discounts',
						'total_discounts_tax_incl',
						'total_discounts_tax_excl',
						'total_discount_tax_excl',
						'total_discount_tax_incl',
						'total_paid',
						'total_paid_tax_incl',
						'total_paid_tax_excl',
						'total_paid_real',
						'total_products',
						'total_products_wt',
						'total_shipping',
						'total_shipping_tax_incl',
						'total_shipping_tax_excl',
						'total_wrapping',
						'total_wrapping_tax_incl',
						'total_wrapping_tax_excl',
					);
 
					$invoices = $order->getInvoicesCollection();
					if ($invoices) {
						foreach ($invoices as $invoice) {
							foreach ($fields as $field) {
								if (isset($invoice->$field)) {
									$invoice->{$field} = Tools::convertPriceFull($invoice->{$field}, $old_currency, $currency);
								}
							}
							$invoice->save();
						}
					}
 
					foreach ($fields as $field) {
						if (isset($order->$field)) {
							$order->{$field} = Tools::convertPriceFull($order->{$field}, $old_currency, $currency);
						}
					}
 
					// Update currency in order
					$order->id_currency = $currency->id;
					// Update exchange rate
					$order->conversion_rate = (float) $currency->conversion_rate;
					$order->update();
				} else {
					$this->errors[] = $this->trans('You cannot change the currency.', array(), 'Admin.Orderscustomers.Notification');
				}
			} else {
				$this->errors[] = $this->trans('You do not have permission to edit this.', array(), 'Admin.Notifications.Error');
			}
		} elseif (Tools::isSubmit('submitGenerateInvoice') && isset($order)) {
			if (!Configuration::get('PS_INVOICE', null, null, $order->id_shop)) {
				$this->errors[] = $this->trans('Invoice management has been disabled.', array(), 'Admin.Orderscustomers.Notification');
			} elseif ($order->hasInvoice()) {
				$this->errors[] = $this->trans('This order already has an invoice.', array(), 'Admin.Orderscustomers.Notification');
			} else {
				$order->setInvoice(true);
				Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=4&token=' . $this->token);
			}
		} elseif (Tools::isSubmit('submitDeleteVoucher') && isset($order)) {
			if ($this->access('edit')) {
				$order_cart_rule = new OrderCartRule(Tools::getValue('id_order_cart_rule'));
				if (Validate::isLoadedObject($order_cart_rule) && $order_cart_rule->id_order == $order->id) {
					if ($order_cart_rule->id_order_invoice) {
						$order_invoice = new OrderInvoice($order_cart_rule->id_order_invoice);
						if (!Validate::isLoadedObject($order_invoice)) {
							throw new PrestaShopException('Can\'t load Order Invoice object');
						}
 
						// Update amounts of Order Invoice
						$order_invoice->total_discount_tax_excl -= $order_cart_rule->value_tax_excl;
						$order_invoice->total_discount_tax_incl -= $order_cart_rule->value;
 
						$order_invoice->total_paid_tax_excl += $order_cart_rule->value_tax_excl;
						$order_invoice->total_paid_tax_incl += $order_cart_rule->value;
 
						// Update Order Invoice
						$order_invoice->update();
					}
 
					// Update amounts of order
					$order->total_discounts -= $order_cart_rule->value;
					$order->total_discounts_tax_incl -= $order_cart_rule->value;
					$order->total_discounts_tax_excl -= $order_cart_rule->value_tax_excl;
 
					$order->total_paid += $order_cart_rule->value;
					$order->total_paid_tax_incl += $order_cart_rule->value;
					$order->total_paid_tax_excl += $order_cart_rule->value_tax_excl;
 
					// Delete Order Cart Rule and update Order
					$order_cart_rule->delete();
					$order->update();
					Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=4&token=' . $this->token);
				} else {
					$this->errors[] = $this->trans('You cannot edit this cart rule.', array(), 'Admin.Orderscustomers.Notification');
				}
			} else {
				$this->errors[] = $this->trans('You do not have permission to edit this.', array(), 'Admin.Notifications.Error');
			}
		} elseif (Tools::isSubmit('submitNewVoucher') && isset($order)) {
			if ($this->access('edit')) {
				if (!Tools::getValue('discount_name')) {
					$this->errors[] = $this->trans('You must specify a name in order to create a new discount.', array(), 'Admin.Orderscustomers.Notification');
				} else {
					if ($order->hasInvoice()) {
						// If the discount is for only one invoice
						if (!Tools::isSubmit('discount_all_invoices')) {
							$order_invoice = new OrderInvoice(Tools::getValue('discount_invoice'));
							if (!Validate::isLoadedObject($order_invoice)) {
								throw new PrestaShopException('Can\'t load Order Invoice object');
							}
						}
					}
 
					$cart_rules = array();
					$discount_value = (float) str_replace(',', '.', Tools::getValue('discount_value'));
					switch (Tools::getValue('discount_type')) {
						// Percent type
						case 1:
							if ($discount_value < 100) {
								if (isset($order_invoice)) {
									$cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($order_invoice->total_paid_tax_incl * $discount_value / 100, 2);
									$cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($order_invoice->total_paid_tax_excl * $discount_value / 100, 2);
 
									// Update OrderInvoice
									$this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']);
								} elseif ($order->hasInvoice()) {
									$order_invoices_collection = $order->getInvoicesCollection();
									foreach ($order_invoices_collection as $order_invoice) {
										/* @var OrderInvoice $order_invoice */
										$cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($order_invoice->total_paid_tax_incl * $discount_value / 100, 2);
										$cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($order_invoice->total_paid_tax_excl * $discount_value / 100, 2);
 
										// Update OrderInvoice
										$this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']);
									}
								} else {
									$cart_rules[0]['value_tax_incl'] = Tools::ps_round($order->total_paid_tax_incl * $discount_value / 100, 2);
									$cart_rules[0]['value_tax_excl'] = Tools::ps_round($order->total_paid_tax_excl * $discount_value / 100, 2);
								}
							} else {
								$this->errors[] = $this->trans('The discount value is invalid.', array(), 'Admin.Orderscustomers.Notification');
							}
 
							break;
						// Amount type
						case 2:
							if (isset($order_invoice)) {
								if ($discount_value > $order_invoice->total_paid_tax_incl) {
									$this->errors[] = $this->trans('The discount value is greater than the order invoice total.', array(), 'Admin.Orderscustomers.Notification');
								} else {
									$cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($discount_value, 2);
									$cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($discount_value / (1 + ($order->getTaxesAverageUsed() / 100)), 2);
 
									// Update OrderInvoice
									$this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']);
								}
							} elseif ($order->hasInvoice()) {
								$order_invoices_collection = $order->getInvoicesCollection();
								foreach ($order_invoices_collection as $order_invoice) {
									/** @var OrderInvoice $order_invoice */
									if ($discount_value > $order_invoice->total_paid_tax_incl) {
										$this->errors[] = $this->trans('The discount value is greater than the order invoice total.', array(), 'Admin.Orderscustomers.Notification') . $order_invoice->getInvoiceNumberFormatted(Context::getContext()->language->id, (int) $order->id_shop) . ')';
									} else {
										$cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($discount_value, 2);
										$cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($discount_value / (1 + ($order->getTaxesAverageUsed() / 100)), 2);
 
										// Update OrderInvoice
										$this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']);
									}
								}
							} else {
								if ($discount_value > $order->total_paid_tax_incl) {
									$this->errors[] = $this->trans('The discount value is greater than the order total.', array(), 'Admin.Orderscustomers.Notification');
								} else {
									$cart_rules[0]['value_tax_incl'] = Tools::ps_round($discount_value, 2);
									$cart_rules[0]['value_tax_excl'] = Tools::ps_round($discount_value / (1 + ($order->getTaxesAverageUsed() / 100)), 2);
								}
							}
 
							break;
						// Free shipping type
						case 3:
							if (isset($order_invoice)) {
								if ($order_invoice->total_shipping_tax_incl > 0) {
									$cart_rules[$order_invoice->id]['value_tax_incl'] = $order_invoice->total_shipping_tax_incl;
									$cart_rules[$order_invoice->id]['value_tax_excl'] = $order_invoice->total_shipping_tax_excl;
 
									// Update OrderInvoice
									$this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']);
								}
							} elseif ($order->hasInvoice()) {
								$order_invoices_collection = $order->getInvoicesCollection();
								foreach ($order_invoices_collection as $order_invoice) {
									/** @var OrderInvoice $order_invoice */
									if ($order_invoice->total_shipping_tax_incl <= 0) {
										continue;
									}
									$cart_rules[$order_invoice->id]['value_tax_incl'] = $order_invoice->total_shipping_tax_incl;
									$cart_rules[$order_invoice->id]['value_tax_excl'] = $order_invoice->total_shipping_tax_excl;
 
									// Update OrderInvoice
									$this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']);
								}
							} else {
								$cart_rules[0]['value_tax_incl'] = $order->total_shipping_tax_incl;
								$cart_rules[0]['value_tax_excl'] = $order->total_shipping_tax_excl;
							}
 
							break;
						default:
							$this->errors[] = $this->trans('The discount type is invalid.', array(), 'Admin.Orderscustomers.Notification');
					}
 
					$res = true;
					foreach ($cart_rules as &$cart_rule) {
						$cartRuleObj = new CartRule();
						$cartRuleObj->date_from = date('Y-m-d H:i:s', strtotime('-1 hour', strtotime($order->date_add)));
						$cartRuleObj->date_to = date('Y-m-d H:i:s', strtotime('+1 hour'));
						$cartRuleObj->name[Configuration::get('PS_LANG_DEFAULT')] = Tools::getValue('discount_name');
						$cartRuleObj->quantity = 0;
						$cartRuleObj->quantity_per_user = 1;
						if (Tools::getValue('discount_type') == 1) {
							$cartRuleObj->reduction_percent = $discount_value;
						} elseif (Tools::getValue('discount_type') == 2) {
							$cartRuleObj->reduction_amount = $cart_rule['value_tax_excl'];
						} elseif (Tools::getValue('discount_type') == 3) {
							$cartRuleObj->free_shipping = 1;
						}
						$cartRuleObj->active = 0;
						if ($res = $cartRuleObj->add()) {
							$cart_rule['id'] = $cartRuleObj->id;
						} else {
							break;
						}
					}
 
					if ($res) {
						foreach ($cart_rules as $id_order_invoice => $cart_rule) {
							// Create OrderCartRule
							$order_cart_rule = new OrderCartRule();
							$order_cart_rule->id_order = $order->id;
							$order_cart_rule->id_cart_rule = $cart_rule['id'];
							$order_cart_rule->id_order_invoice = $id_order_invoice;
							$order_cart_rule->name = Tools::getValue('discount_name');
							$order_cart_rule->value = $cart_rule['value_tax_incl'];
							$order_cart_rule->value_tax_excl = $cart_rule['value_tax_excl'];
							$res &= $order_cart_rule->add();
 
							$order->total_discounts += $order_cart_rule->value;
							$order->total_discounts_tax_incl += $order_cart_rule->value;
							$order->total_discounts_tax_excl += $order_cart_rule->value_tax_excl;
							$order->total_paid -= $order_cart_rule->value;
							$order->total_paid_tax_incl -= $order_cart_rule->value;
							$order->total_paid_tax_excl -= $order_cart_rule->value_tax_excl;
						}
 
						// Update Order
						$res &= $order->update();
					}
 
					if ($res) {
						Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=4&token=' . $this->token);
					} else {
						$this->errors[] = $this->trans('An error occurred during the OrderCartRule creation', array(), 'Admin.Orderscustomers.Notification');
					}
				}
			} else {
				$this->errors[] = $this->trans('You do not have permission to edit this.', array(), 'Admin.Notifications.Error');
			}
		} elseif (Tools::isSubmit('sendStateEmail') && Tools::getValue('sendStateEmail') > 0 && Tools::getValue('id_order') > 0) {
			if ($this->access('edit')) {
				$order_state = new OrderState((int) Tools::getValue('sendStateEmail'));
 
				if (!Validate::isLoadedObject($order_state)) {
					$this->errors[] = $this->trans('An error occurred while loading order status.', array(), 'Admin.Orderscustomers.Notification');
				} else {
					$history = new OrderHistory((int) Tools::getValue('id_order_history'));
 
					$carrier = new Carrier($order->id_carrier, $order->id_lang);
					$templateVars = array();
					if ($order_state->id == Configuration::get('PS_OS_SHIPPING') && $order->shipping_number) {
						$templateVars = array('{followup}' => str_replace('@', $order->shipping_number, $carrier->url));
					}
 
					if ($history->sendEmail($order, $templateVars)) {
						Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=10&token=' . $this->token);
					} else {
						$this->errors[] = $this->trans('An error occurred while sending the e-mail to the customer.', array(), 'Admin.Orderscustomers.Notification');
					}
				}
			} else {
				$this->errors[] = $this->trans('You do not have permission to edit this.', array(), 'Admin.Notifications.Error');
			}
		}
 
		parent::postProcess();
	}

Guardamos los ficheros y los subimos al servidor. Con esto ya deberíamos de tener la funcionalidad lista para poder reenviar correos de confirmación de pedidos en nuestro Prestashop.

Esperamos que os haya servido de ayuda, y en caso de que hayais tenido problemas para implementar esta funcionalidad, hacednoslo saber en los comentarios y os interé ayudar! =)

Consultor SEO | Web | + posts

Programador reconvertido a consultor SEO. Me gusta automatizar cosas, de hecho, este articulo ha sido generado a partir de otras webs de forma automática.