dolibarr 21.0.3
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 $object->next_prev_filter = "(te.fk_product_type:=:".((int) $object->type).")";
182
183 $shownav = 1;
184 if ($user->socid && !in_array('product', explode(',', getDolGlobalString('MAIN_MODULES_FOR_EXTERNAL')))) {
185 $shownav = 0;
186 }
187
188 dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref');
189
190 print '<div class="fichecenter">';
191
192 print '<div class="underbanner clearboth"></div>';
193 print '<table class="border tableforfield centpercent">';
194
195 $nboflines = show_stats_for_company($product, $socid);
196
197 print "</table>";
198
199 print '</div>';
200 print '<div class="clearboth"></div>';
201
202 print dol_get_fiche_end();
203
204 if ($showmessage && $nboflines > 1) {
205 print '<span class="opacitymedium">'.$langs->trans("ClinkOnALinkOfColumn", $langs->transnoentitiesnoconv("Referers")).'</span>';
206 } elseif ($user->hasRight('facture', 'lire')) {
207 $sql = "SELECT DISTINCT s.nom as name, s.rowid as socid, s.code_client,";
208 $sql .= " f.ref, f.datef, f.paye, f.type, f.fk_statut as statut, f.rowid as facid,";
209 $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
210 if (!$user->hasRight('societe', 'client', 'voir')) {
211 $sql .= ", sc.fk_soc, sc.fk_user ";
212 }
213 // Add fields from extrafields
214 if (!empty($extrafields->attributes['facture']['label'])) {
215 foreach ($extrafields->attributes['facture']['label'] as $key => $val) {
216 $sql .= ($extrafields->attributes['facture']['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : '');
217 }
218 }
219 // Add fields from hooks
220 $parameters = array();
221 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
222 $sql .= $hookmanager->resPrint;
223 $sql = preg_replace('/,\s*$/', '', $sql);
224
225 $sql .= " FROM ".MAIN_DB_PREFIX."societe as s";
226 $sql .= ", ".MAIN_DB_PREFIX."facture as f";
227 if (isset($extrafields->attributes['facture']['label']) && is_array($extrafields->attributes['facture']['label']) && count($extrafields->attributes['facture']['label'])) {
228 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.'facture'."_extrafields as ef on (f.rowid = ef.fk_object)";
229 }
230 $sql .= ", ".MAIN_DB_PREFIX."facturedet as d";
231 if (!$user->hasRight('societe', 'client', 'voir')) {
232 $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc";
233 }
234 // Add table from hooks
235 $parameters = array();
236 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object); // Note that $action and $object may have been modified by hook
237 $sql .= $hookmanager->resPrint;
238
239 $sql .= " WHERE f.fk_soc = s.rowid";
240 $sql .= " AND f.entity IN (".getEntity('invoice').")";
241 $sql .= " AND d.fk_facture = f.rowid";
242 $sql .= " AND d.fk_product = ".((int) $product->id);
243 if ($search_date_start) {
244 $sql .= " AND f.datef >= '".$db->idate($search_date_start)."'";
245 }
246 if ($search_date_end) {
247 $sql .= " AND f.datef <= '".$db->idate($search_date_end)."'";
248 }
249 if (!$user->hasRight('societe', 'client', 'voir')) {
250 $sql .= " AND s.rowid = sc.fk_soc AND sc.fk_user = ".((int) $user->id);
251 }
252 if ($socid) {
253 $sql .= " AND f.fk_soc = ".((int) $socid);
254 }
255 // Add where from extra fields
256 $extrafieldsobjectkey = 'facture';
257 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
258 // Add where from hooks
259 $parameters = array();
260 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
261 $sql .= $hookmanager->resPrint;
262
263 // Add HAVING from hooks
264 $parameters = array();
265 $reshook = $hookmanager->executeHooks('printFieldListHaving', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
266 $sql .= empty($hookmanager->resPrint) ? "" : " HAVING 1=1 ".$hookmanager->resPrint;
267
268 $sql .= $db->order($sortfield, $sortorder);
269
270 // Calcul total qty and amount for global if full scan list
271 $total_ht = 0;
272 $total_qty = 0;
273
274 // Count total nb of records
275 $totalofrecords = '';
276 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
277 $result = $db->query($sql);
278 $totalofrecords = $db->num_rows($result);
279 }
280
281 $sql .= $db->plimit($limit + 1, $offset);
282
283 $result = $db->query($sql);
284 if ($result) {
285 $num = $db->num_rows($result);
286
287 $option .= '&id='.$product->id;
288
289 if ($limit > 0 && $limit != $conf->liste_limit) {
290 $option .= '&limit='.((int) $limit);
291 }
292
293 // Add $param from extra fields
294 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
295 // Add $param from hooks
296 $parameters = array('param' => &$param);
297 $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
298 $option .= $hookmanager->resPrint;
299
300 print '<form method="post" action="'.$_SERVER ['PHP_SELF'].'?id='.$product->id.'" name="search_form">'."\n";
301 print '<input type="hidden" name="token" value="'.newToken().'">';
302 if (!empty($sortfield)) {
303 print '<input type="hidden" name="sortfield" value="'.$sortfield.'"/>';
304 }
305 if (!empty($sortorder)) {
306 print '<input type="hidden" name="sortorder" value="'.$sortorder.'"/>';
307 }
308
309 // @phan-suppress-next-line PhanPluginSuspiciousParamOrder
310 print_barre_liste($langs->trans("CustomersInvoices"), $page, $_SERVER["PHP_SELF"], $option, $sortfield, $sortorder, '', $num, $totalofrecords, '', 0, '', '', $limit, 0, 0, 1);
311
312 if (!empty($page)) {
313 $option .= '&page='.urlencode((string) ($page));
314 }
315
316 print '<div class="liste_titre liste_titre_bydiv centpercent">';
317 print '<div class="divsearchfield">';
318 print $langs->trans('Period').' ('.$langs->trans("DateInvoice").') - ';
319 print $form->selectDate($search_date_start ? $search_date_start : -1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'));
320 print $form->selectDate($search_date_end ? $search_date_end : -1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'));
321 $parameters = array();
322 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
323 print $hookmanager->resPrint;
324
325 print '<div style="vertical-align: middle; display: inline-block">';
326 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")).'">';
327 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")).'">';
328 print '</div>';
329 print '</div>';
330 print '</div>';
331
332 $i = 0;
333 print '<div class="div-table-responsive">';
334 print '<table class="tagtable liste listwithfilterbefore" width="100%">';
335 print '<tr class="liste_titre">';
336 print_liste_field_titre("Ref", $_SERVER["PHP_SELF"], "s.rowid", "", $option, '', $sortfield, $sortorder);
337 print_liste_field_titre("Company", $_SERVER["PHP_SELF"], "s.nom", "", $option, '', $sortfield, $sortorder);
338 print_liste_field_titre("CustomerCode", $_SERVER["PHP_SELF"], "s.code_client", "", $option, '', $sortfield, $sortorder);
339 print_liste_field_titre("DateInvoice", $_SERVER["PHP_SELF"], "f.datef", "", $option, 'align="center"', $sortfield, $sortorder);
340 print_liste_field_titre("Qty", $_SERVER["PHP_SELF"], "d.qty", "", $option, 'align="center"', $sortfield, $sortorder);
341 print_liste_field_titre("AmountHT", $_SERVER["PHP_SELF"], "d.total_ht", "", $option, 'align="right"', $sortfield, $sortorder);
342 print_liste_field_titre("Status", $_SERVER["PHP_SELF"], "f.paye,f.fk_statut", "", $option, 'align="right"', $sortfield, $sortorder);
343 // Hook fields
344 $parameters = array('param' => $option, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
345 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
346 print $hookmanager->resPrint;
347 print "</tr>\n";
348
349 if ($num > 0) {
350 while ($i < min($num, $limit)) {
351 $objp = $db->fetch_object($result);
352
353 if ($objp->type == Facture::TYPE_CREDIT_NOTE) {
354 $objp->qty = -($objp->qty);
355 }
356
357 $total_ht += $objp->total_ht;
358 $total_qty += $objp->qty;
359
360 $invoicestatic->id = $objp->facid;
361 $invoicestatic->ref = $objp->ref;
362 $societestatic->fetch($objp->socid);
363 $paiement = $invoicestatic->getSommePaiement();
364
365 print '<tr class="oddeven">';
366 print '<td>';
367 print $invoicestatic->getNomUrl(1);
368 print "</td>\n";
369 print '<td>'.$societestatic->getNomUrl(1).'</td>';
370 print "<td>".$objp->code_client."</td>\n";
371 print '<td class="center">';
372 print dol_print_date($db->jdate($objp->datef), 'dayhour')."</td>";
373 print '<td class="center">'.$objp->qty."</td>\n";
374 print '<td class="right">'.price($objp->total_ht)."</td>\n";
375 print '<td class="right">'.$invoicestatic->LibStatut($objp->paye, $objp->statut, 5, $paiement, $objp->type).'</td>';
376 // Fields from hook
377 $parameters = array();
378 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
379 print $hookmanager->resPrint;
380 print "</tr>\n";
381 $i++;
382 }
383 }
384 print '<tr class="liste_total">';
385 if ($num < $limit && empty($offset)) {
386 print '<td>'.$langs->trans("Total").'</td>';
387 } else {
388 print '<td>'.$form->textwithpicto($langs->trans("Total"), $langs->trans("Totalforthispage")).'</td>';
389 }
390 print '<td colspan="3"></td>';
391 print '<td class="center">'.$total_qty.'</td>';
392 print '<td class="right">'.price($total_ht).'</td>';
393 print '<td></td>';
394 print "</table>";
395 print '</div>';
396 print '</form>';
397 } else {
398 dol_print_error($db);
399 }
400 $db->free($result);
401 }
402 }
403} else {
405}
406
407// End of page
408llxFooter();
409$db->close();
$id
Definition account.php:48
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:87
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...)
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.