dolibarr  16.0.5
invoice.php
Go to the documentation of this file.
1 <?php
26 // if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Not disabled cause need to load personalized language
27 // if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Not disabled cause need to load personalized language
28 // if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1');
29 // if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1');
30 if (!defined('NOCSRFCHECK')) {
31  define('NOCSRFCHECK', '1');
32 }
33 if (!defined('NOTOKENRENEWAL')) {
34  define('NOTOKENRENEWAL', '1');
35 }
36 if (!defined('NOREQUIREMENU')) {
37  define('NOREQUIREMENU', '1');
38 }
39 if (!defined('NOREQUIREHTML')) {
40  define('NOREQUIREHTML', '1');
41 }
42 if (!defined('NOREQUIREAJAX')) {
43  define('NOREQUIREAJAX', '1');
44 }
45 
46 if (!defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
47  require '../main.inc.php';
48 }
49 require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
50 require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
51 require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
52 require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
53 $hookmanager->initHooks(array('takeposinvoice'));
54 
55 global $mysoc;
56 
57 $langs->loadLangs(array("companies", "commercial", "bills", "cashdesk", "stocks", "banks"));
58 
59 $id = GETPOST('id', 'int');
60 $action = GETPOST('action', 'aZ09');
61 $idproduct = GETPOST('idproduct', 'int');
62 $place = (GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : 0); // $place is id of table for Bar or Restaurant
63 $placeid = 0; // $placeid is ID of invoice
64 $mobilepage = GETPOST('mobilepage', 'alpha');
65 
66 // Terminal is stored into $_SESSION["takeposterminal"];
67 
68 if (empty($user->rights->takepos->run) && !defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
70 }
71 
72 
73 /*
74  * View
75  */
76 
77 if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
78  // DIRECT LINK TO THIS PAGE FROM MOBILE AND NO TERMINAL SELECTED
79  if ($_SESSION["takeposterminal"] == "") {
80  if (getDolGlobalString('TAKEPOS_NUM_TERMINALS') == "1") {
81  $_SESSION["takeposterminal"] = 1;
82  } else {
83  header("Location: ".DOL_URL_ROOT."/takepos/index.php");
84  exit;
85  }
86  }
87  $title = 'TakePOS - Dolibarr '.DOL_VERSION;
88  if (!empty($conf->global->MAIN_APPLICATION_TITLE)) {
89  $title = 'TakePOS - '.$conf->global->MAIN_APPLICATION_TITLE;
90  }
91  $head = '<meta name="apple-mobile-web-app-title" content="TakePOS"/>
92  <meta name="apple-mobile-web-app-capable" content="yes">
93  <meta name="mobile-web-app-capable" content="yes">
94  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>';
95  $arrayofcss = array(
96  '/takepos/css/pos.css.php',
97  '/takepos/js/jquery.colorbox-min.js'
98  );
99  $arrayofjs = array('/takepos/js/jquery.colorbox-min.js');
100  $disablejs = 0;
101  $disablehead = 0;
102  top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
103 }
104 
111 function fail($message)
112 {
113  header($_SERVER['SERVER_PROTOCOL'].' 500 Internal Server Error', true, 500);
114  die($message);
115 }
116 
117 
118 
119 $number = GETPOST('number', 'alpha');
120 $idline = GETPOST('idline', 'int');
121 $selectedline = GETPOST('selectedline', 'int');
122 $desc = GETPOST('desc', 'alphanohtml');
123 $pay = GETPOST('pay', 'aZ09');
124 $amountofpayment = price2num(GETPOST('amount', 'alpha'));
125 
126 $invoiceid = GETPOST('invoiceid', 'int');
127 
128 $paycode = $pay;
129 if ($pay == 'cash') {
130  $paycode = 'LIQ'; // For backward compatibility
131 }
132 if ($pay == 'card') {
133  $paycode = 'CB'; // For backward compatibility
134 }
135 if ($pay == 'cheque') {
136  $paycode = 'CHQ'; // For backward compatibility
137 }
138 
139 // Retrieve paiementid
140 $paiementid = 0;
141 if ($paycode) {
142  $sql = "SELECT id FROM ".MAIN_DB_PREFIX."c_paiement";
143  $sql .= " WHERE entity IN (".getEntity('c_paiement').")";
144  $sql .= " AND code = '".$db->escape($paycode)."'";
145  $resql = $db->query($sql);
146  if ($resql) {
147  $obj = $db->fetch_object($resql);
148  if ($obj) {
149  $paiementid = $obj->id;
150  }
151  }
152 }
153 
154 $invoice = new Facture($db);
155 if ($invoiceid > 0) {
156  $ret = $invoice->fetch($invoiceid);
157 } else {
158  $ret = $invoice->fetch('', '(PROV-POS'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '') .'-'.$place.')');
159 }
160 if ($ret > 0) {
161  $placeid = $invoice->id;
162 }
163 
164 $constforcompanyid = 'CASHDESK_ID_THIRDPARTY'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
165 
166 $soc = new Societe($db);
167 if ($invoice->socid > 0) {
168  $soc->fetch($invoice->socid);
169 } else {
170  $soc->fetch(getDolGlobalString("$constforcompanyid"));
171 }
172 
173 // Change the currency of invoice if it was modified
174 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"])) {
175  if ($invoice->multicurrency_code != $_SESSION["takeposcustomercurrency"]) {
176  $invoice->setMulticurrencyCode($_SESSION["takeposcustomercurrency"]);
177  }
178 }
179 
180 
181 /*
182  * Actions
183  */
184 
185 $parameters=array();
186 $reshook=$hookmanager->executeHooks('doActions', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
187 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
188 
189 if (empty($reshook)) {
190  // Action to record a payment on a TakePOS invoice
191  if ($action == 'valid' && $user->rights->facture->creer) {
192  $bankaccount = 0;
193  $error = 0;
194 
195  if (!empty($conf->global->TAKEPOS_CAN_FORCE_BANK_ACCOUNT_DURING_PAYMENT)) {
196  $bankaccount = GETPOST('accountid', 'int');
197  } else {
198  if ($pay == 'LIQ') {
199  $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CASH'.$_SESSION["takeposterminal"]}; // For backward compatibility
200  } elseif ($pay == "CHQ") {
201  $bankaccount = $conf->global->{'CASHDESK_ID_BANKACCOUNT_CHEQUE'.$_SESSION["takeposterminal"]}; // For backward compatibility
202  } else {
203  $accountname = "CASHDESK_ID_BANKACCOUNT_".$pay.$_SESSION["takeposterminal"];
204  $bankaccount = $conf->global->$accountname;
205  }
206  }
207 
208  if ($bankaccount <= 0 && $pay != "delayed" && isModEnabled('banque')) {
209  $errormsg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankAccount"));
210  $error++;
211  }
212 
213  $now = dol_now();
214  $res = 0;
215 
216  $invoice = new Facture($db);
217  $invoice->fetch($placeid);
218 
219  if ($invoice->total_ttc < 0) {
220  $invoice->type = $invoice::TYPE_CREDIT_NOTE;
221 
222  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture WHERE";
223  $sql .= " fk_soc = ".((int) $invoice->socid);
224  $sql .= " AND type <> ".Facture::TYPE_CREDIT_NOTE;
225  $sql .= " AND fk_statut >= ".$invoice::STATUS_VALIDATED;
226  $sql .= " ORDER BY rowid DESC";
227 
228  $resql = $db->query($sql);
229  if ($resql) {
230  $obj = $db->fetch_object($resql);
231  $fk_source = $obj->rowid;
232  if ($fk_source == null) {
233  fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer"));
234  }
235  } else {
236  fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer"));
237  }
238  $invoice->fk_facture_source = $fk_source;
239  $invoice->update($user);
240  }
241 
242  //$sav_FACTURE_ADDON = '';
243  //if (!empty($conf->global->TAKEPOS_ADDON)) {
244  // $sav_FACTURE_ADDON = $conf->global->FACTURE_ADDON;
245  // if ($conf->global->TAKEPOS_ADDON == "terminal") $conf->global->FACTURE_ADDON = $conf->global->{'TAKEPOS_ADDON'.$_SESSION["takeposterminal"]};
246  // else $conf->global->FACTURE_ADDON = $conf->global->TAKEPOS_ADDON;
247  //}
248 
249  $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"];
250  if ($error) {
251  dol_htmloutput_errors($errormsg, null, 1);
252  } elseif ($invoice->statut != Facture::STATUS_DRAFT) {
253  //If invoice is validated but it is not fully paid is not error and make the payment
254  if ($invoice->getRemainToPay() > 0) {
255  $res = 1;
256  } else {
257  dol_syslog("Sale already validated");
258  dol_htmloutput_errors($langs->trans("InvoiceIsAlreadyValidated", "TakePos"), null, 1);
259  }
260  } elseif (count($invoice->lines) == 0) {
261  $error++;
262  dol_syslog('Sale without lines');
263  dol_htmloutput_errors($langs->trans("NoLinesToBill", "TakePos"), null, 1);
264  } elseif (isModEnabled('stock') && $conf->global->$constantforkey != "1") {
265  $savconst = $conf->global->STOCK_CALCULATE_ON_BILL;
266  $conf->global->STOCK_CALCULATE_ON_BILL = 1;
267 
268  $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
269  dol_syslog("Validate invoice with stock change into warehouse defined into constant ".$constantforkey." = ".$conf->global->$constantforkey);
270  $batch_rule = 0;
271  if (isModEnabled('productbatch') && !empty($conf->global->CASHDESK_FORCE_DECREASE_STOCK)) {
272  require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
274  }
275  $res = $invoice->validate($user, '', $conf->global->$constantforkey, 0, $batch_rule);
276 
277  $conf->global->STOCK_CALCULATE_ON_BILL = $savconst;
278  } else {
279  $res = $invoice->validate($user);
280  if ($res < 0) {
281  $error++;
282  $langs->load("admin");
283  dol_htmloutput_errors($invoice->error == 'NotConfigured' ? $langs->trans("NotConfigured").' (TakePos numbering module)': $invoice->error, $invoice->errors, 1);
284  }
285  }
286 
287  // Restore save values
288  //if (!empty($sav_FACTURE_ADDON))
289  //{
290  // $conf->global->FACTURE_ADDON = $sav_FACTURE_ADDON;
291  //}
292 
293  // Add the payment
294  if (!$error && $res >= 0) {
295  $remaintopay = $invoice->getRemainToPay();
296  if ($remaintopay > 0) {
297  $payment = new Paiement($db);
298  $payment->datepaye = $now;
299  $payment->fk_account = $bankaccount;
300  $payment->amounts[$invoice->id] = $amountofpayment;
301  if ($pay == 'LIQ') {
302  $payment->pos_change = price2num(GETPOST('excess', 'alpha'));
303  }
304 
305  // If user has not used change control, add total invoice payment
306  // Or if user has used change control and the amount of payment is higher than remain to pay, add the remain to pay
307  if ($amountofpayment == 0 || $amountofpayment > $remaintopay) {
308  $payment->amounts[$invoice->id] = $remaintopay;
309  }
310 
311  $payment->paiementid = $paiementid;
312  $payment->num_payment = $invoice->ref;
313 
314  if ($pay != "delayed") {
315  $payment->create($user);
316  $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', '');
317  if ($res < 0) {
318  $error++;
319  dol_htmloutput_errors($langs->trans('ErrorNoPaymentDefined'), $payment->errors, 1);
320  }
321  $remaintopay = $invoice->getRemainToPay(); // Recalculate remain to pay after the payment is recorded
322  }
323  }
324 
325  if ($remaintopay == 0) {
326  dol_syslog("Invoice is paid, so we set it to status Paid");
327  $result = $invoice->setPaid($user);
328  if ($result > 0) {
329  $invoice->paye = 1;
330  }
331  // set payment method
332  $invoice->setPaymentMethods($paiementid);
333  } else {
334  dol_syslog("Invoice is not paid, remain to pay = ".$remaintopay);
335  }
336  } else {
337  dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
338  }
339  }
340 
341  if ($action == 'creditnote' && $user->rights->facture->creer) {
342  $creditnote = new Facture($db);
343  $creditnote->socid = $invoice->socid;
344  $creditnote->date = dol_now();
345  $creditnote->module_source = 'takepos';
346  $creditnote->pos_source = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ;
347  $creditnote->type = Facture::TYPE_CREDIT_NOTE;
348  $creditnote->fk_facture_source = $placeid;
349  $creditnote->remise_absolue = $invoice->remise_absolue;
350  $creditnote->remise_percent = $invoice->remise_percent;
351  $creditnote->create($user);
352 
353  foreach ($invoice->lines as $line) {
354  // Extrafields
355  if (method_exists($line, 'fetch_optionals')) {
356  // load extrafields
357  $line->fetch_optionals();
358  }
359  // Reset fk_parent_line for no child products and special product
360  if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
361  $fk_parent_line = 0;
362  }
363  if ($invoice->type == Facture::TYPE_SITUATION) {
364  $source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id
365  $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
366  if (!empty($invoice->tab_previous_situation_invoice)) {
367  // search the last standard invoice in cycle and the possible credit note between this last and invoice
368  // TODO Move this out of loop of $invoice->lines
369  $tab_jumped_credit_notes = array();
370  $lineIndex = count($invoice->tab_previous_situation_invoice) - 1;
371  $searchPreviousInvoice = true;
372  while ($searchPreviousInvoice) {
373  if ($invoice->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_SITUATION || $lineIndex < 1) {
374  $searchPreviousInvoice = false; // find, exit;
375  break;
376  } else {
377  if ($invoice->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_CREDIT_NOTE) {
378  $tab_jumped_credit_notes[$lineIndex] = $invoice->tab_previous_situation_invoice[$lineIndex]->id;
379  }
380  $lineIndex--; // go to previous invoice in cycle
381  }
382  }
383 
384  $maxPrevSituationPercent = 0;
385  foreach ($invoice->tab_previous_situation_invoice[$lineIndex]->lines as $prevLine) {
386  if ($prevLine->id == $source_fk_prev_id) {
387  $maxPrevSituationPercent = max($maxPrevSituationPercent, $prevLine->situation_percent);
388 
389  //$line->subprice = $line->subprice - $prevLine->subprice;
390  $line->total_ht = $line->total_ht - $prevLine->total_ht;
391  $line->total_tva = $line->total_tva - $prevLine->total_tva;
392  $line->total_ttc = $line->total_ttc - $prevLine->total_ttc;
393  $line->total_localtax1 = $line->total_localtax1 - $prevLine->total_localtax1;
394  $line->total_localtax2 = $line->total_localtax2 - $prevLine->total_localtax2;
395 
396  $line->multicurrency_subprice = $line->multicurrency_subprice - $prevLine->multicurrency_subprice;
397  $line->multicurrency_total_ht = $line->multicurrency_total_ht - $prevLine->multicurrency_total_ht;
398  $line->multicurrency_total_tva = $line->multicurrency_total_tva - $prevLine->multicurrency_total_tva;
399  $line->multicurrency_total_ttc = $line->multicurrency_total_ttc - $prevLine->multicurrency_total_ttc;
400  }
401  }
402 
403  // prorata
404  $line->situation_percent = $maxPrevSituationPercent - $line->situation_percent;
405 
406  //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>';
407 
408  // If there is some credit note between last situation invoice and invoice used for credit note generation (note: credit notes are stored as delta)
409  $maxPrevSituationPercent = 0;
410  foreach ($tab_jumped_credit_notes as $index => $creditnoteid) {
411  foreach ($invoice->tab_previous_situation_invoice[$index]->lines as $prevLine) {
412  if ($prevLine->fk_prev_id == $source_fk_prev_id) {
413  $maxPrevSituationPercent = $prevLine->situation_percent;
414 
415  $line->total_ht -= $prevLine->total_ht;
416  $line->total_tva -= $prevLine->total_tva;
417  $line->total_ttc -= $prevLine->total_ttc;
418  $line->total_localtax1 -= $prevLine->total_localtax1;
419  $line->total_localtax2 -= $prevLine->total_localtax2;
420 
421  $line->multicurrency_subprice -= $prevLine->multicurrency_subprice;
422  $line->multicurrency_total_ht -= $prevLine->multicurrency_total_ht;
423  $line->multicurrency_total_tva -= $prevLine->multicurrency_total_tva;
424  $line->multicurrency_total_ttc -= $prevLine->multicurrency_total_ttc;
425  }
426  }
427  }
428 
429  // prorata
430  $line->situation_percent += $maxPrevSituationPercent;
431 
432  //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>';
433  }
434  }
435 
436  $line->fk_facture = $creditnote->id;
437  $line->fk_parent_line = $fk_parent_line;
438 
439  $line->subprice = -$line->subprice; // invert price for object
440  $line->pa_ht = $line->pa_ht; // we choosed to have buy/cost price always positive, so no revert of sign here
441  $line->total_ht = -$line->total_ht;
442  $line->total_tva = -$line->total_tva;
443  $line->total_ttc = -$line->total_ttc;
444  $line->total_localtax1 = -$line->total_localtax1;
445  $line->total_localtax2 = -$line->total_localtax2;
446 
447  $line->multicurrency_subprice = -$line->multicurrency_subprice;
448  $line->multicurrency_total_ht = -$line->multicurrency_total_ht;
449  $line->multicurrency_total_tva = -$line->multicurrency_total_tva;
450  $line->multicurrency_total_ttc = -$line->multicurrency_total_ttc;
451 
452  $result = $line->insert(0, 1); // When creating credit note with same lines than source, we must ignore error if discount alreayd linked
453 
454  $creditnote->lines[] = $line; // insert new line in current object
455 
456  // Defined the new fk_parent_line
457  if ($result > 0 && $line->product_type == 9) {
458  $fk_parent_line = $result;
459  }
460  }
461  $creditnote->update_price(1);
462 
463  $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"];
464  if (isModEnabled('stock') && $conf->global->$constantforkey != "1") {
465  $savconst = $conf->global->STOCK_CALCULATE_ON_BILL;
466  $conf->global->STOCK_CALCULATE_ON_BILL = 1;
467  $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
468  dol_syslog("Validate invoice with stock change into warehouse defined into constant ".$constantforkey." = ".$conf->global->$constantforkey);
469  $batch_rule = 0;
470  if (isModEnabled('productbatch') && !empty($conf->global->CASHDESK_FORCE_DECREASE_STOCK)) {
471  require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
473  }
474  $res = $creditnote->validate($user, '', $conf->global->$constantforkey, 0, $batch_rule);
475  $conf->global->STOCK_CALCULATE_ON_BILL = $savconst;
476  } else {
477  $res = $creditnote->validate($user);
478  }
479  }
480 
481  if ($action == 'history' || $action == 'creditnote') {
482  if ($action == 'creditnote') {
483  $placeid = $creditnote->id;
484  } else {
485  $placeid = (int) GETPOST('placeid', 'int');
486  }
487  $invoice = new Facture($db);
488  $invoice->fetch($placeid);
489  }
490 
491  if (($action == "addline" || $action == "freezone") && $placeid == 0) {
492  $invoice->socid = getDolGlobalString("$constforcompanyid");
493  $invoice->date = dol_now();
494  $invoice->module_source = 'takepos';
495  $invoice->pos_source = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ;
496  $invoice->entity = !empty($_SESSION["takeposinvoiceentity"]) ? $_SESSION["takeposinvoiceentity"] : $conf->entity;
497 
498  if ($invoice->socid <= 0) {
499  $langs->load('errors');
500  dol_htmloutput_errors($langs->trans("ErrorModuleSetupNotComplete", "TakePos"), null, 1);
501  } else {
502  $placeid = $invoice->create($user);
503  if ($placeid < 0) {
504  dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
505  }
506  $sql = "UPDATE ".MAIN_DB_PREFIX."facture set ref='(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")' where rowid = ".((int) $placeid);
507  $db->query($sql);
508  }
509  }
510 
511  if ($action == "addline") {
512  $prod = new Product($db);
513  $prod->fetch($idproduct);
514 
515  $customer = new Societe($db);
516  $customer->fetch($invoice->socid);
517 
518  $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
519 
520  $qty = GETPOSTISSET('qty') ? GETPOST('qty', 'int') : 1;
521  $price = $datapriceofproduct['pu_ht'];
522  $price_ttc = $datapriceofproduct['pu_ttc'];
523  //$price_min = $datapriceofproduct['price_min'];
524  $price_base_type = empty($datapriceofproduct['price_base_type']) ? 'HT' : $datapriceofproduct['price_base_type'];
525  $tva_tx = $datapriceofproduct['tva_tx'];
526  $tva_npr = $datapriceofproduct['tva_npr'];
527 
528  // Local Taxes
529  $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
530  $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
531 
532  if (!empty($conf->global->TAKEPOS_SUPPLEMENTS)) {
533  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
534  $cat = new Categorie($db);
535  $categories = $cat->containing($idproduct, 'product');
536  $found = (array_search($conf->global->TAKEPOS_SUPPLEMENTS_CATEGORY, array_column($categories, 'id')));
537  if ($found !== false) { // If this product is a supplement
538  $sql = "SELECT fk_parent_line FROM ".MAIN_DB_PREFIX."facturedet where rowid=$selectedline";
539  $resql = $db->query($sql);
540  $row = $db->fetch_array($resql);
541  if ($row[0] == null) {
542  $parent_line = $selectedline;
543  } else {
544  $parent_line = $row[0]; //If the parent line is already a supplement, add the supplement to the main product
545  }
546  }
547  }
548 
549  $idoflineadded = 0;
550  // Group if enabled. Skip group if line already sent to the printer
551  if (!empty($conf->global->TAKEPOS_GROUP_SAME_PRODUCT) && $line->special_code != "4") {
552  foreach ($invoice->lines as $line) {
553  if ($line->product_ref == $prod->ref) {
554  if ($line->special_code==4) continue; // If this line is sended to printer create new line
555  $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty + $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);
556  if ($result < 0) {
557  dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
558  } else {
559  $idoflineadded = $line->id;
560  }
561  break;
562  }
563  }
564  }
565  if ($idoflineadded <= 0) {
566  $invoice->fetch_thirdparty();
567  $array_options = array();
568 
569  // complete line by hook
570  $parameters = array('prod' => $prod);
571  $reshook=$hookmanager->executeHooks('completeTakePosAddLine', $parameters, $invoice, $action);
572  if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
573 
574  if (empty($reshook)) {
575  $idoflineadded = $invoice->addline($prod->description, $price, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idproduct, $customer->remise_percent, '', 0, 0, 0, '', $price_base_type, $price_ttc, $prod->type, -1, 0, '', 0, (!empty($parent_line)) ? $parent_line : '', null, '', '', $array_options, 100, '', null, 0);
576  }
577 
578  if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) {
579  $CUSTOMER_DISPLAY_line1 = $prod->label;
580  $CUSTOMER_DISPLAY_line2 = price($price_ttc);
581  }
582  }
583 
584  $invoice->fetch($placeid);
585  }
586 
587  if ($action == "freezone") {
588  $customer = new Societe($db);
589  $customer->fetch($invoice->socid);
590 
591  $tva_tx = GETPOST('tva_tx', 'alpha');
592  if ($tva_tx != '') {
593  if (!preg_match('/\((.*)\)/', $tva_tx)) {
594  $tva_tx = price2num($tva_tx);
595  }
596  } else {
597  $tva_tx = get_default_tva($mysoc, $customer);
598  }
599 
600  // Local Taxes
601  $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
602  $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
603 
604  $invoice->addline($desc, $number, 1, $tva_tx, $localtax1_tx, $localtax2_tx, 0, 0, '', 0, 0, 0, '', getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT') ? 'HT' : 'TTC', $number, 0, -1, 0, '', 0, 0, null, '', '', 0, 100, '', null, 0);
605  $invoice->fetch($placeid);
606  }
607 
608  if ($action == "addnote") {
609  $desc = GETPOST('addnote', 'alpha');
610  if ($idline==0) {
611  $invoice->update_note($desc, '_public');
612  } else foreach ($invoice->lines as $line) {
613  if ($line->id == $idline) {
614  $result = $invoice->updateline($line->id, $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);
615  }
616  }
617  $invoice->fetch($placeid);
618  }
619 
620  if ($action == "deleteline") {
621  if ($idline > 0 and $placeid > 0) { // If invoice exists and line selected. To avoid errors if deleted from another device or no line selected.
622  $invoice->deleteline($idline);
623  $invoice->fetch($placeid);
624  } elseif ($placeid > 0) { // If invoice exists but no line selected, proceed to delete last line.
625  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facturedet where fk_facture = ".((int) $placeid)." ORDER BY rowid DESC";
626  $resql = $db->query($sql);
627  $row = $db->fetch_array($resql);
628  $deletelineid = $row[0];
629  $invoice->deleteline($deletelineid);
630  $invoice->fetch($placeid);
631  }
632  if (count($invoice->lines) == 0) {
633  $invoice->delete($user);
634  header("Location: ".DOL_URL_ROOT."/takepos/invoice.php");
635  exit;
636  }
637  }
638 
639  // Action to delete or discard an invoice
640  if ($action == "delete") {
641  // $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.
642  if ($placeid > 0) {
643  $result = $invoice->fetch($placeid);
644 
645  if ($result > 0 && $invoice->statut == Facture::STATUS_DRAFT) {
646  $db->begin();
647 
648  // We delete the lines
649  $resdeletelines = 1;
650  foreach ($invoice->lines as $line) {
651  $tmpres = $invoice->deleteline($line->id);
652  if ($tmpres < 0) {
653  $resdeletelines = 0;
654  break;
655  }
656  }
657 
658  $sql = "UPDATE ".MAIN_DB_PREFIX."facture";
659  $varforconst = 'CASHDESK_ID_THIRDPARTY'.$_SESSION["takeposterminal"];
660  $sql .= " SET fk_soc = ".((int) $conf->global->$varforconst).", ";
661  $sql .= " datec = '".$db->idate(dol_now())."'";
662  $sql .= " WHERE ref = '(PROV-POS".$db->escape($_SESSION["takeposterminal"]."-".$place).")'";
663  $resql1 = $db->query($sql);
664 
665  if ($resdeletelines && $resql1) {
666  $db->commit();
667  } else {
668  $db->rollback();
669  }
670 
671  $invoice->fetch($placeid);
672  }
673  }
674  }
675 
676  if ($action == "updateqty") {
677  foreach ($invoice->lines as $line) {
678  if ($line->id == $idline) {
679  if (!$user->rights->takepos->editlines || (!$user->rights->takepos->editorderedlines && $line->special_code == "4")) {
680  dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), null, 1);
681  } else {
682  $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);
683  }
684  }
685  }
686 
687  $invoice->fetch($placeid);
688  }
689 
690  if ($action == "updateprice") {
691  $customer = new Societe($db);
692  $customer->fetch($invoice->socid);
693 
694  foreach ($invoice->lines as $line) {
695  if ($line->id == $idline) {
696  $prod = new Product($db);
697  $prod->fetch($line->fk_product);
698  $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
699  $price_min = $datapriceofproduct['price_min'];
700  $usercanproductignorepricemin = ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS));
701  $pu_ht = price2num($number / (1 + ($line->tva_tx / 100)), 'MU');
702  //Check min price
703  if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($pu_ht) * (1 - price2num($line->remise_percent) / 100) < price2num($price_min)))) {
704  echo $langs->trans("CantBeLessThanMinPrice");
705  } else {
706  if (empty($user->rights->takepos->editlines) || (empty($user->rights->takepos->editorderedlines) && $line->special_code == "4")) {
707  dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), null, 1);
708  } elseif (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT') == 1) {
709  $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, '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);
710  } else {
711  $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);
712  }
713  }
714  }
715  }
716 
717  // Reload data
718  $invoice->fetch($placeid);
719  }
720 
721  if ($action == "updatereduction") {
722  $customer = new Societe($db);
723  $customer->fetch($invoice->socid);
724 
725  foreach ($invoice->lines as $line) {
726  if ($line->id == $idline) {
727  dol_syslog("updatereduction Process line ".$line->id.' to apply discount of '.$number.'%');
728 
729  $prod = new Product($db);
730  $prod->fetch($line->fk_product);
731 
732  $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
733  $price_min = $datapriceofproduct['price_min'];
734  $usercanproductignorepricemin = ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS));
735 
736  $pu_ht = price2num($line->subprice / (1 + ($line->tva_tx / 100)), 'MU');
737 
738  // Check min price
739  if ($usercanproductignorepricemin && (!empty($price_min) && (price2num($line->subprice) * (1 - price2num($number) / 100) < price2num($price_min)))) {
740  echo $langs->trans("CantBeLessThanMinPrice");
741  } else {
742  if (empty($user->rights->takepos->editlines) || (empty($user->rights->takepos->editorderedlines) && $line->special_code == "4")) {
743  dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), null, 1);
744  } else {
745  $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);
746  }
747  }
748  }
749  }
750 
751  // Reload data
752  $invoice->fetch($placeid);
753  } elseif ($action == 'update_reduction_global') {
754  foreach ($invoice->lines as $line) {
755  $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);
756  }
757 
758  $invoice->fetch($placeid);
759  }
760 
761  if ($action == "order" and $placeid != 0) {
762  include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
763  if ($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") {
764  require_once DOL_DOCUMENT_ROOT.'/core/class/dolreceiptprinter.class.php';
765  $printer = new dolReceiptPrinter($db);
766  }
767 
768  $sql = "SELECT label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place);
769  $resql = $db->query($sql);
770  $row = $db->fetch_object($resql);
771  $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>';
772  $footerorder = '</tbody></table>'.dol_print_date(dol_now(), 'dayhour').'<br></html>';
773  $order_receipt_printer1 = "";
774  $order_receipt_printer2 = "";
775  $order_receipt_printer3 = "";
776  $catsprinter1 = explode(';', $conf->global->TAKEPOS_PRINTED_CATEGORIES_1);
777  $catsprinter2 = explode(';', $conf->global->TAKEPOS_PRINTED_CATEGORIES_2);
778  $catsprinter3 = explode(';', $conf->global->TAKEPOS_PRINTED_CATEGORIES_3);
779  $linestoprint = 0;
780  foreach ($invoice->lines as $line) {
781  if ($line->special_code == "4") {
782  continue;
783  }
784  $c = new Categorie($db);
785  $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
786  $result = array_intersect($catsprinter1, $existing);
787  $count = count($result);
788  if (!$line->fk_product) {
789  $count++; // Print Free-text item (Unassigned printer) to Printer 1
790  }
791  if ($count > 0) {
792  $linestoprint++;
793  $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='1' where rowid=".$line->id; //Set to print on printer 1
794  $db->query($sql);
795  $order_receipt_printer1 .= '<tr><td class="left">';
796  if ($line->fk_product) {
797  $order_receipt_printer1 .= $line->product_label;
798  } else {
799  $order_receipt_printer1 .= $line->description;
800  }
801  $order_receipt_printer1 .= '</td><td class="right">'.$line->qty;
802  if (!empty($line->array_options['options_order_notes'])) {
803  $order_receipt_printer1 .= "<br>(".$line->array_options['options_order_notes'].")";
804  }
805  $order_receipt_printer1 .= '</td></tr>';
806  }
807  }
808  if (($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") && $linestoprint > 0) {
809  $invoice->fetch($placeid); //Reload object before send to printer
810  $printer->orderprinter = 1;
811  echo "<script>";
812  echo "var orderprinter1esc='";
813  $ret = $printer->sendToPrinter($invoice, getDolGlobalInt('TAKEPOS_TEMPLATE_TO_USE_FOR_ORDERS'.$_SESSION["takeposterminal"]), getDolGlobalInt('TAKEPOS_ORDER_PRINTER1_TO_USE'.$_SESSION["takeposterminal"])); // PRINT TO PRINTER 1
814  echo "';</script>";
815  }
816  $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='1' and fk_facture=".$invoice->id; // Set as printed
817  $db->query($sql);
818  $invoice->fetch($placeid); //Reload object after set lines as printed
819  $linestoprint = 0;
820 
821  foreach ($invoice->lines as $line) {
822  if ($line->special_code == "4") {
823  continue;
824  }
825  $c = new Categorie($db);
826  $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
827  $result = array_intersect($catsprinter2, $existing);
828  $count = count($result);
829  if ($count > 0) {
830  $linestoprint++;
831  $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='2' where rowid=".$line->id; //Set to print on printer 2
832  $db->query($sql);
833  $order_receipt_printer2 .= '<tr>'.$line->product_label.'<td class="right">'.$line->qty;
834  if (!empty($line->array_options['options_order_notes'])) {
835  $order_receipt_printer2 .= "<br>(".$line->array_options['options_order_notes'].")";
836  }
837  $order_receipt_printer2 .= '</td></tr>';
838  }
839  }
840  if (($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") && $linestoprint > 0) {
841  $invoice->fetch($placeid); //Reload object before send to printer
842  $printer->orderprinter = 2;
843  echo "<script>";
844  echo "var orderprinter2esc='";
845  $ret = $printer->sendToPrinter($invoice, getDolGlobalInt('TAKEPOS_TEMPLATE_TO_USE_FOR_ORDERS'.$_SESSION["takeposterminal"]), getDolGlobalInt('TAKEPOS_ORDER_PRINTER2_TO_USE'.$_SESSION["takeposterminal"])); // PRINT TO PRINTER 2
846  echo "';</script>";
847  }
848  $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='2' and fk_facture=".$invoice->id; // Set as printed
849  $db->query($sql);
850  $invoice->fetch($placeid); //Reload object after set lines as printed
851  $linestoprint = 0;
852 
853  foreach ($invoice->lines as $line) {
854  if ($line->special_code == "4") {
855  continue;
856  }
857  $c = new Categorie($db);
858  $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
859  $result = array_intersect($catsprinter3, $existing);
860  $count = count($result);
861  if ($count > 0) {
862  $linestoprint++;
863  $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='3' where rowid=".$line->id; //Set to print on printer 3
864  $db->query($sql);
865  $order_receipt_printer3 .= '<tr>'.$line->product_label.'<td class="right">'.$line->qty;
866  if (!empty($line->array_options['options_order_notes'])) {
867  $order_receipt_printer3 .= "<br>(".$line->array_options['options_order_notes'].")";
868  }
869  $order_receipt_printer3 .= '</td></tr>';
870  }
871  }
872  if (($conf->global->TAKEPOS_PRINT_METHOD == "receiptprinter" || $conf->global->TAKEPOS_PRINT_METHOD == "takeposconnector") && $linestoprint > 0) {
873  $invoice->fetch($placeid); //Reload object before send to printer
874  $printer->orderprinter = 3;
875  echo "<script>";
876  echo "var orderprinter3esc='";
877  $ret = $printer->sendToPrinter($invoice, getDolGlobalInt('TAKEPOS_TEMPLATE_TO_USE_FOR_ORDERS'.$_SESSION["takeposterminal"]), getDolGlobalInt('TAKEPOS_ORDER_PRINTER3_TO_USE'.$_SESSION["takeposterminal"])); // PRINT TO PRINTER 3
878  echo "';</script>";
879  }
880  $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='3' and fk_facture=".$invoice->id; // Set as printed
881  $db->query($sql);
882  $invoice->fetch($placeid); //Reload object after set lines as printed
883  }
884 
885  $sectionwithinvoicelink = '';
886  if ($action == "valid" || $action == "history" || $action == 'creditnote') {
887  $sectionwithinvoicelink .= '<!-- Section with invoice link -->'."\n";
888  $sectionwithinvoicelink .= '<span style="font-size:120%;" class="center">';
889  $sectionwithinvoicelink .= $invoice->getNomUrl(1, '', 0, 0, '', 0, 0, -1, '_backoffice')." - ";
890  $remaintopay = $invoice->getRemainToPay();
891  if ($remaintopay > 0) {
892  $sectionwithinvoicelink .= $langs->trans('RemainToPay').': <span class="amountremaintopay" style="font-size: unset">'.price($remaintopay, 1, $langs, 1, -1, -1, $conf->currency).'</span>';
893  } else {
894  if ($invoice->paye) {
895  $sectionwithinvoicelink .= '<span class="amountpaymentcomplete" style="font-size: unset">'.$langs->trans("Paid").'</span>';
896  } else {
897  $sectionwithinvoicelink .= $langs->trans('BillShortStatusValidated');
898  }
899  }
900  $sectionwithinvoicelink .= '</span><br>';
901  if (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") {
902  if (getDolGlobalString('TAKEPOS_PRINT_SERVER') && filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
903  $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposConnector('.$placeid.');">'.$langs->trans('PrintTicket').'</button>';
904  } else {
905  $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposPrinting('.$placeid.');">'.$langs->trans('PrintTicket').'</button>';
906  }
907  } elseif (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter") {
908  $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="DolibarrTakeposPrinting('.$placeid.');">'.$langs->trans('PrintTicket').'</button>';
909  } else {
910  $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print('.$placeid.');">'.$langs->trans('PrintTicket').'</button>';
911  if (getDolGlobalString('TAKEPOS_PRINT_WITHOUT_DETAILS')) {
912  $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="PrintBox('.$placeid.', \'without_details\');">'.$langs->trans('PrintWithoutDetails').'</button>';
913  }
914  if (getDolGlobalString('TAKEPOS_GIFT_RECEIPT')) {
915  $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print('.$placeid.', 1);">'.$langs->trans('GiftReceipt').'</button>';
916  }
917  }
918  if (getDolGlobalString('TAKEPOS_EMAIL_TEMPLATE_INVOICE') && $conf->global->TAKEPOS_EMAIL_TEMPLATE_INVOICE > 0) {
919  $sectionwithinvoicelink .= ' <button id="buttonsend" type="button" onclick="SendTicket('.$placeid.');">'.$langs->trans('SendTicket').'</button>';
920  }
921 
922  if ($remaintopay <= 0 && getDolGlobalString('TAKEPOS_AUTO_PRINT_TICKETS') && $action != "history") {
923  $sectionwithinvoicelink .= '<script type="text/javascript">$("#buttonprint").click();</script>';
924  }
925  }
926 }
927 
928 /*
929  * View
930  */
931 
932 $form = new Form($db);
933 
934 ?>
935 <script type="text/javascript">
936 var selectedline=0;
937 var selectedtext="";
938 <?php if ($action=="valid") echo "var place=0;";?> // Set to default place after close sale
939 var placeid=<?php echo ($placeid > 0 ? $placeid : 0); ?>;
940 $(document).ready(function() {
941  var idoflineadded = <?php echo (empty($idoflineadded) ? 0 : $idoflineadded); ?>;
942 
943  $('.posinvoiceline').click(function(){
944  console.log("Click done on "+this.id);
945  $('.posinvoiceline').removeClass("selected");
946  $(this).addClass("selected");
947  if (selectedline==this.id) return; // If is already selected
948  else selectedline=this.id;
949  selectedtext=$('#'+selectedline).find("td:first").html();
950  <?php
951  if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
952  print '$("#phonediv1").load("auto_order.php?action=editline&token='.newToken().'&placeid="+placeid+"&selectedline="+selectedline, function() {
953  });';
954  }
955  ?>
956  });
957 
958  /* Autoselect the line */
959  if (idoflineadded > 0)
960  {
961  console.log("Auto select "+idoflineadded);
962  $('.posinvoiceline#'+idoflineadded).click();
963  }
964 <?php
965 
966 if ($action == "order" && !empty($order_receipt_printer1)) {
967  if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
968  ?>
969  $.ajax({
970  type: "POST",
971  url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php',
972  data: 'invoice='+orderprinter1esc
973  });
974  <?php
975  } else {
976  ?>
977  $.ajax({
978  type: "POST",
979  url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
980  data: '<?php
981  print $headerorder.$order_receipt_printer1.$footerorder; ?>'
982  });
983  <?php
984  }
985 }
986 
987 if ($action == "order" && !empty($order_receipt_printer2)) {
988  if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
989  ?>
990  $.ajax({
991  type: "POST",
992  url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php?printer=2',
993  data: 'invoice='+orderprinter2esc
994  });
995  <?php
996  } else {
997  ?>
998  $.ajax({
999  type: "POST",
1000  url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print2',
1001  data: '<?php
1002  print $headerorder.$order_receipt_printer2.$footerorder; ?>'
1003  });
1004  <?php
1005  }
1006 }
1007 
1008 if ($action == "order" && !empty($order_receipt_printer3)) {
1009  if (filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1010  ?>
1011  $.ajax({
1012  type: "POST",
1013  url: '<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>/printer/index.php?printer=3',
1014  data: 'invoice='+orderprinter3esc
1015  });
1016  <?php
1017  }
1018 }
1019 
1020 // Set focus to search field
1021 if ($action == "search" || $action == "valid") {
1022  ?>
1023  parent.setFocusOnSearchField();
1024  <?php
1025 }
1026 
1027 
1028 if ($action == "temp" && !empty($ticket_printer1)) {
1029  ?>
1030  $.ajax({
1031  type: "POST",
1032  url: 'http://<?php print $conf->global->TAKEPOS_PRINT_SERVER; ?>:8111/print',
1033  data: '<?php
1034  print $header_soc.$header_ticket.$body_ticket.$ticket_printer1.$ticket_total.$footer_ticket; ?>'
1035  });
1036  <?php
1037 }
1038 
1039 if ($action == "search") {
1040  ?>
1041  $('#search').focus();
1042  <?php
1043 }
1044 
1045 ?>
1046 
1047 });
1048 
1049 function SendTicket(id)
1050 {
1051  console.log("Open box to select the Print/Send form");
1052  $.colorbox({href:"send.php?facid="+id, width:"70%", height:"30%", transition:"none", iframe:"true", title:'<?php echo dol_escape_js($langs->trans("SendTicket")); ?>'});
1053 }
1054 
1055 function PrintBox(id, action) {
1056  console.log("Open box before printing");
1057  $.colorbox({href:"printbox.php?facid="+id+"&action="+action, width:"80%", height:"200px", transition:"none", iframe:"true", title:"<?php echo $langs->trans("PrintWithoutDetails"); ?>"});
1058 }
1059 
1060 function Print(id, gift){
1061  console.log("Call Print() to generate the receipt.");
1062  $.colorbox({href:"receipt.php?facid="+id+"&gift="+gift, width:"40%", height:"90%", transition:"none", iframe:"true", title:'<?php echo dol_escape_js($langs->trans("PrintTicket")); ?>'});
1063 }
1064 
1065 function TakeposPrinting(id){
1066  var receipt;
1067  console.log("TakeposPrinting" + id);
1068  $.get("receipt.php?facid="+id, function(data, status){
1069  receipt=data.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '');
1070  $.ajax({
1071  type: "POST",
1072  url: 'http://<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>:8111/print',
1073  data: receipt
1074  });
1075  });
1076 }
1077 
1078 function TakeposConnector(id){
1079  console.log("TakeposConnector" + id);
1080  $.get("<?php echo DOL_URL_ROOT; ?>/takepos/ajax/ajax.php?action=printinvoiceticket&term=<?php echo urlencode(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : ''); ?>&id="+id+"&token=<?php echo currentToken(); ?>", function(data, status) {
1081  $.ajax({
1082  type: "POST",
1083  url: '<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>/printer/index.php',
1084  data: 'invoice='+data
1085  });
1086  });
1087 }
1088 
1089 function DolibarrTakeposPrinting(id) {
1090  console.log("DolibarrTakeposPrinting Printing invoice ticket " + id)
1091  $.ajax({
1092  type: "GET",
1093  data: { token: '<?php echo currentToken(); ?>' },
1094  url: "<?php print DOL_URL_ROOT.'/takepos/ajax/ajax.php?action=printinvoiceticket&term='.urlencode(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '').'&id='; ?>" + id,
1095  });
1096 }
1097 
1098 function CreditNote() {
1099  $("#poslines").load("invoice.php?action=creditnote&token=<?php echo newToken() ?>&invoiceid="+placeid, function() {
1100  });
1101 }
1102 
1103 function SetNote() {
1104  $("#poslines").load("invoice.php?action=addnote&token=<?php echo newToken() ?>&invoiceid="+placeid+"&idline="+selectedline, { "addnote": $("#textinput").val() });
1105 }
1106 
1107 
1108 $( document ).ready(function() {
1109  console.log("Set customer info and sales in header placeid=<?php echo $placeid; ?> status=<?php echo $invoice->statut; ?>");
1110 
1111  <?php
1112  $s = $langs->trans("Customer");
1113  if ($invoice->id > 0 && ($invoice->socid != $conf->global->$constforcompanyid)) {
1114  $s = $soc->name;
1115  }
1116  ?>
1117 
1118  $("#customerandsales").html('');
1119  $("#shoppingcart").html('');
1120 
1121  $("#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>');
1122 
1123  <?php
1124  $sql = "SELECT rowid, datec, ref FROM ".MAIN_DB_PREFIX."facture";
1125  if (empty($conf->global->TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED)) {
1126  // By default, only invoices with a ref not already defined can in list of open invoice we can edit.
1127  $sql .= " WHERE ref LIKE '(PROV-POS".$db->escape(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '')."-0%' AND entity IN (".getEntity('invoice').")";
1128  } else {
1129  // If TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED set, we show also draft invoice that already has a reference defined
1130  $sql .= " WHERE pos_source = '".$db->escape($_SESSION["takeposterminal"])."'";
1131  $sql .= " AND module_source = 'takepos'";
1132  $sql .= " AND entity IN (".getEntity('invoice').")";
1133  }
1134 
1135  $sql .= $db->order('datec', 'ASC');
1136  $resql = $db->query($sql);
1137  if ($resql) {
1138  $max_sale = 0;
1139  while ($obj = $db->fetch_object($resql)) {
1140  echo '$("#shoppingcart").append(\'';
1141  echo '<a class="valignmiddle" title="'.dol_escape_js($langs->trans("SaleStartedAt", dol_print_date($db->jdate($obj->datec), '%H:%M', 'tzuser')).' - '.$obj->ref).'" onclick="place=\\\'';
1142  $num_sale = str_replace(")", "", str_replace("(PROV-POS".$_SESSION["takeposterminal"]."-", "", $obj->ref));
1143  echo $num_sale;
1144  if (str_replace("-", "", $num_sale) > $max_sale) {
1145  $max_sale = str_replace("-", "", $num_sale);
1146  }
1147  echo '\\\'; invoiceid=\\\'';
1148  echo $obj->rowid;
1149  echo '\\\'; Refresh();">';
1150  if ($placeid == $obj->rowid) {
1151  echo "<b>";
1152  }
1153  echo '<span class="fa fa-shopping-cart paddingright"></span>'.dol_print_date($db->jdate($obj->datec), '%H:%M', 'tzuser');
1154  if ($placeid == $obj->rowid) {
1155  echo "</b>";
1156  }
1157  echo '</a>\');';
1158  }
1159  echo '$("#shoppingcart").append(\'<a onclick="place=\\\'0-';
1160  echo $max_sale + 1;
1161  echo '\\\'; invoiceid=0; Refresh();"><div><span class="fa fa-plus" title="'.dol_escape_htmltag($langs->trans("StartAParallelSale")).'"><span class="fa fa-shopping-cart"></span></div></a>\');';
1162  } else {
1163  dol_print_error($db);
1164  }
1165 
1166  $s = '';
1167 
1168  $idwarehouse = 0;
1169  $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
1170  if (isModEnabled('stock')) {
1171  if (getDolGlobalString("$constantforkey") != "1") {
1172  $constantforkey = 'CASHDESK_ID_WAREHOUSE'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
1173  $idwarehouse = getDolGlobalString($constantforkey);
1174  if ($idwarehouse > 0) {
1175  $s = '<span class="small">';
1176  $warehouse = new Entrepot($db);
1177  $warehouse->fetch($idwarehouse);
1178  $s .= '<span class="hideonsmartphone">'.$langs->trans("Warehouse").'<br></span>'.$warehouse->ref;
1179  if ($warehouse->statut == Entrepot::STATUS_CLOSED) {
1180  $s .= ' ('.$langs->trans("Closed").')';
1181  }
1182  $s .= '</span>';
1183  print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1184  print '$("#infowarehouse").css("display", "inline-block");';
1185  } else {
1186  $s = '<span class="small hideonsmartphone">';
1187  $s .= $langs->trans("StockChangeDisabled").'<br>'.$langs->trans("NoWarehouseDefinedForTerminal");
1188  $s .= '</span>';
1189  print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1190  if (!empty($conf->dol_optimize_smallscreen)) {
1191  print '$("#infowarehouse").css("display", "none");';
1192  }
1193  }
1194  } else {
1195  $s = '<span class="small hideonsmartphone">'.$langs->trans("StockChangeDisabled").'</span>';
1196  print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1197  if (!empty($conf->dol_optimize_smallscreen)) {
1198  print '$("#infowarehouse").css("display", "none");';
1199  }
1200  }
1201  }
1202 
1203 
1204  // Module Adherent
1205  $s = '';
1206  if (isModEnabled('adherent') && $invoice->socid > 0 && $invoice->socid != $conf->global->$constforcompanyid) {
1207  $s = '<span class="small">';
1208  require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1209  $langs->load("members");
1210  $s .= $langs->trans("Member").': ';
1211  $adh = new Adherent($db);
1212  $result = $adh->fetch('', '', $invoice->socid);
1213  if ($result > 0) {
1214  $adh->ref = $adh->getFullName($langs);
1215  if (empty($adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED ) {
1216  $s .= "<s>";
1217  }
1218  $s .= $adh->getFullName($langs);
1219  $s .= ' - '.$adh->type;
1220  if ($adh->datefin) {
1221  $s .= '<br>'.$langs->trans("SubscriptionEndDate").': '.dol_print_date($adh->datefin, 'day');
1222  if ($adh->hasDelay()) {
1223  $s .= " ".img_warning($langs->trans("Late"));
1224  }
1225  } else {
1226  $s .= '<br>'.$langs->trans("SubscriptionNotReceived");
1227  if ($adh->statut > 0) {
1228  $s .= " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft and not terminated
1229  }
1230  }
1231  if (empty($adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {
1232  $s .= "</s>";
1233  }
1234  } else {
1235  $s .= '<br>'.$langs->trans("ThirdpartyNotLinkedToMember");
1236  }
1237  $s .= '</span>';
1238  }
1239  ?>
1240  $("#moreinfo").html('<?php print dol_escape_js($s); ?>');
1241 
1242 });
1243 
1244 
1245 <?php
1246 if (!empty($conf->global->TAKEPOS_CUSTOMER_DISPLAY)) {
1247  echo "function CustomerDisplay(){";
1248  echo "var line1='".$CUSTOMER_DISPLAY_line1."'.substring(0,20);";
1249  echo "line1=line1.padEnd(20);";
1250  echo "var line2='".$CUSTOMER_DISPLAY_line2."'.substring(0,20);";
1251  echo "line2=line2.padEnd(20);";
1252  echo "$.ajax({
1253  type: 'GET',
1254  data: { text: line1+line2 },
1255  url: '".getDolGlobalString('TAKEPOS_PRINT_SERVER')."/display/index.php',
1256  });";
1257  echo "}";
1258 }
1259 ?>
1260 
1261 </script>
1262 
1263 <?php
1264 // Add again js for footer because this content is injected into index.php page so all init
1265 // for tooltip and other js beautifiers must be reexecuted too.
1266 if (!empty($conf->use_javascript_ajax)) {
1267  print "\n".'<!-- Includes JS Footer of Dolibarr -->'."\n";
1268  print '<script src="'.DOL_URL_ROOT.'/core/js/lib_foot.js.php?lang='.$langs->defaultlang.'"></script>'."\n";
1269 }
1270 
1271 print '<!-- invoice.php place='.(int) $place.' invoice='.$invoice->ref.' mobilepage='.(empty($mobilepage) ? '' : $mobilepage).' $_SESSION["basiclayout"]='.(empty($_SESSION["basiclayout"])?'':$_SESSION["basiclayout"]).' conf->global->TAKEPOS_BAR_RESTAURANT='.getDolGlobalString('TAKEPOS_BAR_RESTAURANT').' -->'."\n";
1272 print '<div class="div-table-responsive-no-min invoice">';
1273 print '<table id="tablelines" class="noborder noshadow postablelines" width="100%">';
1274 if ($sectionwithinvoicelink && ($mobilepage == "invoice" || $mobilepage == "")) {
1275  if (!empty($conf->global->TAKEPOS_SHOW_HT)) {
1276  print '<tr><td colspan="5">'.$sectionwithinvoicelink.'</td></tr>';
1277  } else {
1278  print '<tr><td colspan="4">'.$sectionwithinvoicelink.'</td></tr>';
1279  }
1280 }
1281 print '<tr class="liste_titre nodrag nodrop">';
1282 print '<td class="linecoldescription">';
1283 // In phone version only show when it is invoice page
1284 if (empty($mobilepage) || $mobilepage == "invoice") {
1285  print '<input type="hidden" name="invoiceid" id="invoiceid" value="'.$invoice->id.'">';
1286 }
1287 if (getDolGlobalString('TAKEPOS_BAR_RESTAURANT')) {
1288  $sql = "SELECT floor, label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place);
1289  $resql = $db->query($sql);
1290  $obj = $db->fetch_object($resql);
1291  if ($obj) {
1292  $label = $obj->label;
1293  $floor = $obj->floor;
1294  }
1295  if ($mobilepage == "invoice" || $mobilepage == "") {
1296  // If not on smartphone version or if it is the invoice page
1297  //print 'mobilepage='.$mobilepage;
1298  print '<span class="opacitymedium">'.$langs->trans('Place')."</span> <b>".(empty($label) ? '?' : $label)."</b><br>";
1299  print '<span class="opacitymedium">'.$langs->trans('Floor')."</span> <b>".(empty($floor) ? '?' : $floor)."</b>";
1300  } elseif (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1301  print $mysoc->name;
1302  } elseif ($mobilepage == "cats") {
1303  print $langs->trans('Category');
1304  } elseif ($mobilepage == "products") {
1305  print $langs->trans('Label');
1306  }
1307 } else {
1308  print $langs->trans("Products");
1309 }
1310 print '</td>';
1311 
1312 // complete header by hook
1313 $parameters=array();
1314 $reshook=$hookmanager->executeHooks('completeTakePosInvoiceHeader', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1315 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1316 print $hookmanager->resPrint;
1317 
1318 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1319  print '<td class="linecolqty right">'.$langs->trans('ReductionShort').'</td>';
1320  print '<td class="linecolqty right">'.$langs->trans('Qty').'</td>';
1321  if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1322  print '<td class="linecolht right nowraponall">';
1323  print '<span class="opacitymedium small">' . $langs->trans('TotalHTShort') . '</span><br>';
1324  // In phone version only show when it is invoice page
1325  if (empty($mobilepage) || $mobilepage == "invoice") {
1326  print '<span id="linecolht-span-total" style="font-size:1.3em; font-weight: bold;">' . price($invoice->total_ht, 1, '', 1, -1, -1, $conf->currency) . '</span>';
1327  if (isModEnabled('multicurrency') && $_SESSION["takeposcustomercurrency"] != "" && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1328  //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1329  include_once DOL_DOCUMENT_ROOT . '/multicurrency/class/multicurrency.class.php';
1330  $multicurrency = new MultiCurrency($db);
1331  $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1332  print '<br><span id="linecolht-span-total" style="font-size:0.9em; font-style:italic;">(' . price($invoice->total_ht * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')</span>';
1333  }
1334  print '</td>';
1335  }
1336  print '</td>';
1337  }
1338  print '<td class="linecolht right nowraponall">';
1339  print '<span class="opacitymedium small">'.$langs->trans('TotalTTCShort').'</span><br>';
1340  // In phone version only show when it is invoice page
1341  if (empty($mobilepage) || $mobilepage == "invoice") {
1342  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>';
1343  if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1344  //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1345  include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
1346  $multicurrency = new MultiCurrency($db);
1347  $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1348  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>';
1349  }
1350  print '</td>';
1351  }
1352  print '</td>';
1353 } elseif ($mobilepage == "invoice") {
1354  print '<td class="linecolqty right">'.$langs->trans('Qty').'</td>';
1355 }
1356 print "</tr>\n";
1357 
1358 
1359 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1360  if ($mobilepage == "cats") {
1361  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1362  $categorie = new Categorie($db);
1363  $categories = $categorie->get_full_arbo('product');
1364  $htmlforlines = '';
1365  foreach ($categories as $row) {
1366  if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1367  $htmlforlines .= '<div class="leftcat';
1368  } else {
1369  $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1370  }
1371  $htmlforlines .= '" onclick="LoadProducts('.$row['id'].');">';
1372  if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1373  $htmlforlines .= '<img class="imgwrapper" width="33%" src="'.DOL_URL_ROOT.'/takepos/public/auto_order.php?genimg=cat&query=cat&id='.$row['id'].'"><br>';
1374  } else {
1375  $htmlforlines .= '<td class="left">';
1376  }
1377  $htmlforlines .= $row['label'];
1378  if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1379  $htmlforlines .= '</div>'."\n";
1380  } else {
1381  $htmlforlines .= '</td></tr>'."\n";
1382  }
1383  }
1384  $htmlforlines .= '</table>';
1385  $htmlforlines .= '</table>';
1386  print $htmlforlines;
1387  }
1388 
1389  if ($mobilepage == "products") {
1390  require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1391  $object = new Categorie($db);
1392  $catid = GETPOST('catid', 'int');
1393  $result = $object->fetch($catid);
1394  $prods = $object->getObjectsInCateg("product");
1395  $htmlforlines = '';
1396  foreach ($prods as $row) {
1397  if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1398  $htmlforlines .= '<div class="leftcat';
1399  } else {
1400  $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1401  }
1402  $htmlforlines .= '" onclick="AddProduct(\''.$place.'\', '.$row->id.')">';
1403  if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1404  $htmlforlines .= '<img class="imgwrapper" width="33%" src="'.DOL_URL_ROOT.'/takepos/public/auto_order.php?genimg=pro&query=pro&id='.$row->id.'"><br>';
1405  $htmlforlines .= $row->label.''.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency);
1406  $htmlforlines .= '</div>'."\n";
1407  } else {
1408  $htmlforlines .= '<td class="left">';
1409  $htmlforlines .= $row->label;
1410  $htmlforlines .= '<div class="right">'.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency).'</div>';
1411  $htmlforlines .= '</tr>'."\n";
1412  }
1413  }
1414  $htmlforlines .= '</table>';
1415  print $htmlforlines;
1416  }
1417 
1418  if ($mobilepage == "places") {
1419  $sql = "SELECT rowid, entity, label, leftpos, toppos, floor FROM ".MAIN_DB_PREFIX."takepos_floor_tables";
1420  $resql = $db->query($sql);
1421  $rows = array();
1422  $htmlforlines = '';
1423  while ($row = $db->fetch_array($resql)) {
1424  $rows[] = $row;
1425  $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1426  $htmlforlines .= '" onclick="LoadPlace(\''.$row['label'].'\')">';
1427  $htmlforlines .= '<td class="left">';
1428  $htmlforlines .= $row['label'];
1429  $htmlforlines .= '</td>';
1430  $htmlforlines .= '</tr>'."\n";
1431  }
1432  $htmlforlines .= '</table>';
1433  print $htmlforlines;
1434  }
1435 }
1436 
1437 if ($placeid > 0) {
1438  //In Phone basic layout hide some content depends situation
1439  if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1 && $mobilepage != "invoice" && $action != "order") {
1440  return;
1441  }
1442 
1443  if (is_array($invoice->lines) && count($invoice->lines)) {
1444  print '<!-- invoice.php show lines of invoices -->'."\n";
1445  $tmplines = array_reverse($invoice->lines);
1446  $htmlsupplements = array();
1447  foreach ($tmplines as $line) {
1448  if ($line->fk_parent_line != false) {
1449  $htmlsupplements[$line->fk_parent_line] .= '<tr class="drag drop oddeven posinvoiceline';
1450  if ($line->special_code == "4") {
1451  $htmlsupplements[$line->fk_parent_line] .= ' order';
1452  }
1453  $htmlsupplements[$line->fk_parent_line] .= '" id="'.$line->id.'"';
1454  if ($line->special_code == "4") {
1455  $htmlsupplements[$line->fk_parent_line] .= ' title="'.dol_escape_htmltag($langs->trans("AlreadyPrinted")).'"';
1456  }
1457  $htmlsupplements[$line->fk_parent_line] .= '>';
1458  $htmlsupplements[$line->fk_parent_line] .= '<td class="left">';
1459  $htmlsupplements[$line->fk_parent_line] .= img_picto('', 'rightarrow');
1460  if ($line->product_label) {
1461  $htmlsupplements[$line->fk_parent_line] .= $line->product_label;
1462  }
1463  if ($line->product_label && $line->desc) {
1464  $htmlsupplements[$line->fk_parent_line] .= '<br>';
1465  }
1466  if ($line->product_label != $line->desc) {
1467  $firstline = dolGetFirstLineOfText($line->desc);
1468  if ($firstline != $line->desc) {
1469  $htmlsupplements[$line->fk_parent_line] .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
1470  } else {
1471  $htmlsupplements[$line->fk_parent_line] .= $line->desc;
1472  }
1473  }
1474  $htmlsupplements[$line->fk_parent_line] .= '</td>';
1475 
1476  // complete line by hook
1477  $parameters=array('line' => $line);
1478  $reshook=$hookmanager->executeHooks('completeTakePosInvoiceParentLine', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1479  if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1480  $htmlsupplements[$line->fk_parent_line] .= $hookmanager->resPrint;
1481 
1482  if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1483  $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.vatrate($line->remise_percent, true).'</td>';
1484  $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.$line->qty.'</td>';
1485  $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.price($line->total_ttc).'</td>';
1486  }
1487  $htmlsupplements[$line->fk_parent_line] .= '</tr>'."\n";
1488  continue;
1489  }
1490  $htmlforlines = '';
1491 
1492  $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1493  if ($line->special_code == "4") {
1494  $htmlforlines .= ' order';
1495  }
1496  $htmlforlines .= '" id="'.$line->id.'"';
1497  if ($line->special_code == "4") {
1498  $htmlforlines .= ' title="'.dol_escape_htmltag($langs->trans("AlreadyPrinted")).'"';
1499  }
1500  $htmlforlines .= '>';
1501  $htmlforlines .= '<td class="left">';
1502  if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1503  $htmlforlines .= '<span class="phoneqty">'.$line->qty."</span> x ";
1504  }
1505  if (isset($line->product_type)) {
1506  if (empty($line->product_type)) {
1507  $htmlforlines .= img_object('', 'product').' ';
1508  } else {
1509  $htmlforlines .= img_object('', 'service').' ';
1510  }
1511  }
1512  if (empty($conf->global->TAKEPOS_SHOW_N_FIRST_LINES)) {
1513  $tooltiptext = '';
1514  if ($line->product_ref) {
1515  $tooltiptext .= '<b>'.$langs->trans("Ref").'</b> : '.$line->product_ref.'<br>';
1516  $tooltiptext .= '<b>'.$langs->trans("Label").'</b> : '.$line->product_label.'<br>';
1517  if ($line->product_label != $line->desc) {
1518  if ($line->desc) {
1519  $tooltiptext .= '<br>';
1520  }
1521  $tooltiptext .= $line->desc;
1522  }
1523  }
1524  if ($conf->global->TAKEPOS_SHOW_PRODUCT_REFERENCE == 1) {
1525  $htmlforlines .= $form->textwithpicto($line->product_label ? '<b>' . $line->product_ref . '</b> - ' . $line->product_label : dolGetFirstLineOfText($line->desc, 1), $tooltiptext);
1526  } else {
1527  $htmlforlines .= $form->textwithpicto($line->product_label ? $line->product_label : ($line->product_ref ? $line->product_ref : dolGetFirstLineOfText($line->desc, 1)), $tooltiptext);
1528  }
1529  } else {
1530  if ($line->product_label) {
1531  $htmlforlines .= $line->product_label;
1532  }
1533  if ($line->product_label != $line->desc) {
1534  if ($line->product_label && $line->desc) {
1535  $htmlforlines .= '<br>';
1536  }
1537  $firstline = dolGetFirstLineOfText($line->desc, $conf->global->TAKEPOS_SHOW_N_FIRST_LINES);
1538  if ($firstline != $line->desc) {
1539  $htmlforlines .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
1540  } else {
1541  $htmlforlines .= $line->desc;
1542  }
1543  }
1544  }
1545  if (!empty($line->array_options['options_order_notes'])) {
1546  $htmlforlines .= "<br>(".$line->array_options['options_order_notes'].")";
1547  }
1548  if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1549  $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>';
1550  }
1551  if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1552  $moreinfo = '';
1553  $moreinfo .= $langs->transcountry("TotalHT", $mysoc->country_code).': '.price($line->total_ht);
1554  if ($line->vat_src_code) {
1555  $moreinfo .= '<br>'.$langs->trans("VATCode").': '.$line->vat_src_code;
1556  }
1557  $moreinfo .= '<br>'.$langs->transcountry("TotalVAT", $mysoc->country_code).': '.price($line->total_tva);
1558  $moreinfo .= '<br>'.$langs->transcountry("TotalLT1", $mysoc->country_code).': '.price($line->total_localtax1);
1559  $moreinfo .= '<br>'.$langs->transcountry("TotalLT2", $mysoc->country_code).': '.price($line->total_localtax2);
1560  $moreinfo .= '<br>'.$langs->transcountry("TotalTTC", $mysoc->country_code).': '.price($line->total_ttc);
1561  //$moreinfo .= $langs->trans("TotalHT").': '.$line->total_ht;
1562  if ($line->date_start || $line->date_end) {
1563  $htmlforlines .= '<br><div class="clearboth nowraponall">'.get_date_range($line->date_start, $line->date_end).'</div>';
1564  }
1565  $htmlforlines .= '</td>';
1566 
1567  // complete line by hook
1568  $parameters=array('line' => $line);
1569  $reshook=$hookmanager->executeHooks('completeTakePosInvoiceLine', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1570  if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1571  $htmlforlines .= $hookmanager->resPrint;
1572 
1573  $htmlforlines .= '<td class="right">'.vatrate($line->remise_percent, true).'</td>';
1574  $htmlforlines .= '<td class="right">';
1575  if (isModEnabled('stock') && !empty($user->rights->stock->mouvement->lire)) {
1576  $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
1577  if (!empty($conf->global->$constantforkey) && $line->fk_product > 0 && empty($conf->global->TAKEPOS_HIDE_STOCK_ON_LINE)) {
1578  $sql = "SELECT e.rowid, e.ref, e.lieu, e.fk_parent, e.statut, ps.reel, ps.rowid as product_stock_id, p.pmp";
1579  $sql .= " FROM ".MAIN_DB_PREFIX."entrepot as e,";
1580  $sql .= " ".MAIN_DB_PREFIX."product_stock as ps";
1581  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = ps.fk_product";
1582  $sql .= " WHERE ps.reel != 0";
1583  $sql .= " AND ps.fk_entrepot = ".((int) $conf->global->$constantforkey);
1584  $sql .= " AND e.entity IN (".getEntity('stock').")";
1585  $sql .= " AND ps.fk_product = ".((int) $line->fk_product);
1586  $resql = $db->query($sql);
1587  if ($resql) {
1588  $obj = $db->fetch_object($resql);
1589  $stock_real = price2num($obj->reel, 'MS');
1590  $htmlforlines .= $line->qty;
1591  if ($line->qty && $line->qty > $stock_real) {
1592  $htmlforlines .= '<span style="color: var(--amountremaintopaycolor)">';
1593  }
1594  $htmlforlines .= ' <span class="posstocktoolow">('.$langs->trans("Stock").' '.$stock_real.')</span>';
1595  if ($line->qty && $line->qty > $stock_real) {
1596  $htmlforlines .= "</span>";
1597  }
1598  } else {
1599  dol_print_error($db);
1600  }
1601  } else {
1602  $htmlforlines .= $line->qty;
1603  }
1604  } else {
1605  $htmlforlines .= $line->qty;
1606  }
1607 
1608  $htmlforlines .= '</td>';
1609  if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1610  $htmlforlines .= '<td class="right classfortooltip" title="'.$moreinfo.'">';
1611  $htmlforlines .= price($line->total_ht, 1, '', 1, -1, -1, $conf->currency);
1612  if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1613  //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1614  include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
1615  $multicurrency = new MultiCurrency($db);
1616  $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1617  $htmlforlines .= '<br><span id="linecolht-span-total" style="font-size:0.9em; font-style:italic;">('.price($line->total_ht * $multicurrency->rate->rate).' '.$_SESSION["takeposcustomercurrency"].')</span>';
1618  }
1619  $htmlforlines .= '</td>';
1620  }
1621  $htmlforlines .= '<td class="right classfortooltip" title="'.$moreinfo.'">';
1622  $htmlforlines .= price($line->total_ttc, 1, '', 1, -1, -1, $conf->currency);
1623  if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1624  //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1625  include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
1626  $multicurrency = new MultiCurrency($db);
1627  $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1628  $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>';
1629  }
1630  $htmlforlines .= '</td>';
1631  }
1632  $htmlforlines .= '</tr>'."\n";
1633  $htmlforlines .= empty($htmlsupplements[$line->id]) ? '' : $htmlsupplements[$line->id];
1634 
1635  print $htmlforlines;
1636  }
1637  } else {
1638  print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">'.$langs->trans("Empty").'</span></td><td></td><td></td><td></td>';
1639  if (!empty($conf->global->TAKEPOS_SHOW_HT)) {
1640  print '<td></td>';
1641  }
1642  print '</tr>';
1643  }
1644 } else { // No invoice generated yet
1645  print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">'.$langs->trans("Empty").'</span></td><td></td><td></td><td></td>';
1646 
1647  if (!empty($conf->global->TAKEPOS_SHOW_HT)) {
1648  print '<td></td>';
1649  }
1650  print '</tr>';
1651 }
1652 
1653 print '</table>';
1654 
1655 if (($action == "valid" || $action == "history") && $invoice->type != Facture::TYPE_CREDIT_NOTE) {
1656  print '<button id="buttonprint" type="button" onclick="ModalBox(\'ModalCreditNote\')">'.$langs->trans('CreateCreditNote').'</button>';
1657 }
1658 
1659 
1660 if ($action == "search") {
1661  print '<center>
1662  <input type="text" id="search" class="input-search-takepos" name="search" onkeyup="Search2(\'\', null);" style="width: 80%; font-size: 150%;" placeholder="'.dol_escape_htmltag($langs->trans('Search')).'">
1663  </center>';
1664 }
1665 
1666 print '</div>';
Facture\STATUS_DRAFT
const STATUS_DRAFT
Draft status.
Definition: facture.class.php:412
Societe
Class to manage third parties objects (customers, suppliers, prospects...)
Definition: societe.class.php:48
dol_htmloutput_errors
dol_htmloutput_errors($mesgstring='', $mesgarray=array(), $keepembedded=0)
Print formated error messages to output (Used to show messages on html output).
Definition: functions.lib.php:8367
dolReceiptPrinter
Class to manage Receipt Printers.
Definition: dolreceiptprinter.class.php:119
GETPOST
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Definition: functions.lib.php:484
dol_print_error
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
Definition: functions.lib.php:4844
fail
if(empty($user->rights->takepos->run) &&!defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) if((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT')==1 && $conf->browser->layout=='phone')||defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) fail($message)
Abort invoice creationg with a given error message.
Definition: invoice.php:111
top_htmlhead
top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $disableforlogin=0, $disablenofollow=0, $disablenoindex=0)
Ouput html header of a page.
Definition: main.inc.php:1482
$form
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:142
rowid
print *****$script_file(".$version.") pid c cd cd cd description as p label as s rowid
Definition: email_expire_services_to_representatives.php:79
Categorie
Class to manage categories.
Definition: categorie.class.php:47
Facture
Class to manage invoices.
Definition: facture.class.php:60
price2num
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
Definition: functions.lib.php:5661
dol_print_date
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
Definition: functions.lib.php:2514
MultiCurrency
Class Currency.
Definition: multicurrency.class.php:39
getEntity
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
Definition: functions.lib.php:148
get_localtax
get_localtax($vatrate, $local, $thirdparty_buyer="", $thirdparty_seller="", $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate,...
Definition: functions.lib.php:5837
dol_syslog
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
Definition: functions.lib.php:1603
Adherent
Class to manage members of a foundation.
Definition: adherent.class.php:46
getDolGlobalString
if(!function_exists('utf8_encode')) if(!function_exists('utf8_decode')) getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
Definition: functions.lib.php:80
Adherent\STATUS_EXCLUDED
const STATUS_EXCLUDED
Excluded.
Definition: adherent.class.php:361
get_default_tva
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) VAT...
Definition: functions.lib.php:6304
isModEnabled
isModEnabled($module)
Is Dolibarr module enabled.
Definition: functions.lib.php:105
Facture\TYPE_CREDIT_NOTE
const TYPE_CREDIT_NOTE
Credit note invoice.
Definition: facture.class.php:392
Paiement
Class to manage payments of customer invoices.
Definition: paiement.class.php:41
GETPOSTISSET
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
Definition: functions.lib.php:386
Entrepot\STATUS_CLOSED
const STATUS_CLOSED
Warehouse closed, inactive.
Definition: entrepot.class.php:151
Product
Class to manage products or services.
Definition: product.class.php:46
Form
Class to manage generation of HTML components Only common components must be here.
Definition: html.form.class.php:52
Entrepot
Class to manage warehouses.
Definition: entrepot.class.php:35
dol_now
dol_now($mode='auto')
Return date for now.
Definition: functions.lib.php:2845
$resql
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->rights->fournisseur->facture->lire)||(isModEnabled('supplier_invoice') && $user->rights->supplier_invoice->lire)) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:742
price
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
Definition: functions.lib.php:5541
setEventMessages
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
Definition: functions.lib.php:8137
accessforbidden
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program Calling this function terminate execution ...
Definition: security.lib.php:933
getDolGlobalInt
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
Definition: functions.lib.php:93
Facture\TYPE_SITUATION
const TYPE_SITUATION
Situation invoice.
Definition: facture.class.php:407
type
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition: repair.php:119
Productbatch\BATCH_RULE_SELLBY_EATBY_DATES_FIRST
const BATCH_RULE_SELLBY_EATBY_DATES_FIRST
Batches rules.
Definition: productbatch.class.php:36