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