1<?php
2/* Copyright (C) 2012-2013	Christophe Battarel	<christophe.battarel@altairis.fr>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18/**
19 *	\file       htdocs/margin/tabs/thirdpartyMargins.php
20 *	\ingroup    product margins
21 *	\brief      Page for invoice margins of a thirdparty
22 */
23
24require '../../main.inc.php';
25require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
26require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
27require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
28
29$langs->loadLangs(array("companies", "bills", "products", "margins"));
30
31// Security check
32$socid = GETPOST('socid', 'int');
33if (!empty($user->socid)) $socid = $user->socid;
34$result = restrictedArea($user, 'societe', '', '');
35
36
37$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
38$sortfield = GETPOST("sortfield", 'alpha');
39$sortorder = GETPOST("sortorder", 'alpha');
40$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
41if (empty($page) || $page == -1) { $page = 0; }     // If $page is not defined, or '' or -1
42$offset = $limit * $page;
43$pageprev = $page - 1;
44$pagenext = $page + 1;
45if (!$sortorder) $sortorder = "DESC";
46if (!$sortfield) $sortfield = "f.datef";
47
48$object = new Societe($db);
49if ($socid > 0) $object->fetch($socid);
50
51// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
52$hookmanager->initHooks(array('thirdpartymargins', 'globalcard'));
53
54
55/*
56 * Actions
57 */
58
59$parameters = array('id'=>$socid);
60$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
61if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
62
63
64
65/*
66 * View
67 */
68
69$invoicestatic = new Facture($db);
70$form = new Form($db);
71
72$title = $langs->trans("ThirdParty").' - '.$langs->trans("Margins");
73if (!empty($conf->global->MAIN_HTML_TITLE) && preg_match('/thirdpartynameonly/', $conf->global->MAIN_HTML_TITLE) && $object->name) $title = $object->name.' - '.$langs->trans("Files");
74$help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas';
75llxHeader('', $title, $help_url);
76
77if ($socid > 0)
78{
79	$object = new Societe($db);
80	$object->fetch($socid);
81
82	/*
83     * Affichage onglets
84     */
85
86	$head = societe_prepare_head($object);
87
88	print dol_get_fiche_head($head, 'margin', $langs->trans("ThirdParty"), -1, 'company');
89
90	$linkback = '<a href="'.DOL_URL_ROOT.'/societe/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
91
92	dol_banner_tab($object, 'socid', $linkback, ($user->socid ? 0 : 1), 'rowid', 'nom');
93
94	print '<div class="fichecenter">';
95
96	print '<div class="underbanner clearboth"></div>';
97	print '<table class="border tableforfield" width="100%">';
98
99    if ($object->client)
100    {
101        print '<tr><td class="titlefield">';
102        print $langs->trans('CustomerCode').'</td><td colspan="3">';
103        print $object->code_client;
104        $tmpcheck = $object->check_codeclient();
105        if ($tmpcheck != 0 && $tmpcheck != -5) {
106        	print ' <font class="error">('.$langs->trans("WrongCustomerCode").')</font>';
107        }
108        print '</td></tr>';
109    }
110
111	if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || !empty($conf->supplier_order->enabled) || !empty($conf->supplier_invoice->enabled)) && $object->fournisseur && !empty($user->rights->fournisseur->lire))
112	{
113		print '<tr><td class="titlefield">';
114		print $langs->trans('SupplierCode').'</td><td colspan="3">';
115		print $object->code_fournisseur;
116        $tmpcheck = $object->check_codefournisseur();
117        if ($tmpcheck != 0 && $tmpcheck != -5) {
118        	print ' <font class="error">('.$langs->trans("WrongSupplierCode").')</font>';
119        }
120		print '</td></tr>';
121	}
122
123	// Total Margin
124	print '<tr><td class="titlefield">'.$langs->trans("TotalMargin").'</td><td colspan="3">';
125	print '<span id="totalMargin"></span>'; // set by jquery (see below)
126	print '</td></tr>';
127
128	// Margin Rate
129	if (!empty($conf->global->DISPLAY_MARGIN_RATES)) {
130		print '<tr><td>'.$langs->trans("MarginRate").'</td><td colspan="3">';
131		print '<span id="marginRate"></span>'; // set by jquery (see below)
132		print '</td></tr>';
133	}
134
135	// Mark Rate
136	if (!empty($conf->global->DISPLAY_MARK_RATES)) {
137		print '<tr><td>'.$langs->trans("MarkRate").'</td><td colspan="3">';
138		print '<span id="markRate"></span>'; // set by jquery (see below)
139		print '</td></tr>';
140	}
141
142	print "</table>";
143
144	print '</div>';
145	print '<div style="clear:both"></div>';
146
147	print dol_get_fiche_end();
148
149	print '<br>';
150
151	$sql = "SELECT distinct s.nom, s.rowid as socid, s.code_client,";
152	$sql .= " f.rowid as facid, f.ref, f.total as total_ht,";
153	$sql .= " f.datef, f.paye, f.fk_statut as statut, f.type,";
154	$sql .= " sum(d.total_ht) as selling_price,"; // may be negative or positive
155	$sql .= " sum(d.qty * d.buy_price_ht * (d.situation_percent / 100)) as buying_price,"; // always positive
156	$sql .= " sum(abs(d.total_ht) - (d.buy_price_ht * d.qty * (d.situation_percent / 100))) as marge"; // always positive
157	$sql .= " FROM ".MAIN_DB_PREFIX."societe as s";
158	$sql .= ", ".MAIN_DB_PREFIX."facture as f";
159	$sql .= ", ".MAIN_DB_PREFIX."facturedet as d";
160	$sql .= " WHERE f.fk_soc = s.rowid";
161	$sql .= " AND f.fk_statut > 0";
162	$sql .= " AND f.entity IN (".getEntity('invoice').")";
163	$sql .= " AND d.fk_facture = f.rowid";
164	$sql .= " AND f.fk_soc = $socid";
165	$sql .= " AND d.buy_price_ht IS NOT NULL";
166	// We should not use this here. Option ForceBuyingPriceIfNull should have effect only when inserting data. Once data is recorded, it must be used as it is for report.
167	// We keep it with value ForceBuyingPriceIfNull = 2 for retroactive effect but results are unpredicable.
168	if (isset($conf->global->ForceBuyingPriceIfNull) && $conf->global->ForceBuyingPriceIfNull == 2) {
169		$sql .= " AND d.buy_price_ht <> 0";
170	}
171	$sql .= " GROUP BY s.nom, s.rowid, s.code_client, f.rowid, f.ref, f.total, f.datef, f.paye, f.fk_statut, f.type";
172	$sql .= $db->order($sortfield, $sortorder);
173	// TODO: calculate total to display then restore pagination
174	//$sql.= $db->plimit($conf->liste_limit +1, $offset);
175
176	dol_syslog('margin:tabs:thirdpartyMargins.php', LOG_DEBUG);
177	$result = $db->query($sql);
178	if ($result)
179	{
180		$num = $db->num_rows($result);
181
182		print_barre_liste($langs->trans("MarginDetails"), $page, $_SERVER["PHP_SELF"], "&amp;socid=".$object->id, $sortfield, $sortorder, '', $num, $num, '');
183
184		$i = 0;
185		print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
186		print "<table class=\"noborder\" width=\"100%\">";
187
188		print '<tr class="liste_titre">';
189		print_liste_field_titre("Invoice", $_SERVER["PHP_SELF"], "f.ref", "", "&amp;socid=".$_REQUEST["socid"], '', $sortfield, $sortorder);
190		print_liste_field_titre("DateInvoice", $_SERVER["PHP_SELF"], "f.datef", "", "&amp;socid=".$_REQUEST["socid"], '', $sortfield, $sortorder, 'center ');
191		print_liste_field_titre("SoldAmount", $_SERVER["PHP_SELF"], "selling_price", "", "&amp;socid=".$_REQUEST["socid"], '', $sortfield, $sortorder, 'right ');
192		print_liste_field_titre("PurchasedAmount", $_SERVER["PHP_SELF"], "buying_price", "", "&amp;socid=".$_REQUEST["socid"], '', $sortfield, $sortorder, 'right ');
193		print_liste_field_titre("Margin", $_SERVER["PHP_SELF"], "marge", "", "&amp;socid=".$_REQUEST["socid"], '', $sortfield, $sortorder, 'right ');
194		if (!empty($conf->global->DISPLAY_MARGIN_RATES))
195			print_liste_field_titre("MarginRate", $_SERVER["PHP_SELF"], "", "", "&amp;socid=".$_REQUEST["socid"], '', $sortfield, $sortorder, 'right ');
196		if (!empty($conf->global->DISPLAY_MARK_RATES))
197			print_liste_field_titre("MarkRate", $_SERVER["PHP_SELF"], "", "", "&amp;socid=".$_REQUEST["socid"], '', $sortfield, $sortorder, 'right ');
198		print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "f.paye,f.fk_statut", "", "&amp;socid=".$_REQUEST["socid"], '', $sortfield, $sortorder, 'right ');
199		print "</tr>\n";
200
201		$cumul_achat = 0;
202		$cumul_vente = 0;
203
204		if ($num > 0)
205		{
206			while ($i < $num /*&& $i < $conf->liste_limit*/)
207			{
208				$objp = $db->fetch_object($result);
209
210				$marginRate = ($objp->buying_price != 0) ? (100 * $objp->marge / $objp->buying_price) : '';
211				$markRate = ($objp->selling_price != 0) ? (100 * $objp->marge / $objp->selling_price) : '';
212
213				$sign = '';
214				if ($objp->type == Facture::TYPE_CREDIT_NOTE) {
215					$sign = '-';
216				}
217
218				print '<tr class="oddeven">';
219				print '<td>';
220				$invoicestatic->id = $objp->facid;
221				$invoicestatic->ref = $objp->ref;
222				print $invoicestatic->getNomUrl(1);
223				print "</td>\n";
224				print "<td class=\"center\">";
225				print dol_print_date($db->jdate($objp->datef), 'day')."</td>";
226				print "<td class=\"right\">".price(price2num($objp->selling_price, 'MT'))."</td>\n";
227				print "<td class=\"right\">".price(price2num(($objp->type == 2 ? -1 : 1) * $objp->buying_price, 'MT'))."</td>\n";
228				print "<td class=\"right\">".$sign.price(price2num($objp->marge, 'MT'))."</td>\n";
229				if (!empty($conf->global->DISPLAY_MARGIN_RATES))
230					print "<td class=\"right\">".(($marginRate === '') ? 'n/a' : $sign.price(price2num($marginRate, 'MT'))."%")."</td>\n";
231				if (!empty($conf->global->DISPLAY_MARK_RATES))
232					print "<td class=\"right\">".(($markRate === '') ? 'n/a' : price(price2num($markRate, 'MT'))."%")."</td>\n";
233				print '<td class="right">'.$invoicestatic->LibStatut($objp->paye, $objp->statut, 5).'</td>';
234				print "</tr>\n";
235				$i++;
236				$cumul_vente += $objp->selling_price;
237				$cumul_achat += ($objp->type == 2 ? -1 : 1) * $objp->buying_price;
238			}
239		}
240
241		// affichage totaux marges
242
243		$totalMargin = $cumul_vente - $cumul_achat;
244		if ($totalMargin < 0)
245		{
246			$marginRate = ($cumul_achat != 0) ?-1 * (100 * $totalMargin / $cumul_achat) : '';
247			$markRate = ($cumul_vente != 0) ?-1 * (100 * $totalMargin / $cumul_vente) : '';
248		} else {
249			$marginRate = ($cumul_achat != 0) ? (100 * $totalMargin / $cumul_achat) : '';
250			$markRate = ($cumul_vente != 0) ? (100 * $totalMargin / $cumul_vente) : '';
251		}
252
253		// Total
254		print '<tr class="liste_total">';
255		print '<td colspan=2>'.$langs->trans('TotalMargin')."</td>";
256		print "<td class=\"right\">".price(price2num($cumul_vente, 'MT'))."</td>\n";
257		print "<td class=\"right\">".price(price2num($cumul_achat, 'MT'))."</td>\n";
258		print "<td class=\"right\">".price(price2num($totalMargin, 'MT'))."</td>\n";
259		if (!empty($conf->global->DISPLAY_MARGIN_RATES))
260			print "<td class=\"right\">".(($marginRate === '') ? 'n/a' : price(price2num($marginRate, 'MT'))."%")."</td>\n";
261		if (!empty($conf->global->DISPLAY_MARK_RATES))
262			print "<td class=\"right\">".(($markRate === '') ? 'n/a' : price(price2num($markRate, 'MT'))."%")."</td>\n";
263		print '<td class="right">&nbsp;</td>';
264		print "</tr>\n";
265	} else {
266		dol_print_error($db);
267	}
268	print "</table>";
269	print '</div>';
270
271	print '<br>';
272	$db->free($result);
273} else {
274	dol_print_error('', 'Parameter socid not defined');
275}
276
277
278print '
279    <script type="text/javascript">
280    $(document).ready(function() {
281        $("#totalMargin").html("'. price(price2num($totalMargin, 'MT')).'");
282        $("#marginRate").html("'.(($marginRate === '') ? 'n/a' : price(price2num($marginRate, 'MT'))."%").'");
283        $("#markRate").html("'.(($markRate === '') ? 'n/a' : price(price2num($markRate, 'MT'))."%").'");
284    });
285    </script>
286';
287
288// End of page
289llxFooter();
290$db->close();
291