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