PageRenderTime 72ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/htdocs/facture/facture.php

https://bitbucket.org/speedealing/speedealing
PHP | 2985 lines | 2268 code | 347 blank | 370 comment | 1010 complexity | cdbf5f8b60e3127b4a250dee586ce023 MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1, GPL-3.0, MIT
  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-2012 Laurent Destailleur <eldy@users.sourceforge.net>
  5. * Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
  6. * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
  7. * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
  8. * Copyright (C) 2010-2012 Juanjo Menent <jmenent@2byte.es>
  9. * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
  10. * Copyright (C) 2011-2012 Herve Prot <herve.prot@symeos.com>
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 3 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. */
  25. /**
  26. * \file htdocs/compta/facture.php
  27. * \ingroup facture
  28. * \brief Page to create/see an invoice
  29. */
  30. require '../main.inc.php';
  31. require DOL_DOCUMENT_ROOT . '/facture/class/facture.class.php';
  32. require DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php';
  33. require DOL_DOCUMENT_ROOT . '/facture/core/modules/facture/modules_facture.php';
  34. require DOL_DOCUMENT_ROOT . '/core/class/discount.class.php';
  35. require DOL_DOCUMENT_ROOT . '/core/class/html.formfile.class.php';
  36. require DOL_DOCUMENT_ROOT . '/core/class/html.formother.class.php';
  37. require DOL_DOCUMENT_ROOT . '/core/lib/invoice.lib.php';
  38. require_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
  39. require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
  40. if (!empty($conf->commande->enabled)) {
  41. require DOL_DOCUMENT_ROOT . '/commande/class/commande.class.php';
  42. }
  43. if (!empty($conf->projet->enabled)) {
  44. require DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
  45. require DOL_DOCUMENT_ROOT . '/core/lib/project.lib.php';
  46. }
  47. $langs->load('bills');
  48. $langs->load('companies');
  49. $langs->load('products');
  50. $langs->load('main');
  51. if (!empty($conf->margin->enabled))
  52. $langs->load('margins');
  53. $sall = trim(GETPOST('sall'));
  54. $projectid = (GETPOST('projectid') ? GETPOST('projectid', 'int') : 0);
  55. $id = (GETPOST('id', 'alpha') ? GETPOST('id', 'akpha') : GETPOST('facid', 'alpha')); // For backward compatibility
  56. $ref = GETPOST('ref', 'alpha');
  57. $socid = GETPOST('socid', 'alpha');
  58. $action = GETPOST('action', 'alpha');
  59. $confirm = GETPOST('confirm', 'alpha');
  60. $lineid = GETPOST('lineid', 'alpha');
  61. $userid = GETPOST('userid', 'alpha');
  62. $search_ref = GETPOST('sf_ref') ? GETPOST('sf_ref', 'alpha') : GETPOST('search_ref', 'alpha');
  63. $search_societe = GETPOST('search_societe', 'alpha');
  64. $search_montant_ht = GETPOST('search_montant_ht', 'alpha');
  65. $search_montant_ttc = GETPOST('search_montant_ttc', 'alpha');
  66. $origin = GETPOST('origin', 'alpha');
  67. $originid = (GETPOST('originid', 'alpha') ? GETPOST('originid', 'alpha') : GETPOST('origin_id', 'alpha')); // For backward compatibility
  68. //PDF
  69. $hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
  70. $hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0));
  71. $hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0));
  72. // Security check
  73. $fieldid = (!empty($ref) ? 'facnumber' : 'rowid');
  74. if ($user->societe_id)
  75. $socid = $user->societe_id;
  76. $result = restrictedArea($user, 'facture', $id, '', '', 'fk_soc', $fieldid);
  77. // Nombre de ligne pour choix de produit/service predefinis
  78. $NBLINES = 4;
  79. $usehm = (!empty($conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE) ? $conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE : 0);
  80. $object = new Facture($db);
  81. // Load object
  82. if (!empty($id) || !empty($ref)) {
  83. $ret = $object->fetch($id, $ref);
  84. }
  85. // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
  86. $hookmanager->initHooks(array('invoicecard'));
  87. /*
  88. * Actions
  89. */
  90. $parameters = array('socid' => $socid);
  91. $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
  92. // Action clone object
  93. if ($action == 'confirm_clone' && $confirm == 'yes' && $user->rights->facture->creer) {
  94. if (1 == 0 && empty($_REQUEST["clone_content"]) && empty($_REQUEST["clone_receivers"])) {
  95. $mesgs[] = '<div class="error">' . $langs->trans("NoCloneOptionsSpecified") . '</div>';
  96. } else {
  97. if ($object->fetch($id) > 0) {
  98. $result = $object->createFromClone($socid);
  99. if ($result > 0) {
  100. header("Location: " . $_SERVER['PHP_SELF'] . '?facid=' . $result);
  101. exit;
  102. } else {
  103. $mesgs[] = $object->error;
  104. $action = '';
  105. }
  106. }
  107. }
  108. }
  109. // Change status of invoice
  110. else if ($action == 'reopen' && $user->rights->facture->creer) {
  111. $result = $object->fetch($id);
  112. if ($object->statut == 2
  113. || ($object->statut == 3 && $object->close_code != 'replaced')) {
  114. $result = $object->set_unpaid($user);
  115. if ($result > 0) {
  116. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id);
  117. exit;
  118. } else {
  119. $mesgs[] = '<div class="error">' . $object->error . '</div>';
  120. }
  121. }
  122. }
  123. // Delete invoice
  124. else if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->facture->supprimer) {
  125. $result = $object->fetch($id);
  126. $object->fetch_thirdparty();
  127. $result = $object->delete();
  128. if ($result > 0) {
  129. header('Location: ' . DOL_URL_ROOT . '/compta/facture/list.php');
  130. exit;
  131. } else {
  132. $mesgs[] = '<div class="error">' . $object->error . '</div>';
  133. }
  134. }
  135. // Delete line
  136. else if ($action == 'confirm_deleteline' && $confirm == 'yes' && $user->rights->facture->creer) {
  137. $object->fetch($id);
  138. $object->fetch_thirdparty();
  139. $result = $object->deleteline($_GET['lineid'], $user);
  140. if ($result > 0) {
  141. // Define output language
  142. $outputlangs = $langs;
  143. $newlang = '';
  144. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($_REQUEST['lang_id']))
  145. $newlang = $_REQUEST['lang_id'];
  146. if ($conf->global->MAIN_MULTILANGS && empty($newlang))
  147. $newlang = $object->client->default_lang;
  148. if (!empty($newlang)) {
  149. $outputlangs = new Translate();
  150. $outputlangs->setDefaultLang($newlang);
  151. }
  152. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
  153. $ret = $object->fetch($id); // Reload to get new records
  154. $result = facture_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  155. }
  156. if ($result >= 0) {
  157. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id);
  158. exit;
  159. }
  160. } else {
  161. $mesgs[] = '<div clas="error">' . $object->error . '</div>';
  162. $action = '';
  163. }
  164. }
  165. // Delete link of credit note to invoice
  166. else if ($action == 'unlinkdiscount' && $user->rights->facture->creer) {
  167. $discount = new DiscountAbsolute($db);
  168. $result = $discount->fetch($_GET["discountid"]);
  169. $discount->unlink_invoice();
  170. }
  171. // Validation
  172. else if ($action == 'valid' && $user->rights->facture->creer) {
  173. $object->fetch($id);
  174. // On verifie signe facture
  175. if ($object->type == 2) {
  176. // Si avoir, le signe doit etre negatif
  177. if ($object->total_ht >= 0) {
  178. $mesgs[] = '<div class="error">' . $langs->trans("ErrorInvoiceAvoirMustBeNegative") . '</div>';
  179. $action = '';
  180. }
  181. } else {
  182. // Si non avoir, le signe doit etre positif
  183. if (empty($conf->global->FACTURE_ENABLE_NEGATIVE) && $object->total_ht < 0) {
  184. $mesgs[] = '<div class="error">' . $langs->trans("ErrorInvoiceOfThisTypeMustBePositive") . '</div>';
  185. $action = '';
  186. }
  187. }
  188. } else if ($action == 'set_thirdparty' && $user->rights->facture->creer) {
  189. $object->fetch($id);
  190. $object->setValueFrom('fk_soc', $socid);
  191. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id);
  192. exit;
  193. } else if ($action == 'classin' && $user->rights->facture->creer) {
  194. $object->fetch($id);
  195. $object->setProject($_POST['projectid']);
  196. } else if ($action == 'setmode' && $user->rights->facture->creer) {
  197. $object->fetch($id);
  198. $result = $object->setPaymentMethods(GETPOST('mode_reglement_id', 'int'));
  199. if ($result < 0)
  200. dol_print_error($db, $object->error);
  201. }
  202. else if ($action == 'setinvoicedate' && $user->rights->facture->creer) {
  203. $object->fetch($id);
  204. $object->date = dol_mktime(12, 0, 0, $_POST['invoicedatemonth'], $_POST['invoicedateday'], $_POST['invoicedateyear']);
  205. if ($object->date_lim_reglement < $object->date)
  206. $object->date_lim_reglement = $object->date;
  207. $result = $object->update($user);
  208. if ($result < 0)
  209. dol_print_error($db, $object->error);
  210. }
  211. else if ($action == 'setpaymentterm' && $user->rights->facture->creer) {
  212. $object->fetch($id);
  213. $object->date_lim_reglement = dol_mktime(12, 0, 0, $_POST['paymenttermmonth'], $_POST['paymenttermday'], $_POST['paymenttermyear']);
  214. if ($object->date_lim_reglement < $object->date) {
  215. $object->date_lim_reglement = $object->date;
  216. setEventMessage($langs->trans("DatePaymentTermCantBeLowerThanObjectDate"), 'warnings');
  217. }
  218. $result = $object->update($user);
  219. if ($result < 0)
  220. dol_print_error($db, $object->error);
  221. }
  222. else if ($action == 'setconditions' && $user->rights->facture->creer) {
  223. $object->fetch($id);
  224. $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'));
  225. if ($result < 0)
  226. dol_print_error($db, $object->error);
  227. }
  228. else if ($action == 'setremisepercent' && $user->rights->facture->creer) {
  229. $object->fetch($id);
  230. $result = $object->set_remise($user, $_POST['remise_percent']);
  231. } else if ($action == "setabsolutediscount" && $user->rights->facture->creer) {
  232. // POST[remise_id] ou POST[remise_id_for_payment]
  233. if (!empty($_POST["remise_id"])) {
  234. $ret = $object->fetch($id);
  235. if ($ret > 0) {
  236. $result = $object->insert_discount($_POST["remise_id"]);
  237. if ($result < 0) {
  238. $mesgs[] = '<div class="error">' . $object->error . '</div>';
  239. }
  240. } else {
  241. dol_print_error($db, $object->error);
  242. }
  243. }
  244. if (!empty($_POST["remise_id_for_payment"])) {
  245. require_once DOL_DOCUMENT_ROOT . '/core/class/discount.class.php';
  246. $discount = new DiscountAbsolute($db);
  247. $discount->fetch($_POST["remise_id_for_payment"]);
  248. $result = $discount->link_to_invoice(0, $id);
  249. if ($result < 0) {
  250. $mesgs[] = '<div class="error">' . $discount->error . '</div>';
  251. }
  252. }
  253. } else if ($action == 'set_ref_client' && $user->rights->facture->creer) {
  254. $object->fetch($id);
  255. $object->set_ref_client($_POST['ref_client']);
  256. } else if ($action == 'setnote_public' && $user->rights->facture->creer) {
  257. $object->fetch($id);
  258. $result = $object->update_note_public(dol_html_entity_decode(GETPOST('note_public'), ENT_QUOTES));
  259. if ($result < 0)
  260. dol_print_error($db, $object->error);
  261. }
  262. else if ($action == 'setnote' && $user->rights->facture->creer) {
  263. $object->fetch($id);
  264. $result = $object->update_note(dol_html_entity_decode(GETPOST('note'), ENT_QUOTES));
  265. if ($result < 0)
  266. dol_print_error($db, $object->error);
  267. }
  268. // Classify to validated
  269. else if ($action == 'confirm_valid' && $confirm == 'yes' && $user->rights->facture->valider) {
  270. $idwarehouse = GETPOST('idwarehouse');
  271. $object->fetch($id);
  272. $object->fetch_thirdparty();
  273. // Check parameters
  274. if ($object->type != 3 && !empty($conf->global->STOCK_CALCULATE_ON_BILL) && $object->hasProductsOrServices(1)) {
  275. if (!$idwarehouse || $idwarehouse == -1) {
  276. $error++;
  277. $mesgs[] = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse"));
  278. $action = '';
  279. }
  280. }
  281. if (!$error) {
  282. $result = $object->validate($user, '', $idwarehouse);
  283. if ($result >= 0) {
  284. // Define output language
  285. $outputlangs = $langs;
  286. $newlang = '';
  287. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($_REQUEST['lang_id']))
  288. $newlang = $_REQUEST['lang_id'];
  289. if ($conf->global->MAIN_MULTILANGS && empty($newlang))
  290. $newlang = $object->client->default_lang;
  291. if (!empty($newlang)) {
  292. $outputlangs = new Translate();
  293. $outputlangs->setDefaultLang($newlang);
  294. }
  295. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
  296. $ret = $object->fetch($id); // Reload to get new records
  297. facture_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  298. }
  299. } else {
  300. $mesgs[] = '<div class="error">' . $object->error . '</div>';
  301. }
  302. }
  303. }
  304. // Go back to draft status (unvalidate)
  305. else if ($action == 'confirm_modif' && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->facture->valider) || $user->rights->facture->invoice_advance->unvalidate)) {
  306. $idwarehouse = GETPOST('idwarehouse');
  307. $object->fetch($id);
  308. $object->fetch_thirdparty();
  309. // Check parameters
  310. if ($object->type != 3 && !empty($conf->global->STOCK_CALCULATE_ON_BILL) && $object->hasProductsOrServices(1)) {
  311. if (!$idwarehouse || $idwarehouse == -1) {
  312. $error++;
  313. $mesgs[] = $langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse"));
  314. $action = '';
  315. }
  316. }
  317. if (!$error) {
  318. // On verifie si la facture a des paiements
  319. $sql = 'SELECT pf.amount';
  320. $sql.= ' FROM ' . MAIN_DB_PREFIX . 'paiement_facture as pf';
  321. $sql.= ' WHERE pf.fk_facture = ' . $object->id;
  322. $result = $db->query($sql);
  323. if ($result) {
  324. $i = 0;
  325. $num = $db->num_rows($result);
  326. while ($i < $num) {
  327. $objp = $db->fetch_object($result);
  328. $totalpaye += $objp->amount;
  329. $i++;
  330. }
  331. } else {
  332. dol_print_error($db, '');
  333. }
  334. $resteapayer = $object->total_ttc - $totalpaye;
  335. // On verifie si les lignes de factures ont ete exportees en compta et/ou ventilees
  336. $ventilExportCompta = $object->getVentilExportCompta();
  337. // On verifie si aucun paiement n'a ete effectue
  338. if ($resteapayer == $object->total_ttc && $object->paye == 0 && $ventilExportCompta == 0) {
  339. $object->set_draft($user, $idwarehouse);
  340. // Define output language
  341. $outputlangs = $langs;
  342. $newlang = '';
  343. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($_REQUEST['lang_id']))
  344. $newlang = $_REQUEST['lang_id'];
  345. if ($conf->global->MAIN_MULTILANGS && empty($newlang))
  346. $newlang = $object->client->default_lang;
  347. if (!empty($newlang)) {
  348. $outputlangs = new Translate();
  349. $outputlangs->setDefaultLang($newlang);
  350. }
  351. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
  352. $ret = $object->fetch($id); // Reload to get new records
  353. facture_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  354. }
  355. }
  356. }
  357. }
  358. // Classify "paid"
  359. else if ($action == 'confirm_paid' && $confirm == 'yes' && $user->rights->facture->paiement) {
  360. $object->fetch($id);
  361. $result = $object->set_paid($user);
  362. }
  363. // Classif "paid partialy"
  364. else if ($action == 'confirm_paid_partially' && $confirm == 'yes' && $user->rights->facture->paiement) {
  365. $object->fetch($id);
  366. $close_code = $_POST["close_code"];
  367. $close_note = $_POST["close_note"];
  368. if ($close_code) {
  369. $result = $object->set_paid($user, $close_code, $close_note);
  370. } else {
  371. $mesgs[] = '<div class="error">' . $langs->trans("ErrorFieldRequired", $langs->trans("Reason")) . '</div>';
  372. }
  373. }
  374. // Classify "abandoned"
  375. else if ($action == 'confirm_canceled' && $confirm == 'yes') {
  376. $object->fetch($id);
  377. $close_code = $_POST["close_code"];
  378. $close_note = $_POST["close_note"];
  379. if ($close_code) {
  380. $result = $object->set_canceled($user, $close_code, $close_note);
  381. } else {
  382. $mesgs[] = '<div class="error">' . $langs->trans("ErrorFieldRequired", $langs->trans("Reason")) . '</div>';
  383. }
  384. }
  385. // Convertir en reduc
  386. else if ($action == 'confirm_converttoreduc' && $confirm == 'yes' && $user->rights->facture->creer) {
  387. $db->begin();
  388. $object->fetch($id);
  389. $object->fetch_thirdparty();
  390. $object->fetch_lines();
  391. if (!$object->paye) { // protection against multiple submit
  392. // Boucle sur chaque taux de tva
  393. $i = 0;
  394. foreach ($object->lines as $line) {
  395. $amount_ht[$line->tva_tx]+=$line->total_ht;
  396. $amount_tva[$line->tva_tx]+=$line->total_tva;
  397. $amount_ttc[$line->tva_tx]+=$line->total_ttc;
  398. $i++;
  399. }
  400. // Insert one discount by VAT rate category
  401. $discount = new DiscountAbsolute($db);
  402. if ($object->type == 2)
  403. $discount->description = '(CREDIT_NOTE)';
  404. elseif ($object->type == 3)
  405. $discount->description = '(DEPOSIT)';
  406. else {
  407. $this->error = "CantConvertToReducAnInvoiceOfThisType";
  408. return -1;
  409. }
  410. $discount->tva_tx = abs($object->total_ttc);
  411. $discount->fk_soc = $object->socid;
  412. $discount->fk_facture_source = $object->id;
  413. $error = 0;
  414. foreach ($amount_ht as $tva_tx => $xxx) {
  415. $discount->amount_ht = abs($amount_ht[$tva_tx]);
  416. $discount->amount_tva = abs($amount_tva[$tva_tx]);
  417. $discount->amount_ttc = abs($amount_ttc[$tva_tx]);
  418. $discount->tva_tx = abs($tva_tx);
  419. $result = $discount->create($user);
  420. if ($result < 0) {
  421. $error++;
  422. break;
  423. }
  424. }
  425. if (!$error) {
  426. // Classe facture
  427. $result = $object->set_paid($user);
  428. if ($result > 0) {
  429. //$mesgs[]='OK'.$discount->id;
  430. $db->commit();
  431. } else {
  432. $mesgs[] = '<div class="error">' . $object->error . '</div>';
  433. $db->rollback();
  434. }
  435. } else {
  436. $mesgs[] = '<div class="error">' . $discount->error . '</div>';
  437. $db->rollback();
  438. }
  439. }
  440. }
  441. /*
  442. * Insert new invoice in database
  443. */ else if ($action == 'add' && $user->rights->facture->creer) {
  444. $object->socid = GETPOST('socid', 'int');
  445. $error = 0;
  446. // Replacement invoice
  447. if ($_POST['type'] == 1) {
  448. $datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
  449. if (empty($datefacture)) {
  450. $error++;
  451. $mesgs[] = '<div class="error">' . $langs->trans("ErrorFieldRequired", $langs->trans("Date")) . '</div>';
  452. }
  453. if (!($_POST['fac_replacement'] > 0)) {
  454. $error++;
  455. $mesgs[] = '<div class="error">' . $langs->trans("ErrorFieldRequired", $langs->trans("ReplaceInvoice")) . '</div>';
  456. }
  457. if (!$error) {
  458. // This is a replacement invoice
  459. $result = $object->fetch($_POST['fac_replacement']);
  460. $object->fetch_thirdparty();
  461. $object->date = $datefacture;
  462. $object->note_public = trim($_POST['note_public']);
  463. $object->note = trim($_POST['note']);
  464. $object->ref_client = $_POST['ref_client'];
  465. $object->ref_int = $_POST['ref_int'];
  466. $object->modelpdf = $_POST['model'];
  467. $object->fk_project = $_POST['projectid'];
  468. $object->cond_reglement_id = $_POST['cond_reglement_id'];
  469. $object->mode_reglement_id = $_POST['mode_reglement_id'];
  470. $object->remise_absolue = $_POST['remise_absolue'];
  471. $object->remise_percent = $_POST['remise_percent'];
  472. // Proprietes particulieres a facture de remplacement
  473. $object->fk_facture_source = $_POST['fac_replacement'];
  474. $object->type = 1;
  475. $id = $object->createFromCurrent($user);
  476. if ($id <= 0)
  477. $mesgs[] = $object->error;
  478. }
  479. }
  480. // Credit note invoice
  481. if ($_POST['type'] == 2) {
  482. if (!$_POST['fac_avoir'] > 0) {
  483. $error++;
  484. $mesgs[] = '<div class="error">' . $langs->trans("ErrorFieldRequired", $langs->trans("CorrectInvoice")) . '</div>';
  485. }
  486. $datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
  487. if (empty($datefacture)) {
  488. $error++;
  489. $mesgs[] = '<div class="error">' . $langs->trans("ErrorFieldRequired", $langs->trans("Date")) . '</div>';
  490. }
  491. if (!$error) {
  492. // Si facture avoir
  493. $datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
  494. //$result=$object->fetch($_POST['fac_avoir']);
  495. $object->socid = $_POST['socid'];
  496. $object->number = $_POST['facnumber'];
  497. $object->date = $datefacture;
  498. $object->note_public = trim($_POST['note_public']);
  499. $object->note = trim($_POST['note']);
  500. $object->ref_client = $_POST['ref_client'];
  501. $object->ref_int = $_POST['ref_int'];
  502. $object->modelpdf = $_POST['model'];
  503. $object->fk_project = $_POST['projectid'];
  504. $object->cond_reglement_id = 0;
  505. $object->mode_reglement_id = $_POST['mode_reglement_id'];
  506. $object->remise_absolue = $_POST['remise_absolue'];
  507. $object->remise_percent = $_POST['remise_percent'];
  508. // Proprietes particulieres a facture avoir
  509. $object->fk_facture_source = $_POST['fac_avoir'];
  510. $object->type = 2;
  511. $id = $object->create($user);
  512. // Add predefined lines
  513. for ($i = 1; $i <= $NBLINES; $i++) {
  514. if ($_POST['idprod' . $i]) {
  515. $product = new Product($db);
  516. $product->fetch($_POST['idprod' . $i]);
  517. $startday = dol_mktime(12, 0, 0, $_POST['date_start' . $i . 'month'], $_POST['date_start' . $i . 'day'], $_POST['date_start' . $i . 'year']);
  518. $endday = dol_mktime(12, 0, 0, $_POST['date_end' . $i . 'month'], $_POST['date_end' . $i . 'day'], $_POST['date_end' . $i . 'year']);
  519. $result = $object->addline($id, $product->description, $product->price, $_POST['qty' . $i], $product->tva_tx, $product->localtax1_tx, $product->localtax2_tx, $_POST['idprod' . $i], $_POST['remise_percent' . $i], $startday, $endday, 0, 0, '', $product->price_base_type, $product->price_ttc, $product->type);
  520. }
  521. }
  522. }
  523. }
  524. // Standard invoice or Deposit invoice created from a Predefined invoice
  525. if (($_POST['type'] == "INVOICE_STANDARD" || $_POST['type'] == "INVOICE_DEPOSIT") && $_POST['fac_rec'] > 0) {
  526. $datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
  527. if (empty($datefacture)) {
  528. $error++;
  529. $mesgs[] = '<div class="error">' . $langs->trans("ErrorFieldRequired", $langs->trans("Date")) . '</div>';
  530. }
  531. if (!$error) {
  532. $object->socid = $_POST['socid'];
  533. $object->type = $_POST['type'];
  534. $object->number = $_POST['facnumber'];
  535. $object->date = $datefacture;
  536. $object->note_public = trim($_POST['note_public']);
  537. $object->note = trim($_POST['note']);
  538. $object->ref_client = $_POST['ref_client'];
  539. $object->ref_int = $_POST['ref_int'];
  540. $object->modelpdf = $_POST['model'];
  541. // Source facture
  542. $object->fac_rec = $_POST['fac_rec'];
  543. $id = $object->create($user);
  544. }
  545. }
  546. // Standard or deposit or proforma invoice
  547. if (($_POST['type'] == "INVOICE_STANDARD" || $_POST['type'] == "INVOICE_DEPOSIT" || $_POST['type'] == 4) && $_POST['fac_rec'] <= 0) {
  548. $datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
  549. if (empty($datefacture)) {
  550. $error++;
  551. $mesgs[] = '<div class="error">' . $langs->trans("ErrorFieldRequired", $langs->trans("Date")) . '</div>';
  552. }
  553. if (!$error) {
  554. // Si facture standard
  555. $object->socid = $_POST['socid'];
  556. $object->type = $_POST['type'];
  557. $object->number = $_POST['facnumber'];
  558. $object->date = $datefacture;
  559. $object->note_public = trim($_POST['note_public']);
  560. $object->note = trim($_POST['note']);
  561. $object->ref_client = $_POST['ref_client'];
  562. $object->ref_int = $_POST['ref_int'];
  563. $object->modelpdf = $_POST['model'];
  564. $object->fk_project = $_POST['projectid'];
  565. $object->cond_reglement_code = $_POST["cond_reglement_code"]; //($_POST['type'] == 3?1:$_POST['cond_reglement_id']);
  566. $object->mode_reglement_code = $_POST['mode_reglement_code'];
  567. $object->amount = $_POST['amount'];
  568. $object->remise_absolue = $_POST['remise_absolue'];
  569. $object->remise_percent = $_POST['remise_percent'];
  570. // If creation from another object of another module (Example: origin=propal, originid=1)
  571. if ($_POST['origin'] && $_POST['originid']) {
  572. // Parse element/subelement (ex: project_task)
  573. $element = $subelement = $_POST['origin'];
  574. if (preg_match('/^([^_]+)_([^_]+)/i', $_POST['origin'], $regs)) {
  575. $element = $regs[1];
  576. $subelement = $regs[2];
  577. }
  578. // For compatibility
  579. if ($element == 'order') {
  580. $element = $subelement = 'commande';
  581. }
  582. if ($element == 'propal') {
  583. $element = 'comm/propal';
  584. $subelement = 'propal';
  585. }
  586. if ($element == 'contract') {
  587. $element = $subelement = 'contrat';
  588. }
  589. if ($element == 'inter') {
  590. $element = $subelement = 'ficheinter';
  591. }
  592. if ($element == 'shipping') {
  593. $element = $subelement = 'expedition';
  594. }
  595. $object->origin = $_POST['origin'];
  596. $object->origin_id = $_POST['originid'];
  597. // Possibility to add external linked objects with hooks
  598. $object->linked_objects[$object->origin] = $object->origin_id;
  599. if (is_array($_POST['other_linked_objects']) && !empty($_POST['other_linked_objects'])) {
  600. $object->linked_objects = array_merge($object->linked_objects, $_POST['other_linked_objects']);
  601. }
  602. $id = $object->create($user);
  603. if ($id > 0) {
  604. dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
  605. $classname = ucfirst($subelement);
  606. $srcobject = new $classname($db);
  607. dol_syslog("Try to find source object origin=" . $object->origin . " originid=" . $object->origin_id . " to add lines");
  608. $result = $srcobject->fetch($object->origin_id);
  609. if ($result > 0) {
  610. $lines = $srcobject->lines;
  611. if (empty($lines) && method_exists($srcobject, 'fetch_lines'))
  612. $lines = $srcobject->fetch_lines();
  613. $fk_parent_line = 0;
  614. $num = count($lines);
  615. for ($i = 0; $i < $num; $i++) {
  616. $label = (!empty($lines[$i]->label) ? $lines[$i]->label : '');
  617. $desc = (!empty($lines[$i]->desc) ? $lines[$i]->desc : $lines[$i]->libelle);
  618. if ($lines[$i]->subprice < 0) {
  619. // Negative line, we create a discount line
  620. $discount = new DiscountAbsolute($db);
  621. $discount->fk_soc = $object->socid;
  622. $discount->amount_ht = abs($lines[$i]->total_ht);
  623. $discount->amount_tva = abs($lines[$i]->total_tva);
  624. $discount->amount_ttc = abs($lines[$i]->total_ttc);
  625. $discount->tva_tx = $lines[$i]->tva_tx;
  626. $discount->fk_user = $user->id;
  627. $discount->description = $desc;
  628. $discountid = $discount->create($user);
  629. if ($discountid > 0) {
  630. $result = $object->insert_discount($discountid); // This include link_to_invoice
  631. } else {
  632. $mesgs[] = $discount->error;
  633. $error++;
  634. break;
  635. }
  636. } else {
  637. // Positive line
  638. $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0);
  639. // Date start
  640. $date_start = false;
  641. if ($lines[$i]->date_debut_prevue)
  642. $date_start = $lines[$i]->date_debut_prevue;
  643. if ($lines[$i]->date_debut_reel)
  644. $date_start = $lines[$i]->date_debut_reel;
  645. if ($lines[$i]->date_start)
  646. $date_start = $lines[$i]->date_start;
  647. //Date end
  648. $date_end = false;
  649. if ($lines[$i]->date_fin_prevue)
  650. $date_end = $lines[$i]->date_fin_prevue;
  651. if ($lines[$i]->date_fin_reel)
  652. $date_end = $lines[$i]->date_fin_reel;
  653. if ($lines[$i]->date_end)
  654. $date_end = $lines[$i]->date_end;
  655. // Reset fk_parent_line for no child products and special product
  656. if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) {
  657. $fk_parent_line = 0;
  658. }
  659. $result = $object->addline(
  660. $id, $desc, $lines[$i]->subprice, $lines[$i]->qty, $lines[$i]->tva_tx, $lines[$i]->localtax1_tx, $lines[$i]->localtax2_tx, $lines[$i]->fk_product, $lines[$i]->remise_percent, $date_start, $date_end, 0, $lines[$i]->info_bits, $lines[$i]->fk_remise_except, 'HT', 0, $product_type, $lines[$i]->rang, $lines[$i]->special_code, $object->origin, $lines[$i]->rowid, $fk_parent_line, $lines[$i]->fk_fournprice, $lines[$i]->pa_ht, $label
  661. );
  662. if ($result > 0) {
  663. $lineid = $result;
  664. } else {
  665. $lineid = 0;
  666. $error++;
  667. break;
  668. }
  669. // Defined the new fk_parent_line
  670. if ($result > 0 && $lines[$i]->product_type == 9) {
  671. $fk_parent_line = $result;
  672. }
  673. }
  674. }
  675. // Hooks
  676. $parameters = array('objFrom' => $srcobject);
  677. $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  678. if ($reshook < 0)
  679. $error++;
  680. }
  681. else {
  682. $mesgs[] = $srcobject->error;
  683. $error++;
  684. }
  685. } else {
  686. $mesgs[] = $object->error;
  687. $error++;
  688. }
  689. }
  690. // If some invoice's lines already known
  691. else {
  692. $id = $object->create($user);
  693. for ($i = 1; $i <= $NBLINES; $i++) {
  694. if ($_POST['idprod' . $i]) {
  695. $product = new Product($db);
  696. $product->fetch($_POST['idprod' . $i]);
  697. $startday = dol_mktime(12, 0, 0, $_POST['date_start' . $i . 'month'], $_POST['date_start' . $i . 'day'], $_POST['date_start' . $i . 'year']);
  698. $endday = dol_mktime(12, 0, 0, $_POST['date_end' . $i . 'month'], $_POST['date_end' . $i . 'day'], $_POST['date_end' . $i . 'year']);
  699. $result = $object->addline($id, $product->description, $product->price, $_POST['qty' . $i], $product->tva_tx, $product->localtax1_tx, $product->localtax2_tx, $_POST['idprod' . $i], $_POST['remise_percent' . $i], $startday, $endday, 0, 0, '', $product->price_base_type, $product->price_ttc, $product->type);
  700. }
  701. }
  702. if (!empty($id)) {
  703. header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $id);
  704. exit;
  705. }
  706. }
  707. }
  708. }
  709. // End of object creation, we show it
  710. if ($id > 0 && !$error) {
  711. $db->commit();
  712. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id);
  713. exit;
  714. } else {
  715. $db->rollback();
  716. $action = 'create';
  717. $_GET["origin"] = $_POST["origin"];
  718. $_GET["originid"] = $_POST["originid"];
  719. $mesgs[] = '<div class="error">' . $object->error . '</div>';
  720. }
  721. }
  722. // Add a new line
  723. else if (($action == 'addline' || $action == 'addline_predef') && $user->rights->facture->creer) {
  724. $langs->load('errors');
  725. $error = false;
  726. $idprod = GETPOST('idprod', 'int');
  727. $product_desc = (GETPOST('product_desc') ? GETPOST('product_desc') : (GETPOST('np_desc') ? GETPOST('np_desc') : (GETPOST('dp_desc') ? GETPOST('dp_desc') : '')));
  728. $price_ht = GETPOST('price_ht');
  729. $tva_tx = GETPOST('tva_tx');
  730. if ((empty($idprod) || GETPOST('usenewaddlineform')) && ($price_ht < 0) && (GETPOST('qty') < 0)) {
  731. setEventMessage($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), 'errors');
  732. $error = true;
  733. }
  734. if (empty($idprod) && GETPOST('type') < 0) {
  735. setEventMessage($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), 'errors');
  736. $error = true;
  737. }
  738. if ((empty($idprod) || GETPOST('usenewaddlineform')) && (!($price_ht >= 0) || $price_ht == '')) { // Unit price can be 0 but not ''
  739. setEventMessage($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), 'errors');
  740. $error++;
  741. }
  742. if (!GETPOST('qty') && GETPOST('qty') == '') {
  743. setEventMessage($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), 'errors');
  744. $error = true;
  745. }
  746. if (empty($idprod) && empty($product_desc)) {
  747. setEventMessage($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), 'errors');
  748. $error = true;
  749. }
  750. if (!$error && (GETPOST('qty') >= 0) && (!empty($product_desc) || !empty($idprod))) {
  751. $ret = $object->fetch($id);
  752. if ($ret < 0) {
  753. dol_print_error($db, $object->error);
  754. exit;
  755. }
  756. $ret = $object->fetch_thirdparty();
  757. // Clean parameters
  758. $predef = ((!empty($idprod) && $conf->global->MAIN_FEATURES_LEVEL < 2) ? '_predef' : '');
  759. $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'));
  760. $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'));
  761. $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT');
  762. // Define special_code for special lines
  763. $special_code = 0;
  764. //if (empty($_POST['qty'])) $special_code=3; // Options should not exists on invoices
  765. // Ecrase $pu par celui du produit
  766. // Ecrase $desc par celui du produit
  767. // Ecrase $txtva par celui du produit
  768. // Ecrase $base_price_type par celui du produit
  769. if (!empty($idprod)) {
  770. $prod = new Product($db);
  771. $prod->fetch($idprod);
  772. $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
  773. // Update if prices fields are defined
  774. if (GETPOST('usenewaddlineform')) {
  775. $pu_ht = price2num($price_ht, 'MU');
  776. $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
  777. $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
  778. $tva_tx = str_replace('*', '', $tva_tx);
  779. $desc = $product_desc;
  780. } else {
  781. $tva_tx = get_default_tva($mysoc, $object->client, $prod->id);
  782. $tva_npr = get_default_npr($mysoc, $object->client, $prod->id);
  783. // We define price for product
  784. if (!empty($conf->global->PRODUIT_MULTIPRICES) && !empty($object->client->price_level)) {
  785. $pu_ht = $prod->multiprices[$object->client->price_level];
  786. $pu_ttc = $prod->multiprices_ttc[$object->client->price_level];
  787. $price_min = $prod->multiprices_min[$object->client->price_level];
  788. $price_base_type = $prod->multiprices_base_type[$object->client->price_level];
  789. } else {
  790. $pu_ht = $prod->price;
  791. $pu_ttc = $prod->price_ttc;
  792. $price_min = $prod->price_min;
  793. $price_base_type = $prod->price_base_type;
  794. }
  795. // On reevalue prix selon taux tva car taux tva transaction peut etre different
  796. // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
  797. if ($tva_tx != $prod->tva_tx) {
  798. if ($price_base_type != 'HT') {
  799. $pu_ht = price2num($pu_ttc / (1 + ($tva_tx / 100)), 'MU');
  800. } else {
  801. $pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
  802. }
  803. }
  804. $desc = '';
  805. // Define output language
  806. if (!empty($conf->global->MAIN_MULTILANGS) && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
  807. $outputlangs = $langs;
  808. $newlang = '';
  809. if (empty($newlang) && GETPOST('lang_id'))
  810. $newlang = GETPOST('lang_id');
  811. if (empty($newlang))
  812. $newlang = $object->client->default_lang;
  813. if (!empty($newlang)) {
  814. $outputlangs = new Translate();
  815. $outputlangs->setDefaultLang($newlang);
  816. }
  817. $desc = (!empty($prod->multilangs[$outputlangs->defaultlang]["description"])) ? $prod->multilangs[$outputlangs->defaultlang]["description"] : $prod->description;
  818. } else {
  819. $desc = $prod->description;
  820. }
  821. $desc = dol_concatdesc($desc, $product_desc);
  822. }
  823. if (!empty($prod->customcode) || !empty($prod->country_code)) {
  824. $tmptxt = '(';
  825. if (!empty($prod->customcode))
  826. $tmptxt.=$langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
  827. if (!empty($prod->customcode) && !empty($prod->country_code))
  828. $tmptxt.=' - ';
  829. if (!empty($prod->country_code))
  830. $tmptxt.=$langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
  831. $tmptxt.=')';
  832. $desc.= (dol_textishtml($desc) ? "<br>\n" : "\n") . $tmptxt;
  833. }
  834. $type = $prod->type;
  835. }
  836. else {
  837. $pu_ht = price2num($price_ht, 'MU');
  838. $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
  839. $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
  840. $tva_tx = str_replace('*', '', $tva_tx);
  841. $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
  842. $desc = $product_desc;
  843. $type = GETPOST('type');
  844. }
  845. // Margin
  846. $fournprice = (GETPOST('fournprice') ? GETPOST('fournprice') : '');
  847. $buyingprice = (GETPOST('buying_price') ? GETPOST('buying_price') : '');
  848. // Local Taxes
  849. $localtax1_tx = get_localtax($tva_tx, 1, $object->client);
  850. $localtax2_tx = get_localtax($tva_tx, 2, $object->client);
  851. $info_bits = 0;
  852. if ($tva_npr)
  853. $info_bits |= 0x01;
  854. if (!empty($price_min) && (price2num($pu_ht) * (1 - price2num(GETPOST('remise_percent')) / 100) < price2num($price_min))) {
  855. $mesg = $langs->trans("CantBeLessThanMinPrice", price2num($price_min, 'MU') . $langs->getCurrencySymbol($conf->currency));
  856. setEventMessage($mesg, 'errors');
  857. } else {
  858. // Insert line
  859. $result = $object->addline(
  860. $id, $desc, $pu_ht, GETPOST('qty'), $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, GETPOST('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
  861. );
  862. if ($result > 0) {
  863. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
  864. // Define output language
  865. $outputlangs = $langs;
  866. $newlang = GETPOST('lang_id', 'alpha');
  867. if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang))
  868. $newlang = $object->client->default_lang;
  869. if (!empty($newlang)) {
  870. $outputlangs = new Translate();
  871. $outputlangs->setDefaultLang($newlang);
  872. }
  873. $ret = $object->fetch($id); // Reload to get new records
  874. facture_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  875. }
  876. unset($_POST['qty']);
  877. unset($_POST['type']);
  878. unset($_POST['idprod']);
  879. unset($_POST['remise_percent']);
  880. unset($_POST['price_ht']);
  881. unset($_POST['price_ttc']);
  882. unset($_POST['tva_tx']);
  883. unset($_POST['product_ref']);
  884. unset($_POST['product_label']);
  885. unset($_POST['product_desc']);
  886. unset($_POST['fournprice']);
  887. unset($_POST['buying_price']);
  888. // old method
  889. unset($_POST['np_desc']);
  890. unset($_POST['dp_desc']);
  891. } else {
  892. setEventMessage($object->error, 'errors');
  893. }
  894. $action = '';
  895. }
  896. }
  897. }
  898. else if ($action == 'updateligne' && $user->rights->facture->creer && $_POST['save'] == $langs->trans('Save')) {
  899. if (!$object->fetch($id) > 0)
  900. dol_print_error($db);
  901. $object->fetch_thirdparty();
  902. // Clean parameters
  903. $date_start = '';
  904. $date_end = '';
  905. $date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear'));
  906. $date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear'));
  907. $description = dol_htmlcleanlastbr(GETPOST('product_desc'));
  908. $pu_ht = GETPOST('price_ht');
  909. // Define info_bits
  910. $info_bits = 0;
  911. if (preg_match('/\*/', GETPOST('tva_tx')))
  912. $info_bits |= 0x01;
  913. // Define vat_rate
  914. $vat_rate = $_POST['tva_tx'];
  915. $vat_rate = str_replace('*', '', $vat_rate);
  916. $localtax1_rate = get_localtax($vat_rate, 1, $object->client);
  917. $localtax2_rate = get_localtax($vat_rate, 2, $object->client);
  918. // Add buying price
  919. $fournprice = (GETPOST('fournprice') ? GETPOST('fournprice') : '');
  920. $buyingprice = (GETPOST('buying_price') ? GETPOST('buying_price') : '');
  921. // Check minimum price
  922. $productid = GETPOST('productid', 'int');
  923. if (!empty($productid)) {
  924. $product = new Product($db);
  925. $product->fetch($productid);
  926. $type = $product->type;
  927. $price_min = $product->price_min;
  928. if (!empty($conf->global->PRODUIT_MULTIPRICES) && !empty($object->client->price_level))
  929. $price_min = $product->multiprices_min[$object->client->price_level];
  930. $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
  931. if ($price_min && (price2num($pu_ht) * (1 - price2num(GETPOST('remise_percent')) / 100) < price2num($price_min))) {
  932. setEventMessage($langs->trans("CantBeLessThanMinPrice", price2num($price_min, 'MU')) . $langs->getCurrencySymbol($conf->currency), 'errors');
  933. $error++;
  934. }
  935. } else {
  936. $type = GETPOST('type');
  937. $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
  938. // Check parameters
  939. if (GETPOST('type') < 0) {
  940. setEventMessage($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), 'errors');
  941. $error++;
  942. }
  943. }
  944. // Update line
  945. if (!$error) {
  946. $result = $object->updateline(
  947. GETPOST('lineid'), $description, $pu_ht, GETPOST('qty'), GETPOST('remise_percent'), $date_start, $date_end, $vat_rate, $localtax1_rate, $localtax2_rate, 'HT', $info_bits, $type, GETPOST('fk_parent_line'), 0, $fournprice, $buyingprice, $label
  948. );
  949. if ($result >= 0) {
  950. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
  951. // Define output language
  952. $outputlangs = $langs;
  953. $newlang = '';
  954. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id'))
  955. $newlang = GETPOST('lang_id');
  956. if ($conf->global->MAIN_MULTILANGS && empty($newlang))
  957. $newlang = $object->client->default_lang;
  958. if (!empty($newlang)) {
  959. $outputlangs = new Translate();
  960. $outputlangs->setDefaultLang($newlang);
  961. }
  962. $ret = $object->fetch($id); // Reload to get new records
  963. facture_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  964. }
  965. unset($_POST['qty']);
  966. unset($_POST['type']);
  967. unset($_POST['productid']);
  968. unset($_POST['remise_percent']);
  969. unset($_POST['price_ht']);
  970. unset($_POST['price_ttc']);
  971. unset($_POST['tva_tx']);
  972. unset($_POST['product_ref']);
  973. unset($_POST['product_label']);
  974. unset($_POST['product_desc']);
  975. unset($_POST['fournprice']);
  976. unset($_POST['buying_price']);
  977. } else {
  978. setEventMessage($object->error, 'errors');
  979. }
  980. }
  981. } else if ($action == 'updateligne' && $user->rights->facture->creer && $_POST['cancel'] == $langs->trans('Cancel')) {
  982. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id); // Pour reaffichage de la fiche en cours d'edition
  983. exit;
  984. }
  985. // Modify line position (up)
  986. else if ($action == 'up' && $user->rights->facture->creer) {
  987. $object->fetch($id);
  988. $object->fetch_thirdparty();
  989. $object->line_up($_GET['rowid']);
  990. // Define output language
  991. $outputlangs = $langs;
  992. $newlang = '';
  993. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($_REQUEST['lang_id']))
  994. $newlang = $_REQUEST['lang_id'];
  995. if ($conf->global->MAIN_MULTILANGS && empty($newlang))
  996. $newlang = $object->client->default_lang;
  997. if (!empty($newlang)) {
  998. $outputlangs = new Translate();
  999. $outputlangs->setDefaultLang($newlang);
  1000. }
  1001. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
  1002. facture_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  1003. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '#' . $_GET['rowid']);
  1004. exit;
  1005. }
  1006. // Modify line position (down)
  1007. else if ($action == 'down' && $user->rights->facture->creer) {
  1008. $object->fetch($id);
  1009. $object->fetch_thirdparty();
  1010. $object->line_down($_GET['rowid']);
  1011. // Define output language
  1012. $outputlangs = $langs;
  1013. $newlang = '';
  1014. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($_REQUEST['lang_id']))
  1015. $newlang = $_REQUEST['lang_id'];
  1016. if ($conf->global->MAIN_MULTILANGS && empty($newlang))
  1017. $newlang = $object->client->default_lang;
  1018. if (!empty($newlang)) {
  1019. $outputlangs = new Translate();
  1020. $outputlangs->setDefaultLang($newlang);
  1021. }
  1022. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
  1023. facture_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  1024. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '#' . $_GET['rowid']);
  1025. exit;
  1026. }
  1027. /*
  1028. * Add file in email form
  1029. */
  1030. if (GETPOST('addfile')) {
  1031. require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
  1032. // Set tmp user directory
  1033. $vardir = $conf->user->dir_output . "/" . $user->id;
  1034. $upload_dir_tmp = $vardir . '/temp';
  1035. dol_add_file_process($upload_dir_tmp, 0, 0);
  1036. $action = 'presend';
  1037. }
  1038. /*
  1039. * Remove file in email form
  1040. */
  1041. if (!empty($_POST['removedfile'])) {
  1042. require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
  1043. // Set tmp user directory
  1044. $vardir = $conf->user->dir_output . "/" . $user->id;
  1045. $upload_dir_tmp = $vardir . '/temp';
  1046. // TODO Delete only files that was uploaded from email form
  1047. dol_remove_file_process($_POST['removedfile'], 0);
  1048. $action = 'presend';
  1049. }
  1050. /*
  1051. * Send mail
  1052. */
  1053. if (($action == 'send' || $action == 'relance') && !$_POST['addfile'] && !$_POST['removedfile'] && !$_POST['cancel']) {
  1054. $langs->load('mails');
  1055. $actiontypecode = '';
  1056. $subject = '';
  1057. $actionmsg = '';
  1058. $actionmsg2 = '';
  1059. $result = $object->fetch($id);
  1060. $result = $object->fetch_thirdparty();
  1061. if ($result > 0) {
  1062. // $ref = dol_sanitizeFileName($object->ref);
  1063. // $file = $conf->facture->dir_output . '/' . $ref . '/' . $ref . '.pdf';
  1064. // if (is_readable($file))
  1065. // {
  1066. if ($_POST['sendto']) {
  1067. // Le destinataire a ete fourni via le champ libre
  1068. $sendto = $_POST['sendto'];
  1069. $sendtoid = 0;
  1070. } elseif ($_POST['receiver'] != '-1') {
  1071. // Recipient was provided from combo list
  1072. if ($_POST['receiver'] == 'thirdparty') { // Id of third party
  1073. $sendto = $object->client->email;
  1074. $sendtoid = 0;
  1075. } else { // Id du contact
  1076. $sendto = $object->client->contact_get_property($_POST['receiver'], 'email');
  1077. $sendtoid = $_POST['receiver'];
  1078. }
  1079. }
  1080. if (dol_strlen($sendto)) {
  1081. $langs->load("commercial");
  1082. $from = $_POST['fromname'] . ' <' . $_POST['frommail'] . '>';
  1083. $replyto = $_POST['replytoname'] . ' <' . $_POST['replytomail'] . '>';
  1084. $message = $_POST['message'];
  1085. $sendtocc = $_POST['sendtocc'];
  1086. $deliveryreceipt = $_POST['deliveryreceipt'];
  1087. if ($action == 'send') {
  1088. if (dol_strlen($_POST['subject']))
  1089. $subject = $_POST['subject'];
  1090. else
  1091. $subject = $langs->transnoentities('Bill') . ' ' . $object->ref;
  1092. $actiontypecode = 'AC_FAC';
  1093. $actionmsg = $langs->transnoentities('MailSentBy') . ' ' . $from . ' ' . $langs->transnoentities('To') . ' ' . $sendto . ".\n";
  1094. if ($message) {
  1095. $actionmsg.=$langs->transnoentities('MailTopic') . ": " . $subject . "\n";
  1096. $actionmsg.=$langs->transnoentities('TextUsedInTheMessageBody') . ":\n";
  1097. $actionmsg.=$message;
  1098. }
  1099. //$actionmsg2=$langs->transnoentities('Action'.$actiontypecode);
  1100. }
  1101. if ($action == 'relance') {
  1102. if (dol_strlen($_POST['subject']))
  1103. $subject = $_POST['subject'];
  1104. else
  1105. $subject = $langs->transnoentities('Relance facture ' . $object->ref);
  1106. $actiontypecode = 'AC_FAC';
  1107. $actionmsg = $langs->transnoentities('MailSentBy') . ' ' . $from . ' ' . $langs->transnoentities('To') . ' ' . $sendto . ".\n";
  1108. if ($message) {
  1109. $actionmsg.=$langs->transnoentities('MailTopic') . ": " . $subject . "\n";
  1110. $actionmsg.=$langs->transnoentities('TextUsedInTheMessageBody') . ":\n";
  1111. $actionmsg.=$message;
  1112. }
  1113. //$actionmsg2=$langs->transnoentities('Action'.$actiontypecode);
  1114. }
  1115. // Create form object
  1116. include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
  1117. $formmail = new FormMail($db);
  1118. $attachedfiles = $formmail->get_attached_files();
  1119. $filepath = $attachedfiles['paths'];
  1120. $filename = $attachedfiles['names'];
  1121. $mimetype = $attachedfiles['mimes'];
  1122. // Send mail
  1123. require_once DOL_DOCUMENT_ROOT . '/core/class/CMailFile.class.php';
  1124. $mailfile = new CMailFile($subject, $sendto, $from, $message, $filepath, $mimetype, $filename, $sendtocc, '', $deliveryreceipt, -1);
  1125. if ($mailfile->error) {
  1126. $mesgs[] = '<div class="error">' . $mailfile->error . '</div>';
  1127. } else {
  1128. $result = $mailfile->sendfile();
  1129. if ($result) {
  1130. $error = 0;
  1131. // Initialisation donnees
  1132. $object->sendtoid = $sendtoid;
  1133. $object->actiontypecode = $actiontypecode;
  1134. $object->actionmsg = $actionmsg; // Long text
  1135. $object->actionmsg2 = $actionmsg2; // Short text
  1136. $object->fk_element = $object->id;
  1137. $object->elementtype = $object->element;
  1138. // Appel des triggers
  1139. include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  1140. $interface = new Interfaces($db);
  1141. $result = $interface->run_triggers('BILL_SENTBYMAIL', $object, $user, $langs, $conf);
  1142. if ($result < 0) {
  1143. $error++;
  1144. $this->errors = $interface->errors;
  1145. }
  1146. // Fin appel triggers
  1147. if ($error) {
  1148. dol_print_error($db);
  1149. } else {
  1150. // Redirect here
  1151. // This avoid sending mail twice if going out and then back to page
  1152. $mesg = $langs->trans('MailSuccessfulySent', $mailfile->getValidAddress($from, 2), $mailfile->getValidAddress($sendto, 2));
  1153. setEventMessage($mesg);
  1154. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id);
  1155. exit;
  1156. }
  1157. } else {
  1158. $langs->load("other");
  1159. $mesg = '<div class="error">';
  1160. if ($mailfile->error) {
  1161. $mesg.=$langs->trans('ErrorFailedToSendMail', $from, $sendto);
  1162. $mesg.='<br>' . $mailfile->error;
  1163. } else {
  1164. $mesg.='No mail sent. Feature is disabled by option MAIN_DISABLE_ALL_MAILS';
  1165. }
  1166. $mesg.='</div>';
  1167. $mesgs[] = $mesg;
  1168. }
  1169. }
  1170. /* }
  1171. else
  1172. {
  1173. $langs->load("other");
  1174. $mesgs[]='<div class="error">'.$langs->trans('ErrorMailRecipientIsEmpty').'</div>';
  1175. dol_syslog('Recipient email is empty');
  1176. } */
  1177. } else {
  1178. $langs->load("errors");
  1179. $mesgs[] = '<div class="error">' . $langs->trans('ErrorCantReadFile', $file) . '</div>';
  1180. dol_syslog('Failed to read file: ' . $file);
  1181. }
  1182. } else {
  1183. $langs->load("other");
  1184. $mesgs[] = '<div class="error">' . $langs->trans('ErrorFailedToReadEntity', $langs->trans("Invoice")) . '</div>';
  1185. dol_syslog('Impossible de lire les donnees de la facture. Le fichier facture n\'a peut-etre pas ete genere.');
  1186. }
  1187. $action = 'presend';
  1188. }
  1189. /*
  1190. * Generate document
  1191. */ else if ($action == 'builddoc') { // En get ou en post
  1192. $object->fetch($id);
  1193. $object->fetch_thirdparty();
  1194. if (GETPOST('model')) {
  1195. $object->setDocModel($user, GETPOST('model'));
  1196. }
  1197. // Define output language
  1198. $outputlangs = $langs;
  1199. $newlang = '';
  1200. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id'))
  1201. $newlang = GETPOST('lang_id');
  1202. if ($conf->global->MAIN_MULTILANGS && empty($newlang))
  1203. $newlang = $object->client->default_lang;
  1204. if (!empty($newlang)) {
  1205. $outputlangs = new Translate();
  1206. $outputlangs->setDefaultLang($newlang);
  1207. }
  1208. $result = facture_pdf_create($db, $object, $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  1209. if ($result <= 0) {
  1210. dol_print_error($db, $result);
  1211. exit;
  1212. } else {
  1213. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . (empty($conf->global->MAIN_JUMP_TAG) ? '' : '#builddoc'));
  1214. exit;
  1215. }
  1216. }
  1217. // Remove file in doc form
  1218. else if ($action == 'remove_file') {
  1219. if ($object->fetch($id)) {
  1220. require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
  1221. $object->fetch_thirdparty();
  1222. $langs->load("other");
  1223. $upload_dir = $conf->facture->dir_output;
  1224. $file = $upload_dir . '/' . GETPOST('file');
  1225. $ret = dol_delete_file($file, 0, 0, 0, $object);
  1226. if ($ret)
  1227. setEventMessage($langs->trans("FileWasRemoved", GETPOST('urlfile')));
  1228. else
  1229. setEventMessage($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), 'errors');
  1230. $action = '';
  1231. }
  1232. }
  1233. if (!empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $user->rights->facture->creer) {
  1234. if ($action == 'addcontact') {
  1235. $result = $object->fetch($id);
  1236. if ($result > 0 && $id > 0) {
  1237. $contactid = (GETPOST('userid') ? GETPOST('userid') : GETPOST('contactid'));
  1238. $result = $result = $object->add_contact($contactid, $_POST["type"], $_POST["source"]);
  1239. }
  1240. if ($result >= 0) {
  1241. header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
  1242. exit;
  1243. } else {
  1244. if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
  1245. $langs->load("errors");
  1246. $mesgs[] = '<div class="error">' . $langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType") . '</div>';
  1247. } else {
  1248. $mesgs[] = '<div class="error">' . $object->error . '</div>';
  1249. }
  1250. }
  1251. }
  1252. // bascule du statut d'un contact
  1253. else if ($action == 'swapstatut') {
  1254. if ($object->fetch($id)) {
  1255. $result = $object->swapContactStatus(GETPOST('ligne'));
  1256. } else {
  1257. dol_print_error($db);
  1258. }
  1259. }
  1260. // Efface un contact
  1261. else if ($action == 'deletecontact') {
  1262. $object->fetch($id);
  1263. $result = $object->delete_contact($lineid);
  1264. if ($result >= 0) {
  1265. header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
  1266. exit;
  1267. } else {
  1268. dol_print_error($db);
  1269. }
  1270. }
  1271. }
  1272. /*
  1273. * View
  1274. */
  1275. llxHeader('', $langs->trans('Bill'), 'EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes');
  1276. $form = new Form($db);
  1277. $htmlother = new FormOther($db);
  1278. $formfile = new FormFile($db);
  1279. $bankaccountstatic = new Account($db);
  1280. $now = dol_now();
  1281. /* * *******************************************************************
  1282. *
  1283. * Mode creation
  1284. *
  1285. * ******************************************************************** */
  1286. if ($action == 'create') {
  1287. $facturestatic = new Facture($db);
  1288. print_fiche_titre($langs->trans('NewBill'));
  1289. $soc = new Societe($db);
  1290. if ($socid)
  1291. $res = $soc->fetch($socid);
  1292. if (!empty($origin) && !empty($originid)) {
  1293. // Parse element/subelement (ex: project_task)
  1294. $element = $subelement = $origin;
  1295. if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
  1296. $element = $regs[1];
  1297. $subelement = $regs[2];
  1298. }
  1299. if ($element == 'project') {
  1300. $projectid = $originid;
  1301. } else {
  1302. // For compatibility
  1303. if ($element == 'order' || $element == 'commande') {
  1304. $element = $subelement = 'commande';
  1305. }
  1306. if ($element == 'propal') {
  1307. $element = 'comm/propal';
  1308. $subelement = 'propal';
  1309. }
  1310. if ($element == 'contract') {
  1311. $element = $subelement = 'contrat';
  1312. }
  1313. if ($element == 'shipping') {
  1314. $element = $subelement = 'expedition';
  1315. }
  1316. dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
  1317. $classname = ucfirst($subelement);
  1318. $objectsrc = new $classname($db);
  1319. $objectsrc->fetch($originid);
  1320. if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines'))
  1321. $objectsrc->fetch_lines();
  1322. $objectsrc->fetch_thirdparty();
  1323. $projectid = (!empty($objectsrc->fk_project) ? $objectsrc->fk_project : '');
  1324. $ref_client = (!empty($objectsrc->ref_client) ? $objectsrc->ref_client : '');
  1325. $ref_int = (!empty($objectsrc->ref_int) ? $objectsrc->ref_int : '');
  1326. $soc = $objectsrc->client;
  1327. $cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_id) ? $soc->cond_reglement_id : 1));
  1328. $mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0));
  1329. $remise_percent = (!empty($objectsrc->remise_percent) ? $objectsrc->remise_percent : (!empty($soc->remise_percent) ? $soc->remise_percent : 0));
  1330. $remise_absolue = (!empty($objectsrc->remise_absolue) ? $objectsrc->remise_absolue : (!empty($soc->remise_absolue) ? $soc->remise_absolue : 0));
  1331. $dateinvoice = empty($conf->global->MAIN_AUTOFILL_DATE) ? -1 : 0;
  1332. }
  1333. }
  1334. else {
  1335. $cond_reglement_id = $soc->cond_reglement_id;
  1336. $mode_reglement_id = $soc->mode_reglement_id;
  1337. $remise_percent = $soc->remise_percent;
  1338. $remise_absolue = 0;
  1339. $dateinvoice = empty($conf->global->MAIN_AUTOFILL_DATE) ? -1 : 0;
  1340. }
  1341. $absolute_discount = $soc->getAvailableDiscounts();
  1342. print '<form name="add" action="' . $_SERVER["PHP_SELF"] . '" method="POST">';
  1343. print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
  1344. print '<input type="hidden" name="action" value="add">';
  1345. // print '<input type="hidden" name="socid" value="'.$soc->id.'">' ."\n";
  1346. print '<input name="facnumber" type="hidden" value="provisoire">';
  1347. print '<input name="ref_client" type="hidden" value="' . $ref_client . '">';
  1348. print '<input name="ref_int" type="hidden" value="' . $ref_int . '">';
  1349. print '<input type="hidden" name="origin" value="' . $origin . '">';
  1350. print '<input type="hidden" name="originid" value="' . $originid . '">';
  1351. print '<table class="border" width="100%">';
  1352. // Ref
  1353. print '<tr><td class="fieldrequired">' . $langs->trans('Ref') . '</td><td colspan="2">' . $langs->trans('Draft') . '</td></tr>';
  1354. // Factures predefinies
  1355. // if (empty($origin) && empty($originid))
  1356. // {
  1357. // $sql = 'SELECT r.rowid, r.titre, r.total_ttc';
  1358. // $sql.= ' FROM '.MAIN_DB_PREFIX.'facture_rec as r';
  1359. // $sql.= ' WHERE r.fk_soc = '.$soc->id;
  1360. //
  1361. // $resql=$db->query($sql);
  1362. // if ($resql)
  1363. // {
  1364. // $num = $db->num_rows($resql);
  1365. // $i = 0;
  1366. //
  1367. // if ($num > 0)
  1368. // {
  1369. // print '<tr><td>'.$langs->trans('CreateFromRepeatableInvoice').'</td><td>';
  1370. // print '<select class="flat" name="fac_rec">';
  1371. // print '<option value="0" selected="selected"></option>';
  1372. // while ($i < $num)
  1373. // {
  1374. // $objp = $db->fetch_object($resql);
  1375. // print '<option value="'.$objp->rowid.'"';
  1376. // if (GETPOST('fac_rec') == $objp->rowid) print ' selected="selected"';
  1377. // print '>'.$objp->titre.' ('.price($objp->total_ttc).' '.$langs->trans("TTC").')</option>';
  1378. // $i++;
  1379. // }
  1380. // print '</select></td></tr>';
  1381. // }
  1382. // $db->free($resql);
  1383. // }
  1384. // else
  1385. // {
  1386. // dol_print_error($db);
  1387. // }
  1388. // }
  1389. // Tiers
  1390. print '<tr><td class="fieldrequired">' . $langs->trans('Customer') . '</td><td colspan="2">';
  1391. print $form->select_company($object->socid, "socid");
  1392. print '</td>';
  1393. print '</tr>' . "\n";
  1394. // Type de facture
  1395. $facids=$facturestatic->list_replacable_invoices($soc->id);
  1396. if ($facids < 0)
  1397. {
  1398. dol_print_error($db,$facturestatic);
  1399. exit;
  1400. }
  1401. $options="";
  1402. foreach ($facids as $facparam)
  1403. {
  1404. $options.='<option value="'.$facparam['id'].'"';
  1405. if ($facparam['id'] == $_POST['fac_replacement']) $options.=' selected="selected"';
  1406. $options.='>'.$facparam['ref'];
  1407. //$options.=' ('.$facturestatic->LibStatut(0,$facparam['status']).')';
  1408. $options.='</option>';
  1409. }
  1410. $facids=$facturestatic->list_qualified_avoir_invoices($soc->id);
  1411. if ($facids < 0)
  1412. {
  1413. dol_print_error($db,$facturestatic);
  1414. exit;
  1415. }
  1416. $optionsav="";
  1417. $newinvoice_static=new Facture($db);
  1418. foreach ($facids as $key => $valarray)
  1419. {
  1420. $newinvoice_static->id=$key;
  1421. $newinvoice_static->ref=$valarray['ref'];
  1422. $newinvoice_static->statut=$valarray['status'];
  1423. $newinvoice_static->type=$valarray['type'];
  1424. $newinvoice_static->paye=$valarray['paye'];
  1425. $optionsav.='<option value="'.$key.'"';
  1426. if ($key == $_POST['fac_avoir']) $optionsav.=' selected="selected"';
  1427. $optionsav.='>';
  1428. $optionsav.=$newinvoice_static->ref;
  1429. //$optionsav.=' ('.$newinvoice_static->getLibStatut(1,$valarray['paymentornot']).')';
  1430. $optionsav.='</option>';
  1431. }
  1432. print '<tr><td valign="top" class="fieldrequired">' . $langs->trans('Type') . '</td><td colspan="2">';
  1433. print '<table class="nobordernopadding">' . "\n";
  1434. // Standard invoice
  1435. print '<tr height="18"><td width="16px" valign="middle">';
  1436. print '<input type="radio" name="type" value="INVOICE_STANDARD"' . (GETPOST('type') == "INVOICE_STANDARD" ? ' checked="checked"' : '') . '>';
  1437. print '</td><td valign="middle">';
  1438. $desc = $form->textwithpicto($langs->trans("InvoiceStandardAsk"), $langs->transnoentities("InvoiceStandardDesc"), 1);
  1439. print $desc;
  1440. print '</td></tr>' . "\n";
  1441. // Deposit
  1442. print '<tr height="18"><td width="16px" valign="middle">';
  1443. print '<input type="radio" name="type" value="INVOICE_DEPOSIT"' . (GETPOST('type') == "INVOICE_DEPOSIT" ? ' checked="checked"' : '') . '>';
  1444. print '</td><td valign="middle">';
  1445. $desc = $form->textwithpicto($langs->trans("InvoiceDeposit"), $langs->transnoentities("InvoiceDepositDesc"), 1);
  1446. print $desc;
  1447. print '</td></tr>' . "\n";
  1448. // Proforma
  1449. if (!empty($conf->global->FACTURE_USE_PROFORMAT)) {
  1450. print '<tr height="18"><td width="16px" valign="middle">';
  1451. print '<input type="radio" name="type" value="4"' . (GETPOST('type') == 4 ? ' checked="checked"' : '') . '>';
  1452. print '</td><td valign="middle">';
  1453. $desc = $form->textwithpicto($langs->trans("InvoiceProForma"), $langs->transnoentities("InvoiceProFormaDesc"), 1);
  1454. print $desc;
  1455. print '</td></tr>' . "\n";
  1456. }
  1457. // Replacement
  1458. print '<tr height="18"><td valign="middle">';
  1459. print '<input type="radio" name="type" value="1"' . (GETPOST('type') == 1 ? ' checked="checked"' : '');
  1460. if (!$options)
  1461. print ' disabled="disabled"';
  1462. print '>';
  1463. print '</td><td valign="middle">';
  1464. $text = $langs->trans("InvoiceReplacementAsk") . ' ';
  1465. $text.='<select class="flat" name="fac_replacement" id="fac_replacement"';
  1466. if (!$options)
  1467. $text.=' disabled="disabled"';
  1468. $text.='>';
  1469. if ($options) {
  1470. $text.='<option value="-1"></option>';
  1471. $text.=$options;
  1472. } else {
  1473. $text.='<option value="-1">' . $langs->trans("NoReplacableInvoice") . '</option>';
  1474. }
  1475. $text.='</select>';
  1476. $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceReplacementDesc"), 1);
  1477. print $desc;
  1478. print '</td></tr>' . "\n";
  1479. // Credit note
  1480. print '<tr height="18"><td valign="middle">';
  1481. print '<input type="radio" name="type" value="2"' . (GETPOST('type') == 2 ? ' checked=true' : '');
  1482. if (!$optionsav)
  1483. print ' disabled="disabled"';
  1484. print '>';
  1485. print '</td><td valign="middle">';
  1486. $text = $langs->transnoentities("InvoiceAvoirAsk") . ' ';
  1487. // $text.='<input type="text" value="">';
  1488. $text.='<select class="flat" name="fac_avoir" id="fac_avoir"';
  1489. if (!$optionsav)
  1490. $text.=' disabled="disabled"';
  1491. $text.='>';
  1492. if ($optionsav) {
  1493. $text.='<option value="-1"></option>';
  1494. $text.=$optionsav;
  1495. } else {
  1496. $text.='<option value="-1">' . $langs->trans("NoInvoiceToCorrect") . '</option>';
  1497. }
  1498. $text.='</select>';
  1499. $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceAvoirDesc"), 1);
  1500. print $desc;
  1501. print '</td></tr>' . "\n";
  1502. print '</table>';
  1503. print '</td></tr>';
  1504. // Discounts for third party
  1505. print '<tr><td>' . $langs->trans('Discounts') . '</td><td colspan="2">';
  1506. if ($soc->remise_client)
  1507. print $langs->trans("CompanyHasRelativeDiscount", '<a href="' . DOL_URL_ROOT . '/comm/remise.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"] . '?socid=' . $soc->id . '&action=' . $action . '&origin=' . GETPOST('origin') . '&originid=' . GETPOST('originid')) . '">' . $soc->remise_client . '</a>');
  1508. else
  1509. print $langs->trans("CompanyHasNoRelativeDiscount");
  1510. print ' <a href="' . DOL_URL_ROOT . '/comm/remise.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"] . '?socid=' . $soc->id . '&action=' . $action . '&origin=' . GETPOST('origin') . '&originid=' . GETPOST('originid')) . '">(' . $langs->trans("EditRelativeDiscount") . ')</a>';
  1511. print '. ';
  1512. print '<br>';
  1513. if ($absolute_discount)
  1514. print $langs->trans("CompanyHasAbsoluteDiscount", '<a href="' . DOL_URL_ROOT . '/comm/remx.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"] . '?socid=' . $soc->id . '&action=' . $action . '&origin=' . GETPOST('origin') . '&originid=' . GETPOST('originid')) . '">' . price($absolute_discount) . '</a>', $langs->trans("Currency" . $conf->currency));
  1515. else
  1516. print $langs->trans("CompanyHasNoAbsoluteDiscount");
  1517. print ' <a href="' . DOL_URL_ROOT . '/comm/remx.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"] . '?socid=' . $soc->id . '&action=' . $action . '&origin=' . GETPOST('origin') . '&originid=' . GETPOST('originid')) . '">(' . $langs->trans("EditGlobalDiscounts") . ')</a>';
  1518. print '.';
  1519. print '</td></tr>';
  1520. // Date invoice
  1521. print '<tr><td class="fieldrequired">' . $langs->trans('Date') . '</td><td colspan="2">';
  1522. $form->select_date($dateinvoice, '', '', '', '', "add", 1, 1);
  1523. print '</td></tr>';
  1524. // Payment term
  1525. print '<tr><td nowrap>' . $langs->trans('PaymentConditionsShort') . '</td><td colspan="2">';
  1526. // $form->select_conditions_paiements(isset($_POST['cond_reglement_id'])?$_POST['cond_reglement_id']:$cond_reglement_id,'cond_reglement_id');
  1527. print $object->select_fk_extrafields('mode_reglement_code', 'mode_reglement_code', $object->mode_reglement_code);
  1528. print '</td></tr>';
  1529. // Payment mode
  1530. print '<tr><td>' . $langs->trans('PaymentMode') . '</td><td colspan="2">';
  1531. // $form->select_types_paiements(isset($_POST['mode_reglement_id'])?$_POST['mode_reglement_id']:$mode_reglement_id,'mode_reglement_id');
  1532. print $object->select_fk_extrafields('cond_reglement_code', 'cond_reglement_code', $object->cond_reglement_code);
  1533. print '</td></tr>';
  1534. // Project
  1535. if (!empty($conf->projet->enabled)) {
  1536. $langs->load('projects');
  1537. print '<tr><td>' . $langs->trans('Project') . '</td><td colspan="2">';
  1538. select_projects($soc->id, $projectid, 'projectid');
  1539. print '</td></tr>';
  1540. }
  1541. // Other attributes
  1542. $parameters = array('objectsrc' => $objectsrc, 'colspan' => ' colspan="3"');
  1543. $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  1544. if (empty($reshook) && !empty($extrafields->attribute_label)) {
  1545. foreach ($extrafields->attribute_label as $key => $label) {
  1546. $value = (isset($_POST["options_" . $key]) ? $_POST["options_" . $key] : $object->array_options["options_" . $key]);
  1547. print '<tr><td>' . $label . '</td><td colspan="3">';
  1548. print $extrafields->showInputField($key, $value);
  1549. print '</td></tr>' . "\n";
  1550. }
  1551. }
  1552. // Modele PDF
  1553. print '<tr><td>' . $langs->trans('Model') . '</td>';
  1554. print '<td>';
  1555. include_once DOL_DOCUMENT_ROOT . '/facture/core/modules/facture/modules_facture.php';
  1556. $liste = ModelePDFFactures::liste_modeles($db);
  1557. print $form->selectarray('model', $liste, $conf->global->FACTURE_ADDON_PDF);
  1558. print "</td></tr>";
  1559. // Public note
  1560. print '<tr>';
  1561. print '<td class="border" valign="top">' . $langs->trans('NotePublic') . '</td>';
  1562. print '<td valign="top" colspan="2">';
  1563. print '<textarea name="note_public" wrap="soft" cols="70" rows="' . ROWS_3 . '">';
  1564. if (is_object($objectsrc)) { // Take value from source object
  1565. print $objectsrc->note_public;
  1566. }
  1567. print '</textarea></td></tr>';
  1568. // Private note
  1569. if (empty($user->societe_id)) {
  1570. print '<tr>';
  1571. print '<td class="border" valign="top">' . $langs->trans('NotePrivate') . '</td>';
  1572. print '<td valign="top" colspan="2">';
  1573. print '<textarea name="note" wrap="soft" cols="70" rows="' . ROWS_3 . '">';
  1574. if (!empty($origin) && !empty($originid) && is_object($objectsrc)) { // Take value from source object
  1575. print $objectsrc->note;
  1576. }
  1577. print '</textarea></td></tr>';
  1578. }
  1579. if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
  1580. // TODO for compatibility
  1581. if ($origin == 'contrat') {
  1582. // Calcul contrat->price (HT), contrat->total (TTC), contrat->tva
  1583. $objectsrc->remise_absolue = $remise_absolue;
  1584. $objectsrc->remise_percent = $remise_percent;
  1585. $objectsrc->update_price(1, -1, 1);
  1586. }
  1587. print "\n<!-- " . $classname . " info -->";
  1588. print "\n";
  1589. print '<input type="hidden" name="amount" value="' . $objectsrc->total_ht . '">' . "\n";
  1590. print '<input type="hidden" name="total" value="' . $objectsrc->total_ttc . '">' . "\n";
  1591. print '<input type="hidden" name="tva" value="' . $objectsrc->total_tva . '">' . "\n";
  1592. print '<input type="hidden" name="origin" value="' . $objectsrc->element . '">';
  1593. print '<input type="hidden" name="originid" value="' . $objectsrc->id . '">';
  1594. $newclassname = $classname;
  1595. if ($newclassname == 'Propal')
  1596. $newclassname = 'CommercialProposal';
  1597. print '<tr><td>' . $langs->trans($newclassname) . '</td><td colspan="2">' . $objectsrc->getNomUrl(1) . '</td></tr>';
  1598. print '<tr><td>' . $langs->trans('TotalHT') . '</td><td colspan="2">' . price($objectsrc->total_ht) . '</td></tr>';
  1599. print '<tr><td>' . $langs->trans('TotalVAT') . '</td><td colspan="2">' . price($objectsrc->total_tva) . "</td></tr>";
  1600. if ($mysoc->pays_code == 'ES') {
  1601. if ($mysoc->localtax1_assuj == "1") { //Localtax1 RE
  1602. print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->pays_code) . '</td><td colspan="2">' . price($objectsrc->total_localtax1) . "</td></tr>";
  1603. }
  1604. if ($mysoc->localtax2_assuj == "1") { //Localtax2 IRPF
  1605. print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->pays_code) . '</td><td colspan="2">' . price($objectsrc->total_localtax2) . "</td></tr>";
  1606. }
  1607. }
  1608. print '<tr><td>' . $langs->trans('TotalTTC') . '</td><td colspan="2">' . price($objectsrc->total_ttc) . "</td></tr>";
  1609. } else {
  1610. // Show deprecated optional form to add product line here
  1611. if (!empty($conf->global->PRODUCT_SHOW_WHEN_CREATE)) {
  1612. print '<tr><td colspan="3">';
  1613. // Zone de choix des produits predefinis a la creation
  1614. print '<table class="noborder" width="100%">';
  1615. print '<tr>';
  1616. print '<td>' . $langs->trans('ProductsAndServices') . '</td>';
  1617. print '<td>' . $langs->trans('Qty') . '</td>';
  1618. print '<td>' . $langs->trans('ReductionShort') . '</td>';
  1619. print '<td> &nbsp; &nbsp; </td>';
  1620. if (!empty($conf->service->enabled)) {
  1621. print '<td>' . $langs->trans('ServiceLimitedDuration') . '</td>';
  1622. }
  1623. print '</tr>';
  1624. for ($i = 1; $i <= $NBLINES; $i++) {
  1625. print '<tr>';
  1626. print '<td>';
  1627. // multiprix
  1628. if (!empty($conf->global->PRODUIT_MULTIPRICES))
  1629. $form->select_produits('', 'idprod' . $i, '', $conf->product->limit_size, $soc->price_level);
  1630. else
  1631. $form->select_produits('', 'idprod' . $i, '', $conf->product->limit_size);
  1632. print '</td>';
  1633. print '<td><input type="text" size="2" name="qty' . $i . '" value="1"></td>';
  1634. print '<td nowrap="nowrap"><input type="text" size="1" name="remise_percent' . $i . '" value="' . $soc->remise_client . '">%</td>';
  1635. print '<td>&nbsp;</td>';
  1636. // Si le module service est actif, on propose des dates de debut et fin a la ligne
  1637. if (!empty($conf->service->enabled)) {
  1638. print '<td nowrap="nowrap">';
  1639. print '<table class="nobordernopadding"><tr class="nocellnopadd">';
  1640. print '<td class="nobordernopadding" nowrap="nowrap">';
  1641. print $langs->trans('From') . ' ';
  1642. print '</td><td class="nobordernopadding" nowrap="nowrap">';
  1643. print $form->select_date('', 'date_start' . $i, $usehm, $usehm, 1, "add");
  1644. print '</td></tr>';
  1645. print '<td class="nobordernopadding" nowrap="nowrap">';
  1646. print $langs->trans('to') . ' ';
  1647. print '</td><td class="nobordernopadding" nowrap="nowrap">';
  1648. print $form->select_date('', 'date_end' . $i, $usehm, $usehm, 1, "add");
  1649. print '</td></tr></table>';
  1650. print '</td>';
  1651. }
  1652. print "</tr>\n";
  1653. }
  1654. print '</table>';
  1655. print '</td></tr>';
  1656. }
  1657. }
  1658. print "</table>\n";
  1659. // Button "Create Draft"
  1660. print '<br><center><input type="submit" class="button" name="bouton" value="' . $langs->trans('CreateDraft') . '"></center>';
  1661. print "</form>\n";
  1662. // Show origin lines
  1663. if (!empty($origin) && !empty($originid) && is_object($objectsrc)) {
  1664. print '<br>';
  1665. $title = $langs->trans('ProductsAndServices');
  1666. print_titre($title);
  1667. print '<table class="noborder" width="100%">';
  1668. $objectsrc->printOriginLinesList();
  1669. print '</table>';
  1670. }
  1671. } else if (!empty($id) || !empty($ref)) {
  1672. /*
  1673. * Show object in view mode
  1674. */
  1675. $result = $object->fetch($id, $ref);
  1676. if ($result > 0) {
  1677. if ($user->societe_id > 0 && $user->societe_id != $object->socid)
  1678. accessforbidden('', 0);
  1679. $result = $object->fetch_thirdparty();
  1680. $soc = new Societe($db);
  1681. $soc->fetch($object->socid);
  1682. $totalpaye = 0;//$object->getSommePaiement();
  1683. $totalcreditnotes = 0;//$object->getSumCreditNotesUsed();
  1684. $totaldeposits = 0;//$object->getSumDepositsUsed();
  1685. //print "totalpaye=".$totalpaye." totalcreditnotes=".$totalcreditnotes." totaldeposts=".$totaldeposits;
  1686. // We can also use bcadd to avoid pb with floating points
  1687. // For example print 239.2 - 229.3 - 9.9; does not return 0.
  1688. //$resteapayer=bcadd($object->total_ttc,$totalpaye,$conf->global->MAIN_MAX_DECIMALS_TOT);
  1689. //$resteapayer=bcadd($resteapayer,$totalavoir,$conf->global->MAIN_MAX_DECIMALS_TOT);
  1690. $resteapayer = price2num($object->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits, 'MT');
  1691. if ($object->paye)
  1692. $resteapayer = 0;
  1693. $resteapayeraffiche = $resteapayer;
  1694. if (!empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) {
  1695. $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
  1696. $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
  1697. } else {
  1698. $filterabsolutediscount = "fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND description='(DEPOSIT)')";
  1699. $filtercreditnote = "fk_facture_source IS NOT NULL AND description <> '(DEPOSIT)'";
  1700. }
  1701. $absolute_discount = $soc->getAvailableDiscounts('', $filterabsolutediscount);
  1702. $absolute_creditnote = $soc->getAvailableDiscounts('', $filtercreditnote);
  1703. $absolute_discount = price2num($absolute_discount, 'MT');
  1704. $absolute_creditnote = price2num($absolute_creditnote, 'MT');
  1705. $author = new User($db);
  1706. if ($object->user_author) {
  1707. $author->fetch($object->user_author);
  1708. }
  1709. $objectidnext = $object->getIdReplacingInvoice();
  1710. $head = facture_prepare_head($object);
  1711. dol_fiche_head($head, 'compta', $langs->trans('InvoiceCustomer'), 0, 'bill');
  1712. $formconfirm = '';
  1713. // Confirmation de la conversion de l'avoir en reduc
  1714. if ($action == 'converttoreduc') {
  1715. $text = $langs->trans('ConfirmConvertToReduc');
  1716. $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $langs->trans('ConvertToReduc'), $text, 'confirm_converttoreduc', '', "yes", 2);
  1717. }
  1718. // Confirmation to delete invoice
  1719. if ($action == 'delete') {
  1720. $text = $langs->trans('ConfirmDeleteBill');
  1721. $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $langs->trans('DeleteBill'), $text, 'confirm_delete', '', 0, 1);
  1722. }
  1723. // Confirmation de la validation
  1724. if ($action == 'valid') {
  1725. // on verifie si l'objet est en numerotation provisoire
  1726. $objectref = substr($object->ref, 1, 4);
  1727. if ($objectref == 'PROV') {
  1728. $savdate = $object->date;
  1729. if (!empty($conf->global->FAC_FORCE_DATE_VALIDATION)) {
  1730. $object->date = dol_now();
  1731. $object->date_lim_reglement = $object->calculate_date_lim_reglement();
  1732. }
  1733. $numref = $object->getNextNumRef($soc);
  1734. //$object->date=$savdate;
  1735. } else {
  1736. $numref = $object->ref;
  1737. }
  1738. $text = $langs->trans('ConfirmValidateBill', $numref);
  1739. if (!empty($conf->notification->enabled)) {
  1740. require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
  1741. $notify = new Notify($db);
  1742. $text.='<br>';
  1743. $text.=$notify->confirmMessage('NOTIFY_VAL_FAC', $object->socid);
  1744. }
  1745. $formquestion = array();
  1746. if ($object->type != 3 && !empty($conf->global->STOCK_CALCULATE_ON_BILL) && $object->hasProductsOrServices(1)) {
  1747. $langs->load("stocks");
  1748. require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php';
  1749. $formproduct = new FormProduct($db);
  1750. $label = $object->type == 2 ? $langs->trans("SelectWarehouseForStockIncrease") : $langs->trans("SelectWarehouseForStockDecrease");
  1751. $formquestion = array(
  1752. //'text' => $langs->trans("ConfirmClone"),
  1753. //array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
  1754. //array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
  1755. array('type' => 'other', 'name' => 'idwarehouse', 'label' => $label, 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse'), 'idwarehouse', '', 1)));
  1756. }
  1757. if ($object->type != 2 && $object->total_ttc < 0) { // Can happen only if $conf->global->FACTURE_ENABLE_NEGATIVE is on
  1758. $text.='<br>' . img_warning() . ' ' . $langs->trans("ErrorInvoiceOfThisTypeMustBePositive");
  1759. }
  1760. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('ValidateBill'), $text, 'confirm_valid', $formquestion, (($object->type != 2 && $object->total_ttc < 0) ? "no" : "yes"), ($conf->notification->enabled ? 0 : 2));
  1761. }
  1762. // Confirm back to draft status
  1763. if ($action == 'modif') {
  1764. $text = $langs->trans('ConfirmUnvalidateBill', $object->ref);
  1765. $formquestion = array();
  1766. if ($object->type != 3 && !empty($conf->global->STOCK_CALCULATE_ON_BILL) && $object->hasProductsOrServices(1)) {
  1767. $langs->load("stocks");
  1768. require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php';
  1769. $formproduct = new FormProduct($db);
  1770. $label = $object->type == 2 ? $langs->trans("SelectWarehouseForStockDecrease") : $langs->trans("SelectWarehouseForStockIncrease");
  1771. $formquestion = array(
  1772. //'text' => $langs->trans("ConfirmClone"),
  1773. //array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
  1774. //array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
  1775. array('type' => 'other', 'name' => 'idwarehouse', 'label' => $label, 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse'), 'idwarehouse', '', 1)));
  1776. }
  1777. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('UnvalidateBill'), $text, 'confirm_modif', $formquestion, "yes", 1);
  1778. }
  1779. // Confirmation du classement paye
  1780. if ($action == 'paid' && $resteapayer <= 0) {
  1781. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('ClassifyPaid'), $langs->trans('ConfirmClassifyPaidBill', $object->ref), 'confirm_paid', '', "yes", 1);
  1782. }
  1783. if ($action == 'paid' && $resteapayer > 0) {
  1784. // Code
  1785. $i = 0;
  1786. $close[$i]['code'] = 'discount_vat';
  1787. $i++;
  1788. $close[$i]['code'] = 'badcustomer';
  1789. $i++;
  1790. // Help
  1791. $i = 0;
  1792. $close[$i]['label'] = $langs->trans("HelpEscompte") . '<br><br>' . $langs->trans("ConfirmClassifyPaidPartiallyReasonDiscountVatDesc");
  1793. $i++;
  1794. $close[$i]['label'] = $langs->trans("ConfirmClassifyPaidPartiallyReasonBadCustomerDesc");
  1795. $i++;
  1796. // Texte
  1797. $i = 0;
  1798. $close[$i]['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyPaidPartiallyReasonDiscountVat", $resteapayer, $langs->trans("Currency" . $conf->currency)), $close[$i]['label'], 1);
  1799. $i++;
  1800. $close[$i]['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyPaidPartiallyReasonBadCustomer", $resteapayer, $langs->trans("Currency" . $conf->currency)), $close[$i]['label'], 1);
  1801. $i++;
  1802. // arrayreasons[code]=reason
  1803. foreach ($close as $key => $val) {
  1804. $arrayreasons[$close[$key]['code']] = $close[$key]['reason'];
  1805. }
  1806. // Cree un tableau formulaire
  1807. $formquestion = array(
  1808. 'text' => $langs->trans("ConfirmClassifyPaidPartiallyQuestion"),
  1809. array('type' => 'radio', 'name' => 'close_code', 'label' => $langs->trans("Reason"), 'values' => $arrayreasons),
  1810. array('type' => 'text', 'name' => 'close_note', 'label' => $langs->trans("Comment"), 'value' => '', 'size' => '100')
  1811. );
  1812. // Paiement incomplet. On demande si motif = escompte ou autre
  1813. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('ClassifyPaid'), $langs->trans('ConfirmClassifyPaidPartially', $object->ref), 'confirm_paid_partially', $formquestion, "yes");
  1814. }
  1815. // Confirmation du classement abandonne
  1816. if ($action == 'canceled') {
  1817. // S'il y a une facture de remplacement pas encore validee (etat brouillon),
  1818. // on ne permet pas de classer abandonner la facture.
  1819. if ($objectidnext) {
  1820. $facturereplacement = new Facture($db);
  1821. $facturereplacement->fetch($objectidnext);
  1822. $statusreplacement = $facturereplacement->statut;
  1823. }
  1824. if ($objectidnext && $statusreplacement == 0) {
  1825. print '<div class="error">' . $langs->trans("ErrorCantCancelIfReplacementInvoiceNotValidated") . '</div>';
  1826. } else {
  1827. // Code
  1828. $close[1]['code'] = 'badcustomer';
  1829. $close[2]['code'] = 'abandon';
  1830. // Help
  1831. $close[1]['label'] = $langs->trans("ConfirmClassifyPaidPartiallyReasonBadCustomerDesc");
  1832. $close[2]['label'] = $langs->trans("ConfirmClassifyAbandonReasonOtherDesc");
  1833. // Texte
  1834. $close[1]['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyPaidPartiallyReasonBadCustomer", $object->ref), $close[1]['label'], 1);
  1835. $close[2]['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyAbandonReasonOther"), $close[2]['label'], 1);
  1836. // arrayreasons
  1837. $arrayreasons[$close[1]['code']] = $close[1]['reason'];
  1838. $arrayreasons[$close[2]['code']] = $close[2]['reason'];
  1839. // Cree un tableau formulaire
  1840. $formquestion = array(
  1841. 'text' => $langs->trans("ConfirmCancelBillQuestion"),
  1842. array('type' => 'radio', 'name' => 'close_code', 'label' => $langs->trans("Reason"), 'values' => $arrayreasons),
  1843. array('type' => 'text', 'name' => 'close_note', 'label' => $langs->trans("Comment"), 'value' => '', 'size' => '100')
  1844. );
  1845. $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $langs->trans('CancelBill'), $langs->trans('ConfirmCancelBill', $object->ref), 'confirm_canceled', $formquestion, "yes");
  1846. }
  1847. }
  1848. // Confirmation de la suppression d'une ligne produit
  1849. if ($action == 'ask_deleteline') {
  1850. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&lineid=' . $lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 'no', 1);
  1851. }
  1852. // Clone confirmation
  1853. if ($action == 'clone') {
  1854. // Create an array for form
  1855. $formquestion = array(
  1856. //'text' => $langs->trans("ConfirmClone"),
  1857. //array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1)
  1858. );
  1859. // Paiement incomplet. On demande si motif = escompte ou autre
  1860. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('CloneInvoice'), $langs->trans('ConfirmCloneInvoice', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
  1861. }
  1862. if (!$formconfirm) {
  1863. $parameters = array('lineid' => $lineid);
  1864. $formconfirm = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  1865. }
  1866. // Print form confirm
  1867. print $formconfirm;
  1868. // Invoice content
  1869. print '<table class="border" width="100%">';
  1870. $linkback = '<a href="' . DOL_URL_ROOT . '/compta/facture/list.php' . (!empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
  1871. // Ref
  1872. print '<tr><td width="20%">' . $langs->trans('Ref') . '</td>';
  1873. print '<td colspan="5">';
  1874. $morehtmlref = '';
  1875. $discount = new DiscountAbsolute($db);
  1876. $result = $discount->fetch(0, $object->id);
  1877. if ($result > 0) {
  1878. $morehtmlref = ' (' . $langs->trans("CreditNoteConvertedIntoDiscount", $discount->getNomUrl(1, 'discount')) . ')';
  1879. }
  1880. if ($result < 0) {
  1881. dol_print_error('', $discount->error);
  1882. }
  1883. print $form->showrefnav($object, 'ref', $linkback, 1, 'facnumber', 'ref', $morehtmlref);
  1884. print '</td></tr>';
  1885. // Ref customer
  1886. print '<tr><td width="20%">';
  1887. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1888. print $langs->trans('RefCustomer');
  1889. print '</td>';
  1890. if ($action != 'refclient' && !empty($object->brouillon))
  1891. print '<td align="right"><a href="' . $_SERVER['PHP_SELF'] . '?action=refclient&amp;id=' . $object->id . '">' . img_edit($langs->trans('Modify')) . '</a></td>';
  1892. print '</tr></table>';
  1893. print '</td>';
  1894. print '<td colspan="5">';
  1895. if ($user->rights->facture->creer && $action == 'refclient') {
  1896. print '<form action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
  1897. print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
  1898. print '<input type="hidden" name="action" value="set_ref_client">';
  1899. print '<input type="text" class="flat" size="20" name="ref_client" value="' . $object->ref_client . '">';
  1900. print ' <input type="submit" class="button" value="' . $langs->trans('Modify') . '">';
  1901. print '</form>';
  1902. } else {
  1903. print $object->ref_client;
  1904. }
  1905. print '</td></tr>';
  1906. // Third party
  1907. print '<tr><td>';
  1908. print '<table class="nobordernopadding" width="100%">';
  1909. print '<tr><td>' . $langs->trans('Company') . '</td>';
  1910. print '</td><td colspan="5">';
  1911. if (!empty($conf->global->FACTURE_CHANGE_THIRDPARTY) && $action != 'editthirdparty' && $object->brouillon && $user->rights->facture->creer)
  1912. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editthirdparty&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetLinkToThirdParty'), 1) . '</a></td>';
  1913. print '</tr></table>';
  1914. print '</td><td colspan="5">';
  1915. if ($action == 'editthirdparty') {
  1916. $form->form_thirdparty($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->socid, 'socid');
  1917. } else {
  1918. print ' &nbsp;' . $soc->getNomUrl(1, 'compta');
  1919. print ' &nbsp; (<a href="' . DOL_URL_ROOT . '/compta/facture/list.php?socid=' . $object->socid . '">' . $langs->trans('OtherBills') . '</a>)';
  1920. }
  1921. print '</tr>';
  1922. // Type
  1923. print '<tr><td>' . $langs->trans('Type') . '</td><td colspan="5">';
  1924. print $object->getLibType();
  1925. if ($object->type == 1) {
  1926. $facreplaced = new Facture($db);
  1927. $facreplaced->fetch($object->fk_facture_source);
  1928. print ' (' . $langs->transnoentities("ReplaceInvoice", $facreplaced->getNomUrl(1)) . ')';
  1929. }
  1930. if ($object->type == 2) {
  1931. $facusing = new Facture($db);
  1932. $facusing->fetch($object->fk_facture_source);
  1933. print ' (' . $langs->transnoentities("CorrectInvoice", $facusing->getNomUrl(1)) . ')';
  1934. }
  1935. $facidavoir = $object->getListIdAvoirFromInvoice();
  1936. if (count($facidavoir) > 0) {
  1937. print ' (' . $langs->transnoentities("InvoiceHasAvoir");
  1938. $i = 0;
  1939. foreach ($facidavoir as $id) {
  1940. if ($i == 0)
  1941. print ' ';
  1942. else
  1943. print ',';
  1944. $facavoir = new Facture($db);
  1945. $facavoir->fetch($id);
  1946. print $facavoir->getNomUrl(1);
  1947. }
  1948. print ')';
  1949. }
  1950. if ($objectidnext > 0) {
  1951. $facthatreplace = new Facture($db);
  1952. $facthatreplace->fetch($objectidnext);
  1953. print ' (' . $langs->transnoentities("ReplacedByInvoice", $facthatreplace->getNomUrl(1)) . ')';
  1954. }
  1955. print '</td></tr>';
  1956. // Relative and absolute discounts
  1957. $addrelativediscount = '<a href="' . DOL_URL_ROOT . '/comm/remise.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("EditRelativeDiscounts") . '</a>';
  1958. $addabsolutediscount = '<a href="' . DOL_URL_ROOT . '/comm/remx.php?id=' . $soc->id . '&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("EditGlobalDiscounts") . '</a>';
  1959. $addcreditnote = '<a href="' . DOL_URL_ROOT . '/compta/facture.php?action=create&socid=' . $soc->id . '&type=2&backtopage=' . urlencode($_SERVER["PHP_SELF"]) . '?facid=' . $object->id . '">' . $langs->trans("AddCreditNote") . '</a>';
  1960. print '<tr><td>' . $langs->trans('Discounts');
  1961. print '</td><td colspan="5">';
  1962. if ($soc->remise_client)
  1963. print $langs->trans("CompanyHasRelativeDiscount", $soc->remise_client);
  1964. else
  1965. print $langs->trans("CompanyHasNoRelativeDiscount");
  1966. //print ' ('.$addrelativediscount.')';
  1967. if ($absolute_discount > 0) {
  1968. print '. ';
  1969. if ($object->statut > 0 || $object->type == 2 || $object->type == 3) {
  1970. if ($object->statut == 0) {
  1971. print $langs->trans("CompanyHasAbsoluteDiscount", price($absolute_discount), $langs->transnoentities("Currency" . $conf->currency));
  1972. print '. ';
  1973. } else {
  1974. if ($object->statut < 1 || $object->type == 2 || $object->type == 3) {
  1975. $text = $langs->trans("CompanyHasAbsoluteDiscount", price($absolute_discount), $langs->transnoentities("Currency" . $conf->currency));
  1976. print '<br>' . $text . '.<br>';
  1977. } else {
  1978. $text = $langs->trans("CompanyHasAbsoluteDiscount", price($absolute_discount), $langs->transnoentities("Currency" . $conf->currency));
  1979. $text2 = $langs->trans("AbsoluteDiscountUse");
  1980. print $form->textwithpicto($text, $text2);
  1981. }
  1982. }
  1983. } else {
  1984. // Remise dispo de type remise fixe (not credit note)
  1985. print '<br>';
  1986. $form->form_remise_dispo($_SERVER["PHP_SELF"] . '?facid=' . $object->id, GETPOST('discountid'), 'remise_id', $soc->id, $absolute_discount, $filterabsolutediscount, $resteapayer, ' (' . $addabsolutediscount . ')');
  1987. }
  1988. } else {
  1989. if ($absolute_creditnote > 0) { // If not, link will be added later
  1990. if ($object->statut == 0 && $object->type != 2 && $object->type != 3)
  1991. print ' (' . $addabsolutediscount . ')<br>';
  1992. else
  1993. print '. ';
  1994. }
  1995. else
  1996. print '. ';
  1997. }
  1998. if ($absolute_creditnote > 0) {
  1999. // If validated, we show link "add credit note to payment"
  2000. if ($object->statut != 1 || $object->type == 2 || $object->type == 3) {
  2001. if ($object->statut == 0 && $object->type != 3) {
  2002. $text = $langs->trans("CompanyHasCreditNote", price($absolute_creditnote), $langs->transnoentities("Currency" . $conf->currency));
  2003. print $form->textwithpicto($text, $langs->trans("CreditNoteDepositUse"));
  2004. } else {
  2005. print $langs->trans("CompanyHasCreditNote", price($absolute_creditnote), $langs->transnoentities("Currency" . $conf->currency)) . '.';
  2006. }
  2007. } else {
  2008. // Remise dispo de type avoir
  2009. if (!$absolute_discount)
  2010. print '<br>';
  2011. //$form->form_remise_dispo($_SERVER["PHP_SELF"].'?facid='.$object->id, 0, 'remise_id_for_payment', $soc->id, $absolute_creditnote, $filtercreditnote, $resteapayer);
  2012. $form->form_remise_dispo($_SERVER["PHP_SELF"] . '?facid=' . $object->id, 0, 'remise_id_for_payment', $soc->id, $absolute_creditnote, $filtercreditnote, 0); // We must allow credit not even if amount is higher
  2013. }
  2014. }
  2015. if (!$absolute_discount && !$absolute_creditnote) {
  2016. print $langs->trans("CompanyHasNoAbsoluteDiscount");
  2017. if ($object->statut == 0 && $object->type != 2 && $object->type != 3)
  2018. print ' (' . $addabsolutediscount . ')<br>';
  2019. else
  2020. print '. ';
  2021. }
  2022. /* if ($object->statut == 0 && $object->type != 2 && $object->type != 3)
  2023. {
  2024. if (! $absolute_discount && ! $absolute_creditnote) print '<br>';
  2025. //print ' &nbsp; - &nbsp; ';
  2026. print $addabsolutediscount;
  2027. //print ' &nbsp; - &nbsp; '.$addcreditnote; // We disbale link to credit note
  2028. } */
  2029. print '</td></tr>';
  2030. // Date invoice
  2031. print '<tr><td>';
  2032. print '<table class="nobordernopadding" width="100%"><tr><td>';
  2033. print $langs->trans('Date');
  2034. print '</td>';
  2035. if ($object->type != 2 && $action != 'editinvoicedate' && !empty($object->brouillon) && $user->rights->facture->creer)
  2036. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editinvoicedate&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetDate'), 1) . '</a></td>';
  2037. print '</tr></table>';
  2038. print '</td><td colspan="3">';
  2039. if ($object->type != 2) {
  2040. if ($action == 'editinvoicedate') {
  2041. $form->form_date($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->date, 'invoicedate');
  2042. } else {
  2043. print dol_print_date($object->date, 'daytext');
  2044. }
  2045. } else {
  2046. print dol_print_date($object->date, 'daytext');
  2047. }
  2048. print '</td>';
  2049. /*
  2050. * List of payments
  2051. */
  2052. $nbrows = 8;
  2053. $nbcols = 2;
  2054. if (!empty($conf->projet->enabled))
  2055. $nbrows++;
  2056. if (!empty($conf->banque->enabled))
  2057. $nbcols++;
  2058. //Local taxes
  2059. if ($mysoc->pays_code == 'ES') {
  2060. if ($mysoc->localtax1_assuj == "1")
  2061. $nbrows++;
  2062. if ($mysoc->localtax2_assuj == "1")
  2063. $nbrows++;
  2064. }
  2065. print '<td rowspan="' . $nbrows . '" colspan="2" valign="top">';
  2066. print '<table class="nobordernopadding" width="100%">';
  2067. // List of payments already done
  2068. print '<tr class="liste_titre">';
  2069. print '<td>' . ($object->type == 2 ? $langs->trans("PaymentsBack") : $langs->trans('Payments')) . '</td>';
  2070. print '<td>' . $langs->trans('Type') . '</td>';
  2071. if (!empty($conf->banque->enabled))
  2072. print '<td align="right">' . $langs->trans('BankAccount') . '</td>';
  2073. print '<td align="right">' . $langs->trans('Amount') . '</td>';
  2074. print '<td width="18">&nbsp;</td>';
  2075. print '</tr>';
  2076. $var = true;
  2077. // Payments already done (from payment on this invoice)
  2078. $sql = 'SELECT p.datep as dp, p.num_paiement, p.rowid, p.fk_bank,';
  2079. $sql.= ' c.code as payment_code, c.libelle as payment_label,';
  2080. $sql.= ' pf.amount,';
  2081. $sql.= ' ba.rowid as baid, ba.ref, ba.label';
  2082. $sql.= ' FROM ' . MAIN_DB_PREFIX . 'c_paiement as c, ' . MAIN_DB_PREFIX . 'paiement_facture as pf, ' . MAIN_DB_PREFIX . 'paiement as p';
  2083. $sql.= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'bank as b ON p.fk_bank = b.rowid';
  2084. $sql.= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'bank_account as ba ON b.fk_account = ba.rowid';
  2085. $sql.= ' WHERE pf.fk_facture = ' . $object->id . ' AND p.fk_paiement = c.id AND pf.fk_paiement = p.rowid';
  2086. $sql.= ' ORDER BY p.datep, p.tms';
  2087. $result = $db->query($sql);
  2088. if ($result) {
  2089. $num = $db->num_rows($result);
  2090. $i = 0;
  2091. if ($object->type != 2) {
  2092. if ($num > 0) {
  2093. while ($i < $num) {
  2094. $objp = $db->fetch_object($result);
  2095. $var = !$var;
  2096. print '<tr ' . $bc[$var] . '><td>';
  2097. print '<a href="' . DOL_URL_ROOT . '/compta/paiement/fiche.php?id=' . $objp->rowid . '">' . img_object($langs->trans('ShowPayment'), 'payment') . ' ';
  2098. print dol_print_date($db->jdate($objp->dp), 'day') . '</a></td>';
  2099. $label = ($langs->trans("PaymentType" . $objp->payment_code) != ("PaymentType" . $objp->payment_code)) ? $langs->trans("PaymentType" . $objp->payment_code) : $objp->payment_label;
  2100. print '<td>' . $label . ' ' . $objp->num_paiement . '</td>';
  2101. if (!empty($conf->banque->enabled)) {
  2102. $bankaccountstatic->id = $objp->baid;
  2103. $bankaccountstatic->ref = $objp->ref;
  2104. $bankaccountstatic->label = $objp->ref;
  2105. print '<td align="right">';
  2106. if ($bankaccountstatic->id)
  2107. print $bankaccountstatic->getNomUrl(1, 'transactions');
  2108. print '</td>';
  2109. }
  2110. print '<td align="right">' . price($objp->amount) . '</td>';
  2111. print '<td>&nbsp;</td>';
  2112. print '</tr>';
  2113. $i++;
  2114. }
  2115. }
  2116. else {
  2117. print '<tr ' . $bc[$var] . '><td colspan="' . $nbcols . '">' . $langs->trans("None") . '</td><td></td><td></td></tr>';
  2118. }
  2119. }
  2120. $db->free($result);
  2121. } else {
  2122. dol_print_error($db);
  2123. }
  2124. if ($object->type != 2) {
  2125. // Total already paid
  2126. print '<tr><td colspan="' . $nbcols . '" align="right">';
  2127. if ($object->type != 3)
  2128. print $langs->trans('AlreadyPaidNoCreditNotesNoDeposits');
  2129. else
  2130. print $langs->trans('AlreadyPaid');
  2131. print ' :</td><td align="right">' . price($totalpaye) . '</td><td>&nbsp;</td></tr>';
  2132. $resteapayeraffiche = $resteapayer;
  2133. // Loop on each credit note or deposit amount applied
  2134. $creditnoteamount = 0;
  2135. $depositamount = 0;
  2136. $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
  2137. $sql.= " re.description, re.fk_facture_source";
  2138. $sql.= " FROM " . MAIN_DB_PREFIX . "societe_remise_except as re";
  2139. $sql.= " WHERE fk_facture = " . $object->id;
  2140. $resql = $db->query($sql);
  2141. if ($resql) {
  2142. $num = $db->num_rows($resql);
  2143. $i = 0;
  2144. $invoice = new Facture($db);
  2145. while ($i < $num) {
  2146. $obj = $db->fetch_object($resql);
  2147. $invoice->fetch($obj->fk_facture_source);
  2148. print '<tr><td colspan="' . $nbcols . '" align="right">';
  2149. if ($invoice->type == 2)
  2150. print $langs->trans("CreditNote") . ' ';
  2151. if ($invoice->type == 3)
  2152. print $langs->trans("Deposit") . ' ';
  2153. print $invoice->getNomUrl(0);
  2154. print ' :</td>';
  2155. print '<td align="right">' . price($obj->amount_ttc) . '</td>';
  2156. print '<td align="right">';
  2157. print '<a href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&action=unlinkdiscount&discountid=' . $obj->rowid . '">' . img_delete() . '</a>';
  2158. print '</td></tr>';
  2159. $i++;
  2160. if ($invoice->type == 2)
  2161. $creditnoteamount += $obj->amount_ttc;
  2162. if ($invoice->type == 3)
  2163. $depositamount += $obj->amount_ttc;
  2164. }
  2165. }
  2166. else {
  2167. dol_print_error($db);
  2168. }
  2169. // Paye partiellement 'escompte'
  2170. if (($object->statut == 2 || $object->statut == 3) && $object->close_code == 'discount_vat') {
  2171. print '<tr><td colspan="' . $nbcols . '" align="right" nowrap="1">';
  2172. print $form->textwithpicto($langs->trans("Escompte") . ':', $langs->trans("HelpEscompte"), -1);
  2173. print '</td><td align="right">' . price($object->total_ttc - $creditnoteamount - $depositamount - $totalpaye) . '</td><td>&nbsp;</td></tr>';
  2174. $resteapayeraffiche = 0;
  2175. }
  2176. // Paye partiellement ou Abandon 'badcustomer'
  2177. if (($object->statut == 2 || $object->statut == 3) && $object->close_code == 'badcustomer') {
  2178. print '<tr><td colspan="' . $nbcols . '" align="right" nowrap="1">';
  2179. print $form->textwithpicto($langs->trans("Abandoned") . ':', $langs->trans("HelpAbandonBadCustomer"), -1);
  2180. print '</td><td align="right">' . price($object->total_ttc - $creditnoteamount - $depositamount - $totalpaye) . '</td><td>&nbsp;</td></tr>';
  2181. //$resteapayeraffiche=0;
  2182. }
  2183. // Paye partiellement ou Abandon 'product_returned'
  2184. if (($object->statut == 2 || $object->statut == 3) && $object->close_code == 'product_returned') {
  2185. print '<tr><td colspan="' . $nbcols . '" align="right" nowrap="1">';
  2186. print $form->textwithpicto($langs->trans("ProductReturned") . ':', $langs->trans("HelpAbandonProductReturned"), -1);
  2187. print '</td><td align="right">' . price($object->total_ttc - $creditnoteamount - $depositamount - $totalpaye) . '</td><td>&nbsp;</td></tr>';
  2188. $resteapayeraffiche = 0;
  2189. }
  2190. // Paye partiellement ou Abandon 'abandon'
  2191. if (($object->statut == 2 || $object->statut == 3) && $object->close_code == 'abandon') {
  2192. print '<tr><td colspan="' . $nbcols . '" align="right" nowrap="1">';
  2193. $text = $langs->trans("HelpAbandonOther");
  2194. if ($object->close_note)
  2195. $text.='<br><br><b>' . $langs->trans("Reason") . '</b>:' . $object->close_note;
  2196. print $form->textwithpicto($langs->trans("Abandoned") . ':', $text, -1);
  2197. print '</td><td align="right">' . price($object->total_ttc - $creditnoteamount - $depositamount - $totalpaye) . '</td><td>&nbsp;</td></tr>';
  2198. $resteapayeraffiche = 0;
  2199. }
  2200. // Billed
  2201. print '<tr><td colspan="' . $nbcols . '" align="right">' . $langs->trans("Billed") . ' :</td><td align="right" style="border: 1px solid;">' . price($object->total_ttc) . '</td><td>&nbsp;</td></tr>';
  2202. // Remainder to pay
  2203. print '<tr><td colspan="' . $nbcols . '" align="right">';
  2204. if ($resteapayeraffiche >= 0)
  2205. print $langs->trans('RemainderToPay');
  2206. else
  2207. print $langs->trans('ExcessReceived');
  2208. print ' :</td>';
  2209. print '<td align="right" style="border: 1px solid;" bgcolor="#f0f0f0"><b>' . price($resteapayeraffiche) . '</b></td>';
  2210. print '<td nowrap="nowrap">&nbsp;</td></tr>';
  2211. }
  2212. else {
  2213. // Sold credit note
  2214. print '<tr><td colspan="' . $nbcols . '" align="right">' . $langs->trans('TotalTTC') . ' :</td>';
  2215. print '<td align="right" style="border: 1px solid;" bgcolor="#f0f0f0"><b>' . price(abs($object->total_ttc)) . '</b></td><td>&nbsp;</td></tr>';
  2216. }
  2217. print '</table>';
  2218. // Margin Infos
  2219. if (!empty($conf->margin->enabled)) {
  2220. print '<br>';
  2221. $object->displayMarginInfos($object->statut > 0);
  2222. }
  2223. print '</td></tr>';
  2224. // Date payment term
  2225. print '<tr><td>';
  2226. print '<table class="nobordernopadding" width="100%"><tr><td>';
  2227. print $langs->trans('DateMaxPayment');
  2228. print '</td>';
  2229. if ($object->type != 2 && $action != 'editpaymentterm' && !empty($object->brouillon) && $user->rights->facture->creer)
  2230. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editpaymentterm&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetDate'), 1) . '</a></td>';
  2231. print '</tr></table>';
  2232. print '</td><td colspan="3">';
  2233. if ($object->type != 2) {
  2234. if ($action == 'editpaymentterm') {
  2235. $form->form_date($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->date_lim_reglement, 'paymentterm');
  2236. } else {
  2237. print dol_print_date($object->date_lim_reglement, 'daytext');
  2238. if ($object->date_lim_reglement < ($now - $conf->facture->client->warning_delay) && !$object->paye && $object->statut == 1 && !isset($object->am))
  2239. print img_warning($langs->trans('Late'));
  2240. }
  2241. }
  2242. else {
  2243. print '&nbsp;';
  2244. }
  2245. print '</td></tr>';
  2246. // Conditions de reglement
  2247. print '<tr><td>';
  2248. print '<table class="nobordernopadding" width="100%"><tr><td>';
  2249. print $langs->trans('PaymentConditionsShort');
  2250. print '</td>';
  2251. if ($object->type != 2 && $action != 'editconditions' && !empty($object->brouillon) && $user->rights->facture->creer)
  2252. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editconditions&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetConditions'), 1) . '</a></td>';
  2253. print '</tr></table>';
  2254. print '</td><td colspan="3">';
  2255. if ($object->type != 2) {
  2256. if ($action == 'editconditions') {
  2257. $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->cond_reglement_id, 'cond_reglement_id');
  2258. } else {
  2259. $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->cond_reglement_id, 'none');
  2260. }
  2261. } else {
  2262. print '&nbsp;';
  2263. }
  2264. print '</td></tr>';
  2265. // Mode de reglement
  2266. print '<tr><td>';
  2267. print '<table class="nobordernopadding" width="100%"><tr><td>';
  2268. print $langs->trans('PaymentMode');
  2269. print '</td>';
  2270. if ($action != 'editmode' && !empty($object->brouillon) && $user->rights->facture->creer)
  2271. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmode&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetMode'), 1) . '</a></td>';
  2272. print '</tr></table>';
  2273. print '</td><td colspan="3">';
  2274. if ($action == 'editmode') {
  2275. $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->mode_reglement_id, 'mode_reglement_id');
  2276. } else {
  2277. $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->mode_reglement_id, 'none');
  2278. }
  2279. print '</td></tr>';
  2280. // Amount
  2281. print '<tr><td>' . $langs->trans('AmountHT') . '</td>';
  2282. print '<td align="right" colspan="2" nowrap>' . price($object->total_ht) . '</td>';
  2283. print '<td>' . $langs->trans('Currency' . $conf->currency) . '</td></tr>';
  2284. print '<tr><td>' . $langs->trans('AmountVAT') . '</td><td align="right" colspan="2" nowrap>' . price($object->total_tva) . '</td>';
  2285. print '<td>' . $langs->trans('Currency' . $conf->currency) . '</td>';
  2286. print '</tr>';
  2287. // Amount Local Taxes
  2288. if ($mysoc->pays_code == 'ES') {
  2289. if ($mysoc->localtax1_assuj == "1") { //Localtax1 RE
  2290. print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->pays_code) . '</td>';
  2291. print '<td align="right" colspan="2" nowrap>' . price($object->total_localtax1) . '</td>';
  2292. print '<td>' . $langs->trans("Currency" . $conf->currency) . '</td></tr>';
  2293. }
  2294. if ($mysoc->localtax2_assuj == "1") { //Localtax2 IRPF
  2295. print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->pays_code) . '</td>';
  2296. print '<td align="right" colspan="2" nowrap>' . price($object->total_localtax2) . '</td>';
  2297. print '<td>' . $langs->trans("Currency" . $conf->currency) . '</td></tr>';
  2298. }
  2299. }
  2300. print '<tr><td>' . $langs->trans('AmountTTC') . '</td><td align="right" colspan="2" nowrap>' . price($object->total_ttc) . '</td>';
  2301. print '<td>' . $langs->trans('Currency' . $conf->currency) . '</td></tr>';
  2302. // Statut
  2303. print '<tr><td>' . $langs->trans('Status') . '</td>';
  2304. print '<td align="left" colspan="3">' . ($object->getLibStatut(4, $totalpaye)) . '</td></tr>';
  2305. // Project
  2306. if (!empty($conf->projet->enabled)) {
  2307. $langs->load('projects');
  2308. print '<tr>';
  2309. print '<td>';
  2310. print '<table class="nobordernopadding" width="100%"><tr><td>';
  2311. print $langs->trans('Project');
  2312. print '</td>';
  2313. if ($action != 'classify') {
  2314. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=classify&amp;facid=' . $object->id . '">';
  2315. print img_edit($langs->trans('SetProject'), 1);
  2316. print '</a></td>';
  2317. }
  2318. print '</tr></table>';
  2319. print '</td><td colspan="3">';
  2320. if ($action == 'classify') {
  2321. $form->form_project($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->socid, $object->fk_project, 'projectid');
  2322. } else {
  2323. $form->form_project($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->socid, $object->fk_project, 'none');
  2324. }
  2325. print '</td>';
  2326. print '</tr>';
  2327. }
  2328. // Other attributes
  2329. $parameters = array('colspan' => ' colspan="3"');
  2330. $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  2331. if (empty($reshook) && !empty($extrafields->attribute_label)) {
  2332. foreach ($extrafields->attribute_label as $key => $label) {
  2333. $value = (isset($_POST["options_" . $key]) ? $_POST["options_" . $key] : $object->array_options["options_" . $key]);
  2334. print '<tr><td>' . $label . '</td><td colspan="3">';
  2335. print $extrafields->showInputField($key, $value);
  2336. print '</td></tr>' . "\n";
  2337. }
  2338. }
  2339. print '</table><br>';
  2340. if (!empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) {
  2341. $blocname = 'contacts';
  2342. $title = $langs->trans('ContactsAddresses');
  2343. include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_showhide.tpl.php';
  2344. }
  2345. if (!empty($conf->global->MAIN_DISABLE_NOTES_TAB)) {
  2346. $blocname = 'notes';
  2347. $title = $langs->trans('Notes');
  2348. include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_showhide.tpl.php';
  2349. }
  2350. /*
  2351. * Lines
  2352. */
  2353. $result = $object->getLinesArray();
  2354. if (!empty($conf->use_javascript_ajax) && $object->statut == 0) {
  2355. include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
  2356. }
  2357. print '<table id="tablelines" class="noborder noshadow" width="100%">';
  2358. // Show object lines
  2359. if (!empty($object->lines))
  2360. $ret = $object->printObjectLines($action, $mysoc, $soc, $lineid, 1);
  2361. /*
  2362. * Form to add new line
  2363. */
  2364. if ($object->statut == 0 && $user->rights->facture->creer && $action <> 'valid' && $action <> 'editline') {
  2365. $var = true;
  2366. if ($conf->global->MAIN_FEATURES_LEVEL > 1) {
  2367. // Add free or predefined products/services
  2368. $object->formAddObjectLine(1, $mysoc, $soc);
  2369. } else {
  2370. // Add free products/services
  2371. $object->formAddFreeProduct(1, $mysoc, $soc);
  2372. // Add predefined products/services
  2373. if (!empty($conf->product->enabled) || !empty($conf->service->enabled)) {
  2374. $var = !$var;
  2375. $object->formAddPredefinedProduct(1, $mysoc, $soc);
  2376. }
  2377. }
  2378. $parameters = array();
  2379. $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  2380. }
  2381. print "</table>\n";
  2382. print "</div>\n";
  2383. /*
  2384. * Boutons actions
  2385. */
  2386. if ($action != 'prerelance' && $action != 'presend') {
  2387. if ($user->societe_id == 0 && $action <> 'valid' && $action <> 'editline') {
  2388. print '<div class="tabsAction">';
  2389. // Editer une facture deja validee, sans paiement effectue et pas exporte en compta
  2390. if ($object->statut == 1) {
  2391. // On verifie si les lignes de factures ont ete exportees en compta et/ou ventilees
  2392. $ventilExportCompta = $object->getVentilExportCompta();
  2393. if ($resteapayer == $object->total_ttc && $object->paye == 0 && $ventilExportCompta == 0) {
  2394. if (!$objectidnext) {
  2395. if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->facture->valider) || $user->rights->facture->invoice_advance->unvalidate) {
  2396. print '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=modif">' . $langs->trans('Modify') . '</a>';
  2397. } else {
  2398. print '<span class="butActionRefused" title="' . $langs->trans("NotEnoughPermissions") . '">' . $langs->trans('Modify') . '</span>';
  2399. }
  2400. } else {
  2401. print '<span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('Modify') . '</span>';
  2402. }
  2403. }
  2404. }
  2405. // Reopen a standard paid invoice
  2406. if (($object->type == 0 || $object->type == 1) && ($object->statut == 2 || $object->statut == 3)) { // A paid invoice (partially or completely)
  2407. if (!$objectidnext && $object->close_code != 'replaced') { // Not replaced by another invoice
  2408. print '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=reopen">' . $langs->trans('ReOpen') . '</a>';
  2409. } else {
  2410. print '<span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('ReOpen') . '</span>';
  2411. }
  2412. }
  2413. // Validate
  2414. if ($object->statut == 0 && count($object->lines) > 0 &&
  2415. (
  2416. (($object->type == 0 || $object->type == 1 || $object->type == 3 || $object->type == 4) && (!empty($conf->global->FACTURE_ENABLE_NEGATIVE) || $object->total_ttc >= 0))
  2417. || ($object->type == 2 && $object->total_ttc <= 0))
  2418. ) {
  2419. if ($user->rights->facture->valider) {
  2420. print '<a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&amp;action=valid">' . $langs->trans('Validate') . '</a>';
  2421. }
  2422. }
  2423. // Send by mail
  2424. if (($object->statut == 1 || $object->statut == 2)) {
  2425. if ($objectidnext) {
  2426. print '<span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('SendByMail') . '</span>';
  2427. } else {
  2428. if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->facture->invoice_advance->send) {
  2429. print '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=presend&amp;mode=init">' . $langs->trans('SendByMail') . '</a>';
  2430. }
  2431. else
  2432. print '<a class="butActionRefused" href="#">' . $langs->trans('SendByMail') . '</a>';
  2433. }
  2434. }
  2435. if (!empty($conf->global->FACTURE_SHOW_SEND_REMINDER)) { // For backward compatibility
  2436. if (($object->statut == 1 || $object->statut == 2) && $resteapayer > 0) {
  2437. if ($objectidnext) {
  2438. print '<span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('SendRemindByMail') . '</span>';
  2439. } else {
  2440. if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->facture->invoice_advance->send) {
  2441. print '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=prerelance&amp;mode=init">' . $langs->trans('SendRemindByMail') . '</a>';
  2442. }
  2443. else
  2444. print '<a class="butActionRefused" href="#">' . $langs->trans('SendRemindByMail') . '</a>';
  2445. }
  2446. }
  2447. }
  2448. // Create payment
  2449. if ($object->type != 2 && $object->statut == 1 && $object->paye == 0 && $user->rights->facture->paiement) {
  2450. if ($objectidnext) {
  2451. print '<span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('DoPayment') . '</span>';
  2452. } else {
  2453. if ($resteapayer == 0) {
  2454. print '<span class="butActionRefused" title="' . $langs->trans("DisabledBecauseRemainderToPayIsZero") . '">' . $langs->trans('DoPayment') . '</span>';
  2455. } else {
  2456. print '<a class="butAction" href="paiement.php?facid=' . $object->id . '&amp;action=create">' . $langs->trans('DoPayment') . '</a>';
  2457. }
  2458. }
  2459. }
  2460. // Reverse back money or convert to reduction
  2461. if ($object->type == 2 || $object->type == 3) {
  2462. // For credit note only
  2463. if ($object->type == 2 && $object->statut == 1 && $object->paye == 0 && $user->rights->facture->paiement) {
  2464. print '<a class="butAction" href="paiement.php?facid=' . $object->id . '&amp;action=create">' . $langs->trans('DoPaymentBack') . '</a>';
  2465. }
  2466. // For credit note
  2467. if ($object->type == 2 && $object->statut == 1 && $object->paye == 0 && $user->rights->facture->creer && $object->getSommePaiement() == 0) {
  2468. print '<a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&amp;action=converttoreduc">' . $langs->trans('ConvertToReduc') . '</a>';
  2469. }
  2470. // For deposit invoice
  2471. if ($object->type == 3 && $object->statut == 1 && $resteapayer == 0 && $user->rights->facture->creer) {
  2472. print '<a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&amp;action=converttoreduc">' . $langs->trans('ConvertToReduc') . '</a>';
  2473. }
  2474. }
  2475. // Classify paid (if not deposit and not credit note. Such invoice are "converted")
  2476. if ($object->statut == 1 && $object->paye == 0 && $user->rights->facture->paiement &&
  2477. (($object->type != 2 && $object->type != 3 && $resteapayer <= 0) || ($object->type == 2 && $resteapayer >= 0))) {
  2478. print '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=paid">' . $langs->trans('ClassifyPaid') . '</a>';
  2479. }
  2480. // Classify 'closed not completely paid' (possible si validee et pas encore classee payee)
  2481. if ($object->statut == 1 && $object->paye == 0 && $resteapayer > 0
  2482. && $user->rights->facture->paiement) {
  2483. if ($totalpaye > 0 || $totalcreditnotes > 0) {
  2484. // If one payment or one credit note was linked to this invoice
  2485. print '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=paid">' . $langs->trans('ClassifyPaidPartially') . '</a>';
  2486. } else {
  2487. if ($objectidnext) {
  2488. print '<span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('ClassifyCanceled') . '</span>';
  2489. } else {
  2490. print '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=canceled">' . $langs->trans('ClassifyCanceled') . '</a>';
  2491. }
  2492. }
  2493. }
  2494. // Clone
  2495. if (($object->type == 0 || $object->type == 3 || $object->type == 4) && $user->rights->facture->creer) {
  2496. print '<a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=clone&amp;object=invoice">' . $langs->trans("ToClone") . '</a>';
  2497. }
  2498. // Clone as predefined
  2499. if (($object->type == 0 || $object->type == 3 || $object->type == 4) && $object->statut == 0 && $user->rights->facture->creer) {
  2500. if (!$objectidnext) {
  2501. print '<a class="butAction" href="facture/fiche-rec.php?facid=' . $object->id . '&amp;action=create">' . $langs->trans("ChangeIntoRepeatableInvoice") . '</a>';
  2502. }
  2503. }
  2504. // Delete
  2505. if ($user->rights->facture->supprimer) {
  2506. if (!$object->is_erasable()) {
  2507. print '<a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseNotErasable") . '">' . $langs->trans('Delete') . '</a>';
  2508. } else if ($objectidnext) {
  2509. print '<a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('Delete') . '</a>';
  2510. } elseif ($object->getSommePaiement()) {
  2511. print '<a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecausePayments") . '">' . $langs->trans('Delete') . '</a>';
  2512. } else {
  2513. print '<a class="butActionDelete" href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&amp;action=delete">' . $langs->trans('Delete') . '</a>';
  2514. }
  2515. } else {
  2516. print '<a class="butActionRefused" href="#" title="' . $langs->trans("NotAllowed") . '">' . $langs->trans('Delete') . '</a>';
  2517. }
  2518. print '</div>';
  2519. }
  2520. }
  2521. if ($action != 'prerelance' && $action != 'presend') {
  2522. print '<table width="100%"><tr><td width="50%" valign="top">';
  2523. print '<a name="builddoc"></a>'; // ancre
  2524. /*
  2525. * Documents generes
  2526. */
  2527. $filename = dol_sanitizeFileName($object->ref);
  2528. $filedir = $conf->facture->dir_output . '/' . dol_sanitizeFileName($object->ref);
  2529. $urlsource = $_SERVER['PHP_SELF'] . '?facid=' . $object->id;
  2530. $genallowed = $user->rights->facture->creer;
  2531. $delallowed = $user->rights->facture->supprimer;
  2532. print '<br>';
  2533. print $formfile->showdocuments('facture', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->modelpdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang);
  2534. $somethingshown = $formfile->numoffiles;
  2535. /*
  2536. * Linked object block
  2537. */
  2538. $somethingshown = $object->showLinkedObjectBlock();
  2539. // Link for paypal payment
  2540. if (!empty($conf->paypal->enabled) && $object->statut != 0) {
  2541. include_once DOL_DOCUMENT_ROOT . '/paypal/lib/paypal.lib.php';
  2542. print showPaypalPaymentUrl('invoice', $object->ref);
  2543. }
  2544. print '</td><td valign="top" width="50%">';
  2545. print '<br>';
  2546. // List of actions on element
  2547. include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php';
  2548. $formactions = new FormActions($db);
  2549. $somethingshown = $formactions->showactions($object, 'invoice', $socid);
  2550. print '</td></tr></table>';
  2551. } else {
  2552. /*
  2553. * Affiche formulaire mail
  2554. */
  2555. // By default if $action=='presend'
  2556. $titreform = 'SendBillByMail';
  2557. $topicmail = 'SendBillRef';
  2558. $action = 'send';
  2559. $modelmail = 'facture_send';
  2560. if ($action == 'prerelance') { // For backward compatibility
  2561. $titrefrom = 'SendReminderBillByMail';
  2562. $topicmail = 'SendReminderBillRef';
  2563. $action = 'relance';
  2564. $modelmail = 'facture_relance';
  2565. }
  2566. $ref = dol_sanitizeFileName($object->ref);
  2567. include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
  2568. $fileparams = dol_most_recent_file($conf->facture->dir_output . '/' . $ref);
  2569. $file = $fileparams['fullname'];
  2570. // Build document if it not exists
  2571. if (!$file || !is_readable($file)) {
  2572. // Define output language
  2573. $outputlangs = $langs;
  2574. $newlang = '';
  2575. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && !empty($_REQUEST['lang_id']))
  2576. $newlang = $_REQUEST['lang_id'];
  2577. if ($conf->global->MAIN_MULTILANGS && empty($newlang))
  2578. $newlang = $object->client->default_lang;
  2579. if (!empty($newlang)) {
  2580. $outputlangs = new Translate();
  2581. $outputlangs->setDefaultLang($newlang);
  2582. }
  2583. $result = facture_pdf_create($db, $object, GETPOST('model') ? GETPOST('model') : $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  2584. if ($result <= 0) {
  2585. dol_print_error($db, $result);
  2586. exit;
  2587. }
  2588. $fileparams = dol_most_recent_file($conf->facture->dir_output . '/' . $ref);
  2589. $file = $fileparams['fullname'];
  2590. }
  2591. print '<br>';
  2592. print_titre($langs->trans($titreform));
  2593. // Cree l'objet formulaire mail
  2594. include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
  2595. $formmail = new FormMail($db);
  2596. $formmail->fromtype = 'user';
  2597. $formmail->fromid = $user->id;
  2598. $formmail->fromname = $user->getFullName($langs);
  2599. $formmail->frommail = $user->email;
  2600. $formmail->withfrom = 1;
  2601. $formmail->withto = empty($_POST["sendto"]) ? 1 : $_POST["sendto"];
  2602. $formmail->withtosocid = $soc->id;
  2603. $formmail->withtocc = 1;
  2604. $formmail->withtoccsocid = 0;
  2605. $formmail->withtoccc = $conf->global->MAIN_EMAIL_USECCC;
  2606. $formmail->withtocccsocid = 0;
  2607. $formmail->withtopic = $langs->transnoentities($topicmail, '__FACREF__');
  2608. $formmail->withfile = 2;
  2609. $formmail->withbody = 1;
  2610. $formmail->withdeliveryreceipt = 1;
  2611. $formmail->withcancel = 1;
  2612. // Tableau des substitutions
  2613. $formmail->substit['__FACREF__'] = $object->ref;
  2614. $formmail->substit['__SIGNATURE__'] = $user->signature;
  2615. $formmail->substit['__PERSONALIZED__'] = '';
  2616. // Tableau des parametres complementaires du post
  2617. $formmail->param['action'] = $action;
  2618. $formmail->param['models'] = $modelmail;
  2619. $formmail->param['facid'] = $object->id;
  2620. $formmail->param['returnurl'] = $_SERVER["PHP_SELF"] . '?id=' . $object->id;
  2621. // Init list of files
  2622. if (GETPOST("mode") == 'init') {
  2623. $formmail->clear_attached_files();
  2624. $formmail->add_attached_files($file, basename($file), dol_mimetype($file));
  2625. }
  2626. $formmail->show_form();
  2627. print '<br>';
  2628. }
  2629. } else {
  2630. dol_print_error($db, $object->error);
  2631. }
  2632. }
  2633. print end_box();
  2634. print '</div>';
  2635. dol_htmloutput_mesg('', $mesgs);
  2636. llxFooter();
  2637. $db->close();
  2638. ?>