public function ajaxshowCalendar()
 {
     $id_lang = Context::getContext()->language->id;
     $id_shop = Tools::getValue('ids');
     $shop = new AphStore($id_shop, Context::getContext()->language->id);
     $shop->hours = json_decode($shop->hours, true);
     $id_currency = Validate::isLoadedObject(Context::getContext()->currency) ? (int) Context::getContext()->currency->id : (int) Configuration::get('PS_CURRENCY_DEFAULT');
     $context = Context::getContext();
     $context->shop->id = $id_shop;
     $dates = array();
     $dday = Tools::getValue('date');
     for ($i = 2; $i > 0; $i--) {
         if (date('Y-m-d', strtotime('-' . $i . ' day', strtotime($dday))) >= date('Y-m-d')) {
             $dates[] = date('Y-m-d', strtotime('-' . $i . ' day', strtotime($dday)));
         }
     }
     $dates[] = $dday;
     for ($d = sizeof($dates), $i = 1; $d < 5; $d++, $i++) {
         $dates[] = date('Y-m-d', strtotime('+' . $i . ' day', strtotime($dday)));
     }
     $id_product = Tools::getValue('id_product');
     $product = new Product($id_product, true, $id_lang, $id_shop);
     $product_need_tools = false;
     $product_need_employees = true;
     $service_duration = 0;
     $_features = Product::getFrontFeaturesStatic($id_lang, $id_product);
     foreach ($_features as &$feature) {
         if ($product->id_service_duration > 0 && $feature['id_feature'] == $product->id_service_duration) {
             $service_duration = (int) substr($feature['value'], 0, -1);
         }
         if ($product->id_service_duration < 1 && $feature['id_feature'] == Configuration::get('APH_FEATURE_DURATION')) {
             $service_duration = (int) substr($feature['value'], 0, -1);
         }
         if ($feature['id_feature'] == Configuration::get('APH_FEATURE_SERVICE_BY')) {
             if ((int) $feature['value'] == (int) Configuration::get('APH_FEATURE_SERVICE_BY_NO_EMPLOYEE')) {
                 $product_need_employees = false;
             }
         }
         $service_duration = (int) substr($feature['value'], 0, -1);
     }
     $id_tool = 0;
     $necessary_quantity_of_tool = 0;
     $products_use_this_tool = array();
     $tool = AphTool::getByShopAndProduct($id_shop, $id_product);
     if (!empty($tool)) {
         $id_tool = $tool[0]['id_tool'];
         $necessary_quantity_of_tool = $tool[0]['quantity'];
         $product_need_tools = true;
         $_products = AphTool::getProducts($id_tool);
         if (!empty($_products)) {
             foreach ($_products as &$_product) {
                 $products_use_this_tool[] = $_product['id_product'];
             }
         }
     }
     $employees = array();
     if ($product_need_employees) {
         $_employees = AphEmployeeProduct::getEmployeesByShopAndProduct($id_shop, $id_product);
         foreach ($_employees as &$employee) {
             $employees[] = $employee['id_employee'];
         }
     }
     $time_slice = (int) Configuration::get('APH_CALENDAR_TIME_SLICE_ONLINE');
     if ($service_duration > $time_slice) {
         for ($t = 1; $t <= 4; $t++) {
             if ($time_slice * $t >= $service_duration) {
                 $time_slice = $time_slice * $t;
                 break;
             }
         }
     }
     /*$attributues_by_value = array();
       $attributues = $product->getAttributesResume($id_lang, ': ', ', ');
       foreach ($attributues as &$attribute) {
           list($giorno, $orario) = explode(', ', $attribute['attribute_designation']);
           list(, $giorno) = explode(': ', $giorno);
           list(, $giorno) = explode(' ', $giorno);
           list(, $orario) = explode(': ', $orario);
           list(, $orario) = explode(' ', $orario);
           if (!array_key_exists($giorno, $attributues_by_value))
               $attributues_by_value[$giorno] = array();
           $attributues_by_value[$giorno][strval($orario)] = $attribute['id_product_attribute'];
       }*/
     $first_day = $last_day = NULL;
     $days = array();
     foreach ($dates as $day) {
         if (empty($first_day)) {
             $first_day = $day;
         }
         $last_day = $day;
         $days[$day] = array('date' => $day, 'date_ts' => strtotime($day), 'class' => 'store_opened', 'status' => 'opened', 'available' => true, 'price_from' => $product->price, 'times_tot' => 0, 'times_not_available' => 0, 'times_full' => 0, 'times' => array());
         $days[$day]['date_lang'] = date('d/m/Y', $days[$day]['date_ts']);
         $days[$day]['week_day'] = date('w', $days[$day]['date_ts']);
         $days[$day]['week_day_lang'] = $this->week_days[(int) date('w', $days[$day]['date_ts'])];
         $days[$day]['month_lang'] = $this->months[(int) date('w', $days[$day]['date_ts'])];
         if (!empty($shop->hours[date('w', $days[$day]['date_ts'])])) {
             $hour_1 = $shop->hours[date('w', $days[$day]['date_ts'])][1];
             $hour_2 = $shop->hours[date('w', $days[$day]['date_ts'])][2];
             if ($hour_1['o'] == 'X' && $hour_1['c'] == 'X' && $hour_2['o'] == 'X' && $hour_2['c'] == 'X') {
                 $days[$day]['status'] = 'closed';
                 $days[$day]['available'] = false;
             } else {
                 $time_start = $hour_1['o'] == 'X' ? $hour_2['o'] : $hour_1['o'];
                 $time_end = $hour_2['c'] == 'X' ? $hour_1['c'] : $hour_2['c'];
                 $pause_start = $hour_1['c'] == 'X' ? false : $hour_1['c'];
                 $pause_end = $hour_2['o'] == 'X' ? false : $hour_2['o'];
             }
         } else {
             $days[$day]['status'] = 'closed';
             $days[$day]['available'] = false;
         }
         if (!empty($shop->rights_hasCalendar)) {
             if ($days[$day]['status'] == 'closed') {
                 // apertura straordinaria
                 $shop_availability = AphAvailability::getByDate($id_shop, 0, $day, 1);
                 if (!empty($shop_availability)) {
                     $days[$day]['status'] = 'opened';
                     $days[$day]['available'] = true;
                 }
             } else {
                 // chiusura straordinaria
                 $shop_availability = AphAvailability::getByDate($id_shop, 0, $day, -1);
                 if (!empty($shop_availability)) {
                     $days[$day]['status'] = 'closed';
                     $days[$day]['available'] = false;
                 }
             }
             if ($days[$day]['status'] == 'closed') {
                 $days[$day]['class'] = 'store_closed';
                 $days[$day]['available'] = false;
                 continue;
             }
         }
         // almeno un'offerta disponibile nel giorno
         $shop_offers = AphOffer::getByDate($id_shop, $id_product, $day, 1);
         if (!empty($shop_offers)) {
             $days[$day]['status'] = 'promoted';
             $days[$day]['class'] = 'store_promoted';
         }
         print_r($days[$day]['available']);
         if (!empty($days[$day]['available'])) {
             $times = array();
             for ($hours = substr($time_start, 0, 2); $hours < substr($time_end, 0, 2); $hours++) {
                 // the interval for hours is '1'
                 for ($mins = 0; $mins < 60; $mins += $time_slice) {
                     // the interval for mins is 'APH_CALENDAR_TIME_SLICE'
                     $t = str_pad($hours, 2, '0', STR_PAD_LEFT) . ':' . str_pad($mins, 2, '0', STR_PAD_LEFT);
                     // se sto valutanto l'orario nella pausa allora lo ignoro
                     if (!empty($pause_start) && !empty($pause_end) && $t >= $pause_start && $t < $pause_end) {
                         continue;
                     }
                     $times[$t] = array('time' => $t, 'available' => false, 'status' => 'available', 'class' => $days[$day]['class']);
                     $times[$t]['from'] = $t;
                     $time = new DateTime($day . ' ' . $times[$t]['from']);
                     $time->add(new DateInterval('PT' . $service_duration . 'M'));
                     $times[$t]['to'] = $time->format('H:i');
                     if ($times[$t]['to'] > $time_end) {
                         $times[$t]['available'] = false;
                         $times[$t]['status'] = 'available';
                         $times[$t]['class'] .= ' time_notavailable';
                         $days[$day]['times_not_available']++;
                     }
                     $days[$day]['times_tot']++;
                     if (!empty($shop->rights_hasCalendar)) {
                         $completed_orders = AphOrderDetail::getBetweenTimes($id_shop, 0, 0, $days[$day]['date_ts'], $times[$t]['from'], $times[$t]['to']);
                         if ($product_need_tools && !empty($products_use_this_tool)) {
                             $completed_orders_about_tool = AphOrderDetail::getBetweenTimes($id_shop, 0, $products_use_this_tool, $days[$day]['date_ts'], $times[$t]['from'], $times[$t]['to']);
                             $t = AphTool::getByDate($id_tool, $available_date);
                             $tool_is_availability = !empty($t) ? true : false;
                         } else {
                             $completed_orders_about_tool = array();
                         }
                         $availabilies_of_shop = AphAvailability::getBetweenTimes($id_shop, 0, strtotime($day . ' ' . $times[$t]['from']), strtotime($day . ' ' . $times[$t]['to']), 1);
                         $not_availabilies_of_shop = AphAvailability::getBetweenTimes($id_shop, 0, strtotime($day . ' ' . $times[$t]['from']), strtotime($day . ' ' . $times[$t]['to']), 0);
                         if ($product_need_employees && empty($not_availabilies_of_shop)) {
                             $working_employees = AphWorkingDay::getByEmployeeAndDateBetweenTimes($id_shop, $employees, $day, $times[$t]['from'], $times[$t]['to'], 1);
                             $availabilies_of_employees = AphAvailability::getBetweenTimes($id_shop, $employees, strtotime($day . ' ' . $times[$t]['from']), strtotime($day . ' ' . $times[$t]['to']), 1);
                             $not_availabilies_of_employees = AphAvailability::getBetweenTimes($id_shop, $employees, strtotime($day . ' ' . $times[$t]['from']), strtotime($day . ' ' . $times[$t]['to']), 0);
                         } else {
                             $working_employees = $availabilies_of_employees = $not_availabilies_of_employees = array();
                         }
                     }
                     // chiusura straordinaria
                     if (!empty($not_availabilies_of_shop)) {
                         $times[$t]['available'] = false;
                         $times[$t]['status'] = 'closed';
                         $times[$t]['class'] .= ' time_closed';
                         $days[$day]['times_not_available']++;
                         continue;
                     }
                     // slot di tempo esaurito per mancanza di dipendenti
                     if ($product_need_employees && !empty($completed_orders) && !empty($working_employees) && sizeof($completed_orders) >= sizeof($working_employees) - sizeof($not_availabilies_of_employees)) {
                         $times[$t]['available'] = false;
                         $times[$t]['status'] = 'full';
                         $times[$t]['class'] .= ' time_full';
                         $days[$day]['times_full']++;
                         continue;
                     }
                     // slot di tempo esaurito per mancanza di macchinari
                     if ($product_need_tools && !$tool_is_availability || !empty($necessary_quantity_of_tool) && !empty($completed_orders_about_tool) && sizeof($completed_orders_about_tool) >= $necessary_quantity_of_tool) {
                         $times[$t]['available'] = false;
                         $times[$t]['status'] = 'full';
                         $times[$t]['class'] .= ' time_full';
                         $days[$day]['times_full']++;
                         continue;
                     }
                     // apertura straordinaria (i macchinari sono sempre disponibili)
                     if ($product_need_employees && !empty($availabilies_of_employees) && !empty($completed_orders) && !empty($availabilies_of_employees) && sizeof($completed_orders) >= sizeof($availabilies_of_employees) - sizeof($not_availabilies_of_employees)) {
                         $times[$t]['available'] = false;
                         $times[$t]['status'] = 'full';
                         $times[$t]['class'] .= ' time_full';
                         $days[$day]['times_full']++;
                         continue;
                     }
                     $times[$t]['available'] = true;
                     $times[$t]['status'] = 'available';
                     $times[$t]['class'] .= ' time_available';
                     if (!empty($times[$t]['available'])) {
                         //error_log(var_export(__LINE__,true));
                         //$price = Product::getPriceStatic($id_product, true, 0, 2, null, false, true, 1, false, null, null, null, $specific_price, true, true, $context, true, $day, $times[$t]['from'], $times[$t]['to']);
                         //$times[$t]['price'] = $price;
                         $times[$t]['price'] = 0;
                         $times[$t]['price_label'] = Tools::displayPrice($times[$t]['price'], $id_currency);
                         if ($times[$t]['price'] < $days[$day]['price_from']) {
                             $days[$day]['price_from'] = $times[$t]['price'];
                         }
                     }
                 }
             }
             $days[$day]['times'] = $times;
             $days[$day]['price_from_label'] = Tools::displayPrice($days[$day]['price_from'], $id_currency);
             if ($days[$day]['times_full'] == $days[$day]['times']) {
                 $days[$day]['available'] = false;
                 $days[$day]['status'] = 'full';
                 $days[$day]['class'] = 'store_full';
             } elseif ($days[$day]['times_not_available'] == $days[$day]['times']) {
                 $days[$day]['available'] = false;
                 $days[$day]['status'] = 'closed';
                 $days[$day]['class'] = 'store_closed';
             }
         }
     }
     $jsVars = array();
     $jsVars['calendar_params'] = array('ajax' => 1, 'ajaxCall' => 'ajaxshowCalendar', 'id_product' => $id_product, 'ids' => $id_shop, 'date' => $dday, 'id_city' => empty($id_city) ? $shop->id_city : $id_city);
     $this->context->smarty->assign(array('days' => $days, 'dday' => $dday, 'first_day' => $days[$first_day], 'last_day' => $days[$last_day], 'jsVars' => $jsVars));
     // $jsVars = array(
     //     'language' => $this->context->language->iso_code,
     //     'slotDuration' => '00:'.Configuration::get('APH_CALENDAR_TIME_SLICE').':00'
     // );
     // $this->content .= '<script>var admin_aphcalendar = '.json_encode($jsVars).';</script>';
     return $this->display(__FILE__, 'availability_calendar.tpl', $this->getCacheId('blockmobilecart-column'));
 }
 public function ajaxProcessAddProductOnOrder()
 {
     // Load object
     $order = new Order((int) Tools::getValue('id_order'));
     if (!Validate::isLoadedObject($order)) {
         die(Tools::jsonEncode(array('result' => false, 'error' => Tools::displayError('The order object cannot be loaded.'))));
     }
     $old_cart_rules = Context::getContext()->cart->getCartRules();
     if ($order->hasBeenShipped()) {
         die(Tools::jsonEncode(array('result' => false, 'error' => Tools::displayError('You cannot add products to delivered orders. '))));
     }
     $product_informations = $_POST['add_product'];
     if (isset($_POST['add_invoice'])) {
         $invoice_informations = $_POST['add_invoice'];
     } else {
         $invoice_informations = array();
     }
     $product = new Product($product_informations['product_id'], false, $order->id_lang);
     if (!Validate::isLoadedObject($product)) {
         die(Tools::jsonEncode(array('result' => false, 'error' => Tools::displayError('The product object cannot be loaded.'))));
     }
     $feature_duration = Configuration::get('APH_FEATURE_DURATION');
     $services_duration = json_decode(Configuration::get('APH_SERVICES_DURATION'), true);
     // duration event
     $features = $product->getFeatures();
     foreach ($features as &$feature) {
         if ($feature_duration == $feature['id_feature']) {
             $product_informations['duration'] = (int) $services_duration[$feature['id_feature_value']];
         }
     }
     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('The combination object cannot be loaded.'))));
         }
     }
     // Total method
     $total_method = Cart::BOTH_WITHOUT_SHIPPING;
     // Create new cart
     $cart = new Cart();
     $cart->id_shop_group = $order->id_shop_group;
     $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_lang = $order->id_lang;
     $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);
     // always add taxes even if there are not displayed to the customer
     $use_taxes = true;
     $initial_product_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', null, null, $order->id_shop)});
     // Creating specific price if needed
     if ($product_informations['product_price_tax_incl'] != $initial_product_price_tax_incl) {
         $specific_price = new SpecificPrice();
         $specific_price->id_shop = 0;
         $specific_price->id_shop_group = 0;
         $specific_price->id_currency = 0;
         $specific_price->id_country = 0;
         $specific_price->id_group = 0;
         $specific_price->id_customer = $order->id_customer;
         $specific_price->id_product = $product->id;
         if (isset($combination)) {
             $specific_price->id_product_attribute = $combination->id;
         } else {
             $specific_price->id_product_attribute = 0;
         }
         $specific_price->price = $product_informations['product_price_tax_excl'];
         $specific_price->from_quantity = 1;
         $specific_price->reduction = 0;
         $specific_price->reduction_type = 'amount';
         $specific_price->reduction_tax = 0;
         $specific_price->from = '0000-00-00 00:00:00';
         $specific_price->to = '0000-00-00 00:00:00';
         $specific_price->add();
     }
     // Add product to cart
     $update_quantity = $cart->updateQty($product_informations['product_quantity'], $product->id, isset($product_informations['product_attribute_id']) ? $product_informations['product_attribute_id'] : null, isset($combination) ? $combination->id : null, 'up', 0, new Shop($cart->id_shop));
     /*if ($update_quantity < 0) {
           // If product has attribute, minimal quantity is set with minimal quantity of attribute
           $minimal_quantity = ($product_informations['product_attribute_id']) ? Attribute::getAttributeMinimalQty($product_informations['product_attribute_id']) : $product->minimal_quantity;
           die(Tools::jsonEncode(array('error' => sprintf(Tools::displayError('You must add %d minimum quantity', false), $minimal_quantity))));
       } elseif (!$update_quantity) {
           die(Tools::jsonEncode(array('error' => Tools::displayError('You already have the maximum quantity available for this product.', false))));
       }*/
     // If order is valid, we can create a new invoice or edit an existing invoice
     if (false && $order->hasInvoice()) {
         $order_invoice = new OrderInvoice($product_informations['invoice']);
         // Create new invoice
         if ($order_invoice->id == 0) {
             // If we create a new invoice, we calculate shipping cost
             $total_method = Cart::BOTH;
             // Create Cart rule in order to make free shipping
             if (isset($invoice_informations['free_shipping']) && $invoice_informations['free_shipping']) {
                 $cart_rule = new CartRule();
                 $cart_rule->id_customer = $order->id_customer;
                 $cart_rule->name = array(Configuration::get('PS_LANG_DEFAULT') => $this->l('[Generated] CartRule for Free Shipping'));
                 $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();
                 // Add cart rule to cart and in order
                 $cart->addCartRule($cart_rule->id);
                 $values = array('tax_incl' => $cart_rule->getContextualValue(true), 'tax_excl' => $cart_rule->getContextualValue(false));
                 $order->addCartRule($cart_rule->id, $cart_rule->name[Configuration::get('PS_LANG_DEFAULT')], $values);
             }
             $order_invoice->id_order = $order->id;
             if ($order_invoice->number) {
                 Configuration::updateValue('PS_INVOICE_START_NUMBER', false, false, null, $order->id_shop);
             } else {
                 $order_invoice->number = Order::getLastInvoiceNumber() + 1;
             }
             $invoice_address = new Address((int) $order->{Configuration::get('PS_TAX_ADDRESS_TYPE', null, null, $order->id_shop)});
             $carrier = new Carrier((int) $order->id_carrier);
             $tax_calculator = $carrier->getTaxCalculator($invoice_address);
             $order_invoice->total_paid_tax_excl = Tools::ps_round((double) $cart->getOrderTotal(false, $total_method), 2);
             $order_invoice->total_paid_tax_incl = Tools::ps_round((double) $cart->getOrderTotal($use_taxes, $total_method), 2);
             $order_invoice->total_products = (double) $cart->getOrderTotal(false, Cart::ONLY_PRODUCTS);
             $order_invoice->total_products_wt = (double) $cart->getOrderTotal($use_taxes, Cart::ONLY_PRODUCTS);
             $order_invoice->total_shipping_tax_excl = (double) $cart->getTotalShippingCost(null, false);
             $order_invoice->total_shipping_tax_incl = (double) $cart->getTotalShippingCost();
             $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->shipping_tax_computation_method = (int) $tax_calculator->computation_method;
             // Update current order field, only shipping because other field is updated later
             $order->total_shipping += $order_invoice->total_shipping_tax_incl;
             $order->total_shipping_tax_excl += $order_invoice->total_shipping_tax_excl;
             $order->total_shipping_tax_incl += $use_taxes ? $order_invoice->total_shipping_tax_incl : $order_invoice->total_shipping_tax_excl;
             $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();
             $order_invoice->saveCarrierTaxCalculator($tax_calculator->getTaxesAmount($order_invoice->total_shipping_tax_excl));
             $order_carrier = new OrderCarrier();
             $order_carrier->id_order = (int) $order->id;
             $order_carrier->id_carrier = (int) $order->id_carrier;
             $order_carrier->id_order_invoice = (int) $order_invoice->id;
             $order_carrier->weight = (double) $cart->getTotalWeight();
             $order_carrier->shipping_cost_tax_excl = (double) $order_invoice->total_shipping_tax_excl;
             $order_carrier->shipping_cost_tax_incl = $use_taxes ? (double) $order_invoice->total_shipping_tax_incl : (double) $order_invoice->total_shipping_tax_excl;
             $order_carrier->add();
         } else {
             $order_invoice->total_paid_tax_excl += Tools::ps_round((double) $cart->getOrderTotal(false, $total_method), 2);
             $order_invoice->total_paid_tax_incl += Tools::ps_round((double) $cart->getOrderTotal($use_taxes, $total_method), 2);
             $order_invoice->total_products += (double) $cart->getOrderTotal(false, Cart::ONLY_PRODUCTS);
             $order_invoice->total_products_wt += (double) $cart->getOrderTotal($use_taxes, Cart::ONLY_PRODUCTS);
             $order_invoice->update();
         }
     }
     // Create Order detail information
     $order_detail = new AphOrderDetail();
     $order_detail->createList($order, $cart, $order->getCurrentOrderState(), $cart->getProducts(), isset($order_invoice) ? $order_invoice->id : 0, $use_taxes, (int) Tools::getValue('add_product_warehouse'));
     if ($product_informations['delivery_date'] != '') {
         $order_detail->id_employee = (int) $product_informations['id_employee'];
         $order_detail->delivery_date = $product_informations['delivery_date'];
         $order_detail->delivery_time_from = $product_informations['delivery_time_from'];
         if (!empty($product_informations['duration'])) {
             $time = new DateTime($order_detail->delivery_date . ' ' . $order_detail->delivery_time_from);
             $time->add(new DateInterval('PT' . $product_informations['duration'] . 'M'));
             $time_to = $time->format('H:i');
             if ($time_to > $product_informations['delivery_time_to']) {
                 $product_informations['delivery_time_to'] = $time_to;
             }
         }
         $order_detail->delivery_time_to = $product_informations['delivery_time_to'];
         $order_detail->update();
     }
     // update totals amount of order
     $order->total_products += (double) $cart->getOrderTotal(false, Cart::ONLY_PRODUCTS);
     $order->total_products_wt += (double) $cart->getOrderTotal($use_taxes, Cart::ONLY_PRODUCTS);
     $order->total_paid += Tools::ps_round((double) $cart->getOrderTotal(true, $total_method), 2);
     $order->total_paid_tax_excl += Tools::ps_round((double) $cart->getOrderTotal(false, $total_method), 2);
     $order->total_paid_tax_incl += Tools::ps_round((double) $cart->getOrderTotal($use_taxes, $total_method), 2);
     if (isset($order_invoice) && Validate::isLoadedObject($order_invoice)) {
         $order->total_shipping = $order_invoice->total_shipping_tax_incl;
         $order->total_shipping_tax_incl = $order_invoice->total_shipping_tax_incl;
         $order->total_shipping_tax_excl = $order_invoice->total_shipping_tax_excl;
     }
     // discount
     $order->total_discounts += (double) abs($cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS));
     $order->total_discounts_tax_excl += (double) abs($cart->getOrderTotal(false, Cart::ONLY_DISCOUNTS));
     $order->total_discounts_tax_incl += (double) abs($cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS));
     // Save changes of order
     $order->update();
     // Update weight SUM
     $order_carrier = new OrderCarrier((int) $order->getIdOrderCarrier());
     if (Validate::isLoadedObject($order_carrier)) {
         $order_carrier->weight = (double) $order->getTotalWeight();
         if ($order_carrier->update()) {
             $order->weight = sprintf("%.3f " . Configuration::get('PS_WEIGHT_UNIT'), $order_carrier->weight);
         }
     }
     // Update Tax lines
     $order_detail->updateTaxAmount($order);
     // Delete specific price if exists
     if (isset($specific_price)) {
         $specific_price->delete();
     }
     $products = $this->getProducts($order);
     // Get the last product
     $product = end($products);
     $resume = OrderSlip::getProductSlipResume((int) $product['id_order_detail']);
     $product['quantity_refundable'] = $product['product_quantity'] - $resume['product_quantity'];
     $product['amount_refundable'] = $product['total_price_tax_excl'] - $resume['amount_tax_excl'];
     $product['amount_refund'] = Tools::displayPrice($resume['amount_tax_incl']);
     $product['return_history'] = OrderReturn::getProductReturnDetail((int) $product['id_order_detail']);
     $product['refund_history'] = OrderSlip::getProductSlipDetail((int) $product['id_order_detail']);
     if ($product['id_warehouse'] != 0) {
         $warehouse = new Warehouse((int) $product['id_warehouse']);
         $product['warehouse_name'] = $warehouse->name;
         $warehouse_location = WarehouseProductLocation::getProductLocation($product['product_id'], $product['product_attribute_id'], $product['id_warehouse']);
         if (!empty($warehouse_location)) {
             $product['warehouse_location'] = $warehouse_location;
         } else {
             $product['warehouse_location'] = false;
         }
     } else {
         $product['warehouse_name'] = '--';
         $product['warehouse_location'] = false;
     }
     // Get invoices collection
     $invoice_collection = $order->getInvoicesCollection();
     $invoice_array = array();
     foreach ($invoice_collection as $invoice) {
         /** @var OrderInvoice $invoice */
         $invoice->name = $invoice->getInvoiceNumberFormatted(Context::getContext()->language->id, (int) $order->id_shop);
         $invoice_array[] = $invoice;
     }
     // 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' => $invoice_collection, 'current_id_lang' => Context::getContext()->language->id, 'link' => Context::getContext()->link, 'current_index' => self::$currentIndex, 'display_warehouse' => (int) Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')));
     $this->sendChangedNotification($order);
     $new_cart_rules = Context::getContext()->cart->getCartRules();
     sort($old_cart_rules);
     sort($new_cart_rules);
     $result = array_diff($new_cart_rules, $old_cart_rules);
     $refresh = false;
     $res = true;
     foreach ($result as $cart_rule) {
         $refresh = true;
         // Create OrderCartRule
         $rule = new CartRule($cart_rule['id_cart_rule']);
         $values = array('tax_incl' => $rule->getContextualValue(true), 'tax_excl' => $rule->getContextualValue(false));
         $order_cart_rule = new OrderCartRule();
         $order_cart_rule->id_order = $order->id;
         $order_cart_rule->id_cart_rule = $cart_rule['id_cart_rule'];
         $order_cart_rule->id_order_invoice = $order_invoice->id;
         $order_cart_rule->name = $cart_rule['name'];
         $order_cart_rule->value = $values['tax_incl'];
         $order_cart_rule->value_tax_excl = $values['tax_excl'];
         $res &= $order_cart_rule->add();
         $order->total_discounts += $order_cart_rule->value;
         $order->total_discounts_tax_incl += $order_cart_rule->value;
         $order->total_discounts_tax_excl += $order_cart_rule->value_tax_excl;
         $order->total_paid -= $order_cart_rule->value;
         $order->total_paid_tax_incl -= $order_cart_rule->value;
         $order->total_paid_tax_excl -= $order_cart_rule->value_tax_excl;
     }
     // Update Order
     $res &= $order->update();
     die(Tools::jsonEncode(array('result' => true, 'view' => $this->createTemplate('_product_line.tpl')->fetch(), 'can_edit' => $this->tabAccess['add'], 'order' => $order, 'invoices' => $invoice_array, 'documents_html' => $this->createTemplate('_documents.tpl')->fetch(), 'shipping_html' => $this->createTemplate('_shipping.tpl')->fetch(), 'discount_form_html' => $this->createTemplate('_discount_form.tpl')->fetch(), 'refresh' => $refresh)));
 }
 public function ajaxProcessPayOrder()
 {
     $id_order = Tools::getValue('id_order');
     $order = new Order($id_order);
     $id_order_detail = Tools::getValue('id_order_detail');
     $order_detail = new AphOrderDetail($id_order_detail);
     $order_detail->id_order = $id_order;
     $order_detail->product_quantity = 0;
     $res = $order_detail->update();
     $order_payment = new OrderPayment();
     $order_payment->order_reference = $order->reference;
     $order_payment->id_currency = (int) Context::getContext()->currency->id;
     $order_payment->amount = $products_total_price;
     $order_payment->payment_method = $order->payment;
     $order_payment->conversion_rate = $order->conversion_rate;
     $order_payment->add();
     $order_details = AphOrderDetail::getList($id_order);
     if ($res && !empty($order_details) && is_array($order_details)) {
         $empty_detail = 0;
         foreach ($order_details as &$order_detail) {
             if ((int) $order_detail['product_quantity'] < 1) {
                 $empty_detail++;
             }
         }
         if ($empty_detail == sizeof($order_details)) {
             $order = new Order($id_order);
             $order->setCurrentState(Configuration::get('APH_RESERVATION_DELETED_STATUS'), (int) Context::getContext()->employee->id);
         }
     }
     die(Tools::jsonEncode(array('result' => $res)));
 }