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