Merge pull request #3088 from atm-maxime/develop

New : add stats by qty on report turnover by product (+ clean code)
This commit is contained in:
Juanjo Menent 2015-06-24 18:23:31 +02:00
commit fc9d54fdaa

View File

@ -1,5 +1,5 @@
<?php <?php
/* Copyright (C) 2013 Antoine Iauch <aiauch@gpcsolutions.fr> /* Copyright (C) 2013 Antoine Iauch <aiauch@gpcsolutions.fr>
* Copyright (C) 2013 Laurent Destailleur <eldy@users.sourceforge.net> * Copyright (C) 2013 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr> * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
* *
@ -18,8 +18,8 @@
*/ */
/** /**
* \file htdocs/compta/stats/cabyprodserv.php * \file htdocs/compta/stats/cabyprodserv.php
* \brief Page reporting TO by Products & Services * \brief Page reporting TO by Products & Services
*/ */
require '../../main.inc.php'; require '../../main.inc.php';
@ -47,13 +47,13 @@ if (GETPOST("modecompta")) $modecompta=GETPOST("modecompta");
$sortorder=isset($_GET["sortorder"])?$_GET["sortorder"]:$_POST["sortorder"]; $sortorder=isset($_GET["sortorder"])?$_GET["sortorder"]:$_POST["sortorder"];
$sortfield=isset($_GET["sortfield"])?$_GET["sortfield"]:$_POST["sortfield"]; $sortfield=isset($_GET["sortfield"])?$_GET["sortfield"]:$_POST["sortfield"];
if (! $sortorder) $sortorder="asc"; if (! $sortorder) $sortorder="asc";
if (! $sortfield) $sortfield="name"; if (! $sortfield) $sortfield="ref";
// Category // Category
$selected_cat = (int) GETPOST('search_categ', 'int'); $selected_cat = (int) GETPOST('search_categ', 'int');
$subcat = false; $subcat = false;
if (GETPOST('subcat', 'alpha') === 'yes') { if (GETPOST('subcat', 'alpha') === 'yes') {
$subcat = true; $subcat = true;
} }
// Date range // Date range
@ -132,7 +132,7 @@ $headerparams = array_merge($commonparams, $headerparams);
$tableparams = array_merge($commonparams, $tableparams); $tableparams = array_merge($commonparams, $tableparams);
foreach($allparams as $key => $value) { foreach($allparams as $key => $value) {
$paramslink .= '&' . $key . '=' . $value; $paramslink .= '&' . $key . '=' . $value;
} }
@ -148,28 +148,28 @@ $nom=$langs->trans("SalesTurnover").', '.$langs->trans("ByProductsAndServices");
if ($modecompta=="CREANCES-DETTES") { if ($modecompta=="CREANCES-DETTES") {
$calcmode=$langs->trans("CalcModeDebt"); $calcmode=$langs->trans("CalcModeDebt");
$calcmode.='<br>('.$langs->trans("SeeReportInInputOutputMode",'<a href="'.$_SERVER["PHP_SELF"].'?year='.$year.'&modecompta=RECETTES-DEPENSES">','</a>').')'; $calcmode.='<br>('.$langs->trans("SeeReportInInputOutputMode",'<a href="'.$_SERVER["PHP_SELF"].'?year='.$year.'&modecompta=RECETTES-DEPENSES">','</a>').')';
$period=$form->select_date($date_start,'date_start',0,0,0,'',1,0,1).' - '.$form->select_date($date_end,'date_end',0,0,0,'',1,0,1); $period=$form->select_date($date_start,'date_start',0,0,0,'',1,0,1).' - '.$form->select_date($date_end,'date_end',0,0,0,'',1,0,1);
$description=$langs->trans("RulesCADue"); $description=$langs->trans("RulesCADue");
if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
$description.= $langs->trans("DepositsAreNotIncluded"); $description.= $langs->trans("DepositsAreNotIncluded");
} else { } else {
$description.= $langs->trans("DepositsAreIncluded"); $description.= $langs->trans("DepositsAreIncluded");
} }
$builddate=time(); $builddate=time();
} else { } else {
$calcmode=$langs->trans("CalcModeEngagement"); $calcmode=$langs->trans("CalcModeEngagement");
$calcmode.='<br>('.$langs->trans("SeeReportInDueDebtMode",'<a href="'.$_SERVER["PHP_SELF"].'?year='.$year.'&modecompta=CREANCES-DETTES">','</a>').')'; $calcmode.='<br>('.$langs->trans("SeeReportInDueDebtMode",'<a href="'.$_SERVER["PHP_SELF"].'?year='.$year.'&modecompta=CREANCES-DETTES">','</a>').')';
$period=$form->select_date($date_start,'date_start',0,0,0,'',1,0,1).' - '.$form->select_date($date_end,'date_end',0,0,0,'',1,0,1); $period=$form->select_date($date_start,'date_start',0,0,0,'',1,0,1).' - '.$form->select_date($date_end,'date_end',0,0,0,'',1,0,1);
$description=$langs->trans("RulesCAIn"); $description=$langs->trans("RulesCAIn");
$description.= $langs->trans("DepositsAreIncluded"); $description.= $langs->trans("DepositsAreIncluded");
$builddate=time(); $builddate=time();
} }
report_header($nom,$nomlink,$period,$periodlink,$description,$builddate,$exportlink,$tableparams,$calcmode); report_header($nom,$nomlink,$period,$periodlink,$description,$builddate,$exportlink,$tableparams,$calcmode);
@ -180,221 +180,226 @@ $catotal=0;
if ($modecompta == 'CREANCES-DETTES') if ($modecompta == 'CREANCES-DETTES')
{ {
$sql = "SELECT DISTINCT p.rowid as rowid, p.ref as ref, p.label as label,"; $sql = "SELECT DISTINCT p.rowid as rowid, p.ref as ref, p.label as label,";
$sql.= " sum(l.total_ht) as amount, sum(l.total_ttc) as amount_ttc"; $sql.= " SUM(l.total_ht) as amount, SUM(l.total_ttc) as amount_ttc,";
$sql.= " FROM ".MAIN_DB_PREFIX."facture as f, ".MAIN_DB_PREFIX."facturedet as l, ".MAIN_DB_PREFIX."product as p"; $sql.= " SUM(CASE WHEN f.type = 2 THEN -l.qty ELSE l.qty END) as qty";
$sql.= " FROM ".MAIN_DB_PREFIX."facture as f, ".MAIN_DB_PREFIX."facturedet as l, ".MAIN_DB_PREFIX."product as p";
if ($selected_cat === -2) // Without any category if ($selected_cat === -2) // Without any category
{ {
$sql.= " LEFT OUTER JOIN ".MAIN_DB_PREFIX."categorie_product as cp ON p.rowid = cp.fk_product"; $sql.= " LEFT OUTER JOIN ".MAIN_DB_PREFIX."categorie_product as cp ON p.rowid = cp.fk_product";
} }
else if ($selected_cat) // Into a specific category else if ($selected_cat) // Into a specific category
{ {
$sql.= ", ".MAIN_DB_PREFIX."categorie as c, ".MAIN_DB_PREFIX."categorie_product as cp"; $sql.= ", ".MAIN_DB_PREFIX."categorie as c, ".MAIN_DB_PREFIX."categorie_product as cp";
} }
$sql.= " WHERE l.fk_product = p.rowid"; $sql.= " WHERE l.fk_product = p.rowid";
$sql.= " AND l.fk_facture = f.rowid"; $sql.= " AND l.fk_facture = f.rowid";
$sql.= " AND f.fk_statut in (1,2)"; $sql.= " AND f.fk_statut in (1,2)";
if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
$sql.= " AND f.type IN (0,1,2,5)"; $sql.= " AND f.type IN (0,1,2,5)";
} else { } else {
$sql.= " AND f.type IN (0,1,2,3,5)"; $sql.= " AND f.type IN (0,1,2,3,5)";
} }
if ($date_start && $date_end) { if ($date_start && $date_end) {
$sql.= " AND f.datef >= '".$db->idate($date_start)."' AND f.datef <= '".$db->idate($date_end)."'"; $sql.= " AND f.datef >= '".$db->idate($date_start)."' AND f.datef <= '".$db->idate($date_end)."'";
} }
if ($selected_cat === -2) // Without any category if ($selected_cat === -2) // Without any category
{ {
$sql.=" AND cp.fk_product is null"; $sql.=" AND cp.fk_product is null";
} }
else if ($selected_cat) { // Into a specific category else if ($selected_cat) { // Into a specific category
$sql.= " AND (c.rowid = ".$selected_cat; $sql.= " AND (c.rowid = ".$selected_cat;
if ($subcat) $sql.=" OR c.fk_parent = " . $selected_cat; if ($subcat) $sql.=" OR c.fk_parent = " . $selected_cat;
$sql.= ")"; $sql.= ")";
$sql.= " AND cp.fk_categorie = c.rowid AND cp.fk_product = p.rowid"; $sql.= " AND cp.fk_categorie = c.rowid AND cp.fk_product = p.rowid";
} }
$sql.= " AND f.entity = ".$conf->entity; $sql.= " AND f.entity = ".$conf->entity;
$sql.= " GROUP BY p.rowid, p.ref, p.label"; $sql.= " GROUP BY p.rowid, p.ref, p.label";
$sql.= " ORDER BY p.ref"; $sql.= $db->order($sortfield,$sortorder);
dol_syslog("cabyprodserv", LOG_DEBUG); dol_syslog("cabyprodserv", LOG_DEBUG);
$result = $db->query($sql); $result = $db->query($sql);
if ($result) { if ($result) {
$num = $db->num_rows($result); $num = $db->num_rows($result);
$i=0; $i=0;
while ($i < $num) { while ($i < $num) {
$obj = $db->fetch_object($result); $obj = $db->fetch_object($result);
$amount_ht[$obj->rowid] = $obj->amount; $amount_ht[$obj->rowid] = $obj->amount;
$amount[$obj->rowid] = $obj->amount_ttc; $amount[$obj->rowid] = $obj->amount_ttc;
$name[$obj->rowid] = $obj->ref . '&nbsp;-&nbsp;' . $obj->label; $qty[$obj->rowid] = $obj->qty;
$catotal_ht+=$obj->amount; $name[$obj->rowid] = $obj->ref . '&nbsp;-&nbsp;' . $obj->label;
$catotal+=$obj->amount_ttc; $catotal_ht+=$obj->amount;
$i++; $catotal+=$obj->amount_ttc;
$qtytotal+=$obj->qty;
$i++;
}
} else {
dol_print_error($db);
} }
} else {
dol_print_error($db);
}
// Show Array // Show Array
$i=0; $i=0;
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">'; print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
// Extra parameters management // Extra parameters management
foreach($headerparams as $key => $value) foreach($headerparams as $key => $value)
{ {
print '<input type="hidden" name="'.$key.'" value="'.$value.'">'; print '<input type="hidden" name="'.$key.'" value="'.$value.'">';
} }
print '<table class="noborder" width="100%">'; print '<table class="noborder" width="100%">';
// Category filter // Category filter
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';
print '<td>'; print '<td>';
print $langs->trans("Category") . ': ' . $formother->select_categories(Categorie::TYPE_PRODUCT, $selected_cat, 'search_categ', true); print $langs->trans("Category") . ': ' . $formother->select_categories(Categorie::TYPE_PRODUCT, $selected_cat, 'search_categ', true);
print ' '; print ' ';
print $langs->trans("SubCats") . '? '; print $langs->trans("SubCats") . '? ';
print '<input type="checkbox" name="subcat" value="yes"'; print '<input type="checkbox" name="subcat" value="yes"';
if ($subcat) { if ($subcat) {
print ' checked'; print ' checked';
} }
print '></td>'; print '></td>';
print '<td colspan="3" align="right">'; print '<td colspan="5" align="right">';
print '<input type="image" class="liste_titre" name="button_search" src="'.img_picto($langs->trans("Search"),'search.png','','',1).'" value="'.dol_escape_htmltag($langs->trans("Search")).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">'; print '<input type="image" class="liste_titre" name="button_search" src="'.img_picto($langs->trans("Search"),'search.png','','',1).'" value="'.dol_escape_htmltag($langs->trans("Search")).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">';
print '</td></tr>'; print '</td></tr>';
// Array header
print "<tr class=\"liste_titre\">";
print_liste_field_titre(
$langs->trans("Product"),
$_SERVER["PHP_SELF"],
"name",
"",
$paramslink,
"",
$sortfield,
$sortorder
);
print_liste_field_titre(
$langs->trans('AmountHT'),
$_SERVER["PHP_SELF"],
"amount_ht",
"",
$paramslink,
'align="right"',
$sortfield,
$sortorder
);
print_liste_field_titre(
$langs->trans("AmountTTC"),
$_SERVER["PHP_SELF"],
"amount_ttc",
"",
$paramslink,
'align="right"',
$sortfield,
$sortorder
);
print_liste_field_titre(
$langs->trans("Percentage"),
$_SERVER["PHP_SELF"],
"amount_ttc",
"",
$paramslink,
'align="right"',
$sortfield,
$sortorder
);
// TODO: statistics?
print "</tr>\n";
// Array Data // Array header
$var=true; print "<tr class=\"liste_titre\">";
print_liste_field_titre(
$langs->trans("Product"),
$_SERVER["PHP_SELF"],
"ref",
"",
$paramslink,
"",
$sortfield,
$sortorder
);
print_liste_field_titre(
$langs->trans('Quantity'),
$_SERVER["PHP_SELF"],
"qty",
"",
$paramslink,
'align="right"',
$sortfield,
$sortorder
);
print_liste_field_titre(
$langs->trans("Percentage"),
$_SERVER["PHP_SELF"],
"qty",
"",
$paramslink,
'align="right"',
$sortfield,
$sortorder
);
print_liste_field_titre(
$langs->trans('AmountHT'),
$_SERVER["PHP_SELF"],
"amount",
"",
$paramslink,
'align="right"',
$sortfield,
$sortorder
);
print_liste_field_titre(
$langs->trans("AmountTTC"),
$_SERVER["PHP_SELF"],
"amount_ttc",
"",
$paramslink,
'align="right"',
$sortfield,
$sortorder
);
print_liste_field_titre(
$langs->trans("Percentage"),
$_SERVER["PHP_SELF"],
"amount_ttc",
"",
$paramslink,
'align="right"',
$sortfield,
$sortorder
);
print "</tr>\n";
if (count($amount)) { // Array Data
$arrayforsort=$name; $var=true;
// defining arrayforsort
if ($sortfield == 'nom' && $sortorder == 'asc') {
asort($name);
$arrayforsort=$name;
}
if ($sortfield == 'nom' && $sortorder == 'desc') {
arsort($name);
$arrayforsort=$name;
}
if ($sortfield == 'amount_ht' && $sortorder == 'asc') {
asort($amount_ht);
$arrayforsort=$amount_ht;
}
if ($sortfield == 'amount_ht' && $sortorder == 'desc') {
arsort($amount_ht);
$arrayforsort=$amount_ht;
}
if ($sortfield == 'amount_ttc' && $sortorder == 'asc') {
asort($amount);
$arrayforsort=$amount;
}
if ($sortfield == 'amount_ttc' && $sortorder == 'desc') {
arsort($amount);
$arrayforsort=$amount;
}
foreach($arrayforsort as $key=>$value) {
$var=!$var;
print "<tr ".$bc[$var].">";
// Product if (count($name)) {
$fullname=$name[$key]; foreach($name as $key=>$value) {
if ($key >= 0) { $var=!$var;
$linkname='<a href="'.DOL_URL_ROOT.'/product/card.php?id='.$key.'">'.img_object($langs->trans("ShowProduct"),'product').' '.$fullname.'</a>'; print "<tr ".$bc[$var].">";
} else {
$linkname=$langs->trans("PaymentsNotLinkedToProduct");
}
print "<td>".$linkname."</td>\n"; // Product
$fullname=$name[$key];
if ($key >= 0) {
$linkname='<a href="'.DOL_URL_ROOT.'/product/card.php?id='.$key.'">'.img_object($langs->trans("ShowProduct"),'product').' '.$fullname.'</a>';
} else {
$linkname=$langs->trans("PaymentsNotLinkedToProduct");
}
// Amount w/o VAT print "<td>".$linkname."</td>\n";
print '<td align="right">';
/*if ($key > 0) {
print '<a href="'.DOL_URL_ROOT.'/compta/facture/list.php?productid='.$key.'">';
} else {
print '<a href="#">';
}*/
print price($amount_ht[$key]);
//print '</a>';
print '</td>';
// Amount with VAT // Quantity
print '<td align="right">'; print '<td align="right">';
/*if ($key > 0) { print $qty[$key];
print '<a href="'.DOL_URL_ROOT.'/compta/facture/list.php?productid='.$key.'">'; print '</td>';
} else {
print '<a href="#">';
}*/
print price($amount[$key]);
//print '</a>';
print '</td>';
// Percent; // Percent;
print '<td align="right">'.($catotal > 0 ? round(100 * $amount[$key] / $catotal, 2).'%' : '&nbsp;').'</td>'; print '<td align="right">'.($qtytotal > 0 ? round(100 * $qty[$key] / $qtytotal, 2).'%' : '&nbsp;').'</td>';
// TODO: statistics? // Amount w/o VAT
print '<td align="right">';
/*if ($key > 0) {
print '<a href="'.DOL_URL_ROOT.'/compta/facture/list.php?productid='.$key.'">';
} else {
print '<a href="#">';
}*/
print price($amount_ht[$key]);
//print '</a>';
print '</td>';
print "</tr>\n"; // Amount with VAT
$i++; print '<td align="right">';
} /*if ($key > 0) {
print '<a href="'.DOL_URL_ROOT.'/compta/facture/list.php?productid='.$key.'">';
} else {
print '<a href="#">';
}*/
print price($amount[$key]);
//print '</a>';
print '</td>';
// Total // Percent;
print '<tr class="liste_total">'; print '<td align="right">'.($catotal > 0 ? round(100 * $amount[$key] / $catotal, 2).'%' : '&nbsp;').'</td>';
print '<td>'.$langs->trans("Total").'</td>';
print '<td align="right">'.price($catotal_ht).'</td>';
print '<td align="right">'.price($catotal).'</td>';
print '<td>&nbsp;</td>';
print '</tr>';
$db->free($result); // TODO: statistics?
}
print "</table>"; print "</tr>\n";
print '</form>'; $i++;
}
// Total
print '<tr class="liste_total">';
print '<td>'.$langs->trans("Total").'</td>';
print '<td align="right">'.price($catotal_ht).'</td>';
print '<td align="right">'.price($catotal).'</td>';
print '<td>&nbsp;</td>';
print '</tr>';
$db->free($result);
}
print "</table>";
print '</form>';
} else { } else {
// $modecompta != 'CREANCES-DETTES' // $modecompta != 'CREANCES-DETTES'
// "Calculation of part of each product for accountancy in this mode is not possible. When a partial payment (for example 5 euros) is done on an // "Calculation of part of each product for accountancy in this mode is not possible. When a partial payment (for example 5 euros) is done on an
// invoice with 2 product (product A for 10 euros and product B for 20 euros), what is part of paiment for product A and part of paiment for product B ? // invoice with 2 product (product A for 10 euros and product B for 20 euros), what is part of paiment for product A and part of paiment for product B ?
// Because there is no way to know this, this report is not relevant. // Because there is no way to know this, this report is not relevant.
print '<br>'.$langs->trans("TurnoverPerProductInCommitmentAccountingNotRelevant") . '<br>'; print '<br>'.$langs->trans("TurnoverPerProductInCommitmentAccountingNotRelevant") . '<br>';
} }