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