dolibarr 21.0.4
card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2001-2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2020 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
5 * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
6 * Copyright (C) 2005-2017 Regis Houssin <regis.houssin@inodbox.com>
7 * Copyright (C) 2008 Raphael Bertrand (Resultic) <raphael.bertrand@resultic.fr>
8 * Copyright (C) 2010-2020 Juanjo Menent <jmenent@2byte.es>
9 * Copyright (C) 2013-2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
10 * Copyright (C) 2021-2024 Frédéric France <frederic.france@free.fr>
11 * Copyright (C) 2015 Marcos García <marcosgdf@gmail.com>
12 * Copyright (C) 2020 Open-Dsi <support@open-dsi.fr>
13 * Copyright (C) 2022 Anthony Berton <anthony.berton@bb2a.fr>
14 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <https://www.gnu.org/licenses/>.
28 */
29
36// Load Dolibarr environment
37require '../main.inc.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
40require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
41require_once DOL_DOCUMENT_ROOT.'/societe/class/client.class.php';
42require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
43require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
44require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
45require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
46require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
47if (isModEnabled('invoice')) {
48 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
49 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
50}
51if (isModEnabled("propal")) {
52 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
53}
54if (isModEnabled('order')) {
55 require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
56}
57if (isModEnabled("shipping")) {
58 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
59}
60if (isModEnabled('contract')) {
61 require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
62}
63if (isModEnabled('member')) {
64 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
65}
66if (isModEnabled('intervention')) {
67 require_once DOL_DOCUMENT_ROOT.'/fichinter/class/fichinter.class.php';
68}
69if (isModEnabled('accounting')) {
70 require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
71 require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
72}
73
83// Load translation files required by the page
84$langs->loadLangs(array('companies', 'banks', 'commercial'));
85
86if (isModEnabled('contract')) {
87 $langs->load("contracts");
88}
89if (isModEnabled('order')) {
90 $langs->load("orders");
91}
92if (isModEnabled("shipping")) {
93 $langs->load("sendings");
94}
95if (isModEnabled('invoice')) {
96 $langs->load("bills");
97}
98if (isModEnabled('project')) {
99 $langs->load("projects");
100}
101if (isModEnabled('intervention')) {
102 $langs->load("interventions");
103}
104if (isModEnabled('notification')) {
105 $langs->load("mails");
106}
107
108$action = GETPOST('action', 'aZ09');
109
110$id = (GETPOSTINT('socid') ? GETPOSTINT('socid') : GETPOSTINT('id'));
111
112$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
113$sortfield = GETPOST('sortfield', 'aZ09comma');
114$sortorder = GETPOST('sortorder', 'aZ09comma');
115$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT('page');
116if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
117 // If $page is not defined, or '' or -1 or if we click on clear filters
118 $page = 0;
119}
120$offset = $limit * $page;
121$pageprev = $page - 1;
122$pagenext = $page + 1;
123if (!$sortorder) {
124 $sortorder = "ASC";
125}
126if (!$sortfield) {
127 $sortfield = "nom";
128}
129$cancel = GETPOST('cancel', 'alpha');
130
131$object = new Client($db);
132$extrafields = new ExtraFields($db);
133$formfile = new FormFile($db);
134
135// fetch optionals attributes and labels
136$extrafields->fetch_name_optionals_label($object->table_element);
137
138// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
139$hookmanager->initHooks(array('thirdpartycomm', 'globalcard'));
140
141$now = dol_now();
142
143if ($id > 0 && empty($object->id)) {
144 // Load data of third party
145 $res = $object->fetch($id);
146 if ($object->id < 0) {
147 dol_print_error($db, $object->error, $object->errors);
148 }
149}
150if ($object->id > 0) {
151 if (!($object->client > 0) || !$user->hasRight('societe', 'lire')) {
153 }
154}
155
156// Security check
157if ($user->socid > 0) {
158 $id = $user->socid;
159}
160$result = restrictedArea($user, 'societe', $object->id, '&societe', '', 'fk_soc', 'rowid', 0);
161
162
163/*
164 * Actions
165 */
166$error = 0;
167
168$parameters = array('id' => $id, 'socid' => $id);
169$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some
170if ($reshook < 0) {
171 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
172}
173
174if (empty($reshook)) {
175 if ($cancel) {
176 $action = "";
177 }
178
179 // set accountancy code
180 if ($action == 'setcustomeraccountancycodegeneral') {
181 $result = $object->fetch($id);
182 $object->accountancy_code_customer_general = GETPOST("customeraccountancycodegeneral");
183 $result = $object->update($object->id, $user, 1, 1, 0);
184 if ($result < 0) {
185 setEventMessages($object->error, $object->errors, 'errors');
186 }
187 }
188
189 // Set accountancy code
190 if ($action == 'setcustomeraccountancycode' && $user->hasRight('societe', 'creer')) {
191 $result = $object->fetch($id);
192 $object->code_compta_client = GETPOST("customeraccountancycode");
193 $object->code_compta = $object->code_compta_client; // For Backward compatibility
194 $result = $object->update($object->id, $user, 1, 1, 0);
195 if ($result < 0) {
196 setEventMessages($object->error, $object->errors, 'errors');
197 $action = 'editcustomeraccountancycode';
198 }
199 }
200
201 // Payment terms of the settlement
202 if ($action == 'setconditions' && $user->hasRight('societe', 'creer')) {
203 $object->fetch($id);
204 $result = $object->setPaymentTerms(GETPOSTINT('cond_reglement_id'), GETPOSTINT('cond_reglement_id_deposit_percent'));
205 if ($result < 0) {
206 setEventMessages($object->error, $object->errors, 'errors');
207 }
208 }
209
210 // Payment mode
211 if ($action == 'setmode' && $user->hasRight('societe', 'creer')) {
212 $object->fetch($id);
213 $result = $object->setPaymentMethods(GETPOSTINT('mode_reglement_id'));
214 if ($result < 0) {
215 setEventMessages($object->error, $object->errors, 'errors');
216 }
217 }
218
219 // Transport mode
220 if ($action == 'settransportmode' && $user->hasRight('societe', 'creer')) {
221 $object->fetch($id);
222 $result = $object->setTransportMode(GETPOST('transport_mode_id', 'alpha'));
223 if ($result < 0) {
224 setEventMessages($object->error, $object->errors, 'errors');
225 }
226 }
227
228 // Bank account
229 if ($action == 'setbankaccount' && $user->hasRight('societe', 'creer')) {
230 $object->fetch($id);
231 $result = $object->setBankAccount(GETPOSTINT('fk_account'));
232 if ($result < 0) {
233 setEventMessages($object->error, $object->errors, 'errors');
234 }
235 }
236
237 // customer preferred shipping method
238 if ($action == 'setshippingmethod' && $user->hasRight('societe', 'creer')) {
239 $object->fetch($id);
240 $result = $object->setShippingMethod(GETPOSTINT('shipping_method_id'));
241 if ($result < 0) {
242 setEventMessages($object->error, $object->errors, 'errors');
243 }
244 }
245
246 // assujetissement a la TVA
247 if ($action == 'setassujtva' && $user->hasRight('societe', 'creer')) {
248 $object->fetch($id);
249 $object->tva_assuj = GETPOSTINT('assujtva_value');
250 $result = $object->update($object->id, $user);
251 if ($result < 0) {
252 setEventMessages($object->error, $object->errors, 'errors');
253 }
254 }
255
256 // set prospect level
257 if ($action == 'setprospectlevel' && $user->hasRight('societe', 'creer')) {
258 $object->fetch($id);
259 $object->fk_prospectlevel = GETPOST('prospect_level_id', 'alpha');
260 $result = $object->update($object->id, $user);
261 if ($result < 0) {
262 setEventMessages($object->error, $object->errors, 'errors');
263 }
264 }
265
266 // set communication status
267 if ($action == 'setstcomm' && $user->hasRight('societe', 'creer')) {
268 $object->fetch($id);
269 $object->stcomm_id = dol_getIdFromCode($db, GETPOST('stcomm', 'alpha'), 'c_stcomm');
270 $result = $object->update($object->id, $user);
271 if ($result < 0) {
272 setEventMessages($object->error, $object->errors, 'errors');
273 } else {
274 $result = $object->fetch($object->id);
275 }
276 }
277
278 // update outstandng limit
279 if ($action == 'setoutstanding_limit' && $user->hasRight('societe', 'creer')) {
280 $object->fetch($id);
281 $object->outstanding_limit = GETPOST('outstanding_limit');
282 $result = $object->update($object->id, $user);
283 if ($result < 0) {
284 setEventMessages($object->error, $object->errors, 'errors');
285 }
286 }
287
288 // update order min amount
289 if ($action == 'setorder_min_amount' && $user->hasRight('societe', 'creer')) {
290 $object->fetch($id);
291 $object->order_min_amount = price2num(GETPOST('order_min_amount', 'alpha'));
292 $result = $object->update($object->id, $user);
293 if ($result < 0) {
294 setEventMessages($object->error, $object->errors, 'errors');
295 }
296 }
297
298 // Set sales representatives
299 if ($action == 'set_salesrepresentatives' && $user->hasRight('societe', 'creer')) {
300 $object->fetch($id);
301 $result = $object->setSalesRep(GETPOST('commercial', 'array'));
302 }
303
304 if ($action == 'update_extras' && $user->hasRight('societe', 'creer')) {
305 $object->fetch($id);
306
307 $object->oldcopy = dol_clone($object, 2);
308
309 // Fill array 'array_options' with data from update form
310 $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml'));
311 if ($ret < 0) {
312 $error++;
313 }
314 if (!$error) {
315 $result = $object->insertExtraFields('COMPANY_MODIFY');
316 if ($result < 0) {
317 setEventMessages($object->error, $object->errors, 'errors');
318 $error++;
319 }
320 }
321 if ($error) {
322 $action = 'edit_extras';
323 }
324 }
325
326 // warehouse
327 if ($action == 'setwarehouse' && $user->hasRight('societe', 'creer')) {
328 $result = $object->setWarehouse(GETPOSTINT('fk_warehouse'));
329 }
330}
331
332
333/*
334 * View
335 */
336
337$contactstatic = new Contact($db);
338$userstatic = new User($db);
339$form = new Form($db);
340$formcompany = new FormCompany($db);
341$project = new Project($db);
342
343$title = $langs->trans("ThirdParty")." - ".$langs->trans('Customer');
344if (getDolGlobalString('MAIN_HTML_TITLE') && preg_match('/thirdpartynameonly/', getDolGlobalString('MAIN_HTML_TITLE')) && $object->name) {
345 $title = $object->name." - ".$langs->trans('Customer');
346}
347
348$help_url = 'EN:Module_Third_Parties|FR:Module_Tiers|ES:Empresas|DE:Modul_Geschäftspartner';
349
350llxHeader('', $title, $help_url);
351
352if ($object->id > 0) {
354
355 print dol_get_fiche_head($head, 'customer', $langs->trans("ThirdParty"), -1, 'company');
356
357 $linkback = '<a href="'.DOL_URL_ROOT.'/societe/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
358
359 dol_banner_tab($object, 'socid', $linkback, ($user->socid ? 0 : 1), 'rowid', 'nom');
360
361 print '<div class="fichecenter"><div class="fichehalfleft">';
362
363 print '<div class="underbanner clearboth"></div>';
364 print '<table class="border centpercent tableforfield">';
365
366 // Nature Prospect/Customer/Supplier
367 print '<tr><td class="titlefield">'.$langs->trans('NatureOfThirdParty').'</td><td>';
368 print $object->getTypeUrl(1);
369 print '</td></tr>';
370
371 // Prefix
372 if (getDolGlobalString('SOCIETE_USEPREFIX')) { // Old not used prefix field
373 print '<tr><td>'.$langs->trans("Prefix").'</td><td>';
374 print($object->prefix_comm ? $object->prefix_comm : '&nbsp;');
375 print '</td></tr>';
376 }
377
378 if ($object->client) {
379 $langs->loadLangs(array("compta", "accountancy"));
380
381 print '<tr><td>';
382 print $langs->trans('CustomerCode').'</td><td>';
384 $tmpcheck = $object->check_codeclient();
385 if ($tmpcheck != 0 && $tmpcheck != -5) {
386 print ' <span class="error">('.$langs->trans("WrongCustomerCode").')</span>';
387 }
388 print '</td></tr>';
389
390 if (isModEnabled('accounting')) {
391 $formaccounting = new FormAccounting($db);
392
393 print '<tr>';
394 print '<td>';
395 print $form->editfieldkey("CustomerAccountancyCodeGeneral", 'customeraccountancycodegeneral', length_accountg($object->accountancy_code_customer_general), $object, $user->hasRight('societe', 'creer'));
396 print '</td><td>';
397 if ($action == 'editcustomeraccountancycodegeneral' && $user->hasRight('societe', 'creer')) {
398 print $formaccounting->formAccountingAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->accountancy_code_customer_general, 'customeraccountancycodegeneral', 0, 1, '', 1);
399 } else {
400 if ($object->accountancy_code_customer_general > 0) {
401 $accountingaccount = new AccountingAccount($db);
402 $accountingaccount->fetch(0, $object->accountancy_code_customer_general, 1);
403
404 print $accountingaccount->getNomUrl(0, 1, 1, '', 1);
405 }
406 if (getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER')) {
407 if ($object->accountancy_code_customer_general > 0) {
408 print ' - ';
409 }
410 $accountingAccountByDefault = '<span class="opacitymedium">' . $langs->trans("AccountingAccountByDefaultShort") . ": " . length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER')) . '</span>';
411 print $accountingAccountByDefault;
412 }
413 }
414 print '</td>';
415 print '</tr>';
416 }
417
418 print '<tr>';
419 print '<td>';
420 print $form->editfieldkey("CustomerAccountancyCode", 'customeraccountancycode', $object->code_compta_client, $object, $user->hasRight('societe', 'creer'));
421 print '</td><td>';
422 print $form->editfieldval("CustomerAccountancyCode", 'customeraccountancycode', $object->code_compta_client, $object, $user->hasRight('societe', 'creer'));
423 print '</td>';
424 print '</tr>';
425 }
426
427 // This fields are used to know VAT to include in an invoice when the thirdparty is making a sale, so when it is a supplier.
428 // We don't need them into customer profile.
429 // Except for spain and localtax where localtax depends on buyer and not seller
430
431 // VAT is used
432 /*
433 print '<tr>';
434 print '<td class="nowrap">';
435 print $form->textwithpicto($langs->trans('VATIsUsed'),$langs->trans('VATIsUsedWhenSelling'));
436 print '</td><td>';
437 print yn($object->tva_assuj);
438 print '</td>';
439 print '</tr>';
440 */
441
442 if ($mysoc->country_code == 'ES') {
443 // Local Taxes
444 if ($mysoc->localtax1_assuj == "1") {
445 print '<tr><td class="nowrap">'.$langs->transcountry("LocalTax1IsUsed", $mysoc->country_code).'</td><td>';
446 print yn($object->localtax1_assuj);
447 print '</td></tr>';
448 }
449 if ($mysoc->localtax1_assuj == "1") {
450 print '<tr><td class="nowrap">'.$langs->transcountry("LocalTax2IsUsed", $mysoc->country_code).'</td><td>';
451 print yn($object->localtax2_assuj);
452 print '</td></tr>';
453 }
454 }
455
456 // TVA Intra
457 print '<tr><td class="nowrap">'.$langs->trans('VATIntra').'</td><td>';
459 print '</td></tr>';
460
461 // default terms of the settlement
462 $langs->load('bills');
463 print '<tr><td>';
464 print '<table width="100%" class="nobordernopadding"><tr><td>';
465 print $langs->trans('PaymentConditions');
466 print '<td>';
467 if (($action != 'editconditions') && $user->hasRight('societe', 'creer')) {
468 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editconditions&token='.newToken().'&socid='.$object->id.'">'.img_edit($langs->trans('SetConditions'), 1).'</a></td>';
469 }
470 print '</tr></table>';
471 print '</td><td>';
472 if ($action == 'editconditions') {
473 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id', 1, '', 1, $object->deposit_percent);
474 } else {
475 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->cond_reglement_id, 'none', 0, '', 1, $object->deposit_percent);
476 }
477 print "</td>";
478 print '</tr>';
479
480 // Default payment mode
481 print '<tr><td class="nowrap">';
482 print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
483 print $langs->trans('PaymentMode');
484 print '<td>';
485 if (($action != 'editmode') && $user->hasRight('societe', 'creer')) {
486 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editmode&token='.newToken().'&socid='.$object->id.'">'.img_edit($langs->trans('SetMode'), 1).'</a></td>';
487 }
488 print '</tr></table>';
489 print '</td><td>';
490 if ($action == 'editmode') {
491 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
492 } else {
493 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->mode_reglement_id, 'none');
494 }
495 print "</td>";
496 print '</tr>';
497
498 if (isModEnabled("bank")) {
499 // Default bank account for payments
500 print '<tr><td class="nowrap">';
501 print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
502 print $langs->trans('PaymentBankAccount');
503 print '<td>';
504 if (($action != 'editbankaccount') && $user->hasRight('societe', 'creer')) {
505 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editbankaccount&token='.newToken().'&socid='.$object->id.'">'.img_edit($langs->trans('SetBankAccount'), 1).'</a></td>';
506 }
507 print '</tr></table>';
508 print '</td><td>';
509 if ($action == 'editbankaccount') {
510 $form->formSelectAccount($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->fk_account, 'fk_account', 1);
511 } else {
512 $form->formSelectAccount($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->fk_account, 'none');
513 }
514 print "</td>";
515 print '</tr>';
516 }
517
518 $isCustomer = ($object->client == 1 || $object->client == 3);
519
520 // Relative discounts (Discounts-Drawbacks-Rebates)
521 if ($isCustomer) {
522 print '<tr><td class="nowrap">';
523 print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
524 print $langs->trans("CustomerRelativeDiscountShort");
525 print '<td><td class="right">';
526 if ($user->hasRight('societe', 'creer') && !$user->socid > 0) {
527 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/comm/remise.php?id='.$object->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?socid='.$object->id).'&action=create&token='.newToken().'">'.img_edit($langs->trans("Modify")).'</a>';
528 }
529 print '</td></tr></table>';
530 print '</td><td>'.($object->remise_percent ? '<a href="'.DOL_URL_ROOT.'/comm/remise.php?id='.$object->id.'">'.$object->remise_percent.'%</a>' : '').'</td>';
531 print '</tr>';
532
533 // Absolute discounts (Discounts-Drawbacks-Rebates)
534 print '<tr><td class="nowrap">';
535 print '<table width="100%" class="nobordernopadding">';
536 print '<tr><td class="nowrap">';
537 print $langs->trans("CustomerAbsoluteDiscountShort");
538 print '<td><td class="right">';
539 if ($user->hasRight('societe', 'creer') && !$user->socid > 0) {
540 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/comm/remx.php?id='.$object->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?socid='.$object->id).'&action=create_remise&token='.newToken().'">'.img_edit($langs->trans("Modify")).'</a>';
541 }
542 print '</td></tr></table>';
543 print '</td>';
544 print '<td>';
545 $amount_discount = $object->getAvailableDiscounts();
546 if ($amount_discount < 0) {
547 dol_print_error($db, $object->error);
548 }
549 if ($amount_discount > 0) {
550 print '<a href="'.DOL_URL_ROOT.'/comm/remx.php?id='.$object->id.'&backtopage='.urlencode($_SERVER["PHP_SELF"].'?socid='.$object->id).'&action=create&token='.newToken().'">'.price($amount_discount, 1, $langs, 1, -1, -1, $conf->currency).'</a>';
551 }
552 //else print $langs->trans("DiscountNone");
553 print '</td>';
554 print '</tr>';
555 }
556
557 $limit_field_type = '';
558 // Max outstanding bill
559 if ($object->client) {
560 print '<tr class="nowrap">';
561 print '<td>';
562 print $form->editfieldkey("OutstandingBill", 'outstanding_limit', $object->outstanding_limit, $object, $user->hasRight('societe', 'creer'));
563 print '</td><td>';
564 $limit_field_type = (getDolGlobalString('MAIN_USE_JQUERY_JEDITABLE')) ? 'numeric' : 'amount';
565 print $form->editfieldval("OutstandingBill", 'outstanding_limit', $object->outstanding_limit, $object, $user->hasRight('societe', 'creer'), $limit_field_type, ($object->outstanding_limit != '' ? price($object->outstanding_limit) : ''));
566 print '</td>';
567 print '</tr>';
568 }
569
570 if ($object->client) {
571 if (isModEnabled('order') && getDolGlobalString('ORDER_MANAGE_MIN_AMOUNT')) {
572 print '<!-- Minimum amount for orders -->'."\n";
573 print '<tr class="nowrap">';
574 print '<td>';
575 print $form->editfieldkey("OrderMinAmount", 'order_min_amount', $object->order_min_amount, $object, $user->hasRight('societe', 'creer'));
576 print '</td><td>';
577 print $form->editfieldval("OrderMinAmount", 'order_min_amount', $object->order_min_amount, $object, $user->hasRight('societe', 'creer'), $limit_field_type, ($object->order_min_amount != '' ? price($object->order_min_amount) : ''));
578 print '</td>';
579 print '</tr>';
580 }
581 }
582
583
584 // Multiprice level
585 if (getDolGlobalString('PRODUIT_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES')) {
586 print '<tr><td class="nowrap">';
587 print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
588 print $langs->trans("PriceLevel");
589 print '<td><td class="right">';
590 if ($user->hasRight('societe', 'creer')) {
591 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/comm/multiprix.php?id='.$object->id.'">'.img_edit($langs->trans("Modify")).'</a>';
592 }
593 print '</td></tr></table>';
594 print '</td><td>';
595 print $object->price_level;
596 $keyforlabel = 'PRODUIT_MULTIPRICES_LABEL'.$object->price_level;
597 if (getDolGlobalString($keyforlabel)) {
598 print ' - '.$langs->trans(getDolGlobalString($keyforlabel));
599 }
600 print "</td>";
601 print '</tr>';
602 }
603
604 // Warehouse
605 if (isModEnabled('stock') && getDolGlobalString('SOCIETE_ASK_FOR_WAREHOUSE')) {
606 $langs->load('stocks');
607 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
608 $formproduct = new FormProduct($db);
609 print '<tr class="nowrap">';
610 print '<td>';
611 print $form->editfieldkey("Warehouse", 'warehouse', '', $object, $user->hasRight('societe', 'creer'));
612 print '</td><td>';
613 if ($action == 'editwarehouse') {
614 $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_warehouse, 'fk_warehouse', 1);
615 } else {
616 if ($object->fk_warehouse > 0) {
617 print img_picto('', 'stock', 'class="paddingrightonly"');
618 }
619 $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_warehouse, 'none');
620 }
621 print '</td>';
622 print '</tr>';
623 }
624
625 // Preferred shipping Method
626 if (getDolGlobalString('SOCIETE_ASK_FOR_SHIPPING_METHOD')) {
627 print '<tr><td class="nowrap">';
628 print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
629 print $langs->trans('SendingMethod');
630 print '<td>';
631 if (($action != 'editshipping') && $user->hasRight('societe', 'creer')) {
632 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editshipping&token='.newToken().'&socid='.$object->id.'">'.img_edit($langs->trans('SetMode'), 1).'</a></td>';
633 }
634 print '</tr></table>';
635 print '</td><td>';
636 if ($action == 'editshipping') {
637 $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->shipping_method_id, 'shipping_method_id', 1);
638 } else {
639 $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->shipping_method_id, 'none');
640 }
641 print "</td>";
642 print '</tr>';
643 }
644
645 if (isModEnabled('intracommreport')) {
646 // Transport mode by default
647 print '<tr><td class="nowrap">';
648 print '<table class="centpercent nobordernopadding"><tr><td class="nowrap">';
649 print $langs->trans('IntracommReportTransportMode');
650 print '<td>';
651 if (($action != 'edittransportmode') && $user->hasRight('societe', 'creer')) {
652 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=edittransportmode&token='.newToken().'&socid='.$object->id.'">'.img_edit($langs->trans('SetMode'), 1).'</a></td>';
653 }
654 print '</tr></table>';
655 print '</td><td>';
656 if ($action == 'edittransportmode') {
657 $form->formSelectTransportMode($_SERVER['PHP_SELF'].'?socid='.$object->id, (!empty($object->transport_mode_id) ? $object->transport_mode_id : ''), 'transport_mode_id', 1);
658 } else {
659 $form->formSelectTransportMode($_SERVER['PHP_SELF'].'?socid='.$object->id, (!empty($object->transport_mode_id) ? $object->transport_mode_id : ''), 'none');
660 }
661 print "</td>";
662 print '</tr>';
663 }
664
665 // Categories
666 if (isModEnabled('category') && $user->hasRight('categorie', 'lire')) {
667 $langs->load("categories");
668 print '<tr><td>'.$langs->trans("CustomersCategoriesShort").'</td>';
669 print '<td>';
670 print $form->showCategories($object->id, Categorie::TYPE_CUSTOMER, 1);
671 print "</td></tr>";
672 }
673
674 // Other attributes
675 $parameters = array('socid' => $object->id);
676 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
677
678 // Sales representative
679 include DOL_DOCUMENT_ROOT.'/societe/tpl/linesalesrepresentative.tpl.php';
680
681 // Module Adherent
682 if (isModEnabled('member')) {
683 $langs->load("members");
684 $langs->load("users");
685
686 print '<tr><td class="titlefield">'.$langs->trans("LinkedToDolibarrMember").'</td>';
687 print '<td>';
688 $adh = new Adherent($db);
689 $result = $adh->fetch(0, '', $object->id);
690 if ($result > 0) {
691 $adh->ref = $adh->getFullName($langs);
692 print $adh->getNomUrl(-1);
693 } else {
694 print '<span class="opacitymedium">'.$langs->trans("ThirdpartyNotLinkedToMember").'</span>';
695 }
696 print '</td>';
697 print "</tr>\n";
698 }
699
700 print "</table>";
701
702 print '</div><div class="fichehalfright">';
703
704 // Prospection level and status
705 if ($object->client == 2 || $object->client == 3) {
706 print '<div class="underbanner clearboth"></div>';
707 print '<table class="border centpercent tableforfield">';
708
709 // Level of prospection
710 print '<tr><td class="titlefield nowrap">';
711 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
712 print $langs->trans('ProspectLevel');
713 print '<td>';
714 if ($action != 'editlevel' && $user->hasRight('societe', 'creer')) {
715 print '<td class="right"><a class="editfielda reposition" href="'.$_SERVER["PHP_SELF"].'?action=editlevel&token='.newToken().'&socid='.$object->id.'">'.img_edit($langs->trans('Modify'), 1).'</a></td>';
716 }
717 print '</tr></table>';
718 print '</td><td>';
719 if ($action == 'editlevel') {
720 $formcompany->form_prospect_level($_SERVER['PHP_SELF'].'?socid='.$object->id, $object->fk_prospectlevel, 'prospect_level_id', 1);
721 } else {
722 print $object->getLibProspLevel();
723 }
724 print "</td>";
725 print '</tr>';
726
727 // Status of prospection
728 $object->loadCacheOfProspStatus();
729 print '<tr><td>'.$langs->trans("StatusProsp").'</td><td>'.$object->getLibProspCommStatut(4, $object->cacheprospectstatus[$object->stcomm_id]['label']);
730 print ' &nbsp; &nbsp; ';
731 print '<div class="floatright">';
732 foreach ($object->cacheprospectstatus as $key => $val) {
733 $titlealt = 'default';
734 if (!empty($val['code']) && !in_array($val['code'], array('ST_NO', 'ST_NEVER', 'ST_TODO', 'ST_PEND', 'ST_DONE'))) {
735 $titlealt = $val['label'];
736 }
737 if ($object->stcomm_id != $val['id']) {
738 print '<a class="pictosubstatus reposition" href="'.$_SERVER["PHP_SELF"].'?socid='.$object->id.'&stcomm='.$val['code'].'&action=setstcomm&token='.newToken().'">'.img_action($titlealt, $val['code'], $val['picto']).'</a>';
739 }
740 }
741 print '</div></td></tr>';
742 print "</table>";
743
744 print '<br>';
745 } else {
746 print '<div class="underbanner underbanner-before-box clearboth"></div><br>';
747 }
748
749 $boxstat = '';
750
751 // Max nb of elements in lists
752 $MAXLIST = getDolGlobalString('MAIN_SIZE_SHORTLIST_LIMIT');
753
754 // Link summary/status board
755 $boxstat .= '<div class="box divboxtable box-halfright">';
756 $boxstat .= '<table summary="'.dol_escape_htmltag($langs->trans("DolibarrStateBoard")).'" class="border boxtable boxtablenobottom boxtablenotop boxtablenomarginbottom centpercent">';
757 $boxstat .= '<tr class="impair nohover"><td colspan="2" class="tdboxstats nohover">';
758
759 if (isModEnabled("propal") && $user->hasRight('propal', 'lire')) {
760 // Box proposals
761 $tmp = $object->getOutstandingProposals();
762 $outstandingOpened = $tmp['opened'];
763 $outstandingTotal = $tmp['total_ht'];
764 $outstandingTotalIncTax = $tmp['total_ttc'];
765 $text = $langs->trans("OverAllProposals");
766 $link = DOL_URL_ROOT.'/comm/propal/list.php?socid='.$object->id;
767 $icon = 'bill';
768 if ($link) {
769 $boxstat .= '<a href="'.$link.'" class="boxstatsindicator thumbstat nobold nounderline">';
770 }
771 $boxstat .= '<div class="boxstats" title="'.dol_escape_htmltag($text).'">';
772 $boxstat .= '<span class="boxstatstext">'.img_object("", $icon).' <span>'.$text.'</span></span><br>';
773 $boxstat .= '<span class="boxstatsindicator">'.price($outstandingTotal, 1, $langs, 1, -1, -1, $conf->currency).'</span>';
774 $boxstat .= '</div>';
775 if ($link) {
776 $boxstat .= '</a>';
777 }
778 }
779
780 if (isModEnabled('order') && $user->hasRight('commande', 'lire')) {
781 // Box orders
782 $tmp = $object->getOutstandingOrders();
783 $outstandingOpened = $tmp['opened'];
784 $outstandingTotal = $tmp['total_ht'];
785 $outstandingTotalIncTax = $tmp['total_ttc'];
786 $text = $langs->trans("OverAllOrders");
787 $link = DOL_URL_ROOT.'/commande/list.php?socid='.$object->id;
788 $icon = 'bill';
789 if ($link) {
790 $boxstat .= '<a href="'.$link.'" class="boxstatsindicator thumbstat nobold nounderline">';
791 }
792 $boxstat .= '<div class="boxstats" title="'.dol_escape_htmltag($text).'">';
793 $boxstat .= '<span class="boxstatstext">'.img_object("", $icon).' <span>'.$text.'</span></span><br>';
794 $boxstat .= '<span class="boxstatsindicator">'.price($outstandingTotal, 1, $langs, 1, -1, -1, $conf->currency).'</span>';
795 $boxstat .= '</div>';
796 if ($link) {
797 $boxstat .= '</a>';
798 }
799 }
800
801 if (isModEnabled('invoice') && $user->hasRight('facture', 'lire')) {
802 // Box invoices
803 $tmp = $object->getOutstandingBills('customer', 0);
804 $outstandingOpened = $tmp['opened'];
805 $outstandingTotal = $tmp['total_ht'];
806 $outstandingTotalIncTax = $tmp['total_ttc'];
807
808 $text = $langs->trans("OverAllInvoices");
809 $link = DOL_URL_ROOT.'/compta/facture/list.php?socid='.$object->id;
810 $icon = 'bill';
811 if ($link) {
812 $boxstat .= '<a href="'.$link.'" class="boxstatsindicator thumbstat nobold nounderline">';
813 }
814 $boxstat .= '<div class="boxstats" title="'.dol_escape_htmltag($text).'">';
815 $boxstat .= '<span class="boxstatstext">'.img_object("", $icon).' <span>'.$text.'</span></span><br>';
816 $boxstat .= '<span class="boxstatsindicator">'.price($outstandingTotal, 1, $langs, 1, -1, -1, $conf->currency).'</span>';
817 $boxstat .= '</div>';
818 if ($link) {
819 $boxstat .= '</a>';
820 }
821
822 // Box outstanding bill
823 $warn = '';
824 if ($object->outstanding_limit != '' && $object->outstanding_limit < $outstandingOpened) {
825 $warn = ' '.img_warning($langs->trans("OutstandingBillReached"));
826 }
827 $text = $langs->trans("CurrentOutstandingBill");
828 $link = DOL_URL_ROOT.'/compta/recap-compta.php?socid='.$object->id;
829 $icon = 'bill';
830 if ($link) {
831 $boxstat .= '<a href="'.$link.'" class="boxstatsindicator thumbstat nobold nounderline">';
832 }
833 $boxstat .= '<div class="boxstats" title="'.dol_escape_htmltag($text).'">';
834 $boxstat .= '<span class="boxstatstext">'.img_object("", $icon).' <span>'.$text.'</span></span><br>';
835 $boxstat .= '<span class="boxstatsindicator'.($outstandingOpened > 0 ? ' amountremaintopay' : '').'">'.price($outstandingOpened, 1, $langs, 1, -1, -1, $conf->currency).$warn.'</span>';
836 $boxstat .= '</div>';
837 if ($link) {
838 $boxstat .= '</a>';
839 }
840
841 $tmp = $object->getOutstandingBills('customer', 1);
842 $outstandingOpenedLate = $tmp['opened'];
843 if ($outstandingOpened != $outstandingOpenedLate && !empty($outstandingOpenedLate)) {
844 $warn = '';
845 if ($object->outstanding_limit != '' && $object->outstanding_limit < $outstandingOpenedLate) {
846 $warn = ' '.img_warning($langs->trans("OutstandingBillReached"));
847 }
848 $text = $langs->trans("CurrentOutstandingBillLate");
849 $link = DOL_URL_ROOT.'/compta/recap-compta.php?socid='.$object->id;
850 $icon = 'bill';
851 if ($link) {
852 $boxstat .= '<a href="'.$link.'" class="boxstatsindicator thumbstat nobold nounderline">';
853 }
854 $boxstat .= '<div class="boxstats" title="'.dol_escape_htmltag($text).'">';
855 $boxstat .= '<span class="boxstatstext">'.img_object("", $icon).' <span>'.$text.'</span></span><br>';
856 $boxstat .= '<span class="boxstatsindicator'.($outstandingOpenedLate > 0 ? ' amountremaintopay' : '').'">'.price($outstandingOpenedLate, 1, $langs, 1, -1, -1, $conf->currency).$warn.'</span>';
857 $boxstat .= '</div>';
858 if ($link) {
859 $boxstat .= '</a>';
860 }
861 }
862 }
863
864 $parameters = array();
865 $reshook = $hookmanager->executeHooks('addMoreBoxStatsCustomer', $parameters, $object, $action);
866 if (empty($reshook)) {
867 $boxstat .= $hookmanager->resPrint;
868 }
869
870 $boxstat .= '</td></tr>';
871 $boxstat .= '</table>';
872 $boxstat .= '</div>';
873
874 print $boxstat;
875
876
877 /*
878 * Latest proposals
879 */
880 if (isModEnabled("propal") && $user->hasRight('propal', 'lire')) {
881 $langs->load("propal");
882
883 $sql = "SELECT s.nom, s.rowid, p.rowid as propalid, p.fk_projet, p.fk_statut, p.total_ht";
884 $sql .= ", p.total_tva";
885 $sql .= ", p.total_ttc";
886 $sql .= ", p.ref, p.ref_client, p.remise";
887 $sql .= ", p.datep as dp, p.fin_validite as date_limit, p.entity";
888 $sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."propal as p, ".MAIN_DB_PREFIX."c_propalst as c";
889 $sql .= " WHERE p.fk_soc = s.rowid AND p.fk_statut = c.id";
890 $sql .= " AND s.rowid = ".((int) $object->id);
891 $sql .= " AND p.entity IN (".getEntity('propal').")";
892 $sql .= " ORDER BY p.datep DESC";
893
894 $resql = $db->query($sql);
895 if ($resql) {
896 $propal_static = new Propal($db);
897
898 $num = $db->num_rows($resql);
899 if ($num > 0) {
900 print '<div class="div-table-responsive-no-min">';
901 print '<table class="noborder centpercent lastrecordtable">';
902
903 print '<tr class="liste_titre">';
904 print '<td colspan="5"><table width="100%" class="nobordernopadding"><tr><td>'.$langs->trans("LastPropals", ($num <= $MAXLIST ? "" : $MAXLIST)).'</td><td class="right"><a class="notasortlink" href="'.DOL_URL_ROOT.'/comm/propal/list.php?socid='.$object->id.'"><span class="hideonsmartphone">'.$langs->trans("AllPropals").'</span><span class="badge marginleftonlyshort">'.$num.'</span></a></td>';
905 print '<td width="20px" class="right"><a href="'.DOL_URL_ROOT.'/comm/propal/stats/index.php?socid='.$object->id.'">'.img_picto($langs->trans("Statistics"), 'stats').'</a></td>';
906 print '</tr></table></td>';
907 print '</tr>';
908 }
909
910 $i = 0;
911 while ($i < $num && $i < $MAXLIST) {
912 $objp = $db->fetch_object($resql);
913
914 print '<tr class="oddeven">';
915 print '<td class="nowraponall">';
916 $propal_static->id = $objp->propalid;
917 $propal_static->ref = $objp->ref;
918 $propal_static->ref_client = $objp->ref_client; // deprecated
919 $propal_static->ref_customer = $objp->ref_client;
920 $propal_static->fk_project = $objp->fk_projet;
921 $propal_static->total_ht = $objp->total_ht;
922 $propal_static->total_tva = $objp->total_tva;
923 $propal_static->total_ttc = $objp->total_ttc;
924 print $propal_static->getNomUrl(1);
925
926 // Preview
927 $filedir = $conf->propal->multidir_output[$objp->entity].'/'.dol_sanitizeFileName($objp->ref);
928 $file_list = null;
929 if (!empty($filedir)) {
930 $file_list = dol_dir_list($filedir, 'files', 0, dol_sanitizeFileName($objp->ref).'.pdf', '(\.meta|_preview.*.*\.png)$', 'date', SORT_DESC);
931 }
932 if (is_array($file_list) && !empty($file_list)) {
933 // Defined relative dir to DOL_DATA_ROOT
934 $relativedir = '';
935 if ($filedir) {
936 $relativedir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $filedir);
937 $relativedir = preg_replace('/^[\\/]/', '', $relativedir);
938 }
939 // Get list of files stored into database for same relative directory
940 if ($relativedir) {
941 completeFileArrayWithDatabaseInfo($file_list, $relativedir);
942 '@phan-var-force array<array{name:string,path:string,level1name:string,relativename:string,fullname:string,date:string,size:int,perm:int,type:string,position_name:string,cover:string,keywords:string,acl:string,rowid:int,label:string,share:string}> $file_list';
943
944 //var_dump($sortfield.' - '.$sortorder);
945 if (!empty($sortfield) && !empty($sortorder)) { // If $sortfield is for example 'position_name', we will sort on the property 'position_name' (that is concat of position+name)
946 $file_list = dol_sort_array($file_list, $sortfield, $sortorder);
947 }
948 }
949 $relativepath = dol_sanitizeFileName($objp->ref).'/'.dol_sanitizeFileName($objp->ref).'.pdf';
950 print $formfile->showPreview($file_list, $propal_static->element, $relativepath, 0, 'entity=' . $objp->entity);
951 }
952 print '</td><td class="tdoverflowmax125">';
953 if ($propal_static->fk_project > 0) {
954 $project->fetch($propal_static->fk_project);
955 print $project->getNomUrl(1);
956 }
957 // $filename = dol_sanitizeFileName($objp->ref);
958 // $filedir = $conf->propal->multidir_output[$objp->entity].'/'.dol_sanitizeFileName($objp->ref);
959 // $urlsource = '/comm/propal/card.php?id='.$objp->cid;
960 // print $formfile->getDocumentsLink($propal_static->element, $filename, $filedir);
961 if (($db->jdate($objp->date_limit) < ($now - $conf->propal->cloture->warning_delay)) && $objp->fk_statut == $propal_static::STATUS_VALIDATED) {
962 print " ".img_warning();
963 }
964 print '</td><td class="right" width="80px">'.dol_print_date($db->jdate($objp->dp), 'day')."</td>\n";
965 print '<td class="right nowraponall">'.price($objp->total_ht).'</td>';
966 print '<td class="right" style="min-width: 60px" class="nowrap">'.$propal_static->LibStatut($objp->fk_statut, 5).'</td></tr>';
967 $i++;
968 }
969 $db->free($resql);
970
971 if ($num > 0) {
972 print "</table>";
973 print '</div>';
974 }
975 } else {
976 dol_print_error($db);
977 }
978 }
979
980 $orders2invoice = null;
981 $param = "";
982 /*
983 * Latest orders
984 */
985 if (isModEnabled('order') && $user->hasRight('commande', 'lire')) {
986 $sql = "SELECT s.nom, s.rowid";
987 $sql .= ", c.rowid as cid, c.entity, c.fk_projet, c.total_ht";
988 $sql .= ", c.total_tva";
989 $sql .= ", c.total_ttc";
990 $sql .= ", c.ref, c.ref_client, c.fk_statut, c.facture";
991 $sql .= ", c.date_commande as dc";
992 $sql .= ", c.facture as billed";
993 $sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."commande as c";
994 $sql .= " WHERE c.fk_soc = s.rowid ";
995 $sql .= " AND s.rowid = ".((int) $object->id);
996 $sql .= " AND c.entity IN (".getEntity('commande').')';
997 $sql .= " ORDER BY c.date_commande DESC";
998
999 $resql = $db->query($sql);
1000 if ($resql) {
1001 $commande_static = new Commande($db);
1002
1003 $num = $db->num_rows($resql);
1004 if ($num > 0) {
1005 // Check if there are orders billable
1006 $sql2 = 'SELECT s.nom, s.rowid as socid, s.client, c.rowid, c.ref, c.total_ht, c.ref_client,';
1007 $sql2 .= ' c.date_valid, c.date_commande, c.date_livraison, c.fk_statut, c.facture as billed';
1008 $sql2 .= ' FROM '.MAIN_DB_PREFIX.'societe as s';
1009 $sql2 .= ', '.MAIN_DB_PREFIX.'commande as c';
1010 $sql2 .= ' WHERE c.fk_soc = s.rowid';
1011 $sql2 .= ' AND s.rowid = '.((int) $object->id);
1012 // Show orders with status validated, shipping started and delivered (well any order we can bill)
1013 $sql2 .= " AND ((c.fk_statut IN (1,2)) OR (c.fk_statut = 3 AND c.facture = 0))";
1014
1015 $resql2 = $db->query($sql2);
1016 $orders2invoice = $db->num_rows($resql2);
1017 $db->free($resql2);
1018
1019 print '<div class="div-table-responsive-no-min">';
1020 print '<table class="noborder centpercent lastrecordtable">';
1021
1022 print '<tr class="liste_titre">';
1023 print '<td colspan="5"><table width="100%" class="nobordernopadding"><tr><td>'.$langs->trans("LastCustomerOrders", ($num <= $MAXLIST ? "" : $MAXLIST)).'</td><td class="right"><a class="notasortlink" href="'.DOL_URL_ROOT.'/commande/list.php?socid='.$object->id.'"><span class="hideonsmartphone">'.$langs->trans("AllOrders").'</span><span class="badge marginleftonlyshort">'.$num.'</span></a></td>';
1024 print '<td width="20px" class="right"><a href="'.DOL_URL_ROOT.'/commande/stats/index.php?socid='.$object->id.'">'.img_picto($langs->trans("Statistics"), 'stats').'</a></td>';
1025 print '</tr></table></td>';
1026 print '</tr>';
1027 }
1028
1029 $i = 0;
1030 while ($i < $num && $i < $MAXLIST) {
1031 $objp = $db->fetch_object($resql);
1032
1033 $commande_static->id = $objp->cid;
1034 $commande_static->ref = $objp->ref;
1035 $commande_static->ref_client = $objp->ref_client;
1036 $commande_static->fk_project = $objp->fk_projet;
1037 $commande_static->total_ht = $objp->total_ht;
1038 $commande_static->total_tva = $objp->total_tva;
1039 $commande_static->total_ttc = $objp->total_ttc;
1040 $commande_static->billed = $objp->billed;
1041
1042 print '<tr class="oddeven">';
1043 print '<td class="nowraponall">';
1044 print $commande_static->getNomUrl(1);
1045 // Preview
1046 $filedir = $conf->commande->multidir_output[$objp->entity].'/'.dol_sanitizeFileName($objp->ref);
1047 $file_list = null;
1048 if (!empty($filedir)) {
1049 $file_list = dol_dir_list($filedir, 'files', 0, dol_sanitizeFileName($objp->ref).'.pdf', '(\.meta|_preview.*.*\.png)$', 'date', SORT_DESC);
1050 }
1051 if (is_array($file_list) && !empty($file_list)) {
1052 // Defined relative dir to DOL_DATA_ROOT
1053 $relativedir = '';
1054 if ($filedir) {
1055 $relativedir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $filedir);
1056 $relativedir = preg_replace('/^[\\/]/', '', $relativedir);
1057 }
1058 // Get list of files stored into database for same relative directory
1059 if ($relativedir) {
1060 completeFileArrayWithDatabaseInfo($file_list, $relativedir);
1061 '@phan-var-force array<array{name:string,path:string,level1name:string,relativename:string,fullname:string,date:string,size:int,perm:int,type:string,position_name:string,cover:string,keywords:string,acl:string,rowid:int,label:string,share:string}> $file_list';
1062
1063 //var_dump($sortfield.' - '.$sortorder);
1064 if (!empty($sortfield) && !empty($sortorder)) { // If $sortfield is for example 'position_name', we will sort on the property 'position_name' (that is concat of position+name)
1065 $file_list = dol_sort_array($file_list, $sortfield, $sortorder);
1066 }
1067 }
1068 $relativepath = dol_sanitizeFileName($objp->ref).'/'.dol_sanitizeFileName($objp->ref).'.pdf';
1069 print $formfile->showPreview($file_list, $commande_static->element, $relativepath, 0, 'entity=' . $objp->entity);
1070 }
1071 print '</td><td class="tdoverflowmax125">';
1072 if ($commande_static->fk_project > 0) {
1073 $project->fetch($commande_static->fk_project);
1074 print $project->getNomUrl(1);
1075 }
1076 // $filename = dol_sanitizeFileName($objp->ref);
1077 // $filedir = $conf->order->multidir_output[$objp->entity].'/'.dol_sanitizeFileName($objp->ref);
1078 // $urlsource = '/commande/card.php?id='.$objp->cid;
1079 // print $formfile->getDocumentsLink($commande_static->element, $filename, $filedir);
1080 print '</td>';
1081
1082 print '<td class="right" width="80px">'.dol_print_date($db->jdate($objp->dc), 'day')."</td>\n";
1083 print '<td class="right nowraponall">'.price($objp->total_ht).'</td>';
1084 print '<td class="right" style="min-width: 60px" class="nowrap">'.$commande_static->LibStatut($objp->fk_statut, $objp->facture, 5).'</td></tr>';
1085 $i++;
1086 }
1087 $db->free($resql);
1088
1089 if ($num > 0) {
1090 print "</table>";
1091 print '</div>';
1092 }
1093 } else {
1094 dol_print_error($db);
1095 }
1096 }
1097
1098 /*
1099 * Latest shipments
1100 */
1101 if (isModEnabled("shipping") && $user->hasRight('expedition', 'lire')) {
1102 $param = 'entity=' . ((int) $objp->entity);
1103
1104 $sql = 'SELECT e.rowid as id';
1105 $sql .= ', e.ref, e.entity, e.fk_projet';
1106 $sql .= ', e.date_creation';
1107 $sql .= ', e.fk_statut as statut';
1108 $sql .= ', s.nom';
1109 $sql .= ', s.rowid as socid';
1110 $sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."expedition as e";
1111 $sql .= " WHERE e.fk_soc = s.rowid AND s.rowid = ".((int) $object->id);
1112 $sql .= " AND e.entity IN (".getEntity('expedition').")";
1113 $sql .= ' GROUP BY e.rowid';
1114 $sql .= ', e.ref, e.entity, e.fk_projet';
1115 $sql .= ', e.date_creation';
1116 $sql .= ', e.fk_statut';
1117 $sql .= ', s.nom';
1118 $sql .= ', s.rowid';
1119 $sql .= " ORDER BY e.date_creation DESC";
1120
1121 $resql = $db->query($sql);
1122 if ($resql) {
1123 $sendingstatic = new Expedition($db);
1124
1125 $num = $db->num_rows($resql);
1126 if ($num > 0) {
1127 print '<div class="div-table-responsive-no-min">';
1128 print '<table class="noborder centpercent lastrecordtable">';
1129
1130 print '<tr class="liste_titre">';
1131 print '<td colspan="5"><table class="centpercent nobordernopadding"><tr><td>'.$langs->trans("LastSendings", ($num < $MAXLIST ? "" : $MAXLIST)).'</td><td class="right"><a class="notasortlink" href="'.DOL_URL_ROOT.'/expedition/list.php?socid='.$object->id.'"><span class="hideonsmartphone">'.$langs->trans("AllSendings").'</span><span class="badge marginleftonlyshort">'.$num.'</span></a></td>';
1132 print '<td width="20px" class="right"><a href="'.DOL_URL_ROOT.'/expedition/stats/index.php?socid='.$object->id.'">'.img_picto($langs->trans("Statistics"), 'stats').'</a></td>';
1133 print '</tr></table></td>';
1134 print '</tr>';
1135 }
1136
1137 $i = 0;
1138 while ($i < $num && $i < $MAXLIST) {
1139 $objp = $db->fetch_object($resql);
1140
1141 $sendingstatic->id = $objp->id;
1142 $sendingstatic->ref = $objp->ref;
1143 $sendingstatic->fk_project = $objp->fk_projet;
1144
1145 print '<tr class="oddeven">';
1146 print '<td class="nowraponall">';
1147 print $sendingstatic->getNomUrl(1);
1148 // Preview
1149 $filedir = $conf->expedition->multidir_output[$objp->entity].'/sending/'.dol_sanitizeFileName($objp->ref);
1150 $file_list = null;
1151 if (!empty($filedir)) {
1152 $file_list = dol_dir_list($filedir, 'files', 0, dol_sanitizeFileName($objp->ref).'.pdf', '(\.meta|_preview.*.*\.png)$', 'date', SORT_DESC);
1153 }
1154 if (is_array($file_list) && !empty($file_list)) {
1155 // Defined relative dir to DOL_DATA_ROOT
1156 $relativedir = '';
1157 if ($filedir) {
1158 $relativedir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $filedir);
1159 $relativedir = preg_replace('/^[\\/]/', '', $relativedir);
1160 }
1161 // Get list of files stored into database for same relative directory
1162 if ($relativedir) {
1163 completeFileArrayWithDatabaseInfo($file_list, $relativedir);
1164 '@phan-var-force array<array{name:string,path:string,level1name:string,relativename:string,fullname:string,date:string,size:int,perm:int,type:string,position_name:string,cover:string,keywords:string,acl:string,rowid:int,label:string,share:string}> $file_list';
1165
1166 //var_dump($sortfield.' - '.$sortorder);
1167 if (!empty($sortfield) && !empty($sortorder)) { // If $sortfield is for example 'position_name', we will sort on the property 'position_name' (that is concat of position+name)
1168 $file_list = dol_sort_array($file_list, $sortfield, $sortorder);
1169 }
1170 }
1171 $relativepath = dol_sanitizeFileName($objp->ref).'/'.dol_sanitizeFileName($objp->ref).'.pdf';
1172
1173 print $formfile->showPreview($file_list, $sendingstatic->element, $relativepath, 0, $param);
1174 }
1175 print '</td><td class="tdoverflowmax125">';
1176 if ($sendingstatic->fk_project > 0) {
1177 $project->fetch($sendingstatic->fk_project);
1178 print $project->getNomUrl(1);
1179 }
1180 // $filename = dol_sanitizeFileName($objp->ref);
1181 // $filedir = $conf->expedition->multidir_output[$objp->entity].'/'.dol_sanitizeFileName($objp->ref);
1182 // $urlsource = '/expedition/card.php?id='.$objp->cid;
1183 // print $formfile->getDocumentsLink($sendingstatic->element, $filename, $filedir);
1184 print '</td>';
1185 if ($objp->date_creation > 0) {
1186 print '<td class="right" width="80px">'.dol_print_date($db->jdate($objp->date_creation), 'day').'</td>';
1187 } else {
1188 print '<td class="right"><b>!!!</b></td>';
1189 }
1190
1191 print '<td class="nowrap right">'.$sendingstatic->LibStatut($objp->statut, 5).'</td>';
1192 print "</tr>\n";
1193 $i++;
1194 }
1195 $db->free($resql);
1196
1197 if ($num > 0) {
1198 print "</table>";
1199 print '</div>';
1200 }
1201 } else {
1202 dol_print_error($db);
1203 }
1204 }
1205
1206 /*
1207 * Latest contracts
1208 */
1209 if (isModEnabled('contract') && $user->hasRight('contrat', 'lire')) {
1210 $sql = "SELECT s.nom, s.rowid, c.rowid as id, c.ref as ref, c.fk_projet, c.statut as contract_status, c.datec as dc, c.date_contrat as dcon, c.ref_customer as refcus, c.ref_supplier as refsup, c.entity,";
1211 $sql .= " c.last_main_doc, c.model_pdf";
1212 $sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."contrat as c";
1213 $sql .= " WHERE c.fk_soc = s.rowid ";
1214 $sql .= " AND s.rowid = ".((int) $object->id);
1215 $sql .= " AND c.entity IN (".getEntity('contract').")";
1216 $sql .= " ORDER BY c.datec DESC";
1217
1218 $resql = $db->query($sql);
1219 if ($resql) {
1220 $contrat = new Contrat($db);
1221
1222 $num = $db->num_rows($resql);
1223 if ($num > 0) {
1224 print '<div class="div-table-responsive-no-min">';
1225 print '<table class="noborder centpercent lastrecordtable">';
1226
1227 print '<tr class="liste_titre">';
1228 print '<td colspan="6"><table class="centpercent nobordernopadding"><tr><td>'.$langs->trans("LastContracts", ($num <= $MAXLIST ? "" : $MAXLIST)).'</td>';
1229 print '<td class="right"><a class="notasortlink" href="'.DOL_URL_ROOT.'/contrat/list.php?socid='.$object->id.'">'.$langs->trans("AllContracts").'<span class="badge marginleftonlyshort">'.$num.'</span></a></td>';
1230 //print '<td width="20px" class="right"><a href="'.DOL_URL_ROOT.'/contract/stats/index.php?socid='.$object->id.'">'.img_picto($langs->trans("Statistics"),'stats').'</a></td>';
1231 print '</tr></table></td>';
1232 print '</tr>';
1233 }
1234
1235 $i = 0;
1236 while ($i < $num && $i < $MAXLIST) {
1237 $objp = $db->fetch_object($resql);
1238
1239 $contrat->id = $objp->id;
1240 $contrat->ref = $objp->ref ? $objp->ref : $objp->id;
1241 $contrat->ref_customer = $objp->refcus;
1242 $contrat->ref_supplier = $objp->refsup;
1243 $contrat->fk_project = $objp->fk_projet;
1244 $contrat->statut = $objp->contract_status;
1245 $contrat->status = $objp->contract_status;
1246 $contrat->last_main_doc = $objp->last_main_doc;
1247 $contrat->model_pdf = $objp->model_pdf;
1248 $contrat->fetch_lines();
1249
1250 $late = '';
1251 foreach ($contrat->lines as $line) {
1252 if ($contrat->status == Contrat::STATUS_VALIDATED && $line->statut == ContratLigne::STATUS_OPEN) {
1253 if (((!empty($line->date_end) ? $line->date_end : 0) + $conf->contrat->services->expires->warning_delay) < $now) {
1254 $late = img_warning($langs->trans("Late"));
1255 }
1256 }
1257 }
1258
1259 print '<tr class="oddeven">';
1260 print '<td class="nowraponall">';
1261 print $contrat->getNomUrl(1, 12);
1262 if (!empty($contrat->model_pdf)) {
1263 // Preview
1264 $filedir = $conf->contrat->multidir_output[$objp->entity].'/'.dol_sanitizeFileName($objp->ref);
1265 $file_list = null;
1266 if (!empty($filedir)) {
1267 $file_list = dol_dir_list($filedir, 'files', 0, dol_sanitizeFileName($objp->ref).'.pdf', '(\.meta|_preview.*.*\.png)$', 'date', SORT_DESC);
1268 }
1269 if (is_array($file_list) && !empty($file_list)) {
1270 // Defined relative dir to DOL_DATA_ROOT
1271 $relativedir = '';
1272 if ($filedir) {
1273 $relativedir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $filedir);
1274 $relativedir = preg_replace('/^[\\/]/', '', $relativedir);
1275 }
1276 // Get list of files stored into database for same relative directory
1277 if ($relativedir) {
1278 completeFileArrayWithDatabaseInfo($file_list, $relativedir);
1279 '@phan-var-force array<array{name:string,path:string,level1name:string,relativename:string,fullname:string,date:string,size:int,perm:int,type:string,position_name:string,cover:string,keywords:string,acl:string,rowid:int,label:string,share:string}> $file_list';
1280
1281 //var_dump($sortfield.' - '.$sortorder);
1282 if (!empty($sortfield) && !empty($sortorder)) { // If $sortfield is for example 'position_name', we will sort on the property 'position_name' (that is concat of position+name)
1283 $file_list = dol_sort_array($file_list, $sortfield, $sortorder);
1284 }
1285 }
1286 $relativepath = dol_sanitizeFileName($objp->ref).'/'.dol_sanitizeFileName($objp->ref).'.pdf';
1287 print $formfile->showPreview($file_list, $contrat->element, $relativepath, 0, 'entity=' . $objp->entity);
1288 }
1289 }
1290 // $filename = dol_sanitizeFileName($objp->ref);
1291 // $filedir = $conf->contrat->multidir_output[$objp->entity].'/'.dol_sanitizeFileName($objp->ref);
1292 // $urlsource = '/contrat/card.php?id='.$objp->cid;
1293 // print $formfile->getDocumentsLink($contrat->element, $filename, $filedir);
1294 print $late;
1295 print '</td><td class="tdoverflowmax125">';
1296 if ($contrat->fk_project > 0) {
1297 $project->fetch($contrat->fk_project);
1298 print $project->getNomUrl(1);
1299 }
1300 print "</td>\n";
1301 print '<td class="nowrap">';
1302 print dol_trunc(strtolower(get_class($object)) == strtolower(Client::class) ? $objp->refcus : $objp->refsup, 12);
1303 print "</td>\n";
1304 //print '<td class="right" width="80px"><span title="'.$langs->trans("DateCreation").'">'.dol_print_date($db->jdate($objp->dc), 'day')."</span></td>\n";
1305 print '<td class="right" width="80px"><span title="'.$langs->trans("DateContract").'">'.dol_print_date($db->jdate($objp->dcon), 'day')."</span></td>\n";
1306 print '<td width="20">&nbsp;</td>';
1307 print '<td class="nowraponall right">';
1308 print $contrat->getLibStatut(4);
1309 print "</td>\n";
1310 print '</tr>';
1311 $i++;
1312 }
1313 $db->free($resql);
1314
1315 if ($num > 0) {
1316 print "</table>";
1317 print '</div>';
1318 }
1319 } else {
1320 dol_print_error($db);
1321 }
1322 }
1323
1324 /*
1325 * Latest interventions
1326 */
1327 if (isModEnabled('intervention') && $user->hasRight('ficheinter', 'lire')) {
1328 $sql = "SELECT s.nom, s.rowid, f.rowid as id, f.ref, f.fk_projet, f.fk_statut, f.duree as duration, f.datei as startdate, f.entity";
1329 $sql .= " FROM ".MAIN_DB_PREFIX."societe as s, ".MAIN_DB_PREFIX."fichinter as f";
1330 $sql .= " WHERE f.fk_soc = s.rowid";
1331 $sql .= " AND s.rowid = ".((int) $object->id);
1332 $sql .= " AND f.entity IN (".getEntity('intervention').")";
1333 $sql .= " ORDER BY f.tms DESC";
1334
1335 $resql = $db->query($sql);
1336 if ($resql) {
1337 $fichinter_static = new Fichinter($db);
1338
1339 $num = $db->num_rows($resql);
1340 if ($num > 0) {
1341 print '<div class="div-table-responsive-no-min">';
1342 print '<table class="noborder centpercent lastrecordtable">';
1343
1344 print '<tr class="liste_titre">';
1345 print '<td colspan="4"><table class="centpercent nobordernopadding"><tr><td>'.$langs->trans("LastInterventions", ($num <= $MAXLIST ? "" : $MAXLIST)).'</td><td class="right"><a class="notasortlink" href="'.DOL_URL_ROOT.'/fichinter/list.php?socid='.$object->id.'"><span class="hideonsmartphone">'.$langs->trans("AllInterventions").'</span><span class="badge marginleftonlyshort">'.$num.'</span></td>';
1346 print '<td width="20px" class="right"><a href="'.DOL_URL_ROOT.'/fichinter/stats/index.php?socid='.$object->id.'">'.img_picto($langs->trans("Statistics"), 'stats').'</a></td>';
1347 print '</tr></table></td>';
1348 print '</tr>';
1349 }
1350
1351 $i = 0;
1352 while ($i < $num && $i < $MAXLIST) {
1353 $objp = $db->fetch_object($resql);
1354
1355 $fichinter_static->id = $objp->id;
1356 $fichinter_static->ref = $objp->ref;
1357 $fichinter_static->statut = $objp->fk_statut;
1358 $fichinter_static->fk_project = $objp->fk_projet;
1359
1360 print '<tr class="oddeven">';
1361 print '<td class="nowraponall">';
1362 print $fichinter_static->getNomUrl(1);
1363 // Preview
1364 $filedir = $conf->ficheinter->multidir_output[$objp->entity].'/'.dol_sanitizeFileName($objp->ref);
1365 $file_list = null;
1366 if (!empty($filedir)) {
1367 $file_list = dol_dir_list($filedir, 'files', 0, dol_sanitizeFileName($objp->ref).'.pdf', '(\.meta|_preview.*.*\.png)$', 'date', SORT_DESC);
1368 }
1369 if (is_array($file_list) && !empty($file_list)) {
1370 // Defined relative dir to DOL_DATA_ROOT
1371 $relativedir = '';
1372 if ($filedir) {
1373 $relativedir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $filedir);
1374 $relativedir = preg_replace('/^[\\/]/', '', $relativedir);
1375 }
1376 // Get list of files stored into database for same relative directory
1377 if ($relativedir) {
1378 completeFileArrayWithDatabaseInfo($file_list, $relativedir);
1379 '@phan-var-force array<array{name:string,path:string,level1name:string,relativename:string,fullname:string,date:string,size:int,perm:int,type:string,position_name:string,cover:string,keywords:string,acl:string,rowid:int,label:string,share:string}> $file_list';
1380
1381 //var_dump($sortfield.' - '.$sortorder);
1382 if (!empty($sortfield) && !empty($sortorder)) { // If $sortfield is for example 'position_name', we will sort on the property 'position_name' (that is concat of position+name)
1383 $file_list = dol_sort_array($file_list, $sortfield, $sortorder);
1384 }
1385 }
1386 $relativepath = dol_sanitizeFileName($objp->ref).'/'.dol_sanitizeFileName($objp->ref).'.pdf';
1387 print $formfile->showPreview($file_list, $fichinter_static->element, $relativepath, 0, 'entity=' . $objp->entity);
1388 }
1389 print '</td><td class="tdoverflowmax125">';
1390 if ($fichinter_static->fk_project > 0) {
1391 $project->fetch($fichinter_static->fk_project);
1392 print $project->getNomUrl(1);
1393 }
1394 // $filename = dol_sanitizeFileName($objp->ref);
1395 // $filedir = getMultidirOutput($fichinter_static).'/'.dol_sanitizeFileName($objp->ref);
1396 // $urlsource = '/fichinter/card.php?id='.$objp->cid;
1397 // print $formfile->getDocumentsLink($fichinter_static->element, $filename, $filedir);
1398 print '</td>'."\n";
1399 //print '<td class="right" width="80px">'.dol_print_date($db->jdate($objp->startdate)).'</td>'."\n";
1400 print '<td class="right" style="min-width: 60px">'.convertSecondToTime($objp->duration).'</td>'."\n";
1401 print '<td class="nowrap right" style="min-width: 60px">'.$fichinter_static->getLibStatut(5).'</td>'."\n";
1402 print '</tr>';
1403
1404 $i++;
1405 }
1406 $db->free($resql);
1407
1408 if ($num > 0) {
1409 print "</table>";
1410 print '</div>';
1411 }
1412 } else {
1413 dol_print_error($db);
1414 }
1415 }
1416
1417 /*
1418 * Latest invoices templates
1419 */
1420 if (isModEnabled('invoice') && $user->hasRight('facture', 'lire')) {
1421 $sql = 'SELECT f.rowid as id, f.titre as ref, f.fk_projet';
1422 $sql .= ', f.total_ht';
1423 $sql .= ', f.total_tva';
1424 $sql .= ', f.total_ttc';
1425 $sql .= ', f.datec as dc';
1426 $sql .= ', f.date_last_gen, f.date_when';
1427 $sql .= ', f.frequency';
1428 $sql .= ', f.unit_frequency';
1429 $sql .= ', f.suspended as suspended';
1430 $sql .= ', s.nom, s.rowid as socid';
1431 $sql .= " FROM ".MAIN_DB_PREFIX."societe as s,".MAIN_DB_PREFIX."facture_rec as f";
1432 $sql .= " WHERE f.fk_soc = s.rowid AND s.rowid = ".((int) $object->id);
1433 $sql .= " AND f.entity IN (".getEntity('invoice').")";
1434 $sql .= ' GROUP BY f.rowid, f.titre, f.fk_projet, f.total_ht, f.total_tva, f.total_ttc,';
1435 $sql .= ' f.date_last_gen, f.datec, f.frequency, f.unit_frequency,';
1436 $sql .= ' f.suspended, f.date_when,';
1437 $sql .= ' s.nom, s.rowid';
1438 $sql .= " ORDER BY f.date_last_gen, f.datec DESC";
1439
1440 $resql = $db->query($sql);
1441 if ($resql) {
1442 $invoicetemplate = new FactureRec($db);
1443
1444 $num = $db->num_rows($resql);
1445 if ($num > 0) {
1446 print '<div class="div-table-responsive-no-min">';
1447 print '<table class="noborder centpercent lastrecordtable">';
1448 print '<tr class="liste_titre">';
1449 $colspan = 5;
1450 if (getDolGlobalString('MAIN_SHOW_PRICE_WITH_TAX_IN_SUMMARIES')) {
1451 $colspan++;
1452 }
1453 print '<td colspan="'.$colspan.'">';
1454 print '<table class="centpercent nobordernopadding"><tr>';
1455 print '<td>'.$langs->trans("LatestCustomerTemplateInvoices", ($num <= $MAXLIST ? "" : $MAXLIST)).'</td><td class="right"><a class="notasortlink" href="'.DOL_URL_ROOT.'/compta/facture/invoicetemplate_list.php?socid='.$object->id.'"><span class="hideonsmartphone">'.$langs->trans("AllCustomerTemplateInvoices").'</span><span class="badge marginleftonlyshort">'.$num.'</span></a></td>';
1456 print '</tr></table>';
1457 print '</td>';
1458 print '</tr>';
1459 }
1460
1461 $i = 0;
1462 while ($i < $num && $i < $MAXLIST) {
1463 $objp = $db->fetch_object($resql);
1464
1465 $invoicetemplate->id = $objp->id;
1466 $invoicetemplate->ref = $objp->ref;
1467 $invoicetemplate->fk_project = $objp->fk_projet;
1468 $invoicetemplate->suspended = $objp->suspended;
1469 $invoicetemplate->frequency = $objp->frequency;
1470 $invoicetemplate->unit_frequency = $objp->unit_frequency;
1471 $invoicetemplate->total_ht = $objp->total_ht;
1472 $invoicetemplate->total_tva = $objp->total_tva;
1473 $invoicetemplate->total_ttc = $objp->total_ttc;
1474 $invoicetemplate->date_last_gen = $objp->date_last_gen;
1475 $invoicetemplate->date_when = $objp->date_when;
1476
1477 print '<tr class="oddeven">';
1478 print '<td class="tdoverflowmax250">';
1479 print $invoicetemplate->getNomUrl(1);
1480 print '</td><td class="tdoverflowmax125">';
1481 if ($invoicetemplate->fk_project > 0) {
1482 $project->fetch($invoicetemplate->fk_project);
1483 print $project->getNomUrl(1);
1484 }
1485 print '</td>';
1486
1487 if ($objp->frequency && $objp->date_last_gen > 0) {
1488 print '<td class="right" width="80px">'.dol_print_date($db->jdate($objp->date_last_gen), 'day').'</td>';
1489 } else {
1490 if ($objp->dc > 0) {
1491 print '<td class="right" width="80px">'.dol_print_date($db->jdate($objp->dc), 'day').'</td>';
1492 } else {
1493 print '<td class="right"><b>!!!</b></td>';
1494 }
1495 }
1496 print '<td class="right nowraponall">';
1497 print price($objp->total_ht);
1498 print '</td>';
1499
1500 if (getDolGlobalString('MAIN_SHOW_PRICE_WITH_TAX_IN_SUMMARIES')) {
1501 print '<td class="right nowraponall">';
1502 print price($objp->total_ttc);
1503 print '</td>';
1504 }
1505
1506 print '<td class="nowrap right" style="min-width: 60px">';
1507 print $langs->trans('FrequencyPer_'.$invoicetemplate->unit_frequency, $invoicetemplate->frequency).' - ';
1508 print($invoicetemplate->LibStatut($invoicetemplate->frequency, $invoicetemplate->suspended, 5, 0));
1509 print '</td>';
1510 print "</tr>\n";
1511 $i++;
1512 }
1513 $db->free($resql);
1514
1515 if ($num > 0) {
1516 print "</table>";
1517 print '</div>';
1518 }
1519 } else {
1520 dol_print_error($db);
1521 }
1522 }
1523
1524 /*
1525 * Latest invoices
1526 */
1527 if (isModEnabled('invoice') && $user->hasRight('facture', 'lire')) {
1528 $sql = 'SELECT f.rowid as facid, f.ref, f.type, f.ref_client, f.fk_projet';
1529 $sql .= ', f.total_ht';
1530 $sql .= ', f.total_tva';
1531 $sql .= ', f.total_ttc';
1532 $sql .= ', f.entity';
1533 $sql .= ', f.datef as df, f.date_lim_reglement as dl, f.datec as dc, f.paye as paye, f.fk_statut as status';
1534 $sql .= ', s.nom, s.rowid as socid';
1535 $sql .= ', SUM(pf.amount) as am';
1536 $sql .= " FROM ".MAIN_DB_PREFIX."societe as s,".MAIN_DB_PREFIX."facture as f";
1537 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'paiement_facture as pf ON f.rowid=pf.fk_facture';
1538 $sql .= " WHERE f.fk_soc = s.rowid AND s.rowid = ".((int) $object->id);
1539 $sql .= " AND f.entity IN (".getEntity('invoice').")";
1540 $sql .= ' GROUP BY f.rowid, f.ref, f.type, f.ref_client, f.fk_projet, f.total_ht, f.total_tva, f.total_ttc,';
1541 $sql .= ' f.entity, f.datef, f.date_lim_reglement, f.datec, f.paye, f.fk_statut,';
1542 $sql .= ' s.nom, s.rowid';
1543 $sql .= " ORDER BY f.datef DESC, f.datec DESC";
1544
1545 $resql = $db->query($sql);
1546 if ($resql) {
1547 $facturestatic = new Facture($db);
1548
1549 $num = $db->num_rows($resql);
1550 if ($num > 0) {
1551 print '<div class="div-table-responsive-no-min">';
1552 print '<table class="noborder centpercent lastrecordtable">';
1553 print '<tr class="liste_titre">';
1554 $colspan = 6;
1555 if (getDolGlobalString('MAIN_SHOW_PRICE_WITH_TAX_IN_SUMMARIES')) {
1556 $colspan++;
1557 }
1558 if (getDolGlobalString('MAIN_SHOW_REF_CUSTOMER_INVOICES')) {
1559 $colspan++;
1560 }
1561 print '<td colspan="'.$colspan.'">';
1562 print '<table class="centpercent nobordernopadding"><tr><td>'.$langs->trans("LastCustomersBills", ($num <= $MAXLIST ? "" : $MAXLIST)).'</td><td class="right"><a class="notasortlink" href="'.DOL_URL_ROOT.'/compta/facture/list.php?socid='.$object->id.'"><span class="hideonsmartphone">'.$langs->trans("AllBills").'</span><span class="badge marginleftonlyshort">'.$num.'</span></a></td>';
1563 print '<td width="20px" class="right"><a href="'.DOL_URL_ROOT.'/compta/facture/stats/index.php?socid='.$object->id.'">'.img_picto($langs->trans("Statistics"), 'stats').'</a></td>';
1564 print '</tr></table>';
1565 print '</td>';
1566 print '</tr>';
1567 }
1568
1569 $i = 0;
1570 while ($i < $num && $i < $MAXLIST) {
1571 $objp = $db->fetch_object($resql);
1572
1573 $facturestatic->id = $objp->facid;
1574 $facturestatic->ref = $objp->ref;
1575 $facturestatic->ref_client = $objp->ref_client;
1576 $facturestatic->fk_project = $objp->fk_projet;
1577 $facturestatic->type = $objp->type;
1578 $facturestatic->total_ht = $objp->total_ht;
1579 $facturestatic->total_tva = $objp->total_tva;
1580 $facturestatic->total_ttc = $objp->total_ttc;
1581 $facturestatic->statut = $objp->status;
1582 $facturestatic->status = $objp->status;
1583 $facturestatic->paye = $objp->paye;
1584 $facturestatic->alreadypaid = $objp->am;
1585 $facturestatic->totalpaid = $objp->am;
1586 $facturestatic->date = $db->jdate($objp->df);
1587 $facturestatic->date_lim_reglement = $db->jdate($objp->dl);
1588
1589 print '<tr class="oddeven">';
1590 print '<td class="nowraponall">';
1591 print $facturestatic->getNomUrl(1);
1592 // Preview
1593 $filedir = $conf->facture->multidir_output[$objp->entity].'/'.dol_sanitizeFileName($objp->ref);
1594 $file_list = null;
1595 if (!empty($filedir)) {
1596 $file_list = dol_dir_list($filedir, 'files', 0, dol_sanitizeFileName($objp->ref).'.pdf', '(\.meta|_preview.*.*\.png)$', 'date', SORT_DESC);
1597 }
1598 if (is_array($file_list) && !empty($file_list)) {
1599 // Defined relative dir to DOL_DATA_ROOT
1600 $relativedir = '';
1601 if ($filedir) {
1602 $relativedir = preg_replace('/^'.preg_quote(DOL_DATA_ROOT, '/').'/', '', $filedir);
1603 $relativedir = preg_replace('/^[\\/]/', '', $relativedir);
1604 }
1605 // Get list of files stored into database for same relative directory
1606 if ($relativedir) {
1607 completeFileArrayWithDatabaseInfo($file_list, $relativedir);
1608 '@phan-var-force array<array{name:string,path:string,level1name:string,relativename:string,fullname:string,date:string,size:int,perm:int,type:string,position_name:string,cover:string,keywords:string,acl:string,rowid:int,label:string,share:string}> $file_list';
1609
1610 //var_dump($sortfield.' - '.$sortorder);
1611 if (!empty($sortfield) && !empty($sortorder)) { // If $sortfield is for example 'position_name', we will sort on the property 'position_name' (that is concat of position+name)
1612 $file_list = dol_sort_array($file_list, $sortfield, $sortorder);
1613 }
1614 }
1615 $relativepath = dol_sanitizeFileName($objp->ref).'/'.dol_sanitizeFileName($objp->ref).'.pdf';
1616 print $formfile->showPreview($file_list, $facturestatic->element, $relativepath, 0, 'entity=' . $objp->entity);
1617 }
1618 print '</td><td class="tdoverflowmax125">';
1619 if ($facturestatic->fk_project > 0) {
1620 $project->fetch($facturestatic->fk_project);
1621 print $project->getNomUrl(1);
1622 }
1623 // $filename = dol_sanitizeFileName($objp->ref);
1624 // $filedir = $conf->facture->multidir_output[$objp->entity].'/'.dol_sanitizeFileName($objp->ref);
1625 // $urlsource = '/compta/facture/card.php?id='.$objp->cid;
1626 //print $formfile->getDocumentsLink($facturestatic->element, $filename, $filedir);
1627 print '</td>';
1628 if (getDolGlobalString('MAIN_SHOW_REF_CUSTOMER_INVOICES')) {
1629 print '<td class="nowraponall">';
1630 print dolPrintHTML($objp->ref_client);
1631 print '</td>';
1632 }
1633 if ($objp->df > 0) {
1634 print '<td width="80px" title="'.dol_escape_htmltag($langs->trans('DateInvoice')).'">'.dol_print_date($db->jdate($objp->df), 'day').'</td>';
1635 } else {
1636 print '<td><b>!!!</b></td>';
1637 }
1638 if ($objp->dl > 0) {
1639 print '<td width="80px" title="'.dol_escape_htmltag($langs->trans('DateMaxPayment')).'">'.dol_print_date($db->jdate($objp->dl), 'day').'</td>';
1640 } else {
1641 print '<td><b>!!!</b></td>';
1642 }
1643
1644 print '<td class="right nowraponall">';
1645 print price($objp->total_ht);
1646 print '</td>';
1647
1648 if (getDolGlobalString('MAIN_SHOW_PRICE_WITH_TAX_IN_SUMMARIES')) {
1649 print '<td class="right nowraponall">';
1650 print price($objp->total_ttc);
1651 print '</td>';
1652 }
1653
1654 print '<td class="nowrap right" style="min-width: 60px">'.($facturestatic->LibStatut($objp->paye, $objp->status, 5, $objp->am)).'</td>';
1655 print "</tr>\n";
1656 $i++;
1657 }
1658 $db->free($resql);
1659
1660 if ($num > 0) {
1661 print "</table>";
1662 print '</div>';
1663 }
1664 } else {
1665 dol_print_error($db);
1666 }
1667 }
1668
1669 // Allow external modules to add their own shortlist of recent objects
1670 $parameters = array();
1671 $reshook = $hookmanager->executeHooks('addMoreRecentObjects', $parameters, $object, $action);
1672 if ($reshook < 0) {
1673 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1674 } else {
1675 print $hookmanager->resPrint;
1676 }
1677
1678 print '</div></div>';
1679 print '<div class="clearboth"></div>';
1680
1681 print dol_get_fiche_end();
1682
1683
1684 /*
1685 * Action bar
1686 */
1687 print '<div class="tabsAction">';
1688
1689 $parameters = array();
1690 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
1691
1692 if (empty($reshook)) {
1693 if ($object->status != 1) {
1694 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" title="'.dol_escape_js($langs->trans("ThirdPartyIsClosed")).'" href="#">'.$langs->trans("ThirdPartyIsClosed").'</a></div>';
1695 }
1696
1697 if (isModEnabled("propal") && $user->hasRight('propal', 'creer') && $object->status == 1) {
1698 $langs->load("propal");
1699 print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/comm/propal/card.php?socid='.$object->id.'&action=create">'.$langs->trans("AddProp").'</a></div>';
1700 }
1701
1702 if (isModEnabled('order') && $user->hasRight('commande', 'creer') && $object->status == 1) {
1703 $langs->load("orders");
1704 print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/commande/card.php?socid='.$object->id.'&action=create">'.$langs->trans("AddOrder").'</a></div>';
1705 }
1706
1707 if ($user->hasRight('contrat', 'creer') && $object->status == 1) {
1708 $langs->load("contracts");
1709 print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/contrat/card.php?socid='.$object->id.'&action=create">'.$langs->trans("AddContract").'</a></div>';
1710 }
1711
1712 if (isModEnabled('intervention') && $user->hasRight('ficheinter', 'creer') && $object->status == 1) {
1713 $langs->load("interventions");
1714 print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/fichinter/card.php?socid='.$object->id.'&action=create">'.$langs->trans("AddIntervention").'</a></div>';
1715 }
1716
1717 // Add invoice
1718 if (isModEnabled('deplacement') && $object->status == 1) {
1719 $langs->load("trips");
1720 print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/compta/deplacement/card.php?socid='.$object->id.'&action=create">'.$langs->trans("AddTrip").'</a></div>';
1721 }
1722
1723 if (isModEnabled('invoice') && $object->status == 1) {
1724 if (!$user->hasRight('facture', 'creer')) {
1725 $langs->load("bills");
1726 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" title="'.dol_escape_js($langs->trans("NotAllowed")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
1727 } else {
1728 $langs->loadLangs(array("orders", "bills"));
1729
1730 if ($object->client != 0 && $object->client != 2) {
1731 print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create&socid='.$object->id.'">'.$langs->trans("AddBill").'</a></div>';
1732 } else {
1733 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" title="'.dol_escape_js($langs->trans("ThirdPartyMustBeEditAsCustomer")).'" href="#">'.$langs->trans("AddBill").'</a></div>';
1734 }
1735 }
1736 }
1737
1738 if (isModEnabled('invoice') && $object->status == 1) {
1739 if ($user->hasRight('facture', 'creer')) {
1740 if (isModEnabled('order')) {
1741 if ($object->client != 0 && $object->client != 2) {
1742 if (!empty($orders2invoice) && $orders2invoice > 0) {
1743 print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/commande/list.php?socid='.$object->id.'&search_billed=0&autoselectall=1">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
1744 } else {
1745 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" title="'.dol_escape_js($langs->trans("NoOrdersToInvoice")).'" href="#">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
1746 }
1747 } else {
1748 print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" title="'.dol_escape_js($langs->trans("ThirdPartyMustBeEditAsCustomer")).'" href="#">'.$langs->trans("CreateInvoiceForThisCustomer").'</a></div>';
1749 }
1750 }
1751 }
1752 }
1753
1754 // Add action
1755 if (isModEnabled('agenda') && getDolGlobalString('MAIN_REPEATTASKONEACHTAB') && $object->status == 1) {
1756 if ($user->hasRight('agenda', 'myactions', 'create')) {
1757 print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/comm/action/card.php?action=create&socid='.$object->id.'">'.$langs->trans("AddAction").'</a></div>';
1758 } else {
1759 print '<div class="inline-block divButAction"><a class="butAction" title="'.dol_escape_js($langs->trans("NotAllowed")).'" href="#">'.$langs->trans("AddAction").'</a></div>';
1760 }
1761 }
1762 }
1763
1764 print '</div>';
1765
1766 if (getDolGlobalString('MAIN_DUPLICATE_CONTACTS_TAB_ON_CUSTOMER_CARD')) {
1767 // List of contacts
1768 show_contacts($conf, $langs, $db, $object, $_SERVER["PHP_SELF"].'?socid='.$object->id);
1769 }
1770
1771 if (getDolGlobalString('MAIN_REPEATTASKONEACHTAB')) {
1772 print load_fiche_titre($langs->trans("ActionsOnCompany"), '', '');
1773
1774 // List of todo actions
1775 show_actions_todo($conf, $langs, $db, $object);
1776
1777 // List of done actions
1778 show_actions_done($conf, $langs, $db, $object);
1779 }
1780} else {
1781 $langs->load("errors");
1782 print $langs->trans('ErrorRecordNotFound');
1783}
1784
1785// End of page
1786llxFooter();
1787$db->close();
$id
Definition account.php:48
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
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 accounting accounts.
Class to manage members of a foundation.
Class to manage customers or prospects.
Class to manage customers orders.
Class to manage contact/addresses.
Class to manage standard extra fields.
Class to manage invoices.
Class to manage invoice templates.
Class to manage generation of HTML components for accounting management.
Class to build HTML component for third parties management Only common components are here.
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
Class with static methods for building HTML components related to products Only components common to ...
Class to manage projects.
Class to manage proposals.
Class to manage Dolibarr users.
show_contacts($conf, $langs, $db, $object, $backtopage='', $showuserlogin=0)
Show html area for list of contacts.
show_actions_done($conf, $langs, $db, $filterobj, $objcon=null, $noprint=0, $actioncode='', $donetodo='done', $filters=array(), $sortfield='a.datep, a.id', $sortorder='DESC', $module='')
Show html area with actions (done or not, ignore the name of function).
societe_prepare_head(Societe $object)
Return array of tabs to used on pages for third parties cards.
show_actions_todo($conf, $langs, $db, $filterobj, $objcon=null, $noprint=0, $actioncode='')
Show html area with actions to do.
completeFileArrayWithDatabaseInfo(&$filearray, $relativedir, $object=null)
Complete $filearray with data from database.
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:63
dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0, $filters='', $useCache=true)
Return an id or code from a code or id.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
showValueWithClipboardCPButton($valuetocopy, $showonlyonhover=1, $texttoshow='')
Create a button to copy $valuetocopy in the clipboard (for copy and paste feature).
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
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.
dolPrintHTML($s, $allowiframe=0)
Return a string (that can be on several lines) ready to be output on a HTML page.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
img_action($titlealt, $numaction, $picto='', $moreatt='')
Show logo action.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_now($mode='auto')
Return date for now.
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).
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
newToken()
Return the value of token currently saved into session with name 'newtoken'.
yn($yesno, $format=1, $color=0)
Return yes or no in current language.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_clone($object, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
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.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
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
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.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.