first commit
This commit is contained in:
2793
classes/order/Order.php
Normal file
2793
classes/order/Order.php
Normal file
File diff suppressed because it is too large
Load Diff
193
classes/order/OrderCarrier.php
Normal file
193
classes/order/OrderCarrier.php
Normal file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class OrderCarrierCore extends ObjectModel
|
||||
{
|
||||
/** @var int */
|
||||
public $id_order_carrier;
|
||||
|
||||
/** @var int */
|
||||
public $id_order;
|
||||
|
||||
/** @var int */
|
||||
public $id_carrier;
|
||||
|
||||
/** @var int */
|
||||
public $id_order_invoice;
|
||||
|
||||
/** @var float */
|
||||
public $weight;
|
||||
|
||||
/** @var float */
|
||||
public $shipping_cost_tax_excl;
|
||||
|
||||
/** @var float */
|
||||
public $shipping_cost_tax_incl;
|
||||
|
||||
/** @var string */
|
||||
public $tracking_number;
|
||||
|
||||
/** @var string Object creation date */
|
||||
public $date_add;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'order_carrier',
|
||||
'primary' => 'id_order_carrier',
|
||||
'fields' => [
|
||||
'id_order' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'id_carrier' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'id_order_invoice' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
||||
'weight' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'shipping_cost_tax_excl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'shipping_cost_tax_incl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'tracking_number' => ['type' => self::TYPE_STRING, 'validate' => 'isTrackingNumber'],
|
||||
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
],
|
||||
];
|
||||
|
||||
protected $webserviceParameters = [
|
||||
'objectMethods' => ['update' => 'updateWs'],
|
||||
'fields' => [
|
||||
'id_order' => ['xlink_resource' => 'orders'],
|
||||
'id_carrier' => ['xlink_resource' => 'carriers'],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* @param Order $order Required
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sendInTransitEmail($order)
|
||||
{
|
||||
$orderLanguageId = (int) $order->getAssociatedLanguage()->getId();
|
||||
$customer = new Customer((int) $order->id_customer);
|
||||
$carrier = new Carrier((int) $order->id_carrier, $orderLanguageId);
|
||||
$address = new Address((int) $order->id_address_delivery);
|
||||
|
||||
if (!Validate::isLoadedObject($customer)) {
|
||||
throw new PrestaShopException('Can\'t load Customer object');
|
||||
}
|
||||
if (!Validate::isLoadedObject($carrier)) {
|
||||
throw new PrestaShopException('Can\'t load Carrier object');
|
||||
}
|
||||
if (!Validate::isLoadedObject($address)) {
|
||||
throw new PrestaShopException('Can\'t load Address object');
|
||||
}
|
||||
|
||||
$products = $order->getCartProducts();
|
||||
$link = Context::getContext()->link;
|
||||
|
||||
$metadata = '';
|
||||
foreach ($products as $product) {
|
||||
$prod_obj = new Product((int) $product['product_id']);
|
||||
|
||||
//try to get the first image for the purchased combination
|
||||
$img = $prod_obj->getCombinationImages($orderLanguageId);
|
||||
$link_rewrite = $prod_obj->link_rewrite[$orderLanguageId];
|
||||
$combination_img = $img[$product['product_attribute_id']][0]['id_image'] ?? null;
|
||||
if ($combination_img != null) {
|
||||
$img_url = $link->getImageLink($link_rewrite, $combination_img, 'large_default');
|
||||
} else {
|
||||
//if there is no combination image, then get the product cover instead
|
||||
$img = $prod_obj->getCover($prod_obj->id);
|
||||
$img_url = !empty($img['id_image']) ? $link->getImageLink($link_rewrite, $img['id_image']) : '';
|
||||
}
|
||||
$prod_url = $prod_obj->getLink();
|
||||
|
||||
$metadata .= "\n" . '<div itemprop="itemShipped" itemscope itemtype="https://schema.org/Product">';
|
||||
$metadata .= "\n" . ' <meta itemprop="name" content="' . htmlspecialchars($product['product_name']) . '"/>';
|
||||
$metadata .= "\n" . ' <link itemprop="image" href="' . $img_url . '"/>';
|
||||
$metadata .= "\n" . ' <link itemprop="url" href="' . $prod_url . '"/>';
|
||||
$metadata .= "\n" . '</div>';
|
||||
}
|
||||
|
||||
$orderLanguage = new Language((int) $orderLanguageId);
|
||||
$templateVars = [
|
||||
'{followup}' => str_replace('@', $this->tracking_number, $carrier->url),
|
||||
'{firstname}' => $customer->firstname,
|
||||
'{lastname}' => $customer->lastname,
|
||||
'{id_order}' => $order->id,
|
||||
'{shipping_number}' => $this->tracking_number,
|
||||
'{order_name}' => $order->getUniqReference(),
|
||||
'{carrier}' => $carrier->name,
|
||||
'{address1}' => $address->address1,
|
||||
'{country}' => $address->country,
|
||||
'{postcode}' => $address->postcode,
|
||||
'{city}' => $address->city,
|
||||
'{meta_products}' => $metadata,
|
||||
];
|
||||
|
||||
if (@Mail::Send(
|
||||
$orderLanguageId,
|
||||
'in_transit',
|
||||
$this->trans(
|
||||
'Package in transit',
|
||||
[],
|
||||
'Emails.Subject',
|
||||
$orderLanguage->locale
|
||||
),
|
||||
$templateVars,
|
||||
$customer->email,
|
||||
$customer->firstname . ' ' . $customer->lastname,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
_PS_MAIL_DIR_,
|
||||
true,
|
||||
(int) $order->id_shop
|
||||
)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function updateWs()
|
||||
{
|
||||
if (!parent::update()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sendemail = (bool) Tools::getValue('sendemail', false);
|
||||
|
||||
if ($sendemail) {
|
||||
$order = new Order((int) $this->id_order);
|
||||
if (!Validate::isLoadedObject($order)) {
|
||||
throw new PrestaShopException('Can\'t load Order object');
|
||||
}
|
||||
|
||||
if (!$this->sendInTransitEmail($order)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
78
classes/order/OrderCartRule.php
Normal file
78
classes/order/OrderCartRule.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class OrderCartRuleCore extends ObjectModel
|
||||
{
|
||||
/** @var int */
|
||||
public $id_order_cart_rule;
|
||||
|
||||
/** @var int */
|
||||
public $id_order;
|
||||
|
||||
/** @var int */
|
||||
public $id_cart_rule;
|
||||
|
||||
/** @var int */
|
||||
public $id_order_invoice;
|
||||
|
||||
/** @var string */
|
||||
public $name;
|
||||
|
||||
/** @var float value (tax incl.) of voucher */
|
||||
public $value;
|
||||
|
||||
/** @var float value (tax excl.) of voucher */
|
||||
public $value_tax_excl;
|
||||
|
||||
/** @var bool value : voucher gives free shipping or not */
|
||||
public $free_shipping;
|
||||
|
||||
/** @var bool value : deleted from order */
|
||||
public $deleted = 0;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'order_cart_rule',
|
||||
'primary' => 'id_order_cart_rule',
|
||||
'fields' => [
|
||||
'id_order' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'id_cart_rule' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'id_order_invoice' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
||||
'name' => ['type' => self::TYPE_HTML, 'required' => true],
|
||||
'value' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true],
|
||||
'value_tax_excl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true],
|
||||
'free_shipping' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'deleted' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
],
|
||||
];
|
||||
|
||||
protected $webserviceParameters = [
|
||||
'fields' => [
|
||||
'id_order' => ['xlink_resource' => 'orders'],
|
||||
],
|
||||
];
|
||||
}
|
||||
954
classes/order/OrderDetail.php
Normal file
954
classes/order/OrderDetail.php
Normal file
@@ -0,0 +1,954 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class OrderDetailCore extends ObjectModel
|
||||
{
|
||||
/** @var int */
|
||||
public $id_order_detail;
|
||||
|
||||
/** @var int */
|
||||
public $id_order;
|
||||
|
||||
/** @var int */
|
||||
public $id_order_invoice;
|
||||
|
||||
/** @var int */
|
||||
public $product_id;
|
||||
|
||||
/** @var int */
|
||||
public $id_shop;
|
||||
|
||||
/** @var int */
|
||||
public $product_attribute_id;
|
||||
|
||||
/** @var int */
|
||||
public $id_customization;
|
||||
|
||||
/** @var string */
|
||||
public $product_name;
|
||||
|
||||
/** @var int */
|
||||
public $product_quantity;
|
||||
|
||||
/** @var int */
|
||||
public $product_quantity_in_stock;
|
||||
|
||||
/** @var int */
|
||||
public $product_quantity_return;
|
||||
|
||||
/** @var int */
|
||||
public $product_quantity_refunded;
|
||||
|
||||
/** @var int */
|
||||
public $product_quantity_reinjected;
|
||||
|
||||
/**
|
||||
* @deprecated since 1.5 Use unit_price_tax_excl instead
|
||||
*
|
||||
* @var float Without taxes, includes ecotax
|
||||
*/
|
||||
public $product_price;
|
||||
|
||||
/** @var float */
|
||||
public $original_product_price;
|
||||
|
||||
/** @var float With taxes, includes ecotax */
|
||||
public $unit_price_tax_incl;
|
||||
|
||||
/** @var float Without taxes, includes ecotax */
|
||||
public $unit_price_tax_excl;
|
||||
|
||||
/** @var float With taxes, includes ecotax */
|
||||
public $total_price_tax_incl;
|
||||
|
||||
/** @var float Without taxes, includes ecotax */
|
||||
public $total_price_tax_excl;
|
||||
|
||||
/** @var float */
|
||||
public $reduction_percent;
|
||||
|
||||
/** @var float */
|
||||
public $reduction_amount;
|
||||
|
||||
/** @var float */
|
||||
public $reduction_amount_tax_excl;
|
||||
|
||||
/** @var float */
|
||||
public $reduction_amount_tax_incl;
|
||||
|
||||
/** @var float */
|
||||
public $group_reduction;
|
||||
|
||||
/** @var float */
|
||||
public $product_quantity_discount;
|
||||
|
||||
/** @var string */
|
||||
public $product_ean13;
|
||||
|
||||
/** @var string */
|
||||
public $product_isbn;
|
||||
|
||||
/** @var string */
|
||||
public $product_upc;
|
||||
|
||||
/** @var string */
|
||||
public $product_mpn;
|
||||
|
||||
/** @var string */
|
||||
public $product_reference;
|
||||
|
||||
/** @var string */
|
||||
public $product_supplier_reference;
|
||||
|
||||
/** @var float */
|
||||
public $product_weight;
|
||||
|
||||
/** @var float */
|
||||
public $ecotax;
|
||||
|
||||
/** @var float */
|
||||
public $ecotax_tax_rate;
|
||||
|
||||
/** @var int */
|
||||
public $discount_quantity_applied;
|
||||
|
||||
/** @var string */
|
||||
public $download_hash;
|
||||
|
||||
/** @var int */
|
||||
public $download_nb;
|
||||
|
||||
/** @var datetime */
|
||||
public $download_deadline;
|
||||
|
||||
/**
|
||||
* @var string @deprecated Order Detail Tax is saved in order_detail_tax table now
|
||||
*/
|
||||
public $tax_name;
|
||||
|
||||
/**
|
||||
* @var float @deprecated Order Detail Tax is saved in order_detail_tax table now
|
||||
*/
|
||||
public $tax_rate;
|
||||
|
||||
/** @var float */
|
||||
public $tax_computation_method;
|
||||
|
||||
/** @var int Id tax rules group */
|
||||
public $id_tax_rules_group;
|
||||
|
||||
/** @var int Id warehouse */
|
||||
public $id_warehouse;
|
||||
|
||||
/** @var float additional shipping price tax excl */
|
||||
public $total_shipping_price_tax_excl;
|
||||
|
||||
/** @var float additional shipping price tax incl */
|
||||
public $total_shipping_price_tax_incl;
|
||||
|
||||
/** @var float */
|
||||
public $purchase_supplier_price;
|
||||
|
||||
/** @var float */
|
||||
public $original_wholesale_price;
|
||||
|
||||
/** @var float */
|
||||
public $total_refunded_tax_excl;
|
||||
|
||||
/** @var float */
|
||||
public $total_refunded_tax_incl;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'order_detail',
|
||||
'primary' => 'id_order_detail',
|
||||
'fields' => [
|
||||
'id_order' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'id_order_invoice' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
||||
'id_warehouse' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'id_shop' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'product_id' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
||||
'product_attribute_id' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
||||
'id_customization' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
||||
'product_name' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true],
|
||||
'product_quantity' => ['type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true],
|
||||
'product_quantity_in_stock' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||
'product_quantity_return' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'],
|
||||
'product_quantity_refunded' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'],
|
||||
'product_quantity_reinjected' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'],
|
||||
'product_price' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true],
|
||||
'reduction_percent' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'reduction_amount' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'reduction_amount_tax_incl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'reduction_amount_tax_excl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'group_reduction' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'product_quantity_discount' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'product_ean13' => ['type' => self::TYPE_STRING, 'validate' => 'isEan13'],
|
||||
'product_isbn' => ['type' => self::TYPE_STRING, 'validate' => 'isIsbn'],
|
||||
'product_upc' => ['type' => self::TYPE_STRING, 'validate' => 'isUpc'],
|
||||
'product_mpn' => ['type' => self::TYPE_STRING, 'validate' => 'isMpn'],
|
||||
'product_reference' => ['type' => self::TYPE_STRING, 'validate' => 'isReference'],
|
||||
'product_supplier_reference' => ['type' => self::TYPE_STRING, 'validate' => 'isReference'],
|
||||
'product_weight' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'tax_name' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName'],
|
||||
'tax_rate' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'tax_computation_method' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
||||
'id_tax_rules_group' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||
'ecotax' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'ecotax_tax_rate' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'discount_quantity_applied' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||
'download_hash' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName'],
|
||||
'download_nb' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||
'download_deadline' => ['type' => self::TYPE_DATE, 'validate' => 'isDateFormat'],
|
||||
'unit_price_tax_incl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'unit_price_tax_excl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'total_price_tax_incl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'total_price_tax_excl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'total_shipping_price_tax_excl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'total_shipping_price_tax_incl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'purchase_supplier_price' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'original_product_price' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'original_wholesale_price' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'total_refunded_tax_excl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
'total_refunded_tax_incl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice'],
|
||||
],
|
||||
];
|
||||
|
||||
protected $webserviceParameters = [
|
||||
'fields' => [
|
||||
'id_order' => ['xlink_resource' => 'orders'],
|
||||
'product_id' => ['xlink_resource' => 'products'],
|
||||
'product_attribute_id' => ['xlink_resource' => 'combinations'],
|
||||
'product_quantity_reinjected' => [],
|
||||
'group_reduction' => [],
|
||||
'discount_quantity_applied' => [],
|
||||
'download_hash' => [],
|
||||
'download_deadline' => [],
|
||||
],
|
||||
'hidden_fields' => ['tax_rate', 'tax_name'],
|
||||
'associations' => [
|
||||
'taxes' => ['resource' => 'tax', 'getter' => 'getWsTaxes', 'setter' => false,
|
||||
'fields' => ['id' => []],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
/** @var bool */
|
||||
protected $outOfStock = false;
|
||||
|
||||
/** @var TaxCalculator object */
|
||||
protected $tax_calculator = null;
|
||||
|
||||
/** @var Address object */
|
||||
protected $vat_address = null;
|
||||
|
||||
/** @var Address object */
|
||||
protected $specificPrice = null;
|
||||
|
||||
/** @var Customer object */
|
||||
protected $customer = null;
|
||||
|
||||
/** @var Context object */
|
||||
protected $context = null;
|
||||
|
||||
public function __construct($id = null, $id_lang = null, $context = null)
|
||||
{
|
||||
$this->context = $context;
|
||||
$id_shop = null;
|
||||
if ($this->context != null && isset($this->context->shop)) {
|
||||
$id_shop = $this->context->shop->id;
|
||||
}
|
||||
parent::__construct($id, $id_lang, $id_shop);
|
||||
|
||||
if ($context == null) {
|
||||
$context = Context::getContext();
|
||||
}
|
||||
$this->context = $context->cloneContext();
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
if (!$res = parent::delete()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Db::getInstance()->delete('order_detail_tax', 'id_order_detail=' . (int) $this->id);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
protected function setContext($id_shop)
|
||||
{
|
||||
if ($this->context->shop->id != $id_shop) {
|
||||
$this->context->shop = new Shop((int) $id_shop);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getDownloadFromHash($hash)
|
||||
{
|
||||
if ($hash == '') {
|
||||
return false;
|
||||
}
|
||||
$sql = 'SELECT *
|
||||
FROM `' . _DB_PREFIX_ . 'order_detail` od
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'product_download` pd ON (od.`product_id`=pd.`id_product`)
|
||||
WHERE od.`download_hash` = \'' . pSQL((string) $hash) . '\'
|
||||
AND pd.`active` = 1';
|
||||
|
||||
return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($sql);
|
||||
}
|
||||
|
||||
public static function incrementDownload($id_order_detail, $increment = 1)
|
||||
{
|
||||
$sql = 'UPDATE `' . _DB_PREFIX_ . 'order_detail`
|
||||
SET `download_nb` = `download_nb` + ' . (int) $increment . '
|
||||
WHERE `id_order_detail`= ' . (int) $id_order_detail . '
|
||||
LIMIT 1';
|
||||
|
||||
return Db::getInstance()->execute($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the tax calculator associated to this order detail.
|
||||
*
|
||||
* @since 1.5.0.1
|
||||
*
|
||||
* @return TaxCalculator
|
||||
*/
|
||||
public function getTaxCalculator()
|
||||
{
|
||||
return OrderDetail::getTaxCalculatorStatic($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the tax calculator associated to this order_detail.
|
||||
*
|
||||
* @since 1.5.0.1
|
||||
*
|
||||
* @param int $id_order_detail
|
||||
*
|
||||
* @return TaxCalculator
|
||||
*/
|
||||
public static function getTaxCalculatorStatic($id_order_detail)
|
||||
{
|
||||
$sql = 'SELECT t.*, d.`tax_computation_method`
|
||||
FROM `' . _DB_PREFIX_ . 'order_detail_tax` t
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'order_detail` d ON (d.`id_order_detail` = t.`id_order_detail`)
|
||||
WHERE d.`id_order_detail` = ' . (int) $id_order_detail;
|
||||
|
||||
$computation_method = 1;
|
||||
$taxes = [];
|
||||
if ($results = Db::getInstance()->executeS($sql)) {
|
||||
foreach ($results as $result) {
|
||||
$taxes[] = new Tax((int) $result['id_tax']);
|
||||
$computation_method = $result['tax_computation_method'];
|
||||
}
|
||||
}
|
||||
|
||||
return new TaxCalculator($taxes, $computation_method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the tax calculator.
|
||||
*
|
||||
* @since 1.5.0.1
|
||||
* @deprecated Functionality moved to Order::updateOrderDetailTax
|
||||
* because we need the full order object to do a good job here.
|
||||
* Will no longer be supported after 1.6.1
|
||||
* (Note: this one is not that deprecated because Order::updateOrderDetailTax
|
||||
* performs no update unless order_detail_tax is filled. So we rely on updateTaxAmount
|
||||
* which correctly builds the TaxCalculator with up to date taxes unlike getTaxCalculatorStatic)
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function saveTaxCalculator(Order $order, $replace = false)
|
||||
{
|
||||
// Nothing to save
|
||||
if ($this->tax_calculator == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!($this->tax_calculator instanceof TaxCalculator)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$shipping_tax_amount = 0;
|
||||
|
||||
foreach ($order->getCartRules() as $cart_rule) {
|
||||
if ($cart_rule['free_shipping']) {
|
||||
$shipping_tax_amount = $order->total_shipping_tax_excl;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$ratio = ($order->total_products > 0) ? ($this->unit_price_tax_excl / $order->total_products) : 1;
|
||||
|
||||
$order_reduction_amount = ($order->total_discounts_tax_excl - $shipping_tax_amount) * $ratio;
|
||||
$discounted_price_tax_excl = $this->unit_price_tax_excl - $order_reduction_amount;
|
||||
|
||||
$values = '';
|
||||
foreach ($this->tax_calculator->getTaxesAmount($discounted_price_tax_excl) as $id_tax => $amount) {
|
||||
switch (Configuration::get('PS_ROUND_TYPE')) {
|
||||
case Order::ROUND_ITEM:
|
||||
$unit_amount = (float) Tools::ps_round($amount, Context::getContext()->getComputingPrecision());
|
||||
$total_amount = $unit_amount * $this->product_quantity;
|
||||
|
||||
break;
|
||||
case Order::ROUND_LINE:
|
||||
$unit_amount = $amount;
|
||||
$total_amount = Tools::ps_round($unit_amount * $this->product_quantity, Context::getContext()->getComputingPrecision());
|
||||
|
||||
break;
|
||||
case Order::ROUND_TOTAL:
|
||||
$unit_amount = $amount;
|
||||
$total_amount = $unit_amount * $this->product_quantity;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$values .= '(' . (int) $this->id . ',' . (int) $id_tax . ',' . (float) $unit_amount . ',' . (float) $total_amount . '),';
|
||||
}
|
||||
|
||||
if ($replace) {
|
||||
Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'order_detail_tax` WHERE id_order_detail=' . (int) $this->id);
|
||||
}
|
||||
|
||||
if (!empty($values)) {
|
||||
$values = rtrim($values, ',');
|
||||
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'order_detail_tax` (id_order_detail, id_tax, unit_amount, total_amount)
|
||||
VALUES ' . $values;
|
||||
|
||||
return Db::getInstance()->execute($sql);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function updateTaxAmount($order)
|
||||
{
|
||||
$address = new Address((int) $order->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
|
||||
$this->tax_calculator = $this->getTaxCalculatorByAddress($address);
|
||||
|
||||
return $this->saveTaxCalculator($order, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a TaxCalculator adapted for the OrderDetail's product and the specified address
|
||||
*
|
||||
* @param Address $address
|
||||
*
|
||||
* @return TaxCalculator
|
||||
*/
|
||||
public function getTaxCalculatorByAddress(Address $address): TaxCalculator
|
||||
{
|
||||
$this->setContext((int) $this->id_shop);
|
||||
$tax_manager = TaxManagerFactory::getManager($address, $this->getTaxRulesGroupId());
|
||||
|
||||
return $tax_manager->getTaxCalculator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dynamically get the taxRulesGroupId instead of relying one the one saved in database
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTaxRulesGroupId(): int
|
||||
{
|
||||
return (int) Product::getIdTaxRulesGroupByIdProduct((int) $this->product_id, $this->context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a detailed order list of an id_order.
|
||||
*
|
||||
* @param int $id_order
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getList($id_order)
|
||||
{
|
||||
return Db::getInstance()->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'order_detail` WHERE `id_order` = ' . (int) $id_order);
|
||||
}
|
||||
|
||||
public function getTaxList()
|
||||
{
|
||||
return self::getTaxListStatic($this->id);
|
||||
}
|
||||
|
||||
public static function getTaxListStatic($id_order_detail)
|
||||
{
|
||||
$sql = 'SELECT * FROM `' . _DB_PREFIX_ . 'order_detail_tax`
|
||||
WHERE `id_order_detail` = ' . (int) $id_order_detail;
|
||||
|
||||
return Db::getInstance()->executeS($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set virtual product information
|
||||
*
|
||||
* @param array $product
|
||||
*/
|
||||
protected function setVirtualProductInformation($product)
|
||||
{
|
||||
// Add some informations for virtual products
|
||||
$this->download_deadline = '0000-00-00 00:00:00';
|
||||
$this->download_hash = null;
|
||||
|
||||
if ($id_product_download = ProductDownload::getIdFromIdProduct((int) $product['id_product'])) {
|
||||
$product_download = new ProductDownload((int) $id_product_download);
|
||||
$this->download_deadline = $product_download->getDeadLine();
|
||||
$this->download_hash = $product_download->getHash();
|
||||
|
||||
unset($product_download);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the order status.
|
||||
*
|
||||
* @param array $product
|
||||
* @param int $id_order_state
|
||||
*/
|
||||
protected function checkProductStock($product, $id_order_state)
|
||||
{
|
||||
if ($id_order_state != Configuration::get('PS_OS_CANCELED') && $id_order_state != Configuration::get('PS_OS_ERROR')) {
|
||||
$update_quantity = true;
|
||||
if (!StockAvailable::dependsOnStock($product['id_product'])) {
|
||||
$update_quantity = StockAvailable::updateQuantity($product['id_product'], $product['id_product_attribute'], -(int) $product['cart_quantity'], $product['id_shop'], true);
|
||||
}
|
||||
|
||||
if ($update_quantity) {
|
||||
$product['stock_quantity'] -= $product['cart_quantity'];
|
||||
}
|
||||
|
||||
if ($product['stock_quantity'] < 0 && Configuration::get('PS_STOCK_MANAGEMENT')) {
|
||||
$this->outOfStock = true;
|
||||
}
|
||||
Product::updateDefaultAttribute($product['id_product']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply tax to the product.
|
||||
*
|
||||
* @param object $order
|
||||
* @param array $product
|
||||
*/
|
||||
protected function setProductTax(Order $order, $product)
|
||||
{
|
||||
$this->ecotax = Tools::convertPrice((float) ($product['ecotax']), (int) ($order->id_currency));
|
||||
|
||||
// Exclude VAT
|
||||
if (!Tax::excludeTaxeOption()) {
|
||||
$this->setContext((int) $product['id_shop']);
|
||||
$this->id_tax_rules_group = (int) Product::getIdTaxRulesGroupByIdProduct((int) $product['id_product'], $this->context);
|
||||
|
||||
$tax_manager = TaxManagerFactory::getManager($this->vat_address, $this->id_tax_rules_group);
|
||||
$this->tax_calculator = $tax_manager->getTaxCalculator();
|
||||
$this->tax_computation_method = (int) $this->tax_calculator->computation_method;
|
||||
$this->tax_rate = (float) $this->tax_calculator->getTotalRate();
|
||||
$this->tax_name = $this->tax_calculator->getTaxesName();
|
||||
}
|
||||
|
||||
$this->ecotax_tax_rate = 0;
|
||||
if (!empty($product['ecotax'])) {
|
||||
$this->ecotax_tax_rate = Tax::getProductEcotaxRate($order->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set specific price of the product.
|
||||
*
|
||||
* @param object $order
|
||||
*/
|
||||
protected function setSpecificPrice(Order $order, $product = null)
|
||||
{
|
||||
$this->reduction_amount = 0.00;
|
||||
$this->reduction_percent = 0.00;
|
||||
$this->reduction_amount_tax_incl = 0.00;
|
||||
$this->reduction_amount_tax_excl = 0.00;
|
||||
|
||||
if ($this->specificPrice) {
|
||||
switch ($this->specificPrice['reduction_type']) {
|
||||
case 'percentage':
|
||||
$this->reduction_percent = (float) $this->specificPrice['reduction'] * 100;
|
||||
|
||||
break;
|
||||
|
||||
case 'amount':
|
||||
$price = Tools::convertPrice($this->specificPrice['reduction'], $order->id_currency);
|
||||
$this->reduction_amount = !$this->specificPrice['id_currency'] ? (float) $price : (float) $this->specificPrice['reduction'];
|
||||
if ($product !== null) {
|
||||
$this->setContext((int) $product['id_shop']);
|
||||
}
|
||||
$id_tax_rules = (int) Product::getIdTaxRulesGroupByIdProduct((int) $this->specificPrice['id_product'], $this->context);
|
||||
$tax_manager = TaxManagerFactory::getManager($this->vat_address, $id_tax_rules);
|
||||
$this->tax_calculator = $tax_manager->getTaxCalculator();
|
||||
|
||||
if ($this->specificPrice['reduction_tax']) {
|
||||
$this->reduction_amount_tax_incl = $this->reduction_amount;
|
||||
$this->reduction_amount_tax_excl = Tools::ps_round($this->tax_calculator->removeTaxes($this->reduction_amount), Context::getContext()->getComputingPrecision());
|
||||
} else {
|
||||
$this->reduction_amount_tax_incl = Tools::ps_round($this->tax_calculator->addTaxes($this->reduction_amount), Context::getContext()->getComputingPrecision());
|
||||
$this->reduction_amount_tax_excl = $this->reduction_amount;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set detailed product price to the order detail.
|
||||
*
|
||||
* @param object $order
|
||||
* @param object $cart
|
||||
* @param array $product
|
||||
*/
|
||||
protected function setDetailProductPrice(Order $order, Cart $cart, $product)
|
||||
{
|
||||
$this->setContext((int) $product['id_shop']);
|
||||
Product::getPriceStatic((int) $product['id_product'], true, (int) $product['id_product_attribute'], 6, null, false, true, $product['cart_quantity'], false, (int) $order->id_customer, (int) $order->id_cart, (int) $order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}, $specific_price, true, true, $this->context);
|
||||
$this->specificPrice = $specific_price;
|
||||
$this->original_product_price = Product::getPriceStatic(
|
||||
$product['id_product'],
|
||||
false,
|
||||
(int) $product['id_product_attribute'],
|
||||
6,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
1,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$null,
|
||||
true,
|
||||
true,
|
||||
$this->context
|
||||
);
|
||||
$this->unit_price_tax_incl = (float) $product['price_wt'];
|
||||
$this->product_price = $this->unit_price_tax_excl = (float) $product['price'];
|
||||
$this->total_price_tax_incl = (float) $product['total_wt'];
|
||||
$this->total_price_tax_excl = (float) $product['total'];
|
||||
|
||||
$this->purchase_supplier_price = (float) $product['wholesale_price'];
|
||||
if ($product['id_supplier'] > 0 && ($supplier_price = ProductSupplier::getProductPrice((int) $product['id_supplier'], $product['id_product'], $product['id_product_attribute'], true)) > 0) {
|
||||
$this->purchase_supplier_price = (float) $supplier_price;
|
||||
}
|
||||
|
||||
$this->setSpecificPrice($order, $product);
|
||||
|
||||
$this->group_reduction = (float) Group::getReduction((int) $order->id_customer);
|
||||
|
||||
$shop_id = $this->context->shop->id;
|
||||
|
||||
$quantity_discount = SpecificPrice::getQuantityDiscount(
|
||||
(int) $product['id_product'],
|
||||
$shop_id,
|
||||
(int) $cart->id_currency,
|
||||
(int) $this->vat_address->id_country,
|
||||
(int) $this->customer->id_default_group,
|
||||
(int) $product['cart_quantity'],
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
$null,
|
||||
true,
|
||||
true,
|
||||
$this->context
|
||||
);
|
||||
|
||||
$unit_price = Product::getPriceStatic(
|
||||
(int) $product['id_product'],
|
||||
true,
|
||||
($product['id_product_attribute'] ? (int) ($product['id_product_attribute']) : null),
|
||||
2,
|
||||
null,
|
||||
false,
|
||||
true,
|
||||
1,
|
||||
false,
|
||||
(int) $order->id_customer,
|
||||
null,
|
||||
(int) $order->{Configuration::get('PS_TAX_ADDRESS_TYPE')},
|
||||
$null,
|
||||
true,
|
||||
true,
|
||||
$this->context
|
||||
);
|
||||
$this->product_quantity_discount = 0.00;
|
||||
if ($quantity_discount) {
|
||||
$this->product_quantity_discount = $unit_price;
|
||||
if (Product::getTaxCalculationMethod((int) $order->id_customer) == PS_TAX_EXC) {
|
||||
$this->product_quantity_discount = Tools::ps_round($unit_price, Context::getContext()->getComputingPrecision());
|
||||
}
|
||||
|
||||
if (isset($this->tax_calculator)) {
|
||||
$this->product_quantity_discount -= $this->tax_calculator->addTaxes($quantity_discount['price']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->discount_quantity_applied = (($this->specificPrice && $this->specificPrice['from_quantity'] > 1) ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an order detail liable to an id_order.
|
||||
*
|
||||
* @param object $order
|
||||
* @param object $cart
|
||||
* @param array $product
|
||||
* @param int $id_order_status
|
||||
* @param int $id_order_invoice
|
||||
* @param bool $use_taxes set to false if you don't want to use taxes
|
||||
*/
|
||||
protected function create(Order $order, Cart $cart, $product, $id_order_state, $id_order_invoice, $use_taxes = true, $id_warehouse = 0)
|
||||
{
|
||||
if ($use_taxes) {
|
||||
$this->tax_calculator = new TaxCalculator();
|
||||
}
|
||||
|
||||
$this->id = null;
|
||||
|
||||
$this->product_id = (int) $product['id_product'];
|
||||
$this->product_attribute_id = $product['id_product_attribute'] ? (int) $product['id_product_attribute'] : 0;
|
||||
$this->id_customization = $product['id_customization'] ? (int) $product['id_customization'] : 0;
|
||||
$this->product_name = str_replace( 'Pdf', ' ', $product['name'] .
|
||||
((isset($product['attributes']) && $product['attributes'] != null) ?
|
||||
' (' . $product['attributes'] . ')' : '') );
|
||||
|
||||
$this->product_quantity = (int) $product['cart_quantity'];
|
||||
$this->product_ean13 = empty($product['ean13']) ? null : pSQL($product['ean13']);
|
||||
$this->product_isbn = empty($product['isbn']) ? null : pSQL($product['isbn']);
|
||||
$this->product_upc = empty($product['upc']) ? null : pSQL($product['upc']);
|
||||
$this->product_mpn = empty($product['mpn']) ? null : pSQL($product['mpn']);
|
||||
$this->product_reference = empty($product['reference']) ? null : pSQL($product['reference']);
|
||||
$this->product_supplier_reference = empty($product['supplier_reference']) ? null : pSQL($product['supplier_reference']);
|
||||
$this->product_weight = $product['id_product_attribute'] ? (float) $product['weight_attribute'] : (float) $product['weight'];
|
||||
$this->id_warehouse = $id_warehouse;
|
||||
|
||||
$product_quantity = (int) Product::getQuantity($this->product_id, $this->product_attribute_id, null, $cart);
|
||||
$this->product_quantity_in_stock = ($product_quantity - (int) $product['cart_quantity'] < 0) ?
|
||||
$product_quantity : (int) $product['cart_quantity'];
|
||||
|
||||
$this->setVirtualProductInformation($product);
|
||||
$this->checkProductStock($product, $id_order_state);
|
||||
|
||||
if ($use_taxes) {
|
||||
$this->setProductTax($order, $product);
|
||||
}
|
||||
$this->setShippingCost($order, $product);
|
||||
$this->setDetailProductPrice($order, $cart, $product);
|
||||
|
||||
// Set order invoice id
|
||||
$this->id_order_invoice = (int) $id_order_invoice;
|
||||
|
||||
// Set shop id
|
||||
$this->id_shop = (int) $product['id_shop'];
|
||||
|
||||
// Add new entry to the table
|
||||
$this->save();
|
||||
|
||||
if ($use_taxes) {
|
||||
$this->saveTaxCalculator($order);
|
||||
}
|
||||
unset($this->tax_calculator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list of order detail for a specified id_order using cart.
|
||||
*
|
||||
* @param object $order
|
||||
* @param object $cart
|
||||
* @param int $id_order_status
|
||||
* @param int $id_order_invoice
|
||||
* @param bool $use_taxes set to false if you don't want to use taxes
|
||||
*/
|
||||
public function createList(Order $order, Cart $cart, $id_order_state, $product_list, $id_order_invoice = 0, $use_taxes = true, $id_warehouse = 0)
|
||||
{
|
||||
$this->vat_address = new Address((int) $order->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
|
||||
$this->customer = new Customer((int) $order->id_customer);
|
||||
|
||||
$this->id_order = $order->id;
|
||||
$this->outOfStock = false;
|
||||
|
||||
foreach ($product_list as $product) {
|
||||
$this->create($order, $cart, $product, $id_order_state, $id_order_invoice, $use_taxes, $id_warehouse);
|
||||
}
|
||||
|
||||
unset(
|
||||
$this->vat_address,
|
||||
$this->customer
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the state of the current stock product.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getStockState()
|
||||
{
|
||||
return $this->outOfStock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the additional shipping information.
|
||||
*
|
||||
* @param Order $order
|
||||
* @param $product
|
||||
*/
|
||||
public function setShippingCost(Order $order, $product)
|
||||
{
|
||||
$tax_rate = 0;
|
||||
|
||||
$carrier = OrderInvoice::getCarrier((int) $this->id_order_invoice);
|
||||
if (isset($carrier) && Validate::isLoadedObject($carrier)) {
|
||||
$tax_rate = $carrier->getTaxesRate(new Address((int) $order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}));
|
||||
}
|
||||
|
||||
$this->total_shipping_price_tax_excl = (float) $product['additional_shipping_cost'];
|
||||
$this->total_shipping_price_tax_incl = (float) ($this->total_shipping_price_tax_excl * (1 + ($tax_rate / 100)));
|
||||
$this->total_shipping_price_tax_incl = Tools::ps_round($this->total_shipping_price_tax_incl, Context::getContext()->getComputingPrecision());
|
||||
}
|
||||
|
||||
public function getWsTaxes()
|
||||
{
|
||||
$query = new DbQuery();
|
||||
$query->select('id_tax as id');
|
||||
$query->from('order_detail_tax', 'tax');
|
||||
$query->leftJoin('order_detail', 'od', 'tax.`id_order_detail` = od.`id_order_detail`');
|
||||
$query->where('od.`id_order_detail` = ' . (int) $this->id_order_detail);
|
||||
|
||||
return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query);
|
||||
}
|
||||
|
||||
public static function getCrossSells($id_product, $id_lang, $limit = 12)
|
||||
{
|
||||
if (!$id_product || !$id_lang) {
|
||||
return;
|
||||
}
|
||||
|
||||
$front = true;
|
||||
if (!in_array(Context::getContext()->controller->controller_type, ['front', 'modulefront'])) {
|
||||
$front = false;
|
||||
}
|
||||
|
||||
$orders = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT o.id_order
|
||||
FROM ' . _DB_PREFIX_ . 'orders o
|
||||
LEFT JOIN ' . _DB_PREFIX_ . 'order_detail od ON (od.id_order = o.id_order)
|
||||
WHERE o.valid = 1 AND od.product_id = ' . (int) $id_product);
|
||||
|
||||
if (count($orders)) {
|
||||
$list = '';
|
||||
foreach ($orders as $order) {
|
||||
$list .= (int) $order['id_order'] . ',';
|
||||
}
|
||||
$list = rtrim($list, ',');
|
||||
|
||||
$order_products = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT DISTINCT od.product_id, p.id_product, pl.name, pl.link_rewrite, p.reference, i.id_image, product_shop.show_price,
|
||||
cl.link_rewrite category, p.ean13, p.isbn, p.out_of_stock, p.id_category_default ' . (Combination::isFeatureActive() ? ', IFNULL(product_attribute_shop.id_product_attribute,0) id_product_attribute' : '') . '
|
||||
FROM ' . _DB_PREFIX_ . 'order_detail od
|
||||
LEFT JOIN ' . _DB_PREFIX_ . 'product p ON (p.id_product = od.product_id)
|
||||
' . Shop::addSqlAssociation('product', 'p') .
|
||||
(Combination::isFeatureActive() ? 'LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute_shop` product_attribute_shop
|
||||
ON (p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop=' . (int) Context::getContext()->shop->id . ')' : '') . '
|
||||
LEFT JOIN ' . _DB_PREFIX_ . 'product_lang pl ON (pl.id_product = od.product_id' . Shop::addSqlRestrictionOnLang('pl') . ')
|
||||
LEFT JOIN ' . _DB_PREFIX_ . 'category_lang cl ON (cl.id_category = product_shop.id_category_default' . Shop::addSqlRestrictionOnLang('cl') . ')
|
||||
LEFT JOIN ' . _DB_PREFIX_ . 'image i ON (i.id_product = od.product_id)
|
||||
' . Shop::addSqlAssociation('image', 'i', true, 'image_shop.cover=1') . '
|
||||
WHERE od.id_order IN (' . $list . ')
|
||||
AND pl.id_lang = ' . (int) $id_lang . '
|
||||
AND cl.id_lang = ' . (int) $id_lang . '
|
||||
AND od.product_id != ' . (int) $id_product . '
|
||||
AND product_shop.active = 1'
|
||||
. ($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '') . '
|
||||
ORDER BY RAND()
|
||||
LIMIT ' . (int) $limit . '
|
||||
', true, false);
|
||||
|
||||
$tax_calc = Product::getTaxCalculationMethod();
|
||||
if (is_array($order_products)) {
|
||||
foreach ($order_products as &$order_product) {
|
||||
$order_product['image'] = Context::getContext()->link->getImageLink(
|
||||
$order_product['link_rewrite'],
|
||||
(int) $order_product['product_id'] . '-' . (int) $order_product['id_image'],
|
||||
ImageType::getFormattedName('medium')
|
||||
);
|
||||
$order_product['link'] = Context::getContext()->link->getProductLink(
|
||||
(int) $order_product['product_id'],
|
||||
$order_product['link_rewrite'],
|
||||
$order_product['category'],
|
||||
$order_product['ean13']
|
||||
);
|
||||
if ($tax_calc == 0 || $tax_calc == 2) {
|
||||
$order_product['displayed_price'] = Product::getPriceStatic((int) $order_product['product_id'], true, null);
|
||||
} elseif ($tax_calc == 1) {
|
||||
$order_product['displayed_price'] = Product::getPriceStatic((int) $order_product['product_id'], false, null);
|
||||
}
|
||||
}
|
||||
|
||||
return Product::getProductsProperties($id_lang, $order_products);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function add($autodate = true, $null_values = false)
|
||||
{
|
||||
foreach ($this->def['fields'] as $field => $data) {
|
||||
if (!empty($data['required']) || !empty($data['lang'])) {
|
||||
continue;
|
||||
}
|
||||
if ($this->validateField($field, $this->$field) !== true) {
|
||||
$this->$field = '';
|
||||
}
|
||||
}
|
||||
|
||||
$this->original_wholesale_price = $this->getWholeSalePrice();
|
||||
|
||||
return parent::add($autodate = true, $null_values = false);
|
||||
}
|
||||
|
||||
//return the product OR product attribute whole sale price
|
||||
public function getWholeSalePrice()
|
||||
{
|
||||
$product = new Product($this->product_id);
|
||||
$wholesale_price = $product->wholesale_price;
|
||||
|
||||
if ($this->product_attribute_id) {
|
||||
$combination = new Combination((int) $this->product_attribute_id);
|
||||
if ($combination && $combination->wholesale_price != '0.000000') {
|
||||
$wholesale_price = $combination->wholesale_price;
|
||||
}
|
||||
}
|
||||
|
||||
return $wholesale_price;
|
||||
}
|
||||
}
|
||||
63
classes/order/OrderDiscount.php
Normal file
63
classes/order/OrderDiscount.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @deprecated 1.5.0
|
||||
*/
|
||||
class OrderDiscountCore extends OrderCartRule
|
||||
{
|
||||
public function __get($key)
|
||||
{
|
||||
Tools::displayAsDeprecated();
|
||||
if ($key == 'id_order_discount') {
|
||||
return $this->id_order_cart_rule;
|
||||
}
|
||||
if ($key == 'id_discount') {
|
||||
return $this->id_cart_rule;
|
||||
}
|
||||
|
||||
return $this->{$key};
|
||||
}
|
||||
|
||||
public function __set($key, $value)
|
||||
{
|
||||
Tools::displayAsDeprecated();
|
||||
if ($key == 'id_order_discount') {
|
||||
$this->id_order_cart_rule = $value;
|
||||
}
|
||||
if ($key == 'id_discount') {
|
||||
$this->id_cart_rule = $value;
|
||||
}
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
|
||||
public function __call($method, $args)
|
||||
{
|
||||
Tools::displayAsDeprecated();
|
||||
|
||||
return call_user_func_array([$this->parent, $method], $args);
|
||||
}
|
||||
}
|
||||
638
classes/order/OrderHistory.php
Normal file
638
classes/order/OrderHistory.php
Normal file
@@ -0,0 +1,638 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
use PrestaShop\PrestaShop\Adapter\MailTemplate\MailPartialTemplateRenderer;
|
||||
use PrestaShop\PrestaShop\Adapter\StockManager as StockManagerAdapter;
|
||||
use PrestaShop\PrestaShop\Core\Stock\StockManager;
|
||||
|
||||
class OrderHistoryCore extends ObjectModel
|
||||
{
|
||||
/** @var int Order id */
|
||||
public $id_order;
|
||||
|
||||
/** @var int Order status id */
|
||||
public $id_order_state;
|
||||
|
||||
/** @var int Employee id for this history entry */
|
||||
public $id_employee;
|
||||
|
||||
/** @var string Object creation date */
|
||||
public $date_add;
|
||||
|
||||
/** @var string Object last modification date */
|
||||
public $date_upd;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'order_history',
|
||||
'primary' => 'id_order_history',
|
||||
'fields' => [
|
||||
'id_order' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'id_order_state' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'id_employee' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
||||
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$webserviceParameters
|
||||
*/
|
||||
protected $webserviceParameters = [
|
||||
'objectsNodeName' => 'order_histories',
|
||||
'fields' => [
|
||||
'id_employee' => ['xlink_resource' => 'employees'],
|
||||
'id_order_state' => ['required' => true, 'xlink_resource' => 'order_states'],
|
||||
'id_order' => ['xlink_resource' => 'orders'],
|
||||
],
|
||||
'objectMethods' => [
|
||||
'add' => 'addWs',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Sets the new state of the given order.
|
||||
*
|
||||
* @param int $new_order_state
|
||||
* @param int|Order $id_order
|
||||
* @param bool $use_existing_payment
|
||||
*/
|
||||
public function changeIdOrderState($new_order_state, $id_order, $use_existing_payment = false)
|
||||
{
|
||||
if (!$new_order_state || !$id_order) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_object($id_order) && is_numeric($id_order)) {
|
||||
$order = new Order((int) $id_order);
|
||||
} elseif (is_object($id_order)) {
|
||||
$order = $id_order;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
ShopUrl::cacheMainDomainForShop($order->id_shop);
|
||||
|
||||
$new_os = new OrderState((int) $new_order_state, $order->id_lang);
|
||||
$old_os = $order->getCurrentOrderState();
|
||||
|
||||
// executes hook
|
||||
if (in_array($new_os->id, [Configuration::get('PS_OS_PAYMENT'), Configuration::get('PS_OS_WS_PAYMENT')])) {
|
||||
Hook::exec('actionPaymentConfirmation', ['id_order' => (int) $order->id], null, false, true, false, $order->id_shop);
|
||||
}
|
||||
|
||||
// executes hook
|
||||
Hook::exec('actionOrderStatusUpdate', ['newOrderStatus' => $new_os, 'id_order' => (int) $order->id], null, false, true, false, $order->id_shop);
|
||||
|
||||
if (Validate::isLoadedObject($order) && ($new_os instanceof OrderState)) {
|
||||
$context = Context::getContext();
|
||||
|
||||
// An email is sent the first time a virtual item is validated
|
||||
$virtual_products = $order->getVirtualProducts();
|
||||
if ($virtual_products && (!$old_os || !$old_os->logable) && $new_os && $new_os->logable) {
|
||||
$assign = [];
|
||||
foreach ($virtual_products as $key => $virtual_product) {
|
||||
$id_product_download = ProductDownload::getIdFromIdProduct($virtual_product['product_id']);
|
||||
$product_download = new ProductDownload($id_product_download);
|
||||
// If this virtual item has an associated file, we'll provide the link to download the file in the email
|
||||
if ($product_download->display_filename != '') {
|
||||
$assign[$key]['name'] = $product_download->display_filename;
|
||||
$dl_link = $product_download->getTextLink(false, $virtual_product['download_hash'])
|
||||
. '&id_order=' . (int) $order->id
|
||||
. '&secure_key=' . $order->secure_key;
|
||||
$assign[$key]['link'] = $dl_link;
|
||||
if (isset($virtual_product['download_deadline']) && $virtual_product['download_deadline'] != '0000-00-00 00:00:00') {
|
||||
$assign[$key]['deadline'] = Tools::displayDate($virtual_product['download_deadline']);
|
||||
}
|
||||
if ($product_download->nb_downloadable != 0) {
|
||||
$assign[$key]['downloadable'] = (int) $product_download->nb_downloadable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$customer = new Customer((int) $order->id_customer);
|
||||
$links = [];
|
||||
foreach ($assign as $product) {
|
||||
$complementaryText = [];
|
||||
if (isset($product['deadline'])) {
|
||||
$complementaryText[] = $this->trans('expires on %s.', [$product['deadline']], 'Admin.Orderscustomers.Notification');
|
||||
}
|
||||
if (isset($product['downloadable'])) {
|
||||
$complementaryText[] = $this->trans('downloadable %d time(s)', [(int) $product['downloadable']], 'Admin.Orderscustomers.Notification');
|
||||
}
|
||||
$links[] = [
|
||||
'text' => Tools::htmlentitiesUTF8($product['name']),
|
||||
'url' => $product['link'],
|
||||
'complementary_text' => implode(' ', $complementaryText),
|
||||
];
|
||||
}
|
||||
|
||||
$context = Context::getContext();
|
||||
$partialRenderer = new MailPartialTemplateRenderer($context->smarty);
|
||||
|
||||
$links_txt = $partialRenderer->render('download_product_virtual_products.txt', $context->language, $links, true);
|
||||
$links_html = $partialRenderer->render('download_product_virtual_products.tpl', $context->language, $links);
|
||||
|
||||
$data = [
|
||||
'{lastname}' => $customer->lastname,
|
||||
'{firstname}' => $customer->firstname,
|
||||
'{id_order}' => (int) $order->id,
|
||||
'{order_name}' => $order->getUniqReference(),
|
||||
'{nbProducts}' => count($virtual_products),
|
||||
'{virtualProducts}' => $links_html,
|
||||
'{virtualProductsTxt}' => $links_txt,
|
||||
];
|
||||
// If there is at least one downloadable file
|
||||
if (!empty($assign)) {
|
||||
$orderLanguage = new Language((int) $order->id_lang);
|
||||
Mail::Send(
|
||||
(int) $order->id_lang,
|
||||
'download_product',
|
||||
Context::getContext()->getTranslator()->trans(
|
||||
'The virtual product that you bought is available for download',
|
||||
[],
|
||||
'Emails.Subject',
|
||||
$orderLanguage->locale
|
||||
),
|
||||
$data,
|
||||
$customer->email,
|
||||
$customer->firstname . ' ' . $customer->lastname,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
_PS_MAIL_DIR_,
|
||||
false,
|
||||
(int) $order->id_shop
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 1.5.0 : gets the stock manager */
|
||||
$manager = null;
|
||||
if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
|
||||
$manager = StockManagerFactory::getManager();
|
||||
}
|
||||
|
||||
$error_or_canceled_statuses = [Configuration::get('PS_OS_ERROR'), Configuration::get('PS_OS_CANCELED')];
|
||||
|
||||
$employee = null;
|
||||
if (!(int) $this->id_employee || !Validate::isLoadedObject(($employee = new Employee((int) $this->id_employee)))) {
|
||||
if (!Validate::isLoadedObject($old_os) && $context != null) {
|
||||
// First OrderHistory, there is no $old_os, so $employee is null before here
|
||||
$employee = $context->employee; // filled if from BO and order created (because no old_os)
|
||||
if ($employee) {
|
||||
$this->id_employee = $employee->id;
|
||||
}
|
||||
} else {
|
||||
$employee = null;
|
||||
}
|
||||
}
|
||||
|
||||
// foreach products of the order
|
||||
foreach ($order->getProductsDetail() as $product) {
|
||||
if (Validate::isLoadedObject($old_os)) {
|
||||
// if becoming logable => adds sale
|
||||
if ($new_os->logable && !$old_os->logable) {
|
||||
ProductSale::addProductSale($product['product_id'], $product['product_quantity']);
|
||||
// @since 1.5.0 - Stock Management
|
||||
if (!Pack::isPack($product['product_id']) &&
|
||||
in_array($old_os->id, $error_or_canceled_statuses) &&
|
||||
!StockAvailable::dependsOnStock($product['id_product'], (int) $order->id_shop)) {
|
||||
StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], -(int) $product['product_quantity'], $order->id_shop);
|
||||
}
|
||||
} elseif (!$new_os->logable && $old_os->logable) {
|
||||
// if becoming unlogable => removes sale
|
||||
ProductSale::removeProductSale($product['product_id'], $product['product_quantity']);
|
||||
|
||||
// @since 1.5.0 - Stock Management
|
||||
if (!Pack::isPack($product['product_id']) &&
|
||||
in_array($new_os->id, $error_or_canceled_statuses) &&
|
||||
!StockAvailable::dependsOnStock($product['id_product'])) {
|
||||
StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], (int) $product['product_quantity'], $order->id_shop);
|
||||
}
|
||||
} elseif (!$new_os->logable && !$old_os->logable &&
|
||||
in_array($new_os->id, $error_or_canceled_statuses) &&
|
||||
!in_array($old_os->id, $error_or_canceled_statuses) &&
|
||||
!StockAvailable::dependsOnStock($product['id_product'])
|
||||
) {
|
||||
// if waiting for payment => payment error/canceled
|
||||
StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], (int) $product['product_quantity'], $order->id_shop);
|
||||
}
|
||||
}
|
||||
// From here, there is 2 cases : $old_os exists, and we can test shipped state evolution,
|
||||
// Or old_os does not exists, and we should consider that initial shipped state is 0 (to allow decrease of stocks)
|
||||
|
||||
// @since 1.5.0 : if the order is being shipped and this products uses the advanced stock management :
|
||||
// decrements the physical stock using $id_warehouse
|
||||
if ($new_os->shipped == 1 && (!Validate::isLoadedObject($old_os) || $old_os->shipped == 0) &&
|
||||
Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') &&
|
||||
Warehouse::exists($product['id_warehouse']) &&
|
||||
$manager != null &&
|
||||
(int) $product['advanced_stock_management'] == 1) {
|
||||
// gets the warehouse
|
||||
$warehouse = new Warehouse($product['id_warehouse']);
|
||||
|
||||
// decrements the stock (if it's a pack, the StockManager does what is needed)
|
||||
$manager->removeProduct(
|
||||
$product['product_id'],
|
||||
$product['product_attribute_id'],
|
||||
$warehouse,
|
||||
($product['product_quantity'] - $product['product_quantity_refunded'] - $product['product_quantity_return']),
|
||||
Configuration::get('PS_STOCK_CUSTOMER_ORDER_REASON'),
|
||||
true,
|
||||
(int) $order->id,
|
||||
0,
|
||||
$employee
|
||||
);
|
||||
} elseif ($new_os->shipped == 0 && Validate::isLoadedObject($old_os) && $old_os->shipped == 1 &&
|
||||
Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') &&
|
||||
Warehouse::exists($product['id_warehouse']) &&
|
||||
$manager != null &&
|
||||
(int) $product['advanced_stock_management'] == 1
|
||||
) {
|
||||
// @since.1.5.0 : if the order was shipped, and is not anymore, we need to restock products
|
||||
|
||||
// if the product is a pack, we restock every products in the pack using the last negative stock mvts
|
||||
if (Pack::isPack($product['product_id'])) {
|
||||
$pack_products = Pack::getItems($product['product_id'], Configuration::get('PS_LANG_DEFAULT', null, null, $order->id_shop));
|
||||
foreach ($pack_products as $pack_product) {
|
||||
if ($pack_product->advanced_stock_management == 1) {
|
||||
$mvts = StockMvt::getNegativeStockMvts($order->id, $pack_product->id, 0, $pack_product->pack_quantity * $product['product_quantity']);
|
||||
foreach ($mvts as $mvt) {
|
||||
$manager->addProduct(
|
||||
$pack_product->id,
|
||||
0,
|
||||
new Warehouse($mvt['id_warehouse']),
|
||||
$mvt['physical_quantity'],
|
||||
null,
|
||||
$mvt['price_te'],
|
||||
true,
|
||||
null,
|
||||
$employee
|
||||
);
|
||||
}
|
||||
if (!StockAvailable::dependsOnStock($product['id_product'])) {
|
||||
StockAvailable::updateQuantity($pack_product->id, 0, (int) $pack_product->pack_quantity * $product['product_quantity'], $order->id_shop);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// else, it's not a pack, re-stock using the last negative stock mvts
|
||||
|
||||
$mvts = StockMvt::getNegativeStockMvts(
|
||||
$order->id,
|
||||
$product['product_id'],
|
||||
$product['product_attribute_id'],
|
||||
($product['product_quantity'] - $product['product_quantity_refunded'] - $product['product_quantity_return'])
|
||||
);
|
||||
|
||||
foreach ($mvts as $mvt) {
|
||||
$manager->addProduct(
|
||||
$product['product_id'],
|
||||
$product['product_attribute_id'],
|
||||
new Warehouse($mvt['id_warehouse']),
|
||||
$mvt['physical_quantity'],
|
||||
null,
|
||||
$mvt['price_te'],
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save movement if :
|
||||
// not Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')
|
||||
// new_os->shipped != old_os->shipped
|
||||
if (Validate::isLoadedObject($old_os) && Validate::isLoadedObject($new_os) && $new_os->shipped != $old_os->shipped && !Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
|
||||
$product_quantity = (int) ($product['product_quantity'] - $product['product_quantity_refunded'] - $product['product_quantity_return']);
|
||||
|
||||
if ($product_quantity > 0) {
|
||||
$current_shop_context_type = Context::getContext()->shop->getContextType();
|
||||
if ($current_shop_context_type !== Shop::CONTEXT_SHOP) {
|
||||
//change to order shop context
|
||||
$current_shop_group_id = Context::getContext()->shop->getContextShopGroupID();
|
||||
Context::getContext()->shop->setContext(Shop::CONTEXT_SHOP, $order->id_shop);
|
||||
}
|
||||
(new StockManager())->saveMovement(
|
||||
(int) $product['product_id'],
|
||||
(int) $product['product_attribute_id'],
|
||||
(int) $product_quantity * ($new_os->shipped == 1 ? -1 : 1),
|
||||
[
|
||||
'id_order' => $order->id,
|
||||
'id_stock_mvt_reason' => ($new_os->shipped == 1 ? Configuration::get('PS_STOCK_CUSTOMER_ORDER_REASON') : Configuration::get('PS_STOCK_CUSTOMER_ORDER_CANCEL_REASON')),
|
||||
]
|
||||
);
|
||||
//back to current shop context
|
||||
if ($current_shop_context_type !== Shop::CONTEXT_SHOP) {
|
||||
Context::getContext()->shop->setContext($current_shop_context_type, $current_shop_group_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->id_order_state = (int) $new_order_state;
|
||||
|
||||
// changes invoice number of order ?
|
||||
if (!Validate::isLoadedObject($new_os) || !Validate::isLoadedObject($order)) {
|
||||
die(Tools::displayError($this->trans('Invalid new order status', [], 'Admin.Orderscustomers.Notification')));
|
||||
}
|
||||
|
||||
// the order is valid if and only if the invoice is available and the order is not cancelled
|
||||
$order->current_state = $this->id_order_state;
|
||||
$order->valid = $new_os->logable;
|
||||
$order->update();
|
||||
|
||||
if ($new_os->invoice && !$order->invoice_number) {
|
||||
$order->setInvoice($use_existing_payment);
|
||||
} elseif ($new_os->delivery && !$order->delivery_number) {
|
||||
$order->setDeliverySlip();
|
||||
}
|
||||
|
||||
// set orders as paid
|
||||
if ($new_os->paid == 1) {
|
||||
if ($order->total_paid != 0) {
|
||||
$payment_method = Module::getInstanceByName($order->module);
|
||||
}
|
||||
|
||||
$invoices = $order->getInvoicesCollection();
|
||||
foreach ($invoices as $invoice) {
|
||||
/** @var OrderInvoice $invoice */
|
||||
$rest_paid = $invoice->getRestPaid();
|
||||
if ($rest_paid > 0) {
|
||||
$payment = new OrderPayment();
|
||||
$payment->order_reference = Tools::substr($order->reference, 0, 9);
|
||||
$payment->id_currency = $order->id_currency;
|
||||
$payment->amount = $rest_paid;
|
||||
$payment->payment_method = $payment_method ? $payment_method->displayName : null;
|
||||
$payment->conversion_rate = $order->conversion_rate;
|
||||
$payment->save();
|
||||
|
||||
// Update total_paid_real value for backward compatibility reasons
|
||||
$order->total_paid_real += $rest_paid;
|
||||
$order->save();
|
||||
|
||||
Db::getInstance()->insert(
|
||||
'order_invoice_payment',
|
||||
[
|
||||
'id_order_invoice' => (int) $invoice->id,
|
||||
'id_order_payment' => (int) $payment->id,
|
||||
'id_order' => (int) $order->id,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// updates delivery date even if it was already set by another state change
|
||||
if ($new_os->delivery) {
|
||||
$order->setDelivery();
|
||||
}
|
||||
|
||||
// executes hook
|
||||
Hook::exec('actionOrderStatusPostUpdate', ['newOrderStatus' => $new_os, 'id_order' => (int) $order->id], null, false, true, false, $order->id_shop);
|
||||
|
||||
// sync all stock
|
||||
(new StockManagerAdapter())->updatePhysicalProductQuantity(
|
||||
(int) $order->id_shop,
|
||||
(int) Configuration::get('PS_OS_ERROR'),
|
||||
(int) Configuration::get('PS_OS_CANCELED'),
|
||||
null,
|
||||
(int) $order->id
|
||||
);
|
||||
|
||||
ShopUrl::resetMainDomainCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last order status.
|
||||
*
|
||||
* @param int $id_order
|
||||
*
|
||||
* @return OrderState|bool
|
||||
*
|
||||
* @deprecated 1.5.0.4
|
||||
* @see Order->current_state
|
||||
*/
|
||||
public static function getLastOrderState($id_order)
|
||||
{
|
||||
Tools::displayAsDeprecated();
|
||||
$id_order_state = Db::getInstance()->getValue('
|
||||
SELECT `id_order_state`
|
||||
FROM `' . _DB_PREFIX_ . 'order_history`
|
||||
WHERE `id_order` = ' . (int) $id_order . '
|
||||
ORDER BY `date_add` DESC, `id_order_history` DESC');
|
||||
|
||||
// returns false if there is no state
|
||||
if (!$id_order_state) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// else, returns an OrderState object
|
||||
return new OrderState($id_order_state, Configuration::get('PS_LANG_DEFAULT'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $autodate Optional
|
||||
* @param array $template_vars Optional
|
||||
* @param Context $context Deprecated
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function addWithemail($autodate = true, $template_vars = false, Context $context = null)
|
||||
{
|
||||
$order = new Order($this->id_order);
|
||||
|
||||
if (!$this->add($autodate)) {
|
||||
return false;
|
||||
}
|
||||
Order::cleanHistoryCache();
|
||||
|
||||
if (!$this->sendEmail($order, $template_vars)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Order $order
|
||||
* @param array|false $template_vars
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function sendEmail($order, $template_vars = false)
|
||||
{
|
||||
$result = Db::getInstance()->getRow('
|
||||
SELECT osl.`template`, c.`lastname`, c.`firstname`, osl.`name` AS osname, c.`email`, os.`module_name`, os.`id_order_state`, os.`pdf_invoice`, os.`pdf_delivery`
|
||||
FROM `' . _DB_PREFIX_ . 'order_history` oh
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'orders` o ON oh.`id_order` = o.`id_order`
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'customer` c ON o.`id_customer` = c.`id_customer`
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'order_state` os ON oh.`id_order_state` = os.`id_order_state`
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = o.`id_lang`)
|
||||
WHERE oh.`id_order_history` = ' . (int) $this->id . ' AND os.`send_email` = 1');
|
||||
if (isset($result['template']) && Validate::isEmail($result['email'])) {
|
||||
ShopUrl::cacheMainDomainForShop($order->id_shop);
|
||||
|
||||
$topic = $result['osname'];
|
||||
$carrierUrl = '';
|
||||
if (Validate::isLoadedObject($carrier = new Carrier((int) $order->id_carrier, $order->id_lang))) {
|
||||
$carrierUrl = $carrier->url;
|
||||
}
|
||||
$data = [
|
||||
'{lastname}' => $result['lastname'],
|
||||
'{firstname}' => $result['firstname'],
|
||||
'{id_order}' => (int) $this->id_order,
|
||||
'{order_name}' => $order->getUniqReference(),
|
||||
'{followup}' => str_replace('@', $order->getWsShippingNumber(), $carrierUrl),
|
||||
'{shipping_number}' => $order->getWsShippingNumber(),
|
||||
];
|
||||
|
||||
if ($result['module_name']) {
|
||||
$module = Module::getInstanceByName($result['module_name']);
|
||||
if (Validate::isLoadedObject($module) && isset($module->extra_mail_vars) && is_array($module->extra_mail_vars)) {
|
||||
$data = array_merge($data, $module->extra_mail_vars);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($template_vars)) {
|
||||
$data = array_merge($data, $template_vars);
|
||||
}
|
||||
|
||||
$context = Context::getContext();
|
||||
$data['{total_paid}'] = Tools::getContextLocale($context)->formatPrice((float) $order->total_paid, Currency::getIsoCodeById((int) $order->id_currency));
|
||||
|
||||
if (Validate::isLoadedObject($order)) {
|
||||
// Attach invoice and / or delivery-slip if they exists and status is set to attach them
|
||||
if (($result['pdf_invoice'] || $result['pdf_delivery'])) {
|
||||
$currentLanguage = $context->language;
|
||||
$orderLanguage = new Language((int) $order->id_lang);
|
||||
$context->language = $orderLanguage;
|
||||
$context->getTranslator()->setLocale($orderLanguage->locale);
|
||||
$invoice = $order->getInvoicesCollection();
|
||||
$file_attachement = [];
|
||||
|
||||
if ($result['pdf_invoice'] && (int) Configuration::get('PS_INVOICE') && $order->invoice_number) {
|
||||
Hook::exec('actionPDFInvoiceRender', ['order_invoice_list' => $invoice]);
|
||||
$pdf = new PDF($invoice, PDF::TEMPLATE_INVOICE, $context->smarty);
|
||||
$file_attachement['invoice']['content'] = $pdf->render(false);
|
||||
$file_attachement['invoice']['name'] = Configuration::get('PS_INVOICE_PREFIX', (int) $order->id_lang, null, $order->id_shop) . sprintf('%06d', $order->invoice_number) . '.pdf';
|
||||
$file_attachement['invoice']['mime'] = 'application/pdf';
|
||||
}
|
||||
if ($result['pdf_delivery'] && $order->delivery_number) {
|
||||
$pdf = new PDF($invoice, PDF::TEMPLATE_DELIVERY_SLIP, $context->smarty);
|
||||
$file_attachement['delivery']['content'] = $pdf->render(false);
|
||||
$file_attachement['delivery']['name'] = Configuration::get('PS_DELIVERY_PREFIX', (int) $order->id_lang, null, $order->id_shop) . sprintf('%06d', $order->delivery_number) . '.pdf';
|
||||
$file_attachement['delivery']['mime'] = 'application/pdf';
|
||||
}
|
||||
|
||||
$context->language = $currentLanguage;
|
||||
$context->getTranslator()->setLocale($currentLanguage->locale);
|
||||
} else {
|
||||
$file_attachement = null;
|
||||
}
|
||||
|
||||
if (!Mail::Send(
|
||||
(int) $order->id_lang,
|
||||
$result['template'],
|
||||
$topic,
|
||||
$data,
|
||||
$result['email'],
|
||||
$result['firstname'] . ' ' . $result['lastname'],
|
||||
null,
|
||||
null,
|
||||
$file_attachement,
|
||||
null,
|
||||
_PS_MAIL_DIR_,
|
||||
false,
|
||||
(int) $order->id_shop
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ShopUrl::resetMainDomainCache();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function add($autodate = true, $null_values = false)
|
||||
{
|
||||
if (!parent::add($autodate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$order = new Order((int) $this->id_order);
|
||||
// Update id_order_state attribute in Order
|
||||
$order->current_state = $this->id_order_state;
|
||||
$order->update();
|
||||
|
||||
Hook::exec('actionOrderHistoryAddAfter', ['order_history' => $this], null, false, true, false, $order->id_shop);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function isValidated()
|
||||
{
|
||||
return Db::getInstance()->getValue('
|
||||
SELECT COUNT(oh.`id_order_history`) AS nb
|
||||
FROM `' . _DB_PREFIX_ . 'order_state` os
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'order_history` oh ON (os.`id_order_state` = oh.`id_order_state`)
|
||||
WHERE oh.`id_order` = ' . (int) $this->id_order . '
|
||||
AND os.`logable` = 1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add method for webservice create resource Order History
|
||||
* If sendemail=1 GET parameter is present sends email to customer otherwise does not.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function addWs()
|
||||
{
|
||||
$sendemail = (bool) Tools::getValue('sendemail', false);
|
||||
$this->changeIdOrderState($this->id_order_state, $this->id_order);
|
||||
|
||||
if ($sendemail) {
|
||||
//Mail::Send requires link object on context and is not set when getting here
|
||||
$context = Context::getContext();
|
||||
if ($context->link == null) {
|
||||
$protocol_link = (Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://';
|
||||
$protocol_content = (Tools::usingSecureMode() && Configuration::get('PS_SSL_ENABLED')) ? 'https://' : 'http://';
|
||||
$context->link = new Link($protocol_link, $protocol_content);
|
||||
}
|
||||
|
||||
return $this->addWithemail();
|
||||
} else {
|
||||
return $this->add();
|
||||
}
|
||||
}
|
||||
}
|
||||
955
classes/order/OrderInvoice.php
Normal file
955
classes/order/OrderInvoice.php
Normal file
@@ -0,0 +1,955 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class OrderInvoiceCore extends ObjectModel
|
||||
{
|
||||
const TAX_EXCL = 0;
|
||||
const TAX_INCL = 1;
|
||||
const DETAIL = 2;
|
||||
|
||||
/** @var int */
|
||||
public $id_order;
|
||||
|
||||
/** @var int */
|
||||
public $number;
|
||||
|
||||
/** @var int */
|
||||
public $delivery_number;
|
||||
|
||||
/** @var int */
|
||||
public $delivery_date = '0000-00-00 00:00:00';
|
||||
|
||||
/** @var float */
|
||||
public $total_discount_tax_excl;
|
||||
|
||||
/** @var float */
|
||||
public $total_discount_tax_incl;
|
||||
|
||||
/** @var float */
|
||||
public $total_paid_tax_excl;
|
||||
|
||||
/** @var float */
|
||||
public $total_paid_tax_incl;
|
||||
|
||||
/** @var float */
|
||||
public $total_products;
|
||||
|
||||
/** @var float */
|
||||
public $total_products_wt;
|
||||
|
||||
/** @var float */
|
||||
public $total_shipping_tax_excl;
|
||||
|
||||
/** @var float */
|
||||
public $total_shipping_tax_incl;
|
||||
|
||||
/** @var int */
|
||||
public $shipping_tax_computation_method;
|
||||
|
||||
/** @var float */
|
||||
public $total_wrapping_tax_excl;
|
||||
|
||||
/** @var float */
|
||||
public $total_wrapping_tax_incl;
|
||||
|
||||
/** @var string shop address */
|
||||
public $shop_address;
|
||||
|
||||
/** @var string note */
|
||||
public $note;
|
||||
|
||||
/** @var int */
|
||||
public $date_add;
|
||||
|
||||
/** @var array Total paid cache */
|
||||
protected static $_total_paid_cache = [];
|
||||
|
||||
/** @var Order * */
|
||||
private $order;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'order_invoice',
|
||||
'primary' => 'id_order_invoice',
|
||||
'fields' => [
|
||||
'id_order' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'number' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'delivery_number' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
||||
'delivery_date' => ['type' => self::TYPE_DATE, 'validate' => 'isDateFormat'],
|
||||
'total_discount_tax_excl' => ['type' => self::TYPE_FLOAT],
|
||||
'total_discount_tax_incl' => ['type' => self::TYPE_FLOAT],
|
||||
'total_paid_tax_excl' => ['type' => self::TYPE_FLOAT],
|
||||
'total_paid_tax_incl' => ['type' => self::TYPE_FLOAT],
|
||||
'total_products' => ['type' => self::TYPE_FLOAT],
|
||||
'total_products_wt' => ['type' => self::TYPE_FLOAT],
|
||||
'total_shipping_tax_excl' => ['type' => self::TYPE_FLOAT],
|
||||
'total_shipping_tax_incl' => ['type' => self::TYPE_FLOAT],
|
||||
'shipping_tax_computation_method' => ['type' => self::TYPE_INT],
|
||||
'total_wrapping_tax_excl' => ['type' => self::TYPE_FLOAT],
|
||||
'total_wrapping_tax_incl' => ['type' => self::TYPE_FLOAT],
|
||||
'shop_address' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml', 'size' => 1000],
|
||||
'note' => ['type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 65000],
|
||||
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
],
|
||||
];
|
||||
|
||||
public function add($autodate = true, $null_values = false)
|
||||
{
|
||||
$order = new Order($this->id_order);
|
||||
|
||||
$this->shop_address = OrderInvoice::getCurrentFormattedShopAddress($order->id_shop);
|
||||
|
||||
return parent::add();
|
||||
}
|
||||
|
||||
public function getProductsDetail()
|
||||
{
|
||||
return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT *, od.ecotax as od_ecotax, od.ecotax_tax_rate as od_ecotax_tax_rate
|
||||
FROM `' . _DB_PREFIX_ . 'order_detail` od
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'product` p
|
||||
ON p.id_product = od.product_id
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'product_shop` ps ON (ps.id_product = p.id_product AND ps.id_shop = od.id_shop)
|
||||
WHERE od.`id_order` = ' . (int) $this->id_order . '
|
||||
' . ($this->id && $this->number ? ' AND od.`id_order_invoice` = ' . (int) $this->id : '') . ' ORDER BY od.`product_name`');
|
||||
}
|
||||
|
||||
public static function getInvoiceByNumber($id_invoice)
|
||||
{
|
||||
if (is_numeric($id_invoice)) {
|
||||
$id_invoice = (int) $id_invoice;
|
||||
} elseif (is_string($id_invoice)) {
|
||||
$matches = [];
|
||||
if (preg_match('/^(?:' . Configuration::get('PS_INVOICE_PREFIX', Context::getContext()->language->id) . ')\s*([0-9]+)$/i', $id_invoice, $matches)) {
|
||||
$id_invoice = $matches[1];
|
||||
}
|
||||
}
|
||||
if (!$id_invoice) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$id_order_invoice = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(
|
||||
'SELECT `id_order_invoice`
|
||||
FROM `' . _DB_PREFIX_ . 'order_invoice`
|
||||
WHERE number = ' . (int) $id_invoice
|
||||
);
|
||||
|
||||
return $id_order_invoice ? new OrderInvoice($id_order_invoice) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get order products.
|
||||
*
|
||||
* @return array Products with price, quantity (with taxe and without)
|
||||
*/
|
||||
public function getProducts($products = false, $selected_products = false, $selected_qty = false)
|
||||
{
|
||||
if (!$products) {
|
||||
$products = $this->getProductsDetail();
|
||||
}
|
||||
|
||||
$order = new Order($this->id_order);
|
||||
|
||||
$result_array = [];
|
||||
foreach ($products as $row) {
|
||||
// Change qty if selected
|
||||
if ($selected_qty) {
|
||||
$row['product_quantity'] = 0;
|
||||
foreach ($selected_products as $key => $id_product) {
|
||||
if ($row['id_order_detail'] == $id_product) {
|
||||
$row['product_quantity'] = (int) $selected_qty[$key];
|
||||
}
|
||||
}
|
||||
if (!$row['product_quantity']) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$this->setProductImageInformations($row);
|
||||
$this->setProductCurrentStock($row);
|
||||
|
||||
$customized_datas = Product::getAllCustomizedDatas($order->id_cart, null, true, null, (int) $row['id_customization']);
|
||||
$this->setProductCustomizedDatas($row, $customized_datas);
|
||||
|
||||
// Add information for virtual product
|
||||
if ($row['download_hash'] && !empty($row['download_hash'])) {
|
||||
$row['filename'] = ProductDownload::getFilenameFromIdProduct((int) $row['product_id']);
|
||||
// Get the display filename
|
||||
$row['display_filename'] = ProductDownload::getFilenameFromFilename($row['filename']);
|
||||
}
|
||||
|
||||
$row['id_address_delivery'] = $order->id_address_delivery;
|
||||
|
||||
/* Ecotax */
|
||||
$round_mode = $order->round_mode;
|
||||
|
||||
// Use values from order_detail not from product because they are more accurate at the time the Order was made
|
||||
// and they contain the true value for combinations
|
||||
$ecotax = isset($row['od_ecotax']) ? $row['od_ecotax'] : $row['ecotax'];
|
||||
$ecotaxRate = isset($row['od_ecotax_tax_rate']) ? $row['od_ecotax_tax_rate'] : $row['ecotax_tax_rate'];
|
||||
|
||||
$row['ecotax_tax_excl'] = $ecotax; // alias for coherence
|
||||
$row['ecotax_tax_incl'] = $ecotax * (100 + $ecotaxRate) / 100;
|
||||
$row['ecotax_tax'] = $row['ecotax_tax_incl'] - $row['ecotax_tax_excl'];
|
||||
|
||||
if ($round_mode == Order::ROUND_ITEM) {
|
||||
$row['ecotax_tax_incl'] = Tools::ps_round($row['ecotax_tax_incl'], Context::getContext()->getComputingPrecision(), $round_mode);
|
||||
}
|
||||
|
||||
$row['total_ecotax_tax_excl'] = $row['ecotax_tax_excl'] * $row['product_quantity'];
|
||||
$row['total_ecotax_tax_incl'] = $row['ecotax_tax_incl'] * $row['product_quantity'];
|
||||
|
||||
$row['total_ecotax_tax'] = $row['total_ecotax_tax_incl'] - $row['total_ecotax_tax_excl'];
|
||||
|
||||
foreach ([
|
||||
'ecotax_tax_excl',
|
||||
'ecotax_tax_incl',
|
||||
'ecotax_tax',
|
||||
'total_ecotax_tax_excl',
|
||||
'total_ecotax_tax_incl',
|
||||
'total_ecotax_tax',
|
||||
] as $ecotax_field) {
|
||||
$row[$ecotax_field] = Tools::ps_round($row[$ecotax_field], Context::getContext()->getComputingPrecision(), $round_mode);
|
||||
}
|
||||
|
||||
// Aliases
|
||||
$row['unit_price_tax_excl_including_ecotax'] = $row['unit_price_tax_excl'];
|
||||
$row['unit_price_tax_incl_including_ecotax'] = $row['unit_price_tax_incl'];
|
||||
$row['total_price_tax_excl_including_ecotax'] = $row['total_price_tax_excl'];
|
||||
$row['total_price_tax_incl_including_ecotax'] = $row['total_price_tax_incl'];
|
||||
|
||||
if ($customized_datas) {
|
||||
Product::addProductCustomizationPrice($row, $customized_datas);
|
||||
}
|
||||
/* Stock product */
|
||||
$result_array[(int) $row['id_order_detail']] = $row;
|
||||
}
|
||||
|
||||
return $result_array;
|
||||
}
|
||||
|
||||
protected function setProductCustomizedDatas(&$product, $customized_datas)
|
||||
{
|
||||
$product['customizedDatas'] = null;
|
||||
if (isset($customized_datas[$product['product_id']][$product['product_attribute_id']])) {
|
||||
$product['customizedDatas'] = $customized_datas[$product['product_id']][$product['product_attribute_id']];
|
||||
} else {
|
||||
$product['customizationQuantityTotal'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allow to add stock information on a product detail.
|
||||
*
|
||||
* @param array &$product
|
||||
*/
|
||||
protected function setProductCurrentStock(&$product)
|
||||
{
|
||||
if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')
|
||||
&& (int) $product['advanced_stock_management'] == 1
|
||||
&& (int) $product['id_warehouse'] > 0) {
|
||||
$product['current_stock'] = StockManagerFactory::getManager()->getProductPhysicalQuantities($product['product_id'], $product['product_attribute_id'], null, true);
|
||||
} else {
|
||||
$product['current_stock'] = '--';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allow to add image information on a product detail.
|
||||
*
|
||||
* @param array &$product
|
||||
*/
|
||||
protected function setProductImageInformations(&$product)
|
||||
{
|
||||
if (isset($product['product_attribute_id']) && $product['product_attribute_id']) {
|
||||
$id_image = Db::getInstance()->getValue('
|
||||
SELECT image_shop.id_image
|
||||
FROM ' . _DB_PREFIX_ . 'product_attribute_image pai' .
|
||||
Shop::addSqlAssociation('image', 'pai', true) . '
|
||||
WHERE id_product_attribute = ' . (int) $product['product_attribute_id']);
|
||||
}
|
||||
|
||||
if (!isset($id_image) || !$id_image) {
|
||||
$id_image = Db::getInstance()->getValue('
|
||||
SELECT image_shop.id_image
|
||||
FROM ' . _DB_PREFIX_ . 'image i' .
|
||||
Shop::addSqlAssociation('image', 'i', true, 'image_shop.cover=1') . '
|
||||
WHERE i.id_product = ' . (int) $product['product_id']);
|
||||
}
|
||||
|
||||
$product['image'] = null;
|
||||
$product['image_size'] = null;
|
||||
|
||||
if ($id_image) {
|
||||
$product['image'] = new Image($id_image);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns true if at least one order details uses the
|
||||
* One After Another tax computation method.
|
||||
*
|
||||
* @since 1.5
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function useOneAfterAnotherTaxComputationMethod()
|
||||
{
|
||||
// if one of the order details use the tax computation method the display will be different
|
||||
return Db::getInstance()->getValue('
|
||||
SELECT od.`tax_computation_method`
|
||||
FROM `' . _DB_PREFIX_ . 'order_detail_tax` odt
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'order_detail` od ON (od.`id_order_detail` = odt.`id_order_detail`)
|
||||
WHERE od.`id_order` = ' . (int) $this->id_order . '
|
||||
AND od.`id_order_invoice` = ' . (int) $this->id . '
|
||||
AND od.`tax_computation_method` = ' . (int) TaxCalculator::ONE_AFTER_ANOTHER_METHOD)
|
||||
|| Configuration::get(
|
||||
'PS_INVOICE_TAXES_BREAKDOWN'
|
||||
);
|
||||
}
|
||||
|
||||
public function displayTaxBasesInProductTaxesBreakdown()
|
||||
{
|
||||
return !$this->useOneAfterAnotherTaxComputationMethod();
|
||||
}
|
||||
|
||||
public function getOrder()
|
||||
{
|
||||
if (!$this->order) {
|
||||
$this->order = new Order($this->id_order);
|
||||
}
|
||||
|
||||
return $this->order;
|
||||
}
|
||||
|
||||
public function getProductTaxesBreakdown($order = null)
|
||||
{
|
||||
if (!$order) {
|
||||
$order = $this->getOrder();
|
||||
}
|
||||
|
||||
$sum_composite_taxes = !$this->useOneAfterAnotherTaxComputationMethod();
|
||||
|
||||
// $breakdown will be an array with tax rates as keys and at least the columns:
|
||||
// - 'total_price_tax_excl'
|
||||
// - 'total_amount'
|
||||
$breakdown = [];
|
||||
|
||||
$details = $order->getProductTaxesDetails();
|
||||
|
||||
if ($sum_composite_taxes) {
|
||||
$grouped_details = [];
|
||||
foreach ($details as $row) {
|
||||
if ($this->id !== (int) $row['id_order_invoice']) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($grouped_details[$row['id_order_detail']])) {
|
||||
$grouped_details[$row['id_order_detail']] = [
|
||||
'tax_rate' => 0,
|
||||
'total_tax_base' => 0,
|
||||
'total_amount' => 0,
|
||||
'id_tax' => $row['id_tax'],
|
||||
];
|
||||
}
|
||||
|
||||
$grouped_details[$row['id_order_detail']]['tax_rate'] += $row['tax_rate'];
|
||||
$grouped_details[$row['id_order_detail']]['total_tax_base'] += $row['total_tax_base'];
|
||||
$grouped_details[$row['id_order_detail']]['total_amount'] += $row['total_amount'];
|
||||
}
|
||||
|
||||
$details = $grouped_details;
|
||||
}
|
||||
|
||||
foreach ($details as $row) {
|
||||
$rate = sprintf('%.3f', $row['tax_rate']);
|
||||
if (!isset($breakdown[$rate])) {
|
||||
$breakdown[$rate] = [
|
||||
'total_price_tax_excl' => 0,
|
||||
'total_amount' => 0,
|
||||
'id_tax' => $row['id_tax'],
|
||||
'rate' => $rate,
|
||||
];
|
||||
}
|
||||
|
||||
$breakdown[$rate]['total_price_tax_excl'] += $row['total_tax_base'];
|
||||
$breakdown[$rate]['total_amount'] += $row['total_amount'];
|
||||
}
|
||||
|
||||
foreach ($breakdown as $rate => $data) {
|
||||
$breakdown[$rate]['total_price_tax_excl'] = Tools::ps_round($data['total_price_tax_excl'], Context::getContext()->getComputingPrecision(), $order->round_mode);
|
||||
$breakdown[$rate]['total_amount'] = Tools::ps_round($data['total_amount'], Context::getContext()->getComputingPrecision(), $order->round_mode);
|
||||
}
|
||||
|
||||
ksort($breakdown);
|
||||
|
||||
return $breakdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shipping taxes breakdown.
|
||||
*
|
||||
* @since 1.5
|
||||
*
|
||||
* @param Order $order
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getShippingTaxesBreakdown($order)
|
||||
{
|
||||
// No shipping breakdown if no shipping!
|
||||
if ($this->total_shipping_tax_excl == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// No shipping breakdown if it's free!
|
||||
foreach ($order->getCartRules() as $cart_rule) {
|
||||
if ($cart_rule['free_shipping']) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
$shipping_tax_amount = $this->total_shipping_tax_incl - $this->total_shipping_tax_excl;
|
||||
|
||||
if (Configuration::get('PS_INVOICE_TAXES_BREAKDOWN') || Configuration::get('PS_ATCP_SHIPWRAP')) {
|
||||
$shipping_breakdown = Db::getInstance()->executeS(
|
||||
'SELECT t.id_tax, t.rate, oit.amount as total_amount
|
||||
FROM `' . _DB_PREFIX_ . 'tax` t
|
||||
INNER JOIN `' . _DB_PREFIX_ . 'order_invoice_tax` oit ON oit.id_tax = t.id_tax
|
||||
WHERE oit.type = "shipping" AND oit.id_order_invoice = ' . (int) $this->id
|
||||
);
|
||||
|
||||
$sum_of_split_taxes = 0;
|
||||
$sum_of_tax_bases = 0;
|
||||
foreach ($shipping_breakdown as &$row) {
|
||||
if (Configuration::get('PS_ATCP_SHIPWRAP')) {
|
||||
$row['total_tax_excl'] = Tools::ps_round($row['total_amount'] / $row['rate'] * 100, Context::getContext()->getComputingPrecision(), $this->getOrder()->round_mode);
|
||||
$sum_of_tax_bases += $row['total_tax_excl'];
|
||||
} else {
|
||||
$row['total_tax_excl'] = $this->total_shipping_tax_excl;
|
||||
}
|
||||
|
||||
$row['total_amount'] = Tools::ps_round($row['total_amount'], Context::getContext()->getComputingPrecision(), $this->getOrder()->round_mode);
|
||||
$sum_of_split_taxes += $row['total_amount'];
|
||||
}
|
||||
unset($row);
|
||||
|
||||
$delta_amount = $shipping_tax_amount - $sum_of_split_taxes;
|
||||
|
||||
if ($delta_amount != 0) {
|
||||
Tools::spreadAmount($delta_amount, Context::getContext()->getComputingPrecision(), $shipping_breakdown, 'total_amount');
|
||||
}
|
||||
|
||||
$delta_base = $this->total_shipping_tax_excl - $sum_of_tax_bases;
|
||||
|
||||
if ($delta_base != 0) {
|
||||
Tools::spreadAmount($delta_base, Context::getContext()->getComputingPrecision(), $shipping_breakdown, 'total_tax_excl');
|
||||
}
|
||||
} else {
|
||||
$shipping_breakdown = [
|
||||
[
|
||||
'total_tax_excl' => $this->total_shipping_tax_excl,
|
||||
'rate' => $order->carrier_tax_rate,
|
||||
'total_amount' => $shipping_tax_amount,
|
||||
'id_tax' => null,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $shipping_breakdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the wrapping taxes breakdown.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getWrappingTaxesBreakdown()
|
||||
{
|
||||
if ($this->total_wrapping_tax_excl == 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$wrapping_tax_amount = $this->total_wrapping_tax_incl - $this->total_wrapping_tax_excl;
|
||||
|
||||
$wrapping_breakdown = Db::getInstance()->executeS(
|
||||
'SELECT t.id_tax, t.rate, oit.amount as total_amount
|
||||
FROM `' . _DB_PREFIX_ . 'tax` t
|
||||
INNER JOIN `' . _DB_PREFIX_ . 'order_invoice_tax` oit ON oit.id_tax = t.id_tax
|
||||
WHERE oit.type = "wrapping" AND oit.id_order_invoice = ' . (int) $this->id
|
||||
);
|
||||
|
||||
$sum_of_split_taxes = 0;
|
||||
$sum_of_tax_bases = 0;
|
||||
$total_tax_rate = 0;
|
||||
foreach ($wrapping_breakdown as &$row) {
|
||||
if (Configuration::get('PS_ATCP_SHIPWRAP')) {
|
||||
$row['total_tax_excl'] = Tools::ps_round($row['total_amount'] / $row['rate'] * 100, Context::getContext()->getComputingPrecision(), $this->getOrder()->round_mode);
|
||||
$sum_of_tax_bases += $row['total_tax_excl'];
|
||||
} else {
|
||||
$row['total_tax_excl'] = $this->total_wrapping_tax_excl;
|
||||
}
|
||||
|
||||
$row['total_amount'] = Tools::ps_round($row['total_amount'], Context::getContext()->getComputingPrecision(), $this->getOrder()->round_mode);
|
||||
$sum_of_split_taxes += $row['total_amount'];
|
||||
$total_tax_rate += (float) $row['rate'];
|
||||
}
|
||||
unset($row);
|
||||
|
||||
$delta_amount = $wrapping_tax_amount - $sum_of_split_taxes;
|
||||
|
||||
if ($delta_amount != 0) {
|
||||
Tools::spreadAmount($delta_amount, Context::getContext()->getComputingPrecision(), $wrapping_breakdown, 'total_amount');
|
||||
}
|
||||
|
||||
$delta_base = $this->total_wrapping_tax_excl - $sum_of_tax_bases;
|
||||
|
||||
if ($delta_base != 0) {
|
||||
Tools::spreadAmount($delta_base, Context::getContext()->getComputingPrecision(), $wrapping_breakdown, 'total_tax_excl');
|
||||
}
|
||||
|
||||
if (!Configuration::get('PS_INVOICE_TAXES_BREAKDOWN') && !Configuration::get('PS_ATCP_SHIPWRAP')) {
|
||||
$wrapping_breakdown = [
|
||||
[
|
||||
'total_tax_excl' => $this->total_wrapping_tax_excl,
|
||||
'rate' => $total_tax_rate,
|
||||
'total_amount' => $wrapping_tax_amount,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $wrapping_breakdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ecotax taxes breakdown.
|
||||
*
|
||||
* @since 1.5
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEcoTaxTaxesBreakdown()
|
||||
{
|
||||
$result = Db::getInstance()->executeS('
|
||||
SELECT `ecotax_tax_rate` as `rate`, SUM(`ecotax` * `product_quantity`) as `ecotax_tax_excl`, SUM(`ecotax` * `product_quantity`) as `ecotax_tax_incl`
|
||||
FROM `' . _DB_PREFIX_ . 'order_detail`
|
||||
WHERE `id_order` = ' . (int) $this->id_order . '
|
||||
AND `id_order_invoice` = ' . (int) $this->id . '
|
||||
GROUP BY `ecotax_tax_rate`');
|
||||
|
||||
$priceDisplayPrecision = Context::getContext()->getComputingPrecision();
|
||||
$taxes = [];
|
||||
foreach ($result as $row) {
|
||||
if ($row['ecotax_tax_excl'] > 0) {
|
||||
$row['ecotax_tax_incl'] = Tools::ps_round($row['ecotax_tax_excl'] + ($row['ecotax_tax_excl'] * $row['rate'] / 100), $priceDisplayPrecision);
|
||||
$row['ecotax_tax_excl'] = Tools::ps_round($row['ecotax_tax_excl'], $priceDisplayPrecision);
|
||||
$taxes[] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
return $taxes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the order invoice that match the date interval.
|
||||
*
|
||||
* @since 1.5
|
||||
*
|
||||
* @param $date_from
|
||||
* @param $date_to
|
||||
*
|
||||
* @return array collection of OrderInvoice
|
||||
*/
|
||||
public static function getByDateInterval($date_from, $date_to)
|
||||
{
|
||||
$order_invoice_list = Db::getInstance()->executeS('
|
||||
SELECT oi.*
|
||||
FROM `' . _DB_PREFIX_ . 'order_invoice` oi
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'orders` o ON (o.`id_order` = oi.`id_order`)
|
||||
WHERE DATE_ADD(oi.date_add, INTERVAL -1 DAY) <= \'' . pSQL($date_to) . '\'
|
||||
AND oi.date_add >= \'' . pSQL($date_from) . '\'
|
||||
' . Shop::addSqlRestriction(Shop::SHARE_ORDER, 'o') . '
|
||||
AND oi.number > 0
|
||||
ORDER BY oi.date_add ASC
|
||||
');
|
||||
|
||||
return ObjectModel::hydrateCollection('OrderInvoice', $order_invoice_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.5.0.3
|
||||
*
|
||||
* @param $id_order_state
|
||||
*
|
||||
* @return array collection of OrderInvoice
|
||||
*/
|
||||
public static function getByStatus($id_order_state)
|
||||
{
|
||||
$order_invoice_list = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT oi.*
|
||||
FROM `' . _DB_PREFIX_ . 'order_invoice` oi
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'orders` o ON (o.`id_order` = oi.`id_order`)
|
||||
WHERE ' . (int) $id_order_state . ' = o.current_state
|
||||
' . Shop::addSqlRestriction(Shop::SHARE_ORDER, 'o') . '
|
||||
AND oi.number > 0
|
||||
ORDER BY oi.`date_add` ASC
|
||||
');
|
||||
|
||||
return ObjectModel::hydrateCollection('OrderInvoice', $order_invoice_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.5.0.3
|
||||
*
|
||||
* @param $date_from
|
||||
* @param $date_to
|
||||
*
|
||||
* @return array collection of invoice
|
||||
*/
|
||||
public static function getByDeliveryDateInterval($date_from, $date_to)
|
||||
{
|
||||
$order_invoice_list = Db::getInstance()->executeS('
|
||||
SELECT oi.*
|
||||
FROM `' . _DB_PREFIX_ . 'order_invoice` oi
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'orders` o ON (o.`id_order` = oi.`id_order`)
|
||||
WHERE DATE_ADD(oi.delivery_date, INTERVAL -1 DAY) <= \'' . pSQL($date_to) . '\'
|
||||
AND oi.delivery_date >= \'' . pSQL($date_from) . '\'
|
||||
' . Shop::addSqlRestriction(Shop::SHARE_ORDER, 'o') . '
|
||||
ORDER BY oi.delivery_date ASC
|
||||
');
|
||||
|
||||
return ObjectModel::hydrateCollection('OrderInvoice', $order_invoice_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.5
|
||||
*
|
||||
* @param $id_order_invoice
|
||||
*/
|
||||
public static function getCarrier($id_order_invoice)
|
||||
{
|
||||
$carrier = false;
|
||||
if ($id_carrier = OrderInvoice::getCarrierId($id_order_invoice)) {
|
||||
$carrier = new Carrier((int) $id_carrier);
|
||||
}
|
||||
|
||||
return $carrier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.5
|
||||
*
|
||||
* @param $id_order_invoice
|
||||
*/
|
||||
public static function getCarrierId($id_order_invoice)
|
||||
{
|
||||
$sql = 'SELECT `id_carrier`
|
||||
FROM `' . _DB_PREFIX_ . 'order_carrier`
|
||||
WHERE `id_order_invoice` = ' . (int) $id_order_invoice;
|
||||
|
||||
return Db::getInstance()->getValue($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
*
|
||||
* @return OrderInvoice
|
||||
*
|
||||
* @throws PrestaShopException
|
||||
*/
|
||||
public static function retrieveOneById($id)
|
||||
{
|
||||
$order_invoice = new OrderInvoice($id);
|
||||
if (!Validate::isLoadedObject($order_invoice)) {
|
||||
throw new PrestaShopException('Can\'t load Order Invoice object for id: ' . $id);
|
||||
}
|
||||
|
||||
return $order_invoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Amounts of payments.
|
||||
*
|
||||
* @since 1.5.0.2
|
||||
*
|
||||
* @return float Total paid
|
||||
*/
|
||||
public function getTotalPaid()
|
||||
{
|
||||
$cache_id = 'order_invoice_paid_' . (int) $this->id;
|
||||
if (!Cache::isStored($cache_id)) {
|
||||
$amount = 0;
|
||||
$payments = OrderPayment::getByInvoiceId($this->id);
|
||||
foreach ($payments as $payment) {
|
||||
/* @var OrderPayment $payment */
|
||||
$amount += $payment->amount;
|
||||
}
|
||||
Cache::store($cache_id, $amount);
|
||||
|
||||
return $amount;
|
||||
}
|
||||
|
||||
return Cache::retrieve($cache_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest Paid.
|
||||
*
|
||||
* @since 1.5.0.2
|
||||
*
|
||||
* @return float Rest Paid
|
||||
*/
|
||||
public function getRestPaid()
|
||||
{
|
||||
if (!$this->number) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return round($this->total_paid_tax_incl + $this->getSiblingTotal() - $this->getTotalPaid(), 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return collection of order invoice object linked to the payments of the current order invoice object.
|
||||
*
|
||||
* @since 1.5.0.14
|
||||
*
|
||||
* @return PrestaShopCollection|array Collection of OrderInvoice or empty array
|
||||
*/
|
||||
public function getSibling()
|
||||
{
|
||||
$query = new DbQuery();
|
||||
$query->select('oip2.id_order_invoice');
|
||||
$query->from('order_invoice_payment', 'oip1');
|
||||
$query->innerJoin(
|
||||
'order_invoice_payment',
|
||||
'oip2',
|
||||
'oip2.id_order_payment = oip1.id_order_payment
|
||||
AND oip2.id_order_invoice <> oip1.id_order_invoice
|
||||
AND oip2.id_order = oip1.id_order'
|
||||
);
|
||||
$query->where('oip1.id_order_invoice = ' . (int) $this->id);
|
||||
|
||||
$invoices = Db::getInstance()->executeS($query);
|
||||
if (!$invoices) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$invoice_list = [];
|
||||
foreach ($invoices as $invoice) {
|
||||
$invoice_list[] = $invoice['id_order_invoice'];
|
||||
}
|
||||
|
||||
$payments = new PrestaShopCollection('OrderInvoice');
|
||||
$payments->where('id_order_invoice', 'IN', $invoice_list);
|
||||
|
||||
return $payments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return total to paid of sibling invoices.
|
||||
*
|
||||
* @param int $mod TAX_EXCL, TAX_INCL, DETAIL
|
||||
*
|
||||
* @return float
|
||||
*
|
||||
* @since 1.5.0.14
|
||||
*/
|
||||
public function getSiblingTotal($mod = OrderInvoice::TAX_INCL)
|
||||
{
|
||||
$query = new DbQuery();
|
||||
$query->select('SUM(oi.total_paid_tax_incl) as total_paid_tax_incl, SUM(oi.total_paid_tax_excl) as total_paid_tax_excl');
|
||||
$query->from('order_invoice_payment', 'oip1');
|
||||
$query->innerJoin(
|
||||
'order_invoice_payment',
|
||||
'oip2',
|
||||
'oip2.id_order_payment = oip1.id_order_payment
|
||||
AND oip2.id_order_invoice <> oip1.id_order_invoice
|
||||
AND oip2.id_order = oip1.id_order'
|
||||
);
|
||||
$query->leftJoin(
|
||||
'order_invoice',
|
||||
'oi',
|
||||
'oi.id_order_invoice = oip2.id_order_invoice'
|
||||
);
|
||||
$query->where('oip1.id_order_invoice = ' . (int) $this->id);
|
||||
|
||||
$row = Db::getInstance()->getRow($query);
|
||||
|
||||
switch ($mod) {
|
||||
case OrderInvoice::TAX_EXCL:
|
||||
return $row['total_paid_tax_excl'];
|
||||
case OrderInvoice::TAX_INCL:
|
||||
return $row['total_paid_tax_incl'];
|
||||
default:
|
||||
return $row;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get global rest to paid
|
||||
* This method will return something different of the method getRestPaid if
|
||||
* there is an other invoice linked to the payments of the current invoice.
|
||||
*
|
||||
* @since 1.5.0.13
|
||||
*/
|
||||
public function getGlobalRestPaid()
|
||||
{
|
||||
static $cache;
|
||||
|
||||
if (!isset($cache[$this->id])) {
|
||||
$res = Db::getInstance()->getRow('
|
||||
SELECT SUM(sub.paid) paid, SUM(sub.to_paid) to_paid
|
||||
FROM (
|
||||
SELECT
|
||||
op.amount as paid, SUM(oi.total_paid_tax_incl) to_paid
|
||||
FROM `' . _DB_PREFIX_ . 'order_invoice_payment` oip1
|
||||
INNER JOIN `' . _DB_PREFIX_ . 'order_invoice_payment` oip2
|
||||
ON oip2.id_order_payment = oip1.id_order_payment
|
||||
INNER JOIN `' . _DB_PREFIX_ . 'order_invoice` oi
|
||||
ON oi.id_order_invoice = oip2.id_order_invoice
|
||||
INNER JOIN `' . _DB_PREFIX_ . 'order_payment` op
|
||||
ON op.id_order_payment = oip2.id_order_payment
|
||||
WHERE oip1.id_order_invoice = ' . (int) $this->id . '
|
||||
GROUP BY op.id_order_payment
|
||||
) sub');
|
||||
$cache[$this->id] = round($res['to_paid'] - $res['paid'], 2);
|
||||
}
|
||||
|
||||
return $cache[$this->id];
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.5.0.2
|
||||
*
|
||||
* @return bool Is paid ?
|
||||
*/
|
||||
public function isPaid()
|
||||
{
|
||||
return $this->getTotalPaid() == $this->total_paid_tax_incl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 1.5.0.2
|
||||
*
|
||||
* @return PrestaShopCollection Collection of Order payment
|
||||
*/
|
||||
public function getOrderPaymentCollection()
|
||||
{
|
||||
return OrderPayment::getByInvoiceId($this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the formatted number of invoice.
|
||||
*
|
||||
* @since 1.5.0.2
|
||||
*
|
||||
* @param int $id_lang for invoice_prefix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getInvoiceNumberFormatted($id_lang, $id_shop = null)
|
||||
{
|
||||
$invoice_formatted_number = Hook::exec('actionInvoiceNumberFormatted', [
|
||||
get_class($this) => $this,
|
||||
'id_lang' => (int) $id_lang,
|
||||
'id_shop' => (int) $id_shop,
|
||||
'number' => (int) $this->number,
|
||||
]);
|
||||
|
||||
if (!empty($invoice_formatted_number)) {
|
||||
return $invoice_formatted_number;
|
||||
}
|
||||
|
||||
$format = '%1$s%2$06d';
|
||||
|
||||
if (Configuration::get('PS_INVOICE_USE_YEAR')) {
|
||||
$format = Configuration::get('PS_INVOICE_YEAR_POS') ? '%1$s%3$s/%2$06d' : '%1$s%2$06d/%3$s';
|
||||
}
|
||||
|
||||
return sprintf($format, Configuration::get('PS_INVOICE_PREFIX', (int) $id_lang, null, (int) $id_shop), $this->number, date('Y', strtotime($this->date_add)));
|
||||
}
|
||||
|
||||
public function saveCarrierTaxCalculator(array $taxes_amount)
|
||||
{
|
||||
$is_correct = true;
|
||||
foreach ($taxes_amount as $id_tax => $amount) {
|
||||
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'order_invoice_tax` (`id_order_invoice`, `type`, `id_tax`, `amount`)
|
||||
VALUES (' . (int) $this->id . ', \'shipping\', ' . (int) $id_tax . ', ' . (float) $amount . ')';
|
||||
|
||||
$is_correct &= Db::getInstance()->execute($sql);
|
||||
}
|
||||
|
||||
return $is_correct;
|
||||
}
|
||||
|
||||
public function saveWrappingTaxCalculator(array $taxes_amount)
|
||||
{
|
||||
$is_correct = true;
|
||||
foreach ($taxes_amount as $id_tax => $amount) {
|
||||
$sql = 'INSERT INTO `' . _DB_PREFIX_ . 'order_invoice_tax` (`id_order_invoice`, `type`, `id_tax`, `amount`)
|
||||
VALUES (' . (int) $this->id . ', \'wrapping\', ' . (int) $id_tax . ', ' . (float) $amount . ')';
|
||||
|
||||
$is_correct &= Db::getInstance()->execute($sql);
|
||||
}
|
||||
|
||||
return $is_correct;
|
||||
}
|
||||
|
||||
public static function getCurrentFormattedShopAddress($id_shop = null)
|
||||
{
|
||||
$address = new Address();
|
||||
$address->company = Configuration::get('PS_SHOP_NAME', null, null, $id_shop);
|
||||
$address->address1 = Configuration::get('PS_SHOP_ADDR1', null, null, $id_shop);
|
||||
$address->address2 = Configuration::get('PS_SHOP_ADDR2', null, null, $id_shop);
|
||||
$address->postcode = Configuration::get('PS_SHOP_CODE', null, null, $id_shop);
|
||||
$address->city = Configuration::get('PS_SHOP_CITY', null, null, $id_shop);
|
||||
$address->phone = Configuration::get('PS_SHOP_PHONE', null, null, $id_shop);
|
||||
$address->id_country = Configuration::get('PS_SHOP_COUNTRY_ID', null, null, $id_shop);
|
||||
|
||||
return AddressFormat::generateAddress($address, [], '<br />', ' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to fix shop addresses that cannot be fixed during upgrade process
|
||||
* (because uses the whole environnement of PS classes that is not available during upgrade).
|
||||
* This method should execute once on an upgraded PrestaShop to fix all OrderInvoices in one shot.
|
||||
* This method is triggered once during a (non bulk) creation of a PDF from an OrderInvoice that is not fixed yet.
|
||||
*
|
||||
* @since 1.6.1.1
|
||||
*/
|
||||
public static function fixAllShopAddresses()
|
||||
{
|
||||
$shop_ids = Shop::getShops(false, null, true);
|
||||
$db = Db::getInstance();
|
||||
foreach ($shop_ids as $id_shop) {
|
||||
$address = OrderInvoice::getCurrentFormattedShopAddress($id_shop);
|
||||
$escaped_address = $db->escape($address, true, true);
|
||||
|
||||
$db->execute('UPDATE `' . _DB_PREFIX_ . 'order_invoice` INNER JOIN `' . _DB_PREFIX_ . 'orders` USING (`id_order`)
|
||||
SET `shop_address` = \'' . $escaped_address . '\' WHERE `shop_address` IS NULL AND `id_shop` = ' . $id_shop);
|
||||
}
|
||||
}
|
||||
}
|
||||
69
classes/order/OrderMessage.php
Normal file
69
classes/order/OrderMessage.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class OrderMessageCore extends ObjectModel
|
||||
{
|
||||
/** @var array<string> Name */
|
||||
public $name;
|
||||
|
||||
/** @var array<string> Message content */
|
||||
public $message;
|
||||
|
||||
/** @var string Object creation date */
|
||||
public $date_add;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'order_message',
|
||||
'primary' => 'id_order_message',
|
||||
'multilang' => true,
|
||||
'fields' => [
|
||||
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
|
||||
/* Lang fields */
|
||||
'name' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128],
|
||||
'message' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isMessage', 'required' => true, 'size' => 1200],
|
||||
],
|
||||
];
|
||||
|
||||
protected $webserviceParameters = [
|
||||
'fields' => [
|
||||
'id' => ['sqlId' => 'id_discount_type', 'xlink_resource' => 'order_message_lang'],
|
||||
'date_add' => ['sqlId' => 'date_add'],
|
||||
],
|
||||
];
|
||||
|
||||
public static function getOrderMessages($id_lang)
|
||||
{
|
||||
return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT om.id_order_message, oml.name, oml.message
|
||||
FROM ' . _DB_PREFIX_ . 'order_message om
|
||||
LEFT JOIN ' . _DB_PREFIX_ . 'order_message_lang oml ON (oml.id_order_message = om.id_order_message)
|
||||
WHERE oml.id_lang = ' . (int) $id_lang . '
|
||||
ORDER BY name ASC');
|
||||
}
|
||||
}
|
||||
156
classes/order/OrderPayment.php
Normal file
156
classes/order/OrderPayment.php
Normal file
@@ -0,0 +1,156 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class OrderPaymentCore extends ObjectModel
|
||||
{
|
||||
public $order_reference;
|
||||
public $id_currency;
|
||||
public $amount;
|
||||
public $payment_method;
|
||||
public $conversion_rate;
|
||||
public $transaction_id;
|
||||
public $card_number;
|
||||
public $card_brand;
|
||||
public $card_expiration;
|
||||
public $card_holder;
|
||||
public $date_add;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'order_payment',
|
||||
'primary' => 'id_order_payment',
|
||||
'fields' => [
|
||||
'order_reference' => ['type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 9],
|
||||
'id_currency' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'amount' => ['type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true],
|
||||
'payment_method' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName'],
|
||||
'conversion_rate' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'transaction_id' => ['type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254],
|
||||
'card_number' => ['type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254],
|
||||
'card_brand' => ['type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254],
|
||||
'card_expiration' => ['type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254],
|
||||
'card_holder' => ['type' => self::TYPE_STRING, 'validate' => 'isAnything', 'size' => 254],
|
||||
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
],
|
||||
];
|
||||
|
||||
public function add($autodate = true, $nullValues = false)
|
||||
{
|
||||
if (parent::add($autodate, $nullValues)) {
|
||||
Hook::exec('actionPaymentCCAdd', ['paymentCC' => $this]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the detailed payment of an order.
|
||||
*
|
||||
* @deprecated 1.5.3.0
|
||||
*
|
||||
* @param int $id_order
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getByOrderId($id_order)
|
||||
{
|
||||
Tools::displayAsDeprecated();
|
||||
$order = new Order($id_order);
|
||||
|
||||
return OrderPayment::getByOrderReference($order->reference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the detailed payment of an order.
|
||||
*
|
||||
* @param int $order_reference
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 1.5.0.13
|
||||
*/
|
||||
public static function getByOrderReference($order_reference)
|
||||
{
|
||||
return ObjectModel::hydrateCollection(
|
||||
'OrderPayment',
|
||||
Db::getInstance()->executeS(
|
||||
'SELECT *
|
||||
FROM `' . _DB_PREFIX_ . 'order_payment`
|
||||
WHERE `order_reference` = \'' . pSQL($order_reference) . '\''
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Order Payments By Invoice ID.
|
||||
*
|
||||
* @param int $id_invoice Invoice ID
|
||||
*
|
||||
* @return PrestaShopCollection Collection of OrderPayment
|
||||
*/
|
||||
public static function getByInvoiceId($id_invoice)
|
||||
{
|
||||
$payments = Db::getInstance()->executeS('SELECT id_order_payment FROM `' . _DB_PREFIX_ . 'order_invoice_payment` WHERE id_order_invoice = ' . (int) $id_invoice);
|
||||
if (!$payments) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$payment_list = [];
|
||||
foreach ($payments as $payment) {
|
||||
$payment_list[] = $payment['id_order_payment'];
|
||||
}
|
||||
|
||||
$payments = new PrestaShopCollection('OrderPayment');
|
||||
$payments->where('id_order_payment', 'IN', $payment_list);
|
||||
|
||||
return $payments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return order invoice object linked to the payment.
|
||||
*
|
||||
* @param int $id_order Order Id
|
||||
*
|
||||
* @since 1.5.0.13
|
||||
*/
|
||||
public function getOrderInvoice($id_order)
|
||||
{
|
||||
$res = Db::getInstance()->getValue('
|
||||
SELECT id_order_invoice
|
||||
FROM `' . _DB_PREFIX_ . 'order_invoice_payment`
|
||||
WHERE id_order_payment = ' . (int) $this->id . '
|
||||
AND id_order = ' . (int) $id_order);
|
||||
|
||||
if (!$res) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return new OrderInvoice((int) $res);
|
||||
}
|
||||
}
|
||||
279
classes/order/OrderReturn.php
Normal file
279
classes/order/OrderReturn.php
Normal file
@@ -0,0 +1,279 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class OrderReturnCore extends ObjectModel
|
||||
{
|
||||
/** @var int */
|
||||
public $id;
|
||||
|
||||
/** @var int */
|
||||
public $id_customer;
|
||||
|
||||
/** @var int */
|
||||
public $id_order;
|
||||
|
||||
/** @var int */
|
||||
public $state;
|
||||
|
||||
/** @var string message content */
|
||||
public $question;
|
||||
|
||||
/** @var string Object creation date */
|
||||
public $date_add;
|
||||
|
||||
/** @var string Object last modification date */
|
||||
public $date_upd;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'order_return',
|
||||
'primary' => 'id_order_return',
|
||||
'fields' => [
|
||||
'id_customer' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'id_order' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'question' => ['type' => self::TYPE_HTML, 'validate' => 'isCleanHtml'],
|
||||
'state' => ['type' => self::TYPE_STRING],
|
||||
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
],
|
||||
];
|
||||
|
||||
public function addReturnDetail($order_detail_list, $product_qty_list, $customization_ids, $customization_qty_input)
|
||||
{
|
||||
/* Classic product return */
|
||||
if ($order_detail_list) {
|
||||
foreach ($order_detail_list as $key => $order_detail) {
|
||||
if ($qty = (int) $product_qty_list[$key]) {
|
||||
Db::getInstance()->insert('order_return_detail', ['id_order_return' => (int) $this->id, 'id_order_detail' => (int) $order_detail, 'product_quantity' => $qty, 'id_customization' => 0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Customized product return */
|
||||
if ($customization_ids) {
|
||||
foreach ($customization_ids as $order_detail_id => $customizations) {
|
||||
foreach ($customizations as $customization_id) {
|
||||
if ($quantity = (int) $customization_qty_input[(int) $customization_id]) {
|
||||
Db::getInstance()->insert('order_return_detail', ['id_order_return' => (int) $this->id, 'id_order_detail' => (int) $order_detail_id, 'product_quantity' => $quantity, 'id_customization' => (int) $customization_id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function checkEnoughProduct($order_detail_list, $product_qty_list, $customization_ids, $customization_qty_input)
|
||||
{
|
||||
$order = new Order((int) $this->id_order);
|
||||
if (!Validate::isLoadedObject($order)) {
|
||||
die(Tools::displayError());
|
||||
}
|
||||
$products = $order->getProducts();
|
||||
/* Products already returned */
|
||||
$order_return = OrderReturn::getOrdersReturn($order->id_customer, $order->id, true);
|
||||
foreach ($order_return as $or) {
|
||||
$order_return_products = OrderReturn::getOrdersReturnProducts($or['id_order_return'], $order);
|
||||
foreach ($order_return_products as $key => $orp) {
|
||||
$products[$key]['product_quantity'] -= (int) $orp['product_quantity'];
|
||||
}
|
||||
}
|
||||
/* Quantity check */
|
||||
if ($order_detail_list) {
|
||||
foreach (array_keys($order_detail_list) as $key) {
|
||||
if (!isset($product_qty_list[$key])) {
|
||||
return false;
|
||||
}
|
||||
if ($qty = (int) $product_qty_list[$key]) {
|
||||
if ($products[$key]['product_quantity'] - $qty < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Customization quantity check */
|
||||
if ($customization_ids) {
|
||||
$ordered_customizations = Customization::getOrderedCustomizations((int) $order->id_cart);
|
||||
foreach ($customization_ids as $customizations) {
|
||||
foreach ($customizations as $customization_id) {
|
||||
$customization_id = (int) $customization_id;
|
||||
if (!isset($ordered_customizations[$customization_id])) {
|
||||
return false;
|
||||
}
|
||||
$quantity = (isset($customization_qty_input[$customization_id]) ? (int) $customization_qty_input[$customization_id] : 0);
|
||||
if ((int) $ordered_customizations[$customization_id]['quantity'] - $quantity < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function countProduct()
|
||||
{
|
||||
if (!$data = Db::getInstance()->getRow('
|
||||
SELECT COUNT(`id_order_return`) AS total
|
||||
FROM `' . _DB_PREFIX_ . 'order_return_detail`
|
||||
WHERE `id_order_return` = ' . (int) $this->id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (int) ($data['total']);
|
||||
}
|
||||
|
||||
public static function getOrdersReturn($customer_id, $order_id = false, $no_denied = false, Context $context = null)
|
||||
{
|
||||
if (!$context) {
|
||||
$context = Context::getContext();
|
||||
}
|
||||
$data = Db::getInstance()->executeS('
|
||||
SELECT *
|
||||
FROM `' . _DB_PREFIX_ . 'order_return`
|
||||
WHERE `id_customer` = ' . (int) $customer_id .
|
||||
($order_id ? ' AND `id_order` = ' . (int) $order_id : '') .
|
||||
($no_denied ? ' AND `state` != 4' : '') . '
|
||||
ORDER BY `date_add` DESC');
|
||||
foreach ($data as $k => $or) {
|
||||
$state = new OrderReturnState($or['state']);
|
||||
$data[$k]['state_name'] = $state->name[$context->language->id];
|
||||
$data[$k]['type'] = 'Return';
|
||||
$data[$k]['tracking_number'] = $or['id_order_return'];
|
||||
$data[$k]['can_edit'] = false;
|
||||
$data[$k]['reference'] = Order::getUniqReferenceOf($or['id_order']);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public static function getOrdersReturnDetail($id_order_return)
|
||||
{
|
||||
return Db::getInstance()->executeS('
|
||||
SELECT *
|
||||
FROM `' . _DB_PREFIX_ . 'order_return_detail`
|
||||
WHERE `id_order_return` = ' . (int) $id_order_return);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $order_return_id
|
||||
* @param Order $order
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getOrdersReturnProducts($order_return_id, $order)
|
||||
{
|
||||
$products_ret = OrderReturn::getOrdersReturnDetail($order_return_id);
|
||||
$products = $order->getProducts();
|
||||
$tmp = [];
|
||||
foreach ($products_ret as $return_detail) {
|
||||
$tmp[$return_detail['id_order_detail']]['quantity'] = isset($tmp[$return_detail['id_order_detail']]['quantity']) ? $tmp[$return_detail['id_order_detail']]['quantity'] + (int) $return_detail['product_quantity'] : (int) $return_detail['product_quantity'];
|
||||
$tmp[$return_detail['id_order_detail']]['customizations'] = (int) $return_detail['id_customization'];
|
||||
}
|
||||
$res_tab = [];
|
||||
foreach ($products as $key => $product) {
|
||||
if (isset($tmp[$product['id_order_detail']])) {
|
||||
$res_tab[$key] = $product;
|
||||
$res_tab[$key]['product_quantity'] = $tmp[$product['id_order_detail']]['quantity'];
|
||||
$res_tab[$key]['customizations'] = $tmp[$product['id_order_detail']]['customizations'];
|
||||
}
|
||||
}
|
||||
|
||||
return $res_tab;
|
||||
}
|
||||
|
||||
public static function getReturnedCustomizedProducts($id_order)
|
||||
{
|
||||
$returns = Customization::getReturnedCustomizations($id_order);
|
||||
$order = new Order((int) $id_order);
|
||||
if (!Validate::isLoadedObject($order)) {
|
||||
die(Tools::displayError());
|
||||
}
|
||||
$products = $order->getProducts();
|
||||
|
||||
foreach ($returns as &$return) {
|
||||
$return['product_id'] = (int) $products[(int) $return['id_order_detail']]['product_id'];
|
||||
$return['product_attribute_id'] = (int) $products[(int) $return['id_order_detail']]['product_attribute_id'];
|
||||
$return['name'] = $products[(int) $return['id_order_detail']]['product_name'];
|
||||
$return['reference'] = $products[(int) $return['id_order_detail']]['product_reference'];
|
||||
$return['id_address_delivery'] = $products[(int) $return['id_order_detail']]['id_address_delivery'];
|
||||
}
|
||||
|
||||
return $returns;
|
||||
}
|
||||
|
||||
public static function deleteOrderReturnDetail($id_order_return, $id_order_detail, $id_customization = 0)
|
||||
{
|
||||
return Db::getInstance()->execute('DELETE FROM `' . _DB_PREFIX_ . 'order_return_detail` WHERE `id_order_detail` = ' . (int) $id_order_detail . ' AND `id_order_return` = ' . (int) $id_order_return . ' AND `id_customization` = ' . (int) $id_customization);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get return details for one product line.
|
||||
*
|
||||
* @param $id_order_detail
|
||||
*/
|
||||
public static function getProductReturnDetail($id_order_detail)
|
||||
{
|
||||
return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT product_quantity, date_add, orsl.name as state
|
||||
FROM `' . _DB_PREFIX_ . 'order_return_detail` ord
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'order_return` o
|
||||
ON o.id_order_return = ord.id_order_return
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'order_return_state_lang` orsl
|
||||
ON orsl.id_order_return_state = o.state AND orsl.id_lang = ' . (int) Context::getContext()->language->id . '
|
||||
WHERE ord.`id_order_detail` = ' . (int) $id_order_detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add returned quantity to products list.
|
||||
*
|
||||
* @param array $products
|
||||
* @param int $id_order
|
||||
*/
|
||||
public static function addReturnedQuantity(&$products, $id_order)
|
||||
{
|
||||
$details = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(
|
||||
'SELECT od.id_order_detail, GREATEST(od.product_quantity_return, IFNULL(SUM(ord.product_quantity),0)) as qty_returned
|
||||
FROM ' . _DB_PREFIX_ . 'order_detail od
|
||||
LEFT JOIN ' . _DB_PREFIX_ . 'order_return_detail ord
|
||||
ON ord.id_order_detail = od.id_order_detail
|
||||
WHERE od.id_order = ' . (int) $id_order . '
|
||||
GROUP BY od.id_order_detail'
|
||||
);
|
||||
if (!$details) {
|
||||
return;
|
||||
}
|
||||
|
||||
$detail_list = [];
|
||||
foreach ($details as $detail) {
|
||||
$detail_list[$detail['id_order_detail']] = $detail;
|
||||
}
|
||||
|
||||
foreach ($products as &$product) {
|
||||
if (isset($detail_list[$product['id_order_detail']]['qty_returned'])) {
|
||||
$product['qty_returned'] = $detail_list[$product['id_order_detail']]['qty_returned'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
64
classes/order/OrderReturnState.php
Normal file
64
classes/order/OrderReturnState.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class OrderReturnStateCore extends ObjectModel
|
||||
{
|
||||
/** @var array<string> Name */
|
||||
public $name;
|
||||
|
||||
/** @var string Display state in the specified color */
|
||||
public $color;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'order_return_state',
|
||||
'primary' => 'id_order_return_state',
|
||||
'multilang' => true,
|
||||
'fields' => [
|
||||
'color' => ['type' => self::TYPE_STRING, 'validate' => 'isColor'],
|
||||
|
||||
/* Lang fields */
|
||||
'name' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 64],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Get all available order statuses.
|
||||
*
|
||||
* @param int $id_lang Language id for status name
|
||||
*
|
||||
* @return array Order statuses
|
||||
*/
|
||||
public static function getOrderReturnStates($id_lang)
|
||||
{
|
||||
return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT *
|
||||
FROM `' . _DB_PREFIX_ . 'order_return_state` ors
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'order_return_state_lang` orsl ON (ors.`id_order_return_state` = orsl.`id_order_return_state` AND orsl.`id_lang` = ' . (int) $id_lang . ')
|
||||
ORDER BY ors.`id_order_return_state` ASC');
|
||||
}
|
||||
}
|
||||
572
classes/order/OrderSlip.php
Normal file
572
classes/order/OrderSlip.php
Normal file
@@ -0,0 +1,572 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class OrderSlipCore extends ObjectModel
|
||||
{
|
||||
/** @var int */
|
||||
public $id;
|
||||
|
||||
/** @var int */
|
||||
public $id_customer;
|
||||
|
||||
/** @var int */
|
||||
public $id_order;
|
||||
|
||||
/** @var float */
|
||||
public $conversion_rate;
|
||||
|
||||
/** @var float */
|
||||
public $total_products_tax_excl;
|
||||
|
||||
/** @var float */
|
||||
public $total_products_tax_incl;
|
||||
|
||||
/** @var float */
|
||||
public $total_shipping_tax_excl;
|
||||
|
||||
/** @var float */
|
||||
public $total_shipping_tax_incl;
|
||||
|
||||
/** @var int */
|
||||
public $amount;
|
||||
|
||||
/** @var int */
|
||||
public $shipping_cost;
|
||||
|
||||
/** @var int */
|
||||
public $shipping_cost_amount;
|
||||
|
||||
/** @var int */
|
||||
public $partial;
|
||||
|
||||
/** @var string Object creation date */
|
||||
public $date_add;
|
||||
|
||||
/** @var string Object last modification date */
|
||||
public $date_upd;
|
||||
|
||||
/** @var int */
|
||||
public $order_slip_type = 0;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'order_slip',
|
||||
'primary' => 'id_order_slip',
|
||||
'fields' => [
|
||||
'id_customer' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'id_order' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'conversion_rate' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true],
|
||||
'total_products_tax_excl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true],
|
||||
'total_products_tax_incl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true],
|
||||
'total_shipping_tax_excl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true],
|
||||
'total_shipping_tax_incl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat', 'required' => true],
|
||||
'amount' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'shipping_cost' => ['type' => self::TYPE_INT],
|
||||
'shipping_cost_amount' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'],
|
||||
'partial' => ['type' => self::TYPE_INT],
|
||||
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
'order_slip_type' => ['type' => self::TYPE_INT, 'validate' => 'isInt'],
|
||||
],
|
||||
];
|
||||
|
||||
protected $webserviceParameters = [
|
||||
'objectNodeName' => 'order_slip',
|
||||
'objectsNodeName' => 'order_slips',
|
||||
'fields' => [
|
||||
'id_customer' => ['xlink_resource' => 'customers'],
|
||||
'id_order' => ['xlink_resource' => 'orders'],
|
||||
],
|
||||
'associations' => [
|
||||
'order_slip_details' => ['resource' => 'order_slip_detail', 'setter' => false, 'virtual_entity' => true,
|
||||
'fields' => [
|
||||
'id' => [],
|
||||
'id_order_detail' => ['required' => true],
|
||||
'product_quantity' => ['required' => true],
|
||||
'amount_tax_excl' => ['required' => true],
|
||||
'amount_tax_incl' => ['required' => true],
|
||||
], ],
|
||||
],
|
||||
];
|
||||
|
||||
public function addSlipDetail($orderDetailList, $productQtyList)
|
||||
{
|
||||
foreach ($orderDetailList as $key => $id_order_detail) {
|
||||
if ($qty = (int) ($productQtyList[$key])) {
|
||||
$order_detail = new OrderDetail((int) $id_order_detail);
|
||||
|
||||
if (Validate::isLoadedObject($order_detail)) {
|
||||
Db::getInstance()->insert('order_slip_detail', [
|
||||
'id_order_slip' => (int) $this->id,
|
||||
'id_order_detail' => (int) $id_order_detail,
|
||||
'product_quantity' => $qty,
|
||||
'amount_tax_excl' => $order_detail->unit_price_tax_excl * $qty,
|
||||
'amount_tax_incl' => $order_detail->unit_price_tax_incl * $qty,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getOrdersSlip($customer_id, $order_id = false)
|
||||
{
|
||||
return Db::getInstance()->executeS('
|
||||
SELECT *
|
||||
FROM `' . _DB_PREFIX_ . 'order_slip`
|
||||
WHERE `id_customer` = ' . (int) ($customer_id) .
|
||||
($order_id ? ' AND `id_order` = ' . (int) ($order_id) : '') . '
|
||||
ORDER BY `date_add` DESC');
|
||||
}
|
||||
|
||||
public static function getOrdersSlipDetail($id_order_slip = false, $id_order_detail = false)
|
||||
{
|
||||
return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(
|
||||
($id_order_detail ? 'SELECT SUM(`product_quantity`) AS `total`' : 'SELECT *') .
|
||||
'FROM `' . _DB_PREFIX_ . 'order_slip_detail`'
|
||||
. ($id_order_slip ? ' WHERE `id_order_slip` = ' . (int) ($id_order_slip) : '')
|
||||
. ($id_order_detail ? ' WHERE `id_order_detail` = ' . (int) ($id_order_detail) : '')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $orderSlipId
|
||||
* @param Order $order
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getOrdersSlipProducts($orderSlipId, $order)
|
||||
{
|
||||
$productsRet = OrderSlip::getOrdersSlipDetail($orderSlipId);
|
||||
$order_details = $order->getProductsDetail();
|
||||
|
||||
$slip_quantity = [];
|
||||
foreach ($productsRet as $slip_detail) {
|
||||
$slip_quantity[$slip_detail['id_order_detail']] = $slip_detail;
|
||||
}
|
||||
|
||||
$products = [];
|
||||
foreach ($order_details as $key => $product) {
|
||||
if (isset($slip_quantity[$product['id_order_detail']]) && $slip_quantity[$product['id_order_detail']]['product_quantity']) {
|
||||
$products[$key] = $product;
|
||||
$products[$key] = array_merge($products[$key], $slip_quantity[$product['id_order_detail']]);
|
||||
}
|
||||
}
|
||||
|
||||
return $order->getProducts($products);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resume of all refund for one product line.
|
||||
*
|
||||
* @param $id_order_detail
|
||||
*
|
||||
* @deprecated This method should not be used any more because sometimes OrderSlip is not created, you should use the OrderDetail::total_refunded_tax_excl/incl fields instead
|
||||
*/
|
||||
public static function getProductSlipResume($id_order_detail)
|
||||
{
|
||||
return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
|
||||
SELECT SUM(product_quantity) product_quantity, SUM(amount_tax_excl) amount_tax_excl, SUM(amount_tax_incl) amount_tax_incl
|
||||
FROM `' . _DB_PREFIX_ . 'order_slip_detail`
|
||||
WHERE `id_order_detail` = ' . (int) $id_order_detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get resume of all shipping refund for one order.
|
||||
*
|
||||
* @param int $idOrder
|
||||
*/
|
||||
public static function getShippingSlipResume(int $idOrder)
|
||||
{
|
||||
return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow('
|
||||
SELECT
|
||||
SUM(total_shipping_tax_incl) total_shipping_tax_incl,
|
||||
SUM(total_shipping_tax_excl) total_shipping_tax_excl,
|
||||
SUM(shipping_cost_amount) shipping_cost_amount
|
||||
FROM `' . _DB_PREFIX_ . 'order_slip`
|
||||
WHERE `id_order` = ' . $idOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get refund details for one product line.
|
||||
*
|
||||
* @param $id_order_detail
|
||||
*/
|
||||
public static function getProductSlipDetail($id_order_detail)
|
||||
{
|
||||
return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT product_quantity, amount_tax_excl, amount_tax_incl, date_add
|
||||
FROM `' . _DB_PREFIX_ . 'order_slip_detail` osd
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'order_slip` os
|
||||
ON os.id_order_slip = osd.id_order_slip
|
||||
WHERE osd.`id_order_detail` = ' . (int) $id_order_detail);
|
||||
}
|
||||
|
||||
public function getProducts()
|
||||
{
|
||||
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT *, osd.product_quantity
|
||||
FROM `' . _DB_PREFIX_ . 'order_slip_detail` osd
|
||||
INNER JOIN `' . _DB_PREFIX_ . 'order_detail` od ON osd.id_order_detail = od.id_order_detail
|
||||
WHERE osd.`id_order_slip` = ' . (int) $this->id);
|
||||
|
||||
$order = new Order($this->id_order);
|
||||
$products = [];
|
||||
foreach ($result as $row) {
|
||||
$order->setProductPrices($row);
|
||||
$products[] = $row;
|
||||
}
|
||||
|
||||
return $products;
|
||||
}
|
||||
|
||||
public static function getSlipsIdByDate($dateFrom, $dateTo)
|
||||
{
|
||||
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT `id_order_slip`
|
||||
FROM `' . _DB_PREFIX_ . 'order_slip` os
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'orders` o ON (o.`id_order` = os.`id_order`)
|
||||
WHERE os.`date_add` BETWEEN \'' . pSQL($dateFrom) . ' 00:00:00\' AND \'' . pSQL($dateTo) . ' 23:59:59\'
|
||||
' . Shop::addSqlRestriction(Shop::SHARE_ORDER, 'o') . '
|
||||
ORDER BY os.`date_add` ASC');
|
||||
|
||||
$slips = [];
|
||||
foreach ($result as $slip) {
|
||||
$slips[] = (int) $slip['id_order_slip'];
|
||||
}
|
||||
|
||||
return $slips;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated since 1.6.0.10 use OrderSlip::create() instead
|
||||
*/
|
||||
public static function createOrderSlip($order, $productList, $qtyList, $shipping_cost = false)
|
||||
{
|
||||
Tools::displayAsDeprecated('Use OrderSlip::create() instead');
|
||||
|
||||
$product_list = [];
|
||||
foreach ($productList as $id_order_detail) {
|
||||
$order_detail = new OrderDetail((int) $id_order_detail);
|
||||
$product_list[$id_order_detail] = [
|
||||
'id_order_detail' => $id_order_detail,
|
||||
'quantity' => $qtyList[$id_order_detail],
|
||||
'unit_price' => $order_detail->unit_price_tax_excl,
|
||||
'amount' => $order_detail->unit_price_tax_incl * $qtyList[$id_order_detail],
|
||||
];
|
||||
|
||||
$shipping = $shipping_cost ? null : false;
|
||||
}
|
||||
|
||||
return OrderSlip::create($order, $product_list, $shipping);
|
||||
}
|
||||
|
||||
public static function create(Order $order, $product_list, $shipping_cost = false, $amount = 0, $amount_choosen = false, $add_tax = true)
|
||||
{
|
||||
$currency = new Currency((int) $order->id_currency);
|
||||
$order_slip = new OrderSlip();
|
||||
$order_slip->id_customer = (int) $order->id_customer;
|
||||
$order_slip->id_order = (int) $order->id;
|
||||
$order_slip->conversion_rate = $currency->conversion_rate;
|
||||
|
||||
if ($add_tax) {
|
||||
$add_or_remove = 'add';
|
||||
$inc_or_ex_1 = 'excl';
|
||||
$inc_or_ex_2 = 'incl';
|
||||
} else {
|
||||
$add_or_remove = 'remove';
|
||||
$inc_or_ex_1 = 'incl';
|
||||
$inc_or_ex_2 = 'excl';
|
||||
}
|
||||
|
||||
$order_slip->{'total_shipping_tax_' . $inc_or_ex_1} = 0;
|
||||
$order_slip->{'total_shipping_tax_' . $inc_or_ex_2} = 0;
|
||||
$order_slip->partial = 0;
|
||||
|
||||
if ($shipping_cost !== false) {
|
||||
$order_slip->shipping_cost = true;
|
||||
$carrier = new Carrier((int) $order->id_carrier);
|
||||
$address = Address::initialize($order->id_address_delivery, false);
|
||||
$tax_calculator = $carrier->getTaxCalculator($address);
|
||||
$order_slip->{'total_shipping_tax_' . $inc_or_ex_1} = ($shipping_cost === null ? $order->{'total_shipping_tax_' . $inc_or_ex_1} : (float) $shipping_cost);
|
||||
|
||||
if ($tax_calculator instanceof TaxCalculator) {
|
||||
$order_slip->{'total_shipping_tax_' . $inc_or_ex_2} = Tools::ps_round($tax_calculator->{$add_or_remove . 'Taxes'}($order_slip->{'total_shipping_tax_' . $inc_or_ex_1}), Context::getContext()->getComputingPrecision());
|
||||
} else {
|
||||
$order_slip->{'total_shipping_tax_' . $inc_or_ex_2} = $order_slip->{'total_shipping_tax_' . $inc_or_ex_1};
|
||||
}
|
||||
} else {
|
||||
$order_slip->shipping_cost = false;
|
||||
}
|
||||
|
||||
$order_slip->amount = 0;
|
||||
$order_slip->{'total_products_tax_' . $inc_or_ex_1} = 0;
|
||||
$order_slip->{'total_products_tax_' . $inc_or_ex_2} = 0;
|
||||
$total_products = [];
|
||||
foreach ($product_list as &$product) {
|
||||
$order_detail = new OrderDetail((int) $product['id_order_detail']);
|
||||
$price = (float) $product['unit_price'];
|
||||
$quantity = (int) $product['quantity'];
|
||||
$order_slip_resume = OrderSlip::getProductSlipResume((int) $order_detail->id);
|
||||
if ($quantity + $order_slip_resume['product_quantity'] > $order_detail->product_quantity) {
|
||||
$quantity = $order_detail->product_quantity - $order_slip_resume['product_quantity'];
|
||||
}
|
||||
|
||||
if ($quantity == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!Tools::isSubmit('cancelProduct') && $order->hasBeenPaid()) {
|
||||
$order_detail->product_quantity_refunded += $quantity;
|
||||
}
|
||||
|
||||
$order_detail->save();
|
||||
|
||||
$address = Address::initialize($order->id_address_invoice, false);
|
||||
$id_address = (int) $address->id;
|
||||
$id_tax_rules_group = (int) $order_detail->id_tax_rules_group;
|
||||
$tax_calculator = $order_detail->getTaxCalculator();
|
||||
|
||||
$order_slip->{'total_products_tax_' . $inc_or_ex_1} += $price * $quantity;
|
||||
|
||||
if (in_array(Configuration::get('PS_ROUND_TYPE'), [Order::ROUND_ITEM, Order::ROUND_LINE])) {
|
||||
if (!isset($total_products[$id_tax_rules_group])) {
|
||||
$total_products[$id_tax_rules_group] = 0;
|
||||
}
|
||||
} else {
|
||||
if (!isset($total_products[$id_tax_rules_group . '_' . $id_address])) {
|
||||
$total_products[$id_tax_rules_group . '_' . $id_address] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$product_tax_incl_line = Tools::ps_round($tax_calculator->{$add_or_remove . 'Taxes'}($price) * $quantity, Context::getContext()->getComputingPrecision());
|
||||
|
||||
switch (Configuration::get('PS_ROUND_TYPE')) {
|
||||
case Order::ROUND_ITEM:
|
||||
$product_tax_incl = Tools::ps_round($tax_calculator->{$add_or_remove . 'Taxes'}($price), Context::getContext()->getComputingPrecision()) * $quantity;
|
||||
$total_products[$id_tax_rules_group] += $product_tax_incl;
|
||||
|
||||
break;
|
||||
case Order::ROUND_LINE:
|
||||
$product_tax_incl = $product_tax_incl_line;
|
||||
$total_products[$id_tax_rules_group] += $product_tax_incl;
|
||||
|
||||
break;
|
||||
case Order::ROUND_TOTAL:
|
||||
$product_tax_incl = $product_tax_incl_line;
|
||||
$total_products[$id_tax_rules_group . '_' . $id_address] += $price * $quantity;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$product['unit_price_tax_' . $inc_or_ex_1] = $price;
|
||||
$product['unit_price_tax_' . $inc_or_ex_2] = Tools::ps_round($tax_calculator->{$add_or_remove . 'Taxes'}($price), Context::getContext()->getComputingPrecision());
|
||||
$product['total_price_tax_' . $inc_or_ex_1] = Tools::ps_round($price * $quantity, Context::getContext()->getComputingPrecision());
|
||||
$product['total_price_tax_' . $inc_or_ex_2] = Tools::ps_round($product_tax_incl, Context::getContext()->getComputingPrecision());
|
||||
}
|
||||
unset($product);
|
||||
|
||||
foreach ($total_products as $key => $price) {
|
||||
if (Configuration::get('PS_ROUND_TYPE') == Order::ROUND_TOTAL) {
|
||||
$tmp = explode('_', $key);
|
||||
$address = Address::initialize((int) $tmp[1], true);
|
||||
$tax_calculator = TaxManagerFactory::getManager($address, $tmp[0])->getTaxCalculator();
|
||||
$order_slip->{'total_products_tax_' . $inc_or_ex_2} += Tools::ps_round($tax_calculator->{$add_or_remove . 'Taxes'}($price), Context::getContext()->getComputingPrecision());
|
||||
} else {
|
||||
$order_slip->{'total_products_tax_' . $inc_or_ex_2} += $price;
|
||||
}
|
||||
}
|
||||
|
||||
$order_slip->{'total_products_tax_' . $inc_or_ex_2} -= (float) $amount && !$amount_choosen ? (float) $amount : 0;
|
||||
$order_slip->amount = $amount_choosen ? (float) $amount : $order_slip->{'total_products_tax_' . $inc_or_ex_1};
|
||||
$order_slip->shipping_cost_amount = $order_slip->total_shipping_tax_incl;
|
||||
|
||||
if ((float) $amount && !$amount_choosen) {
|
||||
$order_slip->order_slip_type = 1;
|
||||
}
|
||||
if (((float) $amount && $amount_choosen) || $order_slip->shipping_cost_amount > 0) {
|
||||
$order_slip->order_slip_type = 2;
|
||||
}
|
||||
|
||||
if (!$order_slip->add()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$res = true;
|
||||
|
||||
foreach ($product_list as $product) {
|
||||
$res &= $order_slip->addProductOrderSlip($product);
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
protected function addProductOrderSlip($product)
|
||||
{
|
||||
return Db::getInstance()->insert('order_slip_detail', [
|
||||
'id_order_slip' => (int) $this->id,
|
||||
'id_order_detail' => (int) $product['id_order_detail'],
|
||||
'product_quantity' => $product['quantity'],
|
||||
'unit_price_tax_excl' => $product['unit_price_tax_excl'],
|
||||
'unit_price_tax_incl' => $product['unit_price_tax_incl'],
|
||||
'total_price_tax_excl' => $product['total_price_tax_excl'],
|
||||
'total_price_tax_incl' => $product['total_price_tax_incl'],
|
||||
'amount_tax_excl' => $product['total_price_tax_excl'],
|
||||
'amount_tax_incl' => $product['total_price_tax_incl'],
|
||||
]);
|
||||
}
|
||||
|
||||
public static function createPartialOrderSlip($order, $amount, $shipping_cost_amount, $order_detail_list)
|
||||
{
|
||||
$currency = new Currency($order->id_currency);
|
||||
$orderSlip = new OrderSlip();
|
||||
$orderSlip->id_customer = (int) $order->id_customer;
|
||||
$orderSlip->id_order = (int) $order->id;
|
||||
$orderSlip->amount = (float) $amount;
|
||||
$orderSlip->shipping_cost = false;
|
||||
$orderSlip->shipping_cost_amount = (float) $shipping_cost_amount;
|
||||
$orderSlip->conversion_rate = $currency->conversion_rate;
|
||||
$orderSlip->partial = 1;
|
||||
if (!$orderSlip->add()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$orderSlip->addPartialSlipDetail($order_detail_list);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function addPartialSlipDetail($order_detail_list)
|
||||
{
|
||||
foreach ($order_detail_list as $id_order_detail => $tab) {
|
||||
$order_detail = new OrderDetail($id_order_detail);
|
||||
$order_slip_resume = OrderSlip::getProductSlipResume($id_order_detail);
|
||||
|
||||
if ($tab['amount'] + $order_slip_resume['amount_tax_incl'] > $order_detail->total_price_tax_incl) {
|
||||
$tab['amount'] = $order_detail->total_price_tax_incl - $order_slip_resume['amount_tax_incl'];
|
||||
}
|
||||
|
||||
if ($tab['amount'] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($tab['quantity'] + $order_slip_resume['product_quantity'] > $order_detail->product_quantity) {
|
||||
$tab['quantity'] = $order_detail->product_quantity - $order_slip_resume['product_quantity'];
|
||||
}
|
||||
|
||||
$tab['amount_tax_excl'] = $tab['amount_tax_incl'] = $tab['amount'];
|
||||
|
||||
$id_tax = (int) Db::getInstance()->getValue(
|
||||
'SELECT `id_tax`
|
||||
FROM `' . _DB_PREFIX_ . 'order_detail_tax`
|
||||
WHERE `id_order_detail` = ' . (int) $id_order_detail
|
||||
);
|
||||
|
||||
if ($id_tax > 0) {
|
||||
$rate = (float) Db::getInstance()->getValue(
|
||||
'SELECT `rate`
|
||||
FROM `' . _DB_PREFIX_ . 'tax`
|
||||
WHERE `id_tax` = ' . (int) $id_tax
|
||||
);
|
||||
|
||||
if ($rate > 0) {
|
||||
$rate = 1 + ($rate / 100);
|
||||
$tab['amount_tax_excl'] = $tab['amount_tax_excl'] / $rate;
|
||||
}
|
||||
}
|
||||
|
||||
if ($tab['quantity'] > 0 && $tab['quantity'] > $order_detail->product_quantity_refunded) {
|
||||
$order_detail->product_quantity_refunded = $tab['quantity'];
|
||||
$order_detail->save();
|
||||
}
|
||||
|
||||
$insert_order_slip = [
|
||||
'id_order_slip' => (int) $this->id,
|
||||
'id_order_detail' => (int) $id_order_detail,
|
||||
'product_quantity' => (int) $tab['quantity'],
|
||||
'amount_tax_excl' => (float) $tab['amount_tax_excl'],
|
||||
'amount_tax_incl' => (float) $tab['amount_tax_incl'],
|
||||
];
|
||||
|
||||
Db::getInstance()->insert('order_slip_detail', $insert_order_slip);
|
||||
}
|
||||
}
|
||||
|
||||
public function getEcoTaxTaxesBreakdown()
|
||||
{
|
||||
$ecotax_detail = [];
|
||||
foreach ($this->getOrdersSlipDetail((int) $this->id) as $order_slip_details) {
|
||||
$row = Db::getInstance()->getRow(
|
||||
'SELECT `ecotax_tax_rate` as `rate`, `ecotax` as `ecotax_tax_excl`, `ecotax` as `ecotax_tax_incl`, `product_quantity`
|
||||
FROM `' . _DB_PREFIX_ . 'order_detail`
|
||||
WHERE `id_order_detail` = ' . (int) $order_slip_details['id_order_detail']
|
||||
);
|
||||
|
||||
if (!isset($ecotax_detail[$row['rate']])) {
|
||||
$ecotax_detail[$row['rate']] = ['ecotax_tax_incl' => 0, 'ecotax_tax_excl' => 0, 'rate' => $row['rate']];
|
||||
}
|
||||
|
||||
$ecotax_detail[$row['rate']]['ecotax_tax_incl'] += Tools::ps_round(
|
||||
($row['ecotax_tax_excl'] * $order_slip_details['product_quantity']) + ($row['ecotax_tax_excl'] * $order_slip_details['product_quantity'] * $row['rate'] / 100),
|
||||
Context::getContext()->getComputingPrecision()
|
||||
);
|
||||
$ecotax_detail[$row['rate']]['ecotax_tax_excl'] += Tools::ps_round(
|
||||
$row['ecotax_tax_excl'] * $order_slip_details['product_quantity'],
|
||||
Context::getContext()->getComputingPrecision()
|
||||
);
|
||||
}
|
||||
|
||||
return $ecotax_detail;
|
||||
}
|
||||
|
||||
public function getWsOrderSlipDetails()
|
||||
{
|
||||
$query = 'SELECT id_order_slip as id, id_order_detail, product_quantity, amount_tax_excl, amount_tax_incl
|
||||
FROM `' . _DB_PREFIX_ . 'order_slip_detail`
|
||||
WHERE id_order_slip = ' . (int) $this->id;
|
||||
$result = Db::getInstance()->executeS($query);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function setWsOrderSlipDetails($values)
|
||||
{
|
||||
if (Db::getInstance()->execute('DELETE from `' . _DB_PREFIX_ . 'order_slip_detail` where id_order_slip = ' . (int) $this->id)) {
|
||||
$query = 'INSERT INTO `' . _DB_PREFIX_ . 'order_slip_detail`(`id_order_slip`, `id_order_detail`, `product_quantity`, `amount_tax_excl`, `amount_tax_incl`) VALUES ';
|
||||
|
||||
foreach ($values as $value) {
|
||||
$query .= '(' . (int) $this->id . ', ' . (int) $value['id_order_detail'] . ', ' . (int) $value['product_quantity'] . ', ' .
|
||||
(isset($value['amount_tax_excl']) ? (float) $value['amount_tax_excl'] : 'NULL') . ', ' .
|
||||
(isset($value['amount_tax_incl']) ? (float) $value['amount_tax_incl'] : 'NULL') .
|
||||
'),';
|
||||
}
|
||||
$query = rtrim($query, ',');
|
||||
Db::getInstance()->execute($query);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
187
classes/order/OrderState.php
Normal file
187
classes/order/OrderState.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
class OrderStateCore extends ObjectModel
|
||||
{
|
||||
/** @var array<string> Name */
|
||||
public $name;
|
||||
|
||||
/** @var array<string> Template name if there is any e-mail to send */
|
||||
public $template;
|
||||
|
||||
/** @var bool Send an e-mail to customer ? */
|
||||
public $send_email;
|
||||
|
||||
public $module_name;
|
||||
|
||||
/** @var bool Allow customer to view and download invoice when order is at this state */
|
||||
public $invoice;
|
||||
|
||||
/** @var string Display state in the specified color */
|
||||
public $color;
|
||||
|
||||
public $unremovable;
|
||||
|
||||
/** @var bool Log authorization */
|
||||
public $logable;
|
||||
|
||||
/** @var bool Delivery */
|
||||
public $delivery;
|
||||
|
||||
/** @var bool Hidden */
|
||||
public $hidden;
|
||||
|
||||
/** @var bool Shipped */
|
||||
public $shipped;
|
||||
|
||||
/** @var bool Paid */
|
||||
public $paid;
|
||||
|
||||
/** @var bool Attach PDF Invoice */
|
||||
public $pdf_invoice;
|
||||
|
||||
/** @var bool Attach PDF Delivery Slip */
|
||||
public $pdf_delivery;
|
||||
|
||||
/** @var bool True if carrier has been deleted (staying in database as deleted) */
|
||||
public $deleted = 0;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'order_state',
|
||||
'primary' => 'id_order_state',
|
||||
'multilang' => true,
|
||||
'fields' => [
|
||||
'send_email' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'module_name' => ['type' => self::TYPE_STRING, 'validate' => 'isModuleName'],
|
||||
'invoice' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'color' => ['type' => self::TYPE_STRING, 'validate' => 'isColor'],
|
||||
'logable' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'shipped' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'unremovable' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'delivery' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'hidden' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'paid' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'pdf_delivery' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'pdf_invoice' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
'deleted' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
|
||||
/* Lang fields */
|
||||
'name' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 64],
|
||||
'template' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isTplName', 'size' => 64],
|
||||
],
|
||||
];
|
||||
|
||||
protected $webserviceParameters = [
|
||||
'fields' => [
|
||||
'unremovable' => [],
|
||||
'delivery' => [],
|
||||
'hidden' => [],
|
||||
],
|
||||
];
|
||||
|
||||
const FLAG_NO_HIDDEN = 1; /* 00001 */
|
||||
const FLAG_LOGABLE = 2; /* 00010 */
|
||||
const FLAG_DELIVERY = 4; /* 00100 */
|
||||
const FLAG_SHIPPED = 8; /* 01000 */
|
||||
const FLAG_PAID = 16; /* 10000 */
|
||||
|
||||
/**
|
||||
* Get all available order statuses.
|
||||
*
|
||||
* @param int $id_lang Language id for status name
|
||||
* @param bool $getDeletedStates
|
||||
*
|
||||
* @return array Order statuses
|
||||
*/
|
||||
public static function getOrderStates($id_lang, $filterDeleted = true)
|
||||
{
|
||||
$deletedStates = $filterDeleted ? ' WHERE deleted = 0' : '';
|
||||
$cache_id = 'OrderState::getOrderStates_' . (int) $id_lang;
|
||||
$cache_id .= $filterDeleted ? '_filterDeleted' : '';
|
||||
|
||||
if (!Cache::isStored($cache_id)) {
|
||||
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT *
|
||||
FROM `' . _DB_PREFIX_ . 'order_state` os
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = ' . (int) $id_lang . ')'
|
||||
. $deletedStates . ' ORDER BY `name` ASC');
|
||||
Cache::store($cache_id, $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
return Cache::retrieve($cache_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we can make a invoice when order is in this state.
|
||||
*
|
||||
* @param int $id_order_state State ID
|
||||
*
|
||||
* @return bool availability
|
||||
*/
|
||||
public static function invoiceAvailable($id_order_state)
|
||||
{
|
||||
$result = false;
|
||||
if (Configuration::get('PS_INVOICE')) {
|
||||
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('
|
||||
SELECT `invoice`
|
||||
FROM `' . _DB_PREFIX_ . 'order_state`
|
||||
WHERE `id_order_state` = ' . (int) $id_order_state);
|
||||
}
|
||||
|
||||
return (bool) $result;
|
||||
}
|
||||
|
||||
public function isRemovable()
|
||||
{
|
||||
return !($this->unremovable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a localized name in database for a specific lang (and excluding some IDs)
|
||||
*
|
||||
* @param string $name
|
||||
* @param int $idLang
|
||||
* @param int|null $excludeIdOrderState ID of the order state excluded for the search
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function existsLocalizedNameInDatabase(string $name, int $idLang, ?int $excludeIdOrderState): bool
|
||||
{
|
||||
return (bool) DB::getInstance(_PS_USE_SQL_SLAVE_)->getValue(
|
||||
'SELECT COUNT(*) AS count' .
|
||||
' FROM ' . _DB_PREFIX_ . 'order_state_lang osl' .
|
||||
' INNER JOIN ' . _DB_PREFIX_ . 'order_state os ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = ' . $idLang . ')' .
|
||||
' WHERE osl.id_lang = ' . $idLang .
|
||||
' AND osl.name = \'' . pSQL($name) . '\'' .
|
||||
' AND os.deleted = 0' .
|
||||
($excludeIdOrderState ? ' AND osl.id_order_state != ' . $excludeIdOrderState : '')
|
||||
);
|
||||
}
|
||||
}
|
||||
34
classes/order/index.php
Normal file
34
classes/order/index.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright since 2007 PrestaShop SA and Contributors
|
||||
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Open Software License (OSL 3.0)
|
||||
* that is bundled with this package in the file LICENSE.md.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/OSL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* DISCLAIMER
|
||||
*
|
||||
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
|
||||
* versions in the future. If you wish to customize PrestaShop for your
|
||||
* needs please refer to https://devdocs.prestashop.com/ for more information.
|
||||
*
|
||||
* @author PrestaShop SA and Contributors <contact@prestashop.com>
|
||||
* @copyright Since 2007 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
|
||||
*/
|
||||
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
header('Location: ../../');
|
||||
exit;
|
||||
Reference in New Issue
Block a user