id] = $sale; } public static function getSales() { return self::$sales; } public static function getStateNull() { return $state_null = array(6, 7, 8); } public function getAllSales(DateTime $date_from = null, DateTime $date_to = null, $orderby = null, $ordered = null) { $collection = new Collection('SaleCoreExtend', Context::getContext()->language->id); if($date_from !== null && $date_to !== null) { $format = 'Y-m-d'; $collection->sqlWhere('(date_start BETWEEN "'.$date_from->format($format).'" AND "'.$date_to->format($format).'") OR (date_end BETWEEN "'.$date_from->format($format).'" AND "'.$date_to->format($format).'") '); } if($orderby === null || $ordered === null) $collection->orderBy('id_privatesales', 'DESC'); else { $definition = ObjectModel::getDefinition('SaleCoreExtend', $orderby); $collection->orderBy(($definition['lang'] == 1 ? 'l.' : '').$orderby, $ordered); } //print_r($collection); //exit; $array = array(); foreach($collection as $sale) $array[$sale->id] = $sale; return $array; } /*******************************MISE A JOUR*********************************/ public static function run(DateTime $date_from = null, DateTime $date_to = null) { $sales = self::getSales(); foreach($sales as $sale) { $ids_products = $sale->getProducts(); try { self::setProducts($sale, $ids_products, $date_from, $date_to); self::setOrders($sale, $ids_products, $date_from, $date_to); self::setTotal($sale); } catch(Exception $e) { self::$errors[] = sprintf(Tools::displayError('An error occured during stats update, private sale : %s (%s)'), $sale->title, $e->getMessage() ); } } self::runGeneral($date_from, $date_to); } public static function runGeneral(DateTime $date_from = null, DateTime $date_to = null) { self::setTotalFields($date_from, $date_to); } private static function setProducts($sale, $ids_products, DateTime $date_from = null, DateTime $date_to = null) { Db::getInstance()->delete('privatesales_stats_products', ($date_from !== null && $date_to !== null ? '(date BETWEEN "'.pSQL($date_from->format('Y-m-d')).'" AND "'.pSQL($date_to->format('Y-m-d')).'") AND ' : '') . ' id_sale = '.(int)$sale->id); if(count($ids_products) > 0) { $total = Db::getInstance()->executeS(' SELECT a.*, (total_products_price_tax_excl - total_products_wholesale_price) as rate_amount, (1 - total_products_wholesale_price/total_products_price_tax_excl) as rate FROM ( SELECT '.$sale->id.' as id_sale, d.product_id, d.product_attribute_id, d.product_reference AS reference, d.product_supplier_reference AS supplier_reference, DATE_FORMAT(o.`date_add`, "%Y-%m-%d") as date, d.product_name as name, SUM(d.`product_quantity`) AS `total_products`, SUM( ROUND( d.unit_price_tax_incl * d.`product_quantity`, 6 ) ) AS `total_products_price`, SUM( ROUND( d.unit_price_tax_excl * d.`product_quantity`, 6 ) ) AS `total_products_price_tax_excl`, CASE WHEN pas.wholesale_price IS NULL AND d.product_attribute_id != 0 AND pas.wholesale_price != 0 THEN SUM(pas.wholesale_price * d.`product_quantity`) ELSE SUM(ps.wholesale_price * d.`product_quantity`) END AS total_products_wholesale_price FROM `'._DB_PREFIX_.'order_detail` d RIGHT JOIN `'._DB_PREFIX_.'orders` o ON (d.`id_order` = o.`id_order` AND o.current_state NOT IN ("'.implode('","', self::getStateNull()).'") ) LEFT OUTER JOIN `'._DB_PREFIX_.'product_shop` ps ON ps.id_shop = o.id_shop AND ps.id_product = d.product_id LEFT OUTER JOIN `'._DB_PREFIX_.'product_attribute_shop` pas ON d.product_attribute_id != 0 AND pas.id_product_attribute = d.product_attribute_id WHERE d.`product_id` IN ("'.implode('","', $ids_products).'") '.($date_from !== null && $date_to !== null ? 'AND DATE_FORMAT(o.`date_add`, "%Y-%m-%d") BETWEEN "'.pSQL($date_from->format('Y-m-d')).'" AND "'.pSQL($date_to->format('Y-m-d')).'"' : '').' GROUP BY date, d.product_id, d.product_attribute_id ) a '); foreach($total as $k => $tot) $total[$k]['name'] = pSQL($tot['name']); Db::getInstance()->insert('privatesales_stats_products', $total); } } public static function setOrders($sale, $ids_products, DateTime $date_from = null, DateTime $date_to = null) { Db::getInstance()->delete('privatesales_stats_order', ($date_from !== null && $date_to !== null ? '(date BETWEEN "'.pSQL($date_from->format('Y-m-d')).'" AND "'.pSQL($date_to->format('Y-m-d')).'") AND' : '') . ' id_sale = '.(int)$sale->id); if(count($ids_products) > 0) { $total = Db::getInstance()->executeS(' SELECT a.*, ROUND(total_products_price_tax_excl - total_wholesale_price, 2) as rate_amount, (1 - ROUND(total_wholesale_price/total_products_price_tax_excl,2)) as rate FROM ( SELECT '.$sale->id.' as id_sale, DATE_FORMAT(o.`date_add`, "%Y-%m-%d") as date, SUM(d.`product_quantity`) AS `total_products`, SUM(d.`total_shipping_price_tax_incl`) as `total_shipping`, COUNT(d.id_order) AS total_order, SUM( ROUND( d.unit_price_tax_incl * d.`product_quantity`, 6 ) ) AS `total_products_price`, SUM( ROUND( d.unit_price_tax_excl * d.`product_quantity`, 6 ) ) AS `total_products_price_tax_excl`, CASE WHEN pas.wholesale_price IS NULL AND d.product_attribute_id != 0 THEN SUM(pas.wholesale_price * d.`product_quantity`) ELSE SUM(ps.wholesale_price * d.`product_quantity`) END AS total_wholesale_price FROM `'._DB_PREFIX_.'order_detail` d RIGHT JOIN `'._DB_PREFIX_.'orders` o ON d.`id_order` = o.`id_order` AND o.current_state NOT IN ("'.implode('","', self::getStateNull()).'") LEFT OUTER JOIN `'._DB_PREFIX_.'product_shop` ps ON ps.id_shop = o.id_shop AND ps.id_product = d.product_id LEFT OUTER JOIN `'._DB_PREFIX_.'product_attribute_shop` pas ON d.product_attribute_id != 0 AND pas.id_product_attribute = d.product_attribute_id WHERE d.`product_id` IN ("'.implode('","', $ids_products).'") '.($date_from !== null && $date_to !== null ? 'AND DATE_FORMAT(o.`date_add`, "%Y-%m-%d") BETWEEN "'.pSQL($date_from->format('Y-m-d')).'" AND "'.pSQL($date_to->format('Y-m-d')).'"' : '').' GROUP BY date ) a '); Db::getInstance()->insert('privatesales_stats_order', $total); } } public static function setTotal($sale) { $total = Db::getInstance()->executeS('SELECT id_sale, SUM(`total_products`) AS `total_products`, SUM(`total_products_price`) AS `total_products_price`, SUM(`total_products_price_tax_excl`) AS `total_products_price_tax_excl`, SUM(`total_shipping`) AS `total_shipping`, SUM(`total_wholesale_price`) AS `total_wholesale_price`, SUM(`rate_amount`) AS `rate_amount`, AVG(`rate`) AS `rate` FROM '._DB_PREFIX_.'privatesales_stats_order WHERE id_sale = '.(int)$sale->id.' GROUP BY id_sale'); Db::getInstance()->delete('privatesales_stats_order_global', 'id_sale = '.(int)$sale->id); Db::getInstance()->insert('privatesales_stats_order_global', $total); } public static function setTotalFields(DateTime $date_from = null, DateTime $date_to = null) { Db::getInstance()->delete('privatesales_stats_other', ($date_from !== null && $date_to !== null ? 'date BETWEEN "'.pSQL($date_from->format('Y-m-d')).'" AND "'.pSQL($date_to->format('Y-m-d')).'"' : '')); self::setTotalOrder($date_from, $date_to); self::setTotalPayment($date_from, $date_to); } public static function setTotalPayment(DateTime $date_from = null, DateTime $date_to = null) { $sql = 'SELECT o.date, SUM(amount) AS total_paid, payment_method FROM '._DB_PREFIX_.'order_payment op RIGHT JOIN ( SELECT reference, DATE_FORMAT(o.`date_add`, "%Y-%m-%d") as date FROM '._DB_PREFIX_.'orders o WHERE o.current_state NOT IN ("'.implode('","', self::getStateNull()).'") '.($date_from !== null && $date_to !== null ? 'AND DATE_FORMAT(o.`date_add`, "%Y-%m-%d") BETWEEN "'.pSQL($date_from->format('Y-m-d')).'" AND "'.pSQL($date_to->format('Y-m-d')).'"' : '').' ) o ON o.reference = op.order_reference GROUP BY payment_method, date'; $total_payment_type = Db::getInstance()->executeS($sql); $array_insert = array(); foreach($total_payment_type as $value) { if($value['total_paid'] === null) continue; $array_insert[] = array( 'name' => 'total_payment', 'date' => $value['date'], 'value' => $value['total_paid'], 'value_txt' => $value['payment_method'] ); } return Db::getInstance()->insert('privatesales_stats_other', $array_insert, false, true, Db::INSERT_IGNORE); } public static function setTotalOrder(DateTime $date_from = null, DateTime $date_to = null) { $sql = 'SELECT DATE_FORMAT(o.`date_add`, "%Y-%m-%d") AS date, SUM(total_products) AS total_products_tax_excl, SUM(total_products_wt) AS total_products_tax_incl, SUM(total_shipping_tax_incl) AS total_shipping_tax_incl, SUM(total_shipping_tax_excl) AS total_shipping_tax_excl, SUM(total_discounts_tax_incl) AS total_discounts_tax_incl, SUM(total_discounts_tax_excl) AS total_discounts_tax_excl, SUM(total_paid_tax_excl) AS total_paid_tax_excl, SUM(total_paid_tax_incl) AS total_paid_tax_incl FROM '._DB_PREFIX_.'orders o WHERE o.current_state NOT IN ("'.implode('","', self::getStateNull()).'") '.($date_from !== null && $date_to !== null ? ' AND DATE_FORMAT(o.`date_add`, "%Y-%m-%d") BETWEEN "'.pSQL($date_from->format('Y-m-d')).'" AND "'.pSQL($date_to->format('Y-m-d')).'"' : '').' GROUP BY date '; $total_order = Db::getInstance()->executeS($sql); $array_insert = array(); foreach($total_order as $values) { foreach($values as $key => $value) { if($key == 'date') continue; $array_insert[] = array( 'name' => $key, 'date' => $values['date'], 'value' => $value ); } } return Db::getInstance()->insert('privatesales_stats_other', $array_insert, false, true, Db::INSERT_IGNORE);; } /*******************************FIN MISE A JOUR*********************************/ /*******************************RECUPERATION*********************************/ public static function getStatsGlobal(DateTime $date_from = null, DateTime $date_to = null) { $array = array( 'total_products_tax_excl', 'total_products_tax_incl', 'total_shipping_tax_incl', 'total_shipping_tax_excl', 'total_discounts_tax_incl', 'total_discounts_tax_excl', 'total_paid_tax_excl', 'total_paid_tax_incl' ); $returns = array(); foreach($array as $field) { $sql = 'SELECT SUM(value) FROM '._DB_PREFIX_.'privatesales_stats_other WHERE name = \''.$field.'\' '.($date_from !== null && $date_to !== null ? ' AND date BETWEEN "'.pSQL($date_from->format('Y-m-d')).'" AND "'.pSQL($date_from->format('Y-m-d')).'"' : '').''; $returns[$field] = Db::getInstance()->getValue($sql); } return $returns; } public static function getStatsPaymentType(DateTime $date_from = null, DateTime $date_to = null) { $sql = 'SELECT SUM(value) as total_paid , value_txt as payment_method FROM '._DB_PREFIX_.'privatesales_stats_other WHERE name = \'total_payment\' '.($date_from !== null && $date_to !== null ? ' AND date BETWEEN "'.pSQL($date_from->format('Y-m-d')).'" AND "'.pSQL($date_from->format('Y-m-d')).'"' : '').' GROUP BY value_txt'; $total_payment_type = Db::getInstance()->executeS($sql); return $total_payment_type; } public static function getSaleDateToDate(DateTime $date_from = null, DateTime $date_to = null) { $format = 'Y-m-d'; $sql = ' SELECT p.id_privatesales FROM `'. _DB_PREFIX_ . self::$definition['table'].' p WHERE CAST(`date_start` AS DATE) BETWEEN "'.pSQL($format).'" AND "'.pSQL($date_to).'" OR CAST(`date_end` AS DATE) BETWEEN "'.pSQL($date_from).'" AND "'.pSQL($date_to).'" OR (CAST(p.`date_start` AS DATE) <= "'.pSQL($date_from).'" AND CAST(p.`date_end` AS DATE) >= "'.pSQL($date_to).'") GROUP BY p.`id_privatesales` ORDER BY p.`date_start` DESC'; $res = Db::getInstance()->executeS($sql); $sales = array(); foreach($res as $sale) $sales[(int) $sale['id_sale']] = new SaleCoreExtend($sale['id_sale']); return $sales; } public static function getStatsStatic($sales = array(), $type = 'global', DateTime $date_from = null, DateTime $date_to = null, $order_by = null, $ordered = null) { if(is_object($sales) && get_class($sales) == 'Collection') $sales = $sales->getResults(); if(!is_array($sales) || count($sales) == 0) return false; $sales_ids = array(); foreach($sales as $sale) { if(!is_object($sale)) $sales_ids[] = $sale['id']; else $sales_ids[] = $sale->id; } if($order_by != null && $ordered != null) { $order_by_req = $order_by.' '.$ordered; } else { $order_by_req = 'id_sale DESC'; } switch($type) { case 'global': if($date_from !== null && $date_to !== null) { $req = 'SELECT id_sale, SUM(total_products_price) AS total_products_price, SUM(total_products_price_tax_excl) as total_products_price_tax_excl, SUM(total_products) AS total_products, SUM(total_shipping) AS total_shipping, SUM(total_wholesale_price) AS total_wholesale_price, SUM(rate_amount) AS rate_amount, AVG(`rate`) AS `rate` FROM '._DB_PREFIX_.'privatesales_stats_order WHERE id_sale IN ('.implode(',',$sales_ids).') AND `date` BETWEEN "'.$date_from->format('Y-m-d').'" AND "'.$date_to->format('Y-m-d').'" GROUP BY id_sale ORDER BY '.$order_by_req; $totals = Db::getInstance()->executeS($req); } else { $totals = Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'privatesales_stats_order_global WHERE id_sale IN ('.implode(',',$sales_ids).') GROUP BY id_sale ORDER BY '.$order_by_req); } if(count($totals) == 0) return array(); $array_stats = array(); foreach($totals as $k => $total) { $array_stats[$total['id_sale']] = $total['id_sale']; } foreach($sales_ids as $sale) if(!in_array($sale, $array_stats)) { $array = array(); foreach(array_keys(reset($totals)) as $field) $array[$field] = 0; $array['id_sale'] = $sale; if($order_by != null && $ordered != null) { if($ordered == 'ASC') array_unshift($totals, $array); else $totals[] = $array; } else $totals[] = $array; } $array_stats = $totals; if($date_from !== null && $date_to !== null) { $array_stats['total'] = Db::getInstance()->getRow(' SELECT b.*, ROUND(b.total_total_products_price_tax_excl - b.total_total_wholesale_price, 2) as rate_amount, (1 - ROUND(total_total_wholesale_price/total_total_products_price_tax_excl,2)) as rate FROM ( SELECT SUM(total_products_price) as total_total_products_price, SUM(total_products_price_tax_excl) as total_total_products_price_tax_excl, SUM(total_shipping) as total_total_shipping, SUM(total_products) as total_total_products, SUM(total_wholesale_price) as total_total_wholesale_price FROM ( '.$req.' ) a ) b '); } else { $array_stats['total'] = Db::getInstance()->getRow(' SELECT a.*, ROUND(a.total_total_products_price_tax_excl - a.total_total_wholesale_price, 2) as rate_amount, (1 - ROUND(total_total_wholesale_price/total_total_products_price_tax_excl,2)) as rate FROM ( SELECT SUM(total_products_price) as total_total_products_price, SUM(total_products_price_tax_excl) as total_total_products_price_tax_excl, SUM(total_shipping) as total_total_shipping, SUM(total_products) as total_total_products, SUM(total_wholesale_price) as total_total_wholesale_price FROM '._DB_PREFIX_.'privatesales_stats_order_global WHERE id_sale IN ('.implode(',',$sales_ids).') ) a '); } //BUG DE LA CLE 0 $array_final = array(); foreach($array_stats as $k => $v) $array_final[(Validate::isInt($k) ? ($k+1) : $k)] = $v; return $array_final; break; } } public function getStats($sale, $type = 'global', DateTime $date_from = null, DateTime $date_to = null, $order_by = null, $ordered = null) { $date_req = ''; if($date_to !== null && $date_from !== null) $date_req = ' AND date BETWEEN \''.$date_from->format('Y-m-d').'\' AND \''.$date_to->format('Y-m-d').'\''; if($order_by != null && $ordered != null) $order_by_req = $order_by.' '.$ordered; else switch($type) { case 'product': $order_by_req = 'product_name ASC'; break; case 'order': $order_by_req = 'date DESC'; break; case 'global': $order_by_req = 'id_sale ASC'; break; } switch($type) { case 'global': case 'summary': if($date_req != '') { $req = 'SELECT id_sale, SUM(total_products_price) AS total_products_price, SUM(total_products_price_tax_excl) as total_products_price_tax_excl, SUM(total_products) AS total_products, SUM(total_wholesale_price) AS total_wholesale_price, SUM(rate_amount) AS rate_amount, AVG(`rate`) AS `rate` FROM '._DB_PREFIX_.'privatesales_stats_order WHERE id_sale = '.(int)$sale->id.' '.$date_req.' GROUP BY id_sale'; return Db::getInstance()->getRow($req); } else { return Db::getInstance()->getRow('SELECT * FROM '._DB_PREFIX_.'privatesales_stats_order_global WHERE id_sale = '.$sale->id); } break; case 'product': $sql = 'SELECT id_sale, product_id, reference, supplier_reference, SUM(total_products_price) AS total_total_products_price, SUM(total_products_price_tax_excl) AS total_total_products_price_tax_excl, SUM(total_products) AS total_total_products, SUM(rate_amount) AS rate_amount, AVG(`rate`) AS `rate`, SUM(total_products_wholesale_price) AS total_total_products_wholesale_price, name as product_name FROM '._DB_PREFIX_.'privatesales_stats_products a WHERE id_sale = '.(int)$sale->id.' '.$date_req.' GROUP BY id_sale, product_id, product_attribute_id ORDER BY '.$order_by_req.' '; return Db::getInstance()->executeS($sql); break; case 'order': return Db::getInstance()->executeS('SELECT id_sale, `date`, SUM(total_products_price) AS total_total_products_price, SUM(total_products_price_tax_excl) AS total_products_price_tax_excl, SUM(total_products) AS total_total_products, SUM(total_wholesale_price) AS total_total_wholesale_price, SUM(rate_amount) AS rate_amount, AVG(`rate`) AS `rate` FROM '._DB_PREFIX_.'privatesales_stats_order WHERE id_sale = '.$sale->id.' '.$date_req.' GROUP BY id_sale, date ORDER BY '.$order_by_req.' '); break; } } /*******************************FIN RECUPERATION*********************************/ /*******************************EXPORT*********************************/ public static function getSaleExport(SaleCoreExtend $sale, $order_states = array(), $type = 1, DateTime $date_from, DateTime $date_to) { //TYPE 1 = BDC ; TYPE 2 = MARGE if(count($order_states) == 0) throw new Exception("Aucun statut de commande sélectionné"); $ids_products = $sale->getProducts(); if(count($ids_products) == 0) throw new Exception("Aucun produit pour cette vente"); $orders = self::getProductsOrder($ids_products, $order_states, $date_from, $date_to); self::$array_product = array(); foreach($ids_products as $id_product) self::$array_product[$id_product] = new Product($id_product); $lines = self::getSaleExportLine($orders, $type); if(count($lines) == 0) throw new Exception("Aucune vente pour cette vente privée"); return $lines; } public static function getProductsOrder($ids_products = array(), $order_states = array(), DateTime $date_from = null, DateTime $date_to = null) { if($date_from !== null && $date_to !== null) { $format = 'Y-m-d H:i:s'; $date_from = $date_from->format($format); $date_to = $date_to->format($format); if(!Validate::isDate($date_from) || !Validate::isDate($date_to)) throw new PrestaShopException(Tools::displayError('Invalid date')); } $req = 'SELECT od.* FROM '._DB_PREFIX_.'order_detail od RIGHT JOIN '._DB_PREFIX_.'orders o ON ( od.id_order = o.id_order '.($date_from !== null && $date_to !== null && Validate::isDate($date_from) && Validate::isDate($date_to) ? 'AND o.date_add >= "'.$date_from.'" AND o.date_add <= "'.$date_to.'"' : '' ).' ) WHERE (SELECT id_order_state FROM '._DB_PREFIX_.'order_history oh WHERE o.id_order = oh.id_order ORDER BY id_order_history DESC LIMIT 1) IN ("'.implode('","', $order_states).'") AND product_id IN ("'.implode('","', $ids_products).'")'; $res = Db::getInstance()->executeS($req); return $res; } public static function getProductPriceWithReduction($values) { return (float)( $values['product_price']*( 1-($values['reduction_percent']/100) ) ); } public static function getSaleExportLine($lines, $type, $by_product_price = false) { $arrayTmp = array(); $g = 0; foreach($lines as $line) { if( ($line['product_quantity'] - $line['product_quantity_reinjected']) == 0) continue; if(!isset($arrayTmp[$line['product_id']])) $arrayTmp[$line['product_id']] = array(); $product_price = self::getProductPriceWithReduction($line); if($by_product_price) { if(!isset($arrayTmp[$line['product_id']][$line['product_attribute_id']])) $arrayTmp[$line['product_id']][$line['product_attribute_id']] = array(); if(!isset($arrayTmp[$line['product_id']][$line['product_attribute_id']][$product_price])) $arrayTmp[$line['product_id']][$line['product_attribute_id']][$product_price] = array('line' => $line, 'total' => 0); } else { if(!isset($arrayTmp[$line['product_id']][$line['product_attribute_id']])) $arrayTmp[$line['product_id']][$line['product_attribute_id']] = array('line' => $line, 'total' => 0); } $quantity = $line['product_quantity'] - $line['product_quantity_reinjected']; if($by_product_price) $arrayTmp[$line['product_id']][$line['product_attribute_id']][$product_price]['total'] += $quantity; else $arrayTmp[$line['product_id']][$line['product_attribute_id']]['total'] += $quantity; } return $lines = $arrayTmp; } /*******************************FIN EXPORT*********************************/ }