PageRenderTime 50ms CodeModel.GetById 11ms 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

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /* Copyright (C) 2002-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
  4. * Copyright (C) 2004-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 l…

Large files files are truncated, but you can click here to view the full file