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