invoice.php 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411
  1. <?php
  2. /**
  3. * Copyright (C) 2018 Andreu Bisquerra <jove@bisquerra.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. /**
  19. * \file htdocs/takepos/invoice.php
  20. * \ingroup takepos
  21. * \brief Page to generate section with list of lines
  22. */
  23. // if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Not disabled cause need to load personalized language
  24. // if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Not disabled cause need to load personalized language
  25. // if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1');
  26. // if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1');
  27. if (!defined('NOCSRFCHECK')) { define('NOCSRFCHECK', '1'); }
  28. if (!defined('NOTOKENRENEWAL')) { define('NOTOKENRENEWAL', '1'); }
  29. if (!defined('NOREQUIREMENU')) { define('NOREQUIREMENU', '1'); }
  30. if (!defined('NOREQUIREHTML')) { define('NOREQUIREHTML', '1'); }
  31. if (!defined('NOREQUIREAJAX')) { define('NOREQUIREAJAX', '1'); }
  32. if (!defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) require '../main.inc.php';
  33. require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
  34. require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
  35. require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
  36. global $mysoc;
  37. $langs->loadLangs(array("companies", "commercial", "bills", "cashdesk", "stocks", "banks"));
  38. $id = GETPOST('id', 'int');
  39. $action = GETPOST('action', 'aZ09');
  40. $idproduct = GETPOST('idproduct', 'int');
  41. $place = (GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : 0); // $place is id of table for Bar or Restaurant
  42. $placeid = 0; // $placeid is ID of invoice
  43. // Terminal is stored into $_SESSION["takeposterminal"];
  44. if (empty($user->rights->takepos->run) && !defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
  45. accessforbidden();
  46. }
  47. /*
  48. * View
  49. */
  50. if (($conf->global->TAKEPOS_PHONE_BASIC_LAYOUT == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))
  51. {
  52. // DIRECT LINK TO THIS PAGE FROM MOBILE AND NO TERMINAL SELECTED
  53. if ($_SESSION["takeposterminal"] == "")
  54. {
  55. if ($conf->global->TAKEPOS_NUM_TERMINALS == "1") $_SESSION["takeposterminal"] = 1;
  56. else {
  57. header("Location: ".DOL_URL_ROOT."/takepos/index.php");
  58. exit;
  59. }
  60. }
  61. $mobilepage = GETPOST('mobilepage', 'alpha');
  62. $title = 'TakePOS - Dolibarr '.DOL_VERSION;
  63. if (!empty($conf->global->MAIN_APPLICATION_TITLE)) $title = 'TakePOS - '.$conf->global->MAIN_APPLICATION_TITLE;
  64. $head = '<meta name="apple-mobile-web-app-title" content="TakePOS"/>
  65. <meta name="apple-mobile-web-app-capable" content="yes">
  66. <meta name="mobile-web-app-capable" content="yes">
  67. <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>';
  68. $arrayofcss = array(
  69. '/takepos/css/pos.css.php',
  70. '/takepos/js/jquery.colorbox-min.js'
  71. );
  72. $arrayofjs = array('/takepos/js/jquery.colorbox-min.js');
  73. top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
  74. }
  75. /**
  76. * Abort invoice creationg with a given error message
  77. *
  78. * @param string $message Message explaining the error to the user
  79. * @return void
  80. */
  81. function fail($message)
  82. {
  83. header($_SERVER['SERVER_PROTOCOL'].' 500 Internal Server Error', true, 500);
  84. die($message);
  85. }
  86. $number = GETPOST('number', 'alpha');
  87. $idline = GETPOST('idline', 'int');
  88. $selectedline = GETPOST('selectedline', 'int');
  89. $desc = GETPOST('desc', 'alphanohtml');
  90. $pay = GETPOST('pay', 'aZ09');
  91. $amountofpayment = price2num(GETPOST('amount', 'alpha'));
  92. $invoiceid = GETPOST('invoiceid', 'int');
  93. $paycode = $pay;
  94. if ($pay == 'cash') $paycode = 'LIQ'; // For backward compatibility
  95. if ($pay == 'card') $paycode = 'CB'; // For backward compatibility
  96. if ($pay == 'cheque') $paycode = 'CHQ'; // For backward compatibility
  97. // Retrieve paiementid
  98. $sql = "SELECT id FROM ".MAIN_DB_PREFIX."c_paiement";
  99. $sql .= " WHERE entity IN (".getEntity('c_paiement').")";
  100. $sql .= " AND code = '".$db->escape($paycode)."'";
  101. $resql = $db->query($sql);
  102. $obj = $db->fetch_object($resql);
  103. $paiementid = $obj->id;
  104. $invoice = new Facture($db);
  105. if ($invoiceid > 0)
  106. {
  107. $ret = $invoice->fetch($invoiceid);
  108. } else {
  109. $ret = $invoice->fetch('', '(PROV-POS'.$_SESSION["takeposterminal"].'-'.$place.')');
  110. }
  111. if ($ret > 0)
  112. {
  113. $placeid = $invoice->id;
  114. }
  115. $constforcompanyid = 'CASHDESK_ID_THIRDPARTY'.$_SESSION["takeposterminal"];
  116. $soc = new Societe($db);
  117. if ($invoice->socid > 0) $soc->fetch($invoice->socid);
  118. else $soc->fetch($conf->global->$constforcompanyid);
  119. /*
  120. * Actions
  121. */
  122. // Action to record a payment on a TakePOS invoice
  123. if ($action == 'valid' && $user->rights->facture->creer)
  124. {
  125. $bankaccount = 0;
  126. $error = 0;
  127. if (!empty($conf->global->TAKEPOS_CAN_FORCE_BANK_ACCOUNT_DURING_PAYMENT)) {
  128. $bankaccount = GETPOST('accountid', 'int');
  129. } else {
  130. if ($pay == "cash") $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CASH'.$_SESSION["takeposterminal"]}; // For backward compatibility
  131. elseif ($pay == "card") $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CB'.$_SESSION["takeposterminal"]}; // For backward compatibility
  132. elseif ($pay == "cheque") $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CHEQUE'.$_SESSION["takeposterminal"]}; // For backward compatibility
  133. else {
  134. $accountname = "CASHDESK_ID_BANKACCOUNT_".$pay.$_SESSION["takeposterminal"];
  135. $bankaccount = $conf->global->$accountname;
  136. }
  137. }
  138. if ($bankaccount <= 0 && $pay != "delayed") {
  139. $errormsg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankAccount"));
  140. $error++;
  141. }
  142. $now = dol_now();
  143. $res = 0;
  144. $invoice = new Facture($db);
  145. $invoice->fetch($placeid);
  146. if ($invoice->total_ttc < 0) {
  147. $invoice->type = $invoice::TYPE_CREDIT_NOTE;
  148. $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture WHERE";
  149. $sql .= " fk_soc = ".((int) $invoice->socid);
  150. $sql .= " AND type <> ".Facture::TYPE_CREDIT_NOTE;
  151. $sql .= " AND fk_statut >= ".$invoice::STATUS_VALIDATED;
  152. $sql .= " ORDER BY rowid DESC";
  153. $resql = $db->query($sql);
  154. if ($resql) {
  155. $obj = $db->fetch_object($resql);
  156. $fk_source = $obj->rowid;
  157. if ($fk_source == null) {
  158. fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer"));
  159. }
  160. } else {
  161. fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer"));
  162. }
  163. $invoice->fk_facture_source = $fk_source;
  164. $invoice->update($user);
  165. }
  166. //$sav_FACTURE_ADDON = '';
  167. //if (!empty($conf->global->TAKEPOS_ADDON)) {
  168. // $sav_FACTURE_ADDON = $conf->global->FACTURE_ADDON;
  169. // if ($conf->global->TAKEPOS_ADDON == "terminal") $conf->global->FACTURE_ADDON = $conf->global->{'TAKEPOS_ADDON'.$_SESSION["takeposterminal"]};
  170. // else $conf->global->FACTURE_ADDON = $conf->global->TAKEPOS_ADDON;
  171. //}
  172. $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"];
  173. if ($error) {
  174. dol_htmloutput_errors($errormsg, null, 1);
  175. } elseif ($invoice->statut != Facture::STATUS_DRAFT) {
  176. //If invoice is validated but it is not fully paid is not error and make the payment
  177. if ($invoice->getRemainToPay() > 0) {
  178. $res = 1;
  179. } else {
  180. dol_syslog("Sale already validated");
  181. dol_htmloutput_errors($langs->trans("InvoiceIsAlreadyValidated", "TakePos"), null, 1);
  182. }
  183. } elseif (count($invoice->lines) == 0) {
  184. $error++;
  185. dol_syslog('Sale without lines');
  186. dol_htmloutput_errors($langs->trans("NoLinesToBill", "TakePos"), null, 1);
  187. } elseif (!empty($conf->stock->enabled) && $conf->global->$constantforkey != "1") {
  188. $savconst = $conf->global->STOCK_CALCULATE_ON_BILL;
  189. $conf->global->STOCK_CALCULATE_ON_BILL = 1;
  190. $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
  191. dol_syslog("Validate invoice with stock change into warehouse defined into constant ".$constantforkey." = ".$conf->global->$constantforkey);
  192. $batch_rule = 0;
  193. if (!empty($conf->productbatch->enabled) && !empty($conf->global->CASHDESK_FORCE_DECREASE_STOCK)) {
  194. require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
  195. $batch_rule = Productbatch::BATCH_RULE_SELLBY_EATBY_DATES_FIRST;
  196. }
  197. $res = $invoice->validate($user, '', $conf->global->$constantforkey, 0, $batch_rule);
  198. $conf->global->STOCK_CALCULATE_ON_BILL = $savconst;
  199. } else {
  200. $res = $invoice->validate($user);
  201. if ($res < 0) {
  202. $error++;
  203. dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
  204. }
  205. }
  206. // Restore save values
  207. //if (!empty($sav_FACTURE_ADDON))
  208. //{
  209. // $conf->global->FACTURE_ADDON = $sav_FACTURE_ADDON;
  210. //}
  211. // Add the payment
  212. if (!$error && $res >= 0) {
  213. $remaintopay = $invoice->getRemainToPay();
  214. if ($remaintopay > 0) {
  215. $payment = new Paiement($db);
  216. $payment->datepaye = $now;
  217. $payment->fk_account = $bankaccount;
  218. $payment->amounts[$invoice->id] = $amountofpayment;
  219. if ($pay == 'cash') $payment->pos_change = price2num(GETPOST('excess', 'alpha'));
  220. // If user has not used change control, add total invoice payment
  221. // Or if user has used change control and the amount of payment is higher than remain to pay, add the remain to pay
  222. if ($amountofpayment == 0 || $amountofpayment > $remaintopay) $payment->amounts[$invoice->id] = $remaintopay;
  223. $payment->paiementid = $paiementid;
  224. $payment->num_payment = $invoice->ref;
  225. if ($pay != "delayed") {
  226. $payment->create($user);
  227. $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', '');
  228. $remaintopay = $invoice->getRemainToPay(); // Recalculate remain to pay after the payment is recorded
  229. }
  230. }
  231. if ($remaintopay == 0) {
  232. dol_syslog("Invoice is paid, so we set it to status Paid");
  233. $result = $invoice->setPaid($user);
  234. if ($result > 0) $invoice->paye = 1;
  235. // set payment method
  236. $invoice->setPaymentMethods($paiementid);
  237. } else {
  238. dol_syslog("Invoice is not paid, remain to pay = ".$remaintopay);
  239. }
  240. } else {
  241. dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
  242. }
  243. }
  244. if ($action == 'creditnote')
  245. {
  246. $creditnote = new Facture($db);
  247. $creditnote->socid = $invoice->socid;
  248. $creditnote->date = dol_now();
  249. $creditnote->type = Facture::TYPE_CREDIT_NOTE;
  250. $creditnote->fk_facture_source = $placeid;
  251. $creditnote->remise_absolue = $invoice->remise_absolue;
  252. $creditnote->remise_percent = $invoice->remise_percent;
  253. $creditnote->create($user);
  254. foreach ($invoice->lines as $line)
  255. {
  256. // Extrafields
  257. if (method_exists($line, 'fetch_optionals')) {
  258. // load extrafields
  259. $line->fetch_optionals();
  260. }
  261. // Reset fk_parent_line for no child products and special product
  262. if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
  263. $fk_parent_line = 0;
  264. }
  265. if ($invoice->type == Facture::TYPE_SITUATION)
  266. {
  267. $source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id
  268. $line->fk_prev_id = $line->id; // The new line of the new credit note we are creating must be linked to the situation invoice line it is created from
  269. if (!empty($invoice->tab_previous_situation_invoice))
  270. {
  271. // search the last standard invoice in cycle and the possible credit note between this last and invoice
  272. // TODO Move this out of loop of $invoice->lines
  273. $tab_jumped_credit_notes = array();
  274. $lineIndex = count($invoice->tab_previous_situation_invoice) - 1;
  275. $searchPreviousInvoice = true;
  276. while ($searchPreviousInvoice)
  277. {
  278. if ($invoice->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_SITUATION || $lineIndex < 1)
  279. {
  280. $searchPreviousInvoice = false; // find, exit;
  281. break;
  282. } else {
  283. if ($invoice->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_CREDIT_NOTE) {
  284. $tab_jumped_credit_notes[$lineIndex] = $invoice->tab_previous_situation_invoice[$lineIndex]->id;
  285. }
  286. $lineIndex--; // go to previous invoice in cycle
  287. }
  288. }
  289. $maxPrevSituationPercent = 0;
  290. foreach ($invoice->tab_previous_situation_invoice[$lineIndex]->lines as $prevLine)
  291. {
  292. if ($prevLine->id == $source_fk_prev_id)
  293. {
  294. $maxPrevSituationPercent = max($maxPrevSituationPercent, $prevLine->situation_percent);
  295. //$line->subprice = $line->subprice - $prevLine->subprice;
  296. $line->total_ht = $line->total_ht - $prevLine->total_ht;
  297. $line->total_tva = $line->total_tva - $prevLine->total_tva;
  298. $line->total_ttc = $line->total_ttc - $prevLine->total_ttc;
  299. $line->total_localtax1 = $line->total_localtax1 - $prevLine->total_localtax1;
  300. $line->total_localtax2 = $line->total_localtax2 - $prevLine->total_localtax2;
  301. $line->multicurrency_subprice = $line->multicurrency_subprice - $prevLine->multicurrency_subprice;
  302. $line->multicurrency_total_ht = $line->multicurrency_total_ht - $prevLine->multicurrency_total_ht;
  303. $line->multicurrency_total_tva = $line->multicurrency_total_tva - $prevLine->multicurrency_total_tva;
  304. $line->multicurrency_total_ttc = $line->multicurrency_total_ttc - $prevLine->multicurrency_total_ttc;
  305. }
  306. }
  307. // prorata
  308. $line->situation_percent = $maxPrevSituationPercent - $line->situation_percent;
  309. //print 'New line based on invoice id '.$invoice->tab_previous_situation_invoice[$lineIndex]->id.' fk_prev_id='.$source_fk_prev_id.' will be fk_prev_id='.$line->fk_prev_id.' '.$line->total_ht.' '.$line->situation_percent.'<br>';
  310. // If there is some credit note between last situation invoice and invoice used for credit note generation (note: credit notes are stored as delta)
  311. $maxPrevSituationPercent = 0;
  312. foreach ($tab_jumped_credit_notes as $index => $creditnoteid) {
  313. foreach ($invoice->tab_previous_situation_invoice[$index]->lines as $prevLine)
  314. {
  315. if ($prevLine->fk_prev_id == $source_fk_prev_id)
  316. {
  317. $maxPrevSituationPercent = $prevLine->situation_percent;
  318. $line->total_ht -= $prevLine->total_ht;
  319. $line->total_tva -= $prevLine->total_tva;
  320. $line->total_ttc -= $prevLine->total_ttc;
  321. $line->total_localtax1 -= $prevLine->total_localtax1;
  322. $line->total_localtax2 -= $prevLine->total_localtax2;
  323. $line->multicurrency_subprice -= $prevLine->multicurrency_subprice;
  324. $line->multicurrency_total_ht -= $prevLine->multicurrency_total_ht;
  325. $line->multicurrency_total_tva -= $prevLine->multicurrency_total_tva;
  326. $line->multicurrency_total_ttc -= $prevLine->multicurrency_total_ttc;
  327. }
  328. }
  329. }
  330. // prorata
  331. $line->situation_percent += $maxPrevSituationPercent;
  332. //print 'New line based on invoice id '.$invoice->tab_previous_situation_invoice[$lineIndex]->id.' fk_prev_id='.$source_fk_prev_id.' will be fk_prev_id='.$line->fk_prev_id.' '.$line->total_ht.' '.$line->situation_percent.'<br>';
  333. }
  334. }
  335. $line->fk_facture = $creditnote->id;
  336. $line->fk_parent_line = $fk_parent_line;
  337. $line->subprice = -$line->subprice; // invert price for object
  338. $line->pa_ht = $line->pa_ht; // we choosed to have buy/cost price always positive, so no revert of sign here
  339. $line->total_ht = -$line->total_ht;
  340. $line->total_tva = -$line->total_tva;
  341. $line->total_ttc = -$line->total_ttc;
  342. $line->total_localtax1 = -$line->total_localtax1;
  343. $line->total_localtax2 = -$line->total_localtax2;
  344. $line->multicurrency_subprice = -$line->multicurrency_subprice;
  345. $line->multicurrency_total_ht = -$line->multicurrency_total_ht;
  346. $line->multicurrency_total_tva = -$line->multicurrency_total_tva;
  347. $line->multicurrency_total_ttc = -$line->multicurrency_total_ttc;
  348. $result = $line->insert(0, 1); // When creating credit note with same lines than source, we must ignore error if discount alreayd linked
  349. $creditnote->lines[] = $line; // insert new line in current object
  350. // Defined the new fk_parent_line
  351. if ($result > 0 && $line->product_type == 9) {
  352. $fk_parent_line = $result;
  353. }
  354. }
  355. $creditnote->update_price(1);
  356. $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"];
  357. if (!empty($conf->stock->enabled) && $conf->global->$constantforkey != "1") {
  358. $savconst = $conf->global->STOCK_CALCULATE_ON_BILL;
  359. $conf->global->STOCK_CALCULATE_ON_BILL = 1;
  360. $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
  361. dol_syslog("Validate invoice with stock change into warehouse defined into constant ".$constantforkey." = ".$conf->global->$constantforkey);
  362. $batch_rule = 0;
  363. if (!empty($conf->productbatch->enabled) && !empty($conf->global->CASHDESK_FORCE_DECREASE_STOCK)) {
  364. require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
  365. $batch_rule = Productbatch::BATCH_RULE_SELLBY_EATBY_DATES_FIRST;
  366. }
  367. $res = $creditnote->validate($user, '', $conf->global->$constantforkey, 0, $batch_rule);
  368. $conf->global->STOCK_CALCULATE_ON_BILL = $savconst;
  369. } else {
  370. $res = $creditnote->validate($user);
  371. }
  372. }
  373. if ($action == 'history' || $action == 'creditnote')
  374. {
  375. if ($action == 'creditnote') $placeid = $creditnote->id;
  376. else $placeid = (int) GETPOST('placeid', 'int');
  377. $invoice = new Facture($db);
  378. $invoice->fetch($placeid);
  379. }
  380. if (!empty($conf->multicurrency->enabled) && $_SESSION["takeposcustomercurrency"] != "") {
  381. $invoice->setMulticurrencyCode($_SESSION["takeposcustomercurrency"]);
  382. }
  383. if (($action == "addline" || $action == "freezone") && $placeid == 0)
  384. {
  385. $invoice->socid = $conf->global->$constforcompanyid;
  386. $invoice->date = dol_now();
  387. $invoice->module_source = 'takepos';
  388. $invoice->pos_source = $_SESSION["takeposterminal"];
  389. $invoice->entity = !empty($_SESSION["takeposinvoiceentity"]) ? $_SESSION["takeposinvoiceentity"] : $conf->entity;
  390. if ($invoice->socid <= 0)
  391. {
  392. $langs->load('errors');
  393. dol_htmloutput_errors($langs->trans("ErrorModuleSetupNotComplete", "TakePos"), null, 1);
  394. } else {
  395. $placeid = $invoice->create($user);
  396. if ($placeid < 0)
  397. {
  398. dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
  399. }
  400. $sql = "UPDATE ".MAIN_DB_PREFIX."facture set ref='(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")' where rowid=".$placeid;
  401. $db->query($sql);
  402. }
  403. }
  404. if ($action == "addline")
  405. {
  406. $prod = new Product($db);
  407. $prod->fetch($idproduct);
  408. $customer = new Societe($db);
  409. $customer->fetch($invoice->socid);
  410. $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
  411. $price = $datapriceofproduct['pu_ht'];
  412. $price_ttc = $datapriceofproduct['pu_ttc'];
  413. //$price_min = $datapriceofproduct['price_min'];
  414. $price_base_type = $datapriceofproduct['price_base_type'];
  415. $tva_tx = $datapriceofproduct['tva_tx'];
  416. $tva_npr = $datapriceofproduct['tva_npr'];
  417. // Local Taxes
  418. $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
  419. $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
  420. if (!empty($conf->global->TAKEPOS_SUPPLEMENTS))
  421. {
  422. require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
  423. $cat = new Categorie($db);
  424. $categories = $cat->containing($idproduct, 'product');
  425. $found = (array_search($conf->global->TAKEPOS_SUPPLEMENTS_CATEGORY, array_column($categories, 'id')));
  426. if ($found !== false) // If this product is a supplement
  427. {
  428. $sql = "SELECT fk_parent_line FROM ".MAIN_DB_PREFIX."facturedet where rowid=$selectedline";
  429. $resql = $db->query($sql);
  430. $row = $db->fetch_array($resql);
  431. if ($row[0] == null) $parent_line = $selectedline;
  432. else $parent_line = $row[0]; //If the parent line is already a supplement, add the supplement to the main product
  433. }
  434. }
  435. $idoflineadded = 0;
  436. if (!empty($conf->global->TAKEPOS_GROUP_SAME_PRODUCT)) {
  437. foreach ($invoice->lines as $line) {
  438. if ($line->product_ref == $prod->ref) {
  439. $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty + 1, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
  440. if ($result < 0) {
  441. dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
  442. } else {
  443. $idoflineadded = $line->id;
  444. }
  445. break;
  446. }
  447. }
  448. }
  449. if ($idoflineadded <= 0) {
  450. $invoice->fetch_thirdparty();
  451. $idoflineadded = $invoice->addline($prod->description, $price, 1, $tva_tx, $localtax1_tx, $localtax2_tx, $idproduct, $customer->remise_percent, '', 0, 0, 0, '', $price_base_type, $price_ttc, $prod->type, -1, 0, '', 0, $parent_line, null, '', '', 0, 100, '', null, 0);
  452. }
  453. $invoice->fetch($placeid);
  454. }
  455. if ($action == "freezone") {
  456. $customer = new Societe($db);
  457. $customer->fetch($invoice->socid);
  458. $tva_tx = GETPOST('tva_tx', 'alpha');
  459. if ($tva_tx != '') {
  460. $tva_tx = price2num($tva_tx);
  461. } else {
  462. $tva_tx = get_default_tva($mysoc, $customer);
  463. }
  464. // Local Taxes
  465. $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
  466. $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
  467. $invoice->addline($desc, $number, 1, $tva_tx, $localtax1_tx, $localtax2_tx, 0, 0, '', 0, 0, 0, '', 'TTC', $number, 0, -1, 0, '', 0, 0, null, '', '', 0, 100, '', null, 0);
  468. $invoice->fetch($placeid);
  469. }
  470. if ($action == "addnote") {
  471. foreach ($invoice->lines as $line)
  472. {
  473. if ($line->id == $number)
  474. {
  475. $line->array_options['order_notes'] = $desc;
  476. $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
  477. }
  478. }
  479. $invoice->fetch($placeid);
  480. }
  481. if ($action == "deleteline") {
  482. if ($idline > 0 and $placeid > 0) { // If invoice exists and line selected. To avoid errors if deleted from another device or no line selected.
  483. $invoice->deleteline($idline);
  484. $invoice->fetch($placeid);
  485. } elseif ($placeid > 0) { // If invoice exists but no line selected, proceed to delete last line.
  486. $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facturedet where fk_facture = ".((int) $placeid)." ORDER BY rowid DESC";
  487. $resql = $db->query($sql);
  488. $row = $db->fetch_array($resql);
  489. $deletelineid = $row[0];
  490. $invoice->deleteline($deletelineid);
  491. $invoice->fetch($placeid);
  492. }
  493. if (count($invoice->lines) == 0) {
  494. $invoice->delete($user);
  495. header("Location: ".DOL_URL_ROOT."/takepos/invoice.php");
  496. exit;
  497. }
  498. }
  499. // Action to delete or discard an invoice
  500. if ($action == "delete") {
  501. // $placeid is the invoice id (it differs from place) and is defined if the place is set and the ref of invoice is '(PROV-POS'.$_SESSION["takeposterminal"].'-'.$place.')', so the fetch at begining of page works.
  502. if ($placeid > 0) {
  503. $result = $invoice->fetch($placeid);
  504. if ($result > 0 && $invoice->statut == Facture::STATUS_DRAFT)
  505. {
  506. $db->begin();
  507. // We delete the lines
  508. $resdeletelines = 1;
  509. foreach ($invoice->lines as $line) {
  510. $tmpres = $invoice->deleteline($line->id);
  511. if ($tmpres < 0) {
  512. $resdeletelines = 0;
  513. break;
  514. }
  515. }
  516. $sql = "UPDATE ".MAIN_DB_PREFIX."facture";
  517. $sql .= " SET fk_soc=".$conf->global->{'CASHDESK_ID_THIRDPARTY'.$_SESSION["takeposterminal"]}.", ";
  518. $sql .= " datec = '".$db->idate(dol_now())."'";
  519. $sql .= " WHERE ref='(PROV-POS".$db->escape($_SESSION["takeposterminal"]."-".$place).")'";
  520. $resql1 = $db->query($sql);
  521. if ($resdeletelines && $resql1) {
  522. $db->commit();
  523. } else {
  524. $db->rollback();
  525. }
  526. $invoice->fetch($placeid);
  527. }
  528. }
  529. }
  530. if ($action == "updateqty")
  531. {
  532. foreach ($invoice->lines as $line)
  533. {
  534. if ($line->id == $idline)
  535. {
  536. $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $number, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
  537. }
  538. }
  539. $invoice->fetch($placeid);
  540. }
  541. if ($action == "updateprice")
  542. {
  543. foreach ($invoice->lines as $line)
  544. {
  545. if ($line->id == $idline)
  546. {
  547. $prod = new Product($db);
  548. $prod->fetch($line->fk_product);
  549. $customer = new Societe($db);
  550. $customer->fetch($invoice->socid);
  551. $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
  552. $price_min = $datapriceofproduct['price_min'];
  553. $usercanproductignorepricemin = ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS));
  554. $pu_ht = price2num($number / (1 + ($line->tva_tx / 100)), 'MU');
  555. //Check min price
  556. if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($pu_ht) * (1 - price2num($line->remise_percent) / 100) < price2num($price_min))))
  557. {
  558. echo $langs->trans("CantBeLessThanMinPrice");
  559. } else $result = $invoice->updateline($line->id, $line->desc, $number, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'TTC', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
  560. }
  561. }
  562. $invoice->fetch($placeid);
  563. }
  564. if ($action == "updatereduction")
  565. {
  566. foreach ($invoice->lines as $line)
  567. {
  568. if ($line->id == $idline)
  569. {
  570. $prod = new Product($db);
  571. $prod->fetch($line->fk_product);
  572. $customer = new Societe($db);
  573. $customer->fetch($invoice->socid);
  574. $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
  575. $price_min = $datapriceofproduct['price_min'];
  576. $usercanproductignorepricemin = ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS));
  577. $pu_ht = price2num($line->multicurrency_subprice / (1 + ($line->tva_tx / 100)), 'MU');
  578. //Check min price
  579. if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($line->multicurrency_subprice) * (1 - price2num($number) / 100) < price2num($price_min))))
  580. {
  581. echo $langs->trans("CantBeLessThanMinPrice");
  582. } else $result = $invoice->updateline($line->id, $line->desc, $line->multicurrency_subprice, $line->qty, $number, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
  583. }
  584. }
  585. $invoice->fetch($placeid);
  586. } elseif ($action == 'update_reduction_global') {
  587. foreach ($invoice->lines as $line) {
  588. $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $number, $line->date_start, $line->date_end, $line->tva_tx, $line->localtax1_tx, $line->localtax2_tx, 'HT', $line->info_bits, $line->product_type, $line->fk_parent_line, 0, $line->fk_fournprice, $line->pa_ht, $line->label, $line->special_code, $line->array_options, $line->situation_percent, $line->fk_unit);
  589. }
  590. $invoice->fetch($placeid);
  591. }
  592. if ($action == "order" and $placeid != 0)
  593. {
  594. include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
  595. if ($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") {
  596. require_once DOL_DOCUMENT_ROOT.'/core/class/dolreceiptprinter.class.php';
  597. $printer = new dolReceiptPrinter($db);
  598. }
  599. $sql = "SELECT label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place);
  600. $resql = $db->query($sql);
  601. $row = $db->fetch_object($resql);
  602. $headerorder = '<html><br><b>'.$langs->trans('Place').' '.$row->label.'<br><table width="65%"><thead><tr><th class="left">'.$langs->trans("Label").'</th><th class="right">'.$langs->trans("Qty").'</th></tr></thead><tbody>';
  603. $footerorder = '</tbody></table>'.dol_print_date(dol_now(), 'dayhour').'<br></html>';
  604. $order_receipt_printer1 = "";
  605. $order_receipt_printer2 = "";
  606. $order_receipt_printer3 = "";
  607. $catsprinter1 = explode(';', $conf->global->TAKEPOS_PRINTED_CATEGORIES_1);
  608. $catsprinter2 = explode(';', $conf->global->TAKEPOS_PRINTED_CATEGORIES_2);
  609. $catsprinter3 = explode(';', $conf->global->TAKEPOS_PRINTED_CATEGORIES_3);
  610. foreach ($invoice->lines as $line)
  611. {
  612. if ($line->special_code == "4") {
  613. continue;
  614. }
  615. $c = new Categorie($db);
  616. $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
  617. $result = array_intersect($catsprinter1, $existing);
  618. $count = count($result);
  619. if (!$line->fk_product) $count++; // Print Free-text item (Unassigned printer) to Printer 1
  620. if ($count > 0) {
  621. $linestoprint++;
  622. $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='1' where rowid=".$line->id; //Set to print on printer 1
  623. $db->query($sql);
  624. $order_receipt_printer1 .= '<tr><td class="left">';
  625. if ($line->fk_product) $order_receipt_printer1 .= $line->product_label;
  626. else $order_receipt_printer1 .= $line->description;
  627. $order_receipt_printer1 .= '</td><td class="right">'.$line->qty;
  628. if (!empty($line->array_options['options_order_notes'])) $order_receipt_printer1 .= "<br>(".$line->array_options['options_order_notes'].")";
  629. $order_receipt_printer1 .= '</td></tr>';
  630. }
  631. }
  632. if (($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") && $linestoprint > 0) {
  633. $invoice->fetch($placeid); //Reload object before send to printer
  634. $printer->orderprinter = 1;
  635. echo "<script>";
  636. echo "var orderprinter1esc='";
  637. $ret = $printer->sendToPrinter($invoice, $conf->global->{'TAKEPOS_TEMPLATE_TO_USE_FOR_ORDERS'.$_SESSION["takeposterminal"]}, $conf->global->{'TAKEPOS_ORDER_PRINTER1_TO_USE'.$_SESSION["takeposterminal"]}); // PRINT TO PRINTER 1
  638. echo "';</script>";
  639. }
  640. $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='1' and fk_facture=".$invoice->id; // Set as printed
  641. $db->query($sql);
  642. $invoice->fetch($placeid); //Reload object after set lines as printed
  643. $linestoprint = 0;
  644. foreach ($invoice->lines as $line)
  645. {
  646. if ($line->special_code == "4") {
  647. continue;
  648. }
  649. $c = new Categorie($db);
  650. $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
  651. $result = array_intersect($catsprinter2, $existing);
  652. $count = count($result);
  653. if ($count > 0) {
  654. $linestoprint++;
  655. $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='2' where rowid=".$line->id; //Set to print on printer 2
  656. $db->query($sql);
  657. $order_receipt_printer2 .= '<tr>'.$line->product_label.'<td class="right">'.$line->qty;
  658. if (!empty($line->array_options['options_order_notes'])) $order_receipt_printer2 .= "<br>(".$line->array_options['options_order_notes'].")";
  659. $order_receipt_printer2 .= '</td></tr>';
  660. }
  661. }
  662. if (($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") && $linestoprint > 0) {
  663. $invoice->fetch($placeid); //Reload object before send to printer
  664. $printer->orderprinter = 2;
  665. echo "<script>";
  666. echo "var orderprinter2esc='";
  667. $ret = $printer->sendToPrinter($invoice, $conf->global->{'TAKEPOS_TEMPLATE_TO_USE_FOR_ORDERS'.$_SESSION["takeposterminal"]}, $conf->global->{'TAKEPOS_ORDER_PRINTER2_TO_USE'.$_SESSION["takeposterminal"]}); // PRINT TO PRINTER 2
  668. echo "';</script>";
  669. }
  670. $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='2' and fk_facture=".$invoice->id; // Set as printed
  671. $db->query($sql);
  672. $invoice->fetch($placeid); //Reload object after set lines as printed
  673. $linestoprint = 0;
  674. foreach ($invoice->lines as $line)
  675. {
  676. if ($line->special_code == "4") {
  677. continue;
  678. }
  679. $c = new Categorie($db);
  680. $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
  681. $result = array_intersect($catsprinter3, $existing);
  682. $count = count($result);
  683. if ($count > 0) {
  684. $linestoprint++;
  685. $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='3' where rowid=".$line->id; //Set to print on printer 3
  686. $db->query($sql);
  687. $order_receipt_printer3 .= '<tr>'.$line->product_label.'<td class="right">'.$line->qty;
  688. if (!empty($line->array_options['options_order_notes'])) $order_receipt_printer3 .= "<br>(".$line->array_options['options_order_notes'].")";
  689. $order_receipt_printer3 .= '</td></tr>';
  690. }
  691. }
  692. if (($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") && $linestoprint > 0) {
  693. $invoice->fetch($placeid); //Reload object before send to printer
  694. $printer->orderprinter = 3;
  695. echo "<script>";
  696. echo "var orderprinter3esc='";
  697. $ret = $printer->sendToPrinter($invoice, $conf->global->{'TAKEPOS_TEMPLATE_TO_USE_FOR_ORDERS'.$_SESSION["takeposterminal"]}, $conf->global->{'TAKEPOS_ORDER_PRINTER3_TO_USE'.$_SESSION["takeposterminal"]}); // PRINT TO PRINTER 3
  698. echo "';</script>";
  699. }
  700. $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='3' and fk_facture=".$invoice->id; // Set as printed
  701. $db->query($sql);
  702. $invoice->fetch($placeid); //Reload object after set lines as printed
  703. }
  704. $sectionwithinvoicelink = '';
  705. if ($action == "valid" || $action == "history" || $action == 'creditnote')
  706. {
  707. $sectionwithinvoicelink .= '<!-- Section with invoice link -->'."\n";
  708. $sectionwithinvoicelink .= '<span style="font-size:120%;" class="center">';
  709. $sectionwithinvoicelink .= $invoice->getNomUrl(1, '', 0, 0, '', 0, 0, -1, '_backoffice')." - ";
  710. $remaintopay = $invoice->getRemainToPay();
  711. if ($remaintopay > 0)
  712. {
  713. $sectionwithinvoicelink .= $langs->trans('RemainToPay').': <span class="amountremaintopay" style="font-size: unset">'.price($remaintopay, 1, $langs, 1, -1, -1, $conf->currency).'</span>';
  714. } else {
  715. if ($invoice->paye) $sectionwithinvoicelink .= '<span class="amountpaymentcomplete" style="font-size: unset">'.$langs->trans("Paid").'</span>';
  716. else $sectionwithinvoicelink .= $langs->trans('BillShortStatusValidated');
  717. }
  718. $sectionwithinvoicelink .= '</span><br>';
  719. if ($conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") {
  720. if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposConnector('.$placeid.');">'.$langs->trans('PrintTicket').'</button>';
  721. else $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposPrinting('.$placeid.');">'.$langs->trans('PrintTicket').'</button>';
  722. } elseif ($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter") {
  723. $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="DolibarrTakeposPrinting('.$placeid.');">'.$langs->trans('PrintTicket').'</button>';
  724. } else {
  725. $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print('.$placeid.');">'.$langs->trans('PrintTicket').'</button>';
  726. if ($conf->global->TAKEPOS_GIFT_RECEIPT) {
  727. $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print('.$placeid.', 1);">'.$langs->trans('GiftReceipt').'</button>';
  728. }
  729. }
  730. if ($conf->global->TAKEPOS_EMAIL_TEMPLATE_INVOICE > 0)
  731. {
  732. $sectionwithinvoicelink .= ' <button id="buttonsend" type="button" onclick="SendTicket('.$placeid.');">'.$langs->trans('SendTicket').'</button>';
  733. }
  734. if ($remaintopay <= 0 && $conf->global->TAKEPOS_AUTO_PRINT_TICKETS) $sectionwithinvoicelink .= '<script language="javascript">$("#buttonprint").click();</script>';
  735. }
  736. /*
  737. * View
  738. */
  739. $form = new Form($db);
  740. ?>
  741. <script language="javascript">
  742. var selectedline=0;
  743. var selectedtext="";
  744. var placeid=<?php echo ($placeid > 0 ? $placeid : 0); ?>;
  745. $(document).ready(function() {
  746. var idoflineadded = <?php echo ($idoflineadded ? $idoflineadded : 0); ?>;
  747. $('.posinvoiceline').click(function(){
  748. console.log("Click done on "+this.id);
  749. $('.posinvoiceline').removeClass("selected");
  750. $(this).addClass("selected");
  751. if (selectedline==this.id) return; // If is already selected
  752. else selectedline=this.id;
  753. selectedtext=$('#'+selectedline).find("td:first").html();
  754. <?php
  755. if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
  756. print '$("#phonediv1").load("auto_order.php?action=editline&placeid="+placeid+"&selectedline="+selectedline, function() {
  757. });';
  758. }
  759. ?>
  760. });
  761. /* Autoselect the line */
  762. if (idoflineadded > 0)
  763. {
  764. console.log("Auto select "+idoflineadded);
  765. $('.posinvoiceline#'+idoflineadded).click();
  766. }
  767. <?php
  768. if ($action == "order" and $order_receipt_printer1 != "") {
  769. if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
  770. ?>
  771. $.ajax({
  772. type: "POST",
  773. url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php',
  774. data: 'invoice='+orderprinter1esc
  775. });
  776. <?php
  777. }
  778. else {
  779. ?>
  780. $.ajax({
  781. type: "POST",
  782. url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
  783. data: '<?php
  784. print $headerorder.$order_receipt_printer1.$footerorder; ?>'
  785. });
  786. <?php
  787. }
  788. }
  789. if ($action == "order" and $order_receipt_printer2 != "") {
  790. if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
  791. ?>
  792. $.ajax({
  793. type: "POST",
  794. url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php?printer=2',
  795. data: 'invoice='+orderprinter2esc
  796. });
  797. <?php
  798. }
  799. else {
  800. ?>
  801. $.ajax({
  802. type: "POST",
  803. url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print2',
  804. data: '<?php
  805. print $headerorder.$order_receipt_printer2.$footerorder; ?>'
  806. });
  807. <?php
  808. }
  809. }
  810. if ($action == "order" and $order_receipt_printer3 != "") {
  811. if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
  812. ?>
  813. $.ajax({
  814. type: "POST",
  815. url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php?printer=3',
  816. data: 'invoice='+orderprinter3esc
  817. });
  818. <?php
  819. }
  820. }
  821. // Set focus to search field
  822. if ($action == "search" || $action == "valid") {
  823. ?>
  824. parent.setFocusOnSearchField();
  825. <?php
  826. }
  827. if ($action == "temp" and $ticket_printer1 != "") {
  828. ?>
  829. $.ajax({
  830. type: "POST",
  831. url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
  832. data: '<?php
  833. print $header_soc.$header_ticket.$body_ticket.$ticket_printer1.$ticket_total.$footer_ticket; ?>'
  834. });
  835. <?php
  836. }
  837. if ($action == "search") {
  838. ?>
  839. $('#search').focus();
  840. <?php
  841. }
  842. ?>
  843. });
  844. function SendTicket(id)
  845. {
  846. console.log("Open box to select the Print/Send form");
  847. $.colorbox({href:"send.php?facid="+id, width:"70%", height:"30%", transition:"none", iframe:"true", title:"<?php echo $langs->trans("SendTicket"); ?>"});
  848. }
  849. function Print(id, gift){
  850. $.colorbox({href:"receipt.php?facid="+id+"&gift="+gift, width:"40%", height:"90%", transition:"none", iframe:"true", title:"<?php
  851. echo $langs->trans("PrintTicket"); ?>"});
  852. }
  853. function TakeposPrinting(id){
  854. var receipt;
  855. console.log("TakeposPrinting" + id);
  856. $.get("receipt.php?facid="+id, function(data, status){
  857. receipt=data.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '');
  858. $.ajax({
  859. type: "POST",
  860. url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
  861. data: receipt
  862. });
  863. });
  864. }
  865. function TakeposConnector(id){
  866. console.log("TakeposConnector" + id);
  867. $.get("ajax/ajax.php?action=printinvoiceticket&term=<?php echo $_SESSION["takeposterminal"]; ?>&id="+id, function(data, status){
  868. $.ajax({
  869. type: "POST",
  870. url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php',
  871. data: 'invoice='+data
  872. });
  873. });
  874. }
  875. function DolibarrTakeposPrinting(id) {
  876. console.log("DolibarrTakeposPrinting Printing invoice ticket " + id)
  877. $.ajax({
  878. type: "GET",
  879. url: "<?php print dol_buildpath('/takepos/ajax/ajax.php', 1).'?action=printinvoiceticket&term='.$_SESSION["takeposterminal"].'&id='; ?>" + id,
  880. });
  881. }
  882. function CreditNote() {
  883. $("#poslines").load("invoice.php?action=creditnote&invoiceid="+placeid, function() {
  884. });
  885. }
  886. $( document ).ready(function() {
  887. console.log("Set customer info and sales in header placeid=<?php echo $placeid; ?> status=<?php echo $invoice->statut; ?>");
  888. <?php
  889. $s = $langs->trans("Customer");
  890. if ($invoice->id > 0 && ($invoice->socid != $conf->global->$constforcompanyid)) {
  891. $s = $soc->name;
  892. }
  893. ?>
  894. $("#customerandsales").html('');
  895. $("#customerandsales").append('<a class="valignmiddle tdoverflowmax100 minwidth100" id="customer" onclick="Customer();" title="<?php print dol_escape_js($s); ?>"><span class="fas fa-building paddingrightonly"></span><?php print dol_escape_js($s); ?></a>');
  896. <?php
  897. $sql = "SELECT rowid, datec, ref FROM ".MAIN_DB_PREFIX."facture";
  898. if (empty($conf->global->TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED)) {
  899. // By default, only invoices with a ref not already defined can in list of open invoice we can edit.
  900. $sql .= " WHERE ref LIKE '(PROV-POS".$db->escape($_SESSION["takeposterminal"])."-0%' AND entity IN (".getEntity('invoice').")";
  901. } else {
  902. // If TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED set, we show also draft invoice that already has a reference defined
  903. $sql .= " WHERE pos_source = '".$db->escape($_SESSION["takeposterminal"])."'";
  904. $sql .= " AND module_source = 'takepos'";
  905. $sql .= " AND entity IN (".getEntity('invoice').")";
  906. }
  907. $sql .= $db->order('datec', 'ASC');
  908. $resql = $db->query($sql);
  909. if ($resql) {
  910. while ($obj = $db->fetch_object($resql)) {
  911. echo '$("#customerandsales").append(\'';
  912. echo '<a class="valignmiddle" title="'.dol_escape_js($langs->trans("SaleStartedAt", dol_print_date($db->jdate($obj->datec), '%H:%M', 'tzuser'))).'" onclick="place=\\\'';
  913. $num_sale = str_replace(")", "", str_replace("(PROV-POS".$_SESSION["takeposterminal"]."-", "", $obj->ref));
  914. echo $num_sale;
  915. if (str_replace("-", "", $num_sale) > $max_sale) $max_sale = str_replace("-", "", $num_sale);
  916. echo '\\\'; invoiceid=\\\'';
  917. echo $obj->rowid;
  918. echo '\\\'; Refresh();">';
  919. if ($placeid == $obj->rowid) echo "<b>";
  920. echo dol_print_date($db->jdate($obj->datec), '%H:%M', 'tzuser');
  921. if ($placeid == $obj->rowid) echo "</b>";
  922. echo '</a>\');';
  923. }
  924. echo '$("#customerandsales").append(\'<a onclick="place=\\\'0-';
  925. echo $max_sale + 1;
  926. echo '\\\'; invoiceid=0; Refresh();"><span class="fa fa-plus-square" title="'.dol_escape_htmltag($langs->trans("StartAParallelSale")).'"></a>\');';
  927. } else {
  928. dol_print_error($db);
  929. }
  930. $s = '';
  931. $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"];
  932. if (!empty($conf->stock->enabled) && $conf->global->$constantforkey != "1")
  933. {
  934. $s = '<span class="small">';
  935. $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
  936. $warehouse = new Entrepot($db);
  937. $warehouse->fetch($conf->global->$constantforkey);
  938. $s .= $langs->trans("Warehouse").'<br>'.$warehouse->ref;
  939. $s .= '</span>';
  940. }
  941. ?>
  942. $("#infowarehouse").html('<?php print dol_escape_js($s); ?>');
  943. <?php
  944. // Module Adherent
  945. $s = '';
  946. if (!empty($conf->adherent->enabled) && $invoice->socid > 0 && $invoice->socid != $conf->global->$constforcompanyid)
  947. {
  948. $s = '<span class="small">';
  949. require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
  950. $langs->load("members");
  951. $s .= $langs->trans("Member").': ';
  952. $adh = new Adherent($db);
  953. $result = $adh->fetch('', '', $invoice->socid);
  954. if ($result > 0)
  955. {
  956. $adh->ref = $adh->getFullName($langs);
  957. if (empty($adh->statut)) { $s .= "<s>"; }
  958. $s .= $adh->getFullName($langs);
  959. $s .= ' - '.$adh->type;
  960. if ($adh->datefin)
  961. {
  962. $s .= '<br>'.$langs->trans("SubscriptionEndDate").': '.dol_print_date($adh->datefin, 'day');
  963. if ($adh->hasDelay()) {
  964. $s .= " ".img_warning($langs->trans("Late"));
  965. }
  966. } else {
  967. $s .= '<br>'.$langs->trans("SubscriptionNotReceived");
  968. if ($adh->statut > 0) $s .= " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft and not terminated
  969. }
  970. if (empty($adh->statut)) { $s .= "</s>"; }
  971. } else {
  972. $s .= '<br>'.$langs->trans("ThirdpartyNotLinkedToMember");
  973. }
  974. $s .= '</span>';
  975. }
  976. ?>
  977. $("#moreinfo").html('<?php print dol_escape_js($s); ?>');
  978. });
  979. </script>
  980. <?php
  981. // Add again js for footer because this content is injected into index.php page so all init
  982. // for tooltip and other js beautifiers must be reexecuted too.
  983. if (!empty($conf->use_javascript_ajax))
  984. {
  985. print "\n".'<!-- Includes JS Footer of Dolibarr -->'."\n";
  986. print '<script src="'.DOL_URL_ROOT.'/core/js/lib_foot.js.php?lang='.$langs->defaultlang.($ext ? '&'.$ext : '').'"></script>'."\n";
  987. }
  988. print '<!-- invoice.php place='.(int) $place.' invoice='.$invoice->ref.' mobilepage='.$mobilepage.' $_SESSION["basiclayout"]='.$_SESSION["basiclayout"].' conf->global->TAKEPOS_BAR_RESTAURANT='.$conf->global->TAKEPOS_BAR_RESTAURANT.' -->'."\n";
  989. print '<div class="div-table-responsive-no-min invoice">';
  990. print '<table id="tablelines" class="noborder noshadow postablelines" width="100%">';
  991. if ($sectionwithinvoicelink && ($mobilepage == "invoice" || $mobilepage == "")) {
  992. print '<tr><td colspan="4">'.$sectionwithinvoicelink.'</td></tr>';
  993. }
  994. print '<tr class="liste_titre nodrag nodrop">';
  995. print '<td class="linecoldescription">';
  996. // In phone version only show when it is invoice page
  997. if ($mobilepage == "invoice" || $mobilepage == "") {
  998. print '<input type="hidden" name="invoiceid" id="invoiceid" value="'.$invoice->id.'">';
  999. }
  1000. if ($conf->global->TAKEPOS_BAR_RESTAURANT)
  1001. {
  1002. $sql = "SELECT floor, label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place);
  1003. $resql = $db->query($sql);
  1004. $obj = $db->fetch_object($resql);
  1005. if ($obj)
  1006. {
  1007. $label = $obj->label;
  1008. $floor = $obj->floor;
  1009. }
  1010. // In phone version only show when is invoice page
  1011. if ($mobilepage == "invoice" || $mobilepage == "") {
  1012. print '<span class="opacitymedium">'.$langs->trans('Place')."</span> <b>".$label."</b><br>";
  1013. print '<span class="opacitymedium">'.$langs->trans('Floor')."</span> <b>".$floor."</b>";
  1014. }
  1015. elseif (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) print $mysoc->name;
  1016. elseif ($mobilepage == "cats") print $langs->trans('Category');
  1017. elseif ($mobilepage == "products") print $langs->trans('Label');
  1018. } else {
  1019. print $langs->trans("Products");
  1020. }
  1021. print '</td>';
  1022. if ($_SESSION["basiclayout"] != 1)
  1023. {
  1024. print '<td class="linecolqty right">'.$langs->trans('ReductionShort').'</td>';
  1025. print '<td class="linecolqty right">'.$langs->trans('Qty').'</td>';
  1026. print '<td class="linecolht right nowraponall">';
  1027. print '<span class="opacitymedium small">'.$langs->trans('TotalTTCShort').'</span><br>';
  1028. // In phone version only show when it is invoice page
  1029. if ($mobilepage == "invoice" || $mobilepage == "") {
  1030. print '<span id="linecolht-span-total" style="font-size:1.3em; font-weight: bold;">'.price($invoice->total_ttc, 1, '', 1, -1, -1, $conf->currency).'</span>';
  1031. if (!empty($conf->multicurrency->enabled) && $_SESSION["takeposcustomercurrency"] != "" && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
  1032. //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
  1033. include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
  1034. $multicurrency = new MultiCurrency($db);
  1035. $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
  1036. print '<br><span id="linecolht-span-total" style="font-size:0.9em; font-style:italic;">('.price($invoice->total_ttc * $multicurrency->rate->rate).' '.$_SESSION["takeposcustomercurrency"].')</span>';
  1037. }
  1038. print '</td>';
  1039. }
  1040. print '</td>';
  1041. }
  1042. elseif ($mobilepage == "invoice") print '<td class="linecolqty right">'.$langs->trans('Qty').'</td>';
  1043. print "</tr>\n";
  1044. if ($_SESSION["basiclayout"] == 1)
  1045. {
  1046. if ($mobilepage == "cats")
  1047. {
  1048. require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
  1049. $categorie = new Categorie($db);
  1050. $categories = $categorie->get_full_arbo('product');
  1051. $htmlforlines = '';
  1052. foreach ($categories as $row) {
  1053. if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) $htmlforlines .= '<div class="leftcat';
  1054. else $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
  1055. $htmlforlines .= '" onclick="LoadProducts('.$row['id'].');">';
  1056. if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) $htmlforlines .= '<img class="imgwrapper" width="33%" src="'.DOL_URL_ROOT.'/takepos/public/auto_order.php?genimg=cat&query=cat&id='.$row['id'].'"><br>';
  1057. else $htmlforlines .= '<td class="left">';
  1058. $htmlforlines .= $row['label'];
  1059. if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) $htmlforlines .= '</div>'."\n";
  1060. else $htmlforlines .= '</td></tr>'."\n";
  1061. }
  1062. $htmlforlines .= '</table>';
  1063. $htmlforlines .= '</table>';
  1064. print $htmlforlines;
  1065. }
  1066. if ($mobilepage == "products")
  1067. {
  1068. require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
  1069. $object = new Categorie($db);
  1070. $catid = GETPOST('catid', 'int');
  1071. $result = $object->fetch($catid);
  1072. $prods = $object->getObjectsInCateg("product");
  1073. $htmlforlines = '';
  1074. foreach ($prods as $row) {
  1075. if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) $htmlforlines .= '<div class="leftcat';
  1076. else $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
  1077. $htmlforlines .= '" onclick="AddProduct(\''.$place.'\', '.$row->id.')">';
  1078. if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
  1079. $htmlforlines .= '<img class="imgwrapper" width="33%" src="'.DOL_URL_ROOT.'/takepos/public/auto_order.php?genimg=pro&query=pro&id='.$row->id.'"><br>';
  1080. $htmlforlines .= $row->label.''.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency);
  1081. $htmlforlines .= '</div>'."\n";
  1082. }
  1083. else {
  1084. $htmlforlines .= '<td class="left">';
  1085. $htmlforlines .= $row->label;
  1086. $htmlforlines .= '<div class="right">'.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency).'</div>';
  1087. $htmlforlines .= '</tr>'."\n";
  1088. }
  1089. }
  1090. $htmlforlines .= '</table>';
  1091. print $htmlforlines;
  1092. }
  1093. if ($mobilepage == "places")
  1094. {
  1095. $sql = "SELECT rowid, entity, label, leftpos, toppos, floor FROM ".MAIN_DB_PREFIX."takepos_floor_tables";
  1096. $resql = $db->query($sql);
  1097. $rows = array();
  1098. $htmlforlines = '';
  1099. while ($row = $db->fetch_array($resql)) {
  1100. $rows[] = $row;
  1101. $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
  1102. $htmlforlines .= '" onclick="LoadPlace(\''.$row['label'].'\')">';
  1103. $htmlforlines .= '<td class="left">';
  1104. $htmlforlines .= $row['label'];
  1105. $htmlforlines .= '</td>';
  1106. $htmlforlines .= '</tr>'."\n";
  1107. }
  1108. $htmlforlines .= '</table>';
  1109. print $htmlforlines;
  1110. }
  1111. }
  1112. if ($placeid > 0)
  1113. {
  1114. //In Phone basic layout hide some content depends situation
  1115. if ($_SESSION["basiclayout"] == 1 && $mobilepage != "invoice" && $action != "order") return;
  1116. if (is_array($invoice->lines) && count($invoice->lines))
  1117. {
  1118. print '<!-- invoice.php show lines of invoices -->'."\n";
  1119. $tmplines = array_reverse($invoice->lines);
  1120. foreach ($tmplines as $line)
  1121. {
  1122. if ($line->fk_parent_line != false)
  1123. {
  1124. $htmlsupplements[$line->fk_parent_line] .= '<tr class="drag drop oddeven posinvoiceline';
  1125. if ($line->special_code == "4") $htmlsupplements[$line->fk_parent_line] .= ' order';
  1126. $htmlsupplements[$line->fk_parent_line] .= '" id="'.$line->id.'">';
  1127. $htmlsupplements[$line->fk_parent_line] .= '<td class="left">';
  1128. $htmlsupplements[$line->fk_parent_line] .= img_picto('', 'rightarrow');
  1129. if ($line->product_label) $htmlsupplements[$line->fk_parent_line] .= $line->product_label;
  1130. if ($line->product_label && $line->desc) $htmlsupplements[$line->fk_parent_line] .= '<br>';
  1131. if ($line->product_label != $line->desc)
  1132. {
  1133. $firstline = dolGetFirstLineOfText($line->desc);
  1134. if ($firstline != $line->desc)
  1135. {
  1136. $htmlsupplements[$line->fk_parent_line] .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
  1137. } else {
  1138. $htmlsupplements[$line->fk_parent_line] .= $line->desc;
  1139. }
  1140. }
  1141. $htmlsupplements[$line->fk_parent_line] .= '</td>';
  1142. if ($_SESSION["basiclayout"] != 1)
  1143. {
  1144. $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.vatrate($line->remise_percent, true).'</td>';
  1145. $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.$line->qty.'</td>';
  1146. $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.price($line->total_ttc).'</td>';
  1147. }
  1148. $htmlsupplements[$line->fk_parent_line] .= '</tr>'."\n";
  1149. continue;
  1150. }
  1151. $htmlforlines = '';
  1152. $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
  1153. if ($line->special_code == "4") {
  1154. $htmlforlines .= ' order';
  1155. }
  1156. $htmlforlines .= '" id="'.$line->id.'">';
  1157. $htmlforlines .= '<td class="left">';
  1158. if ($_SESSION["basiclayout"] == 1) $htmlforlines .= '<span class="phoneqty">'.$line->qty."</span> x ";
  1159. if (isset($line->product_type))
  1160. {
  1161. if (empty($line->product_type)) $htmlforlines .= img_object('', 'product').' ';
  1162. else $htmlforlines .= img_object('', 'service').' ';
  1163. }
  1164. if (empty($conf->global->TAKEPOS_SHOW_N_FIRST_LINES)) {
  1165. $tooltiptext = '';
  1166. if ($line->product_ref) {
  1167. $tooltiptext .= '<b>'.$langs->trans("Ref").'</b> : '.$line->product_ref.'<br>';
  1168. $tooltiptext .= '<b>'.$langs->trans("Label").'</b> : '.$line->product_label.'<br>';
  1169. if ($line->product_label != $line->desc) {
  1170. if ($line->desc) $tooltiptext .= '<br>';
  1171. $tooltiptext .= $line->desc;
  1172. }
  1173. }
  1174. $htmlforlines .= $form->textwithpicto($line->product_label ? $line->product_label : ($line->product_ref ? $line->product_ref : dolGetFirstLineOfText($line->desc, 1)), $tooltiptext);
  1175. } else {
  1176. if ($line->product_label) $htmlforlines .= $line->product_label;
  1177. if ($line->product_label != $line->desc)
  1178. {
  1179. if ($line->product_label && $line->desc) $htmlforlines .= '<br>';
  1180. $firstline = dolGetFirstLineOfText($line->desc, $conf->global->TAKEPOS_SHOW_N_FIRST_LINES);
  1181. if ($firstline != $line->desc)
  1182. {
  1183. $htmlforlines .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
  1184. } else {
  1185. $htmlforlines .= $line->desc;
  1186. }
  1187. }
  1188. }
  1189. if (!empty($line->array_options['options_order_notes'])) $htmlforlines .= "<br>(".$line->array_options['options_order_notes'].")";
  1190. if ($_SESSION["basiclayout"] == 1) {
  1191. $htmlforlines .= '</td><td class="right phonetable"><button type="button" onclick="SetQty(place, '.$line->rowid.', '.($line->qty - 1).');" class="publicphonebutton2 phonered">-</button>&nbsp;&nbsp;<button type="button" onclick="SetQty(place, '.$line->rowid.', '.($line->qty + 1).');" class="publicphonebutton2 phonegreen">+</button>';
  1192. }
  1193. if ($_SESSION["basiclayout"] != 1)
  1194. {
  1195. $moreinfo = '';
  1196. $moreinfo .= $langs->transcountry("TotalHT", $mysoc->country_code).': '.price($line->total_ht);
  1197. if ($line->vat_src_code) $moreinfo .= '<br>'.$langs->trans("VATCode").': '.$line->vat_src_code;
  1198. $moreinfo .= '<br>'.$langs->transcountry("TotalVAT", $mysoc->country_code).': '.price($line->total_tva);
  1199. $moreinfo .= '<br>'.$langs->transcountry("TotalLT1", $mysoc->country_code).': '.price($line->total_localtax1);
  1200. $moreinfo .= '<br>'.$langs->transcountry("TotalLT2", $mysoc->country_code).': '.price($line->total_localtax2);
  1201. $moreinfo .= '<br>'.$langs->transcountry("TotalTTC", $mysoc->country_code).': '.price($line->total_ttc);
  1202. //$moreinfo .= $langs->trans("TotalHT").': '.$line->total_ht;
  1203. if ($line->date_start || $line->date_end) $htmlforlines .= '<br><div class="clearboth nowraponall">'.get_date_range($line->date_start, $line->date_end).'</div>';
  1204. $htmlforlines .= '</td>';
  1205. $htmlforlines .= '<td class="right">'.vatrate($line->remise_percent, true).'</td>';
  1206. $htmlforlines .= '<td class="right">';
  1207. if (!empty($conf->stock->enabled) && !empty($user->rights->stock->mouvement->lire))
  1208. {
  1209. $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
  1210. if (!empty($conf->global->$constantforkey) && $line->fk_product > 0) {
  1211. $sql = "SELECT e.rowid, e.ref, e.lieu, e.fk_parent, e.statut, ps.reel, ps.rowid as product_stock_id, p.pmp";
  1212. $sql .= " FROM ".MAIN_DB_PREFIX."entrepot as e,";
  1213. $sql .= " ".MAIN_DB_PREFIX."product_stock as ps";
  1214. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = ps.fk_product";
  1215. $sql .= " WHERE ps.reel != 0";
  1216. $sql .= " AND ps.fk_entrepot = ".$conf->global->$constantforkey;
  1217. $sql .= " AND e.entity IN (".getEntity('stock').")";
  1218. $sql .= " AND ps.fk_product = ".$line->fk_product;
  1219. $resql = $db->query($sql);
  1220. if ($resql) {
  1221. $obj = $db->fetch_object($resql);
  1222. $stock_real = price2num($obj->reel, 'MS');
  1223. $htmlforlines .= $line->qty;
  1224. if ($line->qty && $line->qty > $stock_real) $htmlforlines .= '<span style="color: var(--amountremaintopaycolor)">';
  1225. $htmlforlines .= ' <span class="posstocktoolow">('.$langs->trans("Stock").' '.$stock_real.')</span>';
  1226. if ($line->qty && $line->qty > $stock_real) $htmlforlines .= "</span>";
  1227. } else {
  1228. dol_print_error($db);
  1229. }
  1230. } else {
  1231. $htmlforlines .= $line->qty;
  1232. }
  1233. } else {
  1234. $htmlforlines .= $line->qty;
  1235. }
  1236. $htmlforlines .= '</td>';
  1237. $htmlforlines .= '<td class="right classfortooltip" title="'.$moreinfo.'">';
  1238. $htmlforlines .= price($line->total_ttc, 1, '', 1, -1, -1, $conf->currency);
  1239. if (!empty($conf->multicurrency->enabled) && $_SESSION["takeposcustomercurrency"] != "" && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
  1240. //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
  1241. include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
  1242. $multicurrency = new MultiCurrency($db);
  1243. $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
  1244. $htmlforlines .= '<br><span id="linecolht-span-total" style="font-size:0.9em; font-style:italic;">('.price($line->total_ttc * $multicurrency->rate->rate).' '.$_SESSION["takeposcustomercurrency"].')</span>';
  1245. }
  1246. $htmlforlines .= '</td>';
  1247. }
  1248. $htmlforlines .= '</tr>'."\n";
  1249. $htmlforlines .= $htmlsupplements[$line->id];
  1250. print $htmlforlines;
  1251. }
  1252. } else {
  1253. print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">'.$langs->trans("Empty").'</span></td><td></td><td></td><td></td></tr>';
  1254. }
  1255. } else { // No invoice generated yet
  1256. print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">'.$langs->trans("Empty").'</span></td><td></td><td></td><td></td></tr>';
  1257. }
  1258. print '</table>';
  1259. if (($action == "valid" || $action == "history") && $invoice->type != Facture::TYPE_CREDIT_NOTE) {
  1260. print '<button id="buttonprint" type="button" onclick="ModalBox(\'ModalCreditNote\')">'.$langs->trans('CreateCreditNote').'</button>';
  1261. }
  1262. if ($action == "search")
  1263. {
  1264. print '<center>
  1265. <input type="text" id="search" name="search" onkeyup="Search2();" name="search" style="width:80%;font-size: 150%;" placeholder=' . $langs->trans('Search').'
  1266. </center>';
  1267. }
  1268. print '</div>';