dolibarr 21.0.0-beta
facture.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2003-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
7 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
29// Load Dolibarr environment
30require '../../main.inc.php';
31require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
32require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
33require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
35
44// Load translation files required by the page
45$langs->loadLangs(array('companies', 'bills', 'products', 'supplier_proposal'));
46
47$action = GETPOST('action', 'aZ');
48
49$id = GETPOSTINT('id');
50$ref = GETPOST('ref', 'alpha');
51
52// Security check
53$fieldvalue = (!empty($id) ? $id : (!empty($ref) ? $ref : ''));
54$fieldtype = (!empty($ref) ? 'ref' : 'rowid');
55$socid = '';
56if (!empty($user->socid)) {
57 $socid = $user->socid;
58}
59
60// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
61$hookmanager->initHooks(array('productstatsinvoice'));
62$extrafields = new ExtraFields($db);
63
64// Fetch optionals attributes and labels
65$extrafields->fetch_name_optionals_label('facture');
66
67$search_array_options = $extrafields->getOptionalsFromPost('facture', '', 'search_');
68
69$showmessage = GETPOST('showmessage');
70
71// Load variable for pagination
72$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
73$sortfield = GETPOST('sortfield', 'aZ09comma');
74$sortorder = GETPOST('sortorder', 'aZ09comma');
75$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
76if (empty($page) || $page == -1) {
77 $page = 0;
78} // If $page is not defined, or '' or -1
79$offset = $limit * $page;
80$pageprev = $page - 1;
81$pagenext = $page + 1;
82if (!$sortorder) {
83 $sortorder = "DESC";
84}
85if (!$sortfield) {
86 $sortfield = "f.datef";
87}
88
89$option = '';
90
91$search_date_startday = GETPOSTINT('search_date_startday');
92if (!empty($search_date_startday)) {
93 $option .= '&search_date_startday='.$search_date_startday;
94}
95$search_date_startmonth = GETPOSTINT('search_date_startmonth');
96if (!empty($search_date_startmonth)) {
97 $option .= '&search_date_startmonth='.$search_date_startmonth;
98}
99$search_date_startyear = GETPOSTINT('search_date_startyear');
100if (!empty($search_date_startyear)) {
101 $option .= '&search_date_startyear='.$search_date_startyear;
102}
103$search_date_endday = GETPOSTINT('search_date_endday');
104if (!empty($search_date_endday)) {
105 $option .= '&search_date_endday='.$search_date_endday;
106}
107$search_date_endmonth = GETPOSTINT('search_date_endmonth');
108if (!empty($search_date_endmonth)) {
109 $option .= '&search_date_endmonth='.$search_date_endmonth;
110}
111$search_date_endyear = GETPOSTINT('search_date_endyear');
112if (!empty($search_date_endyear)) {
113 $option .= '&search_date_endyear='.$search_date_endyear;
114}
115$search_date_start = dol_mktime(0, 0, 0, $search_date_startmonth, $search_date_startday, $search_date_startyear); // Use tzserver
116$search_date_end = dol_mktime(23, 59, 59, $search_date_endmonth, $search_date_endday, $search_date_endyear);
117
118if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
119 $search_date_startday = '';
120 $search_date_startmonth = '';
121 $search_date_startyear = '';
122 $search_date_endday = '';
123 $search_date_endmonth = '';
124 $search_date_endyear = '';
125 $search_date_start = '';
126 $search_date_end = '';
127}
128
129$result = restrictedArea($user, 'produit|service', $fieldvalue, 'product&product', '', '', $fieldtype);
130
131
132/*
133 * View
134 */
135
136$invoicestatic = new Facture($db);
137$societestatic = new Societe($db);
138
139$form = new Form($db);
140$formother = new FormOther($db);
141
142if ($id > 0 || !empty($ref)) {
143 $product = new Product($db);
144 $result = $product->fetch($id, $ref);
145
146 $object = $product;
147
148 $parameters = array('id' => $id);
149 $reshook = $hookmanager->executeHooks('doActions', $parameters, $product, $action); // Note that $action and $object may have been modified by some hooks
150 if ($reshook < 0) {
151 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
152 }
153
154 $title = $langs->trans('ProductServiceCard');
155 $helpurl = '';
156 $shortlabel = dol_trunc($object->label, 16);
157 if (GETPOST("type") == '0' || ($object->type == Product::TYPE_PRODUCT)) {
158 $title = $langs->trans('Product')." ".$shortlabel." - ".$langs->trans('Referers');
159 $helpurl = 'EN:Module_Products|FR:Module_Produits|ES:M&oacute;dulo_Productos';
160 }
161 if (GETPOST("type") == '1' || ($object->type == Product::TYPE_SERVICE)) {
162 $title = $langs->trans('Service')." ".$shortlabel." - ".$langs->trans('Referers');
163 $helpurl = 'EN:Module_Services_En|FR:Module_Services|ES:M&oacute;dulo_Servicios';
164 }
165
166 llxHeader('', $title, $helpurl, '', 0, 0, '', '', '', 'mod-product page-stats_facture');
167
168 if ($result > 0) {
169 $head = product_prepare_head($product);
170 $titre = $langs->trans("CardProduct".$product->type);
171 $picto = ($product->type == Product::TYPE_SERVICE ? 'service' : 'product');
172 print dol_get_fiche_head($head, 'referers', $titre, -1, $picto);
173
174 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $product, $action); // Note that $action and $object may have been modified by hook
175 print $hookmanager->resPrint;
176 if ($reshook < 0) {
177 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
178 }
179
180 $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?restore_lastsearch_values=1&type='.$object->type.'">'.$langs->trans("BackToList").'</a>';
181
182 $shownav = 1;
183 if ($user->socid && !in_array('product', explode(',', getDolGlobalString('MAIN_MODULES_FOR_EXTERNAL')))) {
184 $shownav = 0;
185 }
186
187 dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref');
188
189 print '<div class="fichecenter">';
190
191 print '<div class="underbanner clearboth"></div>';
192 print '<table class="border tableforfield centpercent">';
193
194 $nboflines = show_stats_for_company($product, $socid);
195
196 print "</table>";
197
198 print '</div>';
199 print '<div class="clearboth"></div>';
200
201 print dol_get_fiche_end();
202
203 if ($showmessage && $nboflines > 1) {
204 print '<span class="opacitymedium">'.$langs->trans("ClinkOnALinkOfColumn", $langs->transnoentitiesnoconv("Referers")).'</span>';
205 } elseif ($user->hasRight('facture', 'lire')) {
206 $sql = "SELECT DISTINCT s.nom as name, s.rowid as socid, s.code_client,";
207 $sql .= " f.ref, f.datef, f.paye, f.type, f.fk_statut as statut, f.rowid as facid,";
208 $sql .= " d.rowid, d.total_ht as total_ht, d.qty"; // We must keep the d.rowid here to not loose record because of the distinct used to ignore duplicate line when link on societe_commerciaux is used
209 if (!$user->hasRight('societe', 'client', 'voir')) {
210 $sql .= ", sc.fk_soc, sc.fk_user ";
211 }
212 // Add fields from extrafields
213 if (!empty($extrafields->attributes['facture']['label'])) {
214 foreach ($extrafields->attributes['facture']['label'] as $key => $val) {
215 $sql .= ($extrafields->attributes['facture']['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : '');
216 }
217 }
218 // Add fields from hooks
219 $parameters = array();
220 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
221 $sql .= $hookmanager->resPrint;
222 $sql = preg_replace('/,\s*$/', '', $sql);
223
224 $sql .= " FROM ".MAIN_DB_PREFIX."societe as s";
225 $sql .= ", ".MAIN_DB_PREFIX."facture as f";
226 if (isset($extrafields->attributes['facture']['label']) && is_array($extrafields->attributes['facture']['label']) && count($extrafields->attributes['facture']['label'])) {
227 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.'facture'."_extrafields as ef on (f.rowid = ef.fk_object)";
228 }
229 $sql .= ", ".MAIN_DB_PREFIX."facturedet as d";
230 if (!$user->hasRight('societe', 'client', 'voir')) {
231 $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
232 }
233 // Add table from hooks
234 $parameters = array();
235 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook
236 $sql .= $hookmanager->resPrint;
237
238 $sql .= " WHERE f.fk_soc = s.rowid";
239 $sql .= " AND f.entity IN (".getEntity('invoice').")";
240 $sql .= " AND d.fk_facture = f.rowid";
241 $sql .= " AND d.fk_product = ".((int) $product->id);
242 if ($search_date_start) {
243 $sql .= " AND f.datef >= '".$db->idate($search_date_start)."'";
244 }
245 if ($search_date_end) {
246 $sql .= " AND f.datef <= '".$db->idate($search_date_end)."'";
247 }
248 if (!$user->hasRight('societe', 'client', 'voir')) {
249 $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
250 }
251 if ($socid) {
252 $sql .= " AND f.fk_soc = ".((int) $socid);
253 }
254 // Add where from extra fields
255 $extrafieldsobjectkey = 'facture';
256 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
257 // Add where from hooks
258 $parameters = array();
259 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
260 $sql .= $hookmanager->resPrint;
261
262 // Add HAVING from hooks
263 $parameters = array();
264 $reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
265 $sql .= empty($hookmanager->resPrint) ? "" : " HAVING 1=1 ".$hookmanager->resPrint;
266
267 $sql .= $db->order($sortfield, $sortorder);
268
269 // Calcul total qty and amount for global if full scan list
270 $total_ht = 0;
271 $total_qty = 0;
272
273 // Count total nb of records
274 $totalofrecords = '';
275 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
276 $result = $db->query($sql);
277 $totalofrecords = $db->num_rows($result);
278 }
279
280 $sql .= $db->plimit($limit + 1, $offset);
281
282 $result = $db->query($sql);
283 if ($result) {
284 $num = $db->num_rows($result);
285
286 $option .= '&id='.$product->id;
287
288 if ($limit > 0 && $limit != $conf->liste_limit) {
289 $option .= '&limit='.((int) $limit);
290 }
291
292 // Add $param from extra fields
293 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
294 // Add $param from hooks
295 $parameters = array('param' => &$param);
296 $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
297 $option .= $hookmanager->resPrint;
298
299 print '<form method="post" action="'.$_SERVER ['PHP_SELF'].'?id='.$product->id.'" name="search_form">'."\n";
300 print '<input type="hidden" name="token" value="'.newToken().'">';
301 if (!empty($sortfield)) {
302 print '<input type="hidden" name="sortfield" value="'.$sortfield.'"/>';
303 }
304 if (!empty($sortorder)) {
305 print '<input type="hidden" name="sortorder" value="'.$sortorder.'"/>';
306 }
307
308 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
309 print_barre_liste($langs->trans("CustomersInvoices"), $page, $_SERVER["PHP_SELF"], $option, $sortfield, $sortorder, '', $num, $totalofrecords, '', 0, '', '', $limit, 0, 0, 1);
310
311 if (!empty($page)) {
312 $option .= '&page='.urlencode((string) ($page));
313 }
314
315 print '<div class="liste_titre liste_titre_bydiv centpercent">';
316 print '<div class="divsearchfield">';
317 print $langs->trans('Period').' ('.$langs->trans("DateInvoice").') - ';
318 print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
319 print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
320 $parameters = array();
321 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
322 print $hookmanager->resPrint;
323
324 print '<div style="vertical-align: middle; display: inline-block">';
325 print '<input type="image" class="liste_titre" name="button_search" src="'.img_picto($langs->trans("Search"), 'search.png', '', 0, 1).'" value="'.dol_escape_htmltag($langs->trans("Search")).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">';
326 print '<input type="image" class="liste_titre" name="button_removefilter" src="'.img_picto($langs->trans("Search"), 'searchclear.png', '', 0, 1).'" value="'.dol_escape_htmltag($langs->trans("RemoveFilter")).'" title="'.dol_escape_htmltag($langs->trans("RemoveFilter")).'">';
327 print '</div>';
328 print '</div>';
329 print '</div>';
330
331 $i = 0;
332 print '<div class="div-table-responsive">';
333 print '<table class="tagtable liste listwithfilterbefore" width="100%">';
334 print '<tr class="liste_titre">';
335 print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "s.rowid", "", $option, '', $sortfield, $sortorder);
336 print_liste_field_titre("Company", $_SERVER["PHP_SELF"], "s.nom", "", $option, '', $sortfield, $sortorder);
337 print_liste_field_titre("CustomerCode", $_SERVER["PHP_SELF"], "s.code_client", "", $option, '', $sortfield, $sortorder);
338 print_liste_field_titre("DateInvoice", $_SERVER["PHP_SELF"], "f.datef", "", $option, 'align="center"', $sortfield, $sortorder);
339 print_liste_field_titre("Qty", $_SERVER["PHP_SELF"], "d.qty", "", $option, 'align="center"', $sortfield, $sortorder);
340 print_liste_field_titre("AmountHT", $_SERVER["PHP_SELF"], "d.total_ht", "", $option, 'align="right"', $sortfield, $sortorder);
341 print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "f.paye,f.fk_statut", "", $option, 'align="right"', $sortfield, $sortorder);
342 // Hook fields
343 $parameters = array('param' => $option, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
344 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
345 print $hookmanager->resPrint;
346 print "</tr>\n";
347
348 if ($num > 0) {
349 while ($i < min($num, $limit)) {
350 $objp = $db->fetch_object($result);
351
352 if ($objp->type == Facture::TYPE_CREDIT_NOTE) {
353 $objp->qty = -($objp->qty);
354 }
355
356 $total_ht += $objp->total_ht;
357 $total_qty += $objp->qty;
358
359 $invoicestatic->id = $objp->facid;
360 $invoicestatic->ref = $objp->ref;
361 $societestatic->fetch($objp->socid);
362 $paiement = $invoicestatic->getSommePaiement();
363
364 print '<tr class="oddeven">';
365 print '<td>';
366 print $invoicestatic->getNomUrl(1);
367 print "</td>\n";
368 print '<td>'.$societestatic->getNomUrl(1).'</td>';
369 print "<td>".$objp->code_client."</td>\n";
370 print '<td class="center">';
371 print dol_print_date($db->jdate($objp->datef), 'dayhour')."</td>";
372 print '<td class="center">'.$objp->qty."</td>\n";
373 print '<td class="right">'.price($objp->total_ht)."</td>\n";
374 print '<td class="right">'.$invoicestatic->LibStatut($objp->paye, $objp->statut, 5, $paiement, $objp->type).'</td>';
375 // Fields from hook
376 $parameters = array();
377 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
378 print $hookmanager->resPrint;
379 print "</tr>\n";
380 $i++;
381 }
382 }
383 print '<tr class="liste_total">';
384 if ($num < $limit && empty($offset)) {
385 print '<td>'.$langs->trans("Total").'</td>';
386 } else {
387 print '<td>'.$form->textwithpicto($langs->trans("Total"), $langs->trans("Totalforthispage")).'</td>';
388 }
389 print '<td colspan="3"></td>';
390 print '<td class="center">'.$total_qty.'</td>';
391 print '<td class="right">'.price($total_ht).'</td>';
392 print '<td></td>';
393 print "</table>";
394 print '</div>';
395 print '</form>';
396 } else {
397 dol_print_error($db);
398 }
399 $db->free($result);
400 }
401 }
402} else {
404}
405
406// End of page
407llxFooter();
408$db->close();
$id
Definition account.php:48
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:71
Class to manage standard extra fields.
Class to manage invoices.
const TYPE_CREDIT_NOTE
Credit note invoice.
Class to manage generation of HTML components Only common components must be here.
Class permettant la generation de composants html autre Only common components are here.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class to manage third parties objects (customers, suppliers, prospects...)
llxFooter()
Footer empty.
Definition document.php:107
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $selectlimitsuffix=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
product_prepare_head($object)
Prepare array with list of tabs.
show_stats_for_company($product, $socid)
Show stats for a product.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.