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