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 $object->totalcreditnotes = $totalcreditnotes;
4491 $object->totaldeposits = $totaldeposits;
4492 $object->remaintopay = price2num($object->total_ttc - $object->totalpaid - $object->totalcreditnotes - $object->totaldeposits, 'MT');
4493
4494 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref, '', 0, '', '');
4495
4496 print '<div class="fichecenter">';
4497 print '<div class="fichehalfleft">';
4498 print '<div class="underbanner clearboth"></div>';
4499
4500 print '<table class="border centpercent tableforfield">';
4501
4502 // Type
4503 print '<tr><td class="titlefield fieldname_type">'.$langs->trans('Type').'</td><td class="valuefield fieldname_type">';
4504 print $object->getLibType(2);
4505 if ($object->module_source) {
4506 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>';
4507 }
4508 if ($object->type == Facture::TYPE_REPLACEMENT) {
4509 $facreplaced = new Facture($db);
4510 $facreplaced->fetch($object->fk_facture_source);
4511 print ' <span class="opacitymediumbycolor paddingleft">'.$langs->transnoentities("ReplaceInvoice", $facreplaced->getNomUrl(1, '', 32)).'</span>';
4512 }
4513 if ($object->type == Facture::TYPE_CREDIT_NOTE && !empty($object->fk_facture_source)) {
4514 $facusing = new Facture($db);
4515 $facusing->fetch($object->fk_facture_source);
4516 print ' <span class="opacitymediumbycolor paddingleft">'.$langs->transnoentities("CorrectInvoice", $facusing->getNomUrl(1, '', 32)).'</span>';
4517 }
4518
4519 $facidavoir = $object->getListIdAvoirFromInvoice();
4520 if (count($facidavoir) > 0) {
4521 print ' <span class="opacitymediumbycolor paddingleft">'.$langs->transnoentities("InvoiceHasAvoir");
4522 $i = 0;
4523 foreach ($facidavoir as $id) {
4524 if ($i == 0) {
4525 print ' ';
4526 } else {
4527 print ',';
4528 }
4529 $facavoir = new Facture($db);
4530 $facavoir->fetch($id);
4531 print $facavoir->getNomUrl(1, '', 32);
4532 }
4533 print '</span>';
4534 }
4535 if ($objectidnext > 0) {
4536 $facthatreplace = new Facture($db);
4537 $facthatreplace->fetch($objectidnext);
4538 print ' <span class="opacitymediumbycolor paddingleft">'.str_replace('{s1}', $facthatreplace->getNomUrl(1), $langs->transnoentities("ReplacedByInvoice", '{s1}')).'</span>';
4539 }
4540
4541 if ($object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_DEPOSIT) {
4542 $discount = new DiscountAbsolute($db);
4543 $result = $discount->fetch(0, $object->id);
4544 if ($result > 0) {
4545 print ' <span class="opacitymediumbycolor paddingleft">';
4546 $s = $langs->trans("CreditNoteConvertedIntoDiscount", '{s1}', '{s2}');
4547 $s = str_replace('{s1}', $object->getLibType(0), $s);
4548 $s = str_replace('{s2}', $discount->getNomUrl(1, 'discount'), $s);
4549 print $s;
4550 print '</span><br>';
4551 }
4552 }
4553
4554 if ($object->fk_fac_rec_source > 0) {
4555 $tmptemplate = new FactureRec($db);
4556 $result = $tmptemplate->fetch($object->fk_fac_rec_source);
4557 if ($result > 0) {
4558 print ' <span class="opacitymediumbycolor paddingleft">';
4559 $s = $langs->transnoentities("GeneratedFromTemplate", '{s1}');
4560 $s = str_replace('{s1}', $tmptemplate->getNomUrl(1, '', 32), $s);
4561 print $s;
4562 print '</span>';
4563 }
4564 }
4565 print '</td></tr>';
4566
4567 // Relative and absolute discounts
4568 print '<!-- Discounts -->'."\n";
4569 print '<tr><td>'.$langs->trans('DiscountStillRemaining').'</td>';
4570 print '<td>';
4571 $thirdparty = $soc;
4572 $discount_type = 0;
4573 $backtopage = $_SERVER["PHP_SELF"].'?facid='.$object->id;
4574 include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
4575 print '</td></tr>';
4576
4577 // Date invoice
4578 print '<tr><td>';
4579 print '<table class="nobordernopadding centpercent"><tr><td>';
4580 print $langs->trans('DateInvoice');
4581 print '</td>';
4582 if ($action != 'editinvoicedate' && !empty($object->brouillon) && $usercancreate && empty($conf->global->FAC_FORCE_DATE_VALIDATION)) {
4583 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>';
4584 }
4585 print '</tr></table>';
4586 print '</td><td>';
4587
4588 if ($action == 'editinvoicedate') {
4589 $form->form_date($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->date, 'invoicedate');
4590 } else {
4591 print '<span class="valuedate">'.dol_print_date($object->date, 'day').'</span>';
4592 }
4593 print '</td>';
4594
4595 print '</tr>';
4596
4597 if (!empty($conf->global->INVOICE_POINTOFTAX_DATE)) {
4598 // Date invoice point of tax
4599 print '<tr><td>';
4600 print '<table class="nobordernopadding centpercent"><tr><td>';
4601 print $langs->trans('DatePointOfTax');
4602 print '</td>';
4603 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>';
4604 print '</tr></table>';
4605 print '</td><td>';
4606 if ($action == 'editdate_pointoftax') {
4607 $form->form_date($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->date_pointoftax, 'date_pointoftax');
4608 } else {
4609 print '<span class="valuedate">'.dol_print_date($object->date_pointoftax, 'day').'</span>';
4610 }
4611 print '</td></tr>';
4612 }
4613
4614 // Payment term
4615 print '<tr><td>';
4616 print '<table class="nobordernopadding centpercent"><tr><td>';
4617 print $langs->trans('PaymentConditionsShort');
4618 print '</td>';
4619 if ($object->type != Facture::TYPE_CREDIT_NOTE && $action != 'editconditions' && $usercancreate) {
4620 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>';
4621 }
4622 print '</tr></table>';
4623 print '</td><td>';
4624 if ($object->type != Facture::TYPE_CREDIT_NOTE) {
4625 if ($action == 'editconditions') {
4626 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->cond_reglement_id, 'cond_reglement_id');
4627 } else {
4628 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->cond_reglement_id, 'none');
4629 }
4630 } else {
4631 print '&nbsp;';
4632 }
4633 print '</td></tr>';
4634
4635 // Date payment term
4636 print '<tr><td>';
4637 print '<table class="nobordernopadding centpercent"><tr><td>';
4638 print $langs->trans('DateMaxPayment');
4639 print '</td>';
4640 if ($object->type != Facture::TYPE_CREDIT_NOTE && $action != 'editpaymentterm' && $usercancreate) {
4641 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>';
4642 }
4643 print '</tr></table>';
4644 print '</td><td>';
4645 if ($object->type != Facture::TYPE_CREDIT_NOTE) {
4646 if ($action == 'editpaymentterm') {
4647 $form->form_date($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->date_lim_reglement, 'paymentterm');
4648 } else {
4649 print '<span class="valuedate">'.dol_print_date($object->date_lim_reglement, 'day').'</span>';
4650 if ($object->hasDelay()) {
4651 print img_warning($langs->trans('Late'));
4652 }
4653 }
4654 } else {
4655 print '&nbsp;';
4656 }
4657 print '</td></tr>';
4658
4659 // Payment mode
4660 print '<tr><td>';
4661 print '<table class="nobordernopadding centpercent"><tr><td>';
4662 print $langs->trans('PaymentMode');
4663 print '</td>';
4664 if ($action != 'editmode' && $usercancreate) {
4665 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>';
4666 }
4667 print '</tr></table>';
4668 print '</td><td>';
4669 if ($action == 'editmode') {
4670 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
4671 } else {
4672 $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'none', 'CRDT');
4673 }
4674 print '</td></tr>';
4675
4676 // Multicurrency
4677 if (isModEnabled('multicurrency')) {
4678 // Multicurrency code
4679 print '<tr>';
4680 print '<td>';
4681 print '<table class="nobordernopadding centpercent"><tr><td>';
4682 print $form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0);
4683 print '</td>';
4684 if ($usercancreate && $action != 'editmulticurrencycode' && !empty($object->brouillon)) {
4685 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>';
4686 }
4687 print '</tr></table>';
4688 print '</td><td>';
4689 $htmlname = (($usercancreate && $action == 'editmulticurrencycode') ? 'multicurrency_code' : 'none');
4690 $form->form_multicurrency_code($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_code, $htmlname);
4691 print '</td></tr>';
4692
4693 // Multicurrency rate
4694 if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
4695 print '<tr>';
4696 print '<td>';
4697 print '<table class="nobordernopadding" width="100%"><tr><td>';
4698 print $form->editfieldkey('CurrencyRate', 'multicurrency_tx', '', $object, 0);
4699 print '</td>';
4700 if ($usercancreate && $action != 'editmulticurrencyrate' && !empty($object->brouillon) && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
4701 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>';
4702 }
4703 print '</tr></table>';
4704 print '</td><td>';
4705 if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
4706 if ($action == 'actualizemulticurrencyrate') {
4707 list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
4708 }
4709 $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, ($usercancreate ? 'multicurrency_tx' : 'none'), $object->multicurrency_code);
4710 } else {
4711 $form->form_multicurrency_rate($_SERVER['PHP_SELF'].'?id='.$object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
4712 if ($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
4713 print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
4714 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=actualizemulticurrencyrate">'.$langs->trans("ActualizeCurrency").'</a>';
4715 print '</div>';
4716 }
4717 }
4718 print '</td></tr>';
4719 }
4720 }
4721
4722 // Bank Account
4723 if (isModEnabled("banque")) {
4724 print '<tr><td class="nowrap">';
4725 print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
4726 print $langs->trans('BankAccount');
4727 print '<td>';
4728 if (($action != 'editbankaccount') && $usercancreate) {
4729 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>';
4730 }
4731 print '</tr></table>';
4732 print '</td><td>';
4733 if ($action == 'editbankaccount') {
4734 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1);
4735 } else {
4736 $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
4737 }
4738 print "</td>";
4739 print '</tr>';
4740 }
4741
4742 // Incoterms
4743 if (isModEnabled('incoterm')) {
4744 print '<tr><td>';
4745 print '<table class="nobordernopadding centpercent"><tr><td>';
4746 print $langs->trans('IncotermLabel');
4747 print '<td><td class="right">';
4748 if ($usercancreate) {
4749 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/compta/facture/card.php?facid='.$object->id.'&action=editincoterm&token='.newToken().'">'.img_edit().'</a>';
4750 } else {
4751 print '&nbsp;';
4752 }
4753 print '</td></tr></table>';
4754 print '</td>';
4755 print '<td>';
4756 if ($action != 'editincoterm') {
4757 print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
4758 } else {
4759 print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
4760 }
4761 print '</td></tr>';
4762 }
4763
4764
4765
4766 if (!empty($object->retained_warranty) || !empty($conf->global->INVOICE_USE_RETAINED_WARRANTY)) {
4767 $displayWarranty = true;
4768 if (!in_array($object->type, $retainedWarrantyInvoiceAvailableType) && empty($object->retained_warranty)) {
4769 $displayWarranty = false;
4770 }
4771
4772 if ($displayWarranty) {
4773 // Retained Warranty
4774 print '<tr class="retained-warranty-lines" ><td>';
4775 print '<table id="retained-warranty-table" class="nobordernopadding centpercent"><tr><td>';
4776 print $langs->trans('RetainedWarranty');
4777 print '</td>';
4778 if ($action != 'editretainedwarranty' && $user->hasRight('facture', 'creer') && $object->statut == Facture::STATUS_DRAFT) {
4779 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>';
4780 }
4781
4782 print '</tr></table>';
4783 print '</td><td>';
4784 if ($action == 'editretainedwarranty' && $object->statut == Facture::STATUS_DRAFT) {
4785 print '<form id="retained-warranty-form" method="POST" action="'.$_SERVER['PHP_SELF'].'?facid='.$object->id.'">';
4786 print '<input type="hidden" name="action" value="setretainedwarranty">';
4787 print '<input type="hidden" name="token" value="'.newToken().'">';
4788 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
4789 print '<input name="retained_warranty" type="number" step="0.01" min="0" max="100" value="'.$object->retained_warranty.'" >';
4790 print '<input type="submit" class="button valignmiddle smallpaddingimp" value="'.$langs->trans("Modify").'">';
4791 print '</form>';
4792 } else {
4793 print price($object->retained_warranty).'%';
4794 }
4795 print '</td></tr>';
4796
4797 // Retained warranty payment term
4798 print '<tr class="retained-warranty-lines" ><td>';
4799 print '<table id="retained-warranty-cond-reglement-table" class="nobordernopadding" width="100%"><tr><td>';
4800 print $langs->trans('PaymentConditionsShortRetainedWarranty');
4801 print '</td>';
4802 if ($action != 'editretainedwarrantypaymentterms' && $user->hasRight('facture', 'creer') && $object->statut == Facture::STATUS_DRAFT) {
4803 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>';
4804 }
4805
4806 print '</tr></table>';
4807 print '</td><td>';
4808 $defaultDate = !empty($object->retained_warranty_date_limit) ? $object->retained_warranty_date_limit : strtotime('-1 years', $object->date_lim_reglement);
4809 if ($object->date > $defaultDate) {
4810 $defaultDate = $object->date;
4811 }
4812
4813 if ($action == 'editretainedwarrantypaymentterms' && $object->statut == Facture::STATUS_DRAFT) {
4814 //date('Y-m-d',$object->date_lim_reglement)
4815 print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'?facid='.$object->id.'">';
4816 print '<input type="hidden" name="action" value="setretainedwarrantyconditions">';
4817 print '<input type="hidden" name="token" value="'.newToken().'">';
4818 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
4819 $retained_warranty_fk_cond_reglement = GETPOST('retained_warranty_fk_cond_reglement', 'int');
4820 $retained_warranty_fk_cond_reglement = !empty($retained_warranty_fk_cond_reglement) ? $retained_warranty_fk_cond_reglement : $object->retained_warranty_fk_cond_reglement;
4821 $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;
4822 print $form->getSelectConditionsPaiements($retained_warranty_fk_cond_reglement, 'retained_warranty_fk_cond_reglement', -1, 1);
4823 print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4824 print '</form>';
4825 } else {
4826 $form->form_conditions_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->retained_warranty_fk_cond_reglement, 'none');
4827 if (!$displayWarranty) {
4828 print img_picto($langs->trans('RetainedWarrantyNeed100Percent'), 'warning.png', 'class="pictowarning valignmiddle" ');
4829 }
4830 }
4831 print '</td></tr>';
4832
4833 // Retained Warranty payment date limit
4834 print '<tr class="retained-warranty-lines" ><td>';
4835 print '<table id="retained-warranty-date-limit-table" class="nobordernopadding" width="100%"><tr><td>';
4836 print $langs->trans('RetainedWarrantyDateLimit');
4837 print '</td>';
4838 if ($action != 'editretainedwarrantydatelimit' && $user->hasRight('facture', 'creer') && $object->statut == Facture::STATUS_DRAFT) {
4839 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>';
4840 }
4841
4842 print '</tr></table>';
4843 print '</td><td>';
4844 $defaultDate = !empty($object->retained_warranty_date_limit) ? $object->retained_warranty_date_limit : strtotime('-1 years', $object->date_lim_reglement);
4845 if ($object->date > $defaultDate) {
4846 $defaultDate = $object->date;
4847 }
4848
4849 if ($action == 'editretainedwarrantydatelimit' && $object->statut == Facture::STATUS_DRAFT) {
4850 //date('Y-m-d',$object->date_lim_reglement)
4851 print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'?facid='.$object->id.'">';
4852 print '<input type="hidden" name="action" value="setretainedwarrantydatelimit">';
4853 print '<input type="hidden" name="token" value="'.newToken().'">';
4854 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
4855 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').'" >';
4856 print '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
4857 print '</form>';
4858 } else {
4859 print dol_print_date($object->retained_warranty_date_limit, 'day');
4860 }
4861 print '</td></tr>';
4862 }
4863 }
4864
4865
4866 // Other attributes
4867 $cols = 2;
4868 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
4869
4870 print '</table>';
4871
4872 print '</div>';
4873 print '<div class="fichehalfright">';
4874
4875 print '<!-- amounts -->'."\n";
4876 print '<div class="underbanner clearboth"></div>'."\n";
4877
4878 print '<table class="border tableforfield centpercent">';
4879
4880 $sign = 1;
4881 if (!empty($conf->global->INVOICE_POSITIVE_CREDIT_NOTE_SCREEN) && $object->type == $object::TYPE_CREDIT_NOTE) {
4882 $sign = -1; // We invert sign for output
4883 }
4884 print '<tr>';
4885 // Amount HT
4886 print '<td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
4887 print '<td class="nowrap amountcard right">' . price($sign * $object->total_ht, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
4888 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
4889 // Multicurrency Amount HT
4890 print '<td class="nowrap amountcard right">' . price($sign * $object->multicurrency_total_ht, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
4891 }
4892 print '</tr>';
4893
4894 print '<tr>';
4895 // Amount VAT
4896 print '<td class="titlefieldmiddle">' . $langs->trans('AmountVAT') . '</td>';
4897 print '<td class="nowrap amountcard right">' . price($sign * $object->total_tva, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
4898 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
4899 // Multicurrency Amount VAT
4900 print '<td class="nowrap amountcard right">' . price($sign * $object->multicurrency_total_tva, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
4901 }
4902 print '</tr>';
4903
4904 // Amount Local Taxes
4905 if (($mysoc->localtax1_assuj == "1" && $mysoc->useLocalTax(1)) || $object->total_localtax1 != 0) {
4906 print '<tr>';
4907 print '<td class="titlefieldmiddle">' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
4908 print '<td class="nowrap amountcard right">' . price($sign * $object->total_localtax1, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
4909 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
4910 $object->multicurrency_total_localtax1 = price2num($object->total_localtax1 * $object->multicurrency_tx, 'MT');
4911
4912 print '<td class="nowrap amountcard right">' . price($sign * $object->multicurrency_total_localtax1, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
4913 }
4914 print '</tr>';
4915
4916 if (($mysoc->localtax2_assuj == "1" && $mysoc->useLocalTax(2)) || $object->total_localtax2 != 0) {
4917 print '<tr>';
4918 print '<td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
4919 print '<td class="nowrap amountcard right">' . price($sign * $object->total_localtax2, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
4920 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
4921 $object->multicurrency_total_localtax2 = price2num($object->total_localtax2 * $object->multicurrency_tx, 'MT');
4922
4923 print '<td class="nowrap amountcard right">' . price($sign * $object->multicurrency_total_localtax2, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
4924 }
4925 print '</tr>';
4926 }
4927 }
4928
4929
4930 // Add the revenu stamp
4931 if ($selleruserevenustamp) {
4932 print '<tr><td class="titlefieldmiddle">';
4933 print '<table class="nobordernopadding centpercent"><tr><td>';
4934 print $langs->trans('RevenueStamp');
4935 print '</td>';
4936 if ($action != 'editrevenuestamp' && !empty($object->brouillon) && $usercancreate) {
4937 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>';
4938 }
4939 print '</tr></table>';
4940 print '</td><td class="nowrap amountcard right">';
4941 if ($action == 'editrevenuestamp') {
4942 print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
4943 print '<input type="hidden" name="token" value="'.newToken().'">';
4944 print '<input type="hidden" name="action" value="setrevenuestamp">';
4945 print '<input type="hidden" name="revenuestamp" id="revenuestamp_val" value="'.price2num($object->revenuestamp).'">';
4946 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
4947 print $formother->select_revenue_stamp('', 'revenuestamp_type', $mysoc->country_code);
4948 print ' &rarr; <span id="revenuestamp_span"></span>';
4949 print ' <input type="submit" class="button buttongen button-save small" value="'.$langs->trans('Modify').'">';
4950 print '</form>';
4951 print " <script>
4952 $(document).ready(function(){
4953 js_recalculate_revenuestamp();
4954 $('select[name=revenuestamp_type]').on('change',function(){
4955 js_recalculate_revenuestamp();
4956 });
4957 });
4958 function js_recalculate_revenuestamp(){
4959 var valselected = $('select[name=revenuestamp_type]').val();
4960 console.log('Calculate revenue stamp from '+valselected);
4961 var revenue = 0;
4962 if (valselected.indexOf('%') == -1)
4963 {
4964 revenue = valselected;
4965 }
4966 else
4967 {
4968 var revenue_type = parseFloat(valselected);
4969 var amount_net = ".round($object->total_ht, 2).";
4970 revenue = revenue_type * amount_net / 100;
4971 revenue = revenue.toFixed(2);
4972 }
4973 $('#revenuestamp_val').val(revenue);
4974 $('#revenuestamp_span').html(revenue);
4975 }
4976 </script>";
4977 } else {
4978 print price($object->revenuestamp, 1, '', 1, -1, -1, $conf->currency);
4979 }
4980 print '</td></tr>';
4981 }
4982
4983 print '<tr>';
4984 // Amount TTC
4985 print '<td>' . $langs->trans('AmountTTC') . '</td>';
4986 print '<td class="nowrap amountcard right">' . price($sign * $object->total_ttc, '', $langs, 0, -1, -1, $conf->currency) . '</td>';
4987 if (isModEnabled("multicurrency") && ($object->multicurrency_code && $object->multicurrency_code != $conf->currency)) {
4988 // Multicurrency Amount TTC
4989 print '<td class="nowrap amountcard right">' . price($sign * $object->multicurrency_total_ttc, '', $langs, 0, -1, -1, $object->multicurrency_code) . '</td>';
4990 }
4991 print '</tr>';
4992
4993 print '</table>';
4994
4995 $nbrows = 8;
4996 $nbcols = 3;
4997 if (isModEnabled('project')) {
4998 $nbrows++;
4999 }
5000 if (isModEnabled("banque")) {
5001 $nbrows++;
5002 $nbcols++;
5003 }
5004 if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) {
5005 $nbrows++;
5006 }
5007 if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) {
5008 $nbrows++;
5009 }
5010 if ($selleruserevenustamp) {
5011 $nbrows++;
5012 }
5013 if (isModEnabled('multicurrency')) {
5014 $nbrows += 5;
5015 }
5016 if (isModEnabled('incoterm')) {
5017 $nbrows += 1;
5018 }
5019
5020 // List of previous situation invoices
5021 if (($object->situation_cycle_ref > 0) && !empty($conf->global->INVOICE_USE_SITUATION)) {
5022 print '<!-- List of situation invoices -->';
5023 print '<table class="noborder situationstable" width="100%">';
5024
5025 print '<tr class="liste_titre">';
5026 print '<td>'.$langs->trans('ListOfSituationInvoices').'</td>';
5027 print '<td></td>';
5028 print '<td class="center">'.$langs->trans('Situation').'</td>';
5029 if (isModEnabled("banque")) {
5030 print '<td class="right"></td>';
5031 }
5032 print '<td class="right">'.$langs->trans('AmountHT').'</td>';
5033 print '<td class="right">'.$langs->trans('AmountTTC').'</td>';
5034 print '<td width="18">&nbsp;</td>';
5035 print '</tr>';
5036
5037 $total_prev_ht = $total_prev_ttc = 0;
5038 $total_global_ht = $total_global_ttc = 0;
5039
5040 if (count($object->tab_previous_situation_invoice) > 0) {
5041 // List of previous invoices
5042
5043 $current_situation_counter = array();
5044 foreach ($object->tab_previous_situation_invoice as $prev_invoice) {
5045 $tmptotalallpayments = $prev_invoice->getSommePaiement(0);
5046 $tmptotalallpayments += $prev_invoice->getSumDepositsUsed(0);
5047 $tmptotalallpayments += $prev_invoice->getSumCreditNotesUsed(0);
5048 $total_prev_ht += $prev_invoice->total_ht;
5049 $total_prev_ttc += $prev_invoice->total_ttc;
5050 $current_situation_counter[] = (($prev_invoice->type == Facture::TYPE_CREDIT_NOTE) ?-1 : 1) * $prev_invoice->situation_counter;
5051 print '<tr class="oddeven">';
5052 print '<td>'.$prev_invoice->getNomUrl(1).'</td>';
5053 print '<td></td>';
5054 print '<td align="center" >'.(($prev_invoice->type == Facture::TYPE_CREDIT_NOTE) ? $langs->trans('situationInvoiceShortcode_AS') : $langs->trans('situationInvoiceShortcode_S')).$prev_invoice->situation_counter.'</td>';
5055 if (isModEnabled("banque")) {
5056 print '<td class="right"></td>';
5057 }
5058 print '<td class="right"><span class="amount">'.price($prev_invoice->total_ht).'</span></td>';
5059 print '<td class="right"><span class="amount">'.price($prev_invoice->total_ttc).'</span></td>';
5060 print '<td class="right">'.$prev_invoice->getLibStatut(3, $tmptotalallpayments).'</td>';
5061 print '</tr>';
5062 }
5063 }
5064
5065 $totalallpayments = $object->getSommePaiement(0);
5066 $totalallpayments += $object->getSumCreditNotesUsed(0);
5067 $totalallpayments += $object->getSumDepositsUsed(0);
5068
5069 $total_global_ht += $total_prev_ht;
5070 $total_global_ttc += $total_prev_ttc;
5071 $total_global_ht += $object->total_ht;
5072 $total_global_ttc += $object->total_ttc;
5073 $current_situation_counter[] = (($object->type == Facture::TYPE_CREDIT_NOTE) ?-1 : 1) * $object->situation_counter;
5074 print '<tr class="oddeven">';
5075 print '<td>'.$object->getNomUrl(1).'</td>';
5076 print '<td></td>';
5077 print '<td class="center">'.(($object->type == Facture::TYPE_CREDIT_NOTE) ? $langs->trans('situationInvoiceShortcode_AS') : $langs->trans('situationInvoiceShortcode_S')).$object->situation_counter.'</td>';
5078 if (isModEnabled("banque")) {
5079 print '<td class="right"></td>';
5080 }
5081 print '<td class="right"><span class="amount">'.price($object->total_ht).'</span></td>';
5082 print '<td class="right"><span class="amount">'.price($object->total_ttc).'</span></td>';
5083 print '<td class="right">'.$object->getLibStatut(3, $totalallpayments).'</td>';
5084 print '</tr>';
5085
5086
5087 print '<tr class="oddeven">';
5088 print '<td colspan="2" class="left"><b>'.$langs->trans('CurrentSituationTotal').'</b></td>';
5089 print '<td>';
5090 $i = 0;
5091 foreach ($current_situation_counter as $sit) {
5092 $curSign = $sit > 0 ? '+' : '-';
5093 $curType = $sit > 0 ? $langs->trans('situationInvoiceShortcode_S') : $langs->trans('situationInvoiceShortcode_AS');
5094 if ($i > 0) {
5095 print ' '.$curSign.' ';
5096 }
5097 print $curType.abs($sit);
5098 $i++;
5099 }
5100 print '</td>';
5101 if (isModEnabled("banque")) {
5102 print '<td></td>';
5103 }
5104 print '<td class="right"><b>'.price($total_global_ht).'</b></td>';
5105 print '<td class="right"><b>'.price($total_global_ttc).'</b></td>';
5106 print '<td width="18">&nbsp;</td>';
5107 print '</tr>';
5108
5109
5110 if (count($object->tab_next_situation_invoice) > 0) {
5111 // List of next invoices
5112 /*print '<tr class="liste_titre">';
5113 print '<td>' . $langs->trans('ListOfNextSituationInvoices') . '</td>';
5114 print '<td></td>';
5115 print '<td></td>';
5116 if (isModEnabled('banque')) print '<td class="right"></td>';
5117 print '<td class="right">' . $langs->trans('AmountHT') . '</td>';
5118 print '<td class="right">' . $langs->trans('AmountTTC') . '</td>';
5119 print '<td width="18">&nbsp;</td>';
5120 print '</tr>';*/
5121
5122 $total_next_ht = $total_next_ttc = 0;
5123
5124 foreach ($object->tab_next_situation_invoice as $next_invoice) {
5125 $totalpaid = $next_invoice->getSommePaiement(0);
5126 $totalcreditnotes = $next_invoice->getSumCreditNotesUsed(0);
5127 $totaldeposits = $next_invoice->getSumDepositsUsed(0);
5128 $total_next_ht += $next_invoice->total_ht;
5129 $total_next_ttc += $next_invoice->total_ttc;
5130
5131 print '<tr class="oddeven">';
5132 print '<td>'.$next_invoice->getNomUrl(1).'</td>';
5133 print '<td></td>';
5134 print '<td class="center">'.(($next_invoice->type == Facture::TYPE_CREDIT_NOTE) ? $langs->trans('situationInvoiceShortcode_AS') : $langs->trans('situationInvoiceShortcode_S')).$next_invoice->situation_counter.'</td>';
5135 if (isModEnabled("banque")) {
5136 print '<td class="right"></td>';
5137 }
5138 print '<td class="right"><span class="amount">'.price($next_invoice->total_ht).'</span></td>';
5139 print '<td class="right"><span class="amount">'.price($next_invoice->total_ttc).'</span></td>';
5140 print '<td class="right">'.$next_invoice->getLibStatut(3, $totalpaid + $totalcreditnotes + $totaldeposits).'</td>';
5141 print '</tr>';
5142 }
5143
5144 $total_global_ht += $total_next_ht;
5145 $total_global_ttc += $total_next_ttc;
5146
5147 print '<tr class="oddeven">';
5148 print '<td colspan="3" class="right"></td>';
5149 if (isModEnabled("banque")) {
5150 print '<td class="right"></td>';
5151 }
5152 print '<td class="right"><b>'.price($total_global_ht).'</b></td>';
5153 print '<td class="right"><b>'.price($total_global_ttc).'</b></td>';
5154 print '<td width="18">&nbsp;</td>';
5155 print '</tr>';
5156 }
5157
5158 print '</table>';
5159 }
5160
5161 $sign = 1;
5162 if ($object->type == $object::TYPE_CREDIT_NOTE) {
5163 $sign = -1;
5164 }
5165
5166 // List of payments already done
5167
5168 print '<!-- List of payments already done -->';
5169 print '<div class="div-table-responsive-no-min">';
5170 print '<table class="noborder paymenttable centpercent">';
5171
5172 print '<tr class="liste_titre">';
5173 print '<td class="liste_titre">'.($object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("PaymentsBack") : $langs->trans('Payments')).'</td>';
5174 print '<td class="liste_titre"><span class="hideonsmartphone">'.$langs->trans('Date').'</span></td>';
5175 print '<td class="liste_titre"><span class="hideonsmartphone">'.$langs->trans('Type').'</span></td>';
5176 if (isModEnabled("banque")) {
5177 print '<td class="liste_titre"><span class="hideonsmartphone">'.$langs->trans('BankAccount').'</span></td>';
5178 }
5179 print '<td class="liste_titre right">'.$langs->trans('Amount').'</td>';
5180 print '<td class="liste_titre" width="18">&nbsp;</td>';
5181 print '</tr>';
5182
5183 // Payments already done (from payment on this invoice)
5184 $sql = 'SELECT p.datep as dp, p.ref, p.num_paiement as num_payment, p.rowid, p.fk_bank,';
5185 $sql .= ' c.code as payment_code, c.libelle as payment_label,';
5186 $sql .= ' pf.amount,';
5187 $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';
5188 $sql .= ' FROM '.MAIN_DB_PREFIX.'paiement_facture as pf, '.MAIN_DB_PREFIX.'paiement as p';
5189 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as c ON p.fk_paiement = c.id';
5190 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank as b ON p.fk_bank = b.rowid';
5191 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank_account as ba ON b.fk_account = ba.rowid';
5192 $sql .= ' WHERE pf.fk_facture = '.((int) $object->id).' AND pf.fk_paiement = p.rowid';
5193 $sql .= ' AND p.entity IN ('.getEntity('invoice').')';
5194 $sql .= ' ORDER BY p.datep, p.tms';
5195
5196 $result = $db->query($sql);
5197 if ($result) {
5198 $num = $db->num_rows($result);
5199 $i = 0;
5200
5201 if ($num > 0) {
5202 while ($i < $num) {
5203 $objp = $db->fetch_object($result);
5204
5205 $paymentstatic->id = $objp->rowid;
5206 $paymentstatic->datepaye = $db->jdate($objp->dp);
5207 $paymentstatic->ref = $objp->ref;
5208 $paymentstatic->num_payment = $objp->num_payment;
5209 $paymentstatic->paiementcode = $objp->payment_code;
5210
5211 print '<tr class="oddeven"><td class="nowraponall">';
5212 print $paymentstatic->getNomUrl(1);
5213 print '</td>';
5214 print '<td>';
5215 $dateofpayment = $db->jdate($objp->dp);
5216 $tmparray = dol_getdate($dateofpayment);
5217 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
5218 print dol_print_date($dateofpayment, 'day');
5219 } else { // Hours was set to real date of payment (special case for POS for example)
5220 print dol_print_date($dateofpayment, 'dayhour', 'tzuser');
5221 }
5222 print '</td>';
5223 $label = ($langs->trans("PaymentType".$objp->payment_code) != ("PaymentType".$objp->payment_code)) ? $langs->trans("PaymentType".$objp->payment_code) : $objp->payment_label;
5224 print '<td class="tdoverflowmax80" title="'.dol_escape_htmltag($label.' '.$objp->num_payment).'">'.dol_escape_htmltag($label.' '.$objp->num_payment).'</td>';
5225 if (isModEnabled("banque")) {
5226 $bankaccountstatic->id = $objp->baid;
5227 $bankaccountstatic->ref = $objp->baref;
5228 $bankaccountstatic->label = $objp->baref;
5229 $bankaccountstatic->number = $objp->banumber;
5230 $bankaccountstatic->currency_code = $objp->bacurrency_code;
5231
5232 if (isModEnabled('accounting')) {
5233 $bankaccountstatic->account_number = $objp->account_number;
5234
5235 $accountingjournal = new AccountingJournal($db);
5236 $accountingjournal->fetch($objp->fk_accountancy_journal);
5237 $bankaccountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1);
5238 }
5239
5240 print '<td class="nowraponall">';
5241 if ($bankaccountstatic->id) {
5242 print $bankaccountstatic->getNomUrl(1, 'transactions');
5243 }
5244 print '</td>';
5245 }
5246 print '<td class="right"><span class="amount">'.price($sign * $objp->amount).'</span></td>';
5247 print '<td class="center">';
5248
5249 $paiement = new Paiement($db);
5250 $paiement->fetch($objp->rowid);
5251 if ($object->statut == Facture::STATUS_VALIDATED && $object->paye == 0 && $user->socid == 0 && !$paiement->isReconciled()) {
5252 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=deletepayment&token='.newToken().'&paiement_id='.$objp->rowid.'">';
5253 print img_delete();
5254 print '</a>';
5255 }
5256 print '</td>';
5257 print '</tr>';
5258 $i++;
5259 }
5260 }
5261
5262 $db->free($result);
5263 } else {
5264 dol_print_error($db);
5265 }
5266
5267 if ($object->type != Facture::TYPE_CREDIT_NOTE) {
5268 // Total already paid
5269 print '<tr><td colspan="'.$nbcols.'" class="right">';
5270 print '<span class="opacitymedium">';
5271 if ($object->type != Facture::TYPE_DEPOSIT) {
5272 print $langs->trans('AlreadyPaidNoCreditNotesNoDeposits');
5273 } else {
5274 print $langs->trans('AlreadyPaid');
5275 }
5276 print '</span></td><td class="right'.(($totalpaid > 0) ? ' amountalreadypaid' : '').'">'.price($totalpaid).'</td><td>&nbsp;</td></tr>';
5277
5278 $resteapayeraffiche = $resteapayer;
5279 $cssforamountpaymentcomplete = 'amountpaymentcomplete';
5280
5281 // Loop on each credit note or deposit amount applied
5282 $creditnoteamount = 0;
5283 $depositamount = 0;
5284 $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
5285 $sql .= " re.description, re.fk_facture_source";
5286 $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re";
5287 $sql .= " WHERE fk_facture = ".((int) $object->id);
5288 $resql = $db->query($sql);
5289 if ($resql) {
5290 $num = $db->num_rows($resql);
5291 $i = 0;
5292 $invoice = new Facture($db);
5293 while ($i < $num) {
5294 $obj = $db->fetch_object($resql);
5295 $invoice->fetch($obj->fk_facture_source);
5296 print '<tr><td colspan="'.$nbcols.'" class="right">';
5297 print '<span class="opacitymedium">';
5298 if ($invoice->type == Facture::TYPE_CREDIT_NOTE) {
5299 print $langs->trans("CreditNote").' ';
5300 }
5301 if ($invoice->type == Facture::TYPE_DEPOSIT) {
5302 print $langs->trans("Deposit").' ';
5303 }
5304 print $invoice->getNomUrl(0);
5305 print '</span>';
5306 print '</td>';
5307 print '<td class="right"><span class="amount">'.price($obj->amount_ttc).'</span></td>';
5308 print '<td class="right">';
5309 print '<a href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&action=unlinkdiscount&token='.newToken().'&discountid='.$obj->rowid.'">';
5310 print img_picto($langs->transnoentitiesnoconv("RemoveDiscount"), 'unlink');
5311 print '</a>';
5312 print '</td></tr>';
5313 $i++;
5314 if ($invoice->type == Facture::TYPE_CREDIT_NOTE) {
5315 $creditnoteamount += $obj->amount_ttc;
5316 }
5317 if ($invoice->type == Facture::TYPE_DEPOSIT) {
5318 $depositamount += $obj->amount_ttc;
5319 }
5320 }
5321 } else {
5322 dol_print_error($db);
5323 }
5324
5325 // Paye partiellement 'escompte'
5326 if (($object->statut == Facture::STATUS_CLOSED || $object->statut == Facture::STATUS_ABANDONED) && $object->close_code == 'discount_vat') {
5327 print '<tr><td colspan="'.$nbcols.'" class="nowrap right">';
5328 print '<span class="opacitymedium">';
5329 print $form->textwithpicto($langs->trans("Discount"), $langs->trans("HelpEscompte"), - 1);
5330 print '</span>';
5331 print '</td><td class="right"><span class="amount">'.price(price2num($object->total_ttc - $creditnoteamount - $depositamount - $totalpaid, 'MT')).'</span></td><td>&nbsp;</td></tr>';
5332 $resteapayeraffiche = 0;
5333 $cssforamountpaymentcomplete = 'amountpaymentneutral';
5334 }
5335 // Paye partiellement ou Abandon 'badcustomer'
5336 if (($object->statut == Facture::STATUS_CLOSED || $object->statut == Facture::STATUS_ABANDONED) && $object->close_code == 'badcustomer') {
5337 print '<tr><td colspan="'.$nbcols.'" class="nowrap right">';
5338 print '<span class="opacitymedium">';
5339 print $form->textwithpicto($langs->trans("Abandoned"), $langs->trans("HelpAbandonBadCustomer"), - 1);
5340 print '</span>';
5341 print '</td><td class="right">'.price(price2num($object->total_ttc - $creditnoteamount - $depositamount - $totalpaid, 'MT')).'</td><td>&nbsp;</td></tr>';
5342 // $resteapayeraffiche=0;
5343 $cssforamountpaymentcomplete = 'amountpaymentneutral';
5344 }
5345 // Paye partiellement ou Abandon 'product_returned'
5346 if (($object->statut == Facture::STATUS_CLOSED || $object->statut == Facture::STATUS_ABANDONED) && $object->close_code == 'product_returned') {
5347 print '<tr><td colspan="'.$nbcols.'" class="nowrap right">';
5348 print '<span class="opacitymedium">';
5349 print $form->textwithpicto($langs->trans("ProductReturned"), $langs->trans("HelpAbandonProductReturned"), - 1);
5350 print '</span>';
5351 print '</td><td class="right"><span class="amount">'.price(price2num($object->total_ttc - $creditnoteamount - $depositamount - $totalpaid, 'MT')).'</span></td><td>&nbsp;</td></tr>';
5352 $resteapayeraffiche = 0;
5353 $cssforamountpaymentcomplete = 'amountpaymentneutral';
5354 }
5355 // Paye partiellement ou Abandon 'abandon'
5356 if (($object->statut == Facture::STATUS_CLOSED || $object->statut == Facture::STATUS_ABANDONED) && $object->close_code == 'abandon') {
5357 print '<tr><td colspan="'.$nbcols.'" class="nowrap right">';
5358 $text = $langs->trans("HelpAbandonOther");
5359 if ($object->close_note) {
5360 $text .= '<br><br><b>'.$langs->trans("Reason").'</b>:'.$object->close_note;
5361 }
5362 print '<span class="opacitymedium">';
5363 print $form->textwithpicto($langs->trans("Abandoned"), $text, - 1);
5364 print '</span>';
5365 print '</td><td class="right"><span class="amount">'.price(price2num($object->total_ttc - $creditnoteamount - $depositamount - $totalpaid, 'MT')).'</span></td><td>&nbsp;</td></tr>';
5366 $resteapayeraffiche = 0;
5367 $cssforamountpaymentcomplete = 'amountpaymentneutral';
5368 }
5369
5370 // Billed
5371 print '<tr><td colspan="'.$nbcols.'" class="right">';
5372 print '<span class="opacitymedium">';
5373 print $langs->trans("Billed");
5374 print '</td><td class="right">'.price($object->total_ttc).'</td><td>&nbsp;</td></tr>';
5375 // Remainder to pay
5376 print '<tr><td colspan="'.$nbcols.'" class="right">';
5377 print '<span class="opacitymedium">';
5378 print $langs->trans('RemainderToPay');
5379 if ($resteapayeraffiche < 0) {
5380 print ' ('.$langs->trans('NegativeIfExcessReceived').')';
5381 }
5382 print '</span>';
5383 print '</td>';
5384 print '<td class="right'.($resteapayeraffiche ? ' amountremaintopay' : (' '.$cssforamountpaymentcomplete)).'">'.price($resteapayeraffiche).'</td><td>&nbsp;</td></tr>';
5385
5386 // Remainder to pay Multicurrency
5387 if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
5388 print '<tr><td colspan="'.$nbcols.'" class="right">';
5389 print '<span class="opacitymedium">';
5390 print $langs->trans('RemainderToPayMulticurrency');
5391 if ($resteapayeraffiche < 0) {
5392 print ' ('.$langs->trans('NegativeIfExcessReceived').')';
5393 }
5394 print '</span>';
5395 print '</td>';
5396 print '<td class="right'.($resteapayeraffiche ? ' amountremaintopay' : (' '.$cssforamountpaymentcomplete)).'">';
5397 //print (empty($object->multicurrency_code) ? $conf->currency : $object->multicurrency_code).' ';
5398 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>';
5399 }
5400
5401 // Retained warranty : usualy use on construction industry
5402 if (!empty($object->situation_final) && !empty($object->retained_warranty) && $displayWarranty) {
5403 // Billed - retained warranty
5404 if ($object->type == Facture::TYPE_SITUATION) {
5405 $retainedWarranty = $total_global_ttc * $object->retained_warranty / 100;
5406 } else {
5407 // Because one day retained warranty could be used on standard invoices
5408 $retainedWarranty = $object->total_ttc * $object->retained_warranty / 100;
5409 }
5410
5411 $billedWithRetainedWarranty = $object->total_ttc - $retainedWarranty;
5412
5413 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>';
5414
5415 // retained warranty
5416 print '<tr><td colspan="'.$nbcols.'" align="right">';
5417 print $langs->trans("RetainedWarranty").' ('.$object->retained_warranty.'%)';
5418 print !empty($object->retained_warranty_date_limit) ? ' '.$langs->trans("ToPayOn", dol_print_date($object->retained_warranty_date_limit, 'day')) : '';
5419 print ' :</td><td align="right">'.price($retainedWarranty).'</td><td>&nbsp;</td></tr>';
5420 }
5421 } else { // Credit note
5422 $resteapayeraffiche = $resteapayer;
5423 $cssforamountpaymentcomplete = 'amountpaymentneutral';
5424
5425 // Total already paid back
5426 print '<tr><td colspan="'.$nbcols.'" class="right">';
5427 print '<span class="opacitymedium">'.$langs->trans('AlreadyPaidBack').'</span>';
5428 print '</td><td class="right"><span class="amount">'.price($sign * $totalpaid).'</span></td><td>&nbsp;</td></tr>';
5429
5430 // Billed
5431 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>';
5432
5433 // Remainder to pay back
5434 print '<tr><td colspan="'.$nbcols.'" class="right">';
5435 print '<span class="opacitymedium">'.$langs->trans('RemainderToPayBack');
5436 if ($resteapayeraffiche > 0) {
5437 print ' ('.$langs->trans('NegativeIfExcessRefunded').')';
5438 }
5439 print '</span></td>';
5440 print '<td class="right'.($resteapayeraffiche ? ' amountremaintopayback' : (' '.$cssforamountpaymentcomplete)).'">'.price($sign * $resteapayeraffiche).'</td>';
5441 print '<td class="nowrap">&nbsp;</td></tr>';
5442
5443 // Remainder to pay back Multicurrency
5444 if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
5445 print '<tr><td colspan="'.$nbcols.'" class="right">';
5446 print '<span class="opacitymedium">'.$langs->trans('RemainderToPayBackMulticurrency');
5447 if ($resteapayeraffiche > 0) {
5448 print ' ('.$langs->trans('NegativeIfExcessRefunded').')';
5449 }
5450 print '</span>';
5451 print '</td>';
5452 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>';
5453 }
5454
5455 // Sold credit note
5456 // print '<tr><td colspan="'.$nbcols.'" class="right">'.$langs->trans('TotalTTC').' :</td>';
5457 // print '<td class="right" style="border: 1px solid;" bgcolor="#f0f0f0"><b>'.price($sign *
5458 // $object->total_ttc).'</b></td><td>&nbsp;</td></tr>';
5459 }
5460
5461 print '</table>';
5462 print '</div>';
5463
5464 // Margin Infos
5465 if (isModEnabled('margin')) {
5466 $formmargin->displayMarginInfos($object);
5467 }
5468
5469 print '</div>';
5470 print '</div>';
5471
5472 print '<div class="clearboth"></div><br><br>';
5473
5474 if (!empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) {
5475 $blocname = 'contacts';
5476 $title = $langs->trans('ContactsAddresses');
5477 include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
5478 }
5479
5480 if (!empty($conf->global->MAIN_DISABLE_NOTES_TAB)) {
5481 $blocname = 'notes';
5482 $title = $langs->trans('Notes');
5483 include DOL_DOCUMENT_ROOT.'/core/tpl/bloc_showhide.tpl.php';
5484 }
5485
5486 // Get object lines
5487 $result = $object->getLinesArray();
5488
5489 // Add products/services form
5490 //$forceall = 1;
5491 global $inputalsopricewithtax;
5492 $inputalsopricewithtax = 1;
5493
5494 // Show global modifiers for situation invoices
5495 if (!empty($conf->global->INVOICE_USE_SITUATION)) {
5496 if ($object->situation_cycle_ref && $object->statut == 0) {
5497 print '<!-- Area to change globally the situation percent -->'."\n";
5498 print '<div class="div-table-responsive">';
5499
5500 print '<form name="updatealllines" id="updatealllines" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'#updatealllines" method="POST">';
5501 print '<input type="hidden" name="token" value="'.newToken().'" />';
5502 print '<input type="hidden" name="action" value="updatealllines" />';
5503 print '<input type="hidden" name="id" value="'.$object->id.'" />';
5504 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
5505
5506 print '<table id="tablelines_all_progress" class="noborder noshadow" width="100%">';
5507
5508 print '<tr class="liste_titre nodrag nodrop">';
5509
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 class="minwidth500imp">'.$langs->trans('ModifyAllLines').'</td>';
5515 print '<td class="right">'.$langs->trans('Progress').'</td>';
5516 print '<td>&nbsp;</td>';
5517 print "</tr>\n";
5518
5519 print '<tr class="nodrag nodrop">';
5520 // Adds a line numbering column
5521 if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
5522 print '<td align="center" width="5">&nbsp;</td>';
5523 }
5524 print '<td>&nbsp;</td>';
5525 print '<td class="nowrap right"><input type="text" size="1" value="" name="all_progress">%</td>';
5526 print '<td class="right"><input type="submit" class="button" name="all_percent" value="Modifier" /></td>';
5527 print '</tr>';
5528
5529 print '</table>';
5530
5531 print '</form>';
5532
5533 print '</div>';
5534 }
5535 }
5536
5537 print ' <form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="POST">
5538 <input type="hidden" name="token" value="' . newToken().'">
5539 <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">
5540 <input type="hidden" name="mode" value="">
5541 <input type="hidden" name="page_y" value="">
5542 <input type="hidden" name="id" value="' . $object->id.'">
5543 <input type="hidden" name="backtopage" value="'.$backtopage.'">
5544 ';
5545
5546 if (!empty($conf->use_javascript_ajax) && $object->statut == 0) {
5547 include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
5548 }
5549
5550 print '<div class="div-table-responsive-no-min">';
5551 print '<table id="tablelines" class="noborder noshadow" width="100%">';
5552
5553 // Show object lines
5554 if (!empty($object->lines)) {
5555 $object->printObjectLines($action, $mysoc, $soc, $lineid, 1);
5556 }
5557
5558 // Form to add new line
5559 if ($object->statut == 0 && $usercancreate && $action != 'valid' && $action != 'editline') {
5560 if ($action != 'editline' && $action != 'selectlines') {
5561 // Add free products/services
5562
5563 $parameters = array();
5564 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
5565 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
5566 if (empty($reshook))
5567 $object->formAddObjectLine(1, $mysoc, $soc);
5568 }
5569 }
5570
5571 print "</table>\n";
5572 print "</div>";
5573
5574 print "</form>\n";
5575
5576 print dol_get_fiche_end();
5577
5578
5579 // Actions buttons
5580
5581 if ($action != 'prerelance' && $action != 'presend' && $action != 'valid' && $action != 'editline') {
5582 print '<div class="tabsAction">';
5583
5584 $parameters = array();
5585 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
5586 if (empty($reshook)) {
5587 $params = array(
5588 'attr' => array(
5589 'class' => 'classfortooltip'
5590 )
5591 );
5592 // Editer une facture deja validee, sans paiement effectue et pas exporte en compta
5593 if ($object->statut == Facture::STATUS_VALIDATED) {
5594 // We check if lines of invoice are not already transfered into accountancy
5595 $ventilExportCompta = $object->getVentilExportCompta();
5596
5597 if ($ventilExportCompta == 0) {
5598 if (!empty($conf->global->INVOICE_CAN_BE_EDITED_EVEN_IF_PAYMENT_DONE) || ($resteapayer == price2num($object->total_ttc, 'MT', 1) && empty($object->paye))) {
5599 if (!$objectidnext && $object->is_last_in_cycle()) {
5600 if ($usercanunvalidate) {
5601 $params['attr']['title'] = '';
5602 print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER['PHP_SELF'].'?facid='.$object->id.'&action=modif&token='.newToken(), '', true, $params);
5603 } else {
5604 $params['attr']['title'] = $langs->trans('NotEnoughPermissions');
5605 print dolGetButtonAction($langs->trans('Modify'), '', 'default', $_SERVER['PHP_SELF'].'?facid='.$object->id.'&action=modif&token='.newToken(), '', false, $params);
5606 }
5607 } elseif (!$object->is_last_in_cycle()) {
5608 $params['attr']['title'] = $langs->trans('NotLastInCycle');
5609 print dolGetButtonAction($langs->trans('Modify'), '', 'default', '#', '', false, $params);
5610 } else {
5611 $params['attr']['title'] = $langs->trans('DisabledBecauseReplacedInvoice');
5612 print dolGetButtonAction($langs->trans('Modify'), '', 'default', '#', '', false, $params);
5613 }
5614 }
5615 } else {
5616 $params['attr']['title'] = $langs->trans('DisabledBecauseDispatchedInBookkeeping');
5617 print dolGetButtonAction($langs->trans('Modify'), '', 'default', '#', '', false, $params);
5618 }
5619 }
5620
5621 $discount = new DiscountAbsolute($db);
5622 $result = $discount->fetch(0, $object->id);
5623
5624 // Reopen an invoice
5625 if ((($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT)
5626 || ($object->type == Facture::TYPE_CREDIT_NOTE && empty($discount->id))
5627 || ($object->type == Facture::TYPE_DEPOSIT && empty($discount->id))
5628 || ($object->type == Facture::TYPE_SITUATION && empty($discount->id)))
5629 && ($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
5630 && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $usercancreate) || $usercanreopen)) { // A paid invoice (partially or completely)
5631 if ($object->close_code != 'replaced' || (!$objectidnext)) { // Not replaced by another invoice or replaced but the replacement invoice has been deleted
5632 $params['attr']['title'] = '';
5633 print dolGetButtonAction($langs->trans('ReOpen'), '', 'default', $_SERVER['PHP_SELF'].'?facid='.$object->id.'&action=reopen&token='.newToken(), '', true, $params);
5634 } else {
5635 $params['attr']['title'] = $langs->trans("DisabledBecauseReplacedInvoice");
5636 print dolGetButtonAction($langs->trans('ReOpen'), '', 'default', '#', '', false, $params);
5637 }
5638 }
5639
5640 // Create contract
5641 if (!empty($conf->global->CONTRACT_CREATE_FROM_INVOICE)) {
5642 if (isModEnabled('contrat') && $object->statut == Facture::STATUS_VALIDATED) {
5643 $langs->load("contracts");
5644
5645 if ($usercancreatecontract) {
5646 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>';
5647 }
5648 }
5649 }
5650
5651 // Validate
5652 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))) {
5653 if ($usercanvalidate) {
5654 $params['attr']['title'] = '';
5655 print dolGetButtonAction($langs->trans('Validate'), '', 'default', $_SERVER["PHP_SELF"].'?facid='.$object->id.'&action=valid&token='.newToken(), '', true, $params);
5656 }
5657 }
5658
5659 // Send by mail
5660 if (empty($user->socid)) {
5661 if (($object->statut == Facture::STATUS_VALIDATED || $object->statut == Facture::STATUS_CLOSED) || !empty($conf->global->FACTURE_SENDBYEMAIL_FOR_ALL_STATUS)) {
5662 if ($objectidnext) {
5663 print '<span class="butActionRefused classfortooltip" title="'.$langs->trans("DisabledBecauseReplacedInvoice").'">'.$langs->trans('SendMail').'</span>';
5664 } else {
5665 if ($usercansend) {
5666 $params['attr']['title'] = '';
5667 print dolGetButtonAction('', $langs->trans('SendMail'), 'default', $_SERVER['PHP_SELF'].'?facid='.$object->id.'&action=presend&mode=init#formmailbeforetitle', '', true, $params);
5668 } else {
5669 $params['attr']['title'] = '';
5670 print dolGetButtonAction('', $langs->trans('SendMail'), 'default', '#', '', false, $params);
5671 }
5672 }
5673 }
5674 }
5675
5676 // Request a direct debit order
5677 if ($object->statut > Facture::STATUS_DRAFT && $object->paye == 0 && $num == 0) {
5678 if ($resteapayer > 0) {
5679 if ($usercancreatewithdrarequest) {
5680 if (!$objectidnext && $object->close_code != 'replaced') { // Not replaced by another invoice
5681 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>';
5682 } else {
5683 print '<span class="butActionRefused classfortooltip" title="'.$langs->trans("DisabledBecauseReplacedInvoice").'">'.$langs->trans('MakeWithdrawRequest').'</span>';
5684 }
5685 } else {
5686 //print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("MakeWithdrawRequest").'</a>';
5687 }
5688 } else {
5689 //print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("AmountMustBePositive")).'">'.$langs->trans("MakeWithdrawRequest").'</a>';
5690 }
5691 }
5692
5693 // POS Ticket
5694 if (isModEnabled('takepos') && $object->module_source == 'takepos') {
5695 $langs->load("cashdesk");
5696 $receipt_url = DOL_URL_ROOT."/takepos/receipt.php";
5697 print '<a target="_blank" rel="noopener noreferrer" class="butAction" href="'.$receipt_url.'?facid='.((int) $object->id).'">'.$langs->trans('POSTicket').'</a>';
5698 }
5699
5700 // Create payment
5701 if ($object->type != Facture::TYPE_CREDIT_NOTE && $object->statut == 1 && $object->paye == 0 && $usercanissuepayment) {
5702 if ($objectidnext) {
5703 print '<span class="butActionRefused classfortooltip" title="'.$langs->trans("DisabledBecauseReplacedInvoice").'">'.$langs->trans('DoPayment').'</span>';
5704 } else {
5705 if ($object->type == Facture::TYPE_DEPOSIT && $resteapayer == 0) {
5706 // For down payment, we refuse to receive more than amount to pay.
5707 $params['attr']['title'] = $langs->trans('DisabledBecauseRemainderToPayIsZero');
5708 print dolGetButtonAction($langs->trans('DoPayment'), '', 'default', '#', '', false, $params);
5709 } else {
5710 // 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)
5711 //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>';
5712 $params['attr']['title'] = '';
5713 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);
5714 }
5715 }
5716 }
5717
5718 $sumofpayment = $totalpaid;
5719 $sumofpaymentall = $totalpaid + $totalcreditnotes + $totaldeposits;
5720
5721 // Reverse back money or convert to reduction
5722 if ($object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_SITUATION) {
5723 // For credit note only
5724 if ($object->type == Facture::TYPE_CREDIT_NOTE && $object->statut == Facture::STATUS_VALIDATED && $object->paye == 0 && $usercanissuepayment) {
5725 if ($resteapayer == 0) {
5726 print '<span class="butActionRefused classfortooltip" title="'.$langs->trans("DisabledBecauseRemainderToPayIsZero").'">'.$langs->trans('DoPaymentBack').'</span>';
5727 } else {
5728 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>';
5729 }
5730 }
5731
5732 // For standard invoice with excess received
5733 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)) {
5734 print '<a class="butAction'.($conf->use_javascript_ajax ? ' reposition' : '').'" href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&amp;action=converttoreduc">'.$langs->trans('ConvertExcessReceivedToReduc').'</a>';
5735 }
5736 // For credit note
5737 if ($object->type == Facture::TYPE_CREDIT_NOTE && $object->statut == Facture::STATUS_VALIDATED && $object->paye == 0 && $usercancreate
5738 && (!empty($conf->global->INVOICE_ALLOW_REUSE_OF_CREDIT_WHEN_PARTIALLY_REFUNDED) || $sumofpayment == 0)
5739 ) {
5740 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>';
5741 }
5742 // For down payment invoice (deposit)
5743 if ($object->type == Facture::TYPE_DEPOSIT && $usercancreate && $object->statut > Facture::STATUS_DRAFT && empty($discount->id)) {
5744 if (price2num($object->total_ttc, 'MT') == price2num($sumofpaymentall, 'MT') || ($object->type == Facture::STATUS_ABANDONED && in_array($object->close_code, array('bankcharge', 'discount_vat', 'other')))) {
5745 // We can close a down payment only if paid amount is same than amount of down payment (by definition)
5746 print '<a class="butAction'.($conf->use_javascript_ajax ? ' reposition' : '').'" href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&amp;action=converttoreduc">'.$langs->trans('ConvertToReduc').'</a>';
5747 } else {
5748 print '<span class="butActionRefused" title="'.$langs->trans("AmountPaidMustMatchAmountOfDownPayment").'">'.$langs->trans('ConvertToReduc').'</span>';
5749 }
5750 }
5751 }
5752
5753 // Classify paid
5754 if ($object->statut == Facture::STATUS_VALIDATED && $object->paye == 0 && $usercanissuepayment && (
5755 ($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))) ||
5756 ($object->type == Facture::TYPE_CREDIT_NOTE && $resteapayer >= 0) ||
5757 ($object->type == Facture::TYPE_DEPOSIT && $object->total_ttc > 0)
5758 )
5759 ) {
5760 if ($object->type == Facture::TYPE_DEPOSIT && price2num($object->total_ttc, 'MT') != price2num($sumofpaymentall, 'MT')) {
5761 // We can close a down payment only if paid amount is same than amount of down payment (by definition)
5762 $params['attr']['title'] = $langs->trans('AmountPaidMustMatchAmountOfDownPayment');
5763 print dolGetButtonAction($langs->trans('ClassifyPaid'), '', 'default', '#', '', false, $params);
5764 } else {
5765 $params['attr']['title'] = '';
5766 print dolGetButtonAction($langs->trans('ClassifyPaid'), '', 'default', $_SERVER['PHP_SELF'].'?facid='.$object->id.'&amp;action=paid', '', true, $params);
5767 }
5768 }
5769
5770 // Classify 'closed not completely paid' (possible if validated and not yet filed paid)
5771 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) {
5772 if ($totalpaid > 0 || $totalcreditnotes > 0) {
5773 // If one payment or one credit note was linked to this invoice
5774 print '<a class="butAction'.($conf->use_javascript_ajax ? ' reposition' : '').'" href="'.$_SERVER['PHP_SELF'].'?facid='.$object->id.'&amp;action=paid">'.$langs->trans('ClassifyPaidPartially').'</a>';
5775 } else {
5776 if (empty($conf->global->INVOICE_CAN_NEVER_BE_CANCELED)) {
5777 if ($objectidnext) {
5778 print '<span class="butActionRefused classfortooltip" title="'.$langs->trans("DisabledBecauseReplacedInvoice").'">'.$langs->trans('ClassifyCanceled').'</span>';
5779 } else {
5780 print '<a class="butAction'.($conf->use_javascript_ajax ? ' reposition' : '').'" href="'.$_SERVER['PHP_SELF'].'?facid='.$object->id.'&amp;action=canceled">'.$langs->trans('ClassifyCanceled').'</a>';
5781 }
5782 }
5783 }
5784 }
5785
5786 // Create a credit note
5787 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) {
5788 if (!$objectidnext) {
5789 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>';
5790 }
5791 }
5792
5793 // For situation invoice with excess received
5794 if ($object->statut > Facture::STATUS_DRAFT
5795 && $object->type == Facture::TYPE_SITUATION
5796 && ($object->total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits) > 0
5797 && $usercancreate
5798 && !$objectidnext
5799 && $object->is_last_in_cycle()
5800 && getDolGlobalInt('INVOICE_USE_SITUATION_CREDIT_NOTE')
5801 ) {
5802 if ($usercanunvalidate) {
5803 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>';
5804 } else {
5805 print '<span class="butActionRefused classfortooltip" title="'.$langs->trans("NotEnoughPermissions").'">'.$langs->trans("CreateCreditNote").'</span>';
5806 }
5807 }
5808
5809 // Clone
5810 if (($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA) && $usercancreate) {
5811 $params['attr']['title'] = '';
5812 print dolGetButtonAction($langs->trans('ToClone'), '', 'default', $_SERVER['PHP_SELF'].'?facid='.$object->id.'&amp;action=clone&amp;object=invoice', '', true, $params);
5813 }
5814
5815 // Clone as predefined / Create template
5816 if (($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA) && $object->statut == 0 && $usercancreate) {
5817 if (!$objectidnext && count($object->lines) > 0) {
5818 $params['attr']['title'] = '';
5819 print dolGetButtonAction($langs->trans('ChangeIntoRepeatableInvoice'), '', 'default', DOL_URL_ROOT.'/compta/facture/card-rec.php?facid='.$object->id.'&amp;action=create', '', true, $params);
5820 }
5821 }
5822
5823 // Remove situation from cycle
5824 if (in_array($object->statut, array(Facture::STATUS_CLOSED, Facture::STATUS_VALIDATED))
5825 && $object->type == Facture::TYPE_SITUATION
5826 && $usercancreate
5827 && !$objectidnext
5828 && $object->situation_counter > 1
5829 && $object->is_last_in_cycle()
5830 && $usercanunvalidate
5831 ) {
5832 if (($object->total_ttc - $totalcreditnotes) == 0) {
5833 print '<a id="butSituationOut" class="butAction" href="'.$_SERVER['PHP_SELF'].'?facid='.$object->id.'&amp;action=situationout">'.$langs->trans("RemoveSituationFromCycle").'</a>';
5834 } else {
5835 print '<a id="butSituationOutRefused" class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("DisabledBecauseNotEnouthCreditNote").'" >'.$langs->trans("RemoveSituationFromCycle").'</a>';
5836 }
5837 }
5838
5839 // Create next situation invoice
5840 if ($usercancreate && ($object->type == 5) && ($object->statut == 1 || $object->statut == 2)) {
5841 if ($object->is_last_in_cycle() && $object->situation_final != 1) {
5842 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>';
5843 } elseif (!$object->is_last_in_cycle()) {
5844 print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("DisabledBecauseNotLastInCycle").'">'.$langs->trans('CreateNextSituationInvoice').'</a>';
5845 } else {
5846 print '<a class="butActionRefused classfortooltip" href="#" title="'.$langs->trans("DisabledBecauseFinal").'">'.$langs->trans('CreateNextSituationInvoice').'</a>';
5847 }
5848 }
5849
5850 // Delete
5851 $isErasable = $object->is_erasable();
5852 if ($usercandelete || ($usercancreate && $isErasable == 1)) { // isErasable = 1 means draft with temporary ref (draft can always be deleted with no need of permissions)
5853 $enableDelete = false;
5854 $deleteHref = '#';
5855 $htmltooltip = '';
5856 if ($isErasable == -4) {
5857 $htmltooltip = $langs->trans('DisabledBecausePayments');
5858 } elseif ($isErasable == -3) {
5859 $htmltooltip = $langs->trans('DisabledBecauseNotLastSituationInvoice');
5860 } elseif ($isErasable == -2) {
5861 $htmltooltip = $langs->trans('DisabledBecauseNotLastInvoice');
5862 } elseif ($isErasable == -1) {
5863 $htmltooltip = $langs->trans('DisabledBecauseDispatchedInBookkeeping');
5864 } elseif ($isErasable <= 0) { // Any other cases
5865 $htmltooltip = $langs->trans('DisabledBecauseNotErasable');
5866 } elseif ($objectidnext) {
5867 $htmltooltip = $langs->trans('DisabledBecauseReplacedInvoice');
5868 } else {
5869 $deleteHref = $_SERVER["PHP_SELF"].'?facid='.$object->id.'&action=delete&token='.newToken();
5870 $enableDelete = true;
5871 }
5872 $params['attr']['title'] = '';
5873 print dolGetButtonAction($htmltooltip, $langs->trans('Delete'), 'delete', $deleteHref, '', $enableDelete, $params);
5874 } else {
5875 $params['attr']['title'] = '';
5876 print dolGetButtonAction($htmltooltip, $langs->trans('Delete'), 'delete', '#', '', false);
5877 }
5878 }
5879 print '</div>';
5880 }
5881
5882 // Select mail models is same action as presend
5883 if (GETPOST('modelselected', 'alpha')) {
5884 $action = 'presend';
5885 }
5886 if ($action != 'prerelance' && $action != 'presend') {
5887 print '<div class="fichecenter"><div class="fichehalfleft">';
5888 print '<a name="builddoc"></a>'; // ancre
5889
5890 // Generated documents
5891 $filename = dol_sanitizeFileName($object->ref);
5892 $filedir = $conf->facture->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
5893 $urlsource = $_SERVER['PHP_SELF'].'?facid='.$object->id;
5894 $genallowed = $usercanread;
5895 $delallowed = $usercancreate;
5896
5897 print $formfile->showdocuments(
5898 'facture',
5899 $filename,
5900 $filedir,
5901 $urlsource,
5902 $genallowed,
5903 $delallowed,
5904 $object->model_pdf,
5905 1,
5906 0,
5907 0,
5908 28,
5909 0,
5910 '',
5911 '',
5912 '',
5913 $soc->default_lang,
5914 '',
5915 $object,
5916 0,
5917 'remove_file_comfirm'
5918 );
5919
5920 $somethingshown = $formfile->numoffiles;
5921
5922 // Show links to link elements
5923 $linktoelem = $form->showLinkToObjectBlock($object, null, array('invoice'));
5924
5925 $compatibleImportElementsList = false;
5926 if ($usercancreate
5927 && $object->statut == Facture::STATUS_DRAFT
5928 && ($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)) {
5929 $compatibleImportElementsList = array('commande', 'propal'); // import from linked elements
5930 }
5931 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem, $compatibleImportElementsList);
5932
5933
5934 // Show online payment link
5935 $useonlinepayment = (isModEnabled('paypal') || isModEnabled('stripe') || isModEnabled('paybox'));
5936
5937 if ($object->statut != Facture::STATUS_DRAFT && $useonlinepayment) {
5938 print '<br><!-- Link to pay -->'."\n";
5939 require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
5940 print showOnlinePaymentUrl('invoice', $object->ref).'<br>';
5941 }
5942
5943 print '</div><div class="fichehalfright">';
5944
5945 $MAXEVENT = 10;
5946
5947 $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', DOL_URL_ROOT.'/compta/facture/agenda.php?id='.$object->id);
5948
5949 // List of actions on element
5950 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
5951 $formactions = new FormActions($db);
5952 $somethingshown = $formactions->showactions($object, 'invoice', $socid, 1, '', $MAXEVENT, '', $morehtmlcenter); // Show all action for thirdparty
5953
5954 print '</div></div>';
5955 }
5956
5957
5958 // Presend form
5959 $modelmail = 'facture_send';
5960 $defaulttopic = 'SendBillRef';
5961 $diroutput = $conf->facture->multidir_output[$object->entity];
5962 $trackid = 'inv'.$object->id;
5963
5964 include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
5965}
5966
5967// End of page
5968llxFooter();
5969$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:624
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:123
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:410
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.