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