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