dolibarr 21.0.4
invoice.php
Go to the documentation of this file.
1<?php
29// if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Not disabled cause need to load personalized language
30// if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Not disabled cause need to load personalized language
31// if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1');
32// if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1');
33
34if (!defined('NOTOKENRENEWAL')) {
35 define('NOTOKENRENEWAL', '1');
36}
37if (!defined('NOREQUIREMENU')) {
38 define('NOREQUIREMENU', '1');
39}
40if (!defined('NOREQUIREHTML')) {
41 define('NOREQUIREHTML', '1');
42}
43if (!defined('NOREQUIREAJAX')) {
44 define('NOREQUIREAJAX', '1');
45}
46
47// Load Dolibarr environment
48if (!defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
49 require '../main.inc.php';
50}
51require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
52require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
53require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
54require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
55require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
65$hookmanager->initHooks(array('takeposinvoice'));
66
67$langs->loadLangs(array("companies", "commercial", "bills", "cashdesk", "stocks", "banks"));
68
69$action = GETPOST('action', 'aZ09');
70$idproduct = GETPOSTINT('idproduct');
71$place = (GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : 0); // $place is id of table for Bar or Restaurant
72$placeid = 0; // $placeid is ID of invoice
73$mobilepage = GETPOST('mobilepage', 'alpha');
74
75// Terminal is stored into $_SESSION["takeposterminal"];
76
77if (!$user->hasRight('takepos', 'run') && !defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
78 accessforbidden('No permission to use the TakePOS');
79}
80
81if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
82 // DIRECT LINK TO THIS PAGE FROM MOBILE AND NO TERMINAL SELECTED
83 if ($_SESSION["takeposterminal"] == "") {
84 if (getDolGlobalString('TAKEPOS_NUM_TERMINALS') == "1") {
85 $_SESSION["takeposterminal"] = 1;
86 } else {
87 header("Location: ".DOL_URL_ROOT."/takepos/index.php");
88 exit;
89 }
90 }
91}
92
93
94$takeposterminal = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '';
95
96// When session has expired (selected terminal has been lost from session), redirect to the terminal selection.
97if (empty($takeposterminal)) {
98 if (getDolGlobalInt('TAKEPOS_NUM_TERMINALS') == 1) {
99 $_SESSION["takeposterminal"] = 1; // Use terminal 1 if there is only 1 terminal
100 $takeposterminal = 1;
101 } elseif (!empty($_COOKIE["takeposterminal"])) {
102 $_SESSION["takeposterminal"] = preg_replace('/[^a-zA-Z0-9_\-]/', '', $_COOKIE["takeposterminal"]); // Restore takeposterminal from previous session
103 $takeposterminal = $_SESSION["takeposterminal"];
104 } else {
105 print <<<SCRIPT
106<script language="javascript">
107 $( document ).ready(function() {
108 ModalBox('ModalTerminal');
109 });
110</script>
111SCRIPT;
112 exit;
113 }
114}
115
116
123function fail($message)
124{
125 header($_SERVER['SERVER_PROTOCOL'].' 500 Internal Server Error', true, 500);
126 die($message);
127}
128
129
130
131$number = GETPOST('number', 'alpha');
132$idline = GETPOSTINT('idline');
133$selectedline = GETPOSTINT('selectedline');
134$desc = GETPOST('desc', 'alphanohtml');
135$pay = GETPOST('pay', 'aZ09');
136$amountofpayment = GETPOSTFLOAT('amount');
137
138$invoiceid = GETPOSTINT('invoiceid');
139
140$paycode = $pay;
141if ($pay == 'cash') {
142 $paycode = 'LIQ'; // For backward compatibility
143}
144if ($pay == 'card') {
145 $paycode = 'CB'; // For backward compatibility
146}
147if ($pay == 'cheque') {
148 $paycode = 'CHQ'; // For backward compatibility
149}
150
151// Retrieve paiementid
152$paiementid = 0;
153if ($paycode) {
154 $sql = "SELECT id FROM ".MAIN_DB_PREFIX."c_paiement";
155 $sql .= " WHERE entity IN (".getEntity('c_paiement').")";
156 $sql .= " AND code = '".$db->escape($paycode)."'";
157 $resql = $db->query($sql);
158 if ($resql) {
159 $obj = $db->fetch_object($resql);
160 if ($obj) {
161 $paiementid = $obj->id;
162 }
163 }
164}
165
166$invoice = new Facture($db);
167if ($invoiceid > 0) {
168 $ret = $invoice->fetch($invoiceid);
169} else {
170 $ret = $invoice->fetch('', '(PROV-POS'.$takeposterminal.'-'.$place.')');
171}
172if ($ret > 0) {
173 $placeid = $invoice->id;
174}
175
176$constforcompanyid = 'CASHDESK_ID_THIRDPARTY'.$takeposterminal;
177
178$soc = new Societe($db);
179if ($invoice->socid > 0) {
180 $soc->fetch($invoice->socid);
181} else {
182 $soc->fetch(getDolGlobalString($constforcompanyid));
183}
184
185// Assign a default project, if relevant
186if (isModEnabled('project') && getDolGlobalInt("CASHDESK_ID_PROJECT".$takeposterminal)) {
187 $invoice->fk_project = getDolGlobalInt("CASHDESK_ID_PROJECT".$takeposterminal);
188}
189
190// Change the currency of invoice if it was modified
191if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"])) {
192 if ($invoice->multicurrency_code != $_SESSION["takeposcustomercurrency"]) {
193 $invoice->setMulticurrencyCode($_SESSION["takeposcustomercurrency"]);
194 }
195}
196
197$term = empty($_SESSION["takeposterminal"]) ? 1 : $_SESSION["takeposterminal"];
198
199
200/*
201 * Actions
202 */
203$error = 0;
204$parameters = array();
205$reshook = $hookmanager->executeHooks('doActions', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
206if ($reshook < 0) {
207 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
208}
209
210if (empty($reshook)) {
211 // Action to record a payment on a TakePOS invoice
212 if ($action == 'valid' && $user->hasRight('facture', 'creer')) {
213 $bankaccount = 0;
214 $error = 0;
215
216 if (getDolGlobalString('TAKEPOS_CAN_FORCE_BANK_ACCOUNT_DURING_PAYMENT')) {
217 $bankaccount = GETPOSTINT('accountid');
218 } else {
219 if ($pay == 'LIQ') {
220 $bankaccount = getDolGlobalInt('CASHDESK_ID_BANKACCOUNT_CASH'.$_SESSION["takeposterminal"]); // For backward compatibility
221 } elseif ($pay == "CHQ") {
222 $bankaccount = getDolGlobalInt('CASHDESK_ID_BANKACCOUNT_CHEQUE'.$_SESSION["takeposterminal"]); // For backward compatibility
223 } else {
224 $accountname = "CASHDESK_ID_BANKACCOUNT_".$pay.$_SESSION["takeposterminal"];
225 $bankaccount = getDolGlobalInt($accountname);
226 }
227 }
228
229 if ($bankaccount <= 0 && $pay != "delayed" && isModEnabled("bank")) {
230 $errormsg = $langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankAccount"));
231 $error++;
232 }
233
234 $now = dol_now();
235 $res = 0;
236
237 $invoice = new Facture($db);
238 $invoice->fetch($placeid);
239
240 $db->begin();
241
242 if ($invoice->total_ttc < 0) {
243 $invoice->type = $invoice::TYPE_CREDIT_NOTE;
244
245 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture";
246 $sql .= " WHERE entity IN (".getEntity('invoice').")";
247 $sql .= " AND fk_soc = ".((int) $invoice->socid);
248 $sql .= " AND type <> ".Facture::TYPE_CREDIT_NOTE;
249 $sql .= " AND fk_statut >= ".$invoice::STATUS_VALIDATED;
250 $sql .= " ORDER BY rowid DESC";
251
252 $resql = $db->query($sql);
253 if ($resql) {
254 $obj = $db->fetch_object($resql);
255 $fk_source = $obj->rowid;
256 if ($fk_source == null) {
257 fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer"));
258 }
259 } else {
260 fail($langs->transnoentitiesnoconv("NoPreviousBillForCustomer"));
261 }
262 $invoice->fk_facture_source = $fk_source;
263 $invoice->update($user);
264 }
265
266 $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
267 $allowstockchange = (getDolGlobalString($constantforkey) != "1");
268
269 if ($error) {
270 dol_htmloutput_errors($errormsg, [], 1);
271 } elseif ($invoice->status != Facture::STATUS_DRAFT) {
272 //If invoice is validated but it is not fully paid is not error and make the payment
273 if ($invoice->getRemainToPay() > 0) {
274 $res = 1;
275 } else {
276 dol_syslog("Sale already validated");
277 dol_htmloutput_errors($langs->trans("InvoiceIsAlreadyValidated", "TakePos"), [], 1);
278 }
279 } elseif (count($invoice->lines) == 0) {
280 $error++;
281 dol_syslog('Sale without lines');
282 dol_htmloutput_errors($langs->trans("NoLinesToBill", "TakePos"), [], 1);
283 } elseif (isModEnabled('stock') && !isModEnabled('productbatch') && $allowstockchange) {
284 // Validation of invoice with change into stock when produt/lot module is NOT enabled and stock change NOT disabled.
285 // The case for isModEnabled('productbatch') is processed few lines later.
286 $savconst = getDolGlobalString('STOCK_CALCULATE_ON_BILL');
287
288 $conf->global->STOCK_CALCULATE_ON_BILL = 1; // To force the change of stock during invoice validation
289
290 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
291 dol_syslog("Validate invoice with stock change. Warehouse defined into constant ".$constantforkey." = ".getDolGlobalString($constantforkey));
292
293 // Validate invoice with stock change into warehouse getDolGlobalInt($constantforkey)
294 // Label of stock movement will be the same as when we validate invoice "Invoice XXXX validated"
295 $batch_rule = 0; // Module productbatch is disabled here, so no need for a batch_rule.
296 $res = $invoice->validate($user, '', getDolGlobalInt($constantforkey), 0, $batch_rule);
297
298 // Restore setup
299 $conf->global->STOCK_CALCULATE_ON_BILL = $savconst;
300 } else {
301 // Validation of invoice with no change into stock (because param $idwarehouse is not fill)
302 $res = $invoice->validate($user);
303 if ($res < 0) {
304 $error++;
305 $langs->load("admin");
306 dol_htmloutput_errors($invoice->error == 'NotConfigured' ? $langs->trans("NotConfigured").' (TakePos numbering module)' : $invoice->error, $invoice->errors, 1);
307 }
308 }
309
310 // Add the payment
311 if (!$error && $res >= 0) {
312 $remaintopay = $invoice->getRemainToPay();
313 if ($remaintopay > 0) {
314 $payment = new Paiement($db);
315
316 $payment->datepaye = $now;
317 $payment->fk_account = $bankaccount;
318 if ($pay == 'LIQ') {
319 $payment->pos_change = GETPOSTFLOAT('excess');
320 }
321
322 $payment->amounts[$invoice->id] = $amountofpayment;
323 // If user has not used change control, add total invoice payment
324 // Or if user has used change control and the amount of payment is higher than remain to pay, add the remain to pay
325 if ($amountofpayment <= 0 || $amountofpayment > $remaintopay) {
326 $payment->amounts[$invoice->id] = $remaintopay;
327 }
328 // We do not set $payments->multicurrency_amounts because we want payment to be in main currency.
329
330 $payment->paiementid = $paiementid;
331 $payment->num_payment = $invoice->ref;
332
333 if ($pay != "delayed") {
334 $res = $payment->create($user);
335 if ($res < 0) {
336 $error++;
337 dol_htmloutput_errors($langs->trans('Error').' '.$payment->error, $payment->errors, 1);
338 } else {
339 $res = $payment->addPaymentToBank($user, 'payment', '(CustomerInvoicePayment)', $bankaccount, '', '');
340 if ($res < 0) {
341 $error++;
342 dol_htmloutput_errors($langs->trans('ErrorNoPaymentDefined').' '.$payment->error, $payment->errors, 1);
343 }
344 }
345 $remaintopay = $invoice->getRemainToPay(); // Recalculate remain to pay after the payment is recorded
346 } elseif (getDolGlobalInt("TAKEPOS_DELAYED_TERMS")) {
347 $invoice->setPaymentTerms(getDolGlobalInt("TAKEPOS_DELAYED_TERMS"));
348 }
349 }
350
351 if ($remaintopay == 0) {
352 dol_syslog("Invoice is paid, so we set it to status Paid");
353 $result = $invoice->setPaid($user);
354 if ($result > 0) {
355 $invoice->paye = 1;
356 $invoice->status = $invoice::STATUS_CLOSED;
357 }
358 // set payment method
359 $invoice->setPaymentMethods($paiementid);
360 } else {
361 dol_syslog("Invoice is not paid, remain to pay = ".$remaintopay);
362 }
363 } else {
364 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
365 }
366
367 // Update stock for batch products
368 if (!$error && $res >= 0) {
369 if (isModEnabled('stock') && isModEnabled('productbatch') && $allowstockchange) {
370 // Update stocks
371 dol_syslog("Now we record the stock movement for each qualified line");
372
373 // The case !isModEnabled('productbatch') was processed few lines before.
374 require_once DOL_DOCUMENT_ROOT . "/product/stock/class/mouvementstock.class.php";
375 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
376 $inventorycode = dol_print_date(dol_now(), 'dayhourlog');
377 // Label of stock movement will be "TakePOS - Invoice XXXX"
378 $labeltakeposmovement = 'TakePOS - '.$langs->trans("Invoice").' '.$invoice->ref;
379
380 foreach ($invoice->lines as $line) {
381 // Use the warehouse id defined on invoice line else in the setup
382 $warehouseid = ($line->fk_warehouse ? $line->fk_warehouse : getDolGlobalInt($constantforkey));
383
384 // var_dump('fk_product='.$line->fk_product.' batch='.$line->batch.' warehouse='.$line->fk_warehouse.' qty='.$line->qty);
385 if ($line->batch != '' && $warehouseid > 0) {
386 $prod_batch = new Productbatch($db);
387 $prod_batch->find(0, '', '', $line->batch, $warehouseid);
388
389 $mouvP = new MouvementStock($db);
390 $mouvP->setOrigin($invoice->element, $invoice->id);
391
392 $res = $mouvP->livraison($user, $line->fk_product, $warehouseid, $line->qty, $line->price, $labeltakeposmovement, '', '', '', $prod_batch->batch, $prod_batch->id, $inventorycode);
393 if ($res < 0) {
394 dol_htmloutput_errors($mouvP->error, $mouvP->errors, 1);
395 $error++;
396 }
397 } else {
398 $mouvP = new MouvementStock($db);
399 $mouvP->setOrigin($invoice->element, $invoice->id);
400
401 $res = $mouvP->livraison($user, $line->fk_product, $warehouseid, $line->qty, $line->price, $labeltakeposmovement, '', '', '', '', 0, $inventorycode);
402 if ($res < 0) {
403 dol_htmloutput_errors($mouvP->error, $mouvP->errors, 1);
404 $error++;
405 }
406 }
407 }
408 }
409 }
410
411 if (!$error && $res >= 0) {
412 $db->commit();
413 } else {
414 $db->rollback();
415 }
416 }
417 if ($action == 'creditnote' && $user->hasRight('facture', 'creer')) {
418 $db->begin();
419
420 $creditnote = new Facture($db);
421 $creditnote->socid = $invoice->socid;
422 $creditnote->date = dol_now();
423 $creditnote->module_source = 'takepos';
424 $creditnote->pos_source = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ;
425 $creditnote->type = Facture::TYPE_CREDIT_NOTE;
426 $creditnote->fk_facture_source = $placeid;
427 //$creditnote->remise_absolue = $invoice->remise_absolue;
428 //$creditnote->remise_percent = $invoice->remise_percent;
429 $creditnote->create($user);
430
431 $fk_parent_line = 0; // Initialise
432
433 foreach ($invoice->lines as $line) {
434 // Reset fk_parent_line for no child products and special product
435 if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
436 $fk_parent_line = 0;
437 }
438
439 if (getDolGlobalInt('INVOICE_USE_SITUATION')) {
440 if (!empty($invoice->situation_counter)) {
441 $source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id
442 $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
443 if (!empty($invoice->tab_previous_situation_invoice)) {
444 // search the last standard invoice in cycle and the possible credit note between this last and invoice
445 // TODO Move this out of loop of $invoice->lines
446 $tab_jumped_credit_notes = array();
447 $lineIndex = count($invoice->tab_previous_situation_invoice) - 1;
448 $searchPreviousInvoice = true;
449 while ($searchPreviousInvoice) {
450 if ($invoice->tab_previous_situation_invoice[$lineIndex]->situation_cycle_ref || $lineIndex < 1) {
451 $searchPreviousInvoice = false; // find, exit;
452 break;
453 } else {
454 if ($invoice->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_CREDIT_NOTE) {
455 $tab_jumped_credit_notes[$lineIndex] = $invoice->tab_previous_situation_invoice[$lineIndex]->id;
456 }
457 $lineIndex--; // go to previous invoice in cycle
458 }
459 }
460
461 $maxPrevSituationPercent = 0;
462 foreach ($invoice->tab_previous_situation_invoice[$lineIndex]->lines as $prevLine) {
463 if ($prevLine->id == $source_fk_prev_id) {
464 $maxPrevSituationPercent = max($maxPrevSituationPercent, $prevLine->situation_percent);
465
466 //$line->subprice = $line->subprice - $prevLine->subprice;
467 $line->total_ht -= $prevLine->total_ht;
468 $line->total_tva -= $prevLine->total_tva;
469 $line->total_ttc -= $prevLine->total_ttc;
470 $line->total_localtax1 -= $prevLine->total_localtax1;
471 $line->total_localtax2 -= $prevLine->total_localtax2;
472
473 $line->multicurrency_subprice -= $prevLine->multicurrency_subprice;
474 $line->multicurrency_total_ht -= $prevLine->multicurrency_total_ht;
475 $line->multicurrency_total_tva -= $prevLine->multicurrency_total_tva;
476 $line->multicurrency_total_ttc -= $prevLine->multicurrency_total_ttc;
477 }
478 }
479
480 // prorata
481 $line->situation_percent = $maxPrevSituationPercent - $line->situation_percent;
482
483 //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>';
484
485 // If there is some credit note between last situation invoice and invoice used for credit note generation (note: credit notes are stored as delta)
486 $maxPrevSituationPercent = 0;
487 foreach ($tab_jumped_credit_notes as $index => $creditnoteid) {
488 foreach ($invoice->tab_previous_situation_invoice[$index]->lines as $prevLine) {
489 if ($prevLine->fk_prev_id == $source_fk_prev_id) {
490 $maxPrevSituationPercent = $prevLine->situation_percent;
491
492 $line->total_ht -= $prevLine->total_ht;
493 $line->total_tva -= $prevLine->total_tva;
494 $line->total_ttc -= $prevLine->total_ttc;
495 $line->total_localtax1 -= $prevLine->total_localtax1;
496 $line->total_localtax2 -= $prevLine->total_localtax2;
497
498 $line->multicurrency_subprice -= $prevLine->multicurrency_subprice;
499 $line->multicurrency_total_ht -= $prevLine->multicurrency_total_ht;
500 $line->multicurrency_total_tva -= $prevLine->multicurrency_total_tva;
501 $line->multicurrency_total_ttc -= $prevLine->multicurrency_total_ttc;
502 }
503 }
504 }
505
506 // prorata
507 $line->situation_percent += $maxPrevSituationPercent;
508
509 //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>';
510 }
511 }
512 }
513
514 // We update field for credit notes
515 $line->fk_facture = $creditnote->id;
516 $line->fk_parent_line = $fk_parent_line;
517
518 $line->subprice = -$line->subprice; // invert price for object
519 // $line->pa_ht = $line->pa_ht; // we chose to have the buy/cost price always positive, so no inversion of the sign here
520 $line->total_ht = -$line->total_ht;
521 $line->total_tva = -$line->total_tva;
522 $line->total_ttc = -$line->total_ttc;
523 $line->total_localtax1 = -$line->total_localtax1;
524 $line->total_localtax2 = -$line->total_localtax2;
525
526 $line->multicurrency_subprice = -$line->multicurrency_subprice;
527 $line->multicurrency_total_ht = -$line->multicurrency_total_ht;
528 $line->multicurrency_total_tva = -$line->multicurrency_total_tva;
529 $line->multicurrency_total_ttc = -$line->multicurrency_total_ttc;
530
531 $result = $line->insert(0, 1); // When creating credit note with same lines than source, we must ignore error if discount already linked
532
533 $creditnote->lines[] = $line; // insert new line in current object
534
535 // Defined the new fk_parent_line
536 if ($result > 0 && $line->product_type == 9) {
537 $fk_parent_line = $result;
538 }
539 }
540 $creditnote->update_price(1);
541
542 // The credit note is create here. We must now validate it.
543
544 $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
545 $allowstockchange = getDolGlobalString($constantforkey) != "1";
546
547 if (isModEnabled('stock') && !isModEnabled('productbatch') && $allowstockchange) {
548 // If module stock is enabled and we do not setup takepo to disable stock decrease
549 // The case for isModEnabled('productbatch') is processed few lines later.
550 $savconst = getDolGlobalString('STOCK_CALCULATE_ON_BILL');
551 $conf->global->STOCK_CALCULATE_ON_BILL = 1; // We force setup to have update of stock on invoice validation/unvalidation
552
553 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
554
555 dol_syslog("Validate invoice with stock change into warehouse defined into constant ".$constantforkey." = ".getDolGlobalString($constantforkey)." or warehouseid= ".$warehouseid." if defined.");
556
557 // Validate invoice with stock change into warehouse getDolGlobalInt($constantforkey)
558 // Label of stock movement will be the same as when we validate invoice "Invoice XXXX validated"
559 $batch_rule = 0; // Module productbatch is disabled here, so no need for a batch_rule.
560 $res = $creditnote->validate($user, '', getDolGlobalString($constantforkey), 0, $batch_rule);
561 if ($res < 0) {
562 $error++;
563 dol_htmloutput_errors($creditnote->error, $creditnote->errors, 1);
564 }
565
566 // Restore setup
567 $conf->global->STOCK_CALCULATE_ON_BILL = $savconst;
568 } else {
569 $res = $creditnote->validate($user);
570 }
571
572 // Update stock for batch products
573 if (!$error && $res >= 0) {
574 if (isModEnabled('stock') && isModEnabled('productbatch') && $allowstockchange) {
575 // Update stocks
576 dol_syslog("Now we record the stock movement for each qualified line");
577
578 // The case !isModEnabled('productbatch') was processed few lines before.
579 require_once DOL_DOCUMENT_ROOT . "/product/stock/class/mouvementstock.class.php";
580 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
581 $inventorycode = dol_print_date(dol_now(), 'dayhourlog');
582 // Label of stock movement will be "TakePOS - Invoice XXXX"
583 $labeltakeposmovement = 'TakePOS - '.$langs->trans("CreditNote").' '.$creditnote->ref;
584
585 foreach ($creditnote->lines as $line) {
586 // Use the warehouse id defined on invoice line else in the setup
587 $warehouseid = ($line->fk_warehouse ? $line->fk_warehouse : getDolGlobalInt($constantforkey));
588 //var_dump('fk_product='.$line->fk_product.' batch='.$line->batch.' warehouse='.$line->fk_warehouse.' qty='.$line->qty);exit;
589
590 if ($line->batch != '' && $warehouseid > 0) {
591 //$prod_batch = new Productbatch($db);
592 //$prod_batch->find(0, '', '', $line->batch, $warehouseid);
593
594 $mouvP = new MouvementStock($db);
595 $mouvP->setOrigin($creditnote->element, $creditnote->id);
596
597 $res = $mouvP->reception($user, $line->fk_product, $warehouseid, $line->qty, $line->price, $labeltakeposmovement, '', '', $line->batch, '', 0, $inventorycode);
598 if ($res < 0) {
599 dol_htmloutput_errors($mouvP->error, $mouvP->errors, 1);
600 $error++;
601 }
602 } else {
603 $mouvP = new MouvementStock($db);
604 $mouvP->setOrigin($creditnote->element, $creditnote->id);
605
606 $res = $mouvP->reception($user, $line->fk_product, $warehouseid, $line->qty, $line->price, $labeltakeposmovement, '', '', '', '', 0, $inventorycode);
607 if ($res < 0) {
608 dol_htmloutput_errors($mouvP->error, $mouvP->errors, 1);
609 $error++;
610 }
611 }
612 }
613 }
614 }
615
616 if (!$error && $res >= 0) {
617 $db->commit();
618 } else {
619 $creditnote->id = $placeid; // Creation has failed, we reset to ID of source invoice so we go back to this one in action=history
620 $db->rollback();
621 }
622 }
623
624 if (($action == 'history' || $action == 'creditnote') && $user->hasRight('takepos', 'run')) {
625 if ($action == 'creditnote' && $creditnote->id > 0) { // Test on permission already done
626 $placeid = $creditnote->id;
627 } else {
628 $placeid = GETPOSTINT('placeid');
629 }
630
631 $invoice = new Facture($db);
632 $invoice->fetch($placeid);
633 }
634
635 // If we add a line and no invoice yet, we create the invoice
636 if (($action == "addline" || $action == "freezone") && $placeid == 0 && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
637 $invoice->socid = getDolGlobalInt($constforcompanyid);
638
639 $dolnowtzuserrel = dol_now('tzuserrel'); // If user is 02 january 22:00, we want to store '02 january'
640 $monthuser = dol_print_date($dolnowtzuserrel, '%m', 'gmt');
641 $dayuser = dol_print_date($dolnowtzuserrel, '%d', 'gmt');
642 $yearuser = dol_print_date($dolnowtzuserrel, '%Y', 'gmt');
643 $dateinvoice = dol_mktime(0, 0, 0, (int) $monthuser, (int) $dayuser, (int) $yearuser, 'tzserver'); // If we enter the 02 january, we need to save the 02 january for server
644
645 include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
646 $invoice->date = $dateinvoice; // Invoice::create() needs a date with no hours
647
648 $invoice->module_source = 'takepos';
649 $invoice->pos_source = isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '' ;
650 $invoice->entity = !empty($_SESSION["takeposinvoiceentity"]) ? $_SESSION["takeposinvoiceentity"] : $conf->entity;
651
652 if ($invoice->socid <= 0) {
653 $langs->load('errors');
654 dol_htmloutput_errors($langs->trans("ErrorModuleSetupNotComplete", "TakePos"), [], 1);
655 } else {
656 $db->begin();
657
658 // Create invoice
659 $placeid = $invoice->create($user);
660 if ($placeid < 0) {
661 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
662 }
663 $sql = "UPDATE ".MAIN_DB_PREFIX."facture";
664 $sql .= " SET ref='(PROV-POS".$_SESSION["takeposterminal"]."-".$place.")'";
665 $sql .= " WHERE rowid = ".((int) $placeid);
666 $resql = $db->query($sql);
667 if (!$resql) {
668 $error++;
669 }
670
671 if (!$error) {
672 $db->commit();
673 } else {
674 $db->rollback();
675 }
676 }
677 }
678
679 // If we add a line by click on product (invoice exists here because it was created juste before if it didn't exists)
680 if ($action == "addline" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
681 $prod = new Product($db);
682 $prod->fetch($idproduct);
683
684 $customer = new Societe($db);
685 $customer->fetch($invoice->socid);
686
687 $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
688
689 $qty = GETPOSTISSET('qty') ? GETPOSTFLOAT('qty') : 1;
690 $price = $datapriceofproduct['pu_ht'];
691 $price_ttc = $datapriceofproduct['pu_ttc'];
692 //$price_min = $datapriceofproduct['price_min'];
693 $price_base_type = empty($datapriceofproduct['price_base_type']) ? 'HT' : $datapriceofproduct['price_base_type'];
694 $tva_tx = $datapriceofproduct['tva_tx'];
695 $tva_npr = $datapriceofproduct['tva_npr'];
696
697 // Local Taxes
698 $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
699 $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
700
701
702 if (isModEnabled('productbatch') && isModEnabled('stock')) {
703 $batch = GETPOST('batch', 'alpha');
704
705 if (!empty($batch)) { // We have just clicked on a batch number, we will execute action=setbatch later...
706 $action = "setbatch";
707 } elseif ($prod->status_batch > 0) {
708 // If product need a lot/serial, we show the list of lot/serial available for the product...
709
710 // Set nb of suggested with nb of batch into the warehouse of the terminal
711 $nbofsuggested = 0;
712 $prod->load_stock('warehouseopen');
713
714 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
715 $warehouseid = getDolGlobalInt($constantforkey);
716
717 //var_dump($prod->stock_warehouse);
718 foreach ($prod->stock_warehouse as $tmpwarehouseid => $tmpval) {
719 if (getDolGlobalInt($constantforkey) && $tmpwarehouseid != getDolGlobalInt($constantforkey)) {
720 // Product to select is not on the warehouse configured for terminal, so we ignore this warehouse
721 continue;
722 }
723 if (!empty($prod->stock_warehouse[$tmpwarehouseid]) && is_array($prod->stock_warehouse[$tmpwarehouseid]->detail_batch)) {
724 if (is_object($prod->stock_warehouse[$tmpwarehouseid]) && count($prod->stock_warehouse[$tmpwarehouseid]->detail_batch)) {
725 foreach ($prod->stock_warehouse[$tmpwarehouseid]->detail_batch as $dbatch) {
726 $nbofsuggested++;
727 }
728 }
729 }
730 }
731 //var_dump($prod->stock_warehouse);
732
733 echo "<script>\n";
734 echo "function addbatch(batch, warehouseid) {\n";
735 echo "console.log('We add batch '+batch+' from warehouse id '+warehouseid);\n";
736 echo '$("#poslines").load("'.DOL_URL_ROOT.'/takepos/invoice.php?action=addline&batch="+encodeURI(batch)+"&warehouseid="+warehouseid+"&place='.$place.'&idproduct='.$idproduct.'&token='.newToken().'", function() {});'."\n";
737 echo "}\n";
738 echo "</script>\n";
739
740 $suggestednb = 1;
741 echo "<center>".$langs->trans("SearchIntoBatch").": <b> $nbofsuggested </b></center><br><table>";
742 foreach ($prod->stock_warehouse as $tmpwarehouseid => $tmpval) {
743 if (getDolGlobalInt($constantforkey) && $tmpwarehouseid != getDolGlobalInt($constantforkey)) {
744 // Not on the forced warehouse, so we ignore this warehouse
745 continue;
746 }
747 if (!empty($prod->stock_warehouse[$tmpwarehouseid]) && is_array($prod->stock_warehouse[$tmpwarehouseid]->detail_batch)) {
748 foreach ($prod->stock_warehouse[$tmpwarehouseid]->detail_batch as $dbatch) { // $dbatch is instance of Productbatch
749 $batchStock = + $dbatch->qty; // To get a numeric
750 $quantityToBeDelivered = 1;
751 $deliverableQty = min($quantityToBeDelivered, $batchStock);
752 print '<tr>';
753 print '<!-- subj='.$suggestednb.'/'.$nbofsuggested.' -->';
754 print '<!-- Show details of lot/serial in warehouseid='.$tmpwarehouseid.' -->';
755 print '<td class="left">';
756 $detail = '';
757 $detail .= '<span class="opacitymedium">'.$langs->trans("LotSerial").':</span> '.$dbatch->batch;
758 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
759 //$detail .= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby, "day");
760 }
761 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
762 //$detail .= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby, "day");
763 }
764 $detail .= '</td><td>';
765 $detail .= '<span class="opacitymedium">'.$langs->trans("Qty").':</span> '.$dbatch->qty;
766 $detail .= '</td><td>';
767 $detail .= ' <button class="marginleftonly" onclick="addbatch(\''.dol_escape_js($dbatch->batch).'\', '.$tmpwarehouseid.')">'.$langs->trans("Select")."</button>";
768 $detail .= '<br>';
769 print $detail;
770
771 $quantityToBeDelivered -= $deliverableQty;
772 if ($quantityToBeDelivered < 0) {
773 $quantityToBeDelivered = 0;
774 }
775 $suggestednb++;
776 print '</td></tr>';
777 }
778 }
779 }
780 print "</table>";
781
782 print '</body></html>';
783 exit;
784 }
785 }
786
787
788 if (getDolGlobalString('TAKEPOS_SUPPLEMENTS')) {
789 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
790 $cat = new Categorie($db);
791 $categories = $cat->containing($idproduct, 'product');
792 $found = (array_search(getDolGlobalInt('TAKEPOS_SUPPLEMENTS_CATEGORY'), array_column($categories, 'id')));
793 if ($found !== false) { // If this product is a supplement
794 $sql = "SELECT fk_parent_line FROM ".MAIN_DB_PREFIX."facturedet where rowid = ".((int) $selectedline);
795 $resql = $db->query($sql);
796 $row = $db->fetch_array($resql);
797 if ($row[0] == null) {
798 $parent_line = $selectedline;
799 } else {
800 $parent_line = $row[0]; //If the parent line is already a supplement, add the supplement to the main product
801 }
802 }
803 }
804
805 $idoflineadded = 0;
806 $err = 0;
807 // Group if enabled. Skip group if line already sent to the printer
808 if (getDolGlobalString('TAKEPOS_GROUP_SAME_PRODUCT')) {
809 foreach ($invoice->lines as $line) {
810 if ($line->product_ref == $prod->ref) {
811 if ($line->special_code == 4) {
812 continue;
813 } // If this line is sended to printer create new line
814 // check if qty in stock
815 if (getDolGlobalString('TAKEPOS_QTY_IN_STOCK') && (($line->qty + $qty) > $prod->stock_reel)) {
816 $invoice->error = $langs->trans("ErrorStockIsNotEnough");
817 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
818 $err++;
819 break;
820 }
821 $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);
822 if ($result < 0) {
823 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
824 } else {
825 $idoflineadded = $line->id;
826 }
827 break;
828 }
829 }
830 }
831 if ($idoflineadded <= 0 && empty($err)) {
832 $invoice->fetch_thirdparty();
833 $array_options = array();
834
835 $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);
836
837 /* setup of margin calculation */
838 if (getDolGlobalString('MARGIN_TYPE')) {
839 if (getDolGlobalString('MARGIN_TYPE') == 'pmp' && !empty($prod->pmp)) {
840 $line['fk_fournprice'] = null;
841 $line['pa_ht'] = $prod->pmp;
842 } elseif (getDolGlobalString('MARGIN_TYPE') == 'costprice' && !empty($prod->cost_price)) {
843 $line['fk_fournprice'] = null;
844 $line['pa_ht'] = $prod->cost_price;
845 } else {
846 // default is fournprice
847 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
848 $pf = new ProductFournisseur($db);
849 if ($pf->find_min_price_product_fournisseur($idproduct, $qty) > 0) {
850 $line['fk_fournprice'] = $pf->product_fourn_price_id;
851 $line['pa_ht'] = $pf->fourn_unitprice_with_discount;
852 if (getDolGlobalString('PRODUCT_CHARGES') && $pf->fourn_charges > 0) {
853 $line['pa_ht'] += (float) $pf->fourn_charges / $pf->fourn_qty;
854 }
855 }
856 }
857 }
858
859 // complete line by hook
860 $parameters = array('prod' => $prod, 'line' => $line);
861 $reshook = $hookmanager->executeHooks('completeTakePosAddLine', $parameters, $invoice, $action); // Note that $action and $line may have been modified by some hooks
862 if ($reshook < 0) {
863 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
864 }
865
866
867 if (empty($reshook)) {
868 if (!empty($hookmanager->resArray)) {
869 $line = $hookmanager->resArray;
870 }
871
872 // check if qty in stock
873 if (getDolGlobalString('TAKEPOS_QTY_IN_STOCK') && $qty > $prod->stock_reel) {
874 $invoice->error = $langs->trans("ErrorStockIsNotEnough");
875 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
876 $err++;
877 }
878
879 if (empty($err)) {
880 $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), (empty($line['fk_fournprice']) ? 0 : $line['fk_fournprice']), (empty($line['pa_ht']) ? '' : $line['pa_ht']), '', $line['array_options'], 100, '', null, 0);
881 }
882 }
883
884 if (getDolGlobalString('TAKEPOS_CUSTOMER_DISPLAY')) {
885 $CUSTOMER_DISPLAY_line1 = $prod->label;
886 $CUSTOMER_DISPLAY_line2 = price($price_ttc);
887 }
888 }
889
890 $invoice->fetch($placeid);
891 }
892
893 // If we add a line by submitting freezone form (invoice exists here because it was created juste before if it didn't exists)
894 if ($action == "freezone" && $user->hasRight('takepos', 'run')) {
895 $customer = new Societe($db);
896 $customer->fetch($invoice->socid);
897
898 $tva_tx = GETPOST('tva_tx', 'alpha');
899 if ($tva_tx != '') {
900 if (!preg_match('/\‍((.*)\‍)/', $tva_tx)) {
901 $tva_tx = price2num($tva_tx);
902 }
903 } else {
904 $tva_tx = get_default_tva($mysoc, $customer);
905 }
906
907 // Local Taxes
908 $localtax1_tx = get_localtax($tva_tx, 1, $customer, $mysoc, $tva_npr);
909 $localtax2_tx = get_localtax($tva_tx, 2, $customer, $mysoc, $tva_npr);
910
911 $res = $invoice->addline($desc, $number, 1, $tva_tx, $localtax1_tx, $localtax2_tx, 0, 0, '', 0, 0, 0, '', getDolGlobalInt('TAKEPOS_DISCOUNT_TTC') ? ($number >= 0 ? 'HT' : 'TTC') : (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT') ? 'HT' : 'TTC'), $number, 0, -1, 0, '', 0, 0, null, '', '', 0, 100, '', null, 0);
912 if ($res < 0) {
913 dol_htmloutput_errors($invoice->error, $invoice->errors, 1);
914 }
915 $invoice->fetch($placeid);
916 }
917
918 if ($action == "addnote" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
919 $desc = GETPOST('addnote', 'alpha');
920 if ($idline == 0) {
921 $invoice->update_note($desc, '_public');
922 } else {
923 foreach ($invoice->lines as $line) {
924 if ($line->id == $idline) {
925 $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);
926 }
927 }
928 }
929 $invoice->fetch($placeid);
930 }
931
932 if ($action == "deleteline" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
933 /*
934 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
935 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
936 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
937 $permissiontoupdateline = true;
938 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
939 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the table ID
940 }
941 }*/
942
943 if ($idline > 0 && $placeid > 0) { // If invoice exists and line selected. To avoid errors if deleted from another device or no line selected.
944 $invoice->deleteLine($idline);
945 $invoice->fetch($placeid);
946 } elseif ($placeid > 0) { // If invoice exists but no line selected, proceed to delete last line.
947 $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facturedet where fk_facture = ".((int) $placeid)." ORDER BY rowid DESC";
948 $resql = $db->query($sql);
949 $row = $db->fetch_array($resql);
950 $deletelineid = $row[0];
951 $invoice->deleteLine($deletelineid);
952 $invoice->fetch($placeid);
953 }
954
955 if (count($invoice->lines) == 0) {
956 $invoice->delete($user);
957
958 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
959 header("Location: ".DOL_URL_ROOT."/takepos/public/auto_order.php");
960 } else {
961 header("Location: ".DOL_URL_ROOT."/takepos/invoice.php");
962 }
963 exit;
964 }
965 }
966
967 // Action to delete or discard an invoice
968 if ($action == "delete" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
969 // $placeid is the invoice id (it differs from place) and is defined if the place is set and
970 // the ref of invoice is '(PROV-POS'.$_SESSION["takeposterminal"].'-'.$place.')', so the fetch at beginning of page works.
971 if ($placeid > 0) {
972 $result = $invoice->fetch($placeid);
973
974 if ($result > 0 && $invoice->status == Facture::STATUS_DRAFT) {
975 $db->begin();
976
977 // We delete the lines
978 $resdeletelines = 1;
979 foreach ($invoice->lines as $line) {
980 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
981 $tmpres = $invoice->deleteLine($line->id);
982 if ($tmpres < 0) {
983 $resdeletelines = 0;
984 break;
985 }
986 }
987
988 $sql = "UPDATE ".MAIN_DB_PREFIX."facture";
989 $varforconst = 'CASHDESK_ID_THIRDPARTY'.$_SESSION["takeposterminal"];
990 $sql .= " SET fk_soc = ".((int) getDolGlobalString($varforconst)).", ";
991 $sql .= " datec = '".$db->idate(dol_now())."'";
992 $sql .= " WHERE entity IN (".getEntity('invoice').")";
993 $sql .= " AND ref = '(PROV-POS".$db->escape($_SESSION["takeposterminal"]."-".$place).")'";
994 $resql1 = $db->query($sql);
995
996 if ($resdeletelines && $resql1) {
997 $db->commit();
998 } else {
999 $db->rollback();
1000 }
1001
1002 $invoice->fetch($placeid);
1003 }
1004 }
1005 }
1006
1007 if ($action == "updateqty") { // Test on permission is done later
1008 foreach ($invoice->lines as $line) {
1009 if ($line->id == $idline) {
1010 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
1011 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1012 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
1013 $permissiontoupdateline = true;
1014 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
1015 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the table ID
1016 }
1017 }
1018 if (!$permissiontoupdateline) {
1019 dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos").' - No permission to updateqty', [], 1);
1020 } else {
1021 $vatratecode = $line->tva_tx;
1022 if ($line->vat_src_code) {
1023 $vatratecode .= ' ('.$line->vat_src_code.')';
1024 }
1025
1026 $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $number, $line->remise_percent, $line->date_start, $line->date_end, $vatratecode, $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);
1027 }
1028 }
1029 }
1030
1031 $invoice->fetch($placeid);
1032 }
1033
1034 if ($action == "updateprice") { // Test on permission is done later
1035 $customer = new Societe($db);
1036 $customer->fetch($invoice->socid);
1037
1038 foreach ($invoice->lines as $line) {
1039 if ($line->id == $idline) {
1040 $prod = new Product($db);
1041 $prod->fetch($line->fk_product);
1042 $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
1043 $price_min = $datapriceofproduct['price_min'];
1044 $usercanproductignorepricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !$user->hasRight('produit', 'ignore_price_min_advance')) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
1045
1046 $vatratecleaned = $line->tva_tx;
1047 $reg = array();
1048 if (preg_match('/^(.*)\s*\‍((.*)\‍)$/', (string) $line->tva_tx, $reg)) { // If vat is "xx (yy)"
1049 $vatratecleaned = trim($reg[1]);
1050 //$vatratecode = $reg[2];
1051 }
1052
1053 $pu_ht = price2num((float) price2num($number, 'MU') / (1 + ((float) $vatratecleaned / 100)), 'MU');
1054 // Check min price
1055 if ($usercanproductignorepricemin && (!empty($price_min) && ((float) price2num($pu_ht) * (1 - (float) price2num($line->remise_percent) / 100) < price2num($price_min)))) {
1056 $langs->load("products");
1057 dol_htmloutput_errors($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)));
1058 // echo $langs->trans("CantBeLessThanMinPrice");
1059 } else {
1060 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
1061 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1062 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
1063 $permissiontoupdateline = true;
1064 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
1065 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the table ID
1066 }
1067 }
1068
1069 $vatratecode = $line->tva_tx;
1070 if ($line->vat_src_code) {
1071 $vatratecode .= ' ('.$line->vat_src_code.')';
1072 }
1073
1074 if (!$permissiontoupdateline) {
1075 dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos").' - No permission to updateprice', [], 1);
1076 } elseif (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT') == 1) {
1077 $result = $invoice->updateline($line->id, $line->desc, $number, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $vatratecode, $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);
1078 } else {
1079 $result = $invoice->updateline($line->id, $line->desc, $number, $line->qty, $line->remise_percent, $line->date_start, $line->date_end, $vatratecode, $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);
1080 }
1081 }
1082 }
1083 }
1084
1085 // Reload data
1086 $invoice->fetch($placeid);
1087 }
1088
1089 if ($action == "updatereduction") { // Test on permission is done later
1090 $customer = new Societe($db);
1091 $customer->fetch($invoice->socid);
1092
1093 foreach ($invoice->lines as $line) {
1094 if ($line->id == $idline) {
1095 dol_syslog("updatereduction Process line ".$line->id.' to apply discount of '.$number.'%');
1096
1097 $prod = new Product($db);
1098 $prod->fetch($line->fk_product);
1099
1100 $datapriceofproduct = $prod->getSellPrice($mysoc, $customer, 0);
1101 $price_min = $datapriceofproduct['price_min'];
1102 $usercanproductignorepricemin = ((getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && !$user->hasRight('produit', 'ignore_price_min_advance')) || !getDolGlobalString('MAIN_USE_ADVANCED_PERMS'));
1103
1104 $pu_ht = price2num($line->subprice / (1 + ($line->tva_tx / 100)), 'MU');
1105
1106 // Check min price
1107 if ($usercanproductignorepricemin && (!empty($price_min) && ((float) price2num($line->subprice) * (1 - (float) price2num($number) / 100) < (float) price2num($price_min)))) {
1108 $langs->load("products");
1109 dol_htmloutput_errors($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)));
1110 } else {
1111 $permissiontoupdateline = ($user->hasRight('takepos', 'editlines') && ($user->hasRight('takepos', 'editorderedlines') || $line->special_code != "4"));
1112 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1113 if ($invoice->status == $invoice::STATUS_DRAFT && $invoice->pos_source && $invoice->module_source == 'takepos') {
1114 $permissiontoupdateline = true;
1115 // TODO Add also a test on $_SESSION('publicobjectid'] defined at creation of object
1116 // TODO Check also that invoice->ref is (PROV-POS1-2) with 1 = terminal and 2, the table ID
1117 }
1118 }
1119 if (!$permissiontoupdateline) {
1120 dol_htmloutput_errors($langs->trans("NotEnoughPermissions", "TakePos"), [], 1);
1121 } else {
1122 $vatratecode = $line->tva_tx;
1123 if ($line->vat_src_code) {
1124 $vatratecode .= ' ('.$line->vat_src_code.')';
1125 }
1126 $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $number, $line->date_start, $line->date_end, $vatratecode, $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);
1127 }
1128 }
1129 }
1130 }
1131
1132 // Reload data
1133 $invoice->fetch($placeid);
1134 } elseif ($action == 'update_reduction_global' && $user->hasRight('takepos', 'editlines')) {
1135 foreach ($invoice->lines as $line) {
1136 $vatratecode = $line->tva_tx;
1137 if ($line->vat_src_code) {
1138 $vatratecode .= ' ('.$line->vat_src_code.')';
1139 }
1140 $result = $invoice->updateline($line->id, $line->desc, $line->subprice, $line->qty, $number, $line->date_start, $line->date_end, $vatratecode, $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);
1141 }
1142
1143 $invoice->fetch($placeid);
1144 }
1145
1146 if ($action == "setbatch" && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
1147 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
1148 $warehouseid = (GETPOSTINT('warehouseid') > 0 ? GETPOSTINT('warehouseid') : getDolGlobalInt($constantforkey)); // Get the warehouse id from GETPOSTINT('warehouseid'), otherwise use default setup.
1149 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet SET batch = '".$db->escape($batch)."', fk_warehouse = ".((int) $warehouseid);
1150 $sql .= " WHERE rowid=".((int) $idoflineadded);
1151 $db->query($sql);
1152 }
1153
1154 if ($action == "order" && $placeid != 0 && ($user->hasRight('takepos', 'run') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE'))) {
1155 include_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1156 if ((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") {
1157 require_once DOL_DOCUMENT_ROOT.'/core/class/dolreceiptprinter.class.php';
1158 $printer = new dolReceiptPrinter($db);
1159 }
1160
1161 $sql = "SELECT label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place);
1162 $resql = $db->query($sql);
1163 $row = $db->fetch_object($resql);
1164 $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>';
1165 $footerorder = '</tbody></table>'.dol_print_date(dol_now(), 'dayhour').'<br></html>';
1166 $order_receipt_printer1 = "";
1167 $order_receipt_printer2 = "";
1168 $order_receipt_printer3 = "";
1169 $catsprinter1 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_1'));
1170 $catsprinter2 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_2'));
1171 $catsprinter3 = explode(';', getDolGlobalString('TAKEPOS_PRINTED_CATEGORIES_3'));
1172 $linestoprint = 0;
1173 foreach ($invoice->lines as $line) {
1174 if ($line->special_code == "4") {
1175 continue;
1176 }
1177 $c = new Categorie($db);
1178 $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1179 $result = array_intersect($catsprinter1, $existing);
1180 $count = count($result);
1181 if (!$line->fk_product) {
1182 $count++; // Print Free-text item (Unassigned printer) to Printer 1
1183 }
1184 if ($count > 0) {
1185 $linestoprint++;
1186 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='1' where rowid=".$line->id; //Set to print on printer 1
1187 $db->query($sql);
1188 $order_receipt_printer1 .= '<tr><td class="left">';
1189 if ($line->fk_product) {
1190 $order_receipt_printer1 .= $line->product_label;
1191 } else {
1192 $order_receipt_printer1 .= $line->description;
1193 }
1194 $order_receipt_printer1 .= '</td><td class="right">'.$line->qty;
1195 if (!empty($line->array_options['options_order_notes'])) {
1196 $order_receipt_printer1 .= "<br>(".$line->array_options['options_order_notes'].")";
1197 }
1198 $order_receipt_printer1 .= '</td></tr>';
1199 }
1200 }
1201 if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
1202 $invoice->fetch($placeid); //Reload object before send to printer
1203 $printer->orderprinter = 1;
1204 echo "<script>";
1205 echo "var orderprinter1esc='";
1206 $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
1207 echo "';</script>";
1208 }
1209 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='1' and fk_facture=".$invoice->id; // Set as printed
1210 $db->query($sql);
1211 $invoice->fetch($placeid); //Reload object after set lines as printed
1212 $linestoprint = 0;
1213
1214 foreach ($invoice->lines as $line) {
1215 if ($line->special_code == "4") {
1216 continue;
1217 }
1218 $c = new Categorie($db);
1219 $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1220 $result = array_intersect($catsprinter2, $existing);
1221 $count = count($result);
1222 if ($count > 0) {
1223 $linestoprint++;
1224 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='2' where rowid=".$line->id; //Set to print on printer 2
1225 $db->query($sql);
1226 $order_receipt_printer2 .= '<tr>'.$line->product_label.'<td class="right">'.$line->qty;
1227 if (!empty($line->array_options['options_order_notes'])) {
1228 $order_receipt_printer2 .= "<br>(".$line->array_options['options_order_notes'].")";
1229 }
1230 $order_receipt_printer2 .= '</td></tr>';
1231 }
1232 }
1233 if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
1234 $invoice->fetch($placeid); //Reload object before send to printer
1235 $printer->orderprinter = 2;
1236 echo "<script>";
1237 echo "var orderprinter2esc='";
1238 $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
1239 echo "';</script>";
1240 }
1241 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='2' and fk_facture=".$invoice->id; // Set as printed
1242 $db->query($sql);
1243 $invoice->fetch($placeid); //Reload object after set lines as printed
1244 $linestoprint = 0;
1245
1246 foreach ($invoice->lines as $line) {
1247 if ($line->special_code == "4") {
1248 continue;
1249 }
1250 $c = new Categorie($db);
1251 $existing = $c->containing($line->fk_product, Categorie::TYPE_PRODUCT, 'id');
1252 $result = array_intersect($catsprinter3, $existing);
1253 $count = count($result);
1254 if ($count > 0) {
1255 $linestoprint++;
1256 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='3' where rowid=".$line->id; //Set to print on printer 3
1257 $db->query($sql);
1258 $order_receipt_printer3 .= '<tr>'.$line->product_label.'<td class="right">'.$line->qty;
1259 if (!empty($line->array_options['options_order_notes'])) {
1260 $order_receipt_printer3 .= "<br>(".$line->array_options['options_order_notes'].")";
1261 }
1262 $order_receipt_printer3 .= '</td></tr>';
1263 }
1264 }
1265 if (((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter" || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") && $linestoprint > 0) {
1266 $invoice->fetch($placeid); //Reload object before send to printer
1267 $printer->orderprinter = 3;
1268 echo "<script>";
1269 echo "var orderprinter3esc='";
1270 $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
1271 echo "';</script>";
1272 }
1273 $sql = "UPDATE ".MAIN_DB_PREFIX."facturedet set special_code='4' where special_code='3' and fk_facture=".$invoice->id; // Set as printed
1274 $db->query($sql);
1275 $invoice->fetch($placeid); //Reload object after set lines as printed
1276 }
1277
1278 $sectionwithinvoicelink = '';
1279 if (($action == "valid" || $action == "history" || $action == 'creditnote' || ($action == 'addline' && $invoice->status == $invoice::STATUS_CLOSED)) && $user->hasRight('takepos', 'run')) {
1280 $sectionwithinvoicelink .= '<!-- Section with invoice link -->'."\n";
1281 $sectionwithinvoicelink .= '<span style="font-size:120%;" class="center inline-block marginbottomonly">';
1282 $sectionwithinvoicelink .= $invoice->getNomUrl(1, '', 0, 0, '', 0, 0, -1, '_backoffice')." - ";
1283 $remaintopay = $invoice->getRemainToPay();
1284 if ($remaintopay > 0) {
1285 $sectionwithinvoicelink .= $langs->trans('RemainToPay').': <span class="amountremaintopay" style="font-size: unset">'.price($remaintopay, 1, $langs, 1, -1, -1, $conf->currency).'</span>';
1286 } else {
1287 $sectionwithinvoicelink .= $invoice->getLibStatut(2);
1288 }
1289
1290 $sectionwithinvoicelink .= '</span><br>';
1291 if (getDolGlobalInt('TAKEPOS_PRINT_INVOICE_DOC_INSTEAD_OF_RECEIPT')) {
1292 $sectionwithinvoicelink .= ' <a target="_blank" class="button" href="' . DOL_URL_ROOT . '/document.php?token=' . newToken() . '&modulepart=facture&file=' . $invoice->ref . '/' . $invoice->ref . '.pdf">Invoice</a>';
1293 } elseif (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") {
1294 if (getDolGlobalString('TAKEPOS_PRINT_SERVER') && filter_var(getDolGlobalString('TAKEPOS_PRINT_SERVER'), FILTER_VALIDATE_URL) == true) {
1295 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposConnector('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1296 } else {
1297 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="TakeposPrinting('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1298 }
1299 } elseif ((isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter") {
1300 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="DolibarrTakeposPrinting('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1301 } else {
1302 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print('.$placeid.')">'.$langs->trans('PrintTicket').'</button>';
1303 if (getDolGlobalString('TAKEPOS_PRINT_WITHOUT_DETAILS')) {
1304 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="PrintBox('.$placeid.', \'without_details\')">'.$langs->trans('PrintWithoutDetails').'</button>';
1305 }
1306 if (getDolGlobalString('TAKEPOS_GIFT_RECEIPT')) {
1307 $sectionwithinvoicelink .= ' <button id="buttonprint" type="button" onclick="Print('.$placeid.', 1)">'.$langs->trans('GiftReceipt').'</button>';
1308 }
1309 }
1310 if (getDolGlobalString('TAKEPOS_EMAIL_TEMPLATE_INVOICE') && getDolGlobalInt('TAKEPOS_EMAIL_TEMPLATE_INVOICE') > 0) {
1311 $sectionwithinvoicelink .= ' <button id="buttonsend" type="button" onclick="SendTicket('.$placeid.')">'.$langs->trans('SendTicket').'</button>';
1312 }
1313
1314 if ($remaintopay <= 0 && getDolGlobalString('TAKEPOS_AUTO_PRINT_TICKETS') && $action != "history") {
1315 $sectionwithinvoicelink .= '<script type="text/javascript">$("#buttonprint").click();</script>';
1316 }
1317 }
1318}
1319
1320
1321/*
1322 * View
1323 */
1324
1325$form = new Form($db);
1326
1327// llxHeader
1328if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1329 $title = 'TakePOS - Dolibarr '.DOL_VERSION;
1330 if (getDolGlobalString('MAIN_APPLICATION_TITLE')) {
1331 $title = 'TakePOS - ' . getDolGlobalString('MAIN_APPLICATION_TITLE');
1332 }
1333 $head = '<meta name="apple-mobile-web-app-title" content="TakePOS"/>
1334 <meta name="apple-mobile-web-app-capable" content="yes">
1335 <meta name="mobile-web-app-capable" content="yes">
1336 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>';
1337 $arrayofcss = array(
1338 '/takepos/css/pos.css.php',
1339 );
1340 $arrayofjs = array('/takepos/js/jquery.colorbox-min.js');
1341 $disablejs = 0;
1342 $disablehead = 0;
1343 top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
1344
1345 print '<body>'."\n";
1346} else {
1347 top_httphead('text/html', 1);
1348}
1349
1350?>
1351<!-- invoice.php -->
1352<script type="text/javascript">
1353var selectedline=0;
1354var selectedtext="";
1355<?php if ($action == "valid") {
1356 echo "var place=0;";
1357}?> // Set to default place after close sale
1358var placeid=<?php echo($placeid > 0 ? $placeid : 0); ?>;
1359$(document).ready(function() {
1360 var idoflineadded = <?php echo(empty($idoflineadded) ? 0 : $idoflineadded); ?>;
1361
1362 $('.posinvoiceline').click(function(){
1363 console.log("Click done on "+this.id);
1364 $('.posinvoiceline').removeClass("selected");
1365 $(this).addClass("selected");
1366 if (!this.id) {
1367 return;
1368 }
1369 if (selectedline == this.id) {
1370 return; // If is already selected
1371 } else {
1372 selectedline = this.id;
1373 }
1374 selectedtext=$('#'+selectedline).find("td:first").html();
1375 <?php
1376 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1377 print '$("#phonediv1").load("'.DOL_URL_ROOT.'/takepos/public/auto_order.php?action=editline&token='.newToken().'&placeid="+placeid+"&selectedline="+selectedline, function() {
1378 });';
1379 }
1380 ?>
1381 });
1382
1383 /* Autoselect the line */
1384 if (idoflineadded > 0)
1385 {
1386 console.log("Auto select "+idoflineadded);
1387 $('.posinvoiceline#'+idoflineadded).click();
1388 }
1389<?php
1390
1391if ($action == "order" && !empty($order_receipt_printer1)) {
1392 if (filter_var(getDolGlobalString('TAKEPOS_PRINT_SERVER'), FILTER_VALIDATE_URL) == true) {
1393 ?>
1394 $.ajax({
1395 type: "POST",
1396 url: '<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>/printer/index.php',
1397 data: 'invoice='+orderprinter1esc
1398 });
1399 <?php
1400 } else {
1401 ?>
1402 $.ajax({
1403 type: "POST",
1404 url: 'http://<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>:8111/print',
1405 data: '<?php
1406 print $headerorder.$order_receipt_printer1.$footerorder; ?>'
1407 });
1408 <?php
1409 }
1410}
1411
1412if ($action == "order" && !empty($order_receipt_printer2)) {
1413 if (filter_var(getDolGlobalString('TAKEPOS_PRINT_SERVER'), FILTER_VALIDATE_URL) == true) {
1414 ?>
1415 $.ajax({
1416 type: "POST",
1417 url: '<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>/printer/index.php?printer=2',
1418 data: 'invoice='+orderprinter2esc
1419 });
1420 <?php
1421 } else {
1422 ?>
1423 $.ajax({
1424 type: "POST",
1425 url: 'http://<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>:8111/print2',
1426 data: '<?php
1427 print $headerorder.$order_receipt_printer2.$footerorder; ?>'
1428 });
1429 <?php
1430 }
1431}
1432
1433if ($action == "order" && !empty($order_receipt_printer3)) {
1434 if (filter_var(getDolGlobalString('TAKEPOS_PRINT_SERVER'), FILTER_VALIDATE_URL) == true) {
1435 ?>
1436 $.ajax({
1437 type: "POST",
1438 url: '<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>/printer/index.php?printer=3',
1439 data: 'invoice='+orderprinter3esc
1440 });
1441 <?php
1442 }
1443}
1444
1445// Set focus to search field
1446if ($action == "search" || $action == "valid") {
1447 ?>
1448 parent.ClearSearch(true);
1449 <?php
1450}
1451
1452
1453if ($action == "temp" && !empty($ticket_printer1)) {
1454 ?>
1455 $.ajax({
1456 type: "POST",
1457 url: 'http://<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>:8111/print',
1458 data: '<?php
1459 print $header_soc.$header_ticket.$body_ticket.$ticket_printer1.$ticket_total.$footer_ticket; ?>'
1460 });
1461 <?php
1462}
1463
1464if ($action == "search") {
1465 ?>
1466 $('#search').focus();
1467 <?php
1468}
1469
1470?>
1471
1472});
1473
1474function SendTicket(id)
1475{
1476 console.log("Open box to select the Print/Send form");
1477 $.colorbox({href:"send.php?facid="+id, width:"70%", height:"30%", transition:"none", iframe:"true", title:'<?php echo dol_escape_js($langs->trans("SendTicket")); ?>'});
1478 return true;
1479}
1480
1481function PrintBox(id, action) {
1482 console.log("Open box before printing");
1483 $.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"); ?>"});
1484 return true;
1485}
1486
1487function Print(id, gift){
1488 console.log("Call Print() to generate the receipt.");
1489 $.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")); ?>'});
1490 return true;
1491}
1492
1493function TakeposPrinting(id){
1494 var receipt;
1495 console.log("TakeposPrinting" + id);
1496 $.get("receipt.php?facid="+id, function(data, status) {
1497 receipt=data.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '');
1498 $.ajax({
1499 type: "POST",
1500 url: 'http://<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>:8111/print',
1501 data: receipt
1502 });
1503 });
1504 return true;
1505}
1506
1507function TakeposConnector(id){
1508 console.log("TakeposConnector" + id);
1509 $.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) {
1510 $.ajax({
1511 type: "POST",
1512 url: '<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>/printer/index.php',
1513 data: 'invoice='+data
1514 });
1515 });
1516 return true;
1517}
1518
1519// Call the ajax to execute the print.
1520// With some external module another method may be called.
1521function DolibarrTakeposPrinting(id) {
1522 console.log("DolibarrTakeposPrinting Printing invoice ticket " + id);
1523 $.ajax({
1524 type: "GET",
1525 data: { token: '<?php echo currentToken(); ?>' },
1526 url: "<?php print DOL_URL_ROOT.'/takepos/ajax/ajax.php?action=printinvoiceticket&token='.newToken().'&term='.urlencode(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '').'&id='; ?>" + id,
1527
1528 });
1529 return true;
1530}
1531
1532// Call url to generate a credit note (with same lines) from existing invoice
1533function CreditNote() {
1534 $("#poslines").load("<?php print DOL_URL_ROOT; ?>/takepos/invoice.php?action=creditnote&token=<?php echo newToken() ?>&invoiceid="+placeid, function() { });
1535 return true;
1536}
1537
1538// Call url to add notes
1539function SetNote() {
1540 $("#poslines").load("<?php print DOL_URL_ROOT; ?>/takepos/invoice.php?action=addnote&token=<?php echo newToken() ?>&invoiceid="+placeid+"&idline="+selectedline, { "addnote": $("#textinput").val() });
1541 return true;
1542}
1543
1544
1545$( document ).ready(function() {
1546 console.log("Set customer info and sales in header placeid=<?php echo $placeid; ?> status=<?php echo $invoice->statut; ?>");
1547
1548 <?php
1549 $s = $langs->trans("Customer");
1550 if ($invoice->id > 0 && ($invoice->socid != getDolGlobalString($constforcompanyid))) {
1551 $s = $soc->name;
1552 if (getDolGlobalInt('TAKEPOS_CHOOSE_CONTACT')) {
1553 $contactids = $invoice->getIdContact('external', 'BILLING');
1554 $contactid = $contactids[0];
1555 if ($contactid > 0) {
1556 $contact = new Contact($db);
1557 $contact->fetch($contactid);
1558 $s .= " - " . $contact->getFullName($langs);
1559 }
1560 }
1561 } elseif (getDolGlobalInt("TAKEPOS_NO_GENERIC_THIRDPARTY")) {
1562 print '$("#idcustomer").val("");';
1563 }
1564 ?>
1565
1566 $("#customerandsales").html('');
1567 $("#shoppingcart").html('');
1568
1569 <?php if (getDolGlobalInt('TAKEPOS_CHOOSE_CONTACT') == 0) { ?>
1570 $("#customerandsales").append('<a class="valignmiddle tdoverflowmax100 minwidth100" id="customer" onclick="Customer();" title="<?php print dol_escape_js(dol_escape_htmltag($s)); ?>"><span class="fas fa-building paddingrightonly"></span><?php print dol_escape_js($s); ?></a>');
1571 <?php } else { ?>
1572 $("#customerandsales").append('<a class="valignmiddle tdoverflowmax300 minwidth100" id="contact" onclick="Contact();" title="<?php print dol_escape_js(dol_escape_htmltag($s)); ?>"><span class="fas fa-building paddingrightonly"></span><?php print dol_escape_js($s); ?></a>');
1573 <?php } ?>
1574
1575 <?php
1576 $sql = "SELECT rowid, datec, ref FROM ".MAIN_DB_PREFIX."facture";
1577 $sql .= " WHERE entity IN (".getEntity('invoice').")";
1578 if (!getDolGlobalString('TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED')) {
1579 // By default, only invoices with a ref not already defined can in list of open invoice we can edit.
1580 $sql .= " AND ref LIKE '(PROV-POS".$db->escape(isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '')."-0%'";
1581 } else {
1582 // If TAKEPOS_CAN_EDIT_IF_ALREADY_VALIDATED set, we show also draft invoice that already has a reference defined
1583 $sql .= " AND pos_source = '".$db->escape($_SESSION["takeposterminal"])."'";
1584 $sql .= " AND module_source = 'takepos'";
1585 }
1586
1587 $sql .= $db->order('datec', 'ASC');
1588 $resql = $db->query($sql);
1589 if ($resql) {
1590 $max_sale = 0;
1591 while ($obj = $db->fetch_object($resql)) {
1592 echo '$("#shoppingcart").append(\'';
1593 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=\\\'';
1594 $num_sale = str_replace(")", "", str_replace("(PROV-POS".$_SESSION["takeposterminal"]."-", "", $obj->ref));
1595 echo $num_sale;
1596 if (str_replace("-", "", $num_sale) > $max_sale) {
1597 $max_sale = str_replace("-", "", $num_sale);
1598 }
1599 echo '\\\'; invoiceid=\\\'';
1600 echo $obj->rowid;
1601 echo '\\\'; Refresh();">';
1602 if ($placeid == $obj->rowid) {
1603 echo '<span class="basketselected">';
1604 } else {
1605 echo '<span class="basketnotselected">';
1606 }
1607 echo '<span class="fa fa-shopping-cart paddingright"></span>'.dol_print_date($db->jdate($obj->datec), '%H:%M', 'tzuser');
1608 echo '</span>';
1609 echo '</a>\');';
1610 }
1611 echo '$("#shoppingcart").append(\'<a onclick="place=\\\'0-';
1612 echo $max_sale + 1;
1613 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>\');';
1614 } else {
1615 dol_print_error($db);
1616 }
1617
1618 $s = '';
1619
1620 $idwarehouse = 0;
1621 $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
1622 if (isModEnabled('stock')) {
1623 if (getDolGlobalString($constantforkey) != "1") {
1624 $constantforkey = 'CASHDESK_ID_WAREHOUSE'. (isset($_SESSION["takeposterminal"]) ? $_SESSION["takeposterminal"] : '');
1625 $idwarehouse = getDolGlobalString($constantforkey);
1626 if ($idwarehouse > 0) {
1627 $s = '<span class="small">';
1628 $warehouse = new Entrepot($db);
1629 $warehouse->fetch($idwarehouse);
1630 $s .= '<span class="hideonsmartphone">'.$langs->trans("Warehouse").'<br></span>'.$warehouse->ref;
1631 if ($warehouse->statut == Entrepot::STATUS_CLOSED) {
1632 $s .= ' ('.$langs->trans("Closed").')';
1633 }
1634 $s .= '</span>';
1635 print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1636 print '$("#infowarehouse").css("display", "inline-block");';
1637 } else {
1638 $s = '<span class="small hideonsmartphone">';
1639 $s .= $langs->trans("StockChangeDisabled").'<br>'.$langs->trans("NoWarehouseDefinedForTerminal");
1640 $s .= '</span>';
1641 print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1642 if (!empty($conf->dol_optimize_smallscreen)) {
1643 print '$("#infowarehouse").css("display", "none");';
1644 }
1645 }
1646 } else {
1647 $s = '<span class="small hideonsmartphone">'.$langs->trans("StockChangeDisabled").'</span>';
1648 print "$('#infowarehouse').html('".dol_escape_js($s)."');";
1649 if (!empty($conf->dol_optimize_smallscreen)) {
1650 print '$("#infowarehouse").css("display", "none");';
1651 }
1652 }
1653 }
1654
1655
1656 // Module Adherent
1657 $s = '';
1658 if (isModEnabled('member') && $invoice->socid > 0 && $invoice->socid != getDolGlobalInt($constforcompanyid)) {
1659 $s = '<span class="small">';
1660 require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php';
1661 $langs->load("members");
1662 $s .= $langs->trans("Member").': ';
1663 $adh = new Adherent($db);
1664 $result = $adh->fetch('', '', $invoice->socid);
1665 if ($result > 0) {
1666 $adh->ref = $adh->getFullName($langs);
1667 if (empty($adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {
1668 $s .= "<s>";
1669 }
1670 $s .= $adh->getFullName($langs);
1671 $s .= ' - '.$adh->type;
1672 if ($adh->datefin) {
1673 $s .= '<br>'.$langs->trans("SubscriptionEndDate").': '.dol_print_date($adh->datefin, 'day');
1674 if ($adh->hasDelay()) {
1675 $s .= " ".img_warning($langs->trans("Late"));
1676 }
1677 } else {
1678 $s .= '<br>'.$langs->trans("SubscriptionNotReceived");
1679 if ($adh->statut > 0) {
1680 $s .= " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft and not terminated
1681 }
1682 }
1683 if (empty($adh->statut) || $adh->statut == Adherent::STATUS_EXCLUDED) {
1684 $s .= "</s>";
1685 }
1686 } else {
1687 $s .= '<br>'.$langs->trans("ThirdpartyNotLinkedToMember");
1688 }
1689 $s .= '</span>';
1690 }
1691 ?>
1692 $("#moreinfo").html('<?php print dol_escape_js($s); ?>');
1693
1694});
1695
1696
1697<?php
1698if (getDolGlobalString('TAKEPOS_CUSTOMER_DISPLAY')) {
1699 echo "function CustomerDisplay(){";
1700 echo "var line1='".$CUSTOMER_DISPLAY_line1."'.substring(0,20);";
1701 echo "line1=line1.padEnd(20);";
1702 echo "var line2='".$CUSTOMER_DISPLAY_line2."'.substring(0,20);";
1703 echo "line2=line2.padEnd(20);";
1704 echo "$.ajax({
1705 type: 'GET',
1706 data: { text: line1+line2 },
1707 url: '".getDolGlobalString('TAKEPOS_PRINT_SERVER')."/display/index.php',
1708 });";
1709 echo "}";
1710}
1711?>
1712
1713</script>
1714
1715<?php
1716// Add again js for footer because this content is injected into index.php page so all init
1717// for tooltip and other js beautifiers must be reexecuted too.
1718if (!empty($conf->use_javascript_ajax)) {
1719 print "\n".'<!-- Includes JS Footer of Dolibarr -->'."\n";
1720 print '<script src="'.DOL_URL_ROOT.'/core/js/lib_foot.js.php?lang='.$langs->defaultlang.'"></script>'."\n";
1721}
1722
1723$usediv = (GETPOST('format') == 'div');
1724
1725print '<!-- invoice.php place='.(int) $place.' invoice='.$invoice->ref.' usediv='.json_encode($usediv).', mobilepage='.(empty($mobilepage) ? '' : $mobilepage).' $_SESSION["basiclayout"]='.(empty($_SESSION["basiclayout"]) ? '' : $_SESSION["basiclayout"]).' conf TAKEPOS_BAR_RESTAURANT='.getDolGlobalString('TAKEPOS_BAR_RESTAURANT').' -->'."\n";
1726print '<div class="div-table-responsive-no-min invoice">';
1727if ($usediv) {
1728 print '<div id="tablelines">';
1729} else {
1730 print '<table id="tablelines" class="noborder noshadow postablelines centpercent">';
1731}
1732
1733$buttontocreatecreditnote = '';
1734if (($action == "valid" || $action == "history" || ($action == "addline" && $invoice->status == $invoice::STATUS_CLOSED)) && $invoice->type != Facture::TYPE_CREDIT_NOTE && !getDolGlobalString('TAKEPOS_NO_CREDITNOTE')) {
1735 $buttontocreatecreditnote .= ' &nbsp; <!-- Show button to create a credit note -->'."\n";
1736 $buttontocreatecreditnote .= '<button id="buttonprint" type="button" onclick="ModalBox(\'ModalCreditNote\')">'.$langs->trans('CreateCreditNote').'</button>';
1737 if (getDolGlobalInt('TAKEPOS_PRINT_INVOICE_DOC_INSTEAD_OF_RECEIPT')) {
1738 $buttontocreatecreditnote .= ' <a target="_blank" class="button" href="' . DOL_URL_ROOT . '/document.php?token=' . newToken() . '&modulepart=facture&file=' . urlencode($invoice->ref . '/' . $invoice->ref . '.pdf').'">'.$langs->trans("Invoice").'</a>';
1739 }
1740}
1741
1742// Show the ref of invoice
1743if ($sectionwithinvoicelink && ($mobilepage == "invoice" || $mobilepage == "")) {
1744 print '<!-- Print table line with link to invoice ref -->';
1745 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1746 print '<tr><td colspan="5" class="paddingtopimp paddingbottomimp" style="padding-top: 10px !important; padding-bottom: 10px !important;">';
1747 print $sectionwithinvoicelink;
1748 print $buttontocreatecreditnote;
1749 print '</td></tr>';
1750 } else {
1751 print '<tr><td colspan="4" class="paddingtopimp paddingbottomimp" style="padding-top: 10px !important; padding-bottom: 10px !important;">';
1752 print $sectionwithinvoicelink;
1753 print $buttontocreatecreditnote;
1754 print '</td></tr>';
1755 }
1756}
1757
1758// Show the list of selected product
1759if (!$usediv) {
1760 print '<tr class="liste_titre nodrag nodrop">';
1761 print '<td class="linecoldescription">';
1762}
1763// In phone version only show when it is invoice page
1764if (empty($mobilepage) || $mobilepage == "invoice") {
1765 print '<!-- hidden var used by some js functions -->';
1766 print '<input type="hidden" name="invoiceid" id="invoiceid" value="'.$invoice->id.'">';
1767 print '<input type="hidden" name="thirdpartyid" id="thirdpartyid" value="'.$invoice->socid.'">';
1768}
1769if (!$usediv) {
1770 if (getDolGlobalString('TAKEPOS_BAR_RESTAURANT')) {
1771 $sql = "SELECT floor, label FROM ".MAIN_DB_PREFIX."takepos_floor_tables where rowid=".((int) $place);
1772 $resql = $db->query($sql);
1773 $obj = $db->fetch_object($resql);
1774 if ($obj) {
1775 $label = $obj->label;
1776 $floor = $obj->floor;
1777 }
1778 if ($mobilepage == "invoice" || $mobilepage == "") {
1779 // If not on smartphone version or if it is the invoice page
1780 //print 'mobilepage='.$mobilepage;
1781 print '<span class="opacitymedium">'.$langs->trans('Place')."</span> <b>".(empty($label) ? '?' : $label)."</b><br>";
1782 print '<span class="opacitymedium">'.$langs->trans('Floor')."</span> <b>".(empty($floor) ? '?' : $floor)."</b>";
1783 }
1784 }
1785 print '</td>';
1786}
1787
1788// Complete header by hook
1789$parameters = array();
1790$reshook = $hookmanager->executeHooks('completeTakePosInvoiceHeader', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1791if ($reshook < 0) {
1792 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1793}
1794print $hookmanager->resPrint;
1795
1796if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1797 if (getDolGlobalInt("TAKEPOS_SHOW_SUBPRICE")) {
1798 print '<td class="linecolqty right">'.$langs->trans('PriceUHT').'</td>';
1799 }
1800 print '<td class="linecolqty right">'.$langs->trans('ReductionShort').'</td>';
1801 print '<td class="linecolqty right">'.$langs->trans('Qty').'</td>';
1802 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
1803 print '<td class="linecolht right nowraponall">';
1804 print '<span class="opacitymedium small">' . $langs->trans('TotalHTShort') . '</span><br>';
1805 // In phone version only show when it is invoice page
1806 if (empty($mobilepage) || $mobilepage == "invoice") {
1807 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>';
1808 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1809 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1810 include_once DOL_DOCUMENT_ROOT . '/multicurrency/class/multicurrency.class.php';
1811 $multicurrency = new MultiCurrency($db);
1812 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1813 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>';
1814 }
1815 }
1816 print '</td>';
1817 }
1818 print '<td class="linecolht right nowraponall">';
1819 print '<span class="opacitymedium small">'.$langs->trans('TotalTTCShort').'</span><br>';
1820 // In phone version only show when it is invoice page
1821 if (empty($mobilepage) || $mobilepage == "invoice") {
1822 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>';
1823 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
1824 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
1825 include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
1826 $multicurrency = new MultiCurrency($db);
1827 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
1828 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>';
1829 }
1830 }
1831 print '</td>';
1832} elseif ($mobilepage == "invoice") {
1833 print '<td class="linecolqty right">'.$langs->trans('Qty').'</td>';
1834}
1835if (!$usediv) {
1836 print "</tr>\n";
1837}
1838
1839if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1840 if ($mobilepage == "cats") {
1841 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1842 $categorie = new Categorie($db);
1843 $categories = $categorie->get_full_arbo('product');
1844 $htmlforlines = '';
1845 foreach ($categories as $row) {
1846 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1847 $htmlforlines .= '<div class="leftcat"';
1848 } else {
1849 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline"';
1850 }
1851 $htmlforlines .= ' onclick="LoadProducts('.$row['id'].');">';
1852 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1853 $htmlforlines .= '<img class="imgwrapper" width="33%" src="'.DOL_URL_ROOT.'/takepos/public/auto_order.php?genimg=cat&query=cat&id='.$row['id'].'"><br>';
1854 } else {
1855 $htmlforlines .= '<td class="left">';
1856 }
1857 $htmlforlines .= $row['label'];
1858 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1859 $htmlforlines .= '</div>'."\n";
1860 } else {
1861 $htmlforlines .= '</td></tr>'."\n";
1862 }
1863 }
1864 print $htmlforlines;
1865 }
1866
1867 if ($mobilepage == "products") {
1868 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
1869 $object = new Categorie($db);
1870 $catid = GETPOSTINT('catid');
1871 $result = $object->fetch($catid);
1872 $prods = $object->getObjectsInCateg("product");
1873 $htmlforlines = '';
1874 foreach ($prods as $row) {
1875 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1876 $htmlforlines .= '<div class="leftcat"';
1877 } else {
1878 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline"';
1879 }
1880 $htmlforlines .= ' onclick="AddProduct(\''.$place.'\', '.$row->id.')"';
1881 $htmlforlines .= '>';
1882 if (defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
1883 $htmlforlines .= '<img class="imgwrapper" width="33%" src="'.DOL_URL_ROOT.'/takepos/public/auto_order.php?genimg=pro&query=pro&id='.$row->id.'"><br>';
1884 $htmlforlines .= $row->label.' '.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency);
1885 $htmlforlines .= '</div>'."\n";
1886 } else {
1887 $htmlforlines .= '<td class="left">';
1888 $htmlforlines .= $row->label;
1889 $htmlforlines .= '<div class="right">'.price($row->price_ttc, 1, $langs, 1, -1, -1, $conf->currency).'</div>';
1890 $htmlforlines .= '</td>';
1891 $htmlforlines .= '</tr>'."\n";
1892 }
1893 }
1894 print $htmlforlines;
1895 }
1896
1897 if ($mobilepage == "places") {
1898 $sql = "SELECT rowid, entity, label, leftpos, toppos, floor FROM ".MAIN_DB_PREFIX."takepos_floor_tables";
1899 $resql = $db->query($sql);
1900
1901 $rows = array();
1902 $htmlforlines = '';
1903 while ($row = $db->fetch_array($resql)) {
1904 $rows[] = $row;
1905 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1906 $htmlforlines .= '" onclick="LoadPlace(\''.$row['label'].'\')">';
1907 $htmlforlines .= '<td class="left">';
1908 $htmlforlines .= $row['label'];
1909 $htmlforlines .= '</td>';
1910 $htmlforlines .= '</tr>'."\n";
1911 }
1912 print $htmlforlines;
1913 }
1914}
1915
1916if ($placeid > 0) {
1917 //In Phone basic layout hide some content depends situation
1918 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1 && $mobilepage != "invoice" && $action != "order") {
1919 return;
1920 }
1921
1922 // Loop on each lines on invoice
1923 if (is_array($invoice->lines) && count($invoice->lines)) {
1924 print '<!-- invoice.php show lines of invoices -->'."\n";
1925 $tmplines = array_reverse($invoice->lines);
1926 $htmlsupplements = array();
1927 foreach ($tmplines as $line) {
1928 if ($line->fk_parent_line != false) {
1929 $htmlsupplements[$line->fk_parent_line] .= '<tr class="drag drop oddeven posinvoiceline';
1930 if ($line->special_code == "4") {
1931 $htmlsupplements[$line->fk_parent_line] .= ' order';
1932 }
1933 $htmlsupplements[$line->fk_parent_line] .= '" id="'.$line->id.'"';
1934 if ($line->special_code == "4") {
1935 $htmlsupplements[$line->fk_parent_line] .= ' title="'.dol_escape_htmltag($langs->trans("AlreadyPrinted")).'"';
1936 }
1937 $htmlsupplements[$line->fk_parent_line] .= '>';
1938 $htmlsupplements[$line->fk_parent_line] .= '<td class="left">';
1939 $htmlsupplements[$line->fk_parent_line] .= img_picto('', 'rightarrow');
1940 if ($line->product_label) {
1941 $htmlsupplements[$line->fk_parent_line] .= $line->product_label;
1942 }
1943 if ($line->product_label && $line->desc) {
1944 $htmlsupplements[$line->fk_parent_line] .= '<br>';
1945 }
1946 if ($line->product_label != $line->desc) {
1947 $firstline = dolGetFirstLineOfText($line->desc);
1948 if ($firstline != $line->desc) {
1949 $htmlsupplements[$line->fk_parent_line] .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
1950 } else {
1951 $htmlsupplements[$line->fk_parent_line] .= $line->desc;
1952 }
1953 }
1954 $htmlsupplements[$line->fk_parent_line] .= '</td>';
1955
1956 // complete line by hook
1957 $parameters = array('line' => $line);
1958 $reshook = $hookmanager->executeHooks('completeTakePosInvoiceParentLine', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
1959 if ($reshook < 0) {
1960 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1961 }
1962 $htmlsupplements[$line->fk_parent_line] .= $hookmanager->resPrint;
1963
1964 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
1965 $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.vatrate(price2num($line->remise_percent), true).'</td>';
1966 $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.$line->qty.'</td>';
1967 $htmlsupplements[$line->fk_parent_line] .= '<td class="right">'.price($line->total_ttc).'</td>';
1968 }
1969 $htmlsupplements[$line->fk_parent_line] .= '</tr>'."\n";
1970 continue;
1971 }
1972 $htmlforlines = '';
1973
1974 $htmlforlines .= '<tr class="drag drop oddeven posinvoiceline';
1975 if ($line->special_code == "4") {
1976 $htmlforlines .= ' order';
1977 }
1978 $htmlforlines .= '" id="'.$line->id.'"';
1979 if ($line->special_code == "4") {
1980 $htmlforlines .= ' title="'.dol_escape_htmltag($langs->trans("AlreadyPrinted")).'"';
1981 }
1982 $htmlforlines .= '>';
1983 $htmlforlines .= '<td class="left">';
1984 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
1985 $htmlforlines .= '<span class="phoneqty">'.$line->qty."</span> x ";
1986 }
1987 if (isset($line->product_type)) {
1988 if (empty($line->product_type)) {
1989 $htmlforlines .= img_object('', 'product').' ';
1990 } else {
1991 $htmlforlines .= img_object('', 'service').' ';
1992 }
1993 }
1994 $tooltiptext = '';
1995 if (!getDolGlobalString('TAKEPOS_SHOW_N_FIRST_LINES')) {
1996 if ($line->product_ref) {
1997 $tooltiptext .= '<b>'.$langs->trans("Ref").'</b> : '.$line->product_ref.'<br>';
1998 $tooltiptext .= '<b>'.$langs->trans("Label").'</b> : '.$line->product_label.'<br>';
1999 if (!empty($line->batch)) {
2000 $tooltiptext .= '<br><b>'.$langs->trans("LotSerial").'</b> : '.$line->batch.'<br>';
2001 }
2002 if (!empty($line->fk_warehouse)) {
2003 $tooltiptext .= '<b>'.$langs->trans("Warehouse").'</b> : '.$line->fk_warehouse.'<br>';
2004 }
2005 if ($line->product_label != $line->desc) {
2006 if ($line->desc) {
2007 $tooltiptext .= '<br>';
2008 }
2009 $tooltiptext .= $line->desc;
2010 }
2011 }
2012 if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) {
2013 $htmlforlines .= $form->textwithpicto($line->product_label ? '<b>' . $line->product_ref . '</b> - ' . $line->product_label : dolGetFirstLineOfText($line->desc, 1), $tooltiptext);
2014 } elseif (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 2) {
2015 $htmlforlines .= $form->textwithpicto($line->product_ref ? '<b>'.$line->product_ref.'<b>' : dolGetFirstLineOfText($line->desc, 1), $tooltiptext);
2016 } else {
2017 $htmlforlines .= $form->textwithpicto($line->product_label ? $line->product_label : ($line->product_ref ? $line->product_ref : dolGetFirstLineOfText($line->desc, 1)), $tooltiptext);
2018 }
2019 } else {
2020 if ($line->product_ref) {
2021 $tooltiptext .= '<b>'.$langs->trans("Ref").'</b> : '.$line->product_ref.'<br>';
2022 $tooltiptext .= '<b>'.$langs->trans("Label").'</b> : '.$line->product_label.'<br>';
2023 }
2024 if (!empty($line->batch)) {
2025 $tooltiptext .= '<br><b>'.$langs->trans("LotSerial").'</b> : '.$line->batch.'<br>';
2026 }
2027 if (!empty($line->fk_warehouse)) {
2028 $tooltiptext .= '<b>'.$langs->trans("Warehouse").'</b> : '.$line->fk_warehouse.'<br>';
2029 }
2030
2031 if ($line->product_label) {
2032 $htmlforlines .= $line->product_label;
2033 }
2034 if ($line->product_label != $line->desc) {
2035 if ($line->product_label && $line->desc) {
2036 $htmlforlines .= '<br>';
2037 }
2038 $firstline = dolGetFirstLineOfText($line->desc, getDolGlobalInt('TAKEPOS_SHOW_N_FIRST_LINES'));
2039 if ($firstline != $line->desc) {
2040 $htmlforlines .= $form->textwithpicto(dolGetFirstLineOfText($line->desc), $line->desc);
2041 } else {
2042 $htmlforlines .= $line->desc;
2043 }
2044 }
2045 }
2046 if (!empty($line->array_options['options_order_notes'])) {
2047 $htmlforlines .= "<br>(".$line->array_options['options_order_notes'].")";
2048 }
2049 if (!empty($_SESSION["basiclayout"]) && $_SESSION["basiclayout"] == 1) {
2050 $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>';
2051 }
2052 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
2053 $moreinfo = '';
2054 $moreinfo .= $langs->transcountry("TotalHT", $mysoc->country_code).': '.price($line->total_ht);
2055 if ($line->vat_src_code) {
2056 $moreinfo .= '<br>'.$langs->trans("VATCode").': '.$line->vat_src_code;
2057 }
2058 $moreinfo .= '<br>'.$langs->transcountry("TotalVAT", $mysoc->country_code).': '.price($line->total_tva);
2059 $moreinfo .= '<br>'.$langs->transcountry("TotalLT1", $mysoc->country_code).': '.price($line->total_localtax1);
2060 $moreinfo .= '<br>'.$langs->transcountry("TotalLT2", $mysoc->country_code).': '.price($line->total_localtax2);
2061 $moreinfo .= '<hr>';
2062 $moreinfo .= $langs->transcountry("TotalTTC", $mysoc->country_code).': '.price($line->total_ttc);
2063 //$moreinfo .= $langs->trans("TotalHT").': '.$line->total_ht;
2064 if ($line->date_start || $line->date_end) {
2065 $htmlforlines .= '<br><div class="clearboth nowraponall">'.get_date_range($line->date_start, $line->date_end).'</div>';
2066 }
2067 $htmlforlines .= '</td>';
2068
2069 // complete line by hook
2070 $parameters = array('line' => $line);
2071 $reshook = $hookmanager->executeHooks('completeTakePosInvoiceLine', $parameters, $invoice, $action); // Note that $action and $object may have been modified by some hooks
2072 if ($reshook < 0) {
2073 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2074 }
2075 $htmlforlines .= $hookmanager->resPrint;
2076
2077 if (getDolGlobalInt("TAKEPOS_SHOW_SUBPRICE")) {
2078 $htmlforlines .= '<td class="right">'.price($line->subprice).'</td>';
2079 }
2080 $htmlforlines .= '<td class="right">'.vatrate(price2num($line->remise_percent), true).'</td>';
2081 $htmlforlines .= '<td class="right">';
2082 if (isModEnabled('stock') && $user->hasRight('stock', 'mouvement', 'lire')) {
2083 $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"];
2084 if (getDolGlobalString($constantforkey) && $line->fk_product > 0 && !getDolGlobalString('TAKEPOS_HIDE_STOCK_ON_LINE')) {
2085 $sql = "SELECT e.rowid, e.ref, e.lieu, e.fk_parent, e.statut, ps.reel, ps.rowid as product_stock_id, p.pmp";
2086 $sql .= " FROM ".MAIN_DB_PREFIX."entrepot as e,";
2087 $sql .= " ".MAIN_DB_PREFIX."product_stock as ps";
2088 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON p.rowid = ps.fk_product";
2089 $sql .= " WHERE ps.reel != 0";
2090 $sql .= " AND ps.fk_entrepot = ".((int) getDolGlobalString($constantforkey));
2091 $sql .= " AND e.entity IN (".getEntity('stock').")";
2092 $sql .= " AND ps.fk_product = ".((int) $line->fk_product);
2093 $resql = $db->query($sql);
2094 if ($resql) {
2095 $stock_real = 0;
2096 $obj = $db->fetch_object($resql);
2097 if ($obj) {
2098 $stock_real = price2num($obj->reel, 'MS');
2099 }
2100 $htmlforlines .= $line->qty;
2101 $htmlforlines .= '&nbsp; ';
2102 $htmlforlines .= '<span class="opacitylow" title="'.$langs->trans("Stock").' '.price($stock_real, 1, '', 1, 0).'">';
2103 $htmlforlines .= '(';
2104 if ($line->qty && $line->qty > $stock_real) {
2105 $htmlforlines .= '<span style="color: var(--amountremaintopaycolor)">';
2106 }
2107 $htmlforlines .= img_picto('', 'stock', 'class="pictofixedwidth"').price($stock_real, 1, '', 1, 0);
2108 if ($line->qty && $line->qty > $stock_real) {
2109 $htmlforlines .= "</span>";
2110 }
2111 $htmlforlines .= ')';
2112 $htmlforlines .= '</span>';
2113 } else {
2114 dol_print_error($db);
2115 }
2116 } else {
2117 $htmlforlines .= $line->qty;
2118 }
2119 } else {
2120 $htmlforlines .= $line->qty;
2121 }
2122
2123 $htmlforlines .= '</td>';
2124 if (getDolGlobalInt('TAKEPOS_SHOW_HT')) {
2125 $htmlforlines .= '<td class="right classfortooltip" title="'.$moreinfo.'">';
2126 $htmlforlines .= price($line->total_ht, 1, '', 1, -1, -1, $conf->currency);
2127 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
2128 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
2129 include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
2130 $multicurrency = new MultiCurrency($db);
2131 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
2132 $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>';
2133 }
2134 $htmlforlines .= '</td>';
2135 }
2136 $htmlforlines .= '<td class="right classfortooltip" title="'.$moreinfo.'">';
2137 $htmlforlines .= price($line->total_ttc, 1, '', 1, -1, -1, $conf->currency);
2138 if (isModEnabled('multicurrency') && !empty($_SESSION["takeposcustomercurrency"]) && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
2139 //Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
2140 include_once DOL_DOCUMENT_ROOT.'/multicurrency/class/multicurrency.class.php';
2141 $multicurrency = new MultiCurrency($db);
2142 $multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
2143 $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>';
2144 }
2145 $htmlforlines .= '</td>';
2146 }
2147 $htmlforlines .= '</tr>'."\n";
2148 $htmlforlines .= empty($htmlsupplements[$line->id]) ? '' : $htmlsupplements[$line->id];
2149
2150 print $htmlforlines;
2151 }
2152 } else {
2153 print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">'.$langs->trans("Empty").'</span></td><td></td>';
2154 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
2155 print '<td></td><td></td>';
2156 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
2157 print '<td></td>';
2158 }
2159 }
2160 print '</tr>';
2161 }
2162} else { // No invoice generated yet
2163 print '<tr class="drag drop oddeven"><td class="left"><span class="opacitymedium">'.$langs->trans("Empty").'</span></td><td></td>';
2164 if (empty($_SESSION["basiclayout"]) || $_SESSION["basiclayout"] != 1) {
2165 print '<td></td><td></td>';
2166 if (getDolGlobalString('TAKEPOS_SHOW_HT')) {
2167 print '<td></td>';
2168 }
2169 }
2170 print '</tr>';
2171}
2172
2173if ($usediv) {
2174 print '</div>';
2175} else {
2176 print '</table>';
2177}
2178
2179if ($action == "search") {
2180 print '<center>
2181 <input type="text" id="search" class="input-nobottom" name="search" onkeyup="Search2(\'\', null);" style="width: 80%; font-size: 150%;" placeholder="'.dol_escape_htmltag($langs->trans('Search')).'">
2182 </center>';
2183}
2184
2185print '</div>';
2186
2187// llxFooter
2188if ((getDolGlobalString('TAKEPOS_PHONE_BASIC_LAYOUT') == 1 && $conf->browser->layout == 'phone') || defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) {
2189 print '</body></html>';
2190}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
$object ref
Definition info.php:89
Class to manage members of a foundation.
const STATUS_EXCLUDED
Excluded.
Class to manage categories.
Class to manage contact/addresses.
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 to manage stock movements.
Class Currency.
Class to manage payments of customer invoices.
Class to manage products or services.
Manage record for batch number management.
Class to manage third parties objects (customers, suppliers, prospects...)
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:171
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
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_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
GETPOSTFLOAT($paramname, $rounding='')
Return the value of a $_GET or $_POST supervariable, converted into float.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_htmloutput_errors($mesgstring='', $mesgarray=array(), $keepembedded=0)
Print formatted error messages to output (Used to show messages on html output).
get_localtax($vatrate, $local, $thirdparty_buyer=null, $thirdparty_seller=null, $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate,...
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
treeview li table
No Email.
ui state ui widget content ui state ui widget header ui state a ui button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs=array(), $arrayofcss=array(), $disableforlogin=0, $disablenofollow=0, $disablenoindex=0)
Output html header of a page.
if(!defined( 'NOREQUIREMENU')) if(!empty(GETPOST('seteventmessages', 'alpha'))) if(!function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:150
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
if(empty( $takeposterminal)) fail($message)
Abort invoice creation with a given error message.
Definition invoice.php:123