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