dolibarr  7.0.0-beta
card.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2002-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
4  * Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
5  * Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
6  * Copyright (C) 2005-2015 Regis Houssin <regis.houssin@capnetworks.com>
7  * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
8  * Copyright (C) 2010-2015 Juanjo Menent <jmenent@2byte.es>
9  * Copyright (C) 2012-2013 Christophe Battarel <christophe.battarel@altairis.fr>
10  * Copyright (C) 2012-2013 Cédric Salvador <csalvador@gpcsolutions.fr>
11  * Copyright (C) 2012-2014 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
12  * Copyright (C) 2013 Jean-Francois FERRY <jfefe@aternatik.fr>
13  * Copyright (C) 2013-2014 Florian Henry <florian.henry@open-concept.pro>
14  * Copyright (C) 2013 Cédric Salvador <csalvador@gpcsolutions.fr>
15  * Copyright (C) 2014 Ferran Marcet <fmarcet@2byte.es>
16  * Copyright (C) 2015-2016 Marcos García <marcosgdf@gmail.com>
17  *
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 3 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program. If not, see <http://www.gnu.org/licenses/>.
30  */
31 
38 require '../../main.inc.php';
39 require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
40 require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture-rec.class.php';
41 require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
42 require_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php';
43 require_once DOL_DOCUMENT_ROOT . '/core/modules/facture/modules_facture.php';
44 require_once DOL_DOCUMENT_ROOT . '/core/class/discount.class.php';
45 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formfile.class.php';
46 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formother.class.php';
47 require_once DOL_DOCUMENT_ROOT . '/core/class/html.formmargin.class.php';
48 require_once DOL_DOCUMENT_ROOT . '/core/lib/invoice.lib.php';
49 require_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
50 require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
51 require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php';
52 if (! empty($conf->commande->enabled))
53  require_once DOL_DOCUMENT_ROOT . '/commande/class/commande.class.php';
54 if (! empty($conf->projet->enabled)) {
55  require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
56  require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
57 }
58 require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
59 
60 if (!empty($conf->variants->enabled)) {
61  require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
62 }
63 if (! empty($conf->accounting->enabled)) {
64  require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingjournal.class.php';
65 }
66 
67 $langs->loadLangs(array('bills','companies','compta','products','banks','main','withdrawals'));
68 if (! empty($conf->incoterm->enabled)) $langs->load('incoterm');
69 if (! empty($conf->margin->enabled)) $langs->load('margins');
70 
71 $projectid = (GETPOST('projectid','int') ? GETPOST('projectid', 'int') : 0);
72 
73 $id = (GETPOST('id', 'int') ? GETPOST('id', 'int') : GETPOST('facid', 'int')); // For backward compatibility
74 $ref = GETPOST('ref', 'alpha');
75 $socid = GETPOST('socid', 'int');
76 $action = GETPOST('action', 'alpha');
77 $confirm = GETPOST('confirm', 'alpha');
78 $cancel = GETPOST('cancel', 'alpha');
79 $lineid = GETPOST('lineid', 'int');
80 $userid = GETPOST('userid', 'int');
81 $search_ref = GETPOST('sf_ref','alpha') ? GETPOST('sf_ref', 'alpha') : GETPOST('search_ref', 'alpha');
82 $search_societe = GETPOST('search_societe', 'alpha');
83 $search_montant_ht = GETPOST('search_montant_ht', 'alpha');
84 $search_montant_ttc = GETPOST('search_montant_ttc', 'alpha');
85 $origin = GETPOST('origin', 'alpha');
86 $originid = (GETPOST('originid', 'int') ? GETPOST('originid', 'int') : GETPOST('origin_id', 'int')); // For backward compatibility
87 $fac_rec=GETPOST('fac_rec','int');
88 
89 // PDF
90 $hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
91 $hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0));
92 $hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0));
93 
94 // Security check
95 $fieldid = (! empty($ref) ? 'facnumber' : 'rowid');
96 if ($user->societe_id) $socid = $user->societe_id;
97 $result = restrictedArea($user, 'facture', $id, '', '', 'fk_soc', $fieldid);
98 
99 // Nombre de ligne pour choix de produit/service predefinis
100 $NBLINES = 4;
101 
102 $usehm = (! empty($conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE) ? $conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE : 0);
103 
104 $object = new Facture($db);
105 $extrafields = new ExtraFields($db);
106 
107 // Load object
108 if ($id > 0 || ! empty($ref)) {
109  $ret = $object->fetch($id, $ref, '', '', $conf->global->INVOICE_USE_SITUATION);
110 }
111 
112 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
113 $hookmanager->initHooks(array('invoicecard','globalcard'));
114 
115 $permissionnote = $user->rights->facture->creer; // Used by the include of actions_setnotes.inc.php
116 $permissiondellink=$user->rights->facture->creer; // Used by the include of actions_dellink.inc.php
117 $permissiontoedit = $user->rights->facture->creer; // Used by the include of actions_lineupdonw.inc.php
118 
119 
120 /*
121  * Actions
122  */
123 
124 $parameters = array('socid' => $socid);
125 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
126 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
127 
128 if (empty($reshook))
129 {
130  if ($cancel)
131  {
132  if (! empty($backtopage))
133  {
134  header("Location: ".$backtopage);
135  exit;
136  }
137  $action='';
138  }
139 
140  include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not include_once
141 
142  include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be include, not include_once
143 
144  include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be include, not include_once
145 
146  // Action clone object
147  if ($action == 'confirm_clone' && $confirm == 'yes' && $user->rights->facture->creer) {
148  // if (1 == 0 && empty($_REQUEST["clone_content"]) && empty($_REQUEST["clone_receivers"])) {
149  // $mesgs [] = '<div class="error">' . $langs->trans("NoCloneOptionsSpecified") . '</div>';
150  // } else {
151  if ($object->fetch($id) > 0) {
152  $result = $object->createFromClone($socid);
153  if ($result > 0) {
154  header("Location: " . $_SERVER['PHP_SELF'] . '?facid=' . $result);
155  exit();
156  } else {
157  setEventMessages($object->error, $object->errors, 'errors');
158  $action = '';
159  }
160  }
161  // }
162  }
163 
164  // Change status of invoice
165  else if ($action == 'reopen' && $user->rights->facture->creer) {
166  $result = $object->fetch($id);
167  if ($object->statut == 2 || ($object->statut == 3 && $object->close_code != 'replaced') || ($object->statut == 1 && $object->paye == 1)) { // ($object->statut == 1 && $object->paye == 1) should not happened but can be found when data are corrupted
168  $result = $object->set_unpaid($user);
169  if ($result > 0) {
170  header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id);
171  exit();
172  } else {
173  setEventMessages($object->error, $object->errors, 'errors');
174  }
175  }
176  }
177 
178  // Delete invoice
179  else if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->facture->supprimer) {
180  $result = $object->fetch($id);
181  $object->fetch_thirdparty();
182 
183  $idwarehouse = GETPOST('idwarehouse');
184 
185  $qualified_for_stock_change = 0;
186  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
187  $qualified_for_stock_change = $object->hasProductsOrServices(2);
188  } else {
189  $qualified_for_stock_change = $object->hasProductsOrServices(1);
190  }
191 
192  $result = $object->delete($user, 0, $idwarehouse);
193  if ($result > 0) {
194  header('Location: ' . DOL_URL_ROOT . '/compta/facture/list.php');
195  exit();
196  } else {
197  setEventMessages($object->error, $object->errors, 'errors');
198  $action='';
199  }
200  }
201 
202  // Delete line
203  else if ($action == 'confirm_deleteline' && $confirm == 'yes' && $user->rights->facture->creer)
204  {
205  $object->fetch($id);
206  $object->fetch_thirdparty();
207 
208  $result = $object->deleteline(GETPOST('lineid'));
209  if ($result > 0) {
210  // Define output language
211  $outputlangs = $langs;
212  $newlang = '';
213  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && ! empty($_REQUEST['lang_id']))
214  $newlang = $_REQUEST['lang_id'];
215  if ($conf->global->MAIN_MULTILANGS && empty($newlang))
216  $newlang = $object->thirdparty->default_lang;
217  if (! empty($newlang)) {
218  $outputlangs = new Translate("", $conf);
219  $outputlangs->setDefaultLang($newlang);
220  }
221  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
222  $ret = $object->fetch($id); // Reload to get new records
223  $result = $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
224  }
225  if ($result >= 0) {
226  header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id);
227  exit();
228  }
229  } else {
230  setEventMessages($object->error, $object->errors, 'errors');
231  $action = '';
232  }
233  }
234 
235  // Delete link of credit note to invoice
236  else if ($action == 'unlinkdiscount' && $user->rights->facture->creer)
237  {
238  $discount = new DiscountAbsolute($db);
239  $result = $discount->fetch(GETPOST("discountid"));
240  $discount->unlink_invoice();
241  }
242 
243  // Validation
244  else if ($action == 'valid' && $user->rights->facture->creer)
245  {
246  $object->fetch($id);
247 
248  // On verifie signe facture
249  if ($object->type == Facture::TYPE_CREDIT_NOTE) {
250  // Si avoir, le signe doit etre negatif
251  if ($object->total_ht >= 0) {
252  setEventMessages($langs->trans("ErrorInvoiceAvoirMustBeNegative"), null, 'errors');
253  $action = '';
254  }
255  } else {
256  // Si non avoir, le signe doit etre positif
257  if (empty($conf->global->FACTURE_ENABLE_NEGATIVE) && $object->total_ht < 0) {
258  setEventMessages($langs->trans("ErrorInvoiceOfThisTypeMustBePositive"), null, 'errors');
259  $action = '';
260  }
261  }
262  }
263 
264  else if ($action == 'set_thirdparty' && $user->rights->facture->creer)
265  {
266  $object->fetch($id);
267  $object->setValueFrom('fk_soc', $socid, '', null, 'int', '', $user, 'BILL_MODIFY');
268 
269  header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id);
270  exit();
271  }
272 
273  else if ($action == 'classin' && $user->rights->facture->creer)
274  {
275  $object->fetch($id);
276  $object->setProject($_POST['projectid']);
277  }
278 
279  else if ($action == 'setmode' && $user->rights->facture->creer)
280  {
281  $object->fetch($id);
282  $result = $object->setPaymentMethods(GETPOST('mode_reglement_id', 'int'));
283  if ($result < 0)
284  dol_print_error($db, $object->error);
285  }
286 
287  // Multicurrency Code
288  else if ($action == 'setmulticurrencycode' && $user->rights->facture->creer) {
289  $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
290  }
291 
292  // Multicurrency rate
293  else if ($action == 'setmulticurrencyrate' && $user->rights->facture->creer) {
294  $result = $object->setMulticurrencyRate(price2num(GETPOST('multicurrency_tx')), GETPOST('calculation_mode', 'int'));
295  }
296 
297  else if ($action == 'setinvoicedate' && $user->rights->facture->creer)
298  {
299  $object->fetch($id);
300  $old_date_lim_reglement = $object->date_lim_reglement;
301  $date = dol_mktime(12, 0, 0, $_POST['invoicedatemonth'], $_POST['invoicedateday'], $_POST['invoicedateyear']);
302  if (empty($date))
303  {
304  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
305  header('Location: '.$_SERVER["PHP_SELF"].'?facid='.$id.'&action=editinvoicedate');
306  exit;
307  }
308  $object->date=$date;
309  $new_date_lim_reglement = $object->calculate_date_lim_reglement();
310  if ($new_date_lim_reglement > $old_date_lim_reglement) $object->date_lim_reglement = $new_date_lim_reglement;
311  if ($object->date_lim_reglement < $object->date) $object->date_lim_reglement = $object->date;
312  $result = $object->update($user);
313  if ($result < 0) dol_print_error($db, $object->error);
314  }
315 
316  else if ($action == 'setdate_pointoftax' && $user->rights->facture->creer)
317  {
318  $object->fetch($id);
319  $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
320  $object->date_pointoftax=$date_pointoftax;
321  $result = $object->update($user);
322  if ($result < 0) dol_print_error($db, $object->error);
323  }
324 
325  else if ($action == 'setconditions' && $user->rights->facture->creer)
326  {
327  $object->fetch($id);
328  $object->cond_reglement_code = 0; // To clean property
329  $object->cond_reglement_id = 0; // To clean property
330  $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'));
331  if ($result < 0) dol_print_error($db, $object->error);
332 
333  $old_date_lim_reglement = $object->date_lim_reglement;
334  $new_date_lim_reglement = $object->calculate_date_lim_reglement();
335  if ($new_date_lim_reglement > $old_date_lim_reglement) $object->date_lim_reglement = $new_date_lim_reglement;
336  if ($object->date_lim_reglement < $object->date) $object->date_lim_reglement = $object->date;
337  $result = $object->update($user);
338  if ($result < 0) dol_print_error($db, $object->error);
339  }
340 
341  else if ($action == 'setpaymentterm' && $user->rights->facture->creer)
342  {
343  $object->fetch($id);
344  $object->date_lim_reglement = dol_mktime(12, 0, 0, $_POST['paymenttermmonth'], $_POST['paymenttermday'], $_POST['paymenttermyear']);
345  if ($object->date_lim_reglement < $object->date) {
346  $object->date_lim_reglement = $object->calculate_date_lim_reglement();
347  setEventMessages($langs->trans("DatePaymentTermCantBeLowerThanObjectDate"), null, 'warnings');
348  }
349  $result = $object->update($user);
350  if ($result < 0)
351  dol_print_error($db, $object->error);
352  }
353 
354  else if ($action == 'setrevenuestamp' && $user->rights->facture->creer)
355  {
356  $object->fetch($id);
357  $object->revenuestamp = GETPOST('revenuestamp');
358  $result = $object->update($user);
359  $object->update_price(1);
360  if ($result < 0)
361  dol_print_error($db, $object->error);
362  }
363 
364  // Set incoterm
365  elseif ($action == 'set_incoterms' && !empty($conf->incoterm->enabled))
366  {
367  $result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha'));
368  }
369 
370  // bank account
371  else if ($action == 'setbankaccount' && $user->rights->facture->creer)
372  {
373  $result=$object->setBankAccount(GETPOST('fk_account', 'int'));
374  }
375 
376  else if ($action == 'setremisepercent' && $user->rights->facture->creer)
377  {
378  $object->fetch($id);
379  $result = $object->set_remise($user, $_POST['remise_percent']);
380  }
381 
382  else if ($action == "setabsolutediscount" && $user->rights->facture->creer)
383  {
384  // POST[remise_id] or POST[remise_id_for_payment]
385 
386  // We use the credit to reduce amount of invoice
387  if (! empty($_POST["remise_id"])) {
388  $ret = $object->fetch($id);
389  if ($ret > 0) {
390  $result = $object->insert_discount($_POST["remise_id"]);
391  if ($result < 0) {
392  setEventMessages($object->error, $object->errors, 'errors');
393  }
394  } else {
395  dol_print_error($db, $object->error);
396  }
397  }
398  // We use the credit to reduce remain to pay
399  if (! empty($_POST["remise_id_for_payment"]))
400  {
401  require_once DOL_DOCUMENT_ROOT . '/core/class/discount.class.php';
402  $discount = new DiscountAbsolute($db);
403  $discount->fetch($_POST["remise_id_for_payment"]);
404 
405  //var_dump($object->getRemainToPay(0));
406  //var_dump($discount->amount_ttc);exit;
407  if ($discount->amount_ttc > $object->getRemainToPay(0))
408  {
409  // TODO Split the discount in 2 automatically
410  $error++;
411  setEventMessages($langs->trans("ErrorDiscountLargerThanRemainToPaySplitItBefore"), null, 'errors');
412  }
413 
414  if (! $error)
415  {
416  $result = $discount->link_to_invoice(0, $id);
417  if ($result < 0) {
418  setEventMessages($discount->error, $discount->errors, 'errors');
419  }
420  }
421  }
422 
423  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
424  {
425  $outputlangs = $langs;
426  $newlang = '';
427  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
428  if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
429  if (! empty($newlang)) {
430  $outputlangs = new Translate("", $conf);
431  $outputlangs->setDefaultLang($newlang);
432  }
433  $ret = $object->fetch($id); // Reload to get new records
434 
435  $result = $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
436  if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
437  }
438  }
439 
440  else if ($action == 'setref_client' && $user->rights->facture->creer)
441  {
442  $object->fetch($id);
443  $object->set_ref_client(GETPOST('ref_client'));
444  }
445 
446  // Classify to validated
447  else if ($action == 'confirm_valid' && $confirm == 'yes' &&
448  ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->creer))
449  || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->invoice_advance->validate)))
450  )
451  {
452  $idwarehouse = GETPOST('idwarehouse','int');
453 
454  $object->fetch($id);
455  $object->fetch_thirdparty();
456 
457  // Check parameters
458 
459  // Check for mandatory fields defined into setup
460  $array_to_check=array('IDPROF1','IDPROF2','IDPROF3','IDPROF4','IDPROF5','IDPROF6','EMAIL');
461  foreach($array_to_check as $key)
462  {
463  $keymin=strtolower($key);
464  $i=(int) preg_replace('/[^0-9]/','',$key);
465  $vallabel=$object->thirdparty->$keymin;
466 
467  if ($i > 0)
468  {
469  if ($object->thirdparty->isACompany())
470  {
471  // Check for mandatory prof id (but only if country is other than ours)
472  if ($mysoc->country_id > 0 && $object->thirdparty->country_id == $mysoc->country_id)
473  {
474  $idprof_mandatory ='SOCIETE_'.$key.'_INVOICE_MANDATORY';
475  if (! $vallabel && ! empty($conf->global->$idprof_mandatory))
476  {
477  $langs->load("errors");
478  $error++;
479  setEventMessages($langs->trans('ErrorProdIdIsMandatory', $langs->transcountry('ProfId'.$i, $object->thirdparty->country_code)).' ('.$langs->trans("ForbiddenBySetupRules").')', null, 'errors');
480  }
481  }
482  }
483  }
484  else
485  {
486  //var_dump($conf->global->SOCIETE_EMAIL_MANDATORY);
487  if ($key == 'EMAIL')
488  {
489  // Check for mandatory
490  if (! empty($conf->global->SOCIETE_EMAIL_INVOICE_MANDATORY) && ! isValidEMail($object->thirdparty->email))
491  {
492  $langs->load("errors");
493  $error++;
494  setEventMessages($langs->trans("ErrorBadEMail", $object->thirdparty->email).' ('.$langs->trans("ForbiddenBySetupRules").')', null, 'errors');
495  }
496  }
497  }
498  }
499 
500  $qualified_for_stock_change = 0;
501  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
502  $qualified_for_stock_change = $object->hasProductsOrServices(2);
503  } else {
504  $qualified_for_stock_change = $object->hasProductsOrServices(1);
505  }
506 
507  // Check for warehouse
508  if ($object->type != Facture::TYPE_DEPOSIT && ! empty($conf->global->STOCK_CALCULATE_ON_BILL) && $qualified_for_stock_change)
509  {
510  if (! $idwarehouse || $idwarehouse == - 1) {
511  $error ++;
512  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
513  $action = '';
514  }
515  }
516 
517  if (! $error)
518  {
519  $result = $object->validate($user, '', $idwarehouse);
520  if ($result >= 0)
521  {
522  // Define output language
523  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
524  {
525  $outputlangs = $langs;
526  $newlang = '';
527  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
528  if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
529  if (! empty($newlang)) {
530  $outputlangs = new Translate("", $conf);
531  $outputlangs->setDefaultLang($newlang);
532  }
533  $model=$object->modelpdf;
534  $ret = $object->fetch($id); // Reload to get new records
535 
536  $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
537  if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
538  }
539  }
540  else
541  {
542  if (count($object->errors)) setEventMessages(null, $object->errors, 'errors');
543  else setEventMessages($object->error, $object->errors, 'errors');
544  }
545  }
546  }
547 
548  // Go back to draft status (unvalidate)
549  else if ($action == 'confirm_modif' &&
550  ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->creer))
551  || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->invoice_advance->unvalidate)))
552  )
553  {
554  $idwarehouse = GETPOST('idwarehouse');
555 
556  $object->fetch($id);
557  $object->fetch_thirdparty();
558 
559  $qualified_for_stock_change = 0;
560  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
561  $qualified_for_stock_change = $object->hasProductsOrServices(2);
562  } else {
563  $qualified_for_stock_change = $object->hasProductsOrServices(1);
564  }
565 
566  // Check parameters
567  if ($object->type != Facture::TYPE_DEPOSIT && ! empty($conf->global->STOCK_CALCULATE_ON_BILL) && $qualified_for_stock_change)
568  {
569  if (! $idwarehouse || $idwarehouse == - 1) {
570  $error ++;
571  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
572  $action = '';
573  }
574  }
575 
576  if (! $error) {
577  // On verifie si la facture a des paiements
578  $sql = 'SELECT pf.amount';
579  $sql .= ' FROM ' . MAIN_DB_PREFIX . 'paiement_facture as pf';
580  $sql .= ' WHERE pf.fk_facture = ' . $object->id;
581 
582  $result = $db->query($sql);
583  if ($result) {
584  $i = 0;
585  $num = $db->num_rows($result);
586 
587  while ($i < $num) {
588  $objp = $db->fetch_object($result);
589  $totalpaye += $objp->amount;
590  $i ++;
591  }
592  } else {
593  dol_print_error($db, '');
594  }
595 
596  $resteapayer = $object->total_ttc - $totalpaye;
597 
598  // On verifie si les lignes de factures ont ete exportees en compta et/ou ventilees
599  $ventilExportCompta = $object->getVentilExportCompta();
600 
601  // On verifie si aucun paiement n'a ete effectue
602  if ($ventilExportCompta == 0)
603  {
604  if (! empty($conf->global->INVOICE_CAN_ALWAYS_BE_EDITED) || ($resteapayer == $object->total_ttc && empty($object->paye)))
605  {
606  $result=$object->set_draft($user, $idwarehouse);
607  if ($result<0) setEventMessages($object->error, $object->errors, 'errors');
608 
609 
610  // Define output language
611  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
612  {
613  $outputlangs = $langs;
614  $newlang = '';
615  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
616  if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
617  if (! empty($newlang)) {
618  $outputlangs = new Translate("", $conf);
619  $outputlangs->setDefaultLang($newlang);
620  }
621  $model=$object->modelpdf;
622  $ret = $object->fetch($id); // Reload to get new records
623 
624  $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
625  }
626  }
627  }
628  }
629  }
630 
631  // Classify "paid"
632  else if ($action == 'confirm_paid' && $confirm == 'yes' && $user->rights->facture->paiement)
633  {
634  $object->fetch($id);
635  $result = $object->set_paid($user);
636  if ($result<0) setEventMessages($object->error, $object->errors, 'errors');
637  } // Classif "paid partialy"
638  else if ($action == 'confirm_paid_partially' && $confirm == 'yes' && $user->rights->facture->paiement)
639  {
640  $object->fetch($id);
641  $close_code = $_POST["close_code"];
642  $close_note = $_POST["close_note"];
643  if ($close_code) {
644  $result = $object->set_paid($user, $close_code, $close_note);
645  if ($result<0) setEventMessages($object->error, $object->errors, 'errors');
646  } else {
647  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Reason")), null, 'errors');
648  }
649  } // Classify "abandoned"
650  else if ($action == 'confirm_canceled' && $confirm == 'yes') {
651  $object->fetch($id);
652  $close_code = $_POST["close_code"];
653  $close_note = $_POST["close_note"];
654  if ($close_code) {
655  $result = $object->set_canceled($user, $close_code, $close_note);
656  if ($result<0) setEventMessages($object->error, $object->errors, 'errors');
657  } else {
658  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Reason")), null, 'errors');
659  }
660  }
661 
662  // Convertir en reduc
663  else if ($action == 'confirm_converttoreduc' && $confirm == 'yes' && $user->rights->facture->creer)
664  {
665  $object->fetch($id);
666  $object->fetch_thirdparty();
667  //$object->fetch_lines(); // Already done into fetch
668 
669  // Check if there is already a discount (protection to avoid duplicate creation when resubmit post)
670  $discountcheck=new DiscountAbsolute($db);
671  $result=$discountcheck->fetch(0,$object->id);
672 
673  $canconvert=0;
674  if ($object->type == Facture::TYPE_DEPOSIT && empty($discountcheck->id)) $canconvert=1; // we can convert deposit into discount if deposit is payed (completely, partially or not at all) and not already converted (see real condition into condition used to show button converttoreduc)
675  if (($object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_STANDARD) && $object->paye == 0 && empty($discountcheck->id)) $canconvert=1; // we can convert credit note into discount if credit note is not payed back and not already converted and amount of payment is 0 (see real condition into condition used to show button converttoreduc)
676  if ($canconvert)
677  {
678  $db->begin();
679 
680  $amount_ht = $amount_tva = $amount_ttc = array();
681 
682  // Loop on each vat rate
683  $i = 0;
684  foreach ($object->lines as $line)
685  {
686  if ($line->total_ht!=0)
687  { // no need to create discount if amount is null
688  $amount_ht[$line->tva_tx] += $line->total_ht;
689  $amount_tva[$line->tva_tx] += $line->total_tva;
690  $amount_ttc[$line->tva_tx] += $line->total_ttc;
691  $i ++;
692  }
693  }
694 
695  // Insert one discount by VAT rate category
696  $discount = new DiscountAbsolute($db);
697  if ($object->type == Facture::TYPE_CREDIT_NOTE)
698  $discount->description = '(CREDIT_NOTE)';
699  elseif ($object->type == Facture::TYPE_DEPOSIT)
700  $discount->description = '(DEPOSIT)';
701  elseif ($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT || $object->type == Facture::TYPE_SITUATION)
702  $discount->description = '(EXCESS RECEIVED)';
703  else {
704  setEventMessages($langs->trans('CantConvertToReducAnInvoiceOfThisType'), null, 'errors');
705  }
706  $discount->fk_soc = $object->socid;
707  $discount->fk_facture_source = $object->id;
708 
709  $error = 0;
710 
711  if ($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT || $object->type == Facture::TYPE_SITUATION)
712  {
713  // If we're on a standard invoice, we have to get excess received to create a discount in TTC without VAT
714 
715  $sql = 'SELECT SUM(pf.amount) as total_paiements';
716  $sql.= ' FROM '.MAIN_DB_PREFIX.'paiement_facture as pf, '.MAIN_DB_PREFIX.'paiement as p';
717  $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as c ON p.fk_paiement = c.id AND c.entity IN (' . getEntity('c_paiement') . ')';
718  $sql.= ' WHERE pf.fk_facture = '.$object->id;
719  $sql.= ' AND pf.fk_paiement = p.rowid';
720  $sql.= ' AND p.entity IN (' . getEntity('facture').')';
721  $sql.= ' ORDER BY p.datep, p.tms';
722 
723  $resql = $db->query($sql);
724  if (! $resql) dol_print_error($db);
725 
726  $res = $db->fetch_object($resql);
727  $total_paiements = $res->total_paiements;
728 
729  $discount->amount_ht = $discount->amount_ttc = $total_paiements - $object->total_ttc;
730  $discount->amount_tva = 0;
731  $discount->tva_tx = 0;
732 
733  $result = $discount->create($user);
734  if ($result < 0)
735  {
736  $error++;
737  }
738 
739  }
740  if ($object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_DEPOSIT)
741  {
742  foreach ($amount_ht as $tva_tx => $xxx)
743  {
744  $discount->amount_ht = abs($amount_ht[$tva_tx]);
745  $discount->amount_tva = abs($amount_tva[$tva_tx]);
746  $discount->amount_ttc = abs($amount_ttc[$tva_tx]);
747  $discount->tva_tx = abs($tva_tx);
748 
749  $result = $discount->create($user);
750  if ($result < 0)
751  {
752  $error++;
753  break;
754  }
755  }
756 
757  }
758 
759  if (empty($error))
760  {
761  if($object->type != Facture::TYPE_DEPOSIT) {
762  // Classe facture
763  $result = $object->set_paid($user);
764  if ($result >= 0)
765  {
766  $db->commit();
767  }
768  else
769  {
770  setEventMessages($object->error, $object->errors, 'errors');
771  $db->rollback();
772  }
773  } else {
774  $db->commit();
775  }
776  }
777  else
778  {
779  setEventMessages($discount->error, $discount->errors, 'errors');
780  $db->rollback();
781  }
782  }
783  }
784 
785  // Delete payment
786  elseif ($action == 'confirm_delete_paiement' && $confirm == 'yes' && $user->rights->facture->creer)
787  {
788  $object->fetch($id);
789  if ($object->statut == Facture::STATUS_VALIDATED && $object->paye == 0)
790  {
791  $paiement = new Paiement($db);
792  $result=$paiement->fetch(GETPOST('paiement_id'));
793  if ($result > 0) {
794  $result=$paiement->delete(); // If fetch ok and found
795  header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
796  }
797  if ($result < 0) {
798  setEventMessages($paiement->error, $paiement->errors, 'errors');
799  }
800  }
801  }
802 
803  /*
804  * Insert new invoice in database
805  */
806  else if ($action == 'add' && $user->rights->facture->creer)
807  {
808  if ($socid > 0) $object->socid = GETPOST('socid', 'int');
809 
810  $db->begin();
811 
812  $error = 0;
813 
814  // Fill array 'array_options' with data from add form
815  $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
816  $ret = $extrafields->setOptionalsFromPost($extralabels, $object);
817  if ($ret < 0) $error++;
818 
819  // Replacement invoice
820  if ($_POST['type'] == Facture::TYPE_REPLACEMENT)
821  {
822  $dateinvoice = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
823  if (empty($dateinvoice))
824  {
825  $error++;
826  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
827  }
828 
829  if (! ($_POST['fac_replacement'] > 0)) {
830  $error ++;
831  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ReplaceInvoice")), null, 'errors');
832  }
833 
834  $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
835 
836  if (! $error) {
837  // This is a replacement invoice
838  $result = $object->fetch($_POST['fac_replacement']);
839  $object->fetch_thirdparty();
840 
841  $object->date = $dateinvoice;
842  $object->date_pointoftax = $date_pointoftax;
843  $object->note_public = trim($_POST['note_public']);
844  $object->note = trim($_POST['note']);
845  $object->ref_client = $_POST['ref_client'];
846  $object->ref_int = $_POST['ref_int'];
847  $object->modelpdf = $_POST['model'];
848  $object->fk_project = $_POST['projectid'];
849  $object->cond_reglement_id = $_POST['cond_reglement_id'];
850  $object->mode_reglement_id = $_POST['mode_reglement_id'];
851  $object->fk_account = GETPOST('fk_account', 'int');
852  $object->remise_absolue = $_POST['remise_absolue'];
853  $object->remise_percent = $_POST['remise_percent'];
854  $object->fk_incoterms = GETPOST('incoterm_id', 'int');
855  $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
856  $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
857  $object->multicurrency_tx = GETPOST('originmulticurrency_tx', 'int');
858 
859  // Proprietes particulieres a facture de remplacement
860  $object->fk_facture_source = $_POST['fac_replacement'];
861  $object->type = Facture::TYPE_REPLACEMENT;
862 
863  $id = $object->createFromCurrent($user);
864  if ($id <= 0) {
865  setEventMessages($object->error, $object->errors, 'errors');
866  }
867  }
868  }
869 
870  // Credit note invoice
871  if ($_POST['type'] == Facture::TYPE_CREDIT_NOTE)
872  {
873  $sourceinvoice = GETPOST('fac_avoir');
874  if (! ($sourceinvoice > 0) && empty($conf->global->INVOICE_CREDIT_NOTE_STANDALONE))
875  {
876  $error ++;
877  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CorrectInvoice")), null, 'errors');
878  }
879 
880  $dateinvoice = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
881  if (empty($dateinvoice))
882  {
883  $error ++;
884  setEventMessages($langs->trans("ErrorFieldRequired", $langs->trans("Date")), null, 'errors');
885  }
886 
887  $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
888 
889  if (! $error)
890  {
891  $object->socid = GETPOST('socid','int');
892  $object->number = $_POST['facnumber'];
893  $object->date = $dateinvoice;
894  $object->date_pointoftax = $date_pointoftax;
895  $object->note_public = trim($_POST['note_public']);
896  $object->note = trim($_POST['note']);
897  $object->ref_client = $_POST['ref_client'];
898  $object->ref_int = $_POST['ref_int'];
899  $object->modelpdf = $_POST['model'];
900  $object->fk_project = $_POST['projectid'];
901  $object->cond_reglement_id = 0;
902  $object->mode_reglement_id = $_POST['mode_reglement_id'];
903  $object->fk_account = GETPOST('fk_account', 'int');
904  $object->remise_absolue = $_POST['remise_absolue'];
905  $object->remise_percent = $_POST['remise_percent'];
906  $object->fk_incoterms = GETPOST('incoterm_id', 'int');
907  $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
908  $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
909  $object->multicurrency_tx = GETPOST('originmulticurrency_tx', 'int');
910 
911  // Proprietes particulieres a facture avoir
912  $object->fk_facture_source = $sourceinvoice > 0 ? $sourceinvoice : '';
913  $object->type = Facture::TYPE_CREDIT_NOTE;
914 
915  $id = $object->create($user);
916 
917  if (GETPOST('invoiceAvoirWithLines', 'int')==1 && $id>0)
918  {
919  $facture_source = new Facture($db); // fetch origin object
920  if ($facture_source->fetch($object->fk_facture_source)>0)
921  {
922  $fk_parent_line = 0;
923 
924  foreach($facture_source->lines as $line)
925  {
926  // Reset fk_parent_line for no child products and special product
927  if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
928  $fk_parent_line = 0;
929  }
930 
931  $line->fk_facture = $object->id;
932  $line->fk_parent_line = $fk_parent_line;
933 
934  $line->subprice = -$line->subprice; // invert price for object
935  $line->pa_ht = $line->pa_ht; // we choosed to have buy/cost price always positive, so no revert of sign here
936  $line->total_ht = -$line->total_ht;
937  $line->total_tva = -$line->total_tva;
938  $line->total_ttc = -$line->total_ttc;
939  $line->total_localtax1 = -$line->total_localtax1;
940  $line->total_localtax2 = -$line->total_localtax2;
941 
942  $line->multicurrency_subprice = -$line->multicurrency_subprice;
943  $line->multicurrency_total_ht = -$line->multicurrency_total_ht;
944  $line->multicurrency_total_tva = -$line->multicurrency_total_tva;
945  $line->multicurrency_total_ttc = -$line->multicurrency_total_ttc;
946 
947  $result = $line->insert(0, 1); // When creating credit note with same lines than source, we must ignore error if discount alreayd linked
948 
949  $object->lines[] = $line; // insert new line in current object
950 
951  // Defined the new fk_parent_line
952  if ($result > 0 && $line->product_type == 9) {
953  $fk_parent_line = $result;
954  }
955  }
956 
957  $object->update_price(1);
958  }
959 
960  }
961 
962  if(GETPOST('invoiceAvoirWithPaymentRestAmount', 'int')==1 && $id>0)
963  {
964  $facture_source = new Facture($db); // fetch origin object if not previously defined
965  if ($facture_source->fetch($object->fk_facture_source)>0)
966  {
967  $totalpaye = $facture_source->getSommePaiement();
968  $totalcreditnotes = $facture_source->getSumCreditNotesUsed();
969  $totaldeposits = $facture_source->getSumDepositsUsed();
970  $remain_to_pay = abs($facture_source->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits);
971 
972  $object->addline($langs->trans('invoiceAvoirLineWithPaymentRestAmount'),$remain_to_pay,1,0,0,0,0,0,'','','TTC');
973  }
974  }
975  }
976  }
977 
978  // Standard invoice or Deposit invoice, created from a Predefined template invoice
979  if (($_POST['type'] == Facture::TYPE_STANDARD || $_POST['type'] == Facture::TYPE_DEPOSIT) && GETPOST('fac_rec') > 0)
980  {
981  $dateinvoice = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
982  if (empty($dateinvoice))
983  {
984  $error++;
985  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
986  }
987 
988  $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
989 
990  if (! $error)
991  {
992  $object->socid = GETPOST('socid','int');
993  $object->type = $_POST['type'];
994  $object->number = $_POST['facnumber'];
995  $object->date = $dateinvoice;
996  $object->date_pointoftax = $date_pointoftax;
997  $object->note_public = trim($_POST['note_public']);
998  $object->note_private = trim($_POST['note_private']);
999  $object->ref_client = $_POST['ref_client'];
1000  $object->ref_int = $_POST['ref_int'];
1001  $object->modelpdf = $_POST['model'];
1002  $object->fk_project = $_POST['projectid'];
1003  $object->cond_reglement_id = ($_POST['type'] == 3?1:$_POST['cond_reglement_id']);
1004  $object->mode_reglement_id = $_POST['mode_reglement_id'];
1005  $object->fk_account = GETPOST('fk_account', 'int');
1006  $object->amount = $_POST['amount'];
1007  $object->remise_absolue = $_POST['remise_absolue'];
1008  $object->remise_percent = $_POST['remise_percent'];
1009  $object->fk_incoterms = GETPOST('incoterm_id', 'int');
1010  $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
1011  $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
1012  $object->multicurrency_tx = GETPOST('originmulticurrency_tx', 'int');
1013 
1014  // Source facture
1015  $object->fac_rec = GETPOST('fac_rec');
1016 
1017  $id = $object->create($user); // This include recopy of links from recurring invoice
1018  }
1019  }
1020 
1021  // Standard or deposit or proforma invoice, not from a Predefined template invoice
1022  if (($_POST['type'] == Facture::TYPE_STANDARD || $_POST['type'] == Facture::TYPE_DEPOSIT || $_POST['type'] == Facture::TYPE_PROFORMA || ($_POST['type'] == Facture::TYPE_SITUATION && empty($_POST['situations']))) && GETPOST('fac_rec') <= 0)
1023  {
1024  if (GETPOST('socid', 'int') < 1)
1025  {
1026  $error ++;
1027  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Customer")), null, 'errors');
1028  }
1029 
1030  $dateinvoice = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
1031  if (empty($dateinvoice))
1032  {
1033  $error++;
1034  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
1035  }
1036 
1037  $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
1038 
1039  if (! $error)
1040  {
1041  // Si facture standard
1042  $object->socid = GETPOST('socid','int');
1043  $object->type = GETPOST('type');
1044  $object->number = $_POST['facnumber'];
1045  $object->date = $dateinvoice;
1046  $object->date_pointoftax = $date_pointoftax;
1047  $object->note_public = trim($_POST['note_public']);
1048  $object->note_private = trim($_POST['note_private']);
1049  $object->ref_client = $_POST['ref_client'];
1050  $object->ref_int = $_POST['ref_int'];
1051  $object->modelpdf = $_POST['model'];
1052  $object->fk_project = $_POST['projectid'];
1053  $object->cond_reglement_id = ($_POST['type'] == 3?1:$_POST['cond_reglement_id']);
1054  $object->mode_reglement_id = $_POST['mode_reglement_id'];
1055  $object->fk_account = GETPOST('fk_account', 'int');
1056  $object->amount = $_POST['amount'];
1057  $object->remise_absolue = $_POST['remise_absolue'];
1058  $object->remise_percent = $_POST['remise_percent'];
1059  $object->fk_incoterms = GETPOST('incoterm_id', 'int');
1060  $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
1061  $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
1062  $object->multicurrency_tx = GETPOST('originmulticurrency_tx', 'int');
1063 
1064  if (GETPOST('type') == Facture::TYPE_SITUATION)
1065  {
1066  $object->situation_counter = 1;
1067  $object->situation_final = 0;
1068  $object->situation_cycle_ref = $object->newCycle();
1069  }
1070 
1071  $object->fetch_thirdparty();
1072 
1073  // If creation from another object of another module (Example: origin=propal, originid=1)
1074  if (! empty($origin) && ! empty($originid))
1075  {
1076  // Parse element/subelement (ex: project_task)
1077  $element = $subelement = $origin;
1078  if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
1079  $element = $regs [1];
1080  $subelement = $regs [2];
1081  }
1082 
1083  // For compatibility
1084  if ($element == 'order') {
1085  $element = $subelement = 'commande';
1086  }
1087  if ($element == 'propal') {
1088  $element = 'comm/propal';
1089  $subelement = 'propal';
1090  }
1091  if ($element == 'contract') {
1092  $element = $subelement = 'contrat';
1093  }
1094  if ($element == 'inter') {
1095  $element = $subelement = 'ficheinter';
1096  }
1097  if ($element == 'shipping') {
1098  $element = $subelement = 'expedition';
1099  }
1100 
1101  $object->origin = $origin;
1102  $object->origin_id = $originid;
1103 
1104  // Possibility to add external linked objects with hooks
1105  $object->linked_objects[$object->origin] = $object->origin_id;
1106  // link with order if it is a shipping invoice
1107  if ($object->origin == 'shipping')
1108  {
1109  require_once DOL_DOCUMENT_ROOT . '/expedition/class/expedition.class.php';
1110  $exp = new Expedition($db);
1111  $exp->fetch($object->origin_id);
1112  $exp->fetchObjectLinked();
1113  if (is_array($exp->linkedObjectsIds['commande']) && count($exp->linkedObjectsIds['commande']) > 0) {
1114  foreach ($exp->linkedObjectsIds['commande'] as $key => $value){
1115  $object->linked_objects['commande'] = $value;
1116  }
1117  }
1118  }
1119 
1120  if (is_array($_POST['other_linked_objects']) && ! empty($_POST['other_linked_objects']))
1121  {
1122  $object->linked_objects = array_merge($object->linked_objects, $_POST['other_linked_objects']);
1123  }
1124 
1125  $id = $object->create($user); // This include class to add_object_linked() and add add_contact()
1126 
1127  if ($id > 0)
1128  {
1129  dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
1130 
1131  $classname = ucfirst($subelement);
1132  $srcobject = new $classname($db);
1133 
1134  dol_syslog("Try to find source object origin=" . $object->origin . " originid=" . $object->origin_id . " to add lines or deposit lines");
1135  $result = $srcobject->fetch($object->origin_id);
1136 
1137  // If deposit invoice
1138  if ($_POST['type'] == Facture::TYPE_DEPOSIT)
1139  {
1140  $typeamount = GETPOST('typedeposit', 'alpha');
1141  $valuedeposit = GETPOST('valuedeposit', 'int');
1142 
1143  $amountdeposit = array();
1144  if (!empty($conf->global->MAIN_DEPOSIT_MULTI_TVA))
1145  {
1146  if ($typeamount == 'amount') $amount = $valuedeposit;
1147  else $amount = $srcobject->total_ttc * ($valuedeposit / 100);
1148 
1149  $TTotalByTva = array();
1150  foreach ($srcobject->lines as &$line)
1151  {
1152  if(! empty($line->special_code)) continue;
1153  $TTotalByTva[$line->tva_tx] += $line->total_ttc ;
1154  }
1155 
1156  $amount_to_diff = 0;
1157  foreach ($TTotalByTva as $tva => &$total)
1158  {
1159  $coef = $total / $srcobject->total_ttc; // Calc coef
1160  $am = $amount * $coef;
1161  $amount_ttc_diff += $am;
1162  $amountdeposit[$tva] += $am / (1 + $tva / 100); // Convert into HT for the addline
1163  }
1164  }
1165  else
1166  {
1167  if ($typeamount == 'amount')
1168  {
1169  $amountdeposit[0] = $valuedeposit;
1170  }
1171  else
1172  {
1173  if ($result > 0)
1174  {
1175  $totalamount = 0;
1176  $lines = $srcobject->lines;
1177  $numlines=count($lines);
1178  for ($i=0; $i<$numlines; $i++)
1179  {
1180  $qualified=1;
1181  if (empty($lines[$i]->qty)) $qualified=0; // We discard qty=0, it is an option
1182  if (! empty($lines[$i]->special_code)) $qualified=0; // We discard special_code (frais port, ecotaxe, option, ...)
1183  if ($qualified) $totalamount += $lines[$i]->total_ht; // Fixme : is it not for the customer ? Shouldn't we take total_ttc ?
1184  }
1185 
1186  if ($totalamount != 0) {
1187  if ($numlines > 0) $numlines = $numlines-1;
1188  $tva_tx = $lines[$numlines]->tva_tx;
1189  if (! empty($lines[$numlines]->vat_src_code) && ! preg_match('/\(/', $tva_tx)) $tva_tx .= ' ('.$lines[$numlines]->vat_src_code.')';
1190  $amountdeposit[$tva_tx] = ($totalamount * $valuedeposit) / 100;
1191  } else {
1192  $amountdeposit[0] = 0;
1193  }
1194  } else {
1195  setEventMessages($srcobject->error, $srcobject->errors, 'errors');
1196  $error ++;
1197  }
1198  }
1199 
1200  $amount_ttc_diff = $amountdeposit[0];
1201  }
1202 
1203  foreach ($amountdeposit as $tva => $amount)
1204  {
1205  $arraylist = array('amount' => 'FixAmount','variable' => 'VarAmount');
1206  $descline = $langs->trans('Deposit');
1207  $descline.= ' - '.$langs->trans($arraylist[$typeamount]);
1208  if ($typeamount=='amount') {
1209  $descline.= ' ('. price($valuedeposit, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)).')';
1210  } elseif ($typeamount=='variable') {
1211  $descline.= ' ('. $valuedeposit.'%)';
1212  }
1213  $descline.= ' - '.$srcobject->ref;
1214  $result = $object->addline(
1215  $descline,
1216  $amount, // subprice
1217  1, // quantity
1218  $tva, // vat rate
1219  0, // localtax1_tx
1220  0, // localtax2_tx
1221  (empty($conf->global->INVOICE_PRODUCTID_DEPOSIT)?0:$conf->global->INVOICE_PRODUCTID_DEPOSIT), // fk_product
1222  0, // remise_percent
1223  0, // date_start
1224  0, // date_end
1225  0,
1226  $lines[$i]->info_bits, // info_bits
1227  0,
1228  'HT',
1229  0,
1230  0, // product_type
1231  1,
1232  $lines[$i]->special_code,
1233  $object->origin,
1234  0,
1235  0,
1236  0,
1237  0
1238  //,$langs->trans('Deposit') //Deprecated
1239  );
1240  }
1241 
1242  $diff = $object->total_ttc - $amount_ttc_diff;
1243 
1244  if (!empty($conf->global->MAIN_DEPOSIT_MULTI_TVA) && $diff != 0)
1245  {
1246  $object->fetch_lines();
1247  $subprice_diff = $object->lines[0]->subprice - $diff / (1 + $object->lines[0]->tva_tx / 100);
1248  $object->updateline($object->lines[0]->id, $object->lines[0]->desc, $subprice_diff, $object->lines[0]->qty, $object->lines[0]->remise_percent, $object->lines[0]->date_start, $object->lines[0]->date_end, $object->lines[0]->tva_tx, 0, 0, 'HT', $object->lines[0]->info_bits, $object->lines[0]->product_type, 0, 0, 0, $object->lines[0]->pa_ht, $object->lines[0]->label, 0, array(), 100);
1249  }
1250 
1251  }
1252  else
1253  {
1254  if ($result > 0)
1255  {
1256  $lines = $srcobject->lines;
1257  if (empty($lines) && method_exists($srcobject, 'fetch_lines'))
1258  {
1259  $srcobject->fetch_lines();
1260  $lines = $srcobject->lines;
1261  }
1262 
1263  $fk_parent_line=0;
1264  $num=count($lines);
1265  for ($i=0;$i<$num;$i++)
1266  {
1267  // Don't add lines with qty 0 when coming from a shipment including all order lines
1268  if($srcobject->element == 'shipping' && $conf->global->SHIPMENT_GETS_ALL_ORDER_PRODUCTS && $lines[$i]->qty == 0) continue;
1269 
1270  $label=(! empty($lines[$i]->label)?$lines[$i]->label:'');
1271  $desc=(! empty($lines[$i]->desc)?$lines[$i]->desc:$lines[$i]->libelle);
1272  if ($object->situation_counter == 1) $lines[$i]->situation_percent = 0;
1273 
1274  if ($lines[$i]->subprice < 0)
1275  {
1276  // Negative line, we create a discount line
1277  $discount = new DiscountAbsolute($db);
1278  $discount->fk_soc = $object->socid;
1279  $discount->amount_ht = abs($lines[$i]->total_ht);
1280  $discount->amount_tva = abs($lines[$i]->total_tva);
1281  $discount->amount_ttc = abs($lines[$i]->total_ttc);
1282  $discount->tva_tx = $lines[$i]->tva_tx;
1283  $discount->fk_user = $user->id;
1284  $discount->description = $desc;
1285  $discountid = $discount->create($user);
1286  if ($discountid > 0) {
1287  $result = $object->insert_discount($discountid); // This include link_to_invoice
1288  } else {
1289  setEventMessages($discount->error, $discount->errors, 'errors');
1290  $error ++;
1291  break;
1292  }
1293  } else {
1294  // Positive line
1295  $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0);
1296 
1297  // Date start
1298  $date_start = false;
1299  if ($lines[$i]->date_debut_prevue)
1300  $date_start = $lines[$i]->date_debut_prevue;
1301  if ($lines[$i]->date_debut_reel)
1302  $date_start = $lines[$i]->date_debut_reel;
1303  if ($lines[$i]->date_start)
1304  $date_start = $lines[$i]->date_start;
1305 
1306  // Date end
1307  $date_end = false;
1308  if ($lines[$i]->date_fin_prevue)
1309  $date_end = $lines[$i]->date_fin_prevue;
1310  if ($lines[$i]->date_fin_reel)
1311  $date_end = $lines[$i]->date_fin_reel;
1312  if ($lines[$i]->date_end)
1313  $date_end = $lines[$i]->date_end;
1314 
1315  // Reset fk_parent_line for no child products and special product
1316  if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) {
1317  $fk_parent_line = 0;
1318  }
1319 
1320  // Extrafields
1321  if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && method_exists($lines[$i], 'fetch_optionals')) {
1322  $lines[$i]->fetch_optionals($lines[$i]->rowid);
1323  $array_options = $lines[$i]->array_options;
1324  }
1325 
1326  $tva_tx = $lines[$i]->tva_tx;
1327  if (! empty($lines[$i]->vat_src_code) && ! preg_match('/\(/', $tva_tx)) $tva_tx .= ' ('.$lines[$i]->vat_src_code.')';
1328 
1329  // View third's localtaxes for NOW and do not use value from origin.
1330  // TODO Is this really what we want ? Yes if source if template invoice but what if proposal or order ?
1331  $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty);
1332  $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty);
1333 
1334  $result = $object->addline($desc, $lines[$i]->subprice, $lines[$i]->qty, $tva_tx, $localtax1_tx, $localtax2_tx, $lines[$i]->fk_product, $lines[$i]->remise_percent, $date_start, $date_end, 0, $lines[$i]->info_bits, $lines[$i]->fk_remise_except, 'HT', 0, $product_type, $lines[$i]->rang, $lines[$i]->special_code, $object->origin, $lines[$i]->rowid, $fk_parent_line, $lines[$i]->fk_fournprice, $lines[$i]->pa_ht, $label, $array_options, $lines[$i]->situation_percent, $lines[$i]->fk_prev_id, $lines[$i]->fk_unit);
1335 
1336  if ($result > 0) {
1337  $lineid = $result;
1338  } else {
1339  $lineid = 0;
1340  $error ++;
1341  break;
1342  }
1343 
1344  // Defined the new fk_parent_line
1345  if ($result > 0 && $lines[$i]->product_type == 9) {
1346  $fk_parent_line = $result;
1347  }
1348  }
1349  }
1350  } else {
1351  setEventMessages($srcobject->error, $srcobject->errors, 'errors');
1352  $error ++;
1353  }
1354  }
1355 
1356  // Now we create same links to contact than the ones found on origin object
1357  /* Useless, already into the create
1358  if (! empty($conf->global->MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN))
1359  {
1360  $originforcontact = $object->origin;
1361  $originidforcontact = $object->origin_id;
1362  if ($originforcontact == 'shipping') // shipment and order share the same contacts. If creating from shipment we take data of order
1363  {
1364  $originforcontact=$srcobject->origin;
1365  $originidforcontact=$srcobject->origin_id;
1366  }
1367  $sqlcontact = "SELECT code, fk_socpeople FROM ".MAIN_DB_PREFIX."element_contact as ec, ".MAIN_DB_PREFIX."c_type_contact as ctc";
1368  $sqlcontact.= " WHERE element_id = ".$originidforcontact." AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$originforcontact."'";
1369 
1370  $resqlcontact = $db->query($sqlcontact);
1371  if ($resqlcontact)
1372  {
1373  while($objcontact = $db->fetch_object($resqlcontact))
1374  {
1375  //print $objcontact->code.'-'.$objcontact->fk_socpeople."\n";
1376  $object->add_contact($objcontact->fk_socpeople, $objcontact->code);
1377  }
1378  }
1379  else dol_print_error($resqlcontact);
1380  }*/
1381 
1382  // Hooks
1383  $parameters = array('objFrom' => $srcobject);
1384  $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been
1385  // modified by hook
1386  if ($reshook < 0)
1387  {
1388  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1389  $error++;
1390  }
1391 
1392  } else {
1393  setEventMessages($object->error, $object->errors, 'errors');
1394  $error++;
1395  }
1396  }
1397  else
1398  { // If some invoice's lines coming from page
1399  $id = $object->create($user);
1400 
1401  for ($i = 1; $i <= $NBLINES; $i ++) {
1402  if ($_POST['idprod' . $i]) {
1403  $product = new Product($db);
1404  $product->fetch($_POST['idprod' . $i]);
1405  $startday = dol_mktime(12, 0, 0, $_POST['date_start' . $i . 'month'], $_POST['date_start' . $i . 'day'], $_POST['date_start' . $i . 'year']);
1406  $endday = dol_mktime(12, 0, 0, $_POST['date_end' . $i . 'month'], $_POST['date_end' . $i . 'day'], $_POST['date_end' . $i . 'year']);
1407  $result = $object->addline($product->description, $product->price, $_POST['qty' . $i], $product->tva_tx, $product->localtax1_tx, $product->localtax2_tx, $_POST['idprod' . $i], $_POST['remise_percent' . $i], $startday, $endday, 0, 0, '', $product->price_base_type, $product->price_ttc, $product->type, -1, 0, '', 0, 0, null, 0, '', 0, 100, '', $product->fk_unit);
1408  }
1409  }
1410  }
1411  }
1412  }
1413 
1414  if (GETPOST('type') == Facture::TYPE_SITUATION && (!empty($_POST['situations'])))
1415  {
1416  $datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
1417  if (empty($datefacture)) {
1418  $error++;
1419  $mesg = '<div class="error">' . $langs->trans("ErrorFieldRequired", $langs->trans("Date")) . '</div>';
1420  }
1421 
1422  $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
1423 
1424  if (!($_POST['situations'] > 0)) {
1425  $error++;
1426  $mesg = '<div class="error">' . $langs->trans("ErrorFieldRequired", $langs->trans("InvoiceSituation")) . '</div>';
1427  }
1428 
1429  if (!$error) {
1430  $result = $object->fetch($_POST['situations']);
1431  $object->fk_facture_source = $_POST['situations'];
1432  $object->type = Facture::TYPE_SITUATION;
1433 
1434  if (!empty($origin) && !empty($originid))
1435  {
1436  $object->origin = $origin;
1437  $object->origin_id = $originid;
1438 
1439  foreach ($object->lines as &$line)
1440  {
1441  $line->origin = $object->origin;
1442  $line->origin_id = $line->id;
1443  $line->fetch_optionals($line->id);
1444  }
1445  }
1446 
1447  $object->fetch_thirdparty();
1448  $object->date = $datefacture;
1449  $object->date_pointoftax = $date_pointoftax;
1450  $object->note_public = trim($_POST['note_public']);
1451  $object->note = trim($_POST['note']);
1452  $object->ref_client = $_POST['ref_client'];
1453  $object->ref_int = $_POST['ref_int'];
1454  $object->modelpdf = $_POST['model'];
1455  $object->fk_project = $_POST['projectid'];
1456  $object->cond_reglement_id = $_POST['cond_reglement_id'];
1457  $object->mode_reglement_id = $_POST['mode_reglement_id'];
1458  $object->remise_absolue = $_POST['remise_absolue'];
1459  $object->remise_percent = $_POST['remise_percent'];
1460 
1461  // Proprietes particulieres a facture de remplacement
1462 
1463  $object->situation_counter = $object->situation_counter + 1;
1464  $id = $object->createFromCurrent($user);
1465  if ($id <= 0)
1466  {
1467  $mesg = $object->error;
1468  }
1469  else
1470  {
1471  $nextSituationInvoice = new Facture($db);
1472  $nextSituationInvoice->fetch($id);
1473  // create extrafields with data from create form
1474  $extralabels = $extrafields->fetch_name_optionals_label($nextSituationInvoice->table_element);
1475  $ret = $extrafields->setOptionalsFromPost($extralabels, $nextSituationInvoice);
1476  if ($ret > 0) {
1477  $nextSituationInvoice->insertExtraFields();
1478  }
1479  }
1480  }
1481  }
1482 
1483  // End of object creation, we show it
1484  if ($id > 0 && ! $error)
1485  {
1486  $db->commit();
1487 
1488  // Define output language
1489  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE) && count($object->lines))
1490  {
1491  $outputlangs = $langs;
1492  $newlang = '';
1493  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
1494  if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
1495  if (! empty($newlang)) {
1496  $outputlangs = new Translate("", $conf);
1497  $outputlangs->setDefaultLang($newlang);
1498  }
1499  $model=$object->modelpdf;
1500  $ret = $object->fetch($id); // Reload to get new records
1501 
1502  $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1503  if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
1504  }
1505 
1506  header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id);
1507  exit();
1508  }
1509  else
1510  {
1511  $db->rollback();
1512  $action = 'create';
1513  $_GET["origin"] = $_POST["origin"];
1514  $_GET["originid"] = $_POST["originid"];
1515  setEventMessages($object->error, $object->errors, 'errors');
1516  }
1517  }
1518 
1519  // Add a new line
1520  else if ($action == 'addline' && $user->rights->facture->creer)
1521  {
1522  $langs->load('errors');
1523  $error = 0;
1524 
1525  // Set if we used free entry or predefined product
1526  $predef='';
1527  $product_desc=(GETPOST('dp_desc')?GETPOST('dp_desc'):'');
1528  $price_ht = GETPOST('price_ht');
1529  $price_ht_devise = GETPOST('multicurrency_price_ht');
1530  $prod_entry_mode = GETPOST('prod_entry_mode','alpha');
1531  if ($prod_entry_mode == 'free')
1532  {
1533  $idprod=0;
1534  $tva_tx = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
1535  }
1536  else
1537  {
1538  $idprod=GETPOST('idprod', 'int');
1539  $tva_tx = '';
1540  }
1541 
1542  $qty = GETPOST('qty' . $predef);
1543  $remise_percent = GETPOST('remise_percent' . $predef);
1544 
1545  // Extrafields
1546  $extrafieldsline = new ExtraFields($db);
1547  $extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
1548  $array_options = $extrafieldsline->getOptionalsFromPost($extralabelsline, $predef);
1549  // Unset extrafield
1550  if (is_array($extralabelsline)) {
1551  // Get extra fields
1552  foreach ($extralabelsline as $key => $value) {
1553  unset($_POST["options_" . $key . $predef]);
1554  }
1555  }
1556 
1557  if (empty($idprod) && ($price_ht < 0) && ($qty < 0)) {
1558  setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1559  $error ++;
1560  }
1561  if (!$prod_entry_mode)
1562  {
1563  if (GETPOST('type') < 0 && ! GETPOST('search_idprod'))
1564  {
1565  setEventMessages($langs->trans('ErrorChooseBetweenFreeEntryOrPredefinedProduct'), null, 'errors');
1566  $error ++;
1567  }
1568  }
1569  if ($prod_entry_mode == 'free' && empty($idprod) && GETPOST('type') < 0) {
1570  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
1571  $error ++;
1572  }
1573  if ($prod_entry_mode == 'free' && empty($idprod) && (! ($price_ht >= 0) || $price_ht == '') && $price_ht_devise == '') // Unit price can be 0 but not ''
1574  {
1575  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
1576  $error ++;
1577  }
1578  if ($qty == '') {
1579  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1580  $error ++;
1581  }
1582  if ($prod_entry_mode == 'free' && empty($idprod) && empty($product_desc)) {
1583  setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
1584  $error ++;
1585  }
1586  if ($qty < 0) {
1587  $langs->load("errors");
1588  setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
1589  $error ++;
1590  }
1591 
1592  if (!$error && !empty($conf->variants->enabled) && $prod_entry_mode != 'free') {
1593  if ($combinations = GETPOST('combinations', 'array')) {
1594  //Check if there is a product with the given combination
1595  $prodcomb = new ProductCombination($db);
1596 
1597  if ($res = $prodcomb->fetchByProductCombination2ValuePairs($idprod, $combinations)) {
1598  $idprod = $res->fk_product_child;
1599  } else {
1600  setEventMessage($langs->trans('ErrorProductCombinationNotFound'), 'errors');
1601  $error ++;
1602  }
1603  }
1604  }
1605 
1606  if (! $error && ($qty >= 0) && (! empty($product_desc) || ! empty($idprod))) {
1607 
1608  $ret = $object->fetch($id);
1609  if ($ret < 0) {
1610  dol_print_error($db, $object->error);
1611  exit();
1612  }
1613  $ret = $object->fetch_thirdparty();
1614 
1615  // Clean parameters
1616  $date_start = dol_mktime(GETPOST('date_start' . $predef . 'hour'), GETPOST('date_start' . $predef . 'min'), GETPOST('date_start' . $predef . 'sec'), GETPOST('date_start' . $predef . 'month'), GETPOST('date_start' . $predef . 'day'), GETPOST('date_start' . $predef . 'year'));
1617  $date_end = dol_mktime(GETPOST('date_end' . $predef . 'hour'), GETPOST('date_end' . $predef . 'min'), GETPOST('date_end' . $predef . 'sec'), GETPOST('date_end' . $predef . 'month'), GETPOST('date_end' . $predef . 'day'), GETPOST('date_end' . $predef . 'year'));
1618  $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT');
1619 
1620  // Define special_code for special lines
1621  $special_code = 0;
1622  // if (empty($_POST['qty'])) $special_code=3; // Options should not exists on invoices
1623 
1624  // Ecrase $pu par celui du produit
1625  // Ecrase $desc par celui du produit
1626  // Ecrase $tva_tx par celui du produit
1627  // Ecrase $base_price_type par celui du produit
1628  // Replaces $fk_unit with the product's
1629  if (! empty($idprod))
1630  {
1631  $prod = new Product($db);
1632  $prod->fetch($idprod);
1633 
1634  $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
1635 
1636  // Update if prices fields are defined
1637  $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
1638  $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
1639  if (empty($tva_tx)) $tva_npr=0;
1640 
1641  $pu_ht = $prod->price;
1642  $pu_ttc = $prod->price_ttc;
1643  $price_min = $prod->price_min;
1644  $price_base_type = $prod->price_base_type;
1645 
1646  // If price per segment
1647  if (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($object->thirdparty->price_level))
1648  {
1649  $pu_ht = $prod->multiprices[$object->thirdparty->price_level];
1650  $pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
1651  $price_min = $prod->multiprices_min[$object->thirdparty->price_level];
1652  $price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
1653  if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) // using this option is a bug. kept for backward compatibility
1654  {
1655  if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) $tva_tx=$prod->multiprices_tva_tx[$object->thirdparty->price_level];
1656  if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) $tva_npr=$prod->multiprices_recuperableonly[$object->thirdparty->price_level];
1657  if (empty($tva_tx)) $tva_npr=0;
1658  }
1659  }
1660  // If price per customer
1661  elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES))
1662  {
1663  require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
1664 
1665  $prodcustprice = new Productcustomerprice($db);
1666 
1667  $filter = array('t.fk_product' => $prod->id,'t.fk_soc' => $object->thirdparty->id);
1668 
1669  $result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
1670  if ($result) {
1671  if (count($prodcustprice->lines) > 0) {
1672  $pu_ht = price($prodcustprice->lines[0]->price);
1673  $pu_ttc = price($prodcustprice->lines[0]->price_ttc);
1674  $price_base_type = $prodcustprice->lines[0]->price_base_type;
1675  $tva_tx = $prodcustprice->lines[0]->tva_tx;
1676  if ($prodcustprice->lines[0]->default_vat_code && ! preg_match('/\(.*\)/', $tva_tx)) $tva_tx.= ' ('.$prodcustprice->lines[0]->default_vat_code.')';
1677  $tva_npr = $prodcustprice->lines[0]->recuperableonly;
1678  if (empty($tva_tx)) $tva_npr=0;
1679  }
1680  }
1681  }
1682  // If price per quantity
1683  elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))
1684  {
1685  if ($prod->prices_by_qty[0]) // yes, this product has some prices per quantity
1686  {
1687  // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
1688  $pqp = GETPOST('pbq','int');
1689 
1690  // Search price into product_price_by_qty from $prod->id
1691  foreach($prod->prices_by_qty_list[0] as $priceforthequantityarray)
1692  {
1693  if ($priceforthequantityarray['rowid'] != $pqp) continue;
1694  // We found the price
1695  if ($priceforthequantityarray['price_base_type'] == 'HT')
1696  {
1697  $pu_ht = $priceforthequantityarray['unitprice'];
1698  }
1699  else
1700  {
1701  $pu_ttc = $priceforthequantityarray['unitprice'];
1702  }
1703  // Note: the remise_percent or price by qty is used to set data on form, so we will use value from POST.
1704  break;
1705  }
1706  }
1707  }
1708  // If price per quantity and customer
1709  elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES))
1710  {
1711  // TODO Same than PRODUIT_CUSTOMER_PRICES_BY_QTY but using $object->thirdparty->price_level
1712  }
1713 
1714  $tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx));
1715  $tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx));
1716 
1717  // if price ht was forced (ie: from gui when calculated by margin rate and cost price). TODO Why this ?
1718  if (! empty($price_ht))
1719  {
1720  $pu_ht = price2num($price_ht, 'MU');
1721  $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
1722  }
1723  // On reevalue prix selon taux tva car taux tva transaction peut etre different
1724  // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
1725  elseif ($tmpvat != $tmpprodvat)
1726  {
1727  if ($price_base_type != 'HT')
1728  {
1729  $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
1730  }
1731  else
1732  {
1733  $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
1734  }
1735  }
1736 
1737  $desc = '';
1738 
1739  // Define output language
1740  if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
1741  $outputlangs = $langs;
1742  $newlang = '';
1743  if (empty($newlang) && GETPOST('lang_id','aZ09'))
1744  $newlang = GETPOST('lang_id','aZ09');
1745  if (empty($newlang))
1746  $newlang = $object->thirdparty->default_lang;
1747  if (! empty($newlang)) {
1748  $outputlangs = new Translate("", $conf);
1749  $outputlangs->setDefaultLang($newlang);
1750  }
1751 
1752  $desc = (! empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
1753  } else {
1754  $desc = $prod->description;
1755  }
1756 
1757  $desc = dol_concatdesc($desc, $product_desc);
1758 
1759  // Add custom code and origin country into description
1760  if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (! empty($prod->customcode) || ! empty($prod->country_code))) {
1761  $tmptxt = '(';
1762  // Define output language
1763  if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
1764  $outputlangs = $langs;
1765  $newlang = '';
1766  if (empty($newlang) && GETPOST('lang_id','alpha'))
1767  $newlang = GETPOST('lang_id','alpha');
1768  if (empty($newlang))
1769  $newlang = $object->thirdparty->default_lang;
1770  if (! empty($newlang)) {
1771  $outputlangs = new Translate("", $conf);
1772  $outputlangs->setDefaultLang($newlang);
1773  }
1774  if (! empty($prod->customcode))
1775  $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
1776  if (! empty($prod->customcode) && ! empty($prod->country_code))
1777  $tmptxt .= ' - ';
1778  if (! empty($prod->country_code))
1779  $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $outputlangs, 0);
1780  } else {
1781  if (! empty($prod->customcode))
1782  $tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
1783  if (! empty($prod->customcode) && ! empty($prod->country_code))
1784  $tmptxt .= ' - ';
1785  if (! empty($prod->country_code))
1786  $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
1787  }
1788  $tmptxt .= ')';
1789  $desc = dol_concatdesc($desc, $tmptxt);
1790  }
1791 
1792  $type = $prod->type;
1793  $fk_unit = $prod->fk_unit;
1794  } else {
1795  $pu_ht = price2num($price_ht, 'MU');
1796  $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
1797  $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
1798  $tva_tx = str_replace('*', '', $tva_tx);
1799  if (empty($tva_tx)) $tva_npr=0;
1800  $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1801  $desc = $product_desc;
1802  $type = GETPOST('type');
1803  $fk_unit= GETPOST('units', 'alpha');
1804  $pu_ht_devise = price2num($price_ht_devise, 'MU');
1805  }
1806 
1807  // Margin
1808  $fournprice = price2num(GETPOST('fournprice' . $predef) ? GETPOST('fournprice' . $predef) : '');
1809  $buyingprice = price2num(GETPOST('buying_price' . $predef) != '' ? GETPOST('buying_price' . $predef) : ''); // If buying_price is '0', we must keep this value
1810 
1811  // Local Taxes
1812  $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $mysoc, $tva_npr);
1813  $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $mysoc, $tva_npr);
1814 
1815  $info_bits = 0;
1816  if ($tva_npr)
1817  $info_bits |= 0x01;
1818 
1819  if (! empty($price_min) && (price2num($pu_ht) * (1 - price2num($remise_percent) / 100) < price2num($price_min))) {
1820  $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency));
1821  setEventMessages($mesg, null, 'errors');
1822  } else {
1823  // Insert line
1824  $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $date_start, $date_end, 0, $info_bits, '', $price_base_type, $pu_ttc, $type, - 1, $special_code, '', 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, $_POST['progress'], '', $fk_unit, $pu_ht_devise);
1825 
1826  if ($result > 0)
1827  {
1828  // Define output language
1829  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
1830  {
1831  $outputlangs = $langs;
1832  $newlang = '';
1833  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
1834  if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
1835  if (! empty($newlang)) {
1836  $outputlangs = new Translate("", $conf);
1837  $outputlangs->setDefaultLang($newlang);
1838  }
1839  $model=$object->modelpdf;
1840  $ret = $object->fetch($id); // Reload to get new records
1841 
1842  $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
1843  if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
1844  }
1845 
1846  unset($_POST['prod_entry_mode']);
1847 
1848  unset($_POST['qty']);
1849  unset($_POST['type']);
1850  unset($_POST['remise_percent']);
1851  unset($_POST['price_ht']);
1852  unset($_POST['multicurrency_price_ht']);
1853  unset($_POST['price_ttc']);
1854  unset($_POST['tva_tx']);
1855  unset($_POST['product_ref']);
1856  unset($_POST['product_label']);
1857  unset($_POST['product_desc']);
1858  unset($_POST['fournprice']);
1859  unset($_POST['buying_price']);
1860  unset($_POST['np_marginRate']);
1861  unset($_POST['np_markRate']);
1862  unset($_POST['dp_desc']);
1863  unset($_POST['idprod']);
1864  unset($_POST['units']);
1865 
1866  unset($_POST['date_starthour']);
1867  unset($_POST['date_startmin']);
1868  unset($_POST['date_startsec']);
1869  unset($_POST['date_startday']);
1870  unset($_POST['date_startmonth']);
1871  unset($_POST['date_startyear']);
1872  unset($_POST['date_endhour']);
1873  unset($_POST['date_endmin']);
1874  unset($_POST['date_endsec']);
1875  unset($_POST['date_endday']);
1876  unset($_POST['date_endmonth']);
1877  unset($_POST['date_endyear']);
1878 
1879  unset($_POST['situations']);
1880  unset($_POST['progress']);
1881  } else {
1882  setEventMessages($object->error, $object->errors, 'errors');
1883  }
1884 
1885  $action = '';
1886  }
1887  }
1888  }
1889 
1890  elseif ($action == 'updateligne' && $user->rights->facture->creer && ! GETPOST('cancel','alpha'))
1891  {
1892  if (! $object->fetch($id) > 0) dol_print_error($db);
1893  $object->fetch_thirdparty();
1894 
1895  // Clean parameters
1896  $date_start = '';
1897  $date_end = '';
1898  $date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear'));
1899  $date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear'));
1900  $description = dol_htmlcleanlastbr(GETPOST('product_desc','none') ? GETPOST('product_desc','none') : GETPOST('desc','none'));
1901  $pu_ht = GETPOST('price_ht');
1902  $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
1903  $qty = GETPOST('qty');
1904  $pu_ht_devise = GETPOST('multicurrency_subprice');
1905 
1906  // Define info_bits
1907  $info_bits = 0;
1908  if (preg_match('/\*/', $vat_rate))
1909  $info_bits |= 0x01;
1910 
1911  // Define vat_rate
1912  $vat_rate = str_replace('*', '', $vat_rate);
1913  $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty);
1914  $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty);
1915 
1916  // Add buying price
1917  $fournprice = price2num(GETPOST('fournprice') ? GETPOST('fournprice') : '');
1918  $buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : ''); // If buying_price is '0', we muste keep this value
1919 
1920  // Extrafields
1921  $extrafieldsline = new ExtraFields($db);
1922  $extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
1923  $array_options = $extrafieldsline->getOptionalsFromPost($extralabelsline);
1924  // Unset extrafield
1925  if (is_array($extralabelsline)) {
1926  // Get extra fields
1927  foreach ($extralabelsline as $key => $value) {
1928  unset($_POST["options_" . $key]);
1929  }
1930  }
1931 
1932  // Define special_code for special lines
1933  $special_code=GETPOST('special_code');
1934  if (! GETPOST('qty')) $special_code=3;
1935 
1936  $line = new FactureLigne($db);
1937  $line->fetch(GETPOST('lineid'));
1938  $percent = $line->get_prev_progress($object->id);
1939 
1940  if (GETPOST('progress') < $percent)
1941  {
1942  $mesg = '<div class="warning">' . $langs->trans("CantBeLessThanMinPercent") . '</div>';
1943  setEventMessages($mesg, null, 'warnings');
1944  $error++;
1945  $result = -1;
1946  }
1947 
1948  // Check minimum price
1949  $productid = GETPOST('productid', 'int');
1950  if (! empty($productid))
1951  {
1952  $product = new Product($db);
1953  $product->fetch($productid);
1954 
1955  $type = $product->type;
1956 
1957  $price_min = $product->price_min;
1958  if (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($object->thirdparty->price_level))
1959  $price_min = $product->multiprices_min [$object->thirdparty->price_level];
1960 
1961  $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
1962 
1963  // Check price is not lower than minimum (check is done only for standard or replacement invoices)
1964  if (($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT) && $price_min && (price2num($pu_ht) * (1 - price2num(GETPOST('remise_percent')) / 100) < price2num($price_min))) {
1965  setEventMessages($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)), null, 'errors');
1966  $error ++;
1967  }
1968  } else {
1969  $type = GETPOST('type');
1970  $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1971 
1972  // Check parameters
1973  if (GETPOST('type') < 0) {
1974  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
1975  $error ++;
1976  }
1977  }
1978  if ($qty < 0) {
1979  $langs->load("errors");
1980  setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
1981  $error ++;
1982  }
1983 
1984  // Update line
1985  if (! $error) {
1986  if (empty($user->rights->margins->creer))
1987  {
1988  foreach ($object->lines as &$line)
1989  {
1990  if ($line->id == GETPOST('lineid'))
1991  {
1992  $fournprice = $line->fk_fournprice;
1993  $buyingprice = $line->pa_ht;
1994  break;
1995  }
1996  }
1997  }
1998 
1999  $result = $object->updateline(GETPOST('lineid'), $description, $pu_ht, $qty, GETPOST('remise_percent'),
2000  $date_start, $date_end, $vat_rate, $localtax1_rate, $localtax2_rate, 'HT', $info_bits, $type,
2001  GETPOST('fk_parent_line'), 0, $fournprice, $buyingprice, $label, $special_code, $array_options, GETPOST('progress'),
2002  $_POST['units'],$pu_ht_devise);
2003 
2004  if ($result >= 0) {
2005  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
2006  // Define output language
2007  $outputlangs = $langs;
2008  $newlang = '';
2009  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09'))
2010  $newlang = GETPOST('lang_id','aZ09');
2011  if ($conf->global->MAIN_MULTILANGS && empty($newlang))
2012  $newlang = $object->thirdparty->default_lang;
2013  if (! empty($newlang)) {
2014  $outputlangs = new Translate("", $conf);
2015  $outputlangs->setDefaultLang($newlang);
2016  }
2017 
2018  $ret = $object->fetch($id); // Reload to get new records
2019  $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
2020  }
2021 
2022  unset($_POST['qty']);
2023  unset($_POST['type']);
2024  unset($_POST['productid']);
2025  unset($_POST['remise_percent']);
2026  unset($_POST['price_ht']);
2027  unset($_POST['multicurrency_price_ht']);
2028  unset($_POST['price_ttc']);
2029  unset($_POST['tva_tx']);
2030  unset($_POST['product_ref']);
2031  unset($_POST['product_label']);
2032  unset($_POST['product_desc']);
2033  unset($_POST['fournprice']);
2034  unset($_POST['buying_price']);
2035  unset($_POST['np_marginRate']);
2036  unset($_POST['np_markRate']);
2037 
2038  unset($_POST['dp_desc']);
2039  unset($_POST['idprod']);
2040  unset($_POST['units']);
2041 
2042  unset($_POST['date_starthour']);
2043  unset($_POST['date_startmin']);
2044  unset($_POST['date_startsec']);
2045  unset($_POST['date_startday']);
2046  unset($_POST['date_startmonth']);
2047  unset($_POST['date_startyear']);
2048  unset($_POST['date_endhour']);
2049  unset($_POST['date_endmin']);
2050  unset($_POST['date_endsec']);
2051  unset($_POST['date_endday']);
2052  unset($_POST['date_endmonth']);
2053  unset($_POST['date_endyear']);
2054 
2055  unset($_POST['situations']);
2056  unset($_POST['progress']);
2057  } else {
2058  setEventMessages($object->error, $object->errors, 'errors');
2059  }
2060  }
2061  }
2062 
2063  else if ($action == 'updatealllines' && $user->rights->facture->creer && $_POST['all_percent'] == $langs->trans('Modifier'))
2064  {
2065  if (!$object->fetch($id) > 0) dol_print_error($db);
2066  if (!is_null(GETPOST('all_progress')) && GETPOST('all_progress') != "")
2067  {
2068  foreach ($object->lines as $line)
2069  {
2070  $percent = $line->get_prev_progress($object->id);
2071  if (GETPOST('all_progress') < $percent) {
2072  $mesg = '<div class="warning">' . $langs->trans("CantBeLessThanMinPercent") . '</div>';
2073  $result = -1;
2074  } else
2075  $object->update_percent($line, $_POST['all_progress']);
2076  }
2077  }
2078  }
2079 
2080  else if ($action == 'updateligne' && $user->rights->facture->creer && $_POST['cancel'] == $langs->trans('Cancel')) {
2081  header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id); // Pour reaffichage de la fiche en cours d'edition
2082  exit();
2083  }
2084 
2085  // Actions when printing a doc from card
2086  include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
2087 
2088  // Actions to send emails
2089  if (empty($id)) $id=$facid;
2090  $trigger_name='BILL_SENTBYMAIL';
2091  $paramname='id';
2092  $autocopy='MAIN_MAIL_AUTOCOPY_INVOICE_TO';
2093  $trackid='inv'.$object->id;
2094  include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
2095 
2096  // Actions to build doc
2097  $upload_dir = $conf->facture->dir_output;
2098  $permissioncreate=$user->rights->facture->creer;
2099  include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
2100 
2101 
2102  if ($action == 'update_extras') {
2103  // Fill array 'array_options' with data from add form
2104  $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
2105  $ret = $extrafields->setOptionalsFromPost($extralabels, $object, GETPOST('attribute'));
2106  if ($ret < 0) $error++;
2107 
2108  if (! $error) {
2109  // Actions on extra fields (by external module or standard code)
2110  // TODO le hook fait double emploi avec le trigger !!
2111  $hookmanager->initHooks(array('invoicedao'));
2112  $parameters = array('id' => $object->id);
2113  $reshook = $hookmanager->executeHooks('insertExtraFields', $parameters, $object, $action); // Note that $action and $object may have been modified by
2114  // some hooks
2115  if (empty($reshook)) {
2116  $result = $object->insertExtraFields();
2117  if ($result < 0)
2118  {
2119  setEventMessages($object->error, $object->errors, 'errors');
2120  $error++;
2121  }
2122  } else if ($reshook < 0)
2123  $error ++;
2124  }
2125 
2126  if ($error)
2127  $action = 'edit_extras';
2128  }
2129 
2130  if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $user->rights->facture->creer) {
2131  if ($action == 'addcontact') {
2132  $result = $object->fetch($id);
2133 
2134  if ($result > 0 && $id > 0) {
2135  $contactid = (GETPOST('userid') ? GETPOST('userid') : GETPOST('contactid'));
2136  $result = $object->add_contact($contactid, $_POST["type"], $_POST["source"]);
2137  }
2138 
2139  if ($result >= 0) {
2140  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
2141  exit();
2142  } else {
2143  if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
2144  $langs->load("errors");
2145  setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
2146  } else {
2147  setEventMessages($object->error, $object->errors, 'errors');
2148  }
2149  }
2150  } // bascule du statut d'un contact
2151  elseif ($action == 'swapstatut') {
2152  if ($object->fetch($id)) {
2153  $result = $object->swapContactStatus(GETPOST('ligne'));
2154  } else {
2155  dol_print_error($db);
2156  }
2157  } // Efface un contact
2158  elseif ($action == 'deletecontact') {
2159  $object->fetch($id);
2160  $result = $object->delete_contact($lineid);
2161 
2162  if ($result >= 0) {
2163  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
2164  exit();
2165  } else {
2166  dol_print_error($db);
2167  }
2168  }
2169 
2170  if ($error)
2171  $action = 'edit_extras';
2172  }
2173 }
2174 
2175 
2176 /*
2177  * View
2178  */
2179 
2180 $form = new Form($db);
2181 $formother = new FormOther($db);
2182 $formfile = new FormFile($db);
2183 $formmargin = new FormMargin($db);
2184 $paymentstatic=new Paiement($db);
2185 $bankaccountstatic = new Account($db);
2186 if (! empty($conf->projet->enabled)) { $formproject = new FormProjets($db); }
2187 
2188 $now = dol_now();
2189 
2190 $title = $langs->trans('InvoiceCustomer') . " - " . $langs->trans('Card');
2191 $helpurl = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes";
2192 llxHeader('', $title, $helpurl);
2193 
2194 
2195 // Mode creation
2196 
2197 if ($action == 'create')
2198 {
2199  $facturestatic = new Facture($db);
2200  $extralabels = $extrafields->fetch_name_optionals_label($facturestatic->table_element);
2201 
2202  print load_fiche_titre($langs->trans('NewBill'));
2203 
2204  $soc = new Societe($db);
2205  if ($socid > 0)
2206  $res = $soc->fetch($socid);
2207 
2208  $currency_code = $conf->currency;
2209 
2210  // Load objectsrc
2211  $remise_absolue = 0;
2212 
2213  if (! empty($origin) && ! empty($originid))
2214  {
2215  // Parse element/subelement (ex: project_task)
2216  $element = $subelement = $origin;
2217  if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
2218  $element = $regs [1];
2219  $subelement = $regs [2];
2220  }
2221 
2222  if ($element == 'project') {
2223  $projectid = $originid;
2224 
2225  if (!$cond_reglement_id) {
2226  $cond_reglement_id = $soc->cond_reglement_id;
2227  }
2228  if (!$mode_reglement_id) {
2229  $mode_reglement_id = $soc->mode_reglement_id;
2230  }
2231  if (!$remise_percent) {
2232  $remise_percent = $soc->remise_percent;
2233  }
2234  if (!$dateinvoice) {
2235  // Do not set 0 here (0 for a date is 1970)
2236  $dateinvoice = (empty($dateinvoice)?(empty($conf->global->MAIN_AUTOFILL_DATE)?-1:''):$dateinvoice);
2237  }
2238  } else {
2239  // For compatibility
2240  if ($element == 'order' || $element == 'commande') {
2241  $element = $subelement = 'commande';
2242  }
2243  if ($element == 'propal') {
2244  $element = 'comm/propal';
2245  $subelement = 'propal';
2246  }
2247  if ($element == 'contract') {
2248  $element = $subelement = 'contrat';
2249  }
2250  if ($element == 'shipping') {
2251  $element = $subelement = 'expedition';
2252  }
2253 
2254  dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
2255 
2256  $classname = ucfirst($subelement);
2257  $objectsrc = new $classname($db);
2258  $objectsrc->fetch($originid);
2259  if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines'))
2260  $objectsrc->fetch_lines();
2261  $objectsrc->fetch_thirdparty();
2262 
2263  $projectid = (! empty($projectid) ? $projectid : $objectsrc->fk_project);
2264  $ref_client = (! empty($objectsrc->ref_client) ? $objectsrc->ref_client : (! empty($objectsrc->ref_customer) ? $objectsrc->ref_customer:''));
2265  $ref_int = (! empty($objectsrc->ref_int) ? $objectsrc->ref_int : '');
2266 
2267  // only if socid not filled else it's allready done upper
2268  if (empty($socid))
2269  $soc = $objectsrc->thirdparty;
2270 
2271  $cond_reglement_id = (! empty($objectsrc->cond_reglement_id)?$objectsrc->cond_reglement_id:(! empty($soc->cond_reglement_id)?$soc->cond_reglement_id:0));
2272  $mode_reglement_id = (! empty($objectsrc->mode_reglement_id)?$objectsrc->mode_reglement_id:(! empty($soc->mode_reglement_id)?$soc->mode_reglement_id:0));
2273  $fk_account = (! empty($objectsrc->fk_account)?$objectsrc->fk_account:(! empty($soc->fk_account)?$soc->fk_account:0));
2274  $remise_percent = (! empty($objectsrc->remise_percent)?$objectsrc->remise_percent:(! empty($soc->remise_percent)?$soc->remise_percent:0));
2275  $remise_absolue = (! empty($objectsrc->remise_absolue)?$objectsrc->remise_absolue:(! empty($soc->remise_absolue)?$soc->remise_absolue:0));
2276  $dateinvoice = (empty($dateinvoice)?(empty($conf->global->MAIN_AUTOFILL_DATE)?-1:''):$dateinvoice);
2277 
2278  if (!empty($conf->multicurrency->enabled))
2279  {
2280  if (!empty($objectsrc->multicurrency_code)) $currency_code = $objectsrc->multicurrency_code;
2281  if (!empty($conf->global->MULTICURRENCY_USE_ORIGIN_TX) && !empty($objectsrc->multicurrency_tx)) $currency_tx = $objectsrc->multicurrency_tx;
2282  }
2283 
2284  // Replicate extrafields
2285  $objectsrc->fetch_optionals($originid);
2286  $object->array_options = $objectsrc->array_options;
2287  }
2288  }
2289  else
2290  {
2291  $cond_reglement_id = $soc->cond_reglement_id;
2292  $mode_reglement_id = $soc->mode_reglement_id;
2293  $fk_account = $soc->fk_account;
2294  $remise_percent = $soc->remise_percent;
2295  $remise_absolue = 0;
2296  $dateinvoice = (empty($dateinvoice)?(empty($conf->global->MAIN_AUTOFILL_DATE)?-1:''):$dateinvoice); // Do not set 0 here (0 for a date is 1970)
2297 
2298  if (!empty($conf->multicurrency->enabled) && !empty($soc->multicurrency_code)) $currency_code = $soc->multicurrency_code;
2299  }
2300 
2301  if (!empty($soc->id)) $absolute_discount = $soc->getAvailableDiscounts();
2302  $note_public = $object->getDefaultCreateValueFor('note_public', (is_object($objectsrc)?$objectsrc->note_public:null));
2303  $note_private = $object->getDefaultCreateValueFor('note_private', ((! empty($origin) && ! empty($originid) && is_object($objectsrc))?$objectsrc->note_private:null));
2304 
2305  if (! empty($conf->use_javascript_ajax))
2306  {
2307  require_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
2308  print ajax_combobox('fac_replacement');
2309  print ajax_combobox('fac_avoir');
2310  print ajax_combobox('situations');
2311 
2312  }
2313 
2314  if ($origin == 'contrat')
2315  {
2316  $langs->load("admin");
2317  $text=$langs->trans("ToCreateARecurringInvoice");
2318  $text.=' '.$langs->trans("ToCreateARecurringInvoiceGene", $langs->transnoentitiesnoconv("MenuFinancial"), $langs->transnoentitiesnoconv("BillsCustomers"), $langs->transnoentitiesnoconv("ListOfTemplates"));
2319  if (empty($conf->global->INVOICE_DISABLE_AUTOMATIC_RECURRING_INVOICE))
2320  {
2321  $text.=' '.$langs->trans("ToCreateARecurringInvoiceGeneAuto", $langs->transnoentitiesnoconv('Module2300Name'));
2322  }
2323  print info_admin($text, 0, 0, 0).'<br>';
2324  }
2325 
2326  print '<form name="add" action="' . $_SERVER["PHP_SELF"] . '" method="POST">';
2327  print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
2328  print '<input type="hidden" name="action" value="add">';
2329  if ($soc->id > 0) print '<input type="hidden" name="socid" value="' . $soc->id . '">' . "\n";
2330  print '<input name="facnumber" type="hidden" value="provisoire">';
2331  print '<input name="ref_client" type="hidden" value="' . $ref_client . '">';
2332  print '<input name="ref_int" type="hidden" value="' . $ref_int . '">';
2333  print '<input type="hidden" name="origin" value="' . $origin . '">';
2334  print '<input type="hidden" name="originid" value="' . $originid . '">';
2335  if (!empty($currency_tx)) print '<input type="hidden" name="originmulticurrency_tx" value="' . $currency_tx . '">';
2336 
2337  dol_fiche_head('');
2338 
2339  print '<table class="border" width="100%">';
2340 
2341  // Ref
2342  print '<tr><td class="titlefieldcreate fieldrequired">' . $langs->trans('Ref') . '</td><td colspan="2">' . $langs->trans('Draft') . '</td></tr>';
2343 
2344  // Thirdparty
2345  print '<td class="fieldrequired">' . $langs->trans('Customer') . '</td>';
2346  if ($soc->id > 0 && ! GETPOST('fac_rec','alpha'))
2347  {
2348  print '<td colspan="2">';
2349  print $soc->getNomUrl(1);
2350  print '<input type="hidden" name="socid" value="' . $soc->id . '">';
2351  // Outstanding Bill
2352  $outstandingBills = $soc->get_OutstandingBill();
2353  print ' (' . $langs->trans('CurrentOutstandingBill') . ': ';
2354  print price($outstandingBills, '', $langs, 0, 0, -1, $conf->currency);
2355  if ($soc->outstanding_limit != '')
2356  {
2357  if ($outstandingBills > $soc->outstanding_limit) print img_warning($langs->trans("OutstandingBillReached"));
2358  print ' / ' . price($soc->outstanding_limit, '', $langs, 0, 0, -1, $conf->currency);
2359  }
2360  print ')';
2361  print '</td>';
2362  }
2363  else
2364  {
2365  print '<td colspan="2">';
2366  print $form->select_company($soc->id, 'socid', '(s.client = 1 OR s.client = 3) AND status=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300');
2367  // Option to reload page to retrieve customer informations. Note, this clear other input
2368  if (!empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE))
2369  {
2370  print '<script type="text/javascript">
2371  $(document).ready(function() {
2372  $("#socid").change(function() {
2373  var socid = $(this).val();
2374  var fac_rec = $(\'#fac_rec\').val();
2375  // reload page
2376  window.location.href = "'.$_SERVER["PHP_SELF"].'?action=create&socid="+socid+"&fac_rec="+fac_rec;
2377  });
2378  });
2379  </script>';
2380  }
2381  print ' <a href="'.DOL_URL_ROOT.'/societe/card.php?action=create&client=3&fournisseur=0&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create').'">'.$langs->trans("AddThirdParty").'</a>';
2382  print '</td>';
2383  }
2384  print '</tr>' . "\n";
2385 
2386  $exampletemplateinvoice=new FactureRec($db);
2387 
2388  // Overwrite value if creation of invoice is from a predefined invoice
2389  if (empty($origin) && empty($originid) && GETPOST('fac_rec','int') > 0)
2390  {
2391  $invoice_predefined = new FactureRec($db);
2392  $invoice_predefined->fetch(GETPOST('fac_rec','int'));
2393 
2394  $dateinvoice = $invoice_predefined->date_when; // To use next gen date by default later
2395  if (empty($projectid)) $projectid = $invoice_predefined->fk_project;
2396  $cond_reglement_id = $invoice_predefined->cond_reglement_id;
2397  $mode_reglement_id = $invoice_predefined->mode_reglement_id;
2398  $fk_account = $invoice_predefined->fk_account;
2399  $note_public = $invoice_predefined->note_public;
2400  $note_private = $invoice_predefined->note_private;
2401 
2402  $sql = 'SELECT r.rowid, r.titre, r.total_ttc';
2403  $sql .= ' FROM ' . MAIN_DB_PREFIX . 'facture_rec as r';
2404  $sql .= ' WHERE r.fk_soc = ' . $invoice_predefined->socid;
2405 
2406  $resql = $db->query($sql);
2407  if ($resql)
2408  {
2409  $num = $db->num_rows($resql);
2410  $i = 0;
2411 
2412  if ($num > 0)
2413  {
2414  print '<tr><td>' . $langs->trans('CreateFromRepeatableInvoice') . '</td><td>';
2415  print '<select class="flat" id="fac_rec" name="fac_rec">';
2416  print '<option value="0" selected></option>';
2417  while ($i < $num)
2418  {
2419  $objp = $db->fetch_object($resql);
2420  print '<option value="' . $objp->rowid . '"';
2421  if (GETPOST('fac_rec') == $objp->rowid)
2422  {
2423  print ' selected';
2424  $exampletemplateinvoice->fetch(GETPOST('fac_rec'));
2425  }
2426  print '>' . $objp->titre . ' (' . price($objp->total_ttc) . ' ' . $langs->trans("TTC") . ')</option>';
2427  $i ++;
2428  }
2429  print '</select>';
2430  // Option to reload page to retrieve customer informations. Note, this clear other input
2431  if (!empty($conf->global->RELOAD_PAGE_ON_TEMPLATE_CHANGE))
2432  {
2433  print '<script type="text/javascript">
2434  $(document).ready(function() {
2435  $("#fac_rec").change(function() {
2436  var fac_rec = $(this).val();
2437  var socid = $(\'#socid\').val();
2438  // reload page
2439  window.location.href = "'.$_SERVER["PHP_SELF"].'?action=create&socid="+socid+"&fac_rec="+fac_rec;
2440  });
2441  });
2442  </script>';
2443  }
2444  print '</td></tr>';
2445  }
2446  $db->free($resql);
2447  } else {
2448  dol_print_error($db);
2449  }
2450  }
2451 
2452  // Type de facture
2453  $facids = $facturestatic->list_replacable_invoices($soc->id);
2454  if ($facids < 0) {
2455  dol_print_error($db, $facturestatic);
2456  exit();
2457  }
2458  $options = "";
2459  foreach ($facids as $facparam)
2460  {
2461  $options .= '<option value="' . $facparam ['id'] . '"';
2462  if ($facparam ['id'] == $_POST['fac_replacement'])
2463  $options .= ' selected';
2464  $options .= '>' . $facparam ['ref'];
2465  $options .= ' (' . $facturestatic->LibStatut(0, $facparam ['status']) . ')';
2466  $options .= '</option>';
2467  }
2468 
2469  // Show link for credit note
2470  $facids=$facturestatic->list_qualified_avoir_invoices($soc->id);
2471  if ($facids < 0)
2472  {
2473  dol_print_error($db,$facturestatic);
2474  exit;
2475  }
2476  $optionsav = "";
2477  $newinvoice_static = new Facture($db);
2478  foreach ($facids as $key => $valarray)
2479  {
2480  $newinvoice_static->id = $key;
2481  $newinvoice_static->ref = $valarray ['ref'];
2482  $newinvoice_static->statut = $valarray ['status'];
2483  $newinvoice_static->type = $valarray ['type'];
2484  $newinvoice_static->paye = $valarray ['paye'];
2485 
2486  $optionsav .= '<option value="' . $key . '"';
2487  if ($key == GETPOST('fac_avoir'))
2488  $optionsav .= ' selected';
2489  $optionsav .= '>';
2490  $optionsav .= $newinvoice_static->ref;
2491  $optionsav .= ' (' . $newinvoice_static->getLibStatut(1, $valarray ['paymentornot']) . ')';
2492  $optionsav .= '</option>';
2493  }
2494 
2495  print '<tr><td class="tdtop fieldrequired">' . $langs->trans('Type') . '</td><td colspan="2">';
2496 
2497  print '<div class="tagtable">' . "\n";
2498 
2499  // Standard invoice
2500  print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2501  $tmp='<input type="radio" id="radio_standard" name="type" value="0"' . (GETPOST('type') == 0 ? ' checked' : '') . '> ';
2502  $desc = $form->textwithpicto($tmp.$langs->trans("InvoiceStandardAsk"), $langs->transnoentities("InvoiceStandardDesc"), 1, 'help', '', 0, 3);
2503  print $desc;
2504  print '</div></div>';
2505 
2506  if ((empty($origin)) || ((($origin == 'propal') || ($origin == 'commande')) && (! empty($originid))))
2507  {
2508  // Deposit
2509  if (empty($conf->global->INVOICE_DISABLE_DEPOSIT))
2510  {
2511  print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2512  $tmp='<input type="radio" id="radio_deposit" name="type" value="3"' . (GETPOST('type') == 3 ? ' checked' : '') . '> ';
2513  print '<script type="text/javascript" language="javascript">
2514  jQuery(document).ready(function() {
2515  jQuery("#typedeposit, #valuedeposit").click(function() {
2516  jQuery("#radio_deposit").prop("checked", true);
2517  });
2518  });
2519  </script>';
2520 
2521  $desc = $form->textwithpicto($tmp.$langs->trans("InvoiceDeposit"), $langs->transnoentities("InvoiceDepositDesc"), 1, 'help', '', 0, 3);
2522  print '<table class="nobordernopadding"><tr><td>';
2523  print $desc;
2524  print '</td>';
2525  if (($origin == 'propal') || ($origin == 'commande'))
2526  {
2527  print '<td class="nowrap" style="padding-left: 5px">';
2528  $arraylist = array('amount' => 'FixAmount','variable' => 'VarAmount');
2529  print $form->selectarray('typedeposit', $arraylist, GETPOST('typedeposit'), 0, 0, 0, '', 1);
2530  print '</td>';
2531  print '<td class="nowrap" style="padding-left: 5px">' . $langs->trans('Value') . ':<input type="text" id="valuedeposit" name="valuedeposit" size="3" value="' . GETPOST('valuedeposit', 'int') . '"/>';
2532  }
2533  print '</td></tr></table>';
2534 
2535  print '</div></div>';
2536  }
2537  }
2538 
2539  if ($socid > 0)
2540  {
2541  if (! empty($conf->global->INVOICE_USE_SITUATION))
2542  {
2543  // First situation invoice
2544  print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2545  $tmp='<input type="radio" name="type" value="5"' . (GETPOST('type') == 5 ? ' checked' : '') . '> ';
2546  $desc = $form->textwithpicto($tmp.$langs->trans("InvoiceFirstSituationAsk"), $langs->transnoentities("InvoiceFirstSituationDesc"), 1, 'help', '', 0, 3);
2547  print $desc;
2548  print '</div></div>';
2549 
2550  // Next situation invoice
2551  $opt = $form->selectSituationInvoices(GETPOST('originid'), $socid);
2552  print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2553  $tmp='<input type="radio" name="type" value="5"' . (GETPOST('type') == 5 && GETPOST('originid') ? ' checked' : '');
2554  if ($opt == ('<option value ="0" selected>' . $langs->trans('NoSituations') . '</option>') || (GETPOST('origin') && GETPOST('origin') != 'facture' && GETPOST('origin') != 'commande')) $tmp.=' disabled';
2555  $tmp.= '> ';
2556  $text = $tmp.$langs->trans("InvoiceSituationAsk") . ' ';
2557  $text .= '<select class="flat" id="situations" name="situations">';
2558  $text .= $opt;
2559  $text .= '</select>';
2560  $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceSituationDesc"), 1, 'help', '', 0, 3);
2561  print $desc;
2562  print '</div></div>';
2563  }
2564 
2565  // Replacement
2566  if (empty($conf->global->INVOICE_DISABLE_REPLACEMENT))
2567  {
2568  print '<!-- replacement line -->';
2569  print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2570  $tmp='<input type="radio" name="type" id="radio_replacement" value="1"' . (GETPOST('type') == 1 ? ' checked' : '');
2571  if (! $options) $tmp.=' disabled';
2572  $tmp.='> ';
2573  print '<script type="text/javascript" language="javascript">
2574  jQuery(document).ready(function() {
2575  jQuery("#fac_replacement").change(function() {
2576  jQuery("#radio_replacement").prop("checked", true);
2577  });
2578  });
2579  </script>';
2580  $text = $tmp.$langs->trans("InvoiceReplacementAsk") . ' ';
2581  $text .= '<select class="flat" name="fac_replacement" id="fac_replacement"';
2582  if (! $options)
2583  $text .= ' disabled';
2584  $text .= '>';
2585  if ($options) {
2586  $text .= '<option value="-1">&nbsp;</option>';
2587  $text .= $options;
2588  } else {
2589  $text .= '<option value="-1">' . $langs->trans("NoReplacableInvoice") . '</option>';
2590  }
2591  $text .= '</select>';
2592  $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceReplacementDesc"), 1, 'help', '', 0, 3);
2593  print $desc;
2594  print '</div></div>';
2595  }
2596  }
2597  else
2598  {
2599  print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2600  $tmp='<input type="radio" name="type" id="radio_replacement" value="0" disabled> ';
2601  $text = $tmp.$langs->trans("InvoiceReplacement") . ' ';
2602  $text.= '('.$langs->trans("YouMustCreateInvoiceFromThird").') ';
2603  $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceReplacementDesc"), 1, 'help', '', 0, 3);
2604  print $desc;
2605  print '</div></div>';
2606  }
2607 
2608  if (empty($origin))
2609  {
2610  if ($socid > 0)
2611  {
2612  // Credit note
2613  if (empty($conf->global->INVOICE_DISABLE_CREDIT_NOTE))
2614  {
2615  print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2616  $tmp='<input type="radio" id="radio_creditnote" name="type" value="2"' . (GETPOST('type') == 2 ? ' checked' : '');
2617  if (! $optionsav) $tmp.=' disabled';
2618  $tmp.= '> ';
2619  // Show credit note options only if we checked credit note
2620  print '<script type="text/javascript" language="javascript">
2621  jQuery(document).ready(function() {
2622  if (! jQuery("#radio_creditnote").is(":checked"))
2623  {
2624  jQuery("#credit_note_options").hide();
2625  }
2626  jQuery("#radio_creditnote").click(function() {
2627  jQuery("#credit_note_options").show();
2628  });
2629  jQuery("#radio_standard, #radio_replacement, #radio_deposit").click(function() {
2630  jQuery("#credit_note_options").hide();
2631  });
2632  });
2633  </script>';
2634  $text = $tmp.$langs->transnoentities("InvoiceAvoirAsk") . ' ';
2635  // $text.='<input type="text" value="">';
2636  $text .= '<select class="flat valignmiddle" name="fac_avoir" id="fac_avoir"';
2637  if (! $optionsav)
2638  $text .= ' disabled';
2639  $text .= '>';
2640  if ($optionsav) {
2641  $text .= '<option value="-1"></option>';
2642  $text .= $optionsav;
2643  } else {
2644  $text .= '<option value="-1">' . $langs->trans("NoInvoiceToCorrect") . '</option>';
2645  }
2646  $text .= '</select>';
2647  $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceAvoirDesc"), 1, 'help', '', 0, 3);
2648  print $desc;
2649 
2650  print '<div id="credit_note_options" class="clearboth">';
2651  print '&nbsp;&nbsp;&nbsp; <input type="checkbox" name="invoiceAvoirWithLines" id="invoiceAvoirWithLines" value="1" onclick="$(\'#credit_note_options input[type=checkbox]\').not(this).prop(\'checked\', false);" '.(GETPOST('invoiceAvoirWithLines','int')>0 ? 'checked':'').' /> <label for="invoiceAvoirWithLines">'.$langs->trans('invoiceAvoirWithLines')."</label>";
2652  print '<br>&nbsp;&nbsp;&nbsp; <input type="checkbox" name="invoiceAvoirWithPaymentRestAmount" id="invoiceAvoirWithPaymentRestAmount" value="1" onclick="$(\'#credit_note_options input[type=checkbox]\').not(this).prop(\'checked\', false);" '.(GETPOST('invoiceAvoirWithPaymentRestAmount','int')>0 ? 'checked':'').' /> <label for="invoiceAvoirWithPaymentRestAmount">'.$langs->trans('invoiceAvoirWithPaymentRestAmount')."</label>";
2653  print '</div>';
2654 
2655  print '</div></div>';
2656  }
2657  }
2658  else
2659  {
2660  print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2661  if (empty($conf->global->INVOICE_CREDIT_NOTE_STANDALONE)) $tmp='<input type="radio" name="type" id="radio_creditnote" value="0" disabled> ';
2662  else $tmp='<input type="radio" name="type" id="radio_creditnote" value="2" > ';
2663  $text = $tmp.$langs->trans("InvoiceAvoir") . ' ';
2664  $text.= '('.$langs->trans("YouMustCreateInvoiceFromThird").') ';
2665  $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceAvoirDesc"), 1, 'help', '', 0, 3);
2666  print $desc;
2667  print '</div></div>' . "\n";
2668  }
2669  }
2670 
2671  // Template invoice
2672  print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
2673  $tmp='<input type="radio" name="type" id="radio_template" value="0" disabled> ';
2674  $text = $tmp.$langs->trans("RepeatableInvoice") . ' ';
2675  //$text.= '('.$langs->trans("YouMustCreateStandardInvoiceFirst").') ';
2676  $desc = $form->textwithpicto($text, $langs->transnoentities("YouMustCreateStandardInvoiceFirstDesc"), 1, 'help', '', 0, 3);
2677  print $desc;
2678  print '</div></div>';
2679 
2680  print '</div>';
2681 
2682  print '</td></tr>';
2683 
2684  if ($socid > 0)
2685  {
2686  // Discounts for third party
2687  print '<tr><td>' . $langs->trans('Discounts') . '</td><td colspan="2">';
2688  if ($soc->remise_percent)
2689  print $langs->trans("CompanyHasRelativeDiscount", '<a href="' . DOL_URL_ROOT . '/comm/remise.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"] . '?socid=' . $soc->id . '&action=' . $action . '&origin=' . GETPOST('origin') . '&originid=' . GETPOST('originid')) . '">' . $soc->remise_percent . '</a>');
2690  else
2691  print $langs->trans("CompanyHasNoRelativeDiscount");
2692  print ' <a href="' . DOL_URL_ROOT . '/comm/remise.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"] . '?socid=' . $soc->id . '&action=' . $action . '&origin=' . GETPOST('origin') . '&originid=' . GETPOST('originid')) . '">(' . $langs->trans("EditRelativeDiscount") . ')</a>';
2693  print '. ';
2694  print '<br>';
2695  if ($absolute_discount)
2696  print $langs->trans("CompanyHasAbsoluteDiscount", '<a href="' . DOL_URL_ROOT . '/comm/remx.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"] . '?socid=' . $soc->id . '&action=' . $action . '&origin=' . GETPOST('origin') . '&originid=' . GETPOST('originid')) . '">' . price($absolute_discount) . '</a>', $langs->trans("Currency" . $conf->currency));
2697  else
2698  print $langs->trans("CompanyHasNoAbsoluteDiscount");
2699  print ' <a href="' . DOL_URL_ROOT . '/comm/remx.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"] . '?socid=' . $soc->id . '&action=' . $action . '&origin=' . GETPOST('origin') . '&originid=' . GETPOST('originid')) . '">(' . $langs->trans("EditGlobalDiscounts") . ')</a>';
2700  print '.';
2701  print '</td></tr>';
2702  }
2703 
2704  $datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
2705 
2706  // Date invoice
2707  print '<tr><td class="fieldrequired">' . $langs->trans('DateInvoice') . '</td><td colspan="2">';
2708  print $form->select_date($datefacture?$datefacture:$dateinvoice, '', '', '', '', "add", 1, 1, 1);
2709  print '</td></tr>';
2710 
2711  // Date point of tax
2712  if (! empty($conf->global->INVOICE_POINTOFTAX_DATE))
2713  {
2714  print '<tr><td class="fieldrequired">' . $langs->trans('DatePointOfTax') . '</td><td colspan="2">';
2715  $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
2716  print $form->select_date($date_pointoftax?$date_pointoftax:-1, 'date_pointoftax', '', '', '', "add", 1, 1, 1);
2717  print '</td></tr>';
2718  }
2719 
2720  // Payment term
2721  print '<tr><td class="nowrap fieldrequired">' . $langs->trans('PaymentConditionsShort') . '</td><td colspan="2">';
2722  $form->select_conditions_paiements(isset($_POST['cond_reglement_id']) ? $_POST['cond_reglement_id'] : $cond_reglement_id, 'cond_reglement_id');
2723  print '</td></tr>';
2724 
2725  // Payment mode
2726  print '<tr><td>' . $langs->trans('PaymentMode') . '</td><td colspan="2">';
2727  $form->select_types_paiements(isset($_POST['mode_reglement_id']) ? $_POST['mode_reglement_id'] : $mode_reglement_id, 'mode_reglement_id', 'CRDT');
2728  print '</td></tr>';
2729 
2730  // Bank Account
2731  if (isset($_POST['fk_account'])) {
2732  $fk_account = $_POST['fk_account'];
2733  }
2734 
2735  print '<tr><td>' . $langs->trans('BankAccount') . '</td><td colspan="2">';
2736  $form->select_comptes($fk_account, 'fk_account', 0, '', 1);
2737  print '</td></tr>';
2738 
2739  // Project
2740  if (! empty($conf->projet->enabled))
2741  {
2742  $langs->load('projects');
2743  print '<tr><td>' . $langs->trans('Project') . '</td><td colspan="2">';
2744  $numprojet = $formproject->select_projects(($socid > 0 ? $socid : -1), $projectid, 'projectid', 0, 0, 1, 1);
2745  print ' &nbsp; <a href="'.DOL_URL_ROOT.'/projet/card.php?socid=' . $soc->id . '&action=create&status=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&socid='.$soc->id.($fac_rec?'&fac_rec='.$fac_rec:'')).'">' . $langs->trans("AddProject") . '</a>';
2746  print '</td></tr>';
2747  }
2748 
2749  // Incoterms
2750  if (!empty($conf->incoterm->enabled))
2751  {
2752  print '<tr>';
2753  print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $objectsrc->libelle_incoterms, 1).'</label></td>';
2754  print '<td colspan="2" class="maxwidthonsmartphone">';
2755  $incoterm_id = GETPOST('incoterm_id');
2756  $incoterm_location = GETPOST('location_incoterms');
2757  if (empty($incoterm_id))
2758  {
2759  $incoterm_id = (!empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : $soc->fk_incoterms);
2760  $incoterm_location = (!empty($objectsrc->location_incoterms) ? $objectsrc->location_incoterms : $soc->location_incoterms);
2761  }
2762  print $form->select_incoterms($incoterm_id, $incoterm_location);
2763  print '</td></tr>';
2764  }
2765 
2766  // Other attributes
2767  $parameters = array('objectsrc' => $objectsrc,'colspan' => ' colspan="2"', 'cols'=>2);
2768  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2769  print $hookmanager->resPrint;
2770  if (empty($reshook) && ! empty($extrafields->attribute_label)) {
2771  print $object->showOptionals($extrafields, 'edit');
2772  }
2773 
2774  // Template to use by default
2775  print '<tr><td>' . $langs->trans('Model') . '</td>';
2776  print '<td colspan="2">';
2777  include_once DOL_DOCUMENT_ROOT . '/core/modules/facture/modules_facture.php';
2778  $liste = ModelePDFFactures::liste_modeles($db);
2779  print $form->selectarray('model', $liste, $conf->global->FACTURE_ADDON_PDF);
2780  print "</td></tr>";
2781 
2782  // Multicurrency
2783  if (! empty($conf->multicurrency->enabled))
2784  {
2785  print '<tr>';
2786  print '<td>'.fieldLabel('Currency','multicurrency_code').'</td>';
2787  print '<td colspan="2" class="maxwidthonsmartphone">';
2788  print $form->selectMultiCurrency($currency_code, 'multicurrency_code');
2789  print '</td></tr>';
2790  }
2791 
2792  // Help of substitution key
2793  $htmltext='';
2794  if (GETPOST('fac_rec','int') > 0)
2795  {
2796  $dateexample=($datefacture ? $datefacture : $dateinvoice);
2797  if (empty($dateexample)) $dateexample=dol_now();
2798  $substitutionarray=array(
2799  '__TOTAL_HT__' => $langs->trans("AmountHT").' ('.$langs->trans("Example").': '.price($exampletemplateinvoice->total_ht).')',
2800  '__TOTAL_TTC__' => $langs->trans("AmountTTC").' ('.$langs->trans("Example").': '.price($exampletemplateinvoice->total_ttc).')',
2801  '__INVOICE_PREVIOUS_MONTH__' => $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'),'%m').')',
2802  '__INVOICE_MONTH__' => $langs->trans("MonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample,'%m').')',
2803  '__INVOICE_NEXT_MONTH__' => $langs->trans("NextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'),'%m').')',
2804  '__INVOICE_PREVIOUS_MONTH_TEXT__' => $langs->trans("TextPreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'),'%B').')',
2805  '__INVOICE_MONTH_TEXT__' => $langs->trans("TextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample,'%B').')',
2806  '__INVOICE_NEXT_MONTH_TEXT__' => $langs->trans("TextNextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%B').')',
2807  '__INVOICE_PREVIOUS_YEAR__' => $langs->trans("YearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'y'),'%Y').')',
2808  '__INVOICE_YEAR__' => $langs->trans("PreviousYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample,'%Y').')',
2809  '__INVOICE_NEXT_YEAR__' => $langs->trans("NextYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'y'),'%Y').')'
2810  );
2811 
2812  $htmltext = '<i>'.$langs->trans("FollowingConstantsWillBeSubstituted").':<br>';
2813  foreach($substitutionarray as $key => $val)
2814  {
2815  $htmltext.=$key.' = '.$langs->trans($val).'<br>';
2816  }
2817  $htmltext.='</i>';
2818  }
2819 
2820  // Public note
2821  print '<tr>';
2822  print '<td class="tdtop">';
2823  print $form->textwithpicto($langs->trans('NotePublic'), $htmltext);
2824  print '</td>';
2825  print '<td valign="top" colspan="2">';
2826  $doleditor = new DolEditor('note_public', $note_public, '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%');
2827  print $doleditor->Create(1);
2828 
2829  // Private note
2830  if (empty($user->societe_id))
2831  {
2832  print '<tr>';
2833  print '<td class="tdtop">';
2834  print $form->textwithpicto($langs->trans('NotePrivate'), $htmltext);
2835  print '</td>';
2836  print '<td valign="top" colspan="2">';
2837  $doleditor = new DolEditor('note_private', $note_private, '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%');
2838  print $doleditor->Create(1);
2839  // print '<textarea name="note_private" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'.</textarea>
2840  print '</td></tr>';
2841  }
2842 
2843  // Lines from source
2844  if (! empty($origin) && ! empty($originid) && is_object($objectsrc))
2845  {
2846  // TODO for compatibility
2847  if ($origin == 'contrat') {
2848  // Calcul contrat->price (HT), contrat->total (TTC), contrat->tva
2849  $objectsrc->remise_absolue = $remise_absolue;
2850  $objectsrc->remise_percent = $remise_percent;
2851  $objectsrc->update_price(1, - 1, 1);
2852  }
2853 
2854  print "\n<!-- " . $classname . " info -->";
2855  print "\n";
2856  print '<input type="hidden" name="amount" value="' . $objectsrc->total_ht . '">' . "\n";
2857  print '<input type="hidden" name="total" value="' . $objectsrc->total_ttc . '">' . "\n";
2858  print '<input type="hidden" name="tva" value="' . $objectsrc->total_tva . '">' . "\n";
2859  print '<input type="hidden" name="origin" value="' . $objectsrc->element . '">';
2860  print '<input type="hidden" name="originid" value="' . $objectsrc->id . '">';
2861 
2862  switch ($classname) {
2863  case 'Propal':
2864  $newclassname = 'CommercialProposal';
2865  break;
2866  case 'Commande':
2867  $newclassname = 'Order';
2868  break;
2869  case 'Expedition':
2870  $newclassname = 'Sending';
2871  break;
2872  case 'Contrat':
2873  $newclassname = 'Contract';
2874  break;
2875  case 'Fichinter':
2876  $newclassname = 'Intervention';
2877  break;
2878  default:
2879  $newclassname = $classname;
2880  }
2881 
2882  print '<tr><td>' . $langs->trans($newclassname) . '</td><td colspan="2">' . $objectsrc->getNomUrl(1);
2883  // We check if Origin document (id and type is known) has already at least one invoice attached to it
2884  $objectsrc->fetchObjectLinked($originid,$origin,'','facture');
2885  $cntinvoice=count($objectsrc->linkedObjects['facture']);
2886  if ($cntinvoice>=1)
2887  {
2888  setEventMessages('WarningBillExist', null, 'warnings');
2889  echo ' ('.$langs->trans('LatestRelatedBill').end($objectsrc->linkedObjects['facture'])->getNomUrl(1).')';
2890  }
2891  echo '</td></tr>';
2892  print '<tr><td>' . $langs->trans('TotalHT') . '</td><td colspan="2">' . price($objectsrc->total_ht) . '</td></tr>';
2893  print '<tr><td>' . $langs->trans('TotalVAT') . '</td><td colspan="2">' . price($objectsrc->total_tva) . "</td></tr>";
2894  if ($mysoc->localtax1_assuj == "1" || $objectsrc->total_localtax1 != 0) // Localtax1
2895  {
2896  print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td><td colspan="2">' . price($objectsrc->total_localtax1) . "</td></tr>";
2897  }
2898 
2899  if ($mysoc->localtax2_assuj == "1" || $objectsrc->total_localtax2 != 0) // Localtax2
2900  {
2901  print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td><td colspan="2">' . price($objectsrc->total_localtax2) . "</td></tr>";
2902  }
2903  print '<tr><td>' . $langs->trans('TotalTTC') . '</td><td colspan="2">' . price($objectsrc->total_ttc) . "</td></tr>";
2904 
2905  if (!empty($conf->multicurrency->enabled))
2906  {
2907  print '<tr><td>' . $langs->trans('MulticurrencyAmountHT') . '</td><td colspan="2">' . price($objectsrc->multicurrency_total_ht) . '</td></tr>';
2908  print '<tr><td>' . $langs->trans('MulticurrencyAmountVAT') . '</td><td colspan="2">' . price($objectsrc->multicurrency_total_tva) . "</td></tr>";
2909  print '<tr><td>' . $langs->trans('MulticurrencyAmountTTC') . '</td><td colspan="2">' . price($objectsrc->multicurrency_total_ttc) . "</td></tr>";
2910  }
2911  }
2912 
2913  print "</table>\n";
2914 
2915  dol_fiche_end();
2916 
2917  // Button "Create Draft"
2918  print '<div class="center">';
2919  print '<input type="submit" class="button" name="bouton" value="' . $langs->trans('CreateDraft') . '">';
2920  print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
2921  print '<input type="button" class="button" value="' . $langs->trans("Cancel") . '" onClick="javascript:history.go(-1)">';
2922  print '</div>';
2923 
2924  print "</form>\n";
2925 
2926  // Show origin lines
2927  if (! empty($origin) && ! empty($originid) && is_object($objectsrc)) {
2928  print '<br>';
2929 
2930  $title = $langs->trans('ProductsAndServices');
2932 
2933  print '<table class="noborder" width="100%">';
2934 
2935  $objectsrc->printOriginLinesList();
2936 
2937  print '</table>';
2938  }
2939 
2940  print '<br>';
2941 }
2942 else if ($id > 0 || ! empty($ref))
2943 {
2944  /*
2945  * Show object in view mode
2946  */
2947 
2948  $result = $object->fetch($id, $ref);
2949  if ($result <= 0) {
2950  dol_print_error($db, $object->error);
2951  exit();
2952  }
2953 
2954  // fetch optionals attributes and labels
2955  $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
2956 
2957  if ($user->societe_id > 0 && $user->societe_id != $object->socid)
2958  accessforbidden('', 0);
2959 
2960  $result = $object->fetch_thirdparty();
2961 
2962  $soc = new Societe($db);
2963  $result=$soc->fetch($object->socid);
2964  if ($result < 0) dol_print_error($db);
2965  $selleruserevenustamp = $mysoc->useRevenueStamp();
2966 
2967  $totalpaye = $object->getSommePaiement();
2968  $totalcreditnotes = $object->getSumCreditNotesUsed();
2969  $totaldeposits = $object->getSumDepositsUsed();
2970  // print "totalpaye=".$totalpaye." totalcreditnotes=".$totalcreditnotes." totaldeposts=".$totaldeposits."
2971  // selleruserrevenuestamp=".$selleruserevenustamp;
2972 
2973  // We can also use bcadd to avoid pb with floating points
2974  // For example print 239.2 - 229.3 - 9.9; does not return 0.
2975  // $resteapayer=bcadd($object->total_ttc,$totalpaye,$conf->global->MAIN_MAX_DECIMALS_TOT);
2976  // $resteapayer=bcadd($resteapayer,$totalavoir,$conf->global->MAIN_MAX_DECIMALS_TOT);
2977  $resteapayer = price2num($object->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits, 'MT');
2978 
2979  if ($object->paye)
2980  {
2981  $resteapayer = 0;
2982  }
2983  $resteapayeraffiche = $resteapayer;
2984 
2985  if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { // Never use this
2986  $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
2987  $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
2988  } else {
2989  $filterabsolutediscount = "fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%'))";
2990  $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
2991  }
2992 
2993  $absolute_discount = $soc->getAvailableDiscounts('', $filterabsolutediscount);
2994  $absolute_creditnote = $soc->getAvailableDiscounts('', $filtercreditnote);
2995  $absolute_discount = price2num($absolute_discount, 'MT');
2996  $absolute_creditnote = price2num($absolute_creditnote, 'MT');
2997 
2998  $author = new User($db);
2999  if ($object->user_author) {
3000  $author->fetch($object->user_author);
3001  }
3002 
3003  $objectidnext = $object->getIdReplacingInvoice();
3004 
3005  $head = facture_prepare_head($object);
3006 
3007  dol_fiche_head($head, 'compta', $langs->trans('InvoiceCustomer'), -1, 'bill');
3008 
3009  $formconfirm = '';
3010 
3011  // Confirmation de la conversion de l'avoir en reduc
3012  if ($action == 'converttoreduc') {
3013  if($object->type == Facture::TYPE_STANDARD) $type_fac = 'ExcessReceived';
3014  elseif($object->type == Facture::TYPE_CREDIT_NOTE) $type_fac = 'CreditNote';
3015  elseif($object->type == Facture::TYPE_DEPOSIT) $type_fac = 'Deposit';
3016  $text = $langs->trans('ConfirmConvertToReduc', strtolower($langs->transnoentities($type_fac)));
3017  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $langs->trans('ConvertToReduc'), $text, 'confirm_converttoreduc', '', "yes", 2);
3018  }
3019 
3020  // Confirmation to delete invoice
3021  if ($action == 'delete') {
3022  $text = $langs->trans('ConfirmDeleteBill', $object->ref);
3023  $formquestion = array();
3024 
3025  $qualified_for_stock_change = 0;
3026  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
3027  $qualified_for_stock_change = $object->hasProductsOrServices(2);
3028  } else {
3029  $qualified_for_stock_change = $object->hasProductsOrServices(1);
3030  }
3031 
3032  if ($object->type != Facture::TYPE_DEPOSIT && ! empty($conf->global->STOCK_CALCULATE_ON_BILL) && $qualified_for_stock_change && $object->statut >= 1)
3033  {
3034  $langs->load("stocks");
3035  require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php';
3036  $formproduct = new FormProduct($db);
3037  $label = $object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("SelectWarehouseForStockDecrease") : $langs->trans("SelectWarehouseForStockIncrease");
3038  $formquestion = array(
3039  // 'text' => $langs->trans("ConfirmClone"),
3040  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' =>
3041  // 1),
3042  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value'
3043  // => 1),
3044  array('type' => 'other','name' => 'idwarehouse','label' => $label,'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1, 0, 0, $langs->trans("NoStockAction"))));
3045  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $langs->trans('DeleteBill'), $text, 'confirm_delete', $formquestion, "yes", 1);
3046  } else {
3047  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $langs->trans('DeleteBill'), $text, 'confirm_delete', '', '', 1);
3048  }
3049  }
3050 
3051  // Confirmation de la validation
3052  if ($action == 'valid')
3053  {
3054  // on verifie si l'objet est en numerotation provisoire
3055  $objectref = substr($object->ref, 1, 4);
3056  if ($objectref == 'PROV') {
3057  $savdate = $object->date;
3058  if (! empty($conf->global->FAC_FORCE_DATE_VALIDATION)) {
3059  $object->date = dol_now();
3060  $object->date_lim_reglement = $object->calculate_date_lim_reglement();
3061  }
3062  $numref = $object->getNextNumRef($soc);
3063  // $object->date=$savdate;
3064  } else {
3065  $numref = $object->ref;
3066  }
3067 
3068  $text = $langs->trans('ConfirmValidateBill', $numref);
3069  if (! empty($conf->notification->enabled)) {
3070  require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
3071  $notify = new Notify($db);
3072  $text .= '<br>';
3073  $text .= $notify->confirmMessage('BILL_VALIDATE', $object->socid, $object);
3074  }
3075  $formquestion = array();
3076 
3077  $qualified_for_stock_change = 0;
3078  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
3079  $qualified_for_stock_change = $object->hasProductsOrServices(2);
3080  } else {
3081  $qualified_for_stock_change = $object->hasProductsOrServices(1);
3082  }
3083 
3084  if ($object->type != Facture::TYPE_DEPOSIT && ! empty($conf->global->STOCK_CALCULATE_ON_BILL) && $qualified_for_stock_change)
3085  {
3086  $langs->load("stocks");
3087  require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php';
3088  require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
3089  $formproduct = new FormProduct($db);
3090  $warehouse = new Entrepot($db);
3091  $warehouse_array = $warehouse->list_array();
3092  if (count($warehouse_array) == 1) {
3093  $label = $object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("WarehouseForStockIncrease", current($warehouse_array)) : $langs->trans("WarehouseForStockDecrease", current($warehouse_array));
3094  $value = '<input type="hidden" id="idwarehouse" name="idwarehouse" value="' . key($warehouse_array) . '">';
3095  } else {
3096  $label = $object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("SelectWarehouseForStockIncrease") : $langs->trans("SelectWarehouseForStockDecrease");
3097  $value = $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1);
3098  }
3099  $formquestion = array(
3100  // 'text' => $langs->trans("ConfirmClone"),
3101  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' =>
3102  // 1),
3103  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value'
3104  // => 1),
3105  array('type' => 'other','name' => 'idwarehouse','label' => $label,'value' => $value));
3106  }
3107  if ($object->type != Facture::TYPE_CREDIT_NOTE && $object->total_ttc < 0) // Can happen only if $conf->global->FACTURE_ENABLE_NEGATIVE is on
3108  {
3109  $text .= '<br>' . img_warning() . ' ' . $langs->trans("ErrorInvoiceOfThisTypeMustBePositive");
3110  }
3111  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('ValidateBill'), $text, 'confirm_valid', $formquestion, (($object->type != Facture::TYPE_CREDIT_NOTE && $object->total_ttc < 0) ? "no" : "yes"), 2);
3112  }
3113 
3114  // Confirm back to draft status
3115  if ($action == 'modif') {
3116  $text = $langs->trans('ConfirmUnvalidateBill', $object->ref);
3117  $formquestion = array();
3118 
3119  $qualified_for_stock_change = 0;
3120  if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
3121  $qualified_for_stock_change = $object->hasProductsOrServices(2);
3122  } else {
3123  $qualified_for_stock_change = $object->hasProductsOrServices(1);
3124  }
3125  if ($object->type != Facture::TYPE_DEPOSIT && ! empty($conf->global->STOCK_CALCULATE_ON_BILL) && $qualified_for_stock_change) {
3126  $langs->load("stocks");
3127  require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php';
3128  require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
3129  $formproduct = new FormProduct($db);
3130  $warehouse = new Entrepot($db);
3131  $warehouse_array = $warehouse->list_array();
3132  if (count($warehouse_array) == 1) {
3133  $label = $object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("WarehouseForStockDecrease", current($warehouse_array)) : $langs->trans("WarehouseForStockIncrease", current($warehouse_array));
3134  $value = '<input type="hidden" id="idwarehouse" name="idwarehouse" value="' . key($warehouse_array) . '">';
3135  } else {
3136  $label = $object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("SelectWarehouseForStockDecrease") : $langs->trans("SelectWarehouseForStockIncrease");
3137  $value = $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1);
3138  }
3139  $formquestion = array(
3140  // 'text' => $langs->trans("ConfirmClone"),
3141  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' =>
3142  // 1),
3143  // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value'
3144  // => 1),
3145  array('type' => 'other','name' => 'idwarehouse','label' => $label,'value' => $value));
3146  }
3147 
3148  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('UnvalidateBill'), $text, 'confirm_modif', $formquestion, "yes", 1);
3149  }
3150 
3151  // Confirmation du classement paye
3152  if ($action == 'paid' && $resteapayer <= 0) {
3153  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('ClassifyPaid'), $langs->trans('ConfirmClassifyPaidBill', $object->ref), 'confirm_paid', '', "yes", 1);
3154  }
3155  if ($action == 'paid' && $resteapayer > 0) {
3156  // Code
3157  $i = 0;
3158  $close [$i] ['code'] = 'discount_vat'; // escompte
3159  $i ++;
3160  $close [$i] ['code'] = 'badcustomer';
3161  $i ++;
3162  // Help
3163  $i = 0;
3164  $close [$i] ['label'] = $langs->trans("HelpEscompte") . '<br><br>' . $langs->trans("ConfirmClassifyPaidPartiallyReasonDiscountVatDesc");
3165  $i ++;
3166  $close [$i] ['label'] = $langs->trans("ConfirmClassifyPaidPartiallyReasonBadCustomerDesc");
3167  $i ++;
3168  // Texte
3169  $i = 0;
3170  $close [$i] ['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyPaidPartiallyReasonDiscount", $resteapayer, $langs->trans("Currency" . $conf->currency)), $close [$i] ['label'], 1);
3171  $i ++;
3172  $close [$i] ['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyPaidPartiallyReasonBadCustomer", $resteapayer, $langs->trans("Currency" . $conf->currency)), $close [$i] ['label'], 1);
3173  $i ++;
3174  // arrayreasons[code]=reason
3175  foreach ($close as $key => $val) {
3176  $arrayreasons [$close [$key] ['code']] = $close [$key] ['reason'];
3177  }
3178 
3179  // Cree un tableau formulaire
3180  $formquestion = array('text' => $langs->trans("ConfirmClassifyPaidPartiallyQuestion"),array('type' => 'radio','name' => 'close_code','label' => $langs->trans("Reason"),'values' => $arrayreasons),array('type' => 'text','name' => 'close_note','label' => $langs->trans("Comment"),'value' => '','size' => '100'));
3181  // Paiement incomplet. On demande si motif = escompte ou autre
3182  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('ClassifyPaid'), $langs->trans('ConfirmClassifyPaidPartially', $object->ref), 'confirm_paid_partially', $formquestion, "yes");
3183  }
3184 
3185  // Confirmation du classement abandonne
3186  if ($action == 'canceled') {
3187  // S'il y a une facture de remplacement pas encore validee (etat brouillon),
3188  // on ne permet pas de classer abandonner la facture.
3189  if ($objectidnext) {
3190  $facturereplacement = new Facture($db);
3191  $facturereplacement->fetch($objectidnext);
3192  $statusreplacement = $facturereplacement->statut;
3193  }
3194  if ($objectidnext && $statusreplacement == 0) {
3195  print '<div class="error">' . $langs->trans("ErrorCantCancelIfReplacementInvoiceNotValidated") . '</div>';
3196  } else {
3197  // Code
3198  $close [1] ['code'] = 'badcustomer';
3199  $close [2] ['code'] = 'abandon';
3200  // Help
3201  $close [1] ['label'] = $langs->trans("ConfirmClassifyPaidPartiallyReasonBadCustomerDesc");
3202  $close [2] ['label'] = $langs->trans("ConfirmClassifyAbandonReasonOtherDesc");
3203  // Texte
3204  $close [1] ['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyPaidPartiallyReasonBadCustomer", $object->ref), $close [1] ['label'], 1);
3205  $close [2] ['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyAbandonReasonOther"), $close [2] ['label'], 1);
3206  // arrayreasons
3207  $arrayreasons [$close [1] ['code']] = $close [1] ['reason'];
3208  $arrayreasons [$close [2] ['code']] = $close [2] ['reason'];
3209 
3210  // Cree un tableau formulaire
3211  $formquestion = array('text' => $langs->trans("ConfirmCancelBillQuestion"),array('type' => 'radio','name' => 'close_code','label' => $langs->trans("Reason"),'values' => $arrayreasons),array('type' => 'text','name' => 'close_note','label' => $langs->trans("Comment"),'value' => '','size' => '100'));
3212 
3213  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $langs->trans('CancelBill'), $langs->trans('ConfirmCancelBill', $object->ref), 'confirm_canceled', $formquestion, "yes");
3214  }
3215  }
3216 
3217  if ($action == 'deletepaiement')
3218  {
3219  $payment_id = GETPOST('paiement_id');
3220  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&paiement_id='.$payment_id, $langs->trans('DeletePayment'), $langs->trans('ConfirmDeletePayment'), 'confirm_delete_paiement', '', 0, 1);
3221 
3222  }
3223 
3224  // Confirmation de la suppression d'une ligne produit
3225  if ($action == 'ask_deleteline') {
3226  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&lineid=' . $lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 'no', 1);
3227  }
3228 
3229  // Clone confirmation
3230  if ($action == 'clone')
3231  {
3232  // Create an array for form
3233  $formquestion = array(
3234  // 'text' => $langs->trans("ConfirmClone"),
3235  // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1)
3236  array('type' => 'other','name' => 'socid','label' => $langs->trans("SelectThirdParty"),'value' => $form->select_company($object->socid, 'socid', '(s.client=1 OR s.client=2 OR s.client=3)', 1)));
3237  // Paiement incomplet. On demande si motif = escompte ou autre
3238  $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('CloneInvoice'), $langs->trans('ConfirmCloneInvoice', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
3239  }
3240 
3241  if (! $formconfirm)
3242  {
3243  $parameters = array('lineid' => $lineid);
3244  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
3245  if (empty($reshook)) $formconfirm.=$hookmanager->resPrint;
3246  elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint;
3247  }
3248 
3249  // Print form confirm
3250  print $formconfirm;
3251 
3252  // Invoice content
3253 
3254  $linkback = '<a href="' . DOL_URL_ROOT . '/compta/facture/list.php' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
3255 
3256  $morehtmlref='<div class="refidno">';
3257  // Ref customer
3258  $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->facture->creer, 'string', '', 0, 1);
3259  $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->facture->creer, 'string', '', null, null, '', 1);
3260  // Thirdparty
3261  $morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1);
3262  if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) $morehtmlref.=' (<a href="'.DOL_URL_ROOT.'/compta/facture/list.php?socid='.$object->thirdparty->id.'">'.$langs->trans("OtherBills").'</a>)';
3263  // Project
3264  if (! empty($conf->projet->enabled))
3265  {
3266  $langs->load("projects");
3267  $morehtmlref.='<br>'.$langs->trans('Project') . ' ';
3268  if ($user->rights->facture->creer)
3269  {
3270  if ($action != 'classify')
3271  $morehtmlref.='<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
3272  if ($action == 'classify') {
3273  //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
3274  $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
3275  $morehtmlref.='<input type="hidden" name="action" value="classin">';
3276  $morehtmlref.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
3277  $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
3278  $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
3279  $morehtmlref.='</form>';
3280  } else {
3281  $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
3282  }
3283  } else {
3284  if (! empty($object->fk_project)) {
3285  $proj = new Project($db);
3286  $proj->fetch($object->fk_project);
3287  $morehtmlref.='<a href="'.DOL_URL_ROOT.'/projet/card.php?id=' . $object->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
3288  $morehtmlref.=$proj->ref;
3289  $morehtmlref.='</a>';
3290  } else {
3291  $morehtmlref.='';
3292  }
3293  }
3294  }
3295  $morehtmlref.='</div>';
3296 
3297  $object->totalpaye = $totalpaye; // To give a chance to dol_banner_tab to use already paid amount to show correct status
3298 
3299  dol_banner_tab($object, 'ref', $linkback, 1, 'facnumber', 'ref', $morehtmlref, '', 0, '', '');
3300 
3301  print '<div class="fichecenter">';
3302  print '<div class="fichehalfleft">';
3303  print '<div class="underbanner clearboth"></div>';
3304 
3305  print '<table class="border" width="100%">';
3306 
3307  // Type
3308  print '<tr><td class="titlefield">' . $langs->trans('Type') . '</td><td>';
3309  print $object->getLibType();
3310  if ($object->type == Facture::TYPE_REPLACEMENT) {
3311  $facreplaced = new Facture($db);
3312  $facreplaced->fetch($object->fk_facture_source);
3313  print ' (' . $langs->transnoentities("ReplaceInvoice", $facreplaced->getNomUrl(1)) . ')';
3314  }
3315  if ($object->type == Facture::TYPE_CREDIT_NOTE && !empty($object->fk_facture_source)) {
3316  $facusing = new Facture($db);
3317  $facusing->fetch($object->fk_facture_source);
3318  print ' (' . $langs->transnoentities("CorrectInvoice", $facusing->getNomUrl(1)) . ')';
3319  }
3320 
3321  $facidavoir = $object->getListIdAvoirFromInvoice();
3322  if (count($facidavoir) > 0) {
3323  print ' (' . $langs->transnoentities("InvoiceHasAvoir");
3324  $i = 0;
3325  foreach ($facidavoir as $id) {
3326  if ($i == 0)
3327  print ' ';
3328  else
3329  print ',';
3330  $facavoir = new Facture($db);
3331  $facavoir->fetch($id);
3332  print $facavoir->getNomUrl(1);
3333  }
3334  print ')';
3335  }
3336  if ($objectidnext > 0) {
3337  $facthatreplace = new Facture($db);
3338  $facthatreplace->fetch($objectidnext);
3339  print ' (' . $langs->transnoentities("ReplacedByInvoice", $facthatreplace->getNomUrl(1)) . ')';
3340  }
3341 
3342  if ($object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_DEPOSIT) {
3343  $discount = new DiscountAbsolute($db);
3344  $result = $discount->fetch(0, $object->id);
3345  if ($result > 0){
3346  print '. '.$langs->trans("CreditNoteConvertedIntoDiscount", $object->getLibType(), $discount->getNomUrl(1, 'discount')).'<br>';
3347  }
3348  }
3349  print '</td></tr>';
3350 
3351  // Relative and absolute discounts
3352  $addrelativediscount = '<a href="' . DOL_URL_ROOT . '/comm/remise.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("EditRelativeDiscounts") . '</a>';
3353  $addabsolutediscount = '<a href="' . DOL_URL_ROOT . '/comm/remx.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("EditGlobalDiscounts") . '</a>';
3354  $addcreditnote = '<a href="' . DOL_URL_ROOT . '/compta/facture/card.php?action=create&socid=' . $soc->id . '&type=2&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("AddCreditNote") . '</a>';
3355  $viewabsolutediscount = '<a href="' . DOL_URL_ROOT . '/comm/remx.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("ViewAvailableGlobalDiscounts") . '</a>';
3356 
3357  print '<!-- Discounts --><tr><td>' . $langs->trans('Discounts');
3358  print '</td><td>';
3359  if ($soc->remise_percent)
3360  print $langs->trans("CompanyHasRelativeDiscount", $soc->remise_percent);
3361  else
3362  print $langs->trans("CompanyHasNoRelativeDiscount");
3363  // print ' ('.$addrelativediscount.')';
3364 
3365  // Is there is commercial discount or down payment available ?
3366  if ($absolute_discount > 0) {
3367  print '. ';
3368  if ($object->statut > 0 || $object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_DEPOSIT) {
3369  if ($object->statut == 0) {
3370  print $langs->trans("CompanyHasAbsoluteDiscount", price($absolute_discount), $langs->transnoentities("Currency" . $conf->currency));
3371  print '. ';
3372  } else {
3373  if ($object->statut < 1 || $object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_DEPOSIT) {
3374  $text = $langs->trans("CompanyHasAbsoluteDiscount", price($absolute_discount), $langs->transnoentities("Currency" . $conf->currency));
3375  print '<br>' . $text . '.<br>';
3376  } else {
3377  $text = $langs->trans("CompanyHasAbsoluteDiscount", price($absolute_discount), $langs->transnoentities("Currency" . $conf->currency));
3378  $text2 = $langs->trans("AbsoluteDiscountUse");
3379  print $form->textwithpicto($text, $text2);
3380  }
3381  }
3382  } else {
3383  // Discount available of type fixed amount (not credit note)
3384  print '<br>';
3385  $form->form_remise_dispo($_SERVER["PHP_SELF"] . '?facid=' . $object->id, GETPOST('discountid'), 'remise_id', $soc->id, $absolute_discount, $filterabsolutediscount, $resteapayer, ' (' . $addabsolutediscount . ')');
3386  }
3387  } else {
3388  if ($absolute_creditnote > 0) // If not, link will be added later
3389  {
3390  if ($object->statut == Facture::STATUS_DRAFT && $object->type != Facture::TYPE_CREDIT_NOTE && $object->type != Facture::TYPE_DEPOSIT)
3391  print ' (' . $addabsolutediscount . ')<br>';
3392  else
3393  print '. ';
3394  } else
3395  print '. ';
3396  }
3397  // Is there credit notes availables ?
3398  if ($absolute_creditnote > 0)
3399  {
3400  // If validated, we show link "add credit note to payment"
3401  if ($object->statut != Facture::STATUS_VALIDATED || $object->type == Facture::TYPE_CREDIT_NOTE) {
3402  if ($object->statut == 0 && $object->type != Facture::TYPE_DEPOSIT) {
3403  $text = $langs->trans("CompanyHasCreditNote", price($absolute_creditnote), $langs->transnoentities("Currency" . $conf->currency));
3404  print $form->textwithpicto($text, $langs->trans("CreditNoteDepositUse"));
3405  } else {
3406  print $langs->trans("CompanyHasCreditNote", price($absolute_creditnote), $langs->transnoentities("Currency" . $conf->currency)) . '.';
3407  }
3408  } else { // We can add a credit note on a down payment or standard invoice or situation invoice
3409  // There is credit notes discounts available
3410  if (! $absolute_discount) print '<br>';
3411  // $form->form_remise_dispo($_SERVER["PHP_SELF"].'?facid='.$object->id, 0, 'remise_id_for_payment', $soc->id, $absolute_creditnote, $filtercreditnote, $resteapayer);
3412  $more=' ('.$addcreditnote. (($addcreditnote && $viewabsolutediscount) ? ' - ' : '') . $viewabsolutediscount . ')';
3413  $form->form_remise_dispo($_SERVER["PHP_SELF"] . '?facid=' . $object->id, 0, 'remise_id_for_payment', $soc->id, $absolute_creditnote, $filtercreditnote, 0, $more); // We allow credit note even if amount is higher
3414  }
3415  }
3416  if (! $absolute_discount && ! $absolute_creditnote) {
3417  print $langs->trans("CompanyHasNoAbsoluteDiscount");
3418  if ($object->statut == Facture::STATUS_DRAFT && $object->type != Facture::TYPE_CREDIT_NOTE && $object->type != Facture::TYPE_DEPOSIT)
3419  print ' (' . $addabsolutediscount . ')<br>';
3420  else
3421  print '. ';
3422  }
3423  // if ($object->statut == 0 && $object->type != 2 && $object->type != 3)
3424  // {
3425  // if (! $absolute_discount && ! $absolute_creditnote) print '<br>';
3426  // print ' &nbsp; - &nbsp; ';
3427  // print $addabsolutediscount;
3428  // print ' &nbsp; - &nbsp; '.$addcreditnote; // We disbale link to credit note
3429  // }
3430  print '</td></tr>';
3431 
3432  // Date invoice
3433  print '<tr><td>';
3434  print '<table class="nobordernopadding" width="100%"><tr><td>';
3435  print $langs->trans('DateInvoice');
3436  print '</td>';
3437  if ($object->type != Facture::TYPE_CREDIT_NOTE && $action != 'editinvoicedate' && ! empty($object->brouillon) && $user->rights->facture->creer && empty($conf->global->FAC_FORCE_DATE_VALIDATION))
3438  print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editinvoicedate&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetDate'), 1) . '</a></td>';
3439  print '</tr></table>';
3440  print '</td><td>';
3441 
3442  if ($object->type != Facture::TYPE_CREDIT_NOTE) {
3443  if ($action == 'editinvoicedate') {
3444  $form->form_date($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->date, 'invoicedate');
3445  } else {
3446  print dol_print_date($object->date, 'day');
3447  }
3448  } else {
3449  print dol_print_date($object->date, 'day');
3450  }
3451  print '</td>';
3452 
3453  print '</tr>';
3454 
3455  if (! empty($conf->global->INVOICE_POINTOFTAX_DATE))
3456  {
3457  // Date invoice
3458  print '<tr><td>';
3459  print '<table class="nobordernopadding" width="100%"><tr><td>';
3460  print $langs->trans('DatePointOfTax');
3461  print '</td>';
3462  print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editdate_pointoftax&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetDate'), 1) . '</a></td>';
3463  print '</tr></table>';
3464  print '</td><td>';
3465  if ($action == 'editdate_pointoftax') {
3466  $form->form_date($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->date_pointoftax, 'date_pointoftax');
3467  } else {
3468  print dol_print_date($object->date_pointoftax, 'day');
3469  }
3470  print '</td></tr>';
3471  }
3472 
3473  // Payment term
3474  print '<tr><td>';
3475  print '<table class="nobordernopadding" width="100%"><tr><td>';
3476  print $langs->trans('PaymentConditionsShort');
3477  print '</td>';
3478  if ($object->type != Facture::TYPE_CREDIT_NOTE && $action != 'editconditions' && $user->rights->facture->creer)
3479  print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editconditions&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetConditions'), 1) . '</a></td>';
3480  print '</tr></table>';
3481  print '</td><td>';
3482  if ($object->type != Facture::TYPE_CREDIT_NOTE)
3483  {
3484  if ($action == 'editconditions') {
3485  $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->cond_reglement_id, 'cond_reglement_id');
3486  } else {
3487  $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->cond_reglement_id, 'none');
3488  }
3489  } else {
3490  print '&nbsp;';
3491  }
3492  print '</td></tr>';
3493 
3494  // Date payment term
3495  print '<tr><td>';
3496  print '<table class="nobordernopadding" width="100%"><tr><td>';
3497  print $langs->trans('DateMaxPayment');
3498  print '</td>';
3499  if ($object->type != Facture::TYPE_CREDIT_NOTE && $action != 'editpaymentterm' && $user->rights->facture->creer)
3500  print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editpaymentterm&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetDate'), 1) . '</a></td>';
3501  print '</tr></table>';
3502  print '</td><td>';
3503  if ($object->type != Facture::TYPE_CREDIT_NOTE)
3504  {
3505  if ($action == 'editpaymentterm') {
3506  $form->form_date($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->date_lim_reglement, 'paymentterm');
3507  } else {
3508  print dol_print_date($object->date_lim_reglement, 'day');
3509  if ($object->hasDelay()) {
3510  print img_warning($langs->trans('Late'));
3511  }
3512  }
3513  } else {
3514  print '&nbsp;';
3515  }
3516  print '</td></tr>';
3517 
3518  // Payment mode
3519  print '<tr><td>';
3520  print '<table class="nobordernopadding" width="100%"><tr><td>';
3521  print $langs->trans('PaymentMode');
3522  print '</td>';
3523  if ($action != 'editmode' && $user->rights->facture->creer)
3524  print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmode&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetMode'), 1) . '</a></td>';
3525  print '</tr></table>';
3526  print '</td><td>';
3527  if ($action == 'editmode')
3528  {
3529  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT');
3530  }
3531  else
3532  {
3533  $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'none', 'CRDT');
3534  }
3535  print '</td></tr>';
3536 
3537  // Multicurrency
3538  if (! empty($conf->multicurrency->enabled))
3539  {
3540  // Multicurrency code
3541  print '<tr>';
3542  print '<td>';
3543  print '<table class="nobordernopadding" width="100%"><tr><td>';
3544  print fieldLabel('Currency','multicurrency_code');
3545  print '</td>';
3546  if ($action != 'editmulticurrencycode' && ! empty($object->brouillon))
3547  print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencycode&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
3548  print '</tr></table>';
3549  print '</td><td>';
3550  if ($action == 'editmulticurrencycode') {
3551  $form->form_multicurrency_code($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_code, 'multicurrency_code');
3552  } else {
3553  $form->form_multicurrency_code($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_code, 'none');
3554  }
3555  print '</td></tr>';
3556 
3557  print '<tr>';
3558  print '<td>';
3559  print '<table class="nobordernopadding" width="100%"><tr><td>';
3560  print fieldLabel('CurrencyRate','multicurrency_tx');
3561  print '</td>';
3562  if ($action != 'editmulticurrencyrate' && ! empty($object->brouillon) && $object->multicurrency_code && $object->multicurrency_code != $conf->currency)
3563  print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencyrate&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
3564  print '</tr></table>';
3565  print '</td><td>';
3566  if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
3567  if($action == 'actualizemulticurrencyrate') {
3568  list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
3569  }
3570  $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'multicurrency_tx', $object->multicurrency_code);
3571  } else {
3572  $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
3573  if($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
3574  print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
3575  print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=actualizemulticurrencyrate">'.$langs->trans("ActualizeCurrency").'</a>';
3576  print '</div>';
3577  }
3578  }
3579  print '</td></tr>';
3580  }
3581 
3582  // Bank Account
3583  print '<tr><td class="nowrap">';
3584  print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
3585  print $langs->trans('BankAccount');
3586  print '<td>';
3587  if (($action != 'editbankaccount') && $user->rights->facture->creer)
3588  print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editbankaccount&amp;id='.$object->id.'">'.img_edit($langs->trans('SetBankAccount'),1).'</a></td>';
3589  print '</tr></table>';
3590  print '</td><td>';
3591  if ($action == 'editbankaccount')
3592  {
3593  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1);
3594  }
3595  else
3596  {
3597  $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
3598  }
3599  print "</td>";
3600  print '</tr>';
3601 
3602  // Situations
3603  if (! empty($conf->global->INVOICE_USE_SITUATION))
3604  {
3605  if ($object->type == 5 && ($object->situation_counter > 1))
3606  {
3607  $prevsits = $object->get_prev_sits();
3608  print '<tr><td>';
3609  print $langs->trans('SituationAmount');
3610  print ' ';
3611 
3612  print $prevsits[0]->situation_counter;
3613  $cprevsits = count($prevsits);
3614 
3615  for ($i = 1; $i < $cprevsits; $i++) {
3616  print ' + ';
3617  print $prevsits[$i]->situation_counter;
3618  }
3619  print ' + ';
3620  print $object->situation_counter;
3621 
3622  print '</td>';
3623  print '<td class="nowrap">';
3624 
3625  $prevsits_total_amount = 0;
3626  foreach ($prevsits as $situation) {
3627  $prevsits_total_amount += $situation->total_ht;
3628  }
3629  $prevsits_total_amount += $object->total_ht;
3630 
3631  print price($prevsits_total_amount, 0, $langs, 1, -1, -1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency) );
3632 
3633  print '</td></tr>';
3634 
3635  // Previous situation(s) deduction(s)
3636  for ($i = 0; $i < $cprevsits; $i++) {
3637  print '<tr><td>';
3638  print '<a href="' . $_SERVER['PHP_SELF'] . '?facid=' . $prevsits[$i]->id . '">';
3639  print $langs->trans('SituationDeduction');
3640  print ' ';
3641  print $prevsits[$i]->situation_counter;
3642  print '</a></td>';
3643 
3644  print '<td class="nowrap">';
3645  print '- ' . price($prevsits[$i]->total_ht, 0, $langs, 1, -1, -1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency) );
3646  print '</td></tr>';
3647  }
3648  }
3649  }
3650 
3651  // Incoterms
3652  if (!empty($conf->incoterm->enabled))
3653  {
3654  print '<tr><td>';
3655  print '<table width="100%" class="nobordernopadding"><tr><td>';
3656  print $langs->trans('IncotermLabel');
3657  print '<td><td align="right">';
3658  if ($user->rights->facture->creer) print '<a href="'.DOL_URL_ROOT.'/compta/facture/card.php?facid='.$object->id.'&action=editincoterm">'.img_edit().'</a>';
3659  else print '&nbsp;';
3660  print '</td></tr></table>';
3661  print '</td>';
3662  print '<td>';
3663  if ($action != 'editincoterm')
3664  {
3665  print $form->textwithpicto($object->display_incoterms(), $object->libelle_incoterms, 1);
3666  }
3667  else
3668  {
3669  print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''), $_SERVER['PHP_SELF'].'?id='.$object->id);
3670  }
3671  print '</td></tr>';
3672  }
3673 
3674  // Other attributes
3675  $cols = 2;
3676  include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
3677 
3678  print '</table>';
3679 
3680  print '</div>';
3681  print '<div class="fichehalfright">';
3682  print '<div class="ficheaddleft">';
3683  print '<div class="underbanner clearboth"></div>';
3684 
3685  print '<table class="border centpercent">';
3686 
3687  if (!empty($conf->multicurrency->enabled) && ($object->multicurrency_code != $conf->currency))
3688  {
3689  // Multicurrency Amount HT
3690  print '<tr><td class="titlefieldmiddle">' . fieldLabel('MulticurrencyAmountHT','multicurrency_total_ht') . '</td>';
3691  print '<td class="nowrap amountcard">' . price($object->multicurrency_total_ht, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
3692  print '</tr>';
3693 
3694  // Multicurrency Amount VAT
3695  print '<tr><td>' . fieldLabel('MulticurrencyAmountVAT','multicurrency_total_tva') . '</td>';
3696  print '<td class="nowrap amountcard">' . price($object->multicurrency_total_tva, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
3697  print '</tr>';
3698 
3699  // Multicurrency Amount TTC
3700  print '<tr><td>' . fieldLabel('MulticurrencyAmountTTC','multicurrency_total_ttc') . '</td>';
3701  print '<td class="nowrap amountcard">' . price($object->multicurrency_total_ttc, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
3702  print '</tr>';
3703  }
3704 
3705  // Amount
3706  print '<tr><td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
3707  print '<td class="nowrap amountcard">' . price($object->total_ht, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
3708 
3709  // Vat
3710  print '<tr><td>' . $langs->trans('AmountVAT') . '</td><td colspan="3" class="nowrap amountcard">' . price($object->total_tva, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
3711  print '</tr>';
3712 
3713  // Amount Local Taxes
3714  if (($mysoc->localtax1_assuj == "1" && $mysoc->useLocalTax(1)) || $object->total_localtax1 != 0) // Localtax1
3715  {
3716  print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
3717  print '<td class="nowrap amountcard">' . price($object->total_localtax1, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
3718  }
3719  if (($mysoc->localtax2_assuj == "1" && $mysoc->useLocalTax(2)) || $object->total_localtax2 != 0) // Localtax2
3720  {
3721  print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
3722  print '<td class=nowrap amountcard">' . price($object->total_localtax2, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
3723  }
3724 
3725  // Revenue stamp
3726  if ($selleruserevenustamp) // Test company use revenue stamp
3727  {
3728  print '<tr><td>';
3729  print '<table class="nobordernopadding" width="100%"><tr><td>';
3730  print $langs->trans('RevenueStamp');
3731  print '</td>';
3732  if ($action != 'editrevenuestamp' && ! empty($object->brouillon) && $user->rights->facture->creer)
3733  {
3734  print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editrevenuestamp&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetRevenuStamp'), 1) . '</a></td>';
3735  }
3736  print '</tr></table>';
3737  print '</td><td>';
3738  if ($action == 'editrevenuestamp') {
3739  print '<form action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
3740  print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
3741  print '<input type="hidden" name="action" value="setrevenuestamp">';
3742  print '<input type="hidden" name="revenuestamp" id="revenuestamp_val" value="'.price2num($object->revenuestamp).'">';
3743  print $formother->select_revenue_stamp('', 'revenuestamp_type', $mysoc->country_code);
3744  print ' &rarr; <span id="revenuestamp_span"></span>';
3745  print ' <input type="submit" class="button" value="' . $langs->trans('Modify') . '">';
3746  print '</form>';
3747  print " <script>
3748  $(document).ready(function(){
3749  js_recalculate_revenuestamp();
3750  $('select[name=revenuestamp_type]').on('change',function(){
3751  js_recalculate_revenuestamp();
3752  });
3753  });
3754  function js_recalculate_revenuestamp(){
3755  var valselected = $('select[name=revenuestamp_type]').val();
3756  console.log('Calculate revenue stamp from '+valselected);
3757  var revenue = 0;
3758  if (valselected.indexOf('%') == -1)
3759  {
3760  revenue = valselected;
3761  }
3762  else
3763  {
3764  var revenue_type = parseFloat(valselected);
3765  var amount_net = ".round($object->total_ht, 2).";
3766  revenue = revenue_type * amount_net / 100;
3767  revenue = revenue.toFixed(2);
3768  }
3769  $('#revenuestamp_val').val(revenue);
3770  $('#revenuestamp_span').html(revenue);
3771  }
3772  </script>";
3773  } else {
3774  print price($object->revenuestamp, 1, '', 1, - 1, - 1, $conf->currency);
3775  }
3776  print '</td></tr>';
3777  }
3778 
3779  // Total with tax
3780  print '<tr><td>' . $langs->trans('AmountTTC') . '</td><td class="nowrap amountcard">' . price($object->total_ttc, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
3781 
3782  print '</table>';
3783 
3784 
3785  // List of previous situation invoices
3786 
3787  $sign = 1;
3788  if ($object->type == Facture::TYPE_CREDIT_NOTE) $sign = - 1;
3789  $nbrows = 8;
3790  $nbcols = 3;
3791  if (! empty($conf->projet->enabled))
3792  $nbrows ++;
3793  if (! empty($conf->banque->enabled)) {
3794  $nbrows ++;
3795  $nbcols ++;
3796  }
3797  if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0)
3798  $nbrows ++;
3799  if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0)
3800  $nbrows ++;
3801  if ($selleruserevenustamp)
3802  $nbrows ++;
3803  if (! empty($conf->multicurrency->enabled))
3804  $nbrows += 5;
3805  if (! empty($conf->incoterm->enabled))
3806  $nbrows += 1;
3807 
3808  if ($object->type == Facture::TYPE_SITUATION && ! empty($conf->global->INVOICE_USE_SITUATION))
3809  {
3810  if (count($object->tab_previous_situation_invoice) > 0 || count($object->tab_next_situation_invoice) > 0)
3811  print '<table class="noborder situationstable" width="100%">';
3812 
3813  if (count($object->tab_previous_situation_invoice) > 0) {
3814  // List of previous invoices
3815  print '<tr class="liste_titre">';
3816  print '<td>' . $langs->trans('ListOfPreviousSituationInvoices') . '</td>';
3817  print '<td></td>';
3818  if (! empty($conf->banque->enabled)) print '<td align="right"></td>';
3819  print '<td align="right">' . $langs->trans('AmountHT') . '</td>';
3820  print '<td align="right">' . $langs->trans('AmountTTC') . '</td>';
3821  print '<td width="18">&nbsp;</td>';
3822  print '</tr>';
3823 
3824  $total_prev_ht = $total_prev_ttc = 0;
3825  foreach ($object->tab_previous_situation_invoice as $prev_invoice) {
3826  $totalpaye = $prev_invoice->getSommePaiement();
3827  $total_prev_ht += $prev_invoice->total_ht;
3828  $total_prev_ttc += $prev_invoice->total_ttc;
3829  print '<tr class="oddeven">';
3830  print '<td>' . $prev_invoice->getNomUrl(1) . '</td>';
3831  print '<td></td>';
3832  if (! empty($conf->banque->enabled)) print '<td align="right"></td>';
3833  print '<td align="right">' . price($prev_invoice->total_ht) . '</td>';
3834  print '<td align="right">' . price($prev_invoice->total_ttc) . '</td>';
3835  print '<td align="right">' . $prev_invoice->getLibStatut(3, $totalpaye) . '</td>';
3836  print '</tr>';
3837 
3838  }
3839 
3840  print '<tr class="oddeven">';
3841  print '<td></td>';
3842  print '<td></td>';
3843  if (! empty($conf->banque->enabled)) print '<td></td>';
3844  print '<td align="right"><b>' . price($total_prev_ht) . '</b></td>';
3845  print '<td align="right"><b>' . price($total_prev_ttc) . '</b></td>';
3846  print '<td width="18">&nbsp;</td>';
3847  print '</tr>';
3848  }
3849 
3850  if (count($object->tab_next_situation_invoice) > 0) {
3851  // List of next invoices
3852  print '<tr class="liste_titre">';
3853  print '<td>' . $langs->trans('ListOfNextSituationInvoices') . '</td>';
3854  print '<td></td>';
3855  if (! empty($conf->banque->enabled)) print '<td align="right"></td>';
3856  print '<td align="right">' . $langs->trans('AmountHT') . '</td>';
3857  print '<td align="right">' . $langs->trans('AmountTTC') . '</td>';
3858  print '<td width="18">&nbsp;</td>';
3859  print '</tr>';
3860 
3861  $total_next_ht = $total_next_ttc = 0;
3862 
3863  foreach ($object->tab_next_situation_invoice as $next_invoice) {
3864  $totalpaye = $next_invoice->getSommePaiement();
3865  $total_next_ht += $next_invoice->total_ht;
3866  $total_next_ttc += $next_invoice->total_ttc;
3867  print '<tr class="oddeven">';
3868  print '<td>' . $next_invoice->getNomUrl(1) . '</td>';
3869  print '<td></td>';
3870  if (! empty($conf->banque->enabled)) print '<td align="right"></td>';
3871  print '<td align="right">' . price($next_invoice->total_ht) . '</td>';
3872  print '<td align="right">' . price($next_invoice->total_ttc) . '</td>';
3873  print '<td align="right">' . $next_invoice->getLibStatut(3, $totalpaye) . '</td>';
3874  print '</tr>';
3875 
3876  }
3877 
3878  print '<tr class="oddeven">';
3879  print '<td colspan="2" align="right"></td>';
3880  if (! empty($conf->banque->enabled)) print '<td align="right"></td>';
3881 
3882  print '<td align="right"><b>' . price($total_next_ht) . '</b></td>';
3883  print '<td align="right"><b>' . price($total_next_ttc) . '</b></td>';
3884  print '<td width="18">&nbsp;</td>';
3885  print '</tr>';
3886  }
3887 
3888  if (count($object->tab_previous_situation_invoice) > 0 || count($object->tab_next_situation_invoice) > 0)
3889  print '</table>';
3890  }
3891 
3892 
3893  // List of payments already done
3894 
3895  print '<div class="div-table-responsive-no-min">';
3896  print '<table class="noborder paymenttable" width="100%">';
3897 
3898  print '<tr class="liste_titre">';
3899  print '<td class="liste_titre">' . ($object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("PaymentsBack") : $langs->trans('Payments')) . '</td>';
3900  print '<td class="liste_titre">' . $langs->trans('Date') . '</td>';
3901  print '<td class="liste_titre">' . $langs->trans('Type') . '</td>';
3902  if (! empty($conf->banque->enabled)) {
3903  print '<td class="liste_titre" align="right">' . $langs->trans('BankAccount') . '</td>';
3904  }
3905  print '<td class="liste_titre" align="right">' . $langs->trans('Amount') . '</td>';
3906  print '<td class="liste_titre" width="18">&nbsp;</td>';
3907  print '</tr>';
3908 
3909  // Payments already done (from payment on this invoice)
3910  $sql = 'SELECT p.datep as dp, p.ref, p.num_paiement, p.rowid, p.fk_bank,';
3911  $sql .= ' c.code as payment_code, c.libelle as payment_label,';
3912  $sql .= ' pf.amount,';
3913  $sql .= ' ba.rowid as baid, ba.ref as baref, ba.label, ba.number as banumber, ba.account_number, ba.fk_accountancy_journal';
3914  $sql .= ' FROM ' . MAIN_DB_PREFIX . 'paiement_facture as pf, ' . MAIN_DB_PREFIX . 'paiement as p';
3915  $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'c_paiement as c ON p.fk_paiement = c.id' ;
3916  $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'bank as b ON p.fk_bank = b.rowid';
3917  $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'bank_account as ba ON b.fk_account = ba.rowid';
3918  $sql .= ' WHERE pf.fk_facture = ' . $object->id . ' AND pf.fk_paiement = p.rowid';
3919  $sql .= ' AND p.entity IN (' . getEntity('facture').')';
3920  $sql .= ' ORDER BY p.datep, p.tms';
3921 
3922  $result = $db->query($sql);
3923  if ($result) {
3924  $num = $db->num_rows($result);
3925  $i = 0;
3926 
3927  // if ($object->type != 2)
3928  // {
3929  if ($num > 0) {
3930  while ($i < $num) {
3931  $objp = $db->fetch_object($result);
3932 
3933  $paymentstatic->id = $objp->rowid;
3934  $paymentstatic->datepaye = $db->jdate($objp->dp);
3935  $paymentstatic->ref = $objp->ref;
3936  $paymentstatic->num_paiement = $objp->num_paiement;
3937  $paymentstatic->payment_code = $objp->payment_code;
3938 
3939  print '<tr class="oddeven"><td>';
3940  print $paymentstatic->getNomUrl(1);
3941  print '</td>';
3942  print '<td>' . dol_print_date($db->jdate($objp->dp), 'day') . '</td>';
3943  $label = ($langs->trans("PaymentType" . $objp->payment_code) != ("PaymentType" . $objp->payment_code)) ? $langs->trans("PaymentType" . $objp->payment_code) : $objp->payment_label;
3944  print '<td>' . $label . ' ' . $objp->num_paiement . '</td>';
3945  if (! empty($conf->banque->enabled))
3946  {
3947  $bankaccountstatic->id = $objp->baid;
3948  $bankaccountstatic->ref = $objp->baref;
3949  $bankaccountstatic->label = $objp->baref;
3950  $bankaccountstatic->number = $objp->banumber;
3951 
3952  if (! empty($conf->accounting->enabled)) {
3953  $bankaccountstatic->account_number = $objp->account_number;
3954 
3955  $accountingjournal = new AccountingJournal($db);
3956  $accountingjournal->fetch($objp->fk_accountancy_journal);
3957  $bankaccountstatic->accountancy_journal = $accountingjournal->getNomUrl(0,1,1,'',1);
3958  }
3959 
3960  print '<td align="right">';
3961  if ($bankaccountstatic->id)
3962  print $bankaccountstatic->getNomUrl(1, 'transactions');
3963  print '</td>';
3964  }
3965  print '<td align="right">' . price($sign * $objp->amount) . '</td>';
3966  print '<td align="center">';
3967  if ($object->statut == Facture::STATUS_VALIDATED && $object->paye == 0 && $user->societe_id == 0)
3968  {
3969  print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=deletepaiement&paiement_id='.$objp->rowid.'">';
3970  print img_delete();
3971  print '</a>';
3972  }
3973  print '</td>';
3974  print '</tr>';
3975  $i ++;
3976  }
3977  }
3978  /*else {
3979  print '<tr class="oddeven"><td colspan="' . $nbcols . '" class="opacitymedium">' . $langs->trans("None") . '</td><td></td><td></td></tr>';
3980  }*/
3981  // }
3982  $db->free($result);
3983  } else {
3984  dol_print_error($db);
3985  }
3986 
3987  if ($object->type != Facture::TYPE_CREDIT_NOTE) {
3988  // Total already paid
3989  print '<tr><td colspan="' . $nbcols . '" align="right">';
3990  if ($object->type != Facture::TYPE_DEPOSIT)
3991  print $langs->trans('AlreadyPaidNoCreditNotesNoDeposits');
3992  else
3993  print $langs->trans('AlreadyPaid');
3994  print ' :</td><td align="right"'.(($totalpaye > 0)?' class="amountalreadypaid"':'').'>' . price($totalpaye) . '</td><td>&nbsp;</td></tr>';
3995 
3996  $resteapayeraffiche = $resteapayer;
3997  $cssforamountpaymentcomplete = 'amountpaymentcomplete';
3998 
3999  // Loop on each credit note or deposit amount applied
4000  $creditnoteamount = 0;
4001  $depositamount = 0;
4002  $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
4003  $sql .= " re.description, re.fk_facture_source";
4004  $sql .= " FROM " . MAIN_DB_PREFIX . "societe_remise_except as re";
4005  $sql .= " WHERE fk_facture = " . $object->id;
4006  $resql = $db->query($sql);
4007  if ($resql) {
4008  $num = $db->num_rows($resql);
4009  $i = 0;
4010  $invoice = new Facture($db);
4011  while ($i < $num) {
4012  $obj = $db->fetch_object($resql);
4013  $invoice->fetch($obj->fk_facture_source);
4014  print '<tr><td colspan="' . $nbcols . '" align="right">';
4015  if ($invoice->type == Facture::TYPE_CREDIT_NOTE)
4016  print $langs->trans("CreditNote") . ' ';
4017  if ($invoice->type == Facture::TYPE_DEPOSIT)
4018  print $langs->trans("Deposit") . ' ';
4019  print $invoice->getNomUrl(0);
4020  print ' :</td>';
4021  print '<td align="right">' . price($obj->amount_ttc) . '</td>';
4022  print '<td align="right">';
4023  print '<a href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&action=unlinkdiscount&discountid=' . $obj->rowid . '">' . img_delete() . '</a>';
4024  print '</td></tr>';
4025  $i ++;
4026  if ($invoice->type == Facture::TYPE_CREDIT_NOTE)
4027  $creditnoteamount += $obj->amount_ttc;
4028  if ($invoice->type == Facture::TYPE_DEPOSIT)
4029  $depositamount += $obj->amount_ttc;
4030  }
4031  } else {
4032  dol_print_error($db);
4033  }
4034 
4035  // Paye partiellement 'escompte'
4036  if (($object->statut == Facture::STATUS_CLOSED || $object->statut == Facture::STATUS_ABANDONED) && $object->close_code == 'discount_vat') {
4037  print '<tr><td colspan="' . $nbcols . '" align="right" class="nowrap">';
4038  print $form->textwithpicto($langs->trans("Discount") . ':', $langs->trans("HelpEscompte"), - 1);
4039  print '</td><td align="right">' . price($object->total_ttc - $creditnoteamount - $depositamount - $totalpaye) . '</td><td>&nbsp;</td></tr>';
4040  $resteapayeraffiche = 0;
4041  $cssforamountpaymentcomplete = '';
4042  }
4043  // Paye partiellement ou Abandon 'badcustomer'
4044  if (($object->statut == Facture::STATUS_CLOSED || $object->statut == Facture::STATUS_ABANDONED) && $object->close_code == 'badcustomer') {
4045  print '<tr><td colspan="' . $nbcols . '" align="right" class="nowrap">';
4046  print $form->textwithpicto($langs->trans("Abandoned") . ':', $langs->trans("HelpAbandonBadCustomer"), - 1);
4047  print '</td><td align="right">' . price($object->total_ttc - $creditnoteamount - $depositamount - $totalpaye) . '</td><td>&nbsp;</td></tr>';
4048  // $resteapayeraffiche=0;
4049  $cssforamountpaymentcomplete = '';
4050  }
4051  // Paye partiellement ou Abandon 'product_returned'
4052  if (($object->statut == Facture::STATUS_CLOSED || $object->statut == Facture::STATUS_ABANDONED) && $object->close_code == 'product_returned') {
4053  print '<tr><td colspan="' . $nbcols . '" align="right" class="nowrap">';
4054  print $form->textwithpicto($langs->trans("ProductReturned") . ':', $langs->trans("HelpAbandonProductReturned"), - 1);
4055  print '</td><td align="right">' . price($object->total_ttc - $creditnoteamount - $depositamount - $totalpaye) . '</td><td>&nbsp;</td></tr>';
4056  $resteapayeraffiche = 0;
4057  $cssforamountpaymentcomplete = '';
4058  }
4059  // Paye partiellement ou Abandon 'abandon'
4060  if (($object->statut == Facture::STATUS_CLOSED || $object->statut == Facture::STATUS_ABANDONED) && $object->close_code == 'abandon') {
4061  print '<tr><td colspan="' . $nbcols . '" align="right" class="nowrap">';
4062  $text = $langs->trans("HelpAbandonOther");
4063  if ($object->close_note)
4064  $text .= '<br><br><b>' . $langs->trans("Reason") . '</b>:' . $object->close_note;
4065  print $form->textwithpicto($langs->trans("Abandoned") . ':', $text, - 1);
4066  print '</td><td align="right">' . price($object->total_ttc - $creditnoteamount - $depositamount - $totalpaye) . '</td><td>&nbsp;</td></tr>';
4067  $resteapayeraffiche = 0;
4068  $cssforamountpaymentcomplete = '';
4069  }
4070 
4071  // Billed
4072  print '<tr><td colspan="' . $nbcols . '" align="right">' . $langs->trans("Billed") . ' :</td><td align="right">' . price($object->total_ttc) . '</td><td>&nbsp;</td></tr>';
4073 
4074  // Remainder to pay
4075  print '<tr><td colspan="' . $nbcols . '" align="right">';
4076  if ($resteapayeraffiche >= 0)
4077  print $langs->trans('RemainderToPay');
4078  else
4079  print $langs->trans('ExcessReceived');
4080  print ' :</td>';
4081  print '<td align="right"'.($resteapayeraffiche?' class="amountremaintopay"':(' class="'.$cssforamountpaymentcomplete.'"')).'>' . price($resteapayeraffiche) . '</td>';
4082  print '<td class="nowrap">&nbsp;</td></tr>';
4083  }
4084  else // Credit note
4085  {
4086  $cssforamountpaymentcomplete='';
4087 
4088  // Total already paid back
4089  print '<tr><td colspan="' . $nbcols . '" align="right">';
4090  print $langs->trans('AlreadyPaidBack');
4091  print ' :</td><td align="right">' . price($sign * $totalpaye) . '</td><td>&nbsp;</td></tr>';
4092 
4093  // Billed
4094  print '<tr><td colspan="' . $nbcols . '" align="right">' . $langs->trans("Billed") . ' :</td><td align="right">' . price($sign * $object->total_ttc) . '</td><td>&nbsp;</td></tr>';
4095 
4096  // Remainder to pay back
4097  print '<tr><td colspan="' . $nbcols . '" align="right">';
4098  if ($resteapayeraffiche <= 0)
4099  print $langs->trans('RemainderToPayBack');
4100  else
4101  print $langs->trans('ExcessPaydBack');
4102  print ' :</td>';
4103  print '<td align="right"'.($resteapayeraffiche?' class="amountremaintopayback"':(' class="'.$cssforamountpaymentcomplete.'"')).'>' . price($sign * $resteapayeraffiche) . '</td>';
4104  print '<td class="nowrap">&nbsp;</td></tr>';
4105 
4106  // Sold credit note
4107  // print '<tr><td colspan="'.$nbcols.'" align="right">'.$langs->trans('TotalTTC').' :</td>';
4108  // print '<td align="right" style="border: 1px solid;" bgcolor="#f0f0f0"><b>'.price($sign *
4109  // $object->total_ttc).'</b></td><td>&nbsp;</td></tr>';
4110  }
4111 
4112  print '</table>';
4113  print '</div>';
4114 
4115  // Margin Infos
4116  if (! empty($conf->margin->enabled)) {
4117  $formmargin->displayMarginInfos($object);
4118  }
4119 
4120  print '</div>';
4121  print '</div>';
4122  print '</div>';
4123 
4124  print '<div class="clearboth"></div><br>';
4125 
4126  if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) {
4127  $blocname = 'contacts';
4128  $title = $langs->trans('ContactsAddresses');
4129  include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_showhide.tpl.php';
4130  }
4131 
4132  if (! empty($conf->global->MAIN_DISABLE_NOTES_TAB)) {
4133  $blocname = 'notes';
4134  $title = $langs->trans('Notes');
4135  include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_showhide.tpl.php';
4136  }
4137 
4138  // Lines
4139  $result = $object->getLinesArray();
4140 
4141  // Show global modifiers
4142  if (! empty($conf->global->INVOICE_USE_SITUATION))
4143  {
4144  if ($object->situation_cycle_ref && $object->statut == 0) {
4145  print '<div class="div-table-responsive">';
4146 
4147  print '<form name="updatealllines" id="updatealllines" action="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '#updatealllines" method="POST">';
4148  print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '" />';
4149  print '<input type="hidden" name="action" value="updatealllines" />';
4150  print '<input type="hidden" name="id" value="' . $object->id . '" />';
4151 
4152  print '<table id="tablelines_all_progress" class="noborder noshadow" width="100%">';
4153 
4154  print '<tr class="liste_titre nodrag nodrop">';
4155 
4156  if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
4157  print '<td align="center" width="5">&nbsp;</td>';
4158  }
4159  print '<td>' . $langs->trans('ModifyAllLines') . '</td>';
4160  print '<td align="right" width="50">&nbsp;</td>';
4161  print '<td align="right" width="80">&nbsp;</td>';
4162  if ($inputalsopricewithtax) print '<td align="right" width="80">&nbsp;</td>';
4163  print '<td align="right" width="50">&nbsp</td>';
4164  print '<td align="right" width="50">&nbsp</td>';
4165  print '<td align="right" width="50">' . $langs->trans('Progress') . '</td>';
4166  if (! empty($conf->margin->enabled) && empty($user->societe_id))
4167  {
4168  print '<td align="right" class="margininfos" width="80">&nbsp;</td>';
4169  if ((! empty($conf->global->DISPLAY_MARGIN_RATES) || ! empty($conf->global->DISPLAY_MARK_RATES)) && $user->rights->margins->liretous) {
4170  print '<td align="right" class="margininfos" width="50">&nbsp;</td>';
4171  }
4172  }
4173  print '<td align="right" width="50">&nbsp;</td>';
4174  print '<td>&nbsp;</td>';
4175  print '<td width="10">&nbsp;</td>';
4176  print '<td width="10">&nbsp;</td>';
4177  print "</tr>\n";
4178 
4179  if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
4180  print '<td align="center" width="5">&nbsp;</td>';
4181  }
4182  print '<tr width="100%" class="nodrag nodrop">';
4183  print '<td>&nbsp;</td>';
4184  print '<td width="50">&nbsp;</td>';
4185  print '<td width="80">&nbsp;</td>';
4186  print '<td width="50">&nbsp;</td>';
4187  print '<td width="50">&nbsp;</td>';
4188  print '<td align="right" class="nowrap"><input type="text" size="1" value="" name="all_progress">%</td>';
4189  print '<td colspan="4" align="right"><input class="button" type="submit" name="all_percent" value="Modifier" /></td>';
4190  print '</tr>';
4191 
4192  print '</table>';
4193 
4194  print '</form>';
4195 
4196  print '</div>';
4197  }
4198  }
4199 
4200  print ' <form name="addproduct" id="addproduct" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . (($action != 'editline') ? '#addline' : '#line_' . GETPOST('lineid')) . '" method="POST">
4201  <input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">
4202  <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateligne') . '">
4203  <input type="hidden" name="mode" value="">
4204  <input type="hidden" name="id" value="' . $object->id . '">
4205  ';
4206 
4207  if (! empty($conf->use_javascript_ajax) && $object->statut == 0) {
4208  include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
4209  }
4210 
4211  print '<div class="div-table-responsive-no-min">';
4212  print '<table id="tablelines" class="noborder noshadow" width="100%">';
4213 
4214  // Show object lines
4215  if (! empty($object->lines))
4216  $ret = $object->printObjectLines($action, $mysoc, $soc, $lineid, 1);
4217 
4218  // Form to add new line
4219  if ($object->statut == 0 && $user->rights->facture->creer && $action != 'valid' && $action != 'editline' && ($object->is_first() || !$object->situation_cycle_ref))
4220  {
4221  if ($action != 'editline')
4222  {
4223  // Add free products/services
4224  $object->formAddObjectLine(1, $mysoc, $soc);
4225 
4226  $parameters = array();
4227  $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
4228  }
4229  }
4230 
4231  print "</table>\n";
4232  print "</div>";
4233 
4234  print "</form>\n";
4235 
4236  dol_fiche_end();
4237 
4238 
4239  // Actions buttons
4240 
4241  if ($action != 'prerelance' && $action != 'presend' && $action != 'valid' && $action != 'editline')
4242  {
4243  print '<div class="tabsAction">';
4244 
4245  $parameters = array();
4246  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
4247  if (empty($reshook)) {
4248  // Editer une facture deja validee, sans paiement effectue et pas exporte en compta
4249  if ($object->statut == Facture::STATUS_VALIDATED)
4250  {
4251  // On verifie si les lignes de factures ont ete exportees en compta et/ou ventilees
4252  $ventilExportCompta = $object->getVentilExportCompta();
4253 
4254  if ($ventilExportCompta == 0)
4255  {
4256  if (! empty($conf->global->INVOICE_CAN_ALWAYS_BE_EDITED) || ($resteapayer == $object->total_ttc && empty($object->paye)))
4257  {
4258  if (! $objectidnext && $object->is_last_in_cycle())
4259  {
4260  if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->creer))
4261  || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->invoice_advance->unvalidate)))
4262  {
4263  print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=modif">' . $langs->trans('Modify') . '</a></div>';
4264  } else {
4265  print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("NotEnoughPermissions") . '">' . $langs->trans('Modify') . '</span></div>';
4266  }
4267  } else if (!$object->is_last_in_cycle()) {
4268  print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("NotLastInCycle") . '">' . $langs->trans('Modify') . '</span></div>';
4269  } else {
4270  print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('Modify') . '</span></div>';
4271  }
4272  }
4273  }
4274  else
4275  {
4276  print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseDispatchedInAccounting") . '">' . $langs->trans('Modify') . '</span></div>';
4277  }
4278  }
4279 
4280  $discount = new DiscountAbsolute($db);
4281  $result = $discount->fetch(0, $object->id);
4282 
4283  // Reopen a standard paid invoice
4284  if ((($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT)
4285  || ($object->type == Facture::TYPE_CREDIT_NOTE && empty($discount->id))
4286  || ($object->type == Facture::TYPE_DEPOSIT && empty($discount->id)))
4287  && ($object->statut == 2 || $object->statut == 3 || ($object->statut == 1 && $object->paye == 1)) // Condition ($object->statut == 1 && $object->paye == 1) should not happened but can be found due to corrupted data
4288  && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->facture->creer) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->facture->invoice_advance->reopen))) // A paid invoice (partially or completely)
4289  {
4290  if (! $objectidnext && $object->close_code != 'replaced') // Not replaced by another invoice
4291  {
4292  print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=reopen">' . $langs->trans('ReOpen') . '</a></div>';
4293  } else {
4294  print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('ReOpen') . '</span></div>';
4295  }
4296  }
4297 
4298  // Validate
4299  if ($object->statut == Facture::STATUS_DRAFT && count($object->lines) > 0 && ((($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA || $object->type == Facture::TYPE_SITUATION) && (! empty($conf->global->FACTURE_ENABLE_NEGATIVE) || $object->total_ttc >= 0)) || ($object->type == Facture::TYPE_CREDIT_NOTE && $object->total_ttc <= 0))) {
4300  if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->creer))
4301  || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->invoice_advance->validate)))
4302  {
4303  print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&amp;action=valid">' . $langs->trans('Validate') . '</a></div>';
4304  }
4305  }
4306 
4307  // Send by mail
4308  if (($object->statut == Facture::STATUS_VALIDATED || $object->statut == Facture::STATUS_CLOSED) || ! empty($conf->global->FACTURE_SENDBYEMAIL_FOR_ALL_STATUS)) {
4309  if ($objectidnext) {
4310  print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('SendByMail') . '</span></div>';
4311  } else {
4312  if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->facture->invoice_advance->send) {
4313  print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&action=presend&mode=init#formmailbeforetitle">' . $langs->trans('SendByMail') . '</a></div>';
4314  } else
4315  print '<div class="inline-block divButAction"><a class="butActionRefused" href="#">' . $langs->trans('SendByMail') . '</a></div>';
4316  }
4317  }
4318 
4319  // Request a direct debit order
4320  if ($object->statut > Facture::STATUS_DRAFT && $object->paye == 0 && $num == 0)
4321  {
4322  if ($resteapayer > 0)
4323  {
4324  if ($user->rights->prelevement->bons->creer)
4325  {
4326  if (! $objectidnext && $object->close_code != 'replaced') // Not replaced by another invoice
4327  {
4328  print '<a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/prelevement.php?facid='.$object->id.'" title="'.dol_escape_htmltag($langs->trans("MakeWithdrawRequest")).'">'.$langs->trans("MakeWithdrawRequest").'</a>';
4329  } else {
4330  print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('MakeWithdrawRequest') . '</span></div>';
4331  }
4332  }
4333  else
4334  {
4335  //print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("MakeWithdrawRequest").'</a>';
4336  }
4337  }
4338  else
4339  {
4340  //print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("AmountMustBePositive")).'">'.$langs->trans("MakeWithdrawRequest").'</a>';
4341  }
4342  }
4343 
4344  // Create payment
4345  if ($object->type != Facture::TYPE_CREDIT_NOTE && $object->statut == 1 && $object->paye == 0 && $user->rights->facture->paiement) {
4346  if ($objectidnext) {
4347  print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('DoPayment') . '</span></div>';
4348  } else {
4349  //if ($resteapayer == 0) {
4350  // print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseRemainderToPayIsZero") . '">' . $langs->trans('DoPayment') . '</span></div>';
4351  //} else {
4352  print '<div class="inline-block divButAction"><a class="butAction" href="'. DOL_URL_ROOT .'/compta/paiement.php?facid=' . $object->id . '&amp;action=create&amp;accountid='.$object->fk_account.'">' . $langs->trans('DoPayment') . '</a></div>';
4353  //}
4354  }
4355  }
4356 
4357  // Reverse back money or convert to reduction
4358  if ($object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_STANDARD) {
4359  // For credit note only
4360  if ($object->type == Facture::TYPE_CREDIT_NOTE && $object->statut == 1 && $object->paye == 0 && $user->rights->facture->paiement)
4361  {
4362  if ($resteapayer == 0)
4363  {
4364  print '<div class="inline-block divButAction"><span class="butActionRefused" title="'.$langs->trans("DisabledBecauseRemainderToPayIsZero").'">'.$langs->trans('DoPaymentBack').'</span></div>';
4365  }
4366  else
4367  {
4368  print '<div class="inline-block divButAction"><a class="butAction" href="'. DOL_URL_ROOT .'/compta/paiement.php?facid='.$object->id.'&amp;action=create&amp;accountid='.$object->fk_account.'">'.$langs->trans('DoPaymentBack').'</a></div>';
4369  }
4370  }
4371 
4372  // For standard invoice with excess received
4373  if ($object->type == Facture::TYPE_STANDARD && empty($object->paye) && ($object->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits) < 0 && $user->rights->facture->creer && empty($discount->id))
4374  {
4375  print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&amp;action=converttoreduc">'.$langs->trans('ConvertExcessReceivedToReduc').'</a></div>';
4376  }
4377  // For credit note
4378  if ($object->type == Facture::TYPE_CREDIT_NOTE && $object->statut == 1 && $object->paye == 0 && $user->rights->facture->creer && $object->getSommePaiement() == 0) {
4379  print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&amp;action=converttoreduc">' . $langs->trans('ConvertToReduc') . '</a></div>';
4380  }
4381  // For deposit invoice
4382  if ($object->type == Facture::TYPE_DEPOSIT && $user->rights->facture->creer && empty($discount->id))
4383  {
4384  print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&amp;action=converttoreduc">'.$langs->trans('ConvertToReduc').'</a></div>';
4385  }
4386  }
4387 
4388  // Classify paid
4389  if ($object->statut == 1 && $object->paye == 0 && $user->rights->facture->paiement && (($object->type != Facture::TYPE_CREDIT_NOTE && $object->type != Facture::TYPE_DEPOSIT && $resteapayer <= 0) || ($object->type == Facture::TYPE_CREDIT_NOTE && $resteapayer >= 0))
4390  || ($object->type == Facture::TYPE_DEPOSIT && $object->paye == 0 && $object->total_ttc > 0 && $resteapayer == 0 && $user->rights->facture->paiement && empty($discount->id))
4391  )
4392  {
4393  print '<div class="inline-block divButAction"><a class="butAction" href="'.$_SERVER['PHP_SELF'].'?facid='.$object->id.'&amp;action=paid">'.$langs->trans('ClassifyPaid').'</a></div>';
4394  }
4395 
4396  // Classify 'closed not completely paid' (possible si validee et pas encore classee payee)
4397 
4398  if ($object->statut == 1 && $object->paye == 0 && $resteapayer > 0 && $user->rights->facture->paiement)
4399  {
4400  if ($totalpaye > 0 || $totalcreditnotes > 0)
4401  {
4402  // If one payment or one credit note was linked to this invoice
4403  print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=paid">' . $langs->trans('ClassifyPaidPartially') . '</a></div>';
4404  }
4405  else
4406  {
4407  if ( empty($conf->global->INVOICE_CAN_NEVER_BE_CANCELED))
4408  {
4409  if ($objectidnext)
4410  {
4411  print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('ClassifyCanceled') . '</span></div>';
4412  }
4413  else
4414  {
4415  print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=canceled">' . $langs->trans('ClassifyCanceled') . '</a></div>';
4416  }
4417  }
4418  }
4419  }
4420 
4421  // Clone
4422  if (($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA) && $user->rights->facture->creer)
4423  {
4424  print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=clone&amp;object=invoice">' . $langs->trans("ToClone") . '</a></div>';
4425  }
4426 
4427  // Clone as predefined / Create template
4428  if (($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA) && $object->statut == 0 && $user->rights->facture->creer)
4429  {
4430  if (! $objectidnext && count($object->lines) > 0)
4431  {
4432  print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/fiche-rec.php?facid=' . $object->id . '&amp;action=create">' . $langs->trans("ChangeIntoRepeatableInvoice") . '</a></div>';
4433  }
4434  }
4435 
4436  // Create a credit note
4437  if (($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA) && $object->statut > 0 && $user->rights->facture->creer)
4438  {
4439  if (! $objectidnext)
4440  {
4441  print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?socid=' . $object->socid .'&amp;fac_avoir=' . $object->id . '&amp;action=create&amp;type=2'.($object->fk_project > 0 ? '&amp;projectid='.$object->fk_project : '').'">' . $langs->trans("CreateCreditNote") . '</a></div>';
4442  }
4443  }
4444 
4445  // Create next situation invoice
4446  if ($user->rights->facture->creer && ($object->type == 5) && ($object->statut == 1 || $object->statut == 2)) {
4447  if ($object->is_last_in_cycle() && $object->situation_final != 1) {
4448  print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?action=create&amp;type=5&amp;origin=facture&amp;originid=' . $object->id . '&amp;socid=' . $object->socid . '" >' . $langs->trans('CreateNextSituationInvoice') . '</a></div>';
4449  } else if (!$object->is_last_in_cycle()) {
4450  print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseNotLastInCycle") . '">' . $langs->trans('CreateNextSituationInvoice') . '</a></div>';
4451  } else {
4452  print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseFinal") . '">' . $langs->trans('CreateNextSituationInvoice') . '</a></div>';
4453  }
4454  }
4455 
4456  // Delete
4457  if ($user->rights->facture->supprimer)
4458  {
4459  $isErasable = $object->is_erasable();
4460  //var_dump($isErasable);
4461  if ($isErasable == -4) {
4462  print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecausePayments") . '">' . $langs->trans('Delete') . '</a></div>';
4463  }
4464  elseif ($isErasable == -3) {
4465  print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseNotLastSituationInvoice") . '">' . $langs->trans('Delete') . '</a></div>';
4466  }
4467  elseif ($isErasable == -2) {
4468  print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseNotLastInvoice") . '">' . $langs->trans('Delete') . '</a></div>';
4469  }
4470  elseif ($isErasable == -1) {
4471  print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseDispatchedInBookkeeping") . '">' . $langs->trans('Delete') . '</a></div>';
4472  }
4473  elseif ($isErasable <= 0) // Any other cases
4474  {
4475  print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseNotErasable") . '">' . $langs->trans('Delete') . '</a></div>';
4476  }
4477  elseif ($objectidnext)
4478  {
4479  print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('Delete') . '</a></div>';
4480  }
4481  else
4482  {
4483  print '<div class="inline-block divButAction"><a class="butActionDelete" href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&amp;action=delete">' . $langs->trans('Delete') . '</a></div>';
4484  }
4485  } else {
4486  print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("NotAllowed") . '">' . $langs->trans('Delete') . '</a></div>';
4487  }
4488  }
4489  print '</div>';
4490  }
4491 
4492  // Select mail models is same action as presend
4493  if (GETPOST('modelselected','alpha')) {
4494  $action = 'presend';
4495  }
4496  if ($action != 'prerelance' && $action != 'presend')
4497  {
4498  print '<div class="fichecenter"><div class="fichehalfleft">';
4499  print '<a name="builddoc"></a>'; // ancre
4500 
4501  // Documents generes
4502  $filename = dol_sanitizeFileName($object->ref);
4503  $filedir = $conf->facture->dir_output . '/' . dol_sanitizeFileName($object->ref);
4504  $urlsource = $_SERVER['PHP_SELF'] . '?facid=' . $object->id;
4505  $genallowed = $user->rights->facture->lire;
4506  $delallowed = $user->rights->facture->creer;
4507 
4508  print $formfile->showdocuments('facture', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->modelpdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang);
4509  $somethingshown = $formfile->numoffiles;
4510 
4511  // Show links to link elements
4512  $linktoelem = $form->showLinkToObjectBlock($object, null, array('invoice'));
4513  $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
4514 
4515 
4516  // Show online payment link
4517  $useonlinepayment = (! empty($conf->paypal->enabled) || ! empty($conf->stripe->enabled) || ! empty($conf->paybox->enabled));
4518 
4519  if ($object->statut != Facture::STATUS_DRAFT && $useonlinepayment)
4520  {
4521  print '<br><!-- Link to pay -->'."\n";
4522  require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
4523  print showOnlinePaymentUrl('invoice', $object->ref).'<br>';
4524  }
4525 
4526  // Show direct download link
4527  if ($object->statut != Facture::STATUS_DRAFT && ! empty($conf->global->INVOICE_ALLOW_EXTERNAL_DOWNLOAD))
4528  {
4529  print '<br><!-- Link to download main doc -->'."\n";
4530  print showDirectDownloadLink($object).'<br>';
4531  }
4532 
4533  print '</div><div class="fichehalfright"><div class="ficheaddleft">';
4534 
4535  // List of actions on element
4536  include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php';
4537  $formactions = new FormActions($db);
4538  $somethingshown = $formactions->showactions($object, 'invoice', $socid, 1);
4539 
4540  print '</div></div></div>';
4541  }
4542 
4543 
4544  // Presend form
4545  $modelmail='facture_send';
4546  $defaulttopic='SendBillRef';
4547  $diroutput = $conf->facture->dir_output;
4548  $trackid = 'inv'.$object->id;
4549 
4550  include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
4551 }
4552 
4553 llxFooter();
4554 $db->close();
File of class to manage predefined price products or services by customer.
llxFooter()
Empty footer.
Definition: wrapper.php:58
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve')
Convert a html select field into an ajax combobox.
Definition: ajax.lib.php:392
Class to manage notifications.
const TYPE_STANDARD
Standard invoice.
setEventMessages($mesg, $mesgs, $style='mesgs')
Set event messages in dol_events session object.
if(!GETPOST('transkey')&&!GETPOST('transphrase')) else
View.
Definition: notice.php:43
Class to manage building of HTML components.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm=false, $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
dol_fiche_head($links=array(), $active='0', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='')
Show tab header of a card.
</td >< tdclass="liste_titre"align="right"></td ></tr >< trclass="liste_titre">< inputtype="checkbox"onClick="toggle(this)"/> Ref p ref Label p label Duration p duration warehouseinternal SELECT description FROM product_lang WHERE qty< br > qty qty qty StockTooLow img yes disabled img no img no< trclass="oddeven">< td >< inputtype="checkbox"class="check"name="'.$i.'"'.$disabled.'></td >< td >< inputtype="checkbox"class="check"name="choose'.$i.'"></td >< tdclass="nowrap"></td >< td >< inputtype="hidden"name="desc'.$i.'"value="'.dol_escape_htmltag($objp-> description
Only used if Module[ID]Desc translation string is not found.
Definition: replenish.php:554
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
if(GETPOST('cancel','alpha')) if(!GETPOST('confirmmassaction','alpha')&&$massaction!= 'presend'&&$massaction!= 'confirm_presend')
Draft customers invoices.
Definition: list.php:147
Class to manage products or services.
dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $onlybanner=0, $morehtmlright='')
Show tab footer of a card.
Class to manage invoice templates.
Class to manage Dolibarr users.
Definition: user.class.php:39
const TYPE_REPLACEMENT
Replacement invoice.
dol_print_error($db='', $error='', $errors=null)
Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte...
getCountry($searchkey, $withcode='', $dbtouse=0, $outputlangs='', $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
dol_concatdesc($text1, $text2, $forxml=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Fonction qui renvoie si tva doit etre tva percue recuperable.
if(empty($reshook)) $form
View.
Definition: perms.php:103
const TYPE_PROFORMA
Proforma invoice (should not be used.
get_localtax($vatrate, $local, $thirdparty_buyer="", $thirdparty_seller="", $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate, from a $thirdparty_buyer to a $thirdparty_seller Note: This function applies same rules than get_default_tva.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...
const TYPE_SITUATION
Situation invoice.
Class to manage bank accounts.
const TYPE_CREDIT_NOTE
Credit note invoice.
GETPOST($paramname, $check='none', $method=0, $filter=NULL, $options=NULL, $noreplace=0)
Return value of a param into GET or POST supervariable.
Class with static methods for building HTML components related to products Only components common to ...
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0)
Show a message to say access is forbidden and stop program Calling this function terminate execution ...
Class to manage standard extra fields.
showDirectDownloadLink($object)
Return string with full Url.
Class to manage generation of HTML components Only common components must be here.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1')
Show information for admin users or standard users.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
Class to manage third parties objects (customers, suppliers, prospects...)
img_warning($titlealt= 'default', $moreatt= '')
Show warning logo.
const STATUS_VALIDATED
Validated (need to be paid)
Class to manage projects.
Classe permettant la generation de composants html autre Only common components are here...
Class to manage building of HTML components.
if($_POST["cancel"]==$langs->trans("Cancel")&&!$id) if($action== 'setdatev'&&$user->rights->tax->charges->creer) if($action== 'add'&&$_POST["cancel"]<> $langs->trans("Cancel")) if($action== 'delete') $title
Actions.
Definition: card.php:183
Class to manage shipments.
dol_fiche_end($notab=0)
Show tab footer of a card.
const STATUS_DRAFT
Draft.
Classe permettant la generation de composants html autre Only common components are here...
Class to manage payments of customer invoices.
load_fiche_titre($titre, $morehtmlright='', $picto='title_generic.png', $pictoisfullpath=0, $id=0, $morecssontable='', $morehtmlcenter='')
Load a title with picto.
llxHeader()
Empty header.
Definition: wrapper.php:46
getEntity($element, $shared=1, $forceentity=null)
Get list of entity id to use.
Class to manage translations.
const STATUS_CLOSED
Classified paid.
dol_now($mode='gmt')
Return date for now.
img_delete($titlealt= 'default', $other= 'class="pictodelete"')
Show delete logo.
Class ProductCombination Used to represent a product combination.
Class to offer components to list and upload files.
const STATUS_ABANDONED
Classified abandoned and no payment done.
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_print_date($time, $format='', $tzoutput='tzserver', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
const TYPE_DEPOSIT
Deposit invoice.
print
Draft customers invoices.
Definition: index.php:91
setEventMessage($mesgs, $style='mesgs')
Set event message in dol_events session object.
if(preg_match('/set_(.*)/', $action, $reg)) if(preg_match('/del_(.*)/', $action, $reg)) if($action== 'set') else if($action== 'specimen') else if($action== 'setmodel') else if($action== 'del') else if($action== 'setdoc' $formactions)
View.
static liste_modeles($db, $maxfilenamelength=0)
Return list of active generation modules.
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) Si ...
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if(!empty($conf->fournisseur->enabled)&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->societe->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if(!empty($conf->fournisseur->enabled)&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1013
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname='')
Return a prefix to use for this Dolibarr instance, for session/cookie names or email id...
Class to manage absolute discounts.
Class to manage a WYSIWYG editor.
Class to manage accounting accounts.
Class to manage invoices.
fieldLabel($langkey, $fieldkey, $fieldrequired=0)
Show a string with the label tag dedicated to the HTML edit field.
dol_time_plus_duree($time, $duration_value, $duration_unit)
Add a delay to a date.
Definition: date.lib.php:116
type
Definition: viewcat.php:283
img_edit($titlealt= 'default', $float=0, $other= 'class="pictoedit"')
Show logo editer/modifier fiche.
price2num($amount, $rounding='', $alreadysqlnb=0)
Function that return a number with universal decimal format (decimal separator is '...
restrictedArea($user, $features, $objectid=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $objcanvas=null)
Check permissions of a user to show a page and an object.
$parameters
Actions.
Definition: card.php:112
Class to manage invoice lines.
Class to manage warehouses.
facture_prepare_head($object)
Initialize the array of tabs for customer invoice.
Definition: invoice.lib.php:36
static getIdAndTxFromCode(&$db, $code, $date_document='')
Get id and rate of currency from code.