function calculate($order) { //============ format data ============// $result = array(); App::import('Lib', 'Shop.ShopConfig'); $default = array('country' => ShopConfig::load('defaultCountry'), 'region' => ShopConfig::load('defaultRegion')); $extract_data = array('country' => array('country', 'ShopOrder.billing_country', 'ShopOrder.shipping_country'), 'region' => array('region', 'ShopOrder.billing_region', 'ShopOrder.shipping_region'), 'shipping_type' => array('shipping_type', 'ShopOrder.shipping_type')); if (isset($order['order'])) { $order['ShopOrder'] = $order['order']; } App::import('Lib', 'Shop.SetMulti'); $data = SetMulti::extractHierarchicMulti($extract_data, $order, array('extractNull' => false)); $data = array_merge($default, $data); //debug($data); if (isset($order['ShopOrdersItem'])) { $rawItems = $order['ShopOrdersItem']; } else { if ($order['items']) { $rawItems = $order['items']; } } if (empty($rawItems)) { return false; } foreach ($rawItems as $orderItem) { $orderItems[] = $this->extractOrderItemData($orderItem, $order); } $order['ShopOrdersItem'] =& $orderItems; $supplements = ShopConfig::getSupplementOpts(); //debug($supplements); $order['Supplements'] =& $supplements; //============ calcul subItems ============// $orderItems = $this->calculSubItem($orderItems, $order); //debug($orderItems); //============ calcul promos ============// $this->calculPromo($order); //debug($orderItems); //============ total_items ============// $result['total_items'] = 0; $result['nb_total'] = 0; $excludeFromResult = array('ShopPromotion', 'ShopSubproduct', 'ShopOrdersSubitem'); if (!empty($orderItems)) { foreach ($orderItems as &$orderItem) { $result['nb_total'] += $orderItem['nb']; $orderItem['total'] = round($orderItem['item_price'], 2) * $orderItem['nb']; $result['total_items'] += $orderItem['total']; $result['OrderItem'][] = array_diff_key($orderItem, array_flip($excludeFromResult)); } } //============ sub_total ============// $result['sub_total'] = 0; $result['sub_total'] = $result['total_items']; //============ Supplements (Shipping, Packing, etc) ============// $result['total_supplements'] = 0; $exportedSupplements = ShopConfig::getExportedSupplements(); $defaultType = ShopConfig::getDefaultSupplementName(); $supplementsData = array(); if (!empty($data['supplement_choices'])) { $supplementsData = (array) $data['supplement_choices']; } foreach ($exportedSupplements as $name) { if (!empty($data[$name . '_type'])) { $supplementsData[$name] = $data[$name . '_type']; } } foreach ($supplements as $sName => $supplement) { $supplement_choice = array('type' => $defaultType); if (!empty($supplementsData[$sName])) { if (!is_array($supplementsData[$sName])) { $supplementsData[$sName] = array('type' => $supplementsData[$sName]); } if (empty($supplementsData[$sName]['type'])) { $supplementsData[$sName]['type'] = $defaultType; } if (isset($supplements[$sName][$supplementsData[$sName]['type']])) { $supplement_choice = $supplementsData[$sName]; } } $supplementItem = $supplement[$supplement_choice['type']]; if (!empty($supplementItem['applicable'])) { if (!is_array($supplementItem['applicable']) || isset($supplementItem['applicable']['component'])) { $supplementItem['applicable'] = array($supplementItem['applicable']); } foreach ($supplementItem['applicable'] as $funct => $fopt) { //debug($supplementItem); if (is_string($fopt)) { $funct = $fopt; $fopt = array(); } $res = null; if (method_exists($this->SupplementMethod, $funct)) { $res = $this->SupplementMethod->{$funct}($fopt, $supplementItem, $order, $supplement_choice, $result); } elseif (!empty($fopt['component'])) { $fopt['params'][] = $supplementItem; $fopt['params'][] = $order; $fopt['params'][] = $supplement_choice; $fopt['params'][] = $result; $res = $this->callExternalfunction($fopt); } if ($res === false) { break 2; } } } $supplementItem['total'] = $supplementItem['price']; if (!empty($supplementItem['calcul'])) { if (!is_array($supplementItem['calcul']) || isset($supplementItem['calcul']['component'])) { $supplementItem['calcul'] = array($supplementItem['calcul']); } foreach ($supplementItem['calcul'] as $funct => $fopt) { if (is_string($fopt)) { $funct = $fopt; $fopt = array(); } $res = null; if (method_exists($this->SupplementMethod, $funct)) { $res = $this->SupplementMethod->{$funct}($fopt, $supplementItem, $order, $supplement_choice, $result); } elseif (!empty($fopt['component'])) { $fopt['params'][] = $supplementItem; $fopt['params'][] = $order; $fopt['params'][] = $supplement_choice; $fopt['params'][] = $result; $res = $this->callExternalfunction($fopt); } if (!is_null($res)) { if (!is_array($res)) { $res = array('total' => $res); } if (!array_key_exists('total', $res) || $res['total'] === true) { $res['total'] = $supplementItem['total']; } elseif ($res['total'] === false) { $res['total'] = 0; } $supplementItem = array_merge($supplementItem, $res); } } } unset($supplementItem['calculFunction']); unset($supplementItem['calcul']); $result['supplements'][$sName] = $supplementItem; $result['total_supplements'] += $supplementItem['total']; } //debug($exportedSupplements); //debug($result['supplements']); foreach ($exportedSupplements as $name) { if (isset($result['supplements'][$name]['total'])) { $result['total_' . $name] = $result['supplements'][$name]['total']; } } //============ calcul taxes ============// $result['total_taxes'] = 0; $this->ShopTax = ClassRegistry::init('Shop.ShopTax'); $rawTaxes = $this->ShopTax->find('all', array('conditions' => array('active' => 1, 'country' => $data['country'], 'OR' => array('region' => $data['region'], 'region IS NULL')), 'order' => array('region' => 'ASC', 'code' => 'ASC'))); if (!empty($rawTaxes)) { /*$general_taxes = array(); foreach($taxes as $taxe){ $general_taxes[$taxe['ShopTax']['code']] = $taxe['ShopTax']; } $tmpTotal = $result['sub_total']; foreach($general_taxes as $taxe){ if($taxe['apply']){ if($taxe['apply_prev']){ $amount = $tmpTotal * $taxe['rate']; }else{ $amount = $result['sub_total'] * $taxe['rate']; } $result['taxes'][$taxe['code']] = $amount; $tmpTotal += $amount; $result['total_taxes'] += $amount; } }*/ $taxes = array(); foreach ($rawTaxes as $taxe) { $taxes[$taxe['ShopTax']['code']] = $taxe['ShopTax']; } //debug($taxes); $tcheckableItems = $orderItems; if (!empty($result['supplements'])) { $tcheckableItems = array_merge($orderItems, array_values($result['supplements'])); } foreach ($tcheckableItems as $item) { $item['tmpTotal'] = $item['total']; if (isset($item['item_tax_applied'])) { $item['tax_applied'] = $item['item_tax_applied']; } if (!empty($item['tax_applied'])) { foreach ($taxes as $taxe) { //$taxe = $taxe['ShopTax']; $apply = $taxe['apply']; if ($item['tax_applied'] === false) { $apply = false; } elseif (is_array($item['tax_applied'])) { $apply = in_array($taxe['code'], $item['tax_applied']); } if ($apply) { if ($taxe['apply_prev']) { $apply_to = $item['tmpTotal']; } else { $apply_to = $item['total']; } if (!isset($result['taxes'][$taxe['code']]) || !isset($result['taxe_subs'][$taxe['code']])) { $result['taxe_subs'][$taxe['code']] = 0; $result['taxes'][$taxe['code']] = 0; } $result['taxe_subs'][$taxe['code']] += $apply_to; $amount = $apply_to * $taxe['rate']; $result['taxes'][$taxe['code']] += $amount; $item['tmpTotal'] += $amount; $result['total_taxes'] += $amount; } } } } } //============ total ============// $result['total'] = 0; $result['total'] += $result['sub_total']; $result['total'] += $result['total_supplements']; $result['total'] += $result['total_taxes']; $result['total'] = round($result['total'], 2); //debug($result); return $result; }
function supplementInput($type, $options = array()) { if (!isset($options['options'])) { $options['options'] = array(); $choices = ShopConfig::getSupplementOpts($type); foreach ($choices as $name => $opt) { $options['options'][$name] = $opt['title']; } } if (!isset($options['label'])) { $options['label'] = __(Inflector::humanize($type) . ' Type', true); } $exportedSupplements = ShopConfig::getExportedSupplements(); if (in_array($type, $exportedSupplements)) { $fieldName = $type . '_type'; } else { $fieldName = 'ShopOrder.supplement_choices.' . $type; } return $this->O2form->input($fieldName, $options); }