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