Async export

This commit is contained in:
Michael RICOIS 2018-02-01 09:34:23 +01:00
parent a71a5c9eac
commit 1ae7e28abe
7 changed files with 523 additions and 11 deletions

1
.gitignore vendored
View File

@ -109,7 +109,6 @@ modules/lapostews/mpdf/*
modules/landingpages/img/*
modules/privatesales/img/*
modules/privatesales_logistique/*
modules/stats_logistic/*
modules/privatesales_logistique/files/*
modules/emarsys_rss/flux.xml
modules/emarsys_rss/*.xml

View File

@ -37,9 +37,32 @@ class AdminStatsLogistic extends AdminTab
{
global $currentIndex, $cookie;
// Téléchargement fichier
if (Tools::getValue('dl')) {
$filename = Tools::getValue('file');
$content_type = 'application/csv-tab-delimited-table';
$path = dirname(__FILE__) . '/export';
$file = $path . '/' . $filename;
if (file_exists($file)) {
ini_set('zlib.output_compression', '0');
header('Content-Transfer-Encoding: none');
header('Content-Type: ' . $content_type.'');
header('Content-Length: ' . filesize($file));
header('Content-MD5: ' . base64_encode(md5_file($file)));
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
readfile($file);
} else {
echo "Impossible de trouver le fichier.";
}
exit;
}
if (Tools::getValue('submitExport')) {
$this->date_export_begin = Tools::getValue('date_export_begin', $this->date_export_begin);
$this->date_export_end = Tools::getValue('date_export_end', $this->date_export_end);
$sale_ids = $this->getSales();
if ($sale_ids) {
foreach ($sale_ids as $sale) {
@ -281,6 +304,7 @@ class AdminStatsLogistic extends AdminTab
<script type="text/javascript" src="'.__PS_BASE_URI__.'modules/privatesales_livestats/jquery-ui-1.8.20.custom.min.js"></script>
<script type="text/javascript" src="'.__PS_BASE_URI__.'adm/helpers/includes/jquery-ui-timepicker-addon.js"></script>
<script type="text/javascript" src="'.__PS_BASE_URI__.'modules/stats_logistic/views/js/export.js"></script>
';
echo
@ -564,7 +588,7 @@ class AdminStatsLogistic extends AdminTab
echo '<br><br><h2 style="margin-top:15px">Export Remboursements</h2>
<fieldset>
<p>Exporter le détail des ventes dont la date de début est comprise entre : </p>
<form method="POST" action="'.$currentIndex.'" >'
<form method="POST" action="http://'.$_SERVER['SERVER_NAME'].'/modules/stats_logistic/ajax.php?action=export">'
.'<span class="form-group">'
.'<label style="float: none;" class="control-label" for="date_export_begin">Date de début :</label>'
.'<input type="date" name="date_export_begin" value="'.pSQl($this->date_export_begin).'" id="date_export_begin" class="form-control" />'
@ -576,7 +600,7 @@ class AdminStatsLogistic extends AdminTab
.'<input type="hidden" name="token" value="'.Tools::getAdminTokenLite(__CLASS__).'" />'
.'<input type="hidden" name="tab" value="'.__CLASS__.'" />'
.'<input type="submit" class="button" name="submitExport" value="Exporter les Remboursements" />'
.'</form>
.'</form><p id="msg"></p>
</fieldset>';
echo '<br><br><h2 style="margin-top:15px">Export Expeditions</h2>
@ -741,8 +765,7 @@ class AdminStatsLogistic extends AdminTab
FROM `'._DB_PREFIX_.'privatesale` p
LEFT JOIN `ps_privatesale_category` c ON (c.`id_sale` = p.`id_sale`)
LEFT JOIN `ps_category_lang` l ON (l.`id_category` = p.`id_category`)
WHERE p.`date_start` >= "'.pSQL($this->date_export_begin).
'" AND p.`date_start` <= "'.pSQL($this->date_export_end).'"
WHERE p.`date_start` >= "'.pSQL($this->date_export_begin).'" AND p.`date_start` <= "'.pSQL($this->date_export_end).'"
AND l.`id_lang` = '. (int) Context::getContext()->language->id.'
');
}

View File

@ -0,0 +1,48 @@
<?php
require_once dirname(__FILE__).'../../../config/config.inc.php';
require_once dirname(__FILE__).'../../../init.php';
$action = Tools::getValue('action');
switch ($action) {
case 'check':
$filename = Tools::getValue('file');
$path = dirname(__FILE__) . '/export';
$file = $path . '/' . $filename;
if (file_exists($file)) {
echo '<a href="http://'.$_SERVER['SERVER_NAME'].'/adm/index.php?tab=AdminStatsLogistic&token='.
Tools::getValue('token').'&dl=1&file='.$filename.'" target="_blank">Télécharger le fichier</a>';
} else {
echo "";
}
break;
case 'export':
$start = Tools::getValue('date_export_begin');
$end = Tools::getValue('date_export_end');
if (empty($start) || empty($end)) {
$url = '';
} else {
$url = 'http://'.$_SERVER['SERVER_NAME'].__PS_BASE_URI__.
'modules/stats_logistic/ajax.php?action=check&token='.Tools::getValue('token');
}
$cmd = dirname(__FILE__).'/bin/export.php --start '.$start.' --end '.$end.'';
exec('php '.$cmd.' &');
// Always return checkin url
echo json_encode(array(
'url' => $url,
'file' => 'export-remb-'.$start.'-'.$end.'.csv',
));
break;
default:
exit;
}
exit;

View File

@ -0,0 +1,49 @@
<?php
$_SERVER['HTTP_HOST'] = 'www.bebeboutik.com';
$_SERVER['SERVER_NAME'] = 'www.bebeboutik.com';
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$_SERVER['HTTP_PORT'] = 443;
$_SERVER['HTTP_X_FORWARDED_PORT'] = 443;
$_SERVER['SERVER_PORT'] = 443;
require_once __DIR__ . '/../../../config/config.inc.php';
require_once __DIR__ . '/../stats_logistic.php';
if (!Tools::isCli()){
exit();
}
$longopts = array(
'verbose',
'dry-run',
'start:',
'end:'
);
$shortopts = "";
$options = getopt($shortopts, $longopts);
// Options
$optVerbose = false;
if (isset($options['verbose'])) {
$optVerbose = true;
}
$optTest = false;
if (isset($options['dry-run'])) {
$optTest = true;
}
$start = $options['start'];
$end = $options['end'];
$path = __DIR__.'/../export';
if (!file_exists($path)) {
mkdir($path);
}
$path = realpath($path);
$module = new stats_logistic();
$stat = new StatsLogistic($path);
$stat->export($start, $end);

View File

@ -0,0 +1,350 @@
<?php
class StatsLogistic
{
private $path;
private $date_export_begin;
private $date_export_end;
public function __construct($path)
{
$this->path = $path;
}
public function export($start, $end)
{
$this->date_export_begin = $start;
$this->date_export_end = $end;
$result = null;
$sale_ids = $this->getSales();
if ($sale_ids) {
foreach ($sale_ids as $sale) {
//$ps = new Sale((int)$sale['id_sale']);
//$product_ids = $ps->getProducts();
$product_ids = $this->getProducts((int)$sale['id_sale']);
if (!$product_ids) {
continue;
}
$products = $this->getSaleDetails($product_ids);
/*foreach ($products as $key => $product) {
$order_detail_ids[] = (int)$product['id_order_detail'];
}
$packages = $this->getPackageDetails($order_detail_ids);*/
//echo "<pre>";var_dump($product_ids, $products);echo "</pre>";die();
if ($products) {
$result[(int)$sale['id_sale']] = array(
/*'name' => $ps->title[2],
'date' => $ps->date_start,*/
'id' => $sale['id_sale'],
'name' => $sale['title'],
'date' => $sale['date_start'],
'ca_ttc' => 0,
'ca_refund' => 0,
'percent_ca_refund' => 0,
'quantity_sold' => 0,
'quantity_refund' => 0,
'percent_refund' => 0
);
$reasons = array(3,6,8,12,11,1,2,4,5,9,10,7,99);
foreach ($reasons as $key => $reason_id) {
$result[(int)$sale['id_sale']][(int)$reason_id] = array(
'ca_refund' => 0,
'percent_ca_refund' => 0,
'quantity_refund' => 0,
'percent_refund' => 0,
);
}
$id_orders = array();
$id_orders_error = array();
$shipping_numbers = array();
$result[(int)$sale['id_sale']]['nb_orders'] = 0;
$result[(int)$sale['id_sale']]['nb_orders_error_log'] = 0;
$result[(int)$sale['id_sale']]['percent_error_log'] = 0;
$result[(int)$sale['id_sale']]['nb_package'] = 0;
$result[(int)$sale['id_sale']]['nb_pole_1'] = 0;
$result[(int)$sale['id_sale']]['nb_pole_2'] = 0;
$result[(int)$sale['id_sale']]['nb_pole_3'] = 0;
$result[(int)$sale['id_sale']]['nb_pole_4'] = 0;
$result[(int)$sale['id_sale']]['nb_pole_5'] = 0;
// $result[(int)$sale['id_sale']]['nb_pole_5'] = 0;
// $result[(int)$sale['id_sale']]['nb_pole_6'] = 0;
foreach($products as $row) {
if (!in_array((int)$row['id_order'],$id_orders)) {
$id_orders[] = (int)$row['id_order'];
}
/*foreach ($packages as $pack) {
if ((int)$pack['id_order_detail'] == (int)$row['id_order_detail']) {
if(!isset($shipping_numbers[(int)$pack['id_employee']])) {
$shipping_numbers[(int)$pack['id_employee']] = array();
}
if (is_array($shipping_numbers[(int)$pack['id_employee']]) && !in_array($pack['shipping_number'],$shipping_numbers[(int)$pack['id_employee']]) ) {
$shipping_numbers[(int)$pack['id_employee']][] = $pack['shipping_number'];
}
}
}*/
if(isset($row['id_employee']) && !isset($shipping_numbers[(int)$row['id_employee']])) {
$shipping_numbers[(int)$row['id_employee']] = array();
}
if (isset($row['shipping_number']) && is_array($shipping_numbers[(int)$row['id_employee']]) && !in_array($row['shipping_number'],$shipping_numbers[(int)$row['id_employee']]) ) {
$shipping_numbers[(int)$row['id_employee']][] = $row['shipping_number'];
}
/*$price = (isset($row['product_quantity_discount']) && $row['product_quantity_discount']!=0)?(float)$row['product_quantity_discount']:(float)$row['product_price'];
$result[(int)$sale['id_sale']]['ca_ttc'] += (((int)$row['product_quantity'] - (int)$row['product_quantity_reinjected'])*$price);
$result[(int)$sale['id_sale']]['quantity_sold'] += ((int)$row['product_quantity'] - (int)$row['product_quantity_reinjected']);*/
$price = (float)$row['price'];
$result[(int)$sale['id_sale']]['ca_ttc'] += ((int)$row['product_quantity'] * $price);
$result[(int)$sale['id_sale']]['quantity_sold'] += (int)$row['product_quantity'];
if ($row['product_quantity_reinjected']>0) {
$result[(int)$sale['id_sale']]['quantity_refund'] += (int)$row['product_quantity_reinjected'];
$result[(int)$sale['id_sale']]['ca_refund'] += ((int)$row['product_quantity_reinjected']*$price);
if (!isset($row['id_reason'])) {
$row['id_reason'] = 99;
}
if ((int)$row['id_reason'] == 6 && !in_array((int)$row['id_order'],$id_orders_error)) {
$id_orders_error[] = (int)$row['id_order'];
}
if (in_array((int)$row['id_reason'], $reasons)) {
if(!isset($result[(int)$sale['id_sale']][(int)$row['id_reason']])) {
$result[(int)$sale['id_sale']][(int)$row['id_reason']] = array(
'ca_refund' => 0,
'percent_ca_refund' => 0,
'quantity_refund' => 0,
'percent_refund' => 0,
);
}
$result[(int)$sale['id_sale']][(int)$row['id_reason']]['ca_refund'] += round(((int)$row['product_quantity_reinjected']*$price),2);
$result[(int)$sale['id_sale']][(int)$row['id_reason']]['quantity_refund'] += round((int)$row['product_quantity_reinjected'],2);
}
}
}
$result[(int)$sale['id_sale']]['percent_ca_refund'] = number_format(($result[(int)$sale['id_sale']]['ca_refund'] / $result[(int)$sale['id_sale']]['ca_ttc'])*100,2);
$result[(int)$sale['id_sale']]['percent_refund'] = number_format(($result[(int)$sale['id_sale']]['quantity_refund'] / $result[(int)$sale['id_sale']]['quantity_sold'])*100,2);
foreach ($reasons as $key => $reason_id) {
if (isset($result[(int)$sale['id_sale']][$reason_id])) {
$result[(int)$sale['id_sale']][$reason_id]['percent_ca_refund'] += round(($result[(int)$sale['id_sale']][$reason_id]['ca_refund'] / $result[(int)$sale['id_sale']]['ca_ttc'])*100,2);
$result[(int)$sale['id_sale']][$reason_id]['percent_refund'] += round(($result[(int)$sale['id_sale']][$reason_id]['quantity_refund'] / $result[(int)$sale['id_sale']]['quantity_sold'])*100,2);
}
}
$result[(int)$sale['id_sale']]['ca_ttc'] = round($result[(int)$sale['id_sale']]['ca_ttc'],2);
$result[(int)$sale['id_sale']]['ca_refund'] = round($result[(int)$sale['id_sale']]['ca_refund'],2);
$result[(int)$sale['id_sale']]['nb_orders'] = count($id_orders);
$result[(int)$sale['id_sale']]['nb_orders_error_log'] = count($id_orders_error);
$result[(int)$sale['id_sale']]['percent_error_log'] = number_format(($result[(int)$sale['id_sale']]['nb_orders_error_log'] / $result[(int)$sale['id_sale']]['nb_orders'])*100,2);
$nb_package = 0;
foreach ($shipping_numbers as $id_employee => $value) {
$nb_package += count($value);
switch ($id_employee) {
case '22':
case '24':
$result[(int)$sale['id_sale']]['nb_pole_1'] += count($value);
break;
case '25':
case '44':
$result[(int)$sale['id_sale']]['nb_pole_2'] += count($value);
break;
case '47':
case '48':
$result[(int)$sale['id_sale']]['nb_pole_3'] += count($value);
break;
case '35':
case '36':
$result[(int)$sale['id_sale']]['nb_pole_4'] += count($value);
break;
default:
$result[(int)$sale['id_sale']]['nb_pole_5'] += count($value);
break;
}
}
$result[(int)$sale['id_sale']]['nb_package'] = $nb_package;
$result[(int)$sale['id_sale']]['nb_pole_1'] = number_format(($result[(int)$sale['id_sale']]['nb_pole_1'] / $nb_package)*100,2);
$result[(int)$sale['id_sale']]['nb_pole_2'] = number_format(($result[(int)$sale['id_sale']]['nb_pole_2'] / $nb_package)*100,2);
$result[(int)$sale['id_sale']]['nb_pole_3'] = number_format(($result[(int)$sale['id_sale']]['nb_pole_3'] / $nb_package)*100,2);
$result[(int)$sale['id_sale']]['nb_pole_4'] = number_format(($result[(int)$sale['id_sale']]['nb_pole_4'] / $nb_package)*100,2);
$result[(int)$sale['id_sale']]['nb_pole_5'] = number_format(($result[(int)$sale['id_sale']]['nb_pole_5'] / $nb_package)*100,2);
// $result[(int)$sale['id_sale']]['nb_pole_6'] = number_format(($result[(int)$sale['id_sale']]['nb_pole_6'] / $nb_package)*100,2);
}
}
}
$fname = 'export-remb-'.$this->date_export_begin.'-'.$this->date_export_end.'.csv';
if ($result !== null) {
$this->exportCSV($result, $fname);
} else {
file_put_contents($this->path.'/'.$fname, "Aucune information");
}
}
public function getSales()
{
return Db::getInstance()->ExecuteS('
SELECT DISTINCT p.`id_sale`, p.`date_start`, l.`name` as title
FROM `'._DB_PREFIX_.'privatesale` p
LEFT JOIN `ps_privatesale_category` c ON (c.`id_sale` = p.`id_sale`)
LEFT JOIN `ps_category_lang` l ON (l.`id_category` = p.`id_category`)
WHERE p.`date_start` >= "'.pSQL($this->date_export_begin).'" AND p.`date_start` <= "'.pSQL($this->date_export_end).'"
AND l.`id_lang` = 2
');
}
public function getProducts($id_sale)
{
$product_ids = array();
foreach(Db::getInstance()->ExecuteS('
SELECT DISTINCT `id_product`
FROM `'._DB_PREFIX_.'product_ps_cache`
WHERE `id_sale`='.(int)$id_sale.'
') as $row ) {
$product_ids[] = (int) $row['id_product'];
}
return $product_ids;
}
public function getSaleDetails($product_ids)
{
$sale_details = array();
$sale_details_lpw = Db::getInstance()->ExecuteS('
SELECT od.*, rr.`id_reason`, pws.`id_employee`, pws.`shipping_number`,
ROUND(((od.`product_price` * (1 - od.`reduction_percent` / 100) - od.`reduction_amount`) * (1 - od.`group_reduction` / 100) * (1 + od.`tax_rate` / 100)), 6) AS `price`
FROM `'._DB_PREFIX_.'order_detail` od
LEFT JOIN `'._DB_PREFIX_.'order_slip` os ON (os.`id_order` = od.`id_order`)
LEFT JOIN `'._DB_PREFIX_.'lapostews` pws ON (pws.`id_order_detail` = od.`id_order_detail`)
LEFT JOIN `'._DB_PREFIX_.'refundreason` rr ON (rr.`id_order_slip` = os.`id_order_slip`)
WHERE od.`product_id` IN ('.implode(',', $product_ids).')
AND pws.id_order_detail IS NOT NULL
ORDER BY rr.`id_reason`');
$sale_details_mr = Db::getInstance()->ExecuteS('
SELECT od.*, rr.`id_reason`, mrp.`id_employee`, mrp.`shipping_number`,
ROUND(((od.`product_price` * (1 - od.`reduction_percent` / 100) - od.`reduction_amount`) * (1 - od.`group_reduction` / 100) * (1 + od.`tax_rate` / 100)), 6) AS `price`
FROM `'._DB_PREFIX_.'order_detail` od
LEFT JOIN `'._DB_PREFIX_.'order_slip` os ON (os.`id_order` = od.`id_order`)
LEFT JOIN `'._DB_PREFIX_.'mondialrelay_parcel` mrp ON (mrp.`id_order_detail` = od.`id_order_detail`)
LEFT JOIN `'._DB_PREFIX_.'refundreason` rr ON (rr.`id_order_slip` = os.`id_order_slip`)
WHERE od.`product_id` IN ('.implode(',', $product_ids).')
AND mrp.id_order_detail IS NOT NULL
ORDER BY rr.`id_reason`
');
$sale_details = array_merge($sale_details_lpw, $sale_details_mr);
return $sale_details;
}
public function exportCSV ($result, $filename)
{
$fp = fopen($this->path.'/'.$filename, 'w');
$delim = ';';
$row_1 = array("","","","","","","","","");
$row_2 = array("Vente","Marque","Date de Debut","CA produit TTC","CA remb TTC","% remb valeur","Quantite vendue","Quantite remb","% remb volume");
$reasons = array();
$reasons[] = array(
'id_reason' => 3,
'name' => "BBB : Erreur Achat / Prod",
);
$reasons[] = array(
'id_reason' => 6,
'name' => "BBB : Erreur Logistique",
);
$reasons[] = array(
'id_reason' => 8,
'name' => "BBB : Pbme Site / Paiment",
);
$reasons[] = array(
'id_reason' => 12,
'name' => "BBB : Suspicion de fraude",
);
$reasons[] = array(
'id_reason' => 11,
'name' => "CLIENT : Annulation pour re-achat",
);
$reasons[] = array(
'id_reason' => 1,
'name' => "CLIENT : Annulation pre-envoi",
);
$reasons[] = array(
'id_reason' => 2,
'name' => "CLIENT : Retractation post-envoi",
);
$reasons[] = array(
'id_reason' => 4,
'name' => "FEUR : Probleme SAV",
);
$reasons[] = array(
'id_reason' => 5,
'name' => "FEUR : Produit manquant",
);
$reasons[] = array(
'id_reason' => 9,
'name' => "TRANS : Colis detruit",
);
$reasons[] = array(
'id_reason' => 10,
'name' => "TRANS : Colis perdu",
);
$reasons[] = array(
'id_reason' => 7,
'name' => "Autre",
);
$reasons[] = array(
'id_reason' => 99,
'name' => "Vide",
);
foreach ($reasons as $key => $reason) {
$row_1[] = $reason['name'] ;
$row_1[] = "" ;
$row_1[] = "" ;
$row_1[] = "" ;
$row_2[] = "CA remb TTC";
$row_2[] = "% remb valeur";
$row_2[] = "Quantite remb";
$row_2[] = "% remb volume";
}
$row_2 = array_merge(
$row_2,
array(
"Nb commande",
"Nb commande erreur log",
"% erreur","NB colis",
"% colis Pole 1",
"% colis Pole 2",
"% colis Pole 3",
"% colis Pole 4",
"% colis Pole 5",
"% colis Pole 6"
)
);
fputcsv ($fp,$row_1,$delim);
fputcsv ($fp,$row_2,$delim);
foreach ($result as $key => $row) {
$data = array();
foreach ($row as $k => $value) {
if (is_array($value)){
foreach ($value as $key => $val) {
$data[] = $val;
}
} else {
$data[] = $value;
}
}
fputcsv ($fp, array_map('utf8_decode', array_values($data)), $delim);
}
fclose($fp);
}
}

View File

@ -1,9 +1,12 @@
<?php
class stats_logistic extends Module {
require_once __DIR__.'/models/StatsLogistic.php';
class stats_logistic extends Module
{
const ADMIN_STATS_LOGISTIC_CLASS = 'AdminStatsLogistic';
public function __construct() {
public function __construct()
{
$this->name = 'stats_logistic';
$this->tab = 'analytics_stats';
$this->author = 'Antadis';
@ -14,14 +17,16 @@ class stats_logistic extends Module {
$this->description = $this->l('Display stats of the employee');
}
public function install() {
public function install()
{
return (
parent::install()
and self::createTab(6, $this->name, $this->l('Stats logistic'), self::ADMIN_STATS_LOGISTIC_CLASS)
);
}
public function uninstall() {
public function uninstall()
{
return (
parent::uninstall()
and self::dropTable()
@ -29,7 +34,8 @@ class stats_logistic extends Module {
);
}
public static function createTab($id_parent, $module, $name, $class_name, $status=TRUE) {
public static function createTab($id_parent, $module, $name, $class_name, $status=TRUE)
{
$tab = new Tab();
$tab->module = $module;
@ -48,7 +54,8 @@ class stats_logistic extends Module {
return $tab->id;
}
public function getContent() {
public function getContent()
{
global $currentIndex;
Tools::redirectAdmin($currentIndex.'&tab='.self::ADMIN_STATS_LOGISTIC_CLASS.'&token='.Tools::getAdminTokenLite(self::ADMIN_STATS_LOGISTIC_CLASS));
Tools::redirectAdmin($this->context->link->getAdminLink(self::ADMIN_STATS_LOGISTIC_CLASS));

View File

@ -0,0 +1,36 @@
$(function(){
var timer;
var delay = 1000;
var count = 0;
var url;
var file;
function checkFile()
{
count++;
$('#msg').text('Construction du fichier...('+ count +')...');
$.post(url, {count: count, file: file}, function (data, textStatus) {
if (data != '') {
clearInterval(timer);
count = 0;
$('#msg').html(data);
}
});
}
$('form').submit(function(e) {
e.preventDefault();
url = $(this).attr('action');
console.log(url);
console.log($(this).serialize());
$.post(url, $(this).serialize(), function (data, textStatus) {
if (data.url != '') {
url = data.url;
file = data.file;
timer = setInterval(checkFile, delay);
}
}, 'json');
return false;
});
});