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