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