From d902a38ec89ff672ec7f3fbc9d82e4d5313a8e00 Mon Sep 17 00:00:00 2001 From: dMetzger Date: Wed, 23 Nov 2011 17:45:52 +0000 Subject: [PATCH] [+] BO : add new feature, Order edition --- admin-dev/pdf.php | 26 +- .../template/orders/_customized_data.tpl | 1 + .../themes/template/orders/_new_product.tpl | 49 + .../template/orders/_print_pdf_icon.tpl | 43 + .../themes/template/orders/_product_line.tpl | 56 +- admin-dev/themes/template/orders/form.tpl | 6 +- admin-dev/themes/template/orders/view.tpl | 1199 ++++++++++------- classes/AdminController.php | 3 +- classes/Cart.php | 159 +-- classes/CartRule.php | 87 +- classes/Currency.php | 18 +- classes/PaymentCC.php | 22 +- classes/PaymentModule.php | 121 +- classes/Product.php | 3 +- classes/order/Order.php | 239 +++- classes/order/OrderDetail.php | 62 +- classes/order/OrderInvoice.php | 387 ++++++ classes/order/OrderPayment.php | 99 ++ classes/order/OrderReturn.php | 5 +- classes/order/OrderSlip.php | 1 + classes/pdf/HTMLTemplateInvoice.php | 26 +- controllers/admin/AdminOrdersController.php | 745 ++++++++-- controllers/admin/AdminProductsController.php | 3 +- install-dev/sql/db.sql | 48 +- install-dev/sql/db_settings_extends.sql | 6 + install-dev/sql/upgrade/1.5.0.1.sql | 48 +- js/admin_order.js | 621 +++++++++ js/tools.js | 52 + themes/prestashop/order-detail.tpl | 28 + themes/prestashop/pdf/invoice.tax-tab.tpl | 2 +- themes/prestashop/pdf/invoice.tpl | 30 +- 31 files changed, 3349 insertions(+), 846 deletions(-) create mode 100644 admin-dev/themes/template/orders/_new_product.tpl create mode 100644 admin-dev/themes/template/orders/_print_pdf_icon.tpl create mode 100644 classes/order/OrderInvoice.php create mode 100644 classes/order/OrderPayment.php create mode 100644 js/admin_order.js diff --git a/admin-dev/pdf.php b/admin-dev/pdf.php index c20a7ba32..4bc9a6dc4 100644 --- a/admin-dev/pdf.php +++ b/admin-dev/pdf.php @@ -66,13 +66,31 @@ function generateSupplyOrderFormPDF() function generateInvoicePDF() { - if (!isset($_GET['id_order'])) - die (Tools::displayError('Missing order ID')); - $order = new Order((int)($_GET['id_order'])); + if (Tools::isSubmit('id_order')) + generateInvoicePDFByIdOrder(Tools::getValue('id_order')); + elseif (Tools::isSubmit('id_order_invoice')) + generateInvoicePDFByIdOrderInvoice(Tools::getValue('id_order_invoice')); + else + die (Tools::displayError('Missing order ID or invoice order ID')); + exit; +} + +function generateInvoicePDFByIdOrder($id_order) +{ + $order = new Order($id_order); if (!Validate::isLoadedObject($order)) die(Tools::displayError('Cannot find order in database')); - generatePDF($order, PDF::TEMPLATE_INVOICE); + generatePDF($order->getInvoicesCollection(), PDF::TEMPLATE_INVOICE); +} + +function generateInvoicePDFByIdOrderInvoice($id_order_invoice) +{ + $order_invoice = new OrderInvoice($id_order_invoice); + if (!Validate::isLoadedObject($order_invoice)) + die(Tools::displayError('Cannot find order invoice in database')); + + generatePDF($order_invoice, PDF::TEMPLATE_INVOICE); } function generateOrderSlipPDF() diff --git a/admin-dev/themes/template/orders/_customized_data.tpl b/admin-dev/themes/template/orders/_customized_data.tpl index 682b71db0..a3dd0e43d 100755 --- a/admin-dev/themes/template/orders/_customized_data.tpl +++ b/admin-dev/themes/template/orders/_customized_data.tpl @@ -47,6 +47,7 @@ {/if} -- + -- {foreach from=$product.customizedDatas key=customizationId item=customization} diff --git a/admin-dev/themes/template/orders/_new_product.tpl b/admin-dev/themes/template/orders/_new_product.tpl new file mode 100644 index 000000000..6a35b8c22 --- /dev/null +++ b/admin-dev/themes/template/orders/_new_product.tpl @@ -0,0 +1,49 @@ + + + + {l s='Product:'} + + + + {if $currency->sign % 2}{$currency->sign}{/if} {if !($currency->sign % 2)}{$currency->sign}{/if} {l s='tax excl.'}
+ {if $currency->sign % 2}{$currency->sign}{/if} {if !($currency->sign % 2)}{$currency->sign}{/if} {l s='tax incl.'}
+ + + {if ($order->hasBeenPaid())} {/if} + {if ($order->hasBeenDelivered())} {/if} + 0 + {displayPrice price=0 currency=$currency->id} + + {if $order->valid} + + {/if} + + + + + + + +

{l s='New invoice informations'}

+ +
+ {$carrier->name} +
+
+ + +

{l s='If you don\'t select the "Free shipping", the normal shipping cost will be applied'}

+
+ + \ No newline at end of file diff --git a/admin-dev/themes/template/orders/_print_pdf_icon.tpl b/admin-dev/themes/template/orders/_print_pdf_icon.tpl new file mode 100644 index 000000000..0c8c8741a --- /dev/null +++ b/admin-dev/themes/template/orders/_print_pdf_icon.tpl @@ -0,0 +1,43 @@ +{* +* 2007-2011 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* 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 http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision: 10336 $ +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*} + +{* Generate HTML code for printing Invoice Icon with link *} + +{if (($order_state->invoice && $order->invoice_number) && $tr['product_number'])} + invoice +{else} + - +{/if} + + +{* Generate HTML code for printing Delivery Icon with link *} + +{if ($order_state->delivery && $order->delivery_number)} + delivery +{else} + - +{/if} + \ No newline at end of file diff --git a/admin-dev/themes/template/orders/_product_line.tpl b/admin-dev/themes/template/orders/_product_line.tpl index 1e002c260..e43c1bc13 100755 --- a/admin-dev/themes/template/orders/_product_line.tpl +++ b/admin-dev/themes/template/orders/_product_line.tpl @@ -26,9 +26,9 @@ {* Assign product price *} {if ($order->getTaxCalculationMethod() == $smarty.const.PS_TAX_EXC)} - {assign var=product_price value=($product['product_price'] + $product['ecotax'])} + {assign var=product_price value=($product['unit_price_tax_excl'] + $product['ecotax'])} {else} - {assign var=product_price value=$product['product_price_wt']} + {assign var=product_price value=$product['unit_price_tax_incl']} {/if} {if ($product['product_quantity'] > $product['customizationQuantityTotal'])} @@ -39,13 +39,31 @@ {if $product.product_reference}{l s='Ref:'} {$product.product_reference}
{/if} {if $product.product_supplier_reference}{l s='Ref Supplier:'} {$product.product_supplier_reference}{/if} - {displayPrice price=$product_price currency=$currency->id} - 1)}style="font-weight:700;font-size:1.1em;color:red"{/if}>{$product['product_quantity']} + + {displayPrice price=$product_price currency=$currency->id} + {if $can_edit} + + {/if} + + + {$product['product_quantity']} + {if $can_edit} + + {/if} + {if ($order->hasBeenPaid())}{$product['product_quantity_refunded']}{/if} {if ($order->hasBeenDelivered())}{$product['product_quantity_return']}{/if} - {StockManagerFactory::getManager()->getProductRealQuantities($product['product_id'], $product['product_attribute_id'], null, true)} - {displayPrice price=(Tools::ps_round($product_price, 2) * ($product['product_quantity'] - $product['customizationQuantityTotal'])) currency=$currency->id} - + {StockManagerFactory::getManager()->getProductRealQuantities($product['product_id'], $product['product_attribute_id'], null, true)} + + {displayPrice price=(Tools::ps_round($product_price, 2) * ($product['product_quantity'] - $product['customizationQuantityTotal'])) currency=$currency->id} + + @@ -55,7 +73,7 @@ -- {/if} - + {if ($product['product_quantity_return'] + $product['product_quantity_refunded'] >= $product['product_quantity'])} {elseif (!$order->hasBeenDelivered() OR Configuration::get('PS_ORDER_RETURN'))} @@ -76,5 +94,25 @@ 0/{$productQuantity} {/if} + € + {if $can_edit} + + {if $order->hasBeenPaid()} + + {else} +   + {/if} + + + {l s='Edit'} + + + {l s='Delete'} + + {/if} -{/if} \ No newline at end of file +{/if} diff --git a/admin-dev/themes/template/orders/form.tpl b/admin-dev/themes/template/orders/form.tpl index f0ae1f128..b32deb917 100755 --- a/admin-dev/themes/template/orders/form.tpl +++ b/admin-dev/themes/template/orders/form.tpl @@ -467,10 +467,10 @@ products_found += ''; $.each(this.combinations, function() { - attributes_html += ''; + attributes_html += ''; }); attributes_html += ''; }); @@ -508,7 +508,7 @@ var cart_content = ''; $.each(products, function() { cart_quantity[this.id_product+'_'+this.id_product_attribute] = this.cart_quantity; - cart_content += ''+this.name+'
'+this.attributes_small+''+this.reference+' '; + cart_content += ''+this.name+'
'+this.attributes_small+''+this.reference+' '; cart_content += '

'; cart_content += '

'; cart_content += '

'; diff --git a/admin-dev/themes/template/orders/view.tpl b/admin-dev/themes/template/orders/view.tpl index d864bb4fa..6d2699af8 100755 --- a/admin-dev/themes/template/orders/view.tpl +++ b/admin-dev/themes/template/orders/view.tpl @@ -24,482 +24,779 @@ * International Registered Trademark & Property of PrestaShop SA *} - +{extends file="helper/view/view.tpl"} -{if ($order->total_paid != $order->total_paid_real)} -
{l s='Warning:'} {displayPrice price=$order->total_paid_real currency=$currency->id} {l s='paid instead of'} {displayPrice price=$order->total_paid currency=$currency->id} !


-{/if} +{block name="override_tpl"} + + + {if ($HOOK_INVOICE)} +
{$HOOK_INVOICE}

'; {/if} - - - {if ($currentState->delivery || $order->delivery_number)} - {l s='View delivery slip'} {l s='View delivery slip'} - {else} - {l s='No delivery slip'} {l s='No delivery slip'} - {/if} - - - {l s='Print order'} {l s='Print order'} - -
 
- -{foreach from=$history item=row key=key} - {if ($key == 0)} - - - - - - - {else} - - - - - - - {/if} -{/foreach} -
{dateFormat date=$row['date_add'] full=true}{$row['ostate_name']|stripslashes}{if $row['employee_lastname']}{$row['employee_firstname']|stripslashes} {$row['employee_lastname']|stripslashes}{/if}
{dateFormat date=$row['date_add'] full=true}{$row['ostate_name']|stripslashes}{if $row['employee_lastname']}{$row['employee_firstname']|stripslashes} {$row['employee_lastname']|stripslashes}{/if}
-
- -
- - - - -
- -{if $customer->id} -
-
- {l s='Customer information'} - {$customer->firstname} {$customer->lastname} ({l s='#'}{$customer->id})
- ({$customer->email})

- {if ($customer->isGuest())} - {l s='This order has been placed by a'} {l s='guest'} - {if (!Customer::customerExists($customer->email))} -
- -

- {l s='This feature will generate a random password and send an e-mail to the customer'} -
- {else} -
{l s='A registered customer account exists with the same email address'}
- {/if} - {else} - {l s='Account registered:'} {dateFormat date=$customer->date_add full=true}
- {l s='Valid orders placed:'} {$customerStats['nb_orders']}
- {l s='Total paid since registration:'} {displayPrice price=Tools::ps_round(Tools::convertPrice($customerStats['total_orders'], $currency), 2) currency=$currency->id}
-
- {/if} -{/if} - -{if (sizeof($sources))} -
-
- {l s='Sources'} - -
-{/if} - -{if $HOOK_ADMIN_ORDER} - {$HOOK_ADMIN_ORDER} -{/if} - - -
-
- {if (($currentState->invoice OR $order->invoice_number) AND count($products))} - {l s='Invoice'} - {l s='Invoice #'}{Configuration::get('PS_INVOICE_PREFIX', $id_lang)}{"%06d"|sprintf:$order->invoice_number} -
{l s='Created on:'} {dateFormat date=$order->invoice_date full=true} - {else} - {l s='Invoice'} - {l s='No invoice yet.'} - {/if} -
-
- -
- {l s='Shipping information'} - {l s='Total weight:'} {$order->getTotalWeight()|string_format:"%.3f"} {Configuration::get('PS_WEIGHT_UNIT')}
- {l s='Carrier:'} {if $carrier->name == '0'}{Configuration::get('PS_SHOP_NAME')}{else}{$carrier->name}{/if}
- - {if ($currentState->delivery || $order->delivery_number)} -
{l s='Delivery slip #'}{Configuration::get('PS_DELIVERY_PREFIX', $id_lang)}{"%06d"|sprintf:$order->delivery_number}
- {/if} - - {if $order->shipping_number} - {l s='Tracking number:'} {$order->shipping_number} - {if $carrier->url} - {l s='Track the shipment'} +
+
+ {if (count($invoices_collection))} + {l s='View invoice'} {l s='View invoice'} + {else} + {l s='No invoice'} {l s='No invoice'} {/if} - {/if} + - + {if ($currentState->delivery || $order->delivery_number)} + {l s='View delivery slip'} {l s='View delivery slip'} + {else} + {l s='No delivery slip'} {l s='No delivery slip'} + {/if} + - + {l s='Print order'} {l s='Print order'} +
+
+
    +
  • {l s='Date'}: {dateFormat date=$order->date_add full=true} |
  • +
  • {sizeof($messages)} {if (sizeof($messages) > 1)}{l s='messages'}{else}{l s='message'}{/if} |
  • +
  • {sizeof($products)} {if (sizeof($products) > 1)}{l s='products'}{else}{l s='product'}{/if} |
  • +
  • {l s='Total'}: {displayPrice price=$order->total_paid_tax_incl currency=$currency->id}
  • +
+
+
+
- {if $carrierModuleCall} - {$carrierModuleCall} - {/if} - - {if ($carrier->url && $order->hasBeenShipped())} -
- + +
+ + + + - + - {/if} -
+
-
-
- - - {l s='Payment detail'} - -
    -
  • -
    - {l s='Set the transaction id:'} - - - -
    -
  • - {if $paymentCCDetails} - {if $paymentCCDetails['card_holder'] != ''} -
  • - {l s='Card Holder:'} - {$paymentCCDetails['card_holder']} -
  • - {/if} - {if $paymentCCDetails['card_number'] != ''} -
  • - {l s='Card Number:'} - ****{$paymentCCDetails['card_number']|substr:-4} -
  • - {/if} - {if $paymentCCDetails['card_brand'] != ''} -
  • - {l s='Card Brand:'} - {$paymentCCDetails['card_brand']} -
  • - {/if} - {if $paymentCCDetails['card_expiration'] != ''} -
  • - {l s='Card expiration:'} - {$paymentCCDetails['card_expiration']} -
  • - {/if} - {/if} -
-
- -
-
- {l s='Order details'} - {if (Shop::isFeatureActive())} - -
{Shop::getInstance($order->id_shop)->name}
- {/if} - - -
{l s='Cart #'}{"%06d"|sprintf:$cart->id}
- -
{substr($order->payment, 0, 32)}{if $order->module} ({$order->module}){/if}
-
- - - - - - {if $order->total_discounts > 0} - - - - - {/if} - {if $order->total_wrapping > 0} - - - - - {/if} - - - - - - - - -
{l s='Products'}{displayPrice price=$order->getTotalProductsWithTaxes() currency=$currency->id}
{l s='Discounts'}-{displayPrice price=$order->total_discounts currency=$currency->id}
{l s='Wrapping'}{displayPrice price=$order->total_wrapping currency=$currency->id}
{l s='Shipping'}{displayPrice price=$order->total_shipping currency=$currency->id}
{l s='Total'} - {displayPrice price=$order->total_paid currency=$currency->id} - {if $order->total_paid != $order->total_paid_real} -
- {l s='Paid:'} {displayPrice price=$order->total_paid_real currency=$currency->id} - {/if} -
-
-
- {l s='Recycled package:'} - {if $order->recyclable} - + + + {foreach from=$history item=row key=key} + {if ($key == 0)} + + + + + + {else} - + + + + + + {/if} - -
- {l s='Gift wrapping:'} - {if $order->gift} - -
-
- {if $order->gift_message} -
{l s='Message:'}
{$order->gift_message|nl2br}
- {/if} - {else} - - {/if} -
- - -
 
+ {/foreach} +
{dateFormat date=$row['date_add'] full=true}{$row['ostate_name']|stripslashes}{if $row['employee_lastname']}{$row['employee_firstname']|stripslashes} {$row['employee_lastname']|stripslashes}{/if}
{dateFormat date=$row['date_add'] full=true}{$row['ostate_name']|stripslashes}{if $row['employee_lastname']}{$row['employee_firstname']|stripslashes} {$row['employee_lastname']|stripslashes}{/if}
-
 
-
-
- {l s='Shipping address'}{l s='Shipping address'} -
- - -
- {displayAddressDetail address=$addresses.delivery newLine='
'} - {if $addresses.delivery->other}
{$addresses.delivery->other}
{/if} -
-
-
-
- {l s='Invoice address'}{l s='Invoice address'} -
- {displayAddressDetail address=$addresses.invoice newLine='
'} - {if $addresses.invoice->other}
{$addresses.invoice->other}
{/if} -
-
-
 
- -
- -
- {l s='Products'}{l s='Products'} -
- - - - - - - {if ($order->hasBeenPaid())}{/if} - {if ($order->hasBeenDelivered())}{/if} - - - - - - {foreach from=$products item=product key=k} - {* Include customized datas partial *} - {include file='orders/_customized_data.tpl'} - - {* Include product line partial *} - {include file='orders/_product_line.tpl'} - {/foreach} -
 {l s='Product'}{l s='UP'} *{l s='Qty'}{l s='Refunded'}{l s='Returned'}{l s='Stock'}{l s='Total'} *{l s='Products'} - {if ($order->hasBeenDelivered())} - {l s='Return'} - {elseif ($order->hasBeenPaid())} - {l s='Refund'} - {else} - {l s='Cancel'} - {/if} -
- -
- * {l s='According to the group of this customer, prices are printed:'} - {if ($order->getTaxCalculationMethod() == $smarty.const.PS_TAX_EXC)} - {l s='tax excluded.'} + {if $customer->id} + +
+
+ {l s='Customer information'} + {$customer->firstname} {$customer->lastname} ({l s='#'}{$customer->id})
+ ({$customer->email})

+ {if ($customer->isGuest())} + {l s='This order has been placed by a'} {l s='guest'} + {if (!Customer::customerExists($customer->email))} + + +

+ {l s='This feature will generate a random password and send an e-mail to the customer'} + {else} - {l s='tax included.'} +
{l s='A registered customer account exists with the same email address'}
{/if} + {else} + {l s='Account registered:'} {dateFormat date=$customer->date_add full=true}
+ {l s='Valid orders placed:'} {$customerStats['nb_orders']}
+ {l s='Total paid since registration:'} {displayPrice price=Tools::ps_round(Tools::convertPrice($customerStats['total_orders'], $currency), 2) currency=$currency->id}
+
+ {/if} + {/if} - {if Configuration::get('PS_ORDER_RETURN')} -

{l s='Merchandise returns are disabled'} + + {if (sizeof($sources))} +
+
+ {l s='Sources'} + +
+ {/if} + + + {if $HOOK_ADMIN_ORDER} + {$HOOK_ADMIN_ORDER} + {/if} +
+ + + +
+ +
+ {l s='Documents'} + + + + + + + + + + + {foreach from=$order->getDocuments() item=document} + + + + + + {foreachelse} + + + + {/foreach} + +
DateDocumentNumber
{dateFormat date=$document->date_add}Invoice#{Configuration::get('PS_INVOICE_PREFIX', $current_id_lang)}{'%06d'|sprintf:$document->number}
{l s='No document is available'}
+
+
+ + +
+ {l s='Payment'} + + {if !$order->valid} +
+

{l s='Don\'t forget to update your conversion rate before make this change.'}

+ + + +
+
+ {/if} + +

+ {l s='Warning:'} {displayPrice price=$total_paid currency=$currency->id} + {l s='paid instead of'} {displayPrice price=$order->total_paid_tax_incl currency=$currency->id} +

+ +
+ + + + + + + + + + + + {foreach from=$order->getOrderPaymentCollection() item=payment} + + + + + + + + {/foreach} + + + + + + + + +
{l s='Date'}{l s='Payment method'}{l s='Transaction ID'}{l s='Amount'} 
{dateFormat date=$payment->date_add full=true}{$payment->payment_method}{displayPrice price=$payment->amount currency=$payment->id_currency}{$payment->transaction_id}
+ + + + + + +
+
+
+
+ + +
+ {l s='Shipping'} + +
+ {l s='Recycled package:'} + {if $order->recyclable} + + {else} + {/if}
+
+ {l s='Gift wrapping:'} + {if $order->gift} + +
+
+ {if $order->gift_message} +
{l s='Message:'}
{$order->gift_message|nl2br}
+ {/if} + {else} + + {/if} +
+
- {if (sizeof($discounts))} -
- +
+ - - + + + + + + - {foreach from=$discounts item=discount} + + + {foreach from=$order->getShipping() item=line} - - + + + + + {/foreach} + +
{l s='Discounts'}{l s='Discount name'}{l s='Value'}{l s='Date:'}{l s='Type'}{l s='Carrier'}{l s='Weight'}{l s='Shipping cost'}{l s='Tracking number'}
{$discount['name']} - {if $discount['value'] != 0.00} - - - {/if} - {displayPrice price=$discount['value'] currency=$currency->id} + {$line.date_add}{$line.type}{$line.state_name}{$line.weight|string_format:"%.3f"} {Configuration::get('PS_WEIGHT_UNIT')}{if $order->getTaxCalculationMethod() == $smarty.const.PS_TAX_INC}{displayPrice price=$line.shipping_cost_tax_incl currency=$currency->id}{else}{displayPrice price=$line.shipping_cost_tax_excl currency=$currency->id}{/if} + {if $line.url && $line.tracking_number}{$line.tracking_number}{else}{$line.tracking_number}{/if} + {if $line.can_edit} +
+ + {l s='Edit'} + +
+ {/if}
+ + {if $carrierModuleCall} + {$carrierModuleCall} + {/if} +
+ + +
+ {l s='Merchandise returns'} + + {if $order->getReturn()|count > 0} + + + + + + + + + + + {foreach from=$order->getReturn() item=line} + + + + + + + {/foreach} + +
DateTypeCarrierTracking number
{$line.date_add}{$line.type}{$line.state_name} + {if $line.url && $line.tracking_number}{$line.tracking_number}{else}{$line.tracking_number}{/if} + {if $line.can_edit} +
+ + {l s='Edit'} + +
+ {/if} +
+ {else} + {l s='No merchandise returns yet.'} + {/if} + + {if $carrierModuleCall} + {$carrierModuleCall} + {/if} +
+
+ +
+ + +
+ +
+ {l s='Shipping address'}{l s='Shipping address'} + + {if $can_edit} +
+
+

+ + +

+
+
+ {/if} + +
+ + +
+ + {displayAddressDetail address=$addresses.delivery newLine='
'} + {if $addresses.delivery->other}
{$addresses.delivery->other}
{/if} +
+
+ +
+ +
+ {l s='Invoice address'}{l s='Invoice address'} + + {if $can_edit} +
+
+

+ + +

+
+
+ {/if} + +
+ +
+ + {displayAddressDetail address=$addresses.invoice newLine='
'} + {if $addresses.invoice->other}
{$addresses.invoice->other}
{/if} +
+
+
+ +
+ +
+ {l s='Products'}{l s='Products'} +
+ {if $can_edit} + +
+ +
+

+ {/if} + + + + + + + {if ($order->hasBeenPaid())}{/if} + {if ($order->hasBeenDelivered())}{/if} + + + + + + + + {foreach from=$products item=product key=k} + {* Include customized datas partial *} + {include file='orders/_customized_data.tpl'} + + {* Include product line partial *} + {include file='orders/_product_line.tpl'} + {/foreach} + {if $can_edit} + {include file='orders/_new_product.tpl'} + {/if} +
 {l s='Product'}{l s='UP'} *{l s='Qty'}{l s='Refunded'}{l s='Returned'}{l s='Stock'}{l s='Total'} * + {l s='Action'} +
+ +
+ * {l s='According to the group of this customer, prices are printed:'} + {if ($order->getTaxCalculationMethod() == $smarty.const.PS_TAX_EXC)} + {l s='tax excluded.'} + {else} + {l s='tax included.'} + {/if} + + {if Configuration::get('PS_ORDER_RETURN')} +

{l s='Merchandise returns are disabled'} + {/if} +
+ +
+ + + + + + total_discounts_tax_incl == 0}style="display: none;"{/if}> + + + + total_wrapping_tax_incl == 0}style="display: none;"{/if}> + + + + + + + + + + + +
{l s='Products'}{displayPrice price=$order->total_products_wt currency=$currency->id}
{l s='Discounts'}-{displayPrice price=$order->total_discounts_tax_incl currency=$currency->id}
{l s='Wrapping'}{displayPrice price=$order->total_wrapping_tax_incl currency=$currency->id}
{l s='Shipping'}{displayPrice price=$order->total_shipping_tax_incl currency=$currency->id}
{l s='Total'} + {displayPrice price=$order->total_paid_tax_incl currency=$currency->id} +
+
+
+ + {if (sizeof($discounts))} +
+ + + + + + {foreach from=$discounts item=discount} + + + + + {/foreach} +
{l s='Discounts'}{l s='Discount name'}{l s='Value'}
{$discount['name']} + {if $discount['value'] != 0.00} + - + {/if} + {displayPrice price=$discount['value'] currency=$currency->id} +
+
+ {/if} +
+ +
 
+ + +
+
+
 
+ +
+
+
+ {l s='New message'} + +
+

+ {l s='Display to consumer?'} + {l s='Yes'} + {l s='No'} +



+

+ + + +
+
+
+ + {if (sizeof($messages))} +
+
+ {l s='Messages'} + {foreach from=$messages item=message} +
+ {if ($message['is_new_for_me'])} + + {/if} + {l s='At'} {dateFormat date=$message['date_add']} + {l s='from'} {if ($message['elastname'])}{$message['efirstname']} {$message['elastname']}{else}{$message['cfirstname']} {$message['clastname']}{/if} + {if ($message['private'] == 1)}{l s='Private:'}{/if} +

{$message['message']|nl2br}

+
+
+ {/foreach} +

{l s='When you read a message, please click on the green check.'}

+
+ {/if} +
+ +
+
+ {l s='Credit slip'}{l s='Credit slip'} + {if (!sizeof($slips))} + {l s='No slip for this order.'} + {else} + {foreach from=$slips item=slip} + ({dateFormat date=$slip['date_upd']}) : {l s='#'}{'%06d'|sprintf:$slip['id_order_slip']}
+ {/foreach} + {/if} +
+
+
 
+

{l s='Back to list'}
+ + + + + + + +{/block} diff --git a/classes/AdminController.php b/classes/AdminController.php index 45c0a4e4b..51a09b676 100644 --- a/classes/AdminController.php +++ b/classes/AdminController.php @@ -918,6 +918,8 @@ class AdminControllerCore extends Controller 'desc' => $this->l('Save') ); break; + case 'view': + break; default: // list $this->toolbar_btn['new'] = array( 'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token, @@ -1849,7 +1851,6 @@ class AdminControllerCore extends Controller if (empty($order_by)) $order_by = $this->context->cookie->__get($this->table.'Orderby') ? $this->context->cookie->__get($this->table.'Orderby') : $this->_defaultOrderBy; - if (empty($order_way)) $order_way = $this->context->cookie->__get($this->table.'Orderway') ? $this->context->cookie->__get($this->table.'Orderway') : 'ASC'; diff --git a/classes/Cart.php b/classes/Cart.php index 346af8696..3aed25870 100644 --- a/classes/Cart.php +++ b/classes/Cart.php @@ -75,9 +75,9 @@ class CartCore extends ObjectModel public $checkedTos = false; public $pictures; public $textFields; - + public $delivery_option; - + /** @var boolean Allow to seperate order in multiple package in order to recieve as soon as possible the available products */ public $allow_seperated_package = false; @@ -257,6 +257,7 @@ class CartCore extends ObjectModel /** * @deprecated 1.5.0.1 + * @see Cart::getCartRules() */ public function getDiscounts($lite = false, $refresh = false) { @@ -691,7 +692,7 @@ class CartCore extends ObjectModel $context = Context::getContext()->cloneContext(); $context->cart = $this; CartRule::autoAddToCart($context); - + if ($product->customizable) return $this->_updateCustomizationQuantity((int)$quantity, (int)$id_customization, (int)$id_product, (int)$id_product_attribute, $operator); else @@ -983,7 +984,7 @@ class CartCore extends ObjectModel return 0; if ($virtual AND $type == Cart::BOTH) $type = Cart::BOTH_WITHOUT_SHIPPING; - + if ($type != Cart::BOTH_WITHOUT_SHIPPING AND $type != Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING) { if (is_null($products) && is_null($id_carrier)) @@ -993,13 +994,13 @@ class CartCore extends ObjectModel } else $shipping_fees = 0; - + if ($type == Cart::ONLY_PRODUCTS_WITHOUT_SHIPPING) $type = Cart::ONLY_PRODUCTS; if (is_null($products)) $products = $this->getProducts(); - + $order_total = 0; if (Tax::excludeTaxeOption()) $withTaxes = false; @@ -1068,10 +1069,10 @@ class CartCore extends ObjectModel return $order_total_discount; return Tools::ps_round((float)$order_total, 2); } - + /** * Get products grouped by package and by addresses to be sent individualy (one package = one shipping cost). - * + * * @return array array( * 0 => array( // First address * 0 => array( // First package @@ -1095,15 +1096,15 @@ class CartCore extends ObjectModel { if (!isset($warehouse_count_by_address[$product['id_address_delivery']])) $warehouse_count_by_address[$product['id_address_delivery']] = array(); - + $product['warehouse_list'] = array(); - + $warehouse_list = Warehouse::getProductWarehouseList($product['id_product'], $product['id_product_attribute']); // Does the product is in stock ? // If yes, get only warehouse where the product is in stock $warehouse_in_stock = array(); $manager = StockManagerFactory::getManager(); - + foreach ($warehouse_list as $key => $warehouse) { if ($manager->getProductRealQuantities( @@ -1121,7 +1122,7 @@ class CartCore extends ObjectModel } else $product['in_stock'] = false; - + foreach ($warehouse_list as $warehouse) { if (!isset($warehouse_carrier_list[$warehouse['id_warehouse']])) @@ -1129,21 +1130,21 @@ class CartCore extends ObjectModel $warehouse_object = new Warehouse($warehouse['id_warehouse']); $warehouse_carrier_list[$warehouse['id_warehouse']] = $warehouse_object->getCarriers(); } - + $product['warehouse_list'][] = $warehouse['id_warehouse']; if (!isset($warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']])) $warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']] = 0; $warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']]++; } } - + // If product from the cart are not in any warehouse, return false //foreach ($warehouse_count_by_address as $warehouse_count) // if (empty($warehouse_count)) // return false; - + arsort($warehouse_count_by_address); - + // Step 2 : Group product by warehouse $grouped_by_warehouse = array(); foreach ($product_list as &$product) @@ -1153,32 +1154,32 @@ class CartCore extends ObjectModel 'in_stock' => array(), 'out_of_stock' => array(), ); - + // Determine the warehouse to use for this product in order to reduce the number of package $id_warehouse = 0; foreach ($warehouse_count_by_address[$product['id_address_delivery']] as $id_warehouse) if (in_array($id_warehouse, $product['warehouse_list'])) break; - + if (!isset($grouped_by_warehouse[$product['id_address_delivery']]['in_stock'][$id_warehouse])) { $grouped_by_warehouse[$product['id_address_delivery']]['in_stock'][$id_warehouse] = array(); $grouped_by_warehouse[$product['id_address_delivery']]['out_of_stock'][$id_warehouse] = array(); } - + if (!$this->allow_seperated_package) $key = 'in_stock'; else $key = ($product['in_stock']) ? 'in_stock' : 'out_of_stock'; - + $product['carrier_list'] = Carrier::getAvailableCarrierList($product, $id_warehouse); - + if (empty($product['carrier_list'])) $product['carrier_list'] = array(0); - + $grouped_by_warehouse[$product['id_address_delivery']][$key][$id_warehouse][] = $product; } - + // Step 3 : grouped product from grouped_by_warehouse by available carriers $grouped_by_carriers = array(); foreach ($grouped_by_warehouse as $id_address_delivery => $products_in_stock_list) @@ -1188,7 +1189,7 @@ class CartCore extends ObjectModel 'in_stock' => array(), 'out_of_stock' => array(), ); - + foreach ($products_in_stock_list as $key => $warehouse_list) { if (!isset($grouped_by_carriers[$id_address_delivery][$key])) @@ -1197,23 +1198,23 @@ class CartCore extends ObjectModel { if (!isset($grouped_by_carriers[$id_address_delivery][$key][$id_warehouse])) $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse] = array(); - + foreach ($product_list as $product) { $package_carriers_key = implode(',', $product['carrier_list']); - + if (!isset($grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key])) $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key] = array( 'product_list' => array(), 'carrier_list' => $product['carrier_list'] ); - + $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key]['product_list'][] = $product; } } } } - + $package_list = array(); // Step 4 : merge product from grouped_by_carriers into $package to minimize the number of package foreach ($grouped_by_carriers as $id_address_delivery => $products_in_stock_list) @@ -1223,8 +1224,8 @@ class CartCore extends ObjectModel 'in_stock' => array(), 'out_of_stock' => array(), ); - - + + foreach ($products_in_stock_list as $key => $warehouse_list) { if (!isset($package_list[$id_address_delivery][$key])) @@ -1242,7 +1243,7 @@ class CartCore extends ObjectModel } } arsort($carrier_count); - + foreach ($warehouse_list as $id_warehouse => $products_grouped_by_carriers) { if (!isset($package_list[$id_address_delivery][$key][$id_warehouse])) @@ -1269,14 +1270,14 @@ class CartCore extends ObjectModel } } } - + // Step 5 : Reduce deep of $package_list $final_package_list = array(); foreach ($package_list as $id_address_delivery => $products_in_stock_list) { if (!isset($final_package_list[$id_address_delivery])) $final_package_list[$id_address_delivery] = array(); - + foreach ($products_in_stock_list as $key => $warehouse_list) foreach ($warehouse_list as $id_warehouse => $products_grouped_by_carriers) foreach ($products_grouped_by_carriers as $data) @@ -1288,11 +1289,11 @@ class CartCore extends ObjectModel } return $final_package_list; } - + /** * Get all deliveries options available for the current cart * @param Country $default_country - * + * * @return array array( * 0 => array( // First address * 0 => array( // First delivery option available for this address @@ -1326,7 +1327,7 @@ class CartCore extends ObjectModel { $delivery_option_list[$id_address] = array(); $carriers_price[$id_address] = array(); - + $common_carriers = array(); $best_price_carriers = array(); $best_grade_carriers = array(); @@ -1335,10 +1336,10 @@ class CartCore extends ObjectModel // No carriers available if (count($package['carrier_list']) == 1 && current($package['carrier_list']) == 0) return array(); - + $carriers_price[$id_address][$id_package] = array(); $carriers_instance = array(); - + if (empty($common_carriers)) $common_carriers = $package['carrier_list']; else @@ -1361,19 +1362,19 @@ class CartCore extends ObjectModel $carriers_price[$id_address][$id_package][$id_carrier] = array( 'without_tax' => $price_without_tax, 'with_tax' => $price_with_tax); - + $grade = $carriers_instance[$id_carrier]->grade; if (is_null($best_grade) || $grade > $best_grade) { $best_grade = $grade; $best_grade_carrier = $id_carrier; } - + } $best_price_carriers[$id_package] = $best_price_carrier; $best_grade_carriers[$id_package] = $best_grade_carrier; } - + $best_price_carrier = array(); $key = ''; foreach ($best_price_carriers as $id_package => $id_carrier) @@ -1396,7 +1397,7 @@ class CartCore extends ObjectModel 'is_best_grade' => false, 'unique_carrier' => false ); - + $best_grade_carrier = array(); $key = ''; foreach ($best_grade_carriers as $id_package => $id_carrier) @@ -1420,7 +1421,7 @@ class CartCore extends ObjectModel 'unique_carrier' => false ); $delivery_option_list[$id_address][$key]['is_best_grade'] = true; - + foreach ($common_carriers as $id_carrier) { $price = 0; @@ -1463,11 +1464,11 @@ class CartCore extends ObjectModel { $total_price_with_tax += $data['price_with_tax']; $total_price_without_tax += $data['price_without_tax']; - + if (!isset($carrier_collection[$id_carrier])) $carrier_collection[$id_carrier] = new Carrier($id_carrier); $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['instance'] = $carrier_collection[$id_carrier]; - + if (file_exists(_PS_SHIP_IMG_DIR_.$id_carrier.'.jpg')) $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['logo'] = _THEME_SHIP_DIR_.$id_carrier.'.jpg'; else @@ -1479,7 +1480,7 @@ class CartCore extends ObjectModel } return $delivery_option_list; } - + /** * Does the cart use multiple */ @@ -1507,7 +1508,7 @@ class CartCore extends ObjectModel $collection[$row['id_address_delivery']] = new Address($row['id_address_delivery']); return $collection; } - + /** * Set the delivery option and id_carrier, if there is only one carrier */ @@ -1569,7 +1570,7 @@ class CartCore extends ObjectModel { if (is_null($delivery_option)) $delivery_option = $this->getDeliveryOption($default_country); - + $total_shipping = 0; $delivery_option_list = $this->getDeliveryOptionList(); foreach ($delivery_option as $id_address => $key) @@ -1595,14 +1596,14 @@ class CartCore extends ObjectModel * @param Array $product_list * @param array $product_list List of product concerned by the shipping. If null, all the product of the cart are used to calculate the shipping cost * @deprecated since 1.5.0 - * + * * @return float Shipping total */ public function getOrderShippingCost($id_carrier = null, $useTax = true, Country $default_country = null, $product_list = null) { return $this->getPackageShippingCost($id_carrier, $useTax, $default_country, $product_list); } - + /** * Return package shipping cost * @@ -1611,7 +1612,7 @@ class CartCore extends ObjectModel * @param Country $default_country * @param Array $product_list * @param array $product_list List of product concerned by the shipping. If null, all the product of the cart are used to calculate the shipping cost - * + * * @return float Shipping total */ public function getPackageShippingCost($id_carrier = null, $useTax = true, Country $default_country = null, $product_list = null) @@ -1627,7 +1628,7 @@ class CartCore extends ObjectModel $products = $complete_product_list; else $products = $product_list; - + // Checking discounts in cart // if (Discount::isFeatureActive()) // $discounts = $this->getDiscounts(true); @@ -1864,7 +1865,7 @@ class CartCore extends ObjectModel } return $total_weight; } - + if (!isset(self::$_totalWeight[$this->id])) { if (Combination::isFeatureActive()) @@ -2192,16 +2193,16 @@ class CartCore extends ObjectModel } return true; } - + public function setProductAddressDelivery($id_product, $id_product_attribute, $old_id_address_delivery, $new_id_address_delivery) { // Check address is linked with the customer if (!Customer::customerHasAddress(Context::getContext()->customer->id, $new_id_address_delivery)) return false; - + if ($new_id_address_delivery == $old_id_address_delivery) return false; - + // Checking if the product with the old address delivery exists $sql = new DbQuery(); $sql->select('count(*)'); @@ -2213,7 +2214,7 @@ class CartCore extends ObjectModel $result = Db::getInstance()->getValue($sql); if ($result == 0) return false; - + // Checking if there is no others similar products with this new address delivery $sql = new DbQuery(); $sql->select('sum(quantity) as qty'); @@ -2223,7 +2224,7 @@ class CartCore extends ObjectModel $sql->where('id_address_delivery = '.(int)$new_id_address_delivery); $sql->where('id_cart = '.(int)$this->id); $result = Db::getInstance()->getValue($sql); - + // Removing similar products with this new address delivery $sql = 'DELETE FROM '._DB_PREFIX_.'cart_product WHERE id_product = '.(int)$id_product.' @@ -2232,7 +2233,7 @@ class CartCore extends ObjectModel AND id_cart = '.(int)$this->id.' LIMIT 1'; Db::getInstance()->execute($sql); - + // Changing the address $sql = 'UPDATE '._DB_PREFIX_.'cart_product SET `id_address_delivery` = '.(int)$new_id_address_delivery.', @@ -2243,7 +2244,7 @@ class CartCore extends ObjectModel AND id_cart = '.(int)$this->id.' LIMIT 1'; Db::getInstance()->execute($sql); - + // Changing the address of the customizations $sql = 'UPDATE '._DB_PREFIX_.'customization SET `id_address_delivery` = '.(int)$new_id_address_delivery.' @@ -2252,16 +2253,16 @@ class CartCore extends ObjectModel AND id_address_delivery = '.(int)$old_id_address_delivery.' AND id_cart = '.(int)$this->id; Db::getInstance()->execute($sql); - + return true; } - + public function duplicateProduct($id_product, $id_product_attribute, $id_address_delivery, $new_id_address_delivery, $quantity = 1, $keep_quantity = false) { // Check address is linked with the customer if (!Customer::customerHasAddress(Context::getContext()->customer->id, $new_id_address_delivery)) return false; - + // Checking the product do not exist with the new address $sql = new DbQuery(); $sql->select('count(*)'); @@ -2273,7 +2274,7 @@ class CartCore extends ObjectModel $result = Db::getInstance()->getValue($sql); if ($result > 0) return false; - + // Duplicating cart_product line $sql = 'INSERT INTO '._DB_PREFIX_.'cart_product (`id_cart`, `id_product`, `id_shop`, `id_product_attribute`, `quantity`, `date_add`, `id_address_delivery`) @@ -2286,7 +2287,7 @@ class CartCore extends ObjectModel NOW(), '.(int)$new_id_address_delivery.')'; Db::getInstance()->execute($sql); - + if (!$keep_quantity) { $sql = 'UPDATE '._DB_PREFIX_.'cart_product @@ -2298,7 +2299,7 @@ class CartCore extends ObjectModel AND id_address_delivery = '.(int)$id_address_delivery; Db::getInstance()->execute($sql); } - + // Checking if there is customizations $sql = new DbQuery(); $sql->select('*'); @@ -2311,7 +2312,7 @@ class CartCore extends ObjectModel foreach ($results as $customization) { - + // Duplicate customization $sql = 'INSERT INTO '._DB_PREFIX_.'customization(`id_product_attribute`, `id_address_delivery`, `id_cart`, `id_product`, `quantity`, `in_cart`) VALUES ( @@ -2322,12 +2323,12 @@ class CartCore extends ObjectModel '.$quantity.', '.$customization['in_cart'].')'; Db::getInstance()->execute($sql); - + $sql = 'INSERT INTO '._DB_PREFIX_.'customized_data(`id_customization`, `type`, `index`, `value`) (SELECT '.(int)Db::getInstance()->Insert_ID().' `id_customization`, `type`, `index`, `value` FROM customized_data WHERE id_customization = '.$customization['id_customization'].')'; Db::getInstance()->execute($sql); } - + $customization_count = count($results); if ($customization_count > 0) { @@ -2342,7 +2343,7 @@ class CartCore extends ObjectModel } return true; } - + /** * Update products cart address delivery with the address delivery of the cart */ @@ -2365,7 +2366,7 @@ class CartCore extends ObjectModel AND id_product_attribute = '.$product['id_product_attribute']; Db::getInstance()->execute($sql); } - + // Merging multiple lines $sql = 'DELETE cp1 FROM `'._DB_PREFIX_.'cart_product` cp1 @@ -2378,8 +2379,8 @@ class CartCore extends ObjectModel AND (cp1.date_add > cp2.date_add) )'; Db::getInstance()->execute($sql); - - + + // upgradng address delivery $sql = 'UPDATE `'._DB_PREFIX_.'cart_product` SET `id_address_delivery` = @@ -2402,7 +2403,7 @@ class CartCore extends ObjectModel WHERE `id_cart` = '.(int)$this->id; Db::getInstance()->execute($sql); } - + /** * Set an address to all products on the cart without address delivery */ @@ -2415,17 +2416,17 @@ class CartCore extends ObjectModel { if ((int)$cart->id_customer == 0) return; - + $customer = new Customer((int)$cart->id_customer); $addresses = $customer->getAddresses(Context::getContext()->language->id); - + if (count($addresses) == 0) return; - + $id_address_delivery = $addresses[0]['id_address']; } - - // Update + + // Update $sql = 'UPDATE `'._DB_PREFIX_.'cart_product` SET `id_address_delivery` = ( diff --git a/classes/CartRule.php b/classes/CartRule.php index db7b84383..d3a292421 100644 --- a/classes/CartRule.php +++ b/classes/CartRule.php @@ -59,7 +59,7 @@ class CartRuleCore extends ObjectModel protected $table = 'cart_rule'; protected $identifier = 'id_cart_rule'; - + protected $fieldsRequired = array('date_from', 'date_to'); protected $fieldsSize = array('code' => 254, 'description' => 65534); protected $fieldsValidate = array( @@ -134,16 +134,16 @@ class CartRuleCore extends ObjectModel return false; return $this->getTranslationsFields(array('name')); } - + public function add($autodate = true, $nullValues = false) { if (!parent::add($autodate, $nullValues)) return false; - + Configuration::updateGlobalValue('PS_CART_RULE_FEATURE_ACTIVE', '1'); return true; } - + public function delete() { if (!parent::delete()) @@ -158,7 +158,7 @@ class CartRuleCore extends ObjectModel Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'cart_rule_product_rule` WHERE `id_cart_rule` = '.(int)$this->id); Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'cart_rule_product_rule_value` WHERE `id_product_rule` NOT IN (SELECT `id_product_rule` FROM `'._DB_PREFIX_.'cart_rule_product_rule`)'); } - + public static function copyConditions($id_cart_rule_source, $id_cart_rule_destination) { Db::getInstance()->Execute(' @@ -186,7 +186,7 @@ class CartRuleCore extends ObjectModel return false; return Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue('SELECT `id_cart_rule` FROM `'._DB_PREFIX_.'cart_rule` WHERE `code` = \''.pSQL($code).'\''); } - + public static function getCustomerCartRules($id_lang, $id_customer, $active = false, $includeGeneric = true, $inStock = false, Cart $cart = null) { if (!CartRule::isFeatureActive()) @@ -219,7 +219,7 @@ class CartRuleCore extends ObjectModel } return $result; } - + public function usedByCustomer($id_customer) { return (bool)Db::getInstance()->getValue(' @@ -229,7 +229,7 @@ class CartRuleCore extends ObjectModel WHERE ocr.`id_cart_rule` = '.(int)$this->id.' AND o.`id_customer` = '.(int)$id_customer); } - + public static function cartRuleExists($name) { if (!CartRule::isFeatureActive()) @@ -240,7 +240,7 @@ class CartRuleCore extends ObjectModel FROM `'._DB_PREFIX_.'cart_rule` WHERE `code` = \''.pSQL($name).'\''); } - + public static function deleteByIdCustomer($id_customer) { $return = true; @@ -255,7 +255,7 @@ class CartRuleCore extends ObjectModel { if (!Validate::isLoadedObject($this) OR $this->product_restriction == 0) return array(); - + $productRules = array(); $result = Db::getInstance()->ExecuteS(' SELECT * @@ -270,13 +270,13 @@ class CartRuleCore extends ObjectModel } return $productRules; } - + // Todo : Add shop management public function checkValidity(Context $context, $alreadyInCart = false) { if (!CartRule::isFeatureActive()) return false; - + if (!$this->active) return Tools::displayError('This voucher is disabled'); if (!$this->quantity) @@ -285,7 +285,7 @@ class CartRuleCore extends ObjectModel return Tools::displayError('This voucher is not valid yet'); if (strtotime($this->date_to) < time()) return Tools::displayError('This voucher has expired'); - + if ($context->cart->id_customer) { $quantityUsed = Db::getInstance()->getValue(' @@ -304,7 +304,7 @@ class CartRuleCore extends ObjectModel if ($quantityUsed + 1 > $this->quantity_per_user) return Tools::displayError('You cannot use this voucher anymore (usage limit reached)'); } - + $otherCartRules = $context->cart->getCartRules(); if (count($otherCartRules)) foreach ($otherCartRules as $otherCartRule) @@ -325,7 +325,7 @@ class CartRuleCore extends ObjectModel } } } - + // Get an intersection of the customer groups and the cart rule groups (if the customer is not logged in, the default group is 1) if ($this->group_restriction) { @@ -337,7 +337,7 @@ class CartRuleCore extends ObjectModel if (!$id_cart_rule) return Tools::displayError('You cannot use this voucher'); } - + // Check if the customer delivery address is usable with the cart rule if ($this->country_restriction AND $context->cart->id_address_delivery) { @@ -349,7 +349,7 @@ class CartRuleCore extends ObjectModel if (!$id_cart_rule) return Tools::displayError('You cannot use this voucher in your country of delivery'); } - + // Check if the carrier chosen by the customer is usable with the cart rule if ($this->carrier_restriction AND $context->cart->id_carrier) { @@ -361,7 +361,7 @@ class CartRuleCore extends ObjectModel if (!$id_cart_rule) return Tools::displayError('You cannot use this voucher with this carrier'); } - + // Check if the products chosen by the customer are usable with the cart rule if ($this->product_restriction) { @@ -420,13 +420,14 @@ class CartRuleCore extends ObjectModel return Tools::displayError('You cannot use this voucher').' - '.Tools::displayError('Please log in'); return Tools::displayError('You cannot use this voucher'); } - + if ($this->minimum_amount) { $minimum_amount = $this->minimum_amount; if ($this->minimum_amount_currency != Configuration::get('PS_CURRENCY_DEFAULT')) { - $minimumAmountCurrency = new Currency($this->minimum_amount); + $minimumAmountCurrency = new Currency($this->minimum_amount_currency); + //p($this->minimum_amount_currency); $minimum_amount = $this->minimum_amount / $minimumAmountCurrency->convertion_rate; } $cartTotal = $context->cart->getOrderTotal($this->minimum_amount_tax, Cart::ONLY_PRODUCTS); @@ -436,7 +437,7 @@ class CartRuleCore extends ObjectModel return Tools::displayError('You do not reach the minimum amount required to use this voucher'); } } - + // The reduction value is POSITIVE public function getContextualValue($useTax, Context $context = NULL) { @@ -444,9 +445,9 @@ class CartRuleCore extends ObjectModel return 0; if (!$context) $context = Context::getContext(); - + $reductionValue = 0; - + // Free shipping on selected carriers if ($this->free_shipping) { @@ -463,13 +464,13 @@ class CartRuleCore extends ObjectModel $reductionValue += $context->cart->getOrderShippingCost($context->cart->id_carrier, $useTax, $context->country); } } - + // Discount (%) on the whole order if ($this->reduction_percent AND $this->reduction_product == 0) { $reductionValue += $context->cart->getOrderTotal($useTax, Cart::ONLY_PRODUCTS) * $this->reduction_percent / 100; } - + // Discount (%) on a specific product if ($this->reduction_percent AND $this->reduction_product > 0) { @@ -477,7 +478,7 @@ class CartRuleCore extends ObjectModel if ($product['id_product'] == $this->reduction_product) $reductionValue += ($useTax ? $product['total_wt'] : $product['total']) * $this->reduction_percent / 100; } - + // Discount (%) on the cheapest product if ($this->reduction_percent AND $this->reduction_product == -1) { @@ -490,7 +491,7 @@ class CartRuleCore extends ObjectModel $reductionValue += $minPrice * $this->reduction_percent / 100; } } - + // Discount (¤) if ($this->reduction_amount) { @@ -503,10 +504,10 @@ class CartRuleCore extends ObjectModel $reduction_amount /= $voucherCurrency->conversion_rate; // Then we convert the voucher value in the default currency into the cart currency $reduction_amount *= $context->currency->conversion_rate; - + $reduction_amount = Tools::ps_round($reduction_amount); } - + // If it has the same tax application that you need, then it's the right value, whatever the product! if ($this->reduction_tax == $useTax) $reductionValue += $reduction_amount; @@ -543,7 +544,7 @@ class CartRuleCore extends ObjectModel // Todo: discount on the cheapest (but this is not meaningful) } } - + // Free gift if ($this->gift_product) { @@ -551,10 +552,10 @@ class CartRuleCore extends ObjectModel if ($product['id_product'] == $this->gift_product) $reductionValue += ($useTax ? $product['price_wt'] : $product['price']); } - + return $reductionValue; } - + protected function getCartRuleCombinations() { $array = array(); @@ -586,14 +587,14 @@ class CartRuleCore extends ObjectModel )'); return $array; } - + public function getAssociatedRestrictions($type, $active = 1) { $array = array('selected' => array(), 'unselected' => array()); - + if (!in_array($type, array('country', 'carrier', 'group', 'cart_rule'))) return false; - + if (!Validate::isLoadedObject($this) OR $this->{$type.'_restriction'} == 0) { $array['selected'] = Db::getInstance()->ExecuteS(' @@ -625,12 +626,12 @@ class CartRuleCore extends ObjectModel } return $array; } - + public static function autoRemoveFromCart($context = NULL) { if (!CartRule::isFeatureActive()) return; - + $errors = array(); if (!$context) $context = Context::getContext(); @@ -647,14 +648,14 @@ class CartRuleCore extends ObjectModel } return $errors; } - + public static function autoAddToCart($context = NULL) { if ($context === NULL) $context = Context::getContext(); if (!CartRule::isFeatureActive() || !Validate::isLoadedObject($context->cart)) return; - + $result = Db::getInstance()->ExecuteS(' SELECT cr.* FROM '._DB_PREFIX_.'cart_rule cr @@ -667,7 +668,7 @@ class CartRuleCore extends ObjectModel AND cr.date_to > "'.date('Y-m-d H:i:s').'" AND cr.id_cart_rule NOT IN (SELECT id_cart_rule FROM '._DB_PREFIX_.'cart_cart_rule WHERE id_cart = '.(int)$context->cart->id.') AND ( - cr.id_customer = 0 + cr.id_customer = 0 '.($context->customer->id ? 'OR cr.id_customer = '.(int)$context->cart->id_customer : '').' ) AND ( @@ -693,15 +694,15 @@ class CartRuleCore extends ObjectModel ) ) ORDER BY priority'); - + $cartRules = ObjectModel::hydrateCollection('CartRule', $result); - + // Todo: consider optimization (we can avoid many queries in checkValidity) foreach ($cartRules as $cartRule) if (!$cartRule->checkValidity($context)) $context->cart->addCartRule($cartRule->id); } - + public static function isFeatureActive() { return (bool)Configuration::get('PS_CART_RULE_FEATURE_ACTIVE'); diff --git a/classes/Currency.php b/classes/Currency.php index 629264d6b..75d071f2b 100644 --- a/classes/Currency.php +++ b/classes/Currency.php @@ -73,15 +73,15 @@ class CurrencyCore extends ObjectModel protected $webserviceParameters = array( 'objectsNodeName' => 'currencies', ); - + /** * contains the sign to display before price, according to its format - * @var string + * @var string */ public $prefix = null; /** * contains the sign to display after price, according to its format - * @var string + * @var string */ public $suffix = null; @@ -198,7 +198,7 @@ class CurrencyCore extends ObjectModel * * @return array Currencies */ - static public function getCurrencies($object = false, $active = 1, Shop $shop = null) + public static function getCurrencies($object = false, $active = 1, Shop $shop = null) { if (!$shop) $shop = new Shop(Context::getContext()->shop->getID(true)); @@ -216,7 +216,7 @@ class CurrencyCore extends ObjectModel return $tab; } - static public function getPaymentCurrenciesSpecial($id_module, $id_shop = null) + public static function getPaymentCurrenciesSpecial($id_module, $id_shop = null) { if (is_null($id_shop)) $id_shop = Context::getContext()->shop->getID(); @@ -228,7 +228,7 @@ class CurrencyCore extends ObjectModel return Db::getInstance()->getRow($sql); } - static public function getPaymentCurrencies($id_module, $id_shop = null) + public static function getPaymentCurrencies($id_module, $id_shop = null) { if (is_null($id_shop)) $id_shop = Context::getContext()->shop->getID(); @@ -244,7 +244,7 @@ class CurrencyCore extends ObjectModel return Db::getInstance()->executeS($sql); } - static public function checkPaymentCurrencies($id_module, $id_shop = null) + public static function checkPaymentCurrencies($id_module, $id_shop = null) { if (is_null($id_shop)) $id_shop = Context::getContext()->shop->getID(true); @@ -275,7 +275,7 @@ class CurrencyCore extends ObjectModel return $result['id_currency']; } - static public function getIdByIsoCodeNum($iso_code) + public static function getIdByIsoCodeNum($iso_code) { $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT `id_currency` @@ -357,7 +357,7 @@ class CurrencyCore extends ObjectModel /** * Get current currency - * + * * @deprecated as of 1.5 use $context->currency instead * @return Currency */ diff --git a/classes/PaymentCC.php b/classes/PaymentCC.php index 2158a40cb..a623d0b74 100644 --- a/classes/PaymentCC.php +++ b/classes/PaymentCC.php @@ -1,6 +1,6 @@ date_add); return $fields; } - + public function add($autodate = true, $nullValues = false) { if (parent::add($autodate, $nullValues)) @@ -70,20 +76,18 @@ class PaymentCCCore extends ObjectModel } return false; } - + /** * Get the detailed payment of an order * @param int $id_order * @return array + * @deprecated 1.5.0.1 + * @see OrderPaymentCore */ public static function getByOrderId($id_order) { - $query = ' - SELECT * - FROM `'._DB_PREFIX_.'payment_cc` - WHERE `id_order` = '.$id_order; - - return Db::getInstance()->getRow($query); + Tools::displayAsDeprecated(); + return null; } } diff --git a/classes/PaymentModule.php b/classes/PaymentModule.php index ef8c0d1b1..4b06f7e89 100644 --- a/classes/PaymentModule.php +++ b/classes/PaymentModule.php @@ -32,9 +32,6 @@ abstract class PaymentModuleCore extends Module public $currencies = true; public $currencies_mode = 'checkbox'; - /* @var object PaymentCC */ - public $pcc = null; - public function install() { if (!parent::install()) @@ -78,18 +75,6 @@ abstract class PaymentModuleCore extends Module return false; return parent::uninstall(); } - - public function __construct() - { - $this->pcc = new PaymentCC(); - - parent::__construct(); - } - - public function __destruct() - { - unset($this->pcc); - } /** * Validate an order in database @@ -101,12 +86,12 @@ abstract class PaymentModuleCore extends Module * @param string $paymentMethod Payment method (eg. 'Credit card') * @param string $message Message to attach to order */ - public function validateOrder($id_cart, $id_order_state, $amountPaid, $paymentMethod = 'Unknown', - $message = NULL, $extraVars = array(), $currency_special = NULL, $dont_touch_amount = false, + public function validateOrder($id_cart, $id_order_state, $amountPaid, $paymentMethod = 'Unknown', + $message = NULL, $extraVars = array(), $currency_special = NULL, $dont_touch_amount = false, $secure_key = false, Shop $shop = null) { $cart = new Cart((int)($id_cart)); - + if (!$shop) $shop = Context::getContext()->shop; // Does order already exists ? @@ -114,7 +99,7 @@ abstract class PaymentModuleCore extends Module { if ($secure_key !== false AND $secure_key != $cart->secure_key) die(Tools::displayError()); - + // For each package, generate an order $delivery_option_list = $cart->getDeliveryOptionList(); $package_list = $cart->getPackageList(); @@ -128,27 +113,27 @@ abstract class PaymentModuleCore extends Module $cart_delivery_option[$id_address] = $key; break; } - + $order_list = array(); $order_detail_list = array(); $reference = Order::generateReference(); $this->currentOrderReference = $reference; - + $id_currency = $currency_special ? (int)($currency_special) : (int)($cart->id_currency); $currency = new Currency($id_currency); - + $this->context->cart->order_reference = $reference; - + $orderCreationFailed = false; $cart_total_paid = (float)Tools::ps_round((float)($cart->getOrderTotal(true, Cart::BOTH)), 2); - + if ($cart->orderExists()) { $errorMessage = Tools::displayError('An order has already been placed using this cart.'); Logger::addLog($errorMessage, 4, '0000001', 'Cart', intval($cart->id)); die($errorMessage); } - + foreach ($cart_delivery_option as $id_address => $key_carriers) foreach ($delivery_option_list[$id_address][$key_carriers]['carrier_list'] as $id_carrier => $data) foreach ($data['package_list'] as $id_package) @@ -162,14 +147,13 @@ abstract class PaymentModuleCore extends Module $order->id_address_delivery = (int)$id_address; $order->id_currency = $id_currency; $order->id_lang = (int)($cart->id_lang); - $order->id_warehouse = $package_list[$id_address][$id_package]['id_warehouse']; $order->id_cart = (int)($cart->id); $order->reference = $reference; - + $order->id_shop = (int)($shop->getID() ? $shop->getID() : $cart->id_shop); $order->id_group_shop = (int)($shop->getID() ? $shop->getGroupID() : $cart->id_group_shop); - + $customer = new Customer((int)($order->id_customer)); $order->secure_key = ($secure_key ? pSQL($secure_key) : pSQL($customer->secure_key)); $order->payment = $paymentMethod; @@ -191,18 +175,18 @@ abstract class PaymentModuleCore extends Module $order->total_shipping = (float)$cart->getPackageShippingCost((int)$id_carrier, true, null, $product_list, $id_carrier); $order->total_shipping_tax_excl = (float)$cart->getPackageShippingCost((int)$id_carrier, false, null, $product_list, $id_carrier); $order->total_shipping_tax_incl = (float)$cart->getPackageShippingCost((int)$id_carrier, true, null, $product_list, $id_carrier); - + if (Validate::isLoadedObject($carrier)) $order->carrier_tax_rate = $carrier->getTaxesRate(new Address($cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')})); - + $order->total_wrapping = (float)abs($cart->getOrderTotal(true, Cart::ONLY_WRAPPING, $product_list, $id_carrier)); $order->total_wrapping_tax_excl = (float)abs($cart->getOrderTotal(false, Cart::ONLY_WRAPPING, $product_list, $id_carrier)); $order->total_wrapping_tax_incl = (float)abs($cart->getOrderTotal(true, Cart::ONLY_WRAPPING, $product_list, $id_carrier)); - + $order->total_paid = (float)Tools::ps_round((float)($cart->getOrderTotal(true, Cart::BOTH, $product_list, $id_carrier)), 2); $order->total_paid_tax_excl = (float)Tools::ps_round((float)($cart->getOrderTotal(false, Cart::BOTH, $product_list, $id_carrier)), 2); $order->total_paid_tax_incl = (float)Tools::ps_round((float)($cart->getOrderTotal(true, Cart::BOTH, $product_list, $id_carrier)), 2); - + $order->invoice_date = '0000-00-00 00:00:00'; $order->delivery_date = '0000-00-00 00:00:00'; // Amount paid by customer is not the right one -> Status = payment error @@ -211,18 +195,29 @@ abstract class PaymentModuleCore extends Module // We use number_format in order to compare two string if (number_format($cart_total_paid, 2) != number_format($order->total_paid_real, 2)) $id_order_state = Configuration::get('PS_OS_ERROR'); - + // Creating order $result = $order->add(); $order_list[] = $order; - + // Insert new Order detail list using cart for the current order $order_detail = new OrderDetail(null, null, $this->context); $order_detail->createList($order, $cart, $id_order_state, $product_list); $order_detail_list[] = $order_detail; + + // Adding an entry in order_carrier table + Db::getInstance()->execute(' + INSERT INTO `'._DB_PREFIX_.'order_carrier` (`id_order`, `id_carrier`, `weight`, `shipping_cost_tax_excl`, `shipping_cost_tax_incl`, `date_add`) VALUES + ('.(int)$order->id.', '.(int)$carrier->id.', '.(float)$order->getTotalWeight().', '.(float)$order->total_shipping_tax_excl.', '.(float)$order->total_shipping_tax_incl.', NOW())'); } - $this->addPCC($reference, $id_currency, $amountPaid); + // Register Payment + if (!$order->addOrderPayment($amountPaid)) + { + $errorMessage = Tools::displayError('Can\'t save payment'); + Logger::addLog($errorMessage, 4, '0000003', 'Order', intval($order->id)); + die($errorMessage); + } // Next ! foreach ($order_detail_list as $key => $order_detail) @@ -249,9 +244,9 @@ abstract class PaymentModuleCore extends Module // Insert new Order detail list using cart for the current order //$orderDetail = new OrderDetail(null, null, $this->context); //$orderDetail->createList($order, $cart, $id_order_state); - + //$this->addPCC($order->id, $order->id_currency, $amountPaid); - + // Construct order detail table for the email $productsList = ''; $products = $cart->getProducts(); @@ -259,7 +254,7 @@ abstract class PaymentModuleCore extends Module { $price = Product::getPriceStatic((int)($product['id_product']), false, ($product['id_product_attribute'] ? (int)($product['id_product_attribute']) : NULL), 6, NULL, false, true, $product['cart_quantity'], false, (int)($order->id_customer), (int)($order->id_cart), (int)($order->{Configuration::get('PS_TAX_ADDRESS_TYPE')})); $price_wt = Product::getPriceStatic((int)($product['id_product']), true, ($product['id_product_attribute'] ? (int)($product['id_product_attribute']) : NULL), 2, NULL, false, true, $product['cart_quantity'], false, (int)($order->id_customer), (int)($order->id_cart), (int)($order->{Configuration::get('PS_TAX_ADDRESS_TYPE')})); - + $customizationQuantity = 0; if (isset($customizedDatas[$product['id_product']][$product['id_product_attribute']])) { @@ -269,15 +264,15 @@ abstract class PaymentModuleCore extends Module if (isset($customization['datas'][Product::CUSTOMIZE_TEXTFIELD])) foreach ($customization['datas'][Product::CUSTOMIZE_TEXTFIELD] AS $text) $customizationText .= $text['name'].':'.' '.$text['value'].'
'; - + if (isset($customization['datas'][Product::CUSTOMIZE_FILE])) $customizationText .= sizeof($customization['datas'][Product::CUSTOMIZE_FILE]) .' '. Tools::displayError('image(s)').'
'; - + $customizationText .= '---
'; } - + $customizationText = rtrim($customizationText, '---
'); - + $customizationQuantity = (int)($product['customizationQuantityTotal']); $productsList .= ' @@ -288,7 +283,7 @@ abstract class PaymentModuleCore extends Module '.Tools::displayPrice($customizationQuantity * (Product::getTaxCalculationMethod() == PS_TAX_EXC ? $price : $price_wt), $currency, false).' '; } - + if (!$customizationQuantity OR (int)$product['cart_quantity'] > $customizationQuantity) $productsList .= ' @@ -299,7 +294,7 @@ abstract class PaymentModuleCore extends Module '.Tools::displayPrice(((int)($product['cart_quantity']) - $customizationQuantity) * (Product::getTaxCalculationMethod() == PS_TAX_EXC ? $price : $price_wt), $currency, false).' '; } // end foreach ($products) - + $cartRulesList = ''; $result = $cart->getCartRules(); $cartRules = ObjectModel::hydrateCollection('CartRule', $result, (int)$order->id_lang); @@ -326,19 +321,19 @@ abstract class PaymentModuleCore extends Module Mail::Send((int)$order->id_lang, 'voucher', Mail::l('New voucher regarding your order #').$order->id, $params, $customer->email, $customer->firstname.' '.$customer->lastname); } } - + $order->addCartRule($cartRule->id, $cartRule->name, $value); if ($id_order_state != Configuration::get('PS_OS_ERROR') AND $id_order_state != Configuration::get('PS_OS_CANCELED')) $cartRule->quantity = $cartRule->quantity - 1; $cartRule->update(); - + $cartRulesList .= ' '.$this->l('Voucher name:').' '.$cartRule->name.' '.($value != 0.00 ? '-' : '').Tools::displayPrice($value, $currency, false).' '; } - + // Specify order id for message $oldMessage = Message::getMessageByCartId((int)($cart->id)); if ($oldMessage) @@ -347,7 +342,7 @@ abstract class PaymentModuleCore extends Module $message->id_order = (int)$order->id; $message->update(); } - + // Hook validate order $orderStatus = new OrderState((int)$id_order_state, (int)$order->id_lang); if (Validate::isLoadedObject($orderStatus)) @@ -357,7 +352,7 @@ abstract class PaymentModuleCore extends Module if ($orderStatus->logable) ProductSale::addProductSale((int)$product['id_product'], (int)$product['cart_quantity']); } - + if (Configuration::get('PS_STOCK_MANAGEMENT') && $order_detail->getStockState()) { $history = new OrderHistory(); @@ -373,8 +368,8 @@ abstract class PaymentModuleCore extends Module $new_history->changeIdOrderState((int)$id_order_state, (int)$order->id); $new_history->addWithemail(true, $extraVars); - unset($order_detail, $pcc); - + unset($order_detail); + // Order is reloaded because the status just changed $order = new Order($order->id); @@ -385,7 +380,7 @@ abstract class PaymentModuleCore extends Module $delivery = new Address((int)($order->id_address_delivery)); $delivery_state = $delivery->id_state ? new State((int)($delivery->id_state)) : false; $invoice_state = $invoice->id_state ? new State((int)($invoice->id_state)) : false; - + $data = array( '{firstname}' => $customer->firstname, '{lastname}' => $customer->lastname, @@ -434,10 +429,10 @@ abstract class PaymentModuleCore extends Module '{total_discounts}' => Tools::displayPrice($order->total_discounts, $currency, false), '{total_shipping}' => Tools::displayPrice($order->total_shipping, $currency, false), '{total_wrapping}' => Tools::displayPrice($order->total_wrapping, $currency, false)); - + if (is_array($extraVars)) $data = array_merge($data, $extraVars); - + // Join PDF invoice if ((int)(Configuration::get('PS_INVOICE')) AND Validate::isLoadedObject($orderStatus) AND $orderStatus->invoice AND $order->invoice_number) { @@ -447,7 +442,7 @@ abstract class PaymentModuleCore extends Module } else $fileAttachment = NULL; - + if (Validate::isEmail($customer->email)) Mail::Send((int)$order->id_lang, 'order_conf', Mail::l('Order confirmation', (int)$order->id_lang), $data, $customer->email, $customer->firstname.' '.$customer->lastname, NULL, NULL, $fileAttachment); } @@ -470,22 +465,6 @@ abstract class PaymentModuleCore extends Module die($errorMessage); } } - - /** - * Add new PaymentCC to the order - * @var int id_order - * @var int id_currency - * @var float amount - */ - private function addPCC($reference, $id_currency, $amount) - { - // Other information are set by the module - - $this->pcc->order_reference = (int)$reference; - $this->pcc->id_currency = (int)$id_currency; - $this->pcc->amount = (float)$amount; - $this->pcc->add(); - } /** * @param Object Address $the_address that needs to be txt formated diff --git a/classes/Product.php b/classes/Product.php index 3de22dba4..55e695081 100644 --- a/classes/Product.php +++ b/classes/Product.php @@ -2715,7 +2715,8 @@ class ProductCore extends ObjectModel $resultsArray = array(); foreach ($result as $row) { - $row['price'] = Product::getPriceStatic($row['id_product'], true, null, 2); + $row['price_tax_incl'] = Product::getPriceStatic($row['id_product'], true, null, 2); + $row['price_tax_excl'] = Product::getPriceStatic($row['id_product'], false, null, 2); $resultsArray[] = $row; } return $resultsArray; diff --git a/classes/order/Order.php b/classes/order/Order.php index 063836207..d561b43a6 100644 --- a/classes/order/Order.php +++ b/classes/order/Order.php @@ -91,13 +91,13 @@ class OrderCore extends ObjectModel /** @var float Total to pay tax excluded */ public $total_paid_tax_excl; - /** @var float Total really paid */ + /** @var float Total really paid @deprecated 1.5.0.1 */ public $total_paid_real; /** @var float Products total */ public $total_products; - /** @var float Products total tax excluded */ + /** @var float Products total tax included */ public $total_products_wt; /** @var float Shipping total */ @@ -467,8 +467,14 @@ class OrderCore extends ObjectModel '); } + /** + * + * @deprecated 1.5.0.1 + * @see OrderInvoice::setProductPrices + */ public function setProductPrices(&$row) { + //Tools::displayAsDeprecated(); $tax_calculator = OrderDetail::getTaxCalculatorStatic((int)$row['id_order_detail']); $row['tax_calculator'] = $tax_calculator; $row['tax_rate'] = $tax_calculator->getTotalRate(); @@ -979,36 +985,50 @@ class OrderCore extends ObjectModel return ((int)(Configuration::get('PS_ORDER_RETURN')) == 1 AND (int)($this->getCurrentState()) == Configuration::get('PS_OS_DELIVERED') AND $this->getNumberOfDays()); } - - public static function getLastInvoiceNumber() - { - return (int)Db::getInstance()->getValue(' - SELECT MAX(`invoice_number`) AS `invoice_number` - FROM `'._DB_PREFIX_.'orders`'); + public static function getLastInvoiceNumber() + { + return Db::getInstance()->getValue(' + SELECT MAX(`number`) + FROM `'._DB_PREFIX_.'order_invoice` + '); } public function setInvoice() { - $number = (int)Configuration::get('PS_INVOICE_START_NUMBER'); - if ($number) + $order_invoice = new OrderInvoice(); + $order_invoice->id_order = $this->id; + $order_invoice->number = Configuration::get('PS_INVOICE_START_NUMBER'); + // If invoice start number has been set, you clean the value of this configuration + if ($order_invoice->number) Configuration::updateValue('PS_INVOICE_START_NUMBER', false); else - $number = '(SELECT `invoice_number` - FROM ( - SELECT MAX(`invoice_number`) + 1 AS `invoice_number` - FROM `'._DB_PREFIX_.'orders`) - tmp )'; - // a way to avoid duplicate invoice number + $order_invoice->number = self::getLastInvoiceNumber() + 1; + + $order_invoice->total_discount_tax_excl = $this->total_discount_tax_excl; + $order_invoice->total_discount_tax_incl = $this->total_discount_tax_incl; + $order_invoice->total_paid_tax_excl = $this->total_paid_tax_excl; + $order_invoice->total_paid_tax_incl = $this->total_paid_tax_incl; + $order_invoice->total_products = $this->total_products; + $order_invoice->total_products_wt = $this->total_products_wt; + $order_invoice->total_shipping_tax_excl = $this->total_shipping_tax_excl; + $order_invoice->total_shipping_tax_incl = $this->total_shipping_tax_incl; + $order_invoice->total_wrapping_tax_excl = $this->total_wrapping_tax_excl; + $order_invoice->total_wrapping_tax_incl = $this->total_wrapping_tax_incl; + + // Save Order invoice + $order_invoice->add(); + + // Update order_carrier Db::getInstance()->execute(' - UPDATE `'._DB_PREFIX_.'orders` - SET `invoice_number` = '.$number.', `invoice_date` = \''.date('Y-m-d H:i:s').'\' - WHERE `id_order` = '.(int)$this->id - ); - $res = Db::getInstance()->getRow(' - SELECT `invoice_number`, `invoice_date` - FROM `'._DB_PREFIX_.'orders` - WHERE `id_order` = '.(int)$this->id - ); + UPDATE `'._DB_PREFIX_.'order_carrier` + SET `id_order_invoice` = '.(int)$order_invoice->id.' + WHERE `id_order` = '.(int)$order_invoice->id_order); + + // Update order detail + Db::getInstance()->execute(' + UPDATE `'._DB_PREFIX_.'order_detail` + SET `id_order_invoice` = '.(int)$order_invoice->id.' + WHERE `id_order` = '.(int)$order_invoice->id_order); $this->invoice_date = $res['invoice_date']; $this->invoice_number = $res['invoice_number']; @@ -1070,8 +1090,14 @@ class OrderCore extends ObjectModel return (float)($result['weight']); } + /** + * + * @param int $id_invoice + * @deprecated 1.5.0.1 + */ public static function getInvoice($id_invoice) { + Tools::displayAsDeprecated(); return Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow(' SELECT `invoice_number`, `id_order` FROM `'._DB_PREFIX_.'orders` @@ -1128,9 +1154,9 @@ class OrderCore extends ObjectModel $history->id_employee = (int)$id_employee; $history->changeIdOrderState((int)$id_order_state, (int)$this->id); $res = Db::getInstance()->getRow(' - SELECT `invoice_number`, `invoice_date`, `delivery_number`, `delivery_date` - FROM `'._DB_PREFIX_.'orders` - WHERE `id_order` = '.(int)$this->id); + SELECT `invoice_number`, `invoice_date`, `delivery_number`, `delivery_date` + FROM `'._DB_PREFIX_.'orders` + WHERE `id_order` = '.(int)$this->id); $this->invoice_date = $res['invoice_date']; $this->invoice_number = $res['invoice_number']; $this->delivery_date = $res['delivery_date']; @@ -1156,6 +1182,7 @@ class OrderCore extends ObjectModel /** * This method return the ID of the previous order + * @since 1.5.0.1 * @return int */ public function getPreviousOrderId() @@ -1169,6 +1196,7 @@ class OrderCore extends ObjectModel /** * This method return the ID of the next order + * @since 1.5.0.1 * @return int */ public function getNextOrderId() @@ -1243,9 +1271,162 @@ class OrderCore extends ObjectModel WHERE od.`id_order` = '.(int)$this->id.' AND od.`tax_computation_method` = '.(int)TaxCalculator::ONE_AFTER_ANOTHER_METHOD ); - } + /** + * This method allows to get all Order Payment for the current order + * @since 1.5.0.1 + * @return array Collection of Order Payment + */ + public function getOrderPaymentCollection() + { + $order_payment = Db::getInstance()->ExecuteS(' + SELECT * + FROM `'._DB_PREFIX_.'order_payment` + WHERE `id_order` = '.(int)$this->id); + return ObjectModel::hydrateCollection('OrderPayment', $order_payment); + } + + /** + * + * This method allows to add a payment to the current order + * @since 1.5.0.1 + * @param float $amount_paid + * @param string $payment_method + * @param string $payment_transaction_id + * @param Currency $currency + * @param string $date + * @return bool + */ + public function addOrderPayment($amount_paid, $payment_method = null, $payment_transaction_id = null, $currency = null, $date = null) + { + $order_payment = new OrderPayment(); + $order_payment->id_order = $this->id; + $order_payment->id_currency = ($currency ? $currency->id : $this->id_currency); + // we kept the currency rate for historization reasons + $order_payment->conversion_rate = ($currency ? $currency->conversion_rate : 1); + // if payment_method is define, we used this + $order_payment->payment_method = ($payment_method ? $payment_method : $this->payment); + $order_payment->transacation_id = $payment_transaction_id; + $order_payment->amount = $amount_paid; + $order_payment->date_add = ($date ? $date : null); + + // Update total_paid_real value for backward compatibility reasons + if ($order_payment->id_currency == $this->id_currency) + $this->total_paid_real += $order_payment->amount; + else + $this->total_paid_real += Tools::ps_round(Tools::convertPrice($order_payment->amount, $order_payment->id_currency, false), 2); + + return $order_payment->add() && $this->update(); + } + + /** + * Returns the correct product taxes breakdown. + * + * Get all documents linked to the current order + * + * @since 1.5.0.1 + * @return array + */ + public function getDocuments() + { + // TODO + $invoices = $this->getInvoicesCollection(); + + return $invoices; + } + + public function getReturn() + { + return OrderReturn::getOrdersReturn($this->id_customer, $this->id); + } + + public function getShipping() + { + $shipping = Db::getInstance()->ExecuteS(' + SELECT DISTINCT oc.`id_order_invoice`, oc.`weight`, oc.`shipping_cost_tax_excl`, oc.`shipping_cost_tax_incl`, c.`url`, oc.`id_carrier`, c.`name` as `state_name`, oc.`date_add`, "Delivery" as `type`, "true" as `can_edit`, oc.`tracking_number` + FROM `'._DB_PREFIX_.'orders` o + LEFT JOIN `'._DB_PREFIX_.'order_history` oh + ON (o.`id_order` = oh.`id_order`) + LEFT JOIN `'._DB_PREFIX_.'order_carrier` oc + ON (o.`id_order` = oc.`id_order`) + LEFT JOIN `'._DB_PREFIX_.'carrier` c + ON (oc.`id_carrier` = c.`id_carrier`) + LEFT JOIN `'._DB_PREFIX_.'order_state_lang` osl + ON (oh.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = '.(int)Context::getContext()->language->id.') + WHERE o.`id_order` = '.(int)$this->id); + return $shipping; + } + + /** + * + * Get all invoices for the current order + * @since 1.5.0.1 + * @return array Collection of Order invoice + */ + public function getInvoicesCollection() + { + $invoices = Db::getInstance()->ExecuteS(' + SELECT * + FROM `'._DB_PREFIX_.'order_invoice` + WHERE `id_order` = '.(int)$this->id); + return ObjectModel::hydrateCollection('OrderInvoice', $invoices); + } + + /** + * Get total paid + * + * @since 1.5.0.1 + * @param Currency $currency currency used for the total paid of the current order + * @return float amount in the $currency + */ + public function getTotalPaid($currency = null) + { + if (!$currency) + $currency = new Currency($this->id_currency); + + $total = 0; + // Retrieve all payments + $payments = $this->getOrderPaymentCollection(); + foreach($payments as $payment) + { + if ($payment->id_currency == $currency->id) + $total += $payment->amount; + else + { + $amount = Tools::convertPrice($payment->amount, $payment->id_currency, false); + if ($currency->id == Configuration::get('PS_DEFAULT_CURRENCY')) + $total += $amount; + else + $total += Tool::convertPrice($amount, $currency->id, true); + } + } + + return Tools::ps_round($total, 2); + } + + /** + * + * This method allows to change the shipping cost of the current order + * @since 1.5.0.1 + * @param float $amount + * @return bool + */ + public function updateShippingCost($amount) + { + $difference = $amount - $this->total_shipping; + // if the current amount is same as the new, we return true + if ($difference == 0) + return true; + + // update the total_shipping value + $this->total_shipping = $amount; + // update the total of this order + $this->total_paid += $difference; + + // update database + return $this->update(); + } /** * Returns the correct product taxes breakdown. diff --git a/classes/order/OrderDetail.php b/classes/order/OrderDetail.php index 0c0e0bb53..1d561b678 100644 --- a/classes/order/OrderDetail.php +++ b/classes/order/OrderDetail.php @@ -33,6 +33,9 @@ class OrderDetailCore extends ObjectModel /** @var integer */ public $id_order; + /** @var integer */ + public $id_order_invoice; + /** @var integer */ public $product_id; @@ -133,6 +136,7 @@ class OrderDetailCore extends ObjectModel protected $fieldsValidate = array( 'id_order' => 'isUnsignedId', + 'id_order_invoice' => 'isUnsignedId', 'product_id' => 'isUnsignedId', 'product_attribute_id' => 'isUnsignedId', 'product_name' => 'isGenericName', @@ -213,6 +217,7 @@ class OrderDetailCore extends ObjectModel $this->validateFields(); $fields['id_order'] = (int)$this->id_order; + $fields['id_order_invoice'] = (int)$this->id_order_invoice; $fields['product_id'] = (int)$this->product_id; $fields['product_attribute_id'] = (int)$this->product_attribute_id; $fields['product_name'] = pSQL($this->product_name); @@ -229,7 +234,7 @@ class OrderDetailCore extends ObjectModel $fields['product_ean13'] = pSQL($this->product_ean13); $fields['product_upc'] = pSQL($this->product_upc); $fields['product_reference'] = pSQL($this->product_reference); - $fields['product_supplier_reference'] = pSQL($this->product_reference); + $fields['product_supplier_reference'] = pSQL($this->product_supplier_reference); $fields['product_weight'] = (float)$this->product_weight; $fields['tax_name'] = pSQL($this->tax_name); $fields['tax_rate'] = (float)$this->tax_rate; @@ -405,11 +410,11 @@ class OrderDetailCore extends ObjectModel $this->tax_calculator = $tax_manager->getTaxCalculator(); } - $this->ecotax_tax_rate = 0; - if (!empty($product['ecotax'])) - $this->ecotax_tax_rate = Tax::getProductEcotaxRate($order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + $this->ecotax_tax_rate = 0; + if (!empty($product['ecotax'])) + $this->ecotax_tax_rate = Tax::getProductEcotaxRate($order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - $this->tax_computation_method = (int)$this->tax_calculator->computation_method; + $this->tax_computation_method = (int)$this->tax_calculator->computation_method; } /** @@ -445,12 +450,14 @@ class OrderDetailCore extends ObjectModel $customer = new Customer((int)$order->id_customer); $customer_address = new Address((int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); - $this->specificPrice = SpecificPrice::getSpecificPrice((int)$product['id_product'], - (int)$order->id_shop, - (int)$order->id_currency, - (int)$customer_address->id_country, - (int)$customer->id_default_group, - (int)$product['cart_quantity']); + $this->specificPrice = SpecificPrice::getSpecificPrice( + (int)$product['id_product'], + (int)$order->id_shop, + (int)$order->id_currency, + (int)$customer_address->id_country, + (int)$customer->id_default_group, + (int)$product['cart_quantity'] + ); $this->product_price = (float)$product['price']; $this->unit_price_tax_incl = (float)$product['price_wt']; @@ -462,7 +469,12 @@ class OrderDetailCore extends ObjectModel $this->group_reduction = (float)(Group::getReduction((int)($order->id_customer))); - $quantityDiscount = SpecificPrice::getQuantityDiscount((int)$product['id_product'], $this->context->shop->getID(), + if (isset($this->context->shop)) + $shop_id = $this->context->shop->getID(); + else + $shop_id = $cart->id_shop; + + $quantityDiscount = 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']); @@ -484,10 +496,13 @@ class OrderDetailCore extends ObjectModel * @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) + protected function create(Order $order, Cart $cart, $product, $id_order_state, $id_order_invoice, $use_taxes = true) { - $this->tax_calculator = new TaxCalculator(); + if ($use_taxes) + $this->tax_calculator = new TaxCalculator(); $this->id = null; @@ -510,13 +525,19 @@ class OrderDetailCore extends ObjectModel $this->setVirtualProductInformation($product); $this->checkProductStock($product, $id_order_state); - $this->setProductTax($order, $product); + + if ($use_taxes) + $this->setProductTax($order, $product); $this->setDetailProductPrice($order, $cart, $product); + // Set order invoice id + $this->id_order_invoice = (int)$id_order_invoice; + // Add new entry to the table $this->save(); - $this->saveTaxCalculator(); + if ($use_taxes) + $this->saveTaxCalculator(); unset($this->tax_calculator); } @@ -525,18 +546,19 @@ class OrderDetailCore extends ObjectModel * @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) + public function createList(Order $order, Cart $cart, $id_order_state, $product_list, $id_order_invoice, $use_taxes = true) { $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; - $products = $product_list; $this->outOfStock = false; - foreach ($products as $product) - $this->create($order, $cart, $product, $id_order_state); + foreach ($product_list as $product) + $this->create($order, $cart, $product, $id_order_state, $id_order_invoice, $use_taxes); unset($this->vat_address); unset($products); diff --git a/classes/order/OrderInvoice.php b/classes/order/OrderInvoice.php new file mode 100644 index 000000000..6c44b0985 --- /dev/null +++ b/classes/order/OrderInvoice.php @@ -0,0 +1,387 @@ + +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision: 10418 $ +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +class OrderInvoiceCore extends ObjectModel +{ + /** @var integer */ + public $id_order; + + /** @var integer */ + public $number; + + /** @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 float */ + public $total_wrapping_tax_excl; + + /** @var float */ + public $total_wrapping_tax_incl; + + /** @var intger */ + public $date_add; + + protected $fieldsRequired = array('id_order', 'number'); + protected $fieldsValidate = array('id_order' => 'isUnsignedId', 'number' => 'isUnsignedId'); + + protected $table = 'order_invoice'; + protected $identifier = 'id_order_invoice'; + + public function getFields() + { + $this->validateFields(); + + $fields['id_order'] = (int)$this->id_order; + $fields['number'] = (int)$this->number; + $fields['total_discount_tax_excl'] = (float)$this->total_discount_tax_excl; + $fields['total_discount_tax_incl'] = (float)$this->total_discount_tax_incl; + $fields['total_paid_tax_excl'] = (float)$this->total_paid_tax_excl; + $fields['total_paid_tax_incl'] = (float)$this->total_paid_tax_incl; + $fields['total_products'] = (float)$this->total_products; + $fields['total_products_wt'] = (float)$this->total_products_wt; + $fields['total_shipping_tax_excl'] = (float)$this->total_shipping_tax_excl; + $fields['total_shipping_tax_incl'] = (float)$this->total_shipping_tax_incl; + $fields['total_wrapping_tax_excl'] = (float)$this->total_wrapping_tax_excl; + $fields['total_wrapping_tax_incl'] = (float)$this->total_wrapping_tax_incl; + $fields['date_add'] = pSQL($this->date_add); + + return $fields; + } + + public function getProductsDetail() + { + return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' + SELECT * + FROM `'._DB_PREFIX_.'order_detail` od + WHERE od.`id_order` = '.(int)$this->id_order.' + AND od.`id_order_invoice` = '.(int)$this->id); + } + + /** + * Get order products + * + * @return array Products with price, quantity (with taxe and without) + */ + public function getProducts($products = false, $selectedProducts = false, $selectedQty = false) + { + if (!$products) + $products = $this->getProductsDetail(); + + $order = new Order($this->id_order); + $customized_datas = Product::getAllCustomizedDatas($order->id_cart); + + $resultArray = array(); + foreach ($products AS $row) + { + // Change qty if selected + if ($selectedQty) + { + $row['product_quantity'] = 0; + foreach ($selectedProducts AS $key => $id_product) + if ($row['id_order_detail'] == $id_product) + $row['product_quantity'] = (int)($selectedQty[$key]); + if (!$row['product_quantity']) + continue ; + } + + $this->setProductImageInformations($row); + $this->setProductCurrentStock($row); + $this->setProductPrices($row, $order); + $this->setProductCustomizedDatas($row, $customized_datas); + + // Add information for virtual product + if ($row['download_hash'] && !empty($row['download_hash'])) + { + if ($row['product_attribute_id'] && !empty($row['product_attribute_id'])) + $row['filename'] = ProductDownload::getFilenameFromIdAttribute((int)$row['product_id'], (int)$row['product_attribute_id']); + else + $row['filename'] = ProductDownload::getFilenameFromIdProduct((int)$row['product_id']); + // Get the display filename + $row['display_filename'] = ProductDownload::getFilenameFromFilename($row['filename']); + } + /* Stock product */ + $resultArray[(int)$row['id_order_detail']] = $row; + } + + if ($customized_datas) + Product::addCustomizationPrice($resultArray, $customized_datas); + + return $resultArray; + } + + 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) + { + $product['current_stock'] = StockManagerFactory::getManager()->getProductPhysicalQuantities($product['product_id'], $product['product_attribute_id'], null, true); + } + + /** + * + * 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 id_image + FROM '._DB_PREFIX_.'product_attribute_image + WHERE id_product_attribute = '.(int)$product['product_attribute_id']); + + if (!isset($image['id_image']) || !$image['id_image']) + $id_image = Db::getInstance()->getValue(' + SELECT id_image + FROM '._DB_PREFIX_.'image + WHERE id_product = '.(int)($product['product_id']).' AND cover = 1 + '); + + $product['image'] = null; + $product['image_size'] = null; + + if ($id_image) + $product['image'] = new Image($id_image); + } + + public function setProductPrices(&$row, $order) + { + $tax_calculator = OrderDetail::getTaxCalculatorStatic((int)$row['id_order_detail']); + $row['tax_calculator'] = $tax_calculator; + $row['tax_rate'] = $tax_calculator->getTotalRate(); + + if ($order->getTaxCalculationMethod() == PS_TAX_EXC) + $row['product_price'] = Tools::ps_round($row['product_price'], 2); + else + $row['product_price_wt'] = Tools::ps_round($tax_calculator->addTaxes($row['product_price']), 2); + + $group_reduction = 1; + if ($row['group_reduction'] > 0) + $group_reduction = 1 - $row['group_reduction'] / 100; + + if ($row['reduction_percent'] != 0) + { + if ($order->getTaxCalculationMethod() == PS_TAX_EXC) + $row['product_price'] = ($row['product_price'] - $row['product_price'] * ($row['reduction_percent'] * 0.01)); + else + $row['product_price_wt'] = Tools::ps_round(($row['product_price_wt'] - $row['product_price_wt'] * ($row['reduction_percent'] * 0.01)), 2); + } + + if ($row['reduction_amount'] != 0) + { + if ($this->_taxCalculationMethod == PS_TAX_EXC) + $row['product_price'] = ($row['product_price'] - ($tax_calculator->removeTaxes($row['reduction_amount']))); + else + $row['product_price_wt'] = Tools::ps_round(($row['product_price_wt'] - $row['reduction_amount']), 2); + } + + if ($row['group_reduction'] > 0) + { + if ($this->_taxCalculationMethod == PS_TAX_EXC) + $row['product_price'] = $row['product_price'] * $group_reduction; + else + $row['product_price_wt'] = Tools::ps_round($row['product_price_wt'] * $group_reduction , 2); + } + + if (($row['reduction_percent'] OR $row['reduction_amount'] OR $row['group_reduction']) AND $order->getTaxCalculationMethod() == PS_TAX_EXC) + $row['product_price'] = Tools::ps_round($row['product_price'], 2); + + if ($order->getTaxCalculationMethod() == PS_TAX_EXC) + $row['product_price_wt'] = Tools::ps_round($tax_calculator->addTaxes($row['product_price']), 2) + Tools::ps_round($row['ecotax'] * (1 + $row['ecotax_tax_rate'] / 100), 2); + else + { + $row['product_price_wt_but_ecotax'] = $row['product_price_wt']; + $row['product_price_wt'] = Tools::ps_round($row['product_price_wt'] + $row['ecotax'] * (1 + $row['ecotax_tax_rate'] / 100), 2); + } + + $row['total_wt'] = $row['product_quantity'] * $row['product_price_wt']; + $row['total_price'] = $row['product_quantity'] * $row['product_price']; + } + + /** + * This method returns true if at least one order details uses the + * One After Another tax computation method. + * + * @since 1.5.0.1 + * @return boolean + */ + 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 + ); + } + + /** + * Returns the correct product taxes breakdown. + * + * @since 1.5.0.1 + * @return array + */ + public function getProductTaxesBreakdown() + { + $tmp_tax_infos = array(); + if ($this->useOneAfterAnotherTaxComputationMethod()) + { + // sum by taxes + $taxes_by_tax = Db::getInstance()->executeS(' + SELECT odt.`id_order_detail`, t.`name`, t.`rate`, SUM(`total_amount`) AS `total_amount` + FROM `'._DB_PREFIX_.'order_detail_tax` odt + LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = odt.`id_tax`) + 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.' + GROUP BY odt.`id_tax` + '); + + // format response + $tmp_tax_infos = array(); + foreach ($taxes_infos as $tax_infos) + { + $tmp_tax_infos[$tax_infos['rate']]['total_amount'] = $tax_infos['tax_amount']; + $tmp_tax_infos[$tax_infos['rate']]['name'] = $tax_infos['name']; + } + } + else + { + // sum by order details in order to retrieve real taxes rate + $taxes_infos = Db::getInstance()->executeS(' + SELECT odt.`id_order_detail`, t.`rate` AS `name`, SUM(od.`total_price_tax_excl`) AS total_price_tax_excl, SUM(t.`rate`) AS rate, SUM(`total_amount`) AS `total_amount` + FROM `'._DB_PREFIX_.'order_detail_tax` odt + LEFT JOIN `'._DB_PREFIX_.'tax` t ON (t.`id_tax` = odt.`id_tax`) + 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.' + GROUP BY odt.`id_order_detail` + '); + + // sum by taxes + $tmp_tax_infos = array(); + foreach ($taxes_infos as $tax_infos) + { + if (!isset($tmp_tax_infos[$tax_infos['rate']])) + $tmp_tax_infos[$tax_infos['rate']] = array('total_amount' => 0, + 'name' => 0, + 'total_price_tax_excl' => 0); + + $tmp_tax_infos[$tax_infos['rate']]['total_amount'] += $tax_infos['total_amount']; + $tmp_tax_infos[$tax_infos['rate']]['name'] = $tax_infos['name']; + $tmp_tax_infos[$tax_infos['rate']]['total_price_tax_excl'] += $tax_infos['total_price_tax_excl']; + } + } + + return $tmp_tax_infos; + } + + /** + * Returns the shipping taxes breakdown + * + * @since 1.5.0.1 + * @return array + */ + public function getShippingTaxesBreakdown($order) + { + $taxes_breakdown = array(); + + $shipping_tax_amount = $this->total_shipping_tax_incl - $this->total_shipping_tax_excl; + + if ($shipping_tax_amount > 0) + $taxes_breakdown[] = array( + 'rate' => $order->carrier_tax_rate, + 'total_amount' => $shipping_tax_amount + ); + + return $taxes_breakdown; + } + + /** + * Returns the wrapping taxes breakdown + * @todo + + * @since 1.5.0.1 + * @return array + */ + public function getWrappingTaxesBreakdown() + { + $taxes_breakdown = array(); + return $taxes_breakdown; + } + + /** + * Returns the ecotax taxes breakdown + * + * @since 1.5.0.1 + * @return array + */ + public function getEcoTaxTaxesBreakdown() + { + return Db::getInstance()->executeS(' + SELECT `ecotax_tax_rate`, SUM(`ecotax`) as `ecotax_tax_excl`, SUM(`ecotax`) as `ecotax_tax_incl` + FROM `'._DB_PREFIX_.'order_detail` + WHERE `id_order` = '.(int)$this->id_order.' + AND `id_order_invoice` = '.(int)$this->id + ); + } +} diff --git a/classes/order/OrderPayment.php b/classes/order/OrderPayment.php new file mode 100644 index 000000000..fe3711867 --- /dev/null +++ b/classes/order/OrderPayment.php @@ -0,0 +1,99 @@ + +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision: 10336 $ +* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +class OrderPaymentCore extends ObjectModel +{ + public $id_order; + 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; + + protected $fieldsRequired = array('id_order', 'id_currency', 'amount'); + protected $fieldsSize = array('transaction_id' => 254, 'card_number' => 254, 'card_brand' => 254, 'card_expiration' => 254, 'card_holder' => 254); + protected $fieldsValidate = array( + 'id_order' => 'isUnsignedId', + 'id_currency' => 'isUnsignedId', + 'amount' => 'isPrice', + 'payment_method' => 'isName', + 'conversion_rate' => 'isFloat', + 'transaction_id' => 'isAnything', + 'card_number' => 'isAnything', + 'card_brand' => 'isAnything', + 'card_expiration' => 'isAnything', + 'card_holder' => 'isAnything' + ); + + protected $table = 'order_payment'; + protected $identifier = 'id_order_payment'; + + public function getFields() + { + $this->validateFields(); + $fields['id_order'] = (int)($this->id_order); + $fields['id_currency'] = (int)($this->id_currency); + $fields['amount'] = (float)($this->amount); + $fields['payment_method'] = pSQL($this->payment_method); + $fields['transaction_id'] = pSQL($this->transaction_id); + $fields['card_number'] = pSQL($this->card_number); + $fields['card_brand'] = pSQL($this->card_brand); + $fields['card_expiration'] = pSQL($this->card_expiration); + $fields['card_holder'] = pSQL($this->card_holder); + $fields['date_add'] = pSQL($this->date_add); + return $fields; + } + + public function add($autodate = true, $nullValues = false) + { + if (parent::add($autodate, $nullValues)) + { + Hook::exec('paymentCCAdded', array('paymentCC' => $this)); + return true; + } + return false; + } + + /** + * Get the detailed payment of an order + * @param int $id_order + * @return array + */ + public static function getByOrderId($id_order) + { + return Db::getInstance()->ExecuteS(' + SELECT * + FROM `'._DB_PREFIX_.'payment_order` + WHERE `id_order` = '.(int)$id_order); + } +} + diff --git a/classes/order/OrderReturn.php b/classes/order/OrderReturn.php index 11e0d7de0..74480a584 100644 --- a/classes/order/OrderReturn.php +++ b/classes/order/OrderReturn.php @@ -143,10 +143,13 @@ class OrderReturnCore extends ObjectModel ($order_id ? ' AND `id_order` = '.(int)($order_id) : ''). ($no_denied ? ' AND `state` != 4' : '').' ORDER BY `date_add` DESC'); - foreach ($data AS $k => $or) + 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; } return $data; } diff --git a/classes/order/OrderSlip.php b/classes/order/OrderSlip.php index 1dcfc511d..6ba62a6e9 100644 --- a/classes/order/OrderSlip.php +++ b/classes/order/OrderSlip.php @@ -97,6 +97,7 @@ class OrderSlipCore extends ObjectModel .($id_order_detail ? ' WHERE `id_order_detail` = '.(int)($id_order_detail) : '')); } + // TODO clean getProducts($resTab) => now getProducts method don't use his parameters public static function getOrdersSlipProducts($orderSlipId, $order) { $cart_rules = $order->getCartRules(true); diff --git a/classes/pdf/HTMLTemplateInvoice.php b/classes/pdf/HTMLTemplateInvoice.php index 3d2db53f1..de4d76ef3 100755 --- a/classes/pdf/HTMLTemplateInvoice.php +++ b/classes/pdf/HTMLTemplateInvoice.php @@ -34,17 +34,18 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate public $available_in_your_account = false; - public function __construct(Order $order, $smarty) + public function __construct(OrderInvoice $order_invoice, $smarty) { - $this->order = $order; - $this->smarty = $smarty; + $this->order_invoice = $order_invoice; + $this->order = new Order($this->order_invoice->id_order); + $this->smarty = $smarty; // header informations - $this->date = Tools::displayDate($order->invoice_date, (int)$order->id_lang); - $this->title = self::l('Invoice ').Configuration::get('PS_INVOICE_PREFIX').sprintf('%06d', $order->invoice_number); + $this->date = Tools::displayDate($order_invoice->date_add, (int)$this->order->id_lang); + $this->title = self::l('Invoice ').Configuration::get('PS_INVOICE_PREFIX').sprintf('%06d', $order_invoice->number); // footer informations - $shop = new Shop((int)$order->id_shop); + $shop = new Shop((int)$this->order->id_shop); $this->address = $shop->getAddress(); } @@ -69,7 +70,7 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate $this->smarty->assign(array( 'order' => $this->order, - 'order_details' => $this->order->getProducts(), + 'order_details' => $this->order_invoice->getProducts(), 'delivery_address' => $formatted_delivery_address, 'invoice_address' => $formatted_invoice_address, 'tax_excluded_display' => Group::getPriceDisplayMethod($customer->id_default_group), @@ -91,11 +92,12 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate $this->smarty->assign(array( 'tax_exempt' => $tax_exempt, - 'use_one_after_another_method' => $this->order->useOneAfterAnotherTaxComputationMethod(), - 'product_tax_breakdown' => $this->order->getProductTaxesBreakdown(), - 'shipping_tax_breakdown' => $this->order->getShippingTaxesBreakdown(), - 'ecotax_tax_breakdown' => $this->order->getEcoTaxTaxesBreakdown(), + 'use_one_after_another_method' => $this->order_invoice->useOneAfterAnotherTaxComputationMethod(), + 'product_tax_breakdown' => $this->order_invoice->getProductTaxesBreakdown(), + 'shipping_tax_breakdown' => $this->order_invoice->getShippingTaxesBreakdown($this->order), + 'ecotax_tax_breakdown' => $this->order_invoice->getEcoTaxTaxesBreakdown(), 'order' => $this->order, + 'order_invoice' => $this->order_invoice )); return $this->smarty->fetch(_PS_THEME_DIR_.'/pdf/invoice.tax-tab.tpl'); @@ -131,7 +133,7 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate */ public function getFilename() { - return Configuration::get('PS_INVOICE_PREFIX').sprintf('%06d', $this->order->invoice_number).'.pdf'; + return Configuration::get('PS_INVOICE_PREFIX').sprintf('%06d', $this->order_invoice->number).'.pdf'; } } diff --git a/controllers/admin/AdminOrdersController.php b/controllers/admin/AdminOrdersController.php index 6c54f61c4..7ec6ee24c 100755 --- a/controllers/admin/AdminOrdersController.php +++ b/controllers/admin/AdminOrdersController.php @@ -27,6 +27,8 @@ class AdminOrdersControllerCore extends AdminController { + public $toolbar_title; + public function __construct() { $this->table = 'order'; @@ -52,7 +54,8 @@ class AdminOrdersControllerCore extends AdminController LEFT JOIN `'._DB_PREFIX_.'order_state` os ON (os.`id_order_state` = oh.`id_order_state`) LEFT JOIN `'._DB_PREFIX_.'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = '.(int)$this->context->language->id.')'; $this->_where = 'AND oh.`id_order_history` = (SELECT MAX(`id_order_history`) FROM `'._DB_PREFIX_.'order_history` moh WHERE moh.`id_order` = a.`id_order` GROUP BY moh.`id_order`)'; - $this->_orderWay = 'DESC'; + $this->_orderBy = '`id_order`'; + $this->_orderWay = 'DESC'; // FIXME $statesArray = array(); $states = OrderState::getOrderStates((int)$this->context->language->id); @@ -65,7 +68,7 @@ class AdminOrdersControllerCore extends AdminController 'reference' => array('title' => $this->l('Reference'), 'align' => 'center', 'width' => 65), 'new' => array('title' => $this->l('New'), 'width' => 25, 'align' => 'center', 'type' => 'bool', 'filter_key' => 'new', 'tmpTableFilter' => true, 'icon' => array(0 => 'blank.gif', 1 => 'news-new.gif'), 'orderby' => false), 'customer' => array('title' => $this->l('Customer'), 'filter_key' => 'customer', 'tmpTableFilter' => true), - 'total_paid' => array('title' => $this->l('Total'), 'width' => 70, 'align' => 'right', 'prefix' => '', 'suffix' => '', 'type' => 'price', 'currency' => true), + 'total_paid_tax_incl' => array('title' => $this->l('Total'), 'width' => 70, 'align' => 'right', 'prefix' => '', 'suffix' => '', 'type' => 'price', 'currency' => true), 'payment' => array('title' => $this->l('Payment'), 'width' => 100), 'osname' => array('title' => $this->l('Status'), 'width' => 230, 'type' => 'select', 'list' => $statesArray, 'filter_key' => 'os!id_order_state', 'filter_type' => 'int', 'width' => 200), 'date_add' => array('title' => $this->l('Date'), 'width' => 120, 'align' => 'right', 'type' => 'datetime', 'filter_key' => 'a!date_add'), @@ -82,73 +85,118 @@ class AdminOrdersControllerCore extends AdminController parent::initForm(); $this->addJqueryPlugin(array('autocomplete', 'fancybox', 'typewatch')); $cart = new Cart((int)Tools::getValue('id_cart')); - $this->context->smarty->assign(array('recyclable_pack' => (int)Configuration::get('PS_RECYCLABLE_PACK'), - 'gift_wrapping' => (int)Configuration::get('PS_GIFT_WRAPPING'), - 'cart' => $cart, - 'currencies' => Currency::getCurrencies(), - 'langs' => Language::getLanguages(true, Context::getContext()->shop->id), - 'payment_modules' => PaymentModule::getInstalledPaymentModules(), - 'order_states' => OrderState::getOrderStates((int)Context::getContext()->cookie->id_lang))); + $this->context->smarty->assign(array( + 'recyclable_pack' => (int)Configuration::get('PS_RECYCLABLE_PACK'), + 'gift_wrapping' => (int)Configuration::get('PS_GIFT_WRAPPING'), + 'cart' => $cart, + 'currencies' => Currency::getCurrencies(), + 'langs' => Language::getLanguages(true, Context::getContext()->shop->id), + 'payment_modules' => PaymentModule::getInstalledPaymentModules(), + 'order_states' => OrderState::getOrderStates((int)Context::getContext()->cookie->id_lang))); $this->content .= $this->context->smarty->fetch('orders/form.tpl'); } + public function initToolbar() + { + if ($this->display == 'view') + { + $this->toolbar_btn['new'] = array( + 'short' => 'Create', + 'href' => '', + 'desc' => $this->l('Add a product'), + 'class' => 'add_product' + ); + $this->toolbar_btn['standard_refund'] = array( + 'short' => 'Create', + 'href' => '', + 'desc' => $this->l('Standard refund'), + 'class' => 'process-icon-new standard_refund' + ); + $this->toolbar_btn['partial_refund'] = array( + 'short' => 'Create', + 'href' => '', + 'desc' => $this->l('Partial refund'), + 'class' => 'process-icon-new partial_refund' + ); + } + return parent::initToolbar(); + } + + public function setMedia() + { + parent::setMedia(); + $this->addJqueryUI('ui.datepicker'); + if ($this->tabAccess['edit'] == 1 && $this->display == 'view') + { + $this->addJS(_PS_JS_DIR_.'admin_order.js'); + $this->addJS(_PS_JS_DIR_.'tools.js'); + $this->addJqueryPlugin('autocomplete'); + $this->addJqueryPlugin('scrollTo'); + } + } + public function printPDFIcons($id_order, $tr) { $order = new Order($id_order); - $orderState = OrderHistory::getLastOrderState($id_order); - if (!Validate::isLoadedObject($orderState) OR !Validate::isLoadedObject($order)) + $order_state = OrderHistory::getLastOrderState($id_order); + if (!Validate::isLoadedObject($order_state) OR !Validate::isLoadedObject($order)) die(Tools::displayError('Invalid objects')); - // Generate HTML code for printing Invoice Icon with link - $content = ''; - if (($orderState->invoice && $order->invoice_number) && (int)$tr['product_number']) - $content .= 'invoice'; - else - $content .= '-'; - $content .= ''; + $this->context->smarty->assign(array( + 'order' => $order, + 'order_state' => $order_state, + 'tr' => $tr + )); - // Generate HTML code for printing Delivery Icon with link - $content .= ''; - if ($orderState->delivery && $order->delivery_number) - $content .= 'delivery'; - else - $content .= '-'; - $content .= ''; - - return $content; + return $this->context->smarty->fetch('orders/_print_pdf_icon.tpl'); } public function postProcess() { /* Update shipping number */ - if (Tools::isSubmit('submitShippingNumber') AND ($id_order = (int)(Tools::getValue('id_order'))) AND Validate::isLoadedObject($order = new Order($id_order))) + if (Tools::isSubmit('submitShippingNumber') AND ($id_order = (int)Tools::getValue('id_order')) AND Validate::isLoadedObject($order = new Order($id_order))) { if ($this->tabAccess['edit'] === '1') { - if (!$order->hasBeenShipped()) - throw new PrestashopException('The shipping number can only be set once the order has been shipped.'); - $_GET['view'.$this->table] = true; - - $shipping_number = pSQL(Tools::getValue('shipping_number')); - $order->shipping_number = $shipping_number; - $order->update(); - if ($shipping_number) + if (Validate::isUrl(Tools::getValue('tracking_number'))) { - global $_LANGMAIL; - $customer = new Customer((int)($order->id_customer)); - $carrier = new Carrier((int)($order->id_carrier)); - if (!Validate::isLoadedObject($customer) OR !Validate::isLoadedObject($carrier)) - die(Tools::displayError()); - $templateVars = array( - '{followup}' => str_replace('@', $order->shipping_number, $carrier->url), - '{firstname}' => $customer->firstname, - '{lastname}' => $customer->lastname, - '{id_order}' => (int)($order->id) - ); - @Mail::Send((int)($order->id_lang), 'in_transit', Mail::l('Package in transit'), $templateVars, - $customer->email, $customer->firstname.' '.$customer->lastname, NULL, NULL, NULL, NULL, - _PS_MAIL_DIR_, true); + // update shipping number + $order->shipping_number = Tools::getValue('tracking_number'); + if ($order->update()) + { + // Update order_carrier + $id_order_invoice = Tools::getValue('id_order_invoice'); + $id_carrier = Tools::getValue('id_carrier'); + Db::getInstance()->execute(' + UPDATE `'._DB_PREFIX_.'order_carrier` + SET `tracking_number` = '.pSQL(Tools::getValue('tracking_number')).' + WHERE `id_order` = '.(int)$order->id. + ' AND `id_carrier` = '.(int)$id_carrier. + ($id_order_invoice ? ' AND `id_order_invoice` = '.(int)$id_order_invoice : '')); + + global $_LANGMAIL; + $customer = new Customer((int)$order->id_customer); + $carrier = new Carrier((int)$order->id_carrier); + if (!Validate::isLoadedObject($customer)) + throw new PrestashopException('Can\'t load Customer object'); + if (!Validate::isLoadedObject($carrier)) + throw new PrestashopException('Can\'t load Carrier object'); + $templateVars = array( + '{followup}' => str_replace('@', $order->shipping_number, $carrier->url), + '{firstname}' => $customer->firstname, + '{lastname}' => $customer->lastname, + '{id_order}' => (int)$order->id + ); + @Mail::Send((int)$order->id_lang, 'in_transit', Mail::l('Package in transit'), $templateVars, + $customer->email, $customer->firstname.' '.$customer->lastname, NULL, NULL, NULL, NULL, + _PS_MAIL_DIR_, true); + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); + } + else + $this->_errors[] = Tools::displayError('An error occured on updating of order'); } + else + $this->_errors[] = Tools::displayError('Shipping number is incorrect'); } else $this->_errors[] = Tools::displayError('You do not have permission to edit here.'); @@ -256,11 +304,11 @@ class AdminOrdersControllerCore extends AdminController if (Validate::isLoadedObject($order)) { $varsTpl = array( - '{lastname}' => $customer->lastname, - '{firstname}' => $customer->firstname, - '{id_order}' => $order->id, - '{message}' => (Configuration::get('PS_MAIL_TYPE') == 2 ? $cm->message : Tools::nl2br($cm->message)) - ); + '{lastname}' => $customer->lastname, + '{firstname}' => $customer->firstname, + '{id_order}' => $order->id, + '{message}' => (Configuration::get('PS_MAIL_TYPE') == 2 ? $cm->message : Tools::nl2br($cm->message)) + ); if (@Mail::Send((int)($order->id_lang), 'order_merchant_comment', Mail::l('New message regarding your order'), $varsTpl, $customer->email, $customer->firstname.' '.$customer->lastname, NULL, NULL, NULL, NULL, _PS_MAIL_DIR_, true)) @@ -349,10 +397,11 @@ class AdminOrdersControllerCore extends AdminController { $reinjectableQuantity = (int)($orderDetail->product_quantity) - (int)($orderDetail->product_quantity_reinjected); $quantityToReinject = $qtyCancelProduct > $reinjectableQuantity ? $reinjectableQuantity : $qtyCancelProduct; - if (!Product::reinjectQuantities($orderDetail, $quantityToReinject)) - $this->_errors[] = Tools::displayError('Cannot re-stock product').' '.$orderDetail->product_name.''; - else - { + // TODO (Denis) : fix reinject quantities + // if (!Product::reinjectQuantities($orderDetail, $quantityToReinject)) + // $this->_errors[] = Tools::displayError('Cannot re-stock product').' '.$orderDetail->product_name.''; + // else + // { $updProductAttributeID = !empty($orderDetail->product_attribute_id) ? (int)($orderDetail->product_attribute_id) : NULL; $newProductQty = Product::getQuantity($orderDetail->product_id, $updProductAttributeID); $product = get_object_vars(new Product($orderDetail->product_id, false, $this->context->language->id, $order->id_shop)); @@ -367,7 +416,7 @@ class AdminOrdersControllerCore extends AdminController $product['stock_quantity'] = $updProduct['stock_quantity']; } Hook::exec('updateQuantity', array('product' => $product, 'order' => $order)); - } + // } } // Delete product @@ -436,6 +485,7 @@ class AdminOrdersControllerCore extends AdminController { Message::markAsReaded($_GET['messageReaded'], $this->context->employee->id); } + // TODO clean PaymentCC else if (Tools::isSubmit('setTransactionId') && ((int)Tools::getValue('id_order'))) { $order = new Order((int)(Tools::getValue('id_order'))); @@ -449,9 +499,34 @@ class AdminOrdersControllerCore extends AdminController unset($order, $pcc); } + else if (Tools::isSubmit('submitAddPayment')) + { + if ($this->tabAccess['edit'] === '1') + { + $order = new Order(Tools::getValue('id_order')); + $amount = str_replace(',', '.', Tools::getValue('payment_amount')); + $currency = new Currency(Tools::getValue('payment_currency')); + if (!Validate::isLoadedObject($order)) + $this->_errors[] = Tools::displayError('Order can\'t be found'); + elseif (!Validate::isPrice($amount)) + $this->_errors[] = Tools::displayError('Amount is invalid'); + elseif (!Validate::isString(Tools::getValue('payment_method'))) + $this->_errors[] = Tools::displayError('Payment method is invalid'); + elseif (!Validate::isString(Tools::getValue('payment_transaction_id'))) + $this->_errors[] = Tools::displayError('Transaction ID is invalid'); + elseif (!Validate::isLoadedObject($currency)) + $this->_errors[] = Tools::displayError('Currency is invalid'); + elseif (!Validate::isDate(Tools::getValue('payment_date'))) + $this->_errors[] = Tools::displayError('Date is invalid'); + else + if (!$order->addOrderPayment($amount, Tools::getValue('payment_method'), Tools::getValue('payment_transaction_id'), $currency, Tools::getValue('payment_date'))) + $this->_errors[] = Tools::displayError('An error occured on adding of order payment'); + } + else + $this->_errors[] = Tools::displayError('You do not have permission to edit here.'); + } elseif (Tools::isSubmit('submitAddOrder') == 1 && ($id_cart = Tools::getValue('id_cart')) && ($module_name = pSQL(Tools::getValue('payment_module_name'))) && ($id_order_state = Tools::getValue('id_order_state'))) { - if ($this->tabAccess['edit'] === '1') { $payment_module = Module::getInstanceByName($module_name); @@ -463,6 +538,29 @@ class AdminOrdersControllerCore extends AdminController else $this->_errors[] = Tools::displayError('You do not have permission to add here.'); } + elseif (Tools::isSubmit('submitAddressShipping') || Tools::isSubmit('submitAddressInvoice')) + { + if ($this->tabAccess['edit'] === '1') + { + $address = new Address(Tools::getValue('id_address')); + if (Validate::isLoadedObject($address)) + { + // Update the address on order + $order = new Order(Tools::getValue('id_order')); + if (Tools::isSubmit('submitAddressShipping')) + $order->id_address_delivery = $address->id; + elseif (Tools::isSubmit('submitAddressInvoice')) + $order->id_address_invoice = $address->id; + $order->update(); + Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token); + } + else + $this->_errors[] = Tools::displayErrror('This address can\'t be loaded'); + } + else + $this->_errors[] = Tools::displayError('You do not have permission to edit here.'); + } + parent::postProcess(); } @@ -470,22 +568,11 @@ class AdminOrdersControllerCore extends AdminController { $order = $this->loadObject(); if (!Validate::isLoadedObject($order)) - return; + throw new PrestashopException('object can\'t be loaded'); $customer = new Customer($order->id_customer); $carrier = new Carrier($order->id_carrier); - $products = $order->getProducts(); - - foreach ($products as &$product) - { - if ($product['image'] != null) - { - $name = 'product_mini_'.(int)$product['product_id'].(isset($product['product_attribute_id']) ? '_'.(int)$product['product_attribute_id'] : '').'.jpg'; - // generate image cache, only for back office - $product['image_tag'] = cacheImage(_PS_IMG_DIR_.'p/'.$product['image']->getExistingImgPath().'.jpg', $name, 45, 'jpg'); - $product['image_size'] = getimagesize(_PS_TMP_IMG_DIR_.$name); - } - } + $products = $this->getProducts($order); // Carrier module call $carrier_module_call = null; @@ -514,11 +601,14 @@ class AdminOrdersControllerCore extends AdminController $deliveryState = new State((int)($addressDelivery->id_state)); } + $this->toolbar_title = $this->l('Order #').sprintf('%06d', $order->id).' - '.$customer->firstname.' '.$customer->lastname; + // Smarty assign $this->tpl_view_vars = array( 'order' => $order, 'cart' => new Cart($order->id), 'customer' => $customer, + 'customer_addresses' => $customer->getAddresses($this->context->language->id), 'addresses' => array( 'delivery' => $addressDelivery, 'deliveryState' => isset($deliveryState) ? $deliveryState : null, @@ -528,6 +618,7 @@ class AdminOrdersControllerCore extends AdminController 'customerStats' => $customer->getStats(), 'products' => $products, 'discounts' => $order->getCartRules(), + 'total_paid' => $order->getTotalPaid(), 'returns' => OrderReturn::getOrdersReturn($order->id_customer, $order->id), 'slips' => OrderSlip::getOrdersSlip($order->id_customer, $order->id), 'orderMessages' => OrderMessage::getOrderMessages($order->id_lang), @@ -539,20 +630,23 @@ class AdminOrdersControllerCore extends AdminController 'sources' => ConnectionsSource::getOrderSources($order->id), 'currentState' => OrderHistory::getLastOrderState($order->id), 'currency' => new Currency($order->id_currency), + 'currencies' => Currency::getCurrencies(), 'previousOrder' => $order->getPreviousOrderId(), 'nextOrder' => $order->getNextOrderId(), 'currentIndex' => self::$currentIndex, 'carrierModuleCall' => $carrier_module_call, 'iso_code_lang' => $this->context->language->iso_code, 'id_lang' => $this->context->language->id, - 'paymentCCDetails' => PaymentCC::getByOrderId($order->id), - + 'can_edit' => ($this->tabAccess['edit'] == 1), + 'current_id_lang' => $this->context->language->id, + 'invoices_collection' => $order->getInvoicesCollection(), 'HOOK_INVOICE' => Hook::exec('invoice', array('id_order' => $order->id)), 'HOOK_ADMIN_ORDER' => Hook::exec('adminOrder', array('id_order' => $order->id)) ); return parent::initView(); } + public function ajaxProcessSearchCustomers() { if ($customers = Customer::searchByName(pSQL(Tools::getValue('customer_search')))) @@ -571,11 +665,18 @@ class AdminOrdersControllerCore extends AdminController { foreach ($products AS &$product) { - $product['price'] = Tools::displayPrice(Tools::convertPrice($product['price'], $currency), $currency); + // Formatted price + $product['formatted_price'] = Tools::displayPrice(Tools::convertPrice($product['price_tax_incl'], $currency), $currency); + // Concret price + $product['price_tax_incl'] = Tools::ps_round(Tools::convertPrice($product['price_tax_incl'], $currency), 2); + $product['price_tax_excl'] = Tools::ps_round(Tools::convertPrice($product['price_tax_excl'], $currency), 2); $productObj = new Product((int)$product['id_product'], false, (int)$this->context->language->id); $combinations = array(); $attributes = $productObj->getAttributesGroups((int)$this->context->language->id); $product['qty_in_stock'] = StockAvailable::getQuantityAvailableByProduct((int)$product['id_product'], 0, (int)$this->context->shop->getID()); + // Tax rate for this customer + if (Tools::isSubmit('id_address')) + $product['tax_rate'] = $productObj->getTaxesRate(new Address(Tools::getValue('id_address'))); foreach($attributes AS $attribute) { if (!isset($combinations[$attribute['id_product_attribute']]['attributes'])) @@ -584,7 +685,13 @@ class AdminOrdersControllerCore extends AdminController $combinations[$attribute['id_product_attribute']]['id_product_attribute'] = $attribute['id_product_attribute']; $combinations[$attribute['id_product_attribute']]['default_on'] = $attribute['default_on']; if (!isset($combinations[$attribute['id_product_attribute']]['price'])) - $combinations[$attribute['id_product_attribute']]['price'] = Tools::displayPrice(Tools::convertPrice(Product::getPriceStatic((int)$product['id_product'], true, $attribute['id_product_attribute']), $currency), $currency); + { + $price_tax_incl = Product::getPriceStatic((int)$product['id_product'], true, $attribute['id_product_attribute']); + $price_tax_excl = Product::getPriceStatic((int)$product['id_product'], false, $attribute['id_product_attribute']); + $combinations[$attribute['id_product_attribute']]['price_tax_incl'] = Tools::ps_round(Tools::convertPrice($price_tax_incl, $currency), 2); + $combinations[$attribute['id_product_attribute']]['price_tax_excl'] = Tools::ps_round(Tools::convertPrice($price_tax_excl, $currency), 2); + $combinations[$attribute['id_product_attribute']]['formatted_price'] = Tools::displayPrice(Tools::convertPrice($price_tax_incl, $currency), $currency); + } if (!isset($combinations[$attribute['id_product_attribute']]['qty_in_stock'])) $combinations[$attribute['id_product_attribute']]['qty_in_stock']= StockAvailable::getQuantityAvailableByProduct((int)$product['id_product'], $attribute['id_product_attribute'], (int)$this->context->shop->getID()); } @@ -593,8 +700,10 @@ class AdminOrdersControllerCore extends AdminController $combination['attributes'] = rtrim($combination['attributes'], ' - '); $product['combinations'] = $combinations; } - $to_return = array('products' => $products, - 'found' => true); + $to_return = array( + 'products' => $products, + 'found' => true + ); } else $to_return = array('found' => false); @@ -623,4 +732,480 @@ class AdminOrdersControllerCore extends AdminController $this->content = Tools::jsonEncode(array('errors' => true, 'result' => $this->l('Error in sending the email to your customer.'))); } } + + public function ajaxProcessAddProductOnOrder() + { + // Load object + $order = new Order(Tools::getValue('id_order')); + if (!Validate::isLoadedObject($order)) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t load Order object') + ))); + + $product_informations = $_POST['add_product']; + $product = new Product($product_informations['product_id'], false, $order->id_lang); + if (!Validate::isLoadedObject($product)) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t load Product object') + ))); + + if (isset($product_informations['product_attribute_id']) && $product_informations['product_attribute_id']) + { + $combination = new Combination($product_informations['product_attribute_id']); + if (!Validate::isLoadedObject($combination)) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t load Combination object') + ))); + } + + // Create new cart + $cart = new Cart(); + $cart->id_group_shop = $order->id_group_shop; + $cart->id_shop = $order->id_shop; + $cart->id_customer = $order->id_customer; + $cart->id_carrier = $order->id_carrier; + $cart->id_address_delivery = $order->id_address_delivery; + $cart->id_address_invoice = $order->id_address_invoice; + $cart->id_currency = $order->id_currency; + $cart->id_customer = $order->id_customer; + $cart->id_lang = $order->id_lang; + $cart->id_carrier = $order->id_carrier; + $cart->secure_key = $order->secure_key; + + // Save new cart + $cart->add(); + + // Save context (in order to apply cart rule) + $this->context->cart = $cart; + $this->context->customer = new Customer($order->id_customer); + + // Add product to cart + $cart->updateQty($product_informations['product_quantity'], $product->id, isset($combination) ? $combination->id : null, false, 'up', new Shop($cart->id_shop)); + + $use_taxes = ($order->getTaxCalculationMethod() == PS_TAX_INC); + + $initial_prodcut_price_tax_incl = Product::getPriceStatic($product->id, $use_taxes, isset($combination) ? $combination->id : null, 2, null, false, true, 1, + false, $order->id_customer, $cart->id, $order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); + + if ($product_informations['product_price_tax_incl'] < $initial_prodcut_price_tax_incl) + { + $reduction_tax_incl = $initial_prodcut_price_tax_incl - $product_informations['product_price_tax_incl']; + + // FIXME Cart Rule isn't applied but correctly save in database + $cart_rule = new CartRule(); + $cart_rule->id_customer = $order->id_customer; + $cart_rule->date_from = date('Y-m-d H:i:s', time()); + $cart_rule->date_to = date('Y-m-d H:i:s', time() + 24 * 3600); + $cart_rule->quantity = 1; + $cart_rule->quantity_per_user = 1; + $cart_rule->minimum_amount_currency = $order->id_currency; + $cart_rule->reduction_product = $product->id; + $cart_rule->reduction_amount = $reduction_tax_incl; + $cart_rule->reduction_currency = $order->id_currency; + $cart_rule->active = 1; + $cart_rule->add(); + + $cart->addCartRule($cart_rule->id); + //$order->addCartRule($cart_rule->id, $cart_rule->name, $cart_rule->getContextualValue(true)); + } + + // If order is valid, we can create a new invoice or edit an existing invoice + if ($order->valid) + { + $order_invoice = new OrderInvoice($product_informations['invoice']); + // Create new invoice + if ($order_invoice->id == 0) + { + // Create Cart rule in order to make free shipping + if (isset($invoice_informations['free_shipping']) && $invoice_informations['free_shipping']) + { + // FIXME Cart Rule isn't applied but correctly save in database + $cart_rule = new CartRule(); + $cart_rule->id_customer = $order->id_customer; + $cart_rule->date_from = date('Y-m-d H:i:s', time()); + $cart_rule->date_to = date('Y-m-d H:i:s', time() + 24 * 3600); + $cart_rule->quantity = 1; + $cart_rule->quantity_per_user = 1; + $cart_rule->minimum_amount_currency = $order->id_currency; + $cart_rule->reduction_currency = $order->id_currency; + $cart_rule->free_shipping = true; + $cart_rule->active = 1; + $cart_rule->add(); + + $cart->addCartRule($cart_rule->id); + //$order->addCartRule($cart_rule->id, $cart_rule->name, $cart_rule->getContextualValue(true)); + } + if (Tools::isSubmit('add_invoice')) + $invoice_informations = $_POST['add_invoice']; + $order_invoice->id_order = $order->id; + if ($order_invoice->number) + Configuration::updateValue('PS_INVOICE_START_NUMBER', false); + else + $order_invoice->number = Order::getLastInvoiceNumber() + 1; + $order_invoice->total_paid_tax_excl = Tools::ps_round((float)$cart->getOrderTotal(false, Cart::BOTH), 2); + $order_invoice->total_paid_tax_incl = Tools::ps_round((float)$cart->getOrderTotal($use_taxes, Cart::BOTH), 2); + $order_invoice->total_products = (float)$cart->getOrderTotal(false, Cart::ONLY_PRODUCTS); + $order_invoice->total_products_wt = (float)$cart->getOrderTotal($use_taxes, Cart::ONLY_PRODUCTS); + $order_invoice->total_shipping_tax_excl = (float)$cart->getOrderShippingCost(null, false); + $order_invoice->total_shipping_tax_incl = (float)$cart->getOrderShippingCost(); + $order_invoice->total_wrapping_tax_excl = abs($cart->getOrderTotal(false, Cart::ONLY_WRAPPING)); + $order_invoice->total_wrapping_tax_incl = abs($cart->getOrderTotal($use_taxes, Cart::ONLY_WRAPPING)); + + // Update current order field, only shipping because other field is updated later + $order->total_shipping += (float)$cart->getOrderShippingCost(); + $order->total_shipping_tax_excl += (float)$cart->getOrderShippingCost(null, false); + $order->total_shipping_tax_incl += (float)$cart->getOrderShippingCost(null, $use_taxes); + + $order->total_wrapping += abs($cart->getOrderTotal($use_taxes, Cart::ONLY_WRAPPING)); + $order->total_wrapping_tax_excl += abs($cart->getOrderTotal(false, Cart::ONLY_WRAPPING)); + $order->total_wrapping_tax_incl += abs($cart->getOrderTotal($use_taxes, Cart::ONLY_WRAPPING)); + $order_invoice->add(); + // Adding an entry in order_carrier table + Db::getInstance()->execute(' + INSERT INTO `'._DB_PREFIX_.'order_carrier` (`id_order`, `id_carrier`, `id_order_invoice`, `weight`, `shipping_cost_tax_excl`, `shipping_cost_tax_incl`, `date_add`) VALUES + ('.(int)$order->id.', '.(int)$order->id_carrier.', '.(int)$order_invoice->id.', '.(float)$cart->getTotalWeight().', '.(float)$cart->getOrderShippingCost(null, false).', '.(float)$cart->getOrderShippingCost(null, $use_taxes).', NOW())'); + } + // Update current invoice + else + { + $order_invoice->total_paid_tax_excl += Tools::ps_round((float)($cart->getOrderTotal(false, Cart::BOTH)), 2); + $order_invoice->total_paid_tax_incl += Tools::ps_round((float)($cart->getOrderTotal($use_taxes, Cart::BOTH)), 2); + $order_invoice->total_products += (float)$cart->getOrderTotal(false, Cart::ONLY_PRODUCTS); + $order_invoice->total_products_wt += (float)$cart->getOrderTotal($use_taxes, Cart::ONLY_PRODUCTS); + $order_invoice->total_shipping_tax_excl += (float)$cart->getOrderShippingCost(null, false); + $order_invoice->total_shipping_tax_incl += (float)$cart->getOrderShippingCost(null, $use_taxes); + $order_invoice->total_wrapping_tax_excl += abs($cart->getOrderTotal(false, Cart::ONLY_WRAPPING)); + $order_invoice->total_wrapping_tax_incl += abs($cart->getOrderTotal($use_taxes, Cart::ONLY_WRAPPING)); + $order_invoice->update(); + } + } + + // Create Order detail information + $order_detail = new OrderDetail(); + $order_detail->createList($order, $cart, OrderHistory::getLastOrderState($order->id), $cart->getProducts(), (isset($order_invoice) ? $order_invoice->id : 0), $use_taxes); + + // update totals amount of order + $order->total_products += (float)$cart->getOrderTotal(false, Cart::ONLY_PRODUCTS); + $order->total_products_wt += (float)$cart->getOrderTotal($use_taxes, Cart::ONLY_PRODUCTS); + + $order->total_paid += Tools::ps_round((float)($cart->getOrderTotal(true, Cart::BOTH)), 2); + $order->total_paid_tax_excl += Tools::ps_round((float)($cart->getOrderTotal(false, Cart::BOTH)), 2); + $order->total_paid_tax_incl += Tools::ps_round((float)($cart->getOrderTotal($use_taxes, Cart::BOTH)), 2); + + // Save changes of order + $order->update(); + + $products = $this->getProducts($order); + // Get the last product + $product = $products[max(array_keys($products))]; + + // Assign to smarty informations in order to show the new product line + $this->context->smarty->assign(array( + 'product' => $product, + 'order' => $order, + 'currency' => new Currency($order->id_currency), + 'can_edit' => $this->tabAccess['edit'], + 'invoices_collection' => $order->getInvoicesCollection() + )); + + die(Tools::jsonEncode(array( + 'result' => true, + 'view' => $this->context->smarty->fetch('orders/_product_line.tpl'), + 'can_edit' => $this->tabAccess['add'], + 'order' => $order + ))); + } + + public function ajaxProcessLoadProductInformation() + { + $order_detail = new OrderDetail(Tools::getValue('id_order_detail')); + if (!Validate::isLoadedObject($order_detail)) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t load OrderDetail object') + ))); + + $product = new Product($order_detail->product_id); + if (!Validate::isLoadedObject($product)) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t load Product object') + ))); + + $address = new Address(Tools::getValue('id_address')); + if (!Validate::isLoadedObject($address)) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t load Address object') + ))); + + die(Tools::jsonEncode(array( + 'result' => true, + 'product' => $product, + 'tax_rate' => $product->getTaxesRate($address), + 'price_tax_incl' => Product::getPriceStatic($product->id, true, $order_detail->product_attribute_id, 2), + 'price_tax_excl' => Product::getPriceStatic($product->id, false, $order_detail->product_attribute_id, 2) + ))); + } + + public function ajaxProcessEditProductOnOrder() + { + // Return value + $res = true; + + $order_detail = new OrderDetail(Tools::getValue('product_id_order_detail')); + if (Tools::isSubmit('product_invoice')) + $order_invoice = new OrderInvoice(Tools::getValue('product_invoice')); + + $this->doEditProductValidation($order_detail, isset($order_invoice) ? $order_invoice : null); + + $product_price_tax_incl = Tools::ps_round(Tools::getValue('product_price_tax_incl'), 2); + $product_price_tax_excl = Tools::ps_round(Tools::getValue('product_price_tax_excl'), 2); + $total_products_tax_incl = $product_price_tax_incl * Tools::getValue('product_quantity'); + $total_products_tax_excl = $product_price_tax_excl * Tools::getValue('product_quantity'); + + // Calculate differences of price (Before / After) + $diff_price_tax_incl = $total_products_tax_incl - $order_detail->total_price_tax_incl; + $diff_price_tax_excl = $total_products_tax_excl - $order_detail->total_price_tax_excl; + + // Apply change on OrderInvoice + if (isset($order_invoice)) + // If OrderInvoice to use is different, we update the old invoice and new invoice + if ($order_detail->id_order_invoice != $order_invoice->id) + { + $old_order_invoice = new OrderInvoice($order_detail->id_order_invoice); + // We remove cost of products + $old_order_invoice->total_products -= $order_detail->total_price_tax_excl; + $old_order_invoice->total_products_wt -= $order_detail->total_price_tax_incl; + + $old_order_invoice->total_paid_tax_excl -= $order_detail->total_price_tax_excl; + $old_order_invoice->total_paid_tax_incl -= $order_detail->total_price_tax_incl; + + $res &= $old_order_invoice->update(); + // TODO remove invoice if no item ? + + $order_invoice->total_products += $order_detail->total_price_tax_excl; + $order_invoice->total_products_wt += $order_detail->total_price_tax_incl; + + $order_invoice->total_paid_tax_excl += $order_detail->total_price_tax_excl; + $order_invoice->total_paid_tax_incl += $order_detail->total_price_tax_incl; + + $order_detail->id_order_invoice = $order_invoice->id; + } + + if ($diff_price_tax_incl != 0 && $diff_price_tax_excl != 0) + { + $order_detail->unit_price_tax_excl = $product_price_tax_excl; + $order_detail->unit_price_tax_incl = $product_price_tax_incl; + + $order_detail->total_price_tax_incl += $diff_price_tax_incl; + $order_detail->total_price_tax_excl += $diff_price_tax_excl; + + if (isset($order_invoice)) + { + // Apply changes on OrderInvoice + $order_invoice->total_products += $diff_price_tax_excl; + $order_invoice->total_products_wt += $diff_price_tax_incl; + + $order_invoice->total_paid_tax_excl += $diff_price_tax_excl; + $order_invoice->total_paid_tax_incl += $diff_price_tax_incl; + } + + // Apply changes on Order + $order = new Order($order_detail->id_order); + $order->total_products += $diff_price_tax_excl; + $order->total_products_wt += $diff_price_tax_incl; + + $order->total_paid += $diff_price_tax_incl; + $order->total_paid_tax_excl += $diff_price_tax_excl; + $order->total_paid_tax_incl += $diff_price_tax_incl; + + $res &= $order->update(); + } + + $order_detail->product_quantity = Tools::getValue('product_quantity'); + // Save order detail + $res &= $order_detail->update(); + // Save order invoice + if (isset($order_invoice)) + $res &= $order_invoice->update(); + + $products = $this->getProducts($order); + // Get the last product + $product = $products[$order_detail->id]; + + // Assign to smarty informations in order to show the new product line + $this->context->smarty->assign(array( + 'product' => $product, + 'order' => $order, + 'currency' => new Currency($order->id_currency), + 'can_edit' => $this->tabAccess['edit'] + )); + + if (!$res) + die(Tools::jsonEncode(array( + 'result' => $res, + 'error' => Tools::displayError('Error occured on edition of this product line') + ))); + + die(Tools::jsonEncode(array( + 'result' => $res, + 'view' => $this->context->smarty->fetch('orders/_product_line.tpl'), + 'can_edit' => $this->tabAccess['add'], + 'invoices_collection' => $order->getInvoicesCollection(), + 'order' => $order + ))); + } + + public function ajaxProcessDeleteProductLine() + { + $res = true; + + $order_detail = new OrderDetail(Tools::getValue('id_order_detail')); + $order = new Order(Tools::getValue('id_order')); + + $this->doDeleteProductLinveValidation($order_detail, $order); + + // Update OrderInvoice of this OrderDetail + if ($order_detail->id_order_invoice != 0) + { + $order_invoice = new OrderInvoice($order_detail->id_order_invoice); + + /* + TODO refresh total_discount + $order_invoice->total_discount_tax_excl -= ; + $order_invoice->total_discount_tax_incl -= ; + $order_invoice->total_shipping_tax_excl -= ; + $order_invoice->total_shipping_tax_incl -= ; + $order_invoice->total_wrapping_tax_excl -= ; + $order_invoice->total_wrapping_tax_incl -= ; + */ + $order_invoice->total_paid_tax_excl -= $order_detail->total_price_tax_incl; + $order_invoice->total_paid_tax_incl -= $order_detail->total_price_tax_excl; + $order_invoice->total_products -= $order_detail->total_price_tax_incl; + $order_invoice->total_products_wt -= $order_detail->total_price_tax_excl; + $res &= $order_invoice->update(); + } + + // Update Order + /* + * TODO + $order->total_discounts -= ; + $order->total_discounts_tax_incl -= ; + $order->total_discounts_tax_excl -= ; + $order->total_discounts_tax_excl -= ; + $order->total_shipping -= ; + $order->total_shipping_tax_incl -= ; + $order->total_shipping_tax_excl -= ; + $order->total_wrapping -= ; + $order->total_wrapping_tax_incl -= ; + $order->total_wrapping_tax_excl -= ; + */ + $order->total_paid -= $order_detail->total_price_tax_incl; + $order->total_paid_tax_incl -= $order_detail->total_price_tax_incl; + $order->total_paid_tax_excl -= $order_detail->total_price_tax_excl; + $order->total_products -= $order_detail->total_price_tax_incl; + $order->total_products_wt -= $order_detail->total_price_tax_excl; + + $res &= $order->update(); + + // Delete OrderDetail + $res &= $order_detail->delete(); + + if (!$res) + die(Tools::jsonEncode(array( + 'result' => $res, + 'error' => Tools::displayError('Error occured on deletion of this product line') + ))); + + die(Tools::jsonEncode(array( + 'result' => $res, + 'order' => $order + ))); + } + + protected function doEditProductValidation(OrderDetail $order_detail, OrderInvoice $order_invoice = null) + { + if (!Validate::isLoadedObject($order_detail)) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t load Order Detail object') + ))); + + if (!empty($order_invoice) && !Validate::isLoadedObject($order_invoice)) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t load Invoice object') + ))); + + if ($order_detail->id_order != Tools::getValue('id_order')) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t edit this Order Detail for this order') + ))); + + if ($order_invoice->id_order != Tools::getValue('id_order')) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t use this invoice for this order') + ))); + + // Clean price + $product_price_tax_incl = str_replace(',', '.', Tools::getValue('product_price_tax_incl')); + $product_price_tax_excl = str_replace(',', '.', Tools::getValue('product_price_tax_excl')); + + if (!Validate::isPrice($product_price_tax_incl) || !Validate::isPrice($product_price_tax_excl)) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Invalid price') + ))); + + if (!Validate::isUnsignedInt(Tools::getValue('product_quantity'))) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Invalid quantity') + ))); + } + + protected function doDeleteProductLinveValidation(OrderDetail $order_detail, Order $order) + { + if (!Validate::isLoadedObject($order_detail)) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t load Order Detail object') + ))); + + if (!Validate::isLoadedObject($order)) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t load Order object') + ))); + + if ($order_detail->id_order != $order->id) + die(Tools::jsonEncode(array( + 'result' => false, + 'error' => Tools::displayError('Can\'t delete this Order Detail for this order') + ))); + } + + protected function getProducts($order) + { + $products = $order->getProducts(); + + foreach ($products as &$product) + { + if ($product['image'] != null) + { + $name = 'product_mini_'.(int)$product['product_id'].(isset($product['product_attribute_id']) ? '_'.(int)$product['product_attribute_id'] : '').'.jpg'; + // generate image cache, only for back office + $product['image_tag'] = cacheImage(_PS_IMG_DIR_.'p/'.$product['image']->getExistingImgPath().'.jpg', $name, 45, 'jpg'); + $product['image_size'] = getimagesize(_PS_TMP_IMG_DIR_.$name); + } + } + + return $products; + } } diff --git a/controllers/admin/AdminProductsController.php b/controllers/admin/AdminProductsController.php index c65932955..c5b6e76be 100644 --- a/controllers/admin/AdminProductsController.php +++ b/controllers/admin/AdminProductsController.php @@ -1912,8 +1912,7 @@ class AdminProductsControllerCore extends AdminController public function getPreviewUrl(Product $product) { - $shop_url = new ShopUrl($this->context->shop->id); - if (!$shop_url->id && !empty($this->context->cookie->shopContext)) + if (!(bool)$this->context->shop->virtual_uri) return false; $preview_url = $this->context->link->getProductLink( diff --git a/install-dev/sql/db.sql b/install-dev/sql/db.sql index 8dce4aeec..1773292be 100644 --- a/install-dev/sql/db.sql +++ b/install-dev/sql/db.sql @@ -1047,16 +1047,36 @@ CREATE TABLE `PREFIX_orders` ( INDEX `date_add`(`date_add`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; -CREATE TABLE IF NOT EXISTS `PREFIX_order_detail_tax` ( +CREATE TABLE `PREFIX_order_detail_tax` ( `id_order_detail` int(11) NOT NULL, `id_tax` int(11) NOT NULL, `unit_amount` DECIMAL( 10,6 ) NOT NULL default '0.00', `total_amount` DECIMAL( 10, 6 ) NOT NULL default '0.00' ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; +CREATE TABLE `PREFIX_order_invoice` ( + `id_order_invoice` int(11) NOT NULL AUTO_INCREMENT, + `id_order` int(11) NOT NULL, + `number` int(11) NOT NULL, + `total_discount_tax_excl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_discount_tax_incl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_paid_tax_excl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_paid_tax_incl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_products` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_products_wt` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_shipping_tax_excl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_shipping_tax_incl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_wrapping_tax_excl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_wrapping_tax_incl` decimal(17,2) NOT NULL DEFAULT '0.00', + `date_add` datetime NOT NULL, + PRIMARY KEY (`id_order_invoice`), + KEY `id_order` (`id_order`) +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; + CREATE TABLE `PREFIX_order_detail` ( `id_order_detail` int(10) unsigned NOT NULL auto_increment, `id_order` int(10) unsigned NOT NULL, + `id_order_invoice` int(11) default NULL, `product_id` int(10) unsigned NOT NULL, `product_attribute_id` int(10) unsigned default NULL, `product_name` varchar(255) NOT NULL, @@ -1183,6 +1203,8 @@ CREATE TABLE `PREFIX_order_slip` ( `id_customer` int(10) unsigned NOT NULL, `id_order` int(10) unsigned NOT NULL, `shipping_cost` tinyint(3) unsigned NOT NULL default '0', + `amount` DECIMAL(10,2) NOT NULL, + `shipping_cost_amount` DECIMAL(10,2) NOT NULL, `date_add` datetime NOT NULL, `date_upd` datetime NOT NULL, PRIMARY KEY (`id_order_slip`), @@ -1194,6 +1216,7 @@ CREATE TABLE `PREFIX_order_slip_detail` ( `id_order_slip` int(10) unsigned NOT NULL, `id_order_detail` int(10) unsigned NOT NULL, `product_quantity` int(10) unsigned NOT NULL default '0', + `amount` DECIMAL(10,2) NOT NULL, PRIMARY KEY (`id_order_slip`,`id_order_detail`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; @@ -1250,18 +1273,21 @@ CREATE TABLE `PREFIX_page_viewed` ( PRIMARY KEY (`id_page`, `id_date_range`, `id_shop`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; -CREATE TABLE `PREFIX_payment_cc` ( - `id_payment_cc` INT NOT NULL auto_increment, +CREATE TABLE `PREFIX_order_payment` ( + `id_order_payment` INT NOT NULL auto_increment, + `id_order_invoice` INT UNSIGNED NULL, `id_order` INT UNSIGNED NULL, `id_currency` INT UNSIGNED NOT NULL, `amount` DECIMAL(10,2) NOT NULL, + `payment_method` varchar(255) NOT NULL, + `conversion_rate` decimal(13,6) NOT NULL DEFAULT 1, `transaction_id` VARCHAR(254) NULL, `card_number` VARCHAR(254) NULL, `card_brand` VARCHAR(254) NULL, `card_expiration` CHAR(7) NULL, `card_holder` VARCHAR(254) NULL, `date_add` DATETIME NOT NULL, - PRIMARY KEY (`id_payment_cc`), + PRIMARY KEY (`id_order_payment`), KEY `id_order` (`id_order`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; @@ -2245,3 +2271,17 @@ CREATE TABLE `PREFIX_accounting_product_zone_shop` ( PRIMARY KEY (`id_accounting_product_zone_shop`), UNIQUE KEY `id_product` (`id_product`,`id_shop`,`id_zone`) ) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; + +CREATE TABLE `PREFIX_order_carrier` ( + `id_order` int(11) unsigned NOT NULL, + `id_carrier` int(11) unsigned NOT NULL, + `id_order_invoice` int(11) unsigned DEFAULT NULL, + `weight` float DEFAULT NULL, + `shipping_cost_tax_excl` decimal(20,6) DEFAULT NULL, + `shipping_cost_tax_incl` decimal(20,6) DEFAULT NULL, + `tracking_number` int(11) unsigned DEFAULT NULL, + `date_add` datetime NOT NULL, + KEY `id_order` (`id_order`,`id_carrier`), + KEY `id_order_2` (`id_order`), + KEY `id_order_invoice` (`id_order_invoice`) +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; diff --git a/install-dev/sql/db_settings_extends.sql b/install-dev/sql/db_settings_extends.sql index 95f4c4146..dfc8a4297 100644 --- a/install-dev/sql/db_settings_extends.sql +++ b/install-dev/sql/db_settings_extends.sql @@ -180,8 +180,11 @@ INSERT INTO `PREFIX_order_detail` (`id_order_detail`, `id_order`, `product_id`, VALUES (1, 1, 7, 23, 'iPod touch - Capacité: 32Go', 1, 0, '392.140500', '0.000000', NULL, NULL, NULL, 0, '0.00', '', 0, '0000-00-00 00:00:00', ''); INSERT INTO `PREFIX_order_detail` (`id_order_detail`, `id_order`, `product_id`, `product_attribute_id`, `product_name`, `product_quantity`, `product_quantity_return`, `product_price`, `product_quantity_discount`, `product_ean13`, `product_reference`, `product_supplier_reference`, `product_weight`, `ecotax`, `download_hash`, `download_nb`, `download_deadline`, `tax_name`) VALUES (2, 1, 9, 0, 'Écouteurs à isolation sonore Shure SE210', 1, 0, '124.581900', '0.000000', NULL, NULL, NULL, 0, '0.00', '', 0, '0000-00-00 00:00:00', ''); + INSERT INTO `PREFIX_order_history` (`id_order_history`, `id_employee`, `id_order`, `id_order_state`, `date_add`) VALUES (1, 0, 1, 1, NOW()); +INSERT INTO `PREFIX_order_payment` (`id_order`, `id_currency`, `amount`, `payment_method`, `date_add`) VALUES (1, 1, '625.98', 'Chèque', NOW()); + INSERT INTO `PREFIX_manufacturer` (`id_manufacturer`, `name`, `date_add`, `date_upd`, `active`) VALUES (1, 'Apple Computer, Inc', NOW(), NOW(), 1); INSERT INTO `PREFIX_manufacturer` (`id_manufacturer`, `name`, `date_add`, `date_upd`, `active`) VALUES(2, 'Shure Incorporated', NOW(), NOW(), 1); @@ -1367,3 +1370,6 @@ INSERT INTO `PREFIX_stock_available` (`id_stock_available`, `id_product`, `id_pr (28, 6, 0, 1, 4, 0, 2), (29, 8, 0, 1, 8, 0, 2), (30, 9, 0, 1, 15, 0, 2); + +INSERT INTO `PREFIX_order_carrier` (`id_order`, `id_carrier`, `date_add`) VALUES +(1, 2, NOW()); diff --git a/install-dev/sql/upgrade/1.5.0.1.sql b/install-dev/sql/upgrade/1.5.0.1.sql index c970471d2..4d3d2acaf 100644 --- a/install-dev/sql/upgrade/1.5.0.1.sql +++ b/install-dev/sql/upgrade/1.5.0.1.sql @@ -239,6 +239,33 @@ ALTER TABLE `PREFIX_carrier` ADD `position` INT( 10 ) UNSIGNED NOT NULL DEFAULT ALTER TABLE `PREFIX_order_state` ADD COLUMN `shipped` TINYINT(1) UNSIGNED NOT NULL DEFAULT 0 AFTER `delivery`; UPDATE `PREFIX_order_state` SET `shipped` = 1 WHERE id_order_states IN (4, 5); +CREATE TABLE `PREFIX_order_invoice` ( + `id_order_invoice` int(11) NOT NULL AUTO_INCREMENT, + `id_order` int(11) NOT NULL, + `number` int(11) NOT NULL, + `total_discount_tax_excl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_discount_tax_incl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_paid_tax_excl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_paid_tax_incl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_products` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_products_wt` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_shipping_tax_excl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_shipping_tax_incl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_wrapping_tax_excl` decimal(17,2) NOT NULL DEFAULT '0.00', + `total_wrapping_tax_incl` decimal(17,2) NOT NULL DEFAULT '0.00', + `date_add` datetime NOT NULL, + PRIMARY KEY (`id_order_invoice`), + KEY `id_order` (`id_order`) +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; + +ALTER TABLE `PREFIX_order_detail` ADD `id_order_invoice` int(11) NULL AFTER `id_order`; + +ALTER TABLE `PREFIX_payment_cc` CHANGE `id_payment_cc` `id_order_payment` INT NOT NULL auto_increment; +ALTER TABLE `PREFIX_payment_cc` ADD `id_order_invoice` varchar(255) NOT NULL AFTER `id_order_payment`; +ALTER TABLE `PREFIX_payment_cc` ADD `payment_method` varchar(255) NOT NULL AFTER `amount`; +ALTER TABLE `PREFIX_payment_cc` ADD `conversion_rate` decimal(13,6) NOT NULL DEFAULT 1 AFTER `payment_method`; + +RENAME TABLE `PREFIX_payment_cc` TO `PREFIX_order_payment`; ALTER TABLE `PREFIX_carrier` ADD COLUMN `max_width` int(10) DEFAULT 0 AFTER `position`, @@ -264,7 +291,6 @@ ALTER TABLE `PREFIX_customization` ADD COLUMN `id_address_delivery` int(10) UNSI DROP PRIMARY KEY, ADD PRIMARY KEY USING BTREE(`id_customization`, `id_cart`, `id_product`, `id_address_delivery`); - CREATE TABLE `PREFIX_cart_rule` ( `id_cart_rule` int(10) unsigned NOT NULL auto_increment, `id_customer` int unsigned NOT NULL default 0, @@ -581,4 +607,22 @@ UPDATE `PREFIX_employee` SET `bo_theme` = 'default'; UPDATE `PREFIX_tab` SET `class_name` = 'AdminCmsContent' WHERE `class_name` = 'AdminCMSContent'; UPDATE `PREFIX_tab` SET `class_name` = 'AdminCms' WHERE `class_name` = 'AdminCMS'; UPDATE `PREFIX_tab` SET `class_name` = 'AdminCmsCategories' WHERE `class_name` = 'AdminCMSCategories'; -UPDATE `PREFIX_tab` SET `class_name` = 'AdminPdf' WHERE `class_name` = 'AdminPDF'; \ No newline at end of file +UPDATE `PREFIX_tab` SET `class_name` = 'AdminPdf' WHERE `class_name` = 'AdminPDF'; + +CREATE TABLE `PREFIX_order_carrier` ( + `id_order` int(11) unsigned NOT NULL, + `id_carrier` int(11) unsigned NOT NULL, + `id_order_invoice` int(11) unsigned DEFAULT NULL, + `weight` float DEFAULT NULL, + `shipping_cost_tax_excl` decimal(20,6) DEFAULT NULL, + `shipping_cost_tax_incl` decimal(20,6) DEFAULT NULL, + `tracking_number` int(11) unsigned DEFAULT NULL, + `date_add` datetime NOT NULL, + KEY `id_order` (`id_order`,`id_carrier`), + KEY `id_order_2` (`id_order`), + KEY `id_order_invoice` (`id_order_invoice`) +) ENGINE=ENGINE_TYPE DEFAULT CHARSET=utf8; + +ALTER TABLE `PREFIX_order_slip` ADD COLUMN `amount` DECIMAL(10,2) NOT NULL AFTER `shipping_cost`; +ALTER TABLE `PREFIX_order_slip` ADD COLUMN `shipping_cost_amount` DECIMAL(10,2) NOT NULL AFTER `amount`; +ALTER TABLE `PREFIX_order_slip_detail` ADD COLUMN `amount` DECIMAL(10,2) NOT NULL AFTER `product_quantity`; diff --git a/js/admin_order.js b/js/admin_order.js new file mode 100644 index 000000000..ce9a3390a --- /dev/null +++ b/js/admin_order.js @@ -0,0 +1,621 @@ +/* +* 2007-2011 PrestaShop +* +* NOTICE OF LICENSE +* +* This source file is subject to the Academic Free License (AFL 3.0) +* that is bundled with this package in the file LICENSE.txt. +* It is also available through the world-wide-web at this URL: +* http://opensource.org/licenses/afl-3.0.php +* 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 http://www.prestashop.com for more information. +* +* @author PrestaShop SA +* @copyright 2007-2011 PrestaShop SA +* @version Release: $Revision: 10575 $ +* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) +* International Registered Trademark & Property of PrestaShop SA +*/ + +var current_product = null; + +$(document).ready(function() { + $('.add_product').click(function() { + $('.cancel_product_change_link:visible').trigger('click'); + $('tr#new_product').slideDown('fast', function () { + $('tr#new_product td').fadeIn('fast'); + }); + + $.scrollTo('tr#new_product', 1200, {offset: -100}); + + return false; + }); + + $("#add_product_product_name").autocomplete(admin_order_tab_link, + { + minChars: 3, + max: 10, + width: 500, + selectFirst: false, + scroll: false, + dataType: "json", + highlightItem: true, + formatItem: function(data, i, max, value, term) { + return value; + }, + parse: function(data) { + var products = new Array(); + for (var i = 0; i < data.products.length; i++) + products[i] = { data: data.products[i], value: data.products[i].name }; + return products; + }, + extraParams: { + ajax: true, + token: token, + action: 'searchProducts', + id_lang: id_lang, + id_currency: id_currency, + id_address: id_address, + product_search: function() { return $('#add_product_product_name').val(); } + } + } + ) + .result(function(event, data, formatted) { + if (!data) + { + $('tr#new_product input, tr#new_product select').each(function() { + if ($(this).attr('id') != 'add_product_product_name') + $('tr#new_product input, tr#new_product select').attr('disabled', 'disabled'); + }); + } + else + { + $('tr#new_product input, tr#new_product select').removeAttr('disabled'); + // Keep product variable + current_product = data; + $('#add_product_product_id').val(data.id_product); + $('#add_product_product_name').val(data.name); + $('#add_product_product_price_tax_incl').val(data.price_tax_incl); + $('#add_product_product_price_tax_excl').val(data.price_tax_excl); + addProductRefreshTotal(); + $('#add_product_product_stock').html(data.qty_in_stock); + + if (current_product.combinations.length !== 0) + { + // Reset combinations list + $('select#add_product_product_attribute_id').html(''); + $.each(current_product.combinations, function() { + $('select#add_product_product_attribute_id').append(''); + if (this.default_on == 1) + $('#add_product_product_stock').html(this.qty_in_stock); + }); + // Show select list + $('#add_product_product_attribute_area').show(); + } + else + { + // Reset combinations list + $('select#add_product_product_attribute_id').html(''); + // Hide select list + $('#add_product_product_attribute_area').hide(); + } + } + }); + + $('select#add_product_product_attribute_id').change(function() { + $('#add_product_product_price_tax_incl').val(current_product.combinations[$(this).val()].price_tax_incl); + $('#add_product_product_price_tax_excl').val(current_product.combinations[$(this).val()].price_tax_excl); + + addProductRefreshTotal(); + + $('#add_product_product_stock').html(current_product.combinations[$(this).val()].qty_in_stock); + }); + + $('input#add_product_product_quantity').keyup(function() { + var quantity = parseInt($(this).val()); + if (quantity < 1 || isNaN(quantity)) + quantity = 1; + var stock_available = parseInt($('#add_product_product_stock').html()); + // total update + addProductRefreshTotal(); + + // stock status update + if (quantity > stock_available) + $('#add_product_product_stock').css('font-weight', 'bold').css('color', 'red').css('font-size', '1.2em'); + else + $('#add_product_product_stock').css('font-weight', 'normal').css('color', 'black').css('font-size', '1em');; + }); + + $('#submitAddProduct').click(function() { + var go = true; + + if ($('input#add_product_product_id').val() == 0) + { + alert(txt_add_product_no_product); + go = false; + } + + if ($('input#add_product_product_quantity').val() == 0) + { + alert(txt_add_product_no_product_quantity); + go = false; + } + + if ($('input#add_product_product_price_excl').val() == 0) + { + alert(txt_add_product_no_product_price); + go = false; + } + + if (go) + { + if (parseInt($('input#add_product_product_quantity').val()) > parseInt($('#add_product_product_stock').html())) + go = confirm(txt_add_product_stock_issue); + + if (go && $('select#add_product_product_invoice').val() == 0) + go = confirm(txt_add_product_new_invoice); + + if (go) + { + var query = 'ajax=1&token='+token+'&action=addProductOnOrder&id_order='+id_order+'&'; + + query += $('tr#new_product select, tr#new_product input').serialize(); + if ($('select#add_product_product_invoice').val() == 0) + query += '&'+$('tr#new_invoice select, tr#new_invoice input').serialize(); + + $.ajax({ + type: 'POST', + url: admin_order_tab_link, + cache: false, + dataType: 'json', + data : query, + success : function(data) + { + if (data.result) + { + addViewOrderDetailRow(data.view); + updateAmounts(data.order); + } + else + alert(data.error); + } + }); + } + } + }); + + $('#edit_shipping_cost_link').click(function() { + $('#shipping_cost_show').hide(); + $('#shipping_cost_edit').show(); + + $('#edit_shipping_cost_link').hide(); + $('#cancel_shipping_cost_link').show(); + + return false; + }); + + $('#cancel_shipping_cost_link').click(function() { + $('#shipping_cost_show').show(); + $('#shipping_cost_edit').hide(); + + $('#edit_shipping_cost_link').show(); + $('#cancel_shipping_cost_link').hide(); + + return false; + }); + + $('.edit_shipping_number_link').click(function() { + $(this).parent().find('.shipping_number_show').hide(); + $(this).parent().find('.shipping_number_edit').show(); + + $(this).parent().find('.edit_shipping_number_link').hide(); + $(this).parent().find('.cancel_shipping_number_link').show(); + + return false; + }); + + $('.cancel_shipping_number_link').click(function() { + $(this).parent().find('.shipping_number_show').show(); + $(this).parent().find('.shipping_number_edit').hide(); + + $(this).parent().find('.edit_shipping_number_link').show(); + $(this).parent().find('.cancel_shipping_number_link').hide(); + + return false; + }); + + $('#add_product_product_invoice').change(function() { + if ($(this).val() == '0') + $('#new_invoice').slideDown('slow'); + else + $('#new_invoice').slideUp('slow'); + }); + + $('#add_product_product_price_tax_excl').keyup(function() { + var price_tax_excl = parseFloat($(this).val()); + if (price_tax_excl < 0 || isNaN(price_tax_excl)) + price_tax_excl = 0; + + var tax_rate = current_product.tax_rate / 100 + 1; + $('#add_product_product_price_tax_incl').val(ps_round(price_tax_excl * tax_rate, 2)); + + // Update total product + addProductRefreshTotal(); + }); + + $('#add_product_product_price_tax_incl').keyup(function() { + var price_tax_incl = parseFloat($(this).val()); + if (price_tax_incl < 0 || isNaN(price_tax_incl)) + price_tax_incl = 0; + + var tax_rate = current_product.tax_rate / 100 + 1; + $('#add_product_product_price_tax_excl').val(ps_round(price_tax_incl / tax_rate, 2)); + + // Update total product + addProductRefreshTotal(); + }); + + $('.edit_product_change_link').click(function() { + $('.cancel_product_change_link:visible').trigger('click'); + closeAddProduct(); + + query = 'ajax=1&token='+token+'&action=loadProductInformation&id_order_detail='+ + $(this).parent().parent().find('input.edit_product_id_order_detail').val()+'&id_address='+id_address; + var element = $(this); + $.ajax({ + type: 'POST', + url: admin_order_tab_link, + cache: false, + dataType: 'json', + data : query, + success : function(data) + { + if (data.result) + { + current_product = data; + element.parent().parent().css('background-color', '#E8EDC2'); + + element.parent().parent().find('td .product_price_show').hide(); + element.parent().parent().find('td .product_quantity_show').hide(); + element.parent().parent().find('td .product_price_edit').parent().attr('align', 'left'); + element.parent().parent().find('td .product_price_edit').show(); + element.parent().parent().find('td .product_quantity_edit').show(); + + element.parent().parent().find('td.cancelCheck').hide(); + element.parent().parent().find('td.cancelQuantity').hide(); + element.parent().parent().find('td.product_invoice').show(); + + element.parent().children('.delete_product_line').hide(); + element.parent().children('.edit_product_change_link').hide(); + element.parent().children('input[name=submitProductChange]').show(); + element.parent().children('.cancel_product_change_link').show(); + } + else + alert(data.error); + } + }); + + return false; + }); + + $('.cancel_product_change_link').click(function() { + current_product = null; + + $(this).parent().parent().css('background-color', '#FFF'); + + $(this).parent().parent().find('td .product_price_show').show(); + $(this).parent().parent().find('td .product_quantity_show').show(); + $(this).parent().parent().find('td .product_price_edit').parent().attr('align', 'center'); + $(this).parent().parent().find('td .product_price_edit').hide(); + $(this).parent().parent().find('td .product_quantity_edit').hide(); + + $(this).parent().parent().find('td.product_invoice').hide(); + $(this).parent().parent().find('td.cancelCheck').show(); + $(this).parent().parent().find('td.cancelQuantity').show(); + + $(this).parent().children('.delete_product_line').show(); + $(this).parent().children('.edit_product_change_link').show(); + $(this).parent().children('input[name=submitProductChange]').hide(); + $(this).parent().children('.cancel_product_change_link').hide(); + + return false; + }); + + $('input[name=submitProductChange]').click(function() { + if ($(this).parent().parent().find('td .edit_product_quantity').val() <= 0) + { + alert(txt_add_product_no_product_quantity); + return false; + } + + if ($(this).parent().parent().find('td .edit_product_price').val() <= 0) + { + alert(txt_add_product_no_product_price); + return false; + } + + if (confirm(txt_confirm)) + { + var element = $(this); + + query = 'ajax=1&token='+token+'&action=editProductOnOrder&id_order='+id_order+'&'+ + element.parent().parent().find('input:visible, select:visible, input.edit_product_id_order_detail').serialize(); + + $.ajax({ + type: 'POST', + url: admin_order_tab_link, + cache: false, + dataType: 'json', + data : query, + success : function(data) + { + if (data.result) + { + refreshProductLineView(element, data.view); + updateAmounts(data.order); + } + else + alert(data.error); + } + }); + } + + return false; + }); + + $('.edit_product_price_tax_excl').keyup(function() { + var price_tax_excl = parseFloat($(this).val()); + if (price_tax_excl < 0 || isNaN(price_tax_excl)) + price_tax_excl = 0; + + var tax_rate = current_product.tax_rate / 100 + 1; + $('.edit_product_price_tax_incl:visible').val(ps_round(price_tax_excl * tax_rate, 2)); + + // Update total product + editProductRefreshTotal($(this)); + }); + + $('.edit_product_price_tax_incl').keyup(function() { + var price_tax_incl = parseFloat($(this).val()); + if (price_tax_incl < 0 || isNaN(price_tax_incl)) + price_tax_incl = 0; + + var tax_rate = current_product.tax_rate / 100 + 1; + $('.edit_product_price_tax_excl:visible').val(ps_round(price_tax_incl / tax_rate, 2)); + + // Update total product + editProductRefreshTotal($(this)); + }); + + $('.edit_product_quantity').keyup(function() { + var quantity = parseInt($(this).val()); + if (quantity < 1 || isNaN(quantity)) + quantity = 1; + + var stock_available = parseInt($(this).parent().parent().parent().find('td.product_stock').html()); + // total update + editProductRefreshTotal($(this)); + }); + + $('.delete_product_line').click(function() { + if (!confirm(txt_confirm)) + return false; + + var tr_product = $(this).parent().parent(); + var id_order_detail = $(this).parent().parent().find('td .edit_product_id_order_detail').val(); + var query = 'ajax=1&action=deleteProductLine&token='+token+'&id_order_detail='+id_order_detail+'&id_order='+id_order; + + $.ajax({ + type: 'POST', + url: admin_order_tab_link, + cache: false, + dataType: 'json', + data : query, + success : function(data) + { + if (data.result) + { + tr_product.fadeOut('slow', function() { + $(this).remove(); + }); + updateAmounts(data.order); + } + else + alert(data.error); + } + }); + return false; + }); +}); + +function addProductRefreshTotal() +{ + var quantity = parseInt($('#add_product_product_quantity').val()); + if (quantity < 1|| isNaN(quantity)) + quantity = 1; + if (use_taxes) + var price = parseFloat($('#add_product_product_price_tax_incl').val()); + else + var price = parseFloat($('#add_product_product_price_tax_excl').val()); + + if (price < 0 || isNaN(price)) + price = 0; + var total = makeTotalProductCaculation(quantity, price); + $('#add_product_product_total').html(formatCurrency(total, currency_format, currency_sign, currency_blank)); +} + +function editProductRefreshTotal(element) +{ + element = element.parent().parent().parent(); + + var quantity = parseInt(element.find('td .edit_product_quantity').val()); + if (quantity < 1 || isNaN(quantity)) + quantity = 1; + if (use_taxes) + var price = parseFloat(element.find('td .edit_product_price_tax_incl').val()); + else + var price = parseFloat(element.find('td .edit_product_price_tax_excl').val()) + + if (price < 0 || isNaN(price)) + price = 0; + + var total = makeTotalProductCaculation(quantity, price); + element.find('td.total_product').html(formatCurrency(total, currency_format, currency_sign, currency_blank)); +} + +function makeTotalProductCaculation(quantity, price) +{ + return Math.round(quantity * price * 100) / 100; +} + +function addViewOrderDetailRow(view) +{ + html = $(view); + html.find('td').hide(); + $('tr#new_invoice').hide(); + $('tr#new_product').hide(); + + // Initialize fields + closeAddProduct(); + + $('tr#new_product').before(html); + html.find('td').each(function() { + if (!$(this).is('.product_invoice')) + $(this).fadeIn('slow'); + }); +} + +function refreshProductLineView(element, view) +{ + var new_product_line = $(view); + new_product_line.find('td').hide(); + + var current_product_line = element.parent().parent(); + current_product_line.before(new_product_line); + current_product_line.remove(); + + new_product_line.find('td').each(function() { + if (!$(this).is('.product_invoice')) + $(this).fadeIn('slow'); + }); +} + +function updateAmounts(order) +{ + $('#total_products td:last').fadeOut('slow', function() { + $(this).html(formatCurrency(parseFloat(order.total_products_wt), currency_format, currency_sign, currency_blank)); + $(this).fadeIn('slow'); + }); + $('#total_discounts td:last').fadeOut('slow', function() { + $(this).html(formatCurrency(parseFloat(order.total_discounts_tax_incl), currency_format, currency_sign, currency_blank)); + $(this).fadeIn('slow'); + }); + if (order.total_discounts_tax_incl > 0) + $('#total_discounts').slideDown('slow'); + $('#total_wrapping td:last').fadeOut('slow', function() { + $(this).html(formatCurrency(parseFloat(order.total_wrapping_tax_incl), currency_format, currency_sign, currency_blank)); + $(this).fadeIn('slow'); + }); + if (order.total_wrapping_tax_incl > 0) + $('#total_wrapping').slideDown('slow'); + $('#total_shipping td:last').fadeOut('slow', function() { + $(this).html(formatCurrency(parseFloat(order.total_shipping_tax_incl), currency_format, currency_sign, currency_blank)); + $(this).fadeIn('slow'); + }); + $('#total_order td:last').fadeOut('slow', function() { + $(this).html(formatCurrency(parseFloat(order.total_paid_tax_incl), currency_format, currency_sign, currency_blank)); + $(this).fadeIn('slow'); + }); + $('.total_paid').fadeOut('slow', function() { + $(this).html(formatCurrency(parseFloat(order.total_paid_tax_incl), currency_format, currency_sign, currency_blank)); + $(this).fadeIn('slow'); + }); + $('.alert').slideDown('slow'); + $('#product_number').fadeOut('slow', function() { + var old_quantity = parseInt($(this).html()); + $(this).html(old_quantity + 1); + $(this).fadeIn('slow'); + }); +} + +function closeAddProduct() +{ + $('tr#new_invoice').hide(); + $('tr#new_product').hide(); + + // Initialize fields + $('tr#new_product select, tr#new_product input').each(function() { + if (!$(this).is('.button')) + $(this).val('') + }); + $('tr#new_invoice select, tr#new_invoice input').val(''); + $('#add_product_product_quantity').val('1'); + $('#add_product_product_attribute_id option').remove(); + $('#add_product_product_attribute_area').hide(); + $('#add_product_product_stock').html('0'); + current_product = null; +} + + + + + + + +/* Refund system script */ +var flagRefund = ''; + +$(document).ready(function() { + $('.standard_refund').click(function() { + + $.scrollTo('#refundForm', 1200, {offset: -100}); + + if (flagRefund == 'standard') + { + flagRefund = ''; + $('.partial_refund_fields').hide(); + $('.standard_refund_fields').hide(); + } + else + { + flagRefund = 'standard'; + $('.partial_refund_fields').hide(); + $('.standard_refund_fields').fadeIn(); + } + + return false; + }); + + $('.partial_refund').click(function() { + + $.scrollTo('#refundForm', 1200, {offset: -100}); + + if (flagRefund == 'partial') + { + flagRefund = ''; + $('.partial_refund_fields').hide(); + $('.standard_refund_fields').hide(); + } + else + { + flagRefund = 'partial'; + $('.standard_refund_fields').hide(); + $('.partial_refund_fields').fadeIn(); + } + + return false; + }); +}); + + + + + + diff --git a/js/tools.js b/js/tools.js index 1a66e2188..5038af989 100644 --- a/js/tools.js +++ b/js/tools.js @@ -24,6 +24,58 @@ * International Registered Trademark & Property of PrestaShop SA */ +function formatedNumberToFloat(price, currencyFormat, currencySign) +{ + price = price.replace(currencySign, ''); + if (currencyFormat == 1) + return parseFloat(price.replace(',', '').replace(' ', '')); + else if (currencyFormat == 2) + return parseFloat(price.replace(' ', '').replace(',', '.')); + else if (currencyFormat == 3) + return parseFloat(price.replace('.', '').replace(' ', '').replace(',', '.')); + else if (currencyFormat == 4) + return parseFloat(price.replace(',', '').replace(' ', '')); + return price; +} + +//return a formatted number +function formatNumber(value, numberOfDecimal, thousenSeparator, virgule) +{ + value = value.toFixed(numberOfDecimal); + var val_string = value+''; + var tmp = val_string.split('.'); + var abs_val_string = (tmp.length == 2) ? tmp[0] : val_string; + var deci_string = ('0.' + (tmp.length == 2 ? tmp[1] : 0)).substr(2); + var nb = abs_val_string.length; + + for (var i = 1 ; i < 4; i++) + if (value >= Math.pow(10, (3 * i))) + abs_val_string = abs_val_string.substring(0, nb - (3 * i)) + thousenSeparator + abs_val_string.substring(nb - (3 * i)); + + if (parseInt(numberOfDecimal) == 0) + return abs_val_string; + return abs_val_string + virgule + (deci_string > 0 ? deci_string : '00'); +} + +function formatCurrency(price, currencyFormat, currencySign, currencyBlank) +{ + // if you modified this function, don't forget to modify the PHP function displayPrice (in the Tools.php class) + blank = ''; + price = parseFloat(price.toFixed(6)); + price = ps_round(price, priceDisplayPrecision); + if (currencyBlank > 0) + blank = ' '; + if (currencyFormat == 1) + return currencySign + blank + formatNumber(price, priceDisplayPrecision, ',', '.'); + if (currencyFormat == 2) + return (formatNumber(price, priceDisplayPrecision, ' ', ',') + blank + currencySign); + if (currencyFormat == 3) + return (currencySign + blank + formatNumber(price, priceDisplayPrecision, '.', ',')); + if (currencyFormat == 4) + return (formatNumber(price, priceDisplayPrecision, ',', '.') + blank + currencySign); + return price; +} + function ps_round(value, precision) { if (typeof(roundMode) == 'undefined') diff --git a/themes/prestashop/order-detail.tpl b/themes/prestashop/order-detail.tpl index ac8f4e05b..34b0b49b5 100644 --- a/themes/prestashop/order-detail.tpl +++ b/themes/prestashop/order-detail.tpl @@ -301,6 +301,34 @@
+
+{if $order->getShipping()|count > 0} + + + + + + + + + + + + {foreach from=$order->getShipping() item=line} + + + + + + + + {/foreach} + +
{l s='Date'}{l s='Carrier'}{l s='Weight'}{l s='Shipping cost'}{l s='Tracking number'}
{$line.date_add}{$line.state_name}{$line.weight|string_format:"%.3f"} {Configuration::get('PS_WEIGHT_UNIT')}{if $order->getTaxCalculationMethod() == $smarty.const.PS_TAX_INC}{displayPrice price=$line.shipping_cost_tax_incl currency=$currency->id}{else}{displayPrice price=$line.shipping_cost_tax_excl currency=$currency->id}{/if} + {if $line.url && $line.tracking_number}{$line.tracking_number}{else}{$line.tracking_number}{/if} +
+{/if} +

{if !$is_guest} {if $return_allowed} diff --git a/themes/prestashop/pdf/invoice.tax-tab.tpl b/themes/prestashop/pdf/invoice.tax-tab.tpl index 87c2d9606..57ec1fb10 100755 --- a/themes/prestashop/pdf/invoice.tax-tab.tpl +++ b/themes/prestashop/pdf/invoice.tax-tab.tpl @@ -33,7 +33,7 @@ {l s='Shipping' pdf='true'} {$shipping_tax_infos.rate} - {displayPrice currency=$order->id_currency price=$order->total_shipping_tax_excl} + {displayPrice currency=$order->id_currency price=$order_invoice->total_shipping_tax_excl} {displayPrice currency=$order->id_currency price=$shipping_tax_infos.total_amount} {/foreach} diff --git a/themes/prestashop/pdf/invoice.tpl b/themes/prestashop/pdf/invoice.tpl index 8f44c0067..aecab1fa0 100755 --- a/themes/prestashop/pdf/invoice.tpl +++ b/themes/prestashop/pdf/invoice.tpl @@ -130,66 +130,66 @@ - {if (($order->total_paid_tax_incl - $order->total_paid_tax_excl) > 0)} + {if (($order_invoice->total_paid_tax_incl - $order_invoice->total_paid_tax_excl) > 0)} - + - + {else} - + {/if} - {if $order->total_discounts_tax_incl > 0} + {if $order_invoice->total_discount_tax_incl > 0} - + {/if} - {if $order->total_wrapping_tax_incl > 0} + {if $order_invoice->total_wrapping_tax_incl > 0} {/if} - {if $order->total_shipping_tax_incl > 0} + {if $order_invoice->total_shipping_tax_incl > 0} {/if} - {if ($order->total_paid_tax_incl - $order->total_paid_tax_excl) > 0} + {if ($order_invoice->total_paid_tax_incl - $order_invoice->total_paid_tax_excl) > 0} - + {/if} - +
{l s='Product Total (Tax Excl.)' pdf='true'}{displayPrice currency=$order->id_currency price=$order->total_products}{displayPrice currency=$order->id_currency price=$order_invoice->total_products}
{l s='Product Total (Tax Incl.)' pdf='true'}{displayPrice currency=$order->id_currency price=$order->total_products_wt}{displayPrice currency=$order->id_currency price=$order_invoice->total_products_wt}
{l s='Product Total' pdf='true'}{displayPrice currency=$order->id_currency price=$order->total_products}{displayPrice currency=$order->id_currency price=$order_invoice->total_products}
{l s='Total Vouchers' pdf='true'}-{displayPrice currency=$order->id_currency price=$order->total_discounts_tax_incl}-{displayPrice currency=$order->id_currency price=$order_invoice->total_discount_tax_incl}
{l s='Wrapping Cost' pdf='true'} {if $tax_excluded_display} - {displayPrice currency=$order->id_currency price=$order->total_wrapping_tax_excl} + {displayPrice currency=$order->id_currency price=$order_invoice->total_wrapping_tax_excl} {else} - {displayPrice currency=$order->id_currency price=$order->total_wrapping_tax_incl} + {displayPrice currency=$order->id_currency price=$order_invoice->total_wrapping_tax_incl} {/if}
{l s='Shipping Cost' pdf='true'} {if $tax_excluded_display} - {displayPrice currency=$order->id_currency price=$order->total_shipping_tax_excl} + {displayPrice currency=$order->id_currency price=$order_invoice->total_shipping_tax_excl} {else} - {displayPrice currency=$order->id_currency price=$order->total_shipping_tax_incl} + {displayPrice currency=$order->id_currency price=$order_invoice->total_shipping_tax_incl} {/if}
{l s='Total Tax' pdf='true'}{displayPrice currency=$order->id_currency price=($order->total_paid_tax_incl - $order->total_paid_tax_excl)}{displayPrice currency=$order->id_currency price=($order_invoice->total_paid_tax_incl - $order_invoice->total_paid_tax_excl)}
{l s='Total' pdf='true'}{displayPrice currency=$order->id_currency price=$order->total_paid_tax_incl}{displayPrice currency=$order->id_currency price=$order_invoice->total_paid_tax_incl}