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