dolibarr 25.0.0-alpha
index.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2018 Andreu Bisquerra <jove@bisquerra.com>
3 * Copyright (C) 2019 Josep Lluís Amador <joseplluis@lliuretic.cat>
4 * Copyright (C) 2020 Thibault FOUCART <support@ptibogxiv.net>
5 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
6 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2026 Jose Martinez <jose.martinez@pichinov.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
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('NOREQUIREMENU')) {
35 define('NOREQUIREMENU', '1');
36}
37if (!defined('NOREQUIREHTML')) {
38 define('NOREQUIREHTML', '1');
39}
40if (!defined('NOREQUIREAJAX')) {
41 define('NOREQUIREAJAX', '1');
42}
43
44// Load Dolibarr environment
45require '../main.inc.php'; // Load $user and permissions
54require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
55require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
56require_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php';
57require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
58require_once DOL_DOCUMENT_ROOT.'/core/lib/takepos.lib.php';
59require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
60require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
61require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
62
63
64$langs->loadLangs(array("bills", "orders", "commercial", "cashdesk", "receiptprinter", "banks"));
65
66$place = (GETPOST('place', 'aZ09') ? GETPOST('place', 'aZ09') : 0); // $place is id of table for Bar or Restaurant or multiple sales
67$action = GETPOST('action', 'aZ09');
68$setterminal = GETPOSTINT('setterminal');
69$setcurrency = GETPOST('setcurrency', 'aZ09');
70
71$hookmanager->initHooks(array('takeposfrontend'));
72if (empty($_SESSION["takeposterminal"])) {
73 $enabledterminals = takeposEnabledTerminals();
74 if (count($enabledterminals) == 1) {
75 $_SESSION["takeposterminal"] = (int) $enabledterminals[0]; // Use the only usable terminal
76 } elseif (!empty($_COOKIE["takeposterminal"])) {
77 $_SESSION["takeposterminal"] = preg_replace('/[^a-zA-Z0-9_\-]/', '', $_COOKIE["takeposterminal"]); // Restore takeposterminal from previous session
78 }
79}
80
81if ($setterminal > 0) {
82 $_SESSION["takeposterminal"] = (int) $setterminal;
83 dolSetCookie("takeposterminal", (string) $setterminal, -1); // takeposterminal var in a 1 year cookie
84}
85
86if ($setcurrency != "") {
87 $_SESSION["takeposcustomercurrency"] = $setcurrency;
88 // We will recalculate amount for foreign currency at next call of invoice.php when $_SESSION["takeposcustomercurrency"] differs from invoice->multicurrency_code.
89}
90
91
92$categorie = new Categorie($db);
93
94$maxcategbydefaultforthisdevice = 12;
95$maxproductbydefaultforthisdevice = 24;
96
97$MAXCATEG = getDolGlobalInt('TAKEPOS_NB_MAXCATEG', $maxcategbydefaultforthisdevice);
98$MAXPRODUCT = getDolGlobalInt('TAKEPOS_NB_MAXPRODUCT', $maxproductbydefaultforthisdevice);
99
100$term = empty($_SESSION['takeposterminal']) ? 1 : $_SESSION['takeposterminal'];
101
102$socid = getDolGlobalInt('CASHDESK_ID_THIRDPARTY' . $term);
103
104
105/*
106 $constforcompanyid = 'CASHDESK_ID_THIRDPARTY'.$_SESSION["takeposterminal"];
107 $soc = new Societe($db);
108 if ($invoice->socid > 0) $soc->fetch($invoice->socid);
109 else $soc->fetch(getDolGlobalInt($constforcompanyid));
110 */
111
112// Security check
113$result = restrictedArea($user, 'takepos', 0, '');
114
115
116
117/*
118 * View
119 */
120
121$form = new Form($db);
122
123$disablejs = 0;
124$disablehead = 0;
125$arrayofjs = array('/takepos/js/jquery.colorbox-min.js'); // TODO It seems we don't need this
126$arrayofcss = array('/takepos/css/pos.css.php', '/takepos/css/colorbox.css');
127
128if (getDolGlobalInt('TAKEPOS_COLOR_THEME') == 1) {
129 $arrayofcss[] = '/takepos/css/colorful.css';
130}
131
132
133// Title
134$title = 'TakePOS - Dolibarr '.DOL_VERSION;
135if (getDolGlobalString('MAIN_APPLICATION_TITLE')) {
136 $title = 'TakePOS - ' . getDolGlobalString('MAIN_APPLICATION_TITLE');
137}
138$head = '<meta name="apple-mobile-web-app-title" content="TakePOS"/>
139<meta name="apple-mobile-web-app-capable" content="yes">
140<meta name="mobile-web-app-capable" content="yes">
141<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>';
142
143top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss);
144
145
146$categories = $categorie->get_full_arbo('product', getDolGlobalInt('TAKEPOS_ROOT_CATEGORY_ID'), 1);
147
148
149// Search root category to know its level
150//$conf->global->TAKEPOS_ROOT_CATEGORY_ID=0;
151$levelofrootcategory = 0;
152if (getDolGlobalInt('TAKEPOS_ROOT_CATEGORY_ID') > 0) {
153 foreach ($categories as $key => $categorycursor) {
154 // @phan-suppress-next-line PhanTypeInvalidDimOffset
155 if ($categorycursor['id'] == getDolGlobalInt('TAKEPOS_ROOT_CATEGORY_ID')) {
156 $levelofrootcategory = $categorycursor['level'];
157 break;
158 }
159 }
160}
161
162$levelofmaincategories = $levelofrootcategory + 1; // Main categories are categories just under the root categorie of POS products.
163
164$maincategories = array();
165$subcategories = array();
166foreach ($categories as $key => $categorycursor) {
167 if ($categorycursor['level'] == $levelofmaincategories) {
168 $maincategories[$key] = $categorycursor;
169 } elseif ($categorycursor['level'] > $levelofmaincategories) {
170 $subcategories[$key] = $categorycursor; // If category level 2 or 3 or ...
171 }
172}
173
174$maincategories = dol_sort_array($maincategories, 'label');
175$subcategories = dol_sort_array($subcategories, 'label');
176?>
177<?php
178$keyCodeForEnter = '';
179if (!empty($_SESSION['takeposterminal'])) {
180 $keyCodeForEnter = getDolGlobalInt('CASHDESK_READER_KEYCODE_FOR_ENTER'.$_SESSION['takeposterminal']) > 0 ? getDolGlobalString('CASHDESK_READER_KEYCODE_FOR_ENTER'.$_SESSION['takeposterminal']) : '';
181}
182?>
183
184<body class="bodytakepos" style="overflow: hidden;">
185
186<script>
187var categories = <?php echo json_encode($maincategories); ?>;
188var subcategories = <?php echo json_encode($subcategories); ?>;
189
190var currentcat;
191var pageproducts=0;
192var pagecategories=0;
193var pageactions=0;
194var place="<?php echo $place; ?>";
195var editaction="qty";
196var editnumber="";
197var invoiceid=0;
198var search2_timer=null;
199
200/*
201var app = this;
202app.hasKeyboard = false;
203this.keyboardPress = function() {
204 app.hasKeyboard = true;
205 $(window).unbind("keyup", app.keyboardPress);
206 localStorage.hasKeyboard = true;
207 console.log("has keyboard!")
208}
209$(window).on("keyup", app.keyboardPress)
210if(localStorage.hasKeyboard) {
211 app.hasKeyboard = true;
212 $(window).unbind("keyup", app.keyboardPress);
213 console.log("has keyboard from localStorage")
214}
215*/
216
217function ClearSearch(clearSearchResults) {
218 console.log("ClearSearch");
219 $("#search").val('');
220 $("#qty").html("<?php echo $langs->trans("Qty"); ?>").removeClass('clicked');
221 $("#price").html("<?php echo $langs->trans("Price"); ?>").removeClass('clicked');
222 $("#reduction").html("<?php echo $langs->trans("LineDiscountShort"); ?>").removeClass('clicked');
223 <?php if ($conf->browser->layout == 'classic') { ?>
224 setFocusOnSearchField();
225 <?php } ?>
226 if (clearSearchResults) {
227 $("#search").trigger('keyup');
228 }
229}
230
231// Set the focus on search field but only on desktop. On tablet or smartphone, we don't to avoid to have the keyboard open automatically
232function setFocusOnSearchField() {
233 console.log("Call setFocusOnSearchField in page index.php");
234 <?php if ($conf->browser->layout == 'classic') { ?>
235 console.log("has keyboard from localStorage, so we can force focus on search field");
236 $("#search").focus();
237 <?php } ?>
238}
239
240function PrintCategories(first) {
241 console.log("PrintCategories");
242 for (i = 0; i < <?php echo($MAXCATEG - 2); ?>; i++) {
243 if (typeof (categories[parseInt(i)+parseInt(first)]) == "undefined")
244 {
245 $("#catdivdesc"+i).hide();
246 $("#catdesc"+i).text("");
247 $("#catimg"+i).attr("src","genimg/empty.png");
248 $("#catwatermark"+i).hide();
249 $("#catdiv"+i).attr('class', 'wrapper divempty');
250 continue;
251 }
252 $("#catdivdesc"+i).show();
253 <?php
254 if (getDolGlobalString('TAKEPOS_SHOW_CATEGORY_DESCRIPTION') == 1) { ?>
255 $("#catdesc"+i).html(categories[parseInt(i)+parseInt(first)]['label'].bold() + ' - ' + categories[parseInt(i)+parseInt(first)]['description']);
256 <?php } else { ?>
257 $("#catdesc"+i).text(categories[parseInt(i)+parseInt(first)]['label']);
258 <?php } ?>
259 $("#catimg"+i).attr("src","genimg/index.php?query=cat&id="+categories[parseInt(i)+parseInt(first)]['rowid']);
260 $("#catdiv"+i).data("rowid",categories[parseInt(i)+parseInt(first)]['rowid']);
261 $("#catdiv"+i).attr("data-rowid",categories[parseInt(i)+parseInt(first)]['rowid']);
262 $("#catdiv"+i).attr('class', 'wrapper');
263 $("#catwatermark"+i).show();
264 }
265}
266
267function MoreCategories(moreorless) {
268 console.log("MoreCategories moreorless="+moreorless+" pagecategories="+pagecategories);
269 if (moreorless == "more") {
270 $('#catimg15').animate({opacity: '0.5'}, 1);
271 $('#catimg15').animate({opacity: '1'}, 100);
272 pagecategories=pagecategories+1;
273 }
274 if (moreorless == "less") {
275 $('#catimg14').animate({opacity: '0.5'}, 1);
276 $('#catimg14').animate({opacity: '1'}, 100);
277 if (pagecategories==0) return; //Return if no less pages
278 pagecategories=pagecategories-1;
279 }
280 if (typeof (categories[<?php echo($MAXCATEG - 2); ?> * pagecategories] && moreorless == "more") == "undefined") { // Return if no more pages
281 pagecategories=pagecategories-1;
282 return;
283 }
284
285 for (i = 0; i < <?php echo($MAXCATEG - 2); ?>; i++) {
286 if (typeof (categories[i+(<?php echo($MAXCATEG - 2); ?> * pagecategories)]) == "undefined") {
287 // complete with empty record
288 console.log("complete with empty record");
289 $("#catdivdesc"+i).hide();
290 $("#catdesc"+i).text("");
291 $("#catimg"+i).attr("src","genimg/empty.png");
292 $("#catwatermark"+i).hide();
293 continue;
294 }
295 $("#catdivdesc"+i).show();
296 <?php
297 if (getDolGlobalString('TAKEPOS_SHOW_CATEGORY_DESCRIPTION') == 1) { ?>
298 $("#catdesc"+i).html(categories[i+(<?php echo($MAXCATEG - 2); ?> * pagecategories)]['label'].bold() + ' - ' + categories[i+(<?php echo($MAXCATEG - 2); ?> * pagecategories)]['description']);
299 <?php } else { ?>
300 $("#catdesc"+i).text(categories[i+(<?php echo($MAXCATEG - 2); ?> * pagecategories)]['label']);
301 <?php } ?>
302 $("#catimg"+i).attr("src","genimg/index.php?query=cat&id="+categories[i+(<?php echo($MAXCATEG - 2); ?> * pagecategories)]['rowid']);
303 $("#catdiv"+i).data("rowid",categories[i+(<?php echo($MAXCATEG - 2); ?> * pagecategories)]['rowid']);
304 $("#catdiv"+i).attr("data-rowid",categories[i+(<?php echo($MAXCATEG - 2); ?> * pagecategories)]['rowid']);
305 $("#catwatermark"+i).show();
306 }
307
308 ClearSearch(false);
309}
310
311// LoadProducts
312function LoadProducts(position, issubcat) {
313 console.log("LoadProducts position="+position+" issubcat="+issubcat);
314 var maxproduct = <?php echo (int) ($MAXPRODUCT - 2); ?>;
315
316 if (position == "supplements") {
317 currentcat = "supplements";
318
319 if (subcategories.count == 0) {
320 alert("No product found into categories level 2 or more");
321 }
322 } else {
323 $('#catimg'+position).animate({opacity: '0.5'}, 1);
324 $('#catimg'+position).animate({opacity: '1'}, 100);
325 if (issubcat == true) {
326 currentcat = $('#prodiv'+position).data('rowid');
327 } else {
328 console.log('#catdiv'+position);
329 currentcat = $('#catdiv'+position).data('rowid');
330 console.log("currentcat="+currentcat);
331 }
332 }
333 if (currentcat == undefined) {
334 return;
335 }
336 pageproducts=0;
337 ishow=0; //product to show counter
338
339 var parent_cat = 0;
340 var parent_cat_label = <?php echo "'".dol_escape_js($langs->trans('GoBack'))."'" ; ?>;
341 if (currentcat != "supplements") {
342 jQuery.each(subcategories, function(i, val) {
343 if (val.rowid == currentcat) {
344 parent_cat = val.fk_parent;
345 return false;
346 }
347 });
348
349 if (parent_cat > 0) {
350 var found = false;
351 jQuery.each(categories, function(i, val) {
352 if (val.rowid == parent_cat) {
353 parent_cat_label = val.label;
354 found = true;
355 return false;
356 }
357 });
358 if (!found) {
359 jQuery.each(subcategories, function(i, val) {
360 if (val.rowid == parent_cat) {
361 parent_cat_label = val.label;
362 return false;
363 }
364 });
365 }
366
367 $("#prodivdesc"+ishow).show();
368 var back_html = '<span class="fa fa-chevron-left paddingright"></span> ' + parent_cat_label;
369
370 <?php if (getDolGlobalString('TAKEPOS_SHOW_CATEGORY_DESCRIPTION') == 1) { ?>
371 $("#prodesc"+ishow).html('<strong>' + back_html + '</strong>');
372 <?php } else { ?>
373 $("#prodesc"+ishow).html(back_html);
374 <?php } ?>
375 $("#probutton"+ishow).html(back_html);
376
377 $("#probutton"+ishow).show();
378 $("#proprice"+ishow).attr("class", "hidden");
379 $("#proprice"+ishow).html("");
380 <?php if (!getDolGlobalString('TAKEPOS_HIDE_PRODUCT_IMAGES')) { ?>
381 $("#proimg"+ishow).attr("src", "img/back.png");
382 <?php } ?>
383 $("#prodiv"+ishow).data("rowid", parent_cat);
384 $("#prodiv"+ishow).attr("data-rowid", parent_cat);
385 $("#prodiv"+ishow).data("iscat", 1);
386 $("#prodiv"+ishow).attr("data-iscat", 1);
387 $("#prodiv"+ishow).removeClass("divempty");
388 $("#prowatermark"+ishow).hide();
389 ishow++;
390 }
391
392 console.log("Loop on each category level 2 or more");
393 jQuery.each(subcategories, function(i, val) {
394 if (currentcat == val.fk_parent) {
395 $("#prodivdesc"+ishow).show();
396 <?php if (getDolGlobalString('TAKEPOS_SHOW_CATEGORY_DESCRIPTION') == 1) { ?>
397 $("#prodesc"+ishow).html(val.label.bold() + ' - ' + val.description);
398 $("#probutton"+ishow).html(val.label);
399 <?php } else { ?>
400 $("#prodesc"+ishow).text(val.label);
401 $("#probutton"+ishow).text(val.label);
402 <?php } ?>
403 $("#probutton"+ishow).show();
404 $("#proprice"+ishow).attr("class", "hidden");
405 $("#proprice"+ishow).html("");
406 $("#proimg"+ishow).attr("src","genimg/index.php?query=cat&id="+val.rowid);
407 $("#prodiv"+ishow).data("rowid",val.rowid);
408 $("#prodiv"+ishow).attr("data-rowid",val.rowid);
409 $("#prodiv"+ishow).data("iscat", 1);
410 $("#prodiv"+ishow).attr("data-iscat", 1);
411 $("#prodiv"+ishow).removeClass("divempty");
412 $("#prowatermark"+ishow).show();
413 ishow++;
414 }
415 });
416 }
417
418 idata=0; //product data counter
419 var limit = 0;
420 if (maxproduct >= 1) {
421 limit = maxproduct - 1;
422 }
423
424 // Get socid
425 let socid = jQuery('#thirdpartyid').val();
426 if ((socid === undefined || socid === "") && parseInt(<?php echo "'".dol_escape_js($socid)."'"; ?>) > 0) {
427 socid = parseInt(<?php echo "'".dol_escape_js($socid)."'" ; ?>);
428 }
429
430 // Only show products for sale (tosell=1)
431 $.getJSON('<?php echo DOL_URL_ROOT ?>/takepos/ajax/ajax.php?action=getProducts&token=<?php echo currentToken();?>&thirdpartyid=' + socid + '&category='+currentcat+'&tosell=1&limit='+limit+'&offset=0', function(data) {
432 /* Fill thumbs from ishow to end max of products with products loaded into data array */
433 console.log("Call ajax.php (in LoadProducts) to get Products of category "+currentcat+" then loop on result to fill image thumbs");
434 console.log("Found "+data.length+" record");
435
436 if (data.length == 0 && currentcat == "supplements") {
437 alert("No supplements found into the supplement category. Check the module setup and your product categories.");
438 }
439
440 while (ishow < maxproduct) {
441 console.log("ishow"+ishow+" idata="+idata);
442 console.log(data[idata]);
443
444 if (typeof (data[idata]) == "undefined") {
445 <?php if (!getDolGlobalString('TAKEPOS_HIDE_PRODUCT_IMAGES')) {
446 echo '$("#prodivdesc"+ishow).hide();';
447 echo '$("#prodesc"+ishow).text("");';
448 echo '$("#proimg"+ishow).attr("title","");';
449 echo '$("#proimg"+ishow).attr("src","genimg/empty.png");';
450 } else {
451 echo '$("#probutton"+ishow).hide();';
452 echo '$("#probutton"+ishow).text("");';
453 }?>
454 $("#proprice"+ishow).attr("class", "hidden");
455 $("#proprice"+ishow).html("");
456
457 $("#prodiv"+ishow).data("rowid","");
458 $("#prodiv"+ishow).attr("data-rowid","");
459
460 $("#prodiv"+ishow).data("iscat","0");
461 $("#prodiv"+ishow).attr("data-iscat","0");
462
463 $("#prodiv"+ishow).attr("class","wrapper2 divempty");
464 } else {
465 <?php
466 $titlestring = "'".dol_escape_js($langs->transnoentities('Ref').': ')."' + data[idata]['ref']";
467 $titlestring .= " + ' - ".dol_escape_js($langs->trans("Barcode").': ')."' + data[idata]['barcode']";
468 ?>
469 var titlestring = <?php echo $titlestring; ?>;
470 <?php if (!getDolGlobalString('TAKEPOS_HIDE_PRODUCT_IMAGES')) {
471 echo '$("#prodivdesc"+ishow).show();';
472 if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) {
473 echo '$("#prodesc"+ishow).html(data[parseInt(idata)][\'ref\'].bold() + \' - \' + data[parseInt(idata)][\'label\']);';
474 } elseif (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 2) {
475 echo '$("#prodesc"+ishow).html(data[parseInt(idata)][\'ref\'].bold());';
476 } else {
477 echo '$("#prodesc"+ishow).html(data[parseInt(idata)][\'label\']);';
478 }
479 echo '$("#proimg"+ishow).attr("title", titlestring);';
480 echo '$("#proimg"+ishow).attr("src", "genimg/index.php?query=pro&id="+data[idata][\'id\']);';
481 } else {
482 echo '$("#probutton"+ishow).show();';
483 echo '$("#probutton"+ishow).html(data[parseInt(idata)][\'label\']);';
484 }
485 ?>
486 if (data[parseInt(idata)]['price_formated']) {
487 $("#proprice" + ishow).attr("class", "productprice");
488 <?php
489 if (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT')) {
490 ?>
491 $("#proprice" + ishow).html(data[parseInt(idata)]['price_formated']);
492 <?php
493 } else {
494 ?>
495 $("#proprice" + ishow).html(data[parseInt(idata)]['price_ttc_formated']);
496 <?php
497 }
498 ?>
499 }
500 console.log("#prodiv"+ishow+".data(rowid)="+data[idata]['id']);
501
502 $("#prodiv"+ishow).data("rowid", data[idata]['id']);
503 $("#prodiv"+ishow).attr("data-rowid", data[idata]['id']);
504 console.log($('#prodiv4').data('rowid'));
505
506 $("#prodiv"+ishow).data("iscat", 0);
507 $("#prodiv"+ishow).attr("data-iscat", 0);
508
509 $("#prodiv"+ishow).attr("class","wrapper2");
510
511 <?php
512 // Add js from hooks
513 $parameters = array();
514 $parameters['caller'] = 'loadProducts';
515 $hookmanager->executeHooks('completeJSProductDisplay', $parameters);
516 print $hookmanager->resPrint;
517 ?>
518 }
519 $("#prowatermark"+ishow).hide();
520 ishow++; //Next product to show after print data product
521 idata++; //Next data every time
522 }
523 });
524
525 ClearSearch(false);
526}
527
528function MoreProducts(moreorless) {
529 console.log("MoreProducts");
530
531 if ($('#search_pagination').val() != '') {
532 return Search2('<?php echo(isset($keyCodeForEnter) ? $keyCodeForEnter : ''); ?>', moreorless);
533 }
534
535 var maxproduct = <?php echo($MAXPRODUCT - 2); ?>;
536
537 if (moreorless=="more"){
538 $('#proimg31').animate({opacity: '0.5'}, 1);
539 $('#proimg31').animate({opacity: '1'}, 100);
540 pageproducts=pageproducts+1;
541 }
542 if (moreorless=="less"){
543 $('#proimg30').animate({opacity: '0.5'}, 1);
544 $('#proimg30').animate({opacity: '1'}, 100);
545 if (pageproducts==0) return; //Return if no less pages
546 pageproducts=pageproducts-1;
547 }
548
549 ishow=0; //product to show counter
550 idata=0; //product data counter
551 var limit = 0;
552 if (maxproduct >= 1) {
553 limit = maxproduct-1;
554 }
555
556 var nb_cat_shown = $('.div5 div.wrapper2[data-iscat=1]').length;
557 var offset = <?php echo($MAXPRODUCT - 2); ?> * pageproducts - nb_cat_shown;
558
559 // Get socid
560 let socid = jQuery('#thirdpartyid').val();
561 if ((socid === undefined || socid === "") && parseInt(<?php echo "'".dol_escape_js($socid)."'"; ?>) > 0) {
562 socid = parseInt(<?php echo "'".dol_escape_js($socid)."'" ; ?>);
563 }
564
565 // Only show products for sale (tosell=1)
566 $.getJSON('<?php echo DOL_URL_ROOT ?>/takepos/ajax/ajax.php?action=getProducts&token=<?php echo currentToken();?>&thirdpartyid=' + socid + '&category='+currentcat+'&tosell=1&limit='+limit+'&offset='+offset, function(data) {
567 console.log("Call ajax.php (in MoreProducts) to get Products of category "+currentcat);
568
569 if (typeof (data[0]) == "undefined" && moreorless=="more"){ // Return if no more pages
570 pageproducts=pageproducts-1;
571 return;
572 }
573
574 while (ishow < maxproduct) {
575 if (typeof (data[idata]) == "undefined") {
576 $("#prodivdesc"+ishow).hide();
577 $("#prodesc"+ishow).text("");
578 $("#probutton"+ishow).text("");
579 $("#probutton"+ishow).hide();
580 $("#proprice"+ishow).attr("class", "");
581 $("#proprice"+ishow).html("");
582 $("#proimg"+ishow).attr("src","genimg/empty.png");
583 $("#prodiv"+ishow).data("rowid","");
584 $("#prodiv"+ishow).attr("data-rowid","");
585 $("#prodiv"+ishow).addClass("divempty");
586 } else {
587 $("#prodivdesc"+ishow).show();
588 $("#prodiv"+ishow).removeClass("divempty");
589 <?php if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) { ?>
590 $("#prodesc"+ishow).html(data[parseInt(idata)]['ref'].bold() + ' - ' + data[parseInt(idata)]['label']);
591 <?php } elseif (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 2) { ?>
592 $("#prodesc"+ishow).html(data[parseInt(idata)]['ref'].bold());
593 <?php } else { ?>
594 $("#prodesc"+ishow).html(data[parseInt(idata)]['label']);
595 <?php } ?>
596 $("#probutton"+ishow).html(data[parseInt(idata)]['label']);
597 $("#probutton"+ishow).show();
598 if (data[parseInt(idata)]['price_formated']) {
599 $("#proprice" + ishow).attr("class", "productprice");
600 <?php
601 if (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT')) {
602 ?>
603 $("#proprice" + ishow).html(data[parseInt(idata)]['price_formated']);
604 <?php
605 } else {
606 ?>
607 $("#proprice" + ishow).html(data[parseInt(idata)]['price_ttc_formated']);
608 <?php
609 }
610 ?>
611 }
612 $("#proimg"+ishow).attr("src","genimg/index.php?query=pro&id="+data[idata]['id']);
613 $("#prodiv"+ishow).data("rowid",data[idata]['id']);
614 $("#prodiv"+ishow).attr("data-rowid",data[idata]['id']);
615 $("#prodiv"+ishow).data("iscat",0);
616 }
617 $("#prowatermark"+ishow).hide();
618 ishow++; //Next product to show after print data product
619 idata++; //Next data every time
620 }
621 });
622
623 ClearSearch(false);
624}
625
626function ClickProduct(position, qty = 1, qty_std = 0) {
627 console.log("ClickProduct at position"+position);
628 if ($('#invoiceid').val() == "") {
629 invoiceid = $('#invoiceid').val();
630 Refresh();
631 }
632 $('#proimg'+position).animate({opacity: '0.5'}, 1);
633 $('#proimg'+position).animate({opacity: '1'}, 100);
634 if ($('#prodiv'+position).data('iscat') == 1){
635 console.log("Click on a category at position "+position);
636 LoadProducts(position, true);
637 }
638 else{
639 invoiceid = $("#invoiceid").val();
640 idproduct=$('#prodiv'+position).data('rowid');
641 console.log("Click on product at position "+position+" for idproduct "+idproduct+", qty="+qty+" invoiceid="+invoiceid);
642 if (idproduct == "") {
643 return;
644 }
645
646 addInvoiceLine = function(qty, qty_std_inner = 0) {
647 // Call page invoice.php to generate the section with product lines
648 $("#poslines").load("invoice.php?action=addline&token=<?php echo currentToken(); ?>&place="+place+"&idproduct="+idproduct+"&selectedline="+selectedline+"&qty="+qty+"&invoiceid="+invoiceid+(qty_std_inner ? '&qty_std=1' : ''), function() {
649 idproduct = "";
650 <?php if (getDolGlobalString('TAKEPOS_CUSTOMER_DISPLAY')) {
651 echo "CustomerDisplay();";
652 }?>
653 });
654 };
655
656 // call WeighingScale() if product is a product that need to measure weight
657 <?php if (getDolGlobalString('TAKEPOS_WEIGHING_SCALE')) { ?>
658 if ($('#prodiv'+position).data('unit') == 2) {
659 WeighingScale(addInvoiceLine);
660 } else {
661 addInvoiceLine(qty, qty_std);
662 }
663 <?php } else { ?>
664 addInvoiceLine(qty, qty_std);
665 <?php } ?>
666 }
667
668 ClearSearch(false);
669}
670
671function ChangeThirdparty(idcustomer) {
672 console.log("ChangeThirdparty");
673 // Call page list.php to change customer
674 $("#poslines").load("<?php echo DOL_URL_ROOT ?>/societe/list.php?action=change&token=<?php echo currentToken();?>&type=t&contextpage=poslist&idcustomer="+idcustomer+"&place="+place+"", function() {
675 });
676
677 ClearSearch(false);
678}
679
680function deleteline() {
681 if (selectedline == 0) return;
682 invoiceid = $("#invoiceid").val();
683 console.log("Delete line invoiceid="+invoiceid);
684 $("#poslines").load("invoice.php?action=deleteline&token=<?php echo currentToken(); ?>&place="+place+"&idline="+selectedline+"&invoiceid="+invoiceid, function() {
685 //$('#poslines').scrollTop($('#poslines')[0].scrollHeight);
686 });
687 ClearSearch(false);
688}
689
690function editbatch(lineid, idproduct, clonebatch) {
691 $("#poslines").load("invoice.php?action=editbatch_popup&token=<?php echo newToken(); ?>&place="+place+"&idline="+lineid+"&idproduct="+idproduct+"&invoiceid="+invoiceid+(clonebatch ? '&clonebatch=1' : ''), function() {});
692}
693
694function updatebatch(batch, warehouseid, lineid, clonebatch) {
695 $("#poslines").load("invoice.php?action=setbatch&token=<?php echo newToken(); ?>&place="+place+"&idline="+lineid+"&batch="+encodeURIComponent(batch)+"&warehouseid="+warehouseid+"&invoiceid="+invoiceid+(clonebatch ? '&clonebatch=1' : ''), function() {});
696}
697
698function Customer() {
699 console.log("Open box to select the thirdparty place="+place);
700 $.colorbox({href:"../societe/list.php?type=t&contextpage=poslist&nomassaction=1&place="+place, width:"90%", height:"80%", transition:"none", iframe:"true", title:"<?php echo $langs->trans("Customer"); ?>"});
701}
702
703function Contact() {
704 console.log("Open box to select the contact place="+place);
705 $.colorbox({href:"../contact/list.php?type=c&contextpage=poslist&nomassaction=1&place="+place, width:"90%", height:"80%", transition:"none", iframe:"true", title:"<?php echo $langs->trans("Contact"); ?>"});
706}
707
708function History()
709{
710 console.log("Open box to select the history");
711 $.colorbox({href:"../compta/facture/list.php?contextpage=poslist&search_module_source=takepos", width:"90%", height:"80%", transition:"none", iframe:"true", title:"<?php echo $langs->trans("History"); ?>"});
712}
713
714function CloneTicket(sourceinvoiceid) {
715 if (!sourceinvoiceid) {
716 sourceinvoiceid = invoiceid;
717 }
718 if (!sourceinvoiceid) {
719 return false;
720 }
721 $.getJSON("<?php print DOL_URL_ROOT; ?>/takepos/invoice.php?action=cloneticket&format=json&token=<?php echo currentToken(); ?>&sourceinvoiceid="+sourceinvoiceid)
722 .done(function(data) {
723 if (!data.success) {
724 alert(data.message || <?php echo "'".dol_escape_js($langs->trans('ErrorFailedToCloneTicket'))."'"; ?>);
725 return;
726 }
727
728 place = data.place;
729 invoiceid = data.invoiceid;
730 if (data.batchlineid > 0) {
731 editbatch(data.batchlineid, data.batchproductid, 1);
732 } else {
733 $("#poslines").load("invoice.php?place="+place+"&invoiceid="+invoiceid, function() {});
734 }
735 })
736 .fail(function() {
737 alert(<?php echo "'".dol_escape_js($langs->trans('ErrorFailedToCloneTicket'))."'"; ?>);
738 });
739 return true;
740}
741
742function Reduction() {
743 invoiceid = $("#invoiceid").val();
744 console.log("Open popup to enter reduction on invoiceid="+invoiceid);
745 $.colorbox({href:"reduction.php?place="+place+"&invoiceid="+invoiceid, width:"80%", height:"90%", transition:"none", iframe:"true", title:""});
746}
747
748var closeBillParams="";
749function CloseBill() {
750 <?php
751 $parameters = array();
752 $reshook = $hookmanager->executeHooks('paramsForCloseBill', $parameters, $obj, $action);
753 if (getDolGlobalString('TAKEPOS_FORBID_SALES_TO_DEFAULT_CUSTOMER')) {
754 echo "customerAnchorTag = document.querySelector('a[id=\"customer\"]'); ";
755 echo "if (customerAnchorTag && customerAnchorTag.innerText.trim() === '".$langs->trans("Customer")."') { ";
756 echo "alert('".dol_escape_js($langs->trans("NoClientErrorMessage"))."'); ";
757 echo "return; } \n";
758 }
759 ?>
760 invoiceid = $("#invoiceid").val();
761 console.log("Open popup to enter payment on invoiceid="+invoiceid);
762 <?php if (getDolGlobalInt("TAKEPOS_NO_GENERIC_THIRDPARTY")) { ?>
763 if ($("#idcustomer").val() == "") {
764 alert("<?php echo $langs->trans('TakePosCustomerMandatory'); ?>");
765 <?php if (getDolGlobalString('TAKEPOS_CHOOSE_CONTACT')) { ?>
766 Contact();
767 <?php } else { ?>
768 Customer();
769 <?php } ?>
770 return;
771 }
772 <?php } ?>
773 <?php
774 $alternative_payurl = getDolGlobalString('TAKEPOS_ALTERNATIVE_PAYMENT_SCREEN');
775 if (empty($alternative_payurl)) {
776 $payurl = "pay.php";
777 } else {
778 $payurl = dol_buildpath($alternative_payurl, 1);
779 }
780 ?>
781 $.colorbox({href:"<?php echo $payurl; ?>?place="+place+"&invoiceid="+invoiceid+closeBillParams, width:"80%", height:"90%", transition:"none", iframe:"true", title:""});
782}
783
784function Split() {
785 invoiceid = $("#invoiceid").val();
786 console.log("Open popup to split on invoiceid="+invoiceid);
787 $.colorbox({href:"split.php?place="+place+"&invoiceid="+invoiceid, width:"80%", height:"90%", transition:"none", iframe:"true", title:""});
788}
789
790function Floors() {
791 console.log("Open box to select floor place="+place);
792 $.colorbox({href:"floors.php?place="+place, width:"90%", height:"90%", transition:"none", iframe:"true", title:"<?php echo $langs->trans("Floors"); ?>"});
793}
794
795function FreeZone() {
796 invoiceid = $("#invoiceid").val();
797 console.log("Open box to enter a free product on invoiceid="+invoiceid);
798 $.colorbox({href:"freezone.php?action=freezone&token=<?php echo newToken(); ?>&place="+place+"&invoiceid="+invoiceid, width:"80%", height:"40%", transition:"none", iframe:"true", title:"<?php echo $langs->trans("FreeZone"); ?>"});
799}
800
801function TakeposOrderNotes() {
802 console.log("Open box to order notes");
803 ModalBox('ModalNote');
804 $("#textinput").focus();
805}
806
807function Refresh() {
808 console.log("Refresh by reloading place="+place+" invoiceid="+invoiceid);
809 $("#poslines").load("invoice.php?place="+place+"&invoiceid="+invoiceid, function() {
810 //$('#poslines').scrollTop($('#poslines')[0].scrollHeight);
811 });
812}
813
814function New() {
815 // If we go here,it means $conf->global->TAKEPOS_BAR_RESTAURANT is not defined
816 invoiceid = $("#invoiceid").val(); // This is a hidden field added by invoice.php
817
818 console.log("New with place = <?php echo $place; ?>, js place="+place+", invoiceid="+invoiceid);
819
820 if (invoiceid == '') {
821 $("#poslines").load("invoice.php?action=delete&token=<?php echo currentToken(); ?>&place=" + place, function () {
822 //$('#poslines').scrollTop($('#poslines')[0].scrollHeight);
823 });
824
825 ClearSearch(false);
826 $("#idcustomer").val("");
827 return;
828 }
829
830 $.getJSON('<?php echo DOL_URL_ROOT ?>/takepos/ajax/ajax.php?action=getInvoice&token=<?php echo currentToken();?>&id='+invoiceid, function(data) {
831 var r;
832
833 if (parseInt(data['paye']) === 1) {
834 r = true;
835 } else {
836 r = confirm('<?php echo($place > 0 ? $langs->transnoentitiesnoconv("ConfirmDeletionOfThisPOSSale") : $langs->transnoentitiesnoconv("ConfirmDiscardOfThisPOSSale")); ?>');
837 }
838
839 if (r == true) {
840 // Reload section with invoice lines
841 $("#poslines").load("invoice.php?action=delete&token=<?php echo currentToken(); ?>&place=" + place, function () {
842 //$('#poslines').scrollTop($('#poslines')[0].scrollHeight);
843 });
844
845 ClearSearch(false);
846 $("#idcustomer").val("");
847 }
848 });
849}
855function DeleteSale() {
856 if (typeof place === 'undefined') {
857 return;
858 }
859 if (confirm(<?php echo "'".dol_escape_js($langs->transnoentitiesnoconv("ConfirmDeletionOfThisPOSSale"))."'" ; ?>)) {
860 // Fully remove the draft (its tab disappears), then switch to the main cart.
861 $("#poslines").load("invoice.php?action=discardsale&token=<?php echo newToken(); ?>&place=" + place, function () {
862 place = '0';
863 invoiceid = 0;
864 ClearSearch(false);
865 $("#idcustomer").val("");
866 Refresh();
867 });
868 }
869}
870
878function Search2(keyCodeForEnter, moreorless) {
879 var eventKeyCode = null;
880
881 if (window.event && window.event.keyCode) {
882 eventKeyCode = window.event.keyCode;
883 }
884 if (eventKeyCode === null && keyCodeForEnter !== '') {
885 // No key code available, exit early if a key code is required
886 return;
887 }
888
889 console.log("Search2 Call ajax search to replace products keyCodeForEnter="+keyCodeForEnter+", eventKeyCode="+eventKeyCode);
890
891 var search_term = $('#search').val();
892 var search_start = 0;
893 var search_limit = <?php echo $MAXPRODUCT - 2; ?>;
894 if (moreorless != null) {
895 search_term = $('#search_pagination').val();
896 search_start = $('#search_start_'+moreorless).val();
897 }
898
899 console.log("search_term="+search_term);
900
901 if (search_term == '') {
902 $("[id^=prowatermark]").html("");
903 $("[id^=prodesc]").text("");
904 $("[id^=probutton]").text("");
905 $("[id^=probutton]").hide();
906 $("[id^=proprice]").attr("class", "hidden");
907 $("[id^=proprice]").html("");
908 $("[id^=proimg]").attr("src", "genimg/empty.png");
909 $("[id^=prodiv]").data("rowid", "");
910 $("[id^=prodiv]").attr("data-rowid", "");
911 $("[id^=prodiv]").addClass("divempty");
912 return;
913 }
914
915 var search = false;
916 if (keyCodeForEnter == '' || eventKeyCode == keyCodeForEnter) {
917 search = true;
918 }
919
920 if (search === true) {
921 // if a timer has been already started (search2_timer is a global js variable), we cancel it now
922 // we click onto another key, we will restart another timer just after
923 if (search2_timer) {
924 clearTimeout(search2_timer);
925 }
926
927 // temporization time to give time to type
928 search2_timer = setTimeout(function(){
929 pageproducts = 0;
930 jQuery(".wrapper2 .catwatermark").hide();
931 var nbsearchresults = 0;
932
933 // Only show products for sale (tosell=1)
934 let socid = jQuery('#thirdpartyid').val();
935 if ((socid === undefined || socid === "") && parseInt(<?php echo "'".dol_escape_js($socid)."'"; ?>) > 0) {
936 socid = parseInt(<?php echo "'".dol_escape_js($socid)."'" ; ?>);
937 }
938
939 $.getJSON('<?php echo DOL_URL_ROOT ?>/takepos/ajax/ajax.php?action=search&token=<?php echo currentToken();?>&search_term=' + search_term + '&thirdpartyid=' + socid + '&search_start=' + search_start + '&search_limit=' + search_limit, function (data) {
940 for (i = 0; i < <?php echo ($MAXPRODUCT - 2); ?>; i++) { // the last 2 slots are the pager arrows, not product slots
941 if (typeof (data[i]) == "undefined") {
942 $("#prowatermark" + i).html("");
943 $("#prodesc" + i).text("");
944 $("#probutton" + i).text("");
945 $("#probutton" + i).hide();
946 $("#proprice" + i).attr("class", "hidden");
947 $("#proprice" + i).html("");
948 $("#proimg" + i).attr("src", "genimg/empty.png");
949 $("#prodiv" + i).data("rowid", "");
950 $("#prodiv" + i).attr("data-rowid", "");
951 continue;
952 }
953 <?php
954 $titlestring = "'".dol_escape_js($langs->transnoentities('Ref').': ')."' + data[i]['ref']";
955 $titlestring .= " + ' - ".dol_escape_js($langs->trans("Barcode").': ')."' + data[i]['barcode']";
956 ?>
957 var titlestring = <?php echo $titlestring; ?>;
958 <?php if (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 1) { ?>
959 $("#prodesc" + i).html(data[i]['ref'].bold() + ' - ' + data[i]['label']);
960 <?php } elseif (getDolGlobalInt('TAKEPOS_SHOW_PRODUCT_REFERENCE') == 2) { ?>
961 $("#prodesc" + i).html(data[i]['ref'].bold());
962 <?php } else { ?>
963 $("#prodesc" + i).html(data[i]['label']);
964 <?php } ?>
965 $("#prodivdesc" + i).show();
966 $("#prodiv" + i).removeClass("divempty");
967 $("#probutton" + i).html(data[i]['label']);
968 $("#probutton" + i).show();
969 if (data[i]['price_formated']) {
970 $("#proprice" + i).attr("class", "productprice");
971 <?php
972 if (getDolGlobalInt('TAKEPOS_CHANGE_PRICE_HT')) {
973 ?>
974 $("#proprice" + i).html(data[i]['price_formated']);
975 <?php
976 } else {
977 ?>
978 $("#proprice" + i).html(data[i]['price_ttc_formated']);
979 <?php
980 }
981 ?>
982 }
983 $("#proimg" + i).attr("title", titlestring);
984 if( undefined !== data[i]['img']) {
985 $("#proimg" + i).attr("src", data[i]['img']);
986 }
987 else {
988 $("#proimg" + i).attr("src", "genimg/index.php?query=pro&id=" + data[i]['rowid']);
989 }
990 $("#prodiv" + i).data("rowid", data[i]['rowid']);
991 $("#prodiv" + i).attr("data-rowid", data[i]['rowid']);
992 $("#prodiv" + i).data("iscat", 0);
993 $("#prodiv" + i).attr("data-iscat", 0);
994
995 <?php
996 // Add js from hooks
997 $parameters = array();
998 $parameters['caller'] = 'search2';
999 $hookmanager->executeHooks('completeJSProductDisplay', $parameters);
1000 print $hookmanager->resPrint;
1001 ?>
1002
1003 nbsearchresults++;
1004 }
1005 }).always(function (data) {
1006 // If there is only 1 answer
1007 if ($('#search').val().length > 0 && data.length == 1) {
1008 console.log($('#search').val()+' - '+data[0]['barcode']);
1009 if ($('#search').val() == data[0]['barcode'] && 'thirdparty' == data[0]['object']) {
1010 console.log("There is only 1 answer with barcode matching the search, so we change the thirdparty "+data[0]['rowid']);
1011 ChangeThirdparty(data[0]['rowid']);
1012 }
1013 else if ('product' == data[0]['object'] && $('#search').val() == data[0]['barcode']) {
1014 console.log("There is only 1 answer and we found search on a barcode, so we add the product in basket, qty="+data[0]['qty']);
1015 ClickProduct(0, data[0]['qty'], 1);
1016 }
1017 }
1018 if (eventKeyCode == keyCodeForEnter){
1019 if (data.length == 0) {
1020 $('#search').val(<?php
1021 $langs->load('errors');
1022 echo "'".dol_escape_js($langs->transnoentitiesnoconv("ErrorRecordNotFoundShort"))." ('";
1023 ?>+search_term+')');
1024 $('#search').select();
1025 }
1026 else ClearSearch(false);
1027 }
1028 // memorize search_term and start for pagination
1029 $("#search_pagination").val($("#search").val());
1030 if (search_start == 0) {
1031 $("#prodiv<?php echo $MAXPRODUCT - 2; ?> span").hide();
1032 }
1033 else {
1034 $("#prodiv<?php echo $MAXPRODUCT - 2; ?> span").show();
1035 var search_start_less = Math.max(0, parseInt(search_start) - parseInt(<?php echo $MAXPRODUCT - 2;?>));
1036 $("#search_start_less").val(search_start_less);
1037 }
1038 if (nbsearchresults != <?php echo $MAXPRODUCT - 2; ?>) {
1039 $("#prodiv<?php echo $MAXPRODUCT - 1; ?> span").hide();
1040 }
1041 else {
1042 $("#prodiv<?php echo $MAXPRODUCT - 1; ?> span").show();
1043 var search_start_more = parseInt(search_start) + parseInt(<?php echo $MAXPRODUCT - 2;?>);
1044 $("#search_start_more").val(search_start_more);
1045 }
1046 });
1047 }, 500); // 500ms delay
1048 }
1049
1050}
1051
1052/* Function called on an action into the PAD */
1053function Edit(number) {
1054 console.log("We click on PAD on key="+number);
1055
1056 invoiceid = $("#invoiceid").val();
1057
1058 if (typeof(selectedtext) == "undefined") {
1059 return; // We click on an action on the number pad but there is no line selected
1060 }
1061
1062 var text=selectedtext+"<br> ";
1063
1064
1065 if (number=='c') {
1066 editnumber='';
1067 Refresh();
1068 $("#qty").html("<?php echo $langs->trans("Qty"); ?>").removeClass('clicked');
1069 $("#price").html("<?php echo $langs->trans("Price"); ?>").removeClass('clicked');
1070 $("#reduction").html("<?php echo $langs->trans("LineDiscountShort"); ?>").removeClass('clicked');
1071 return;
1072 } else if (number=='qty') {
1073 if (editaction=='qty' && editnumber != '') {
1074 $("#poslines").load("invoice.php?action=updateqty&token=<?php echo currentToken(); ?>&place="+place+"&idline="+selectedline+"&number="+editnumber+"&invoiceid="+invoiceid, function() {
1075 editnumber="";
1076 //$('#poslines').scrollTop($('#poslines')[0].scrollHeight);
1077 $("#qty").html("<?php echo $langs->trans("Qty"); ?>").removeClass('clicked');
1078 });
1079
1080 setFocusOnSearchField();
1081 return;
1082 }
1083 else {
1084 editaction="qty";
1085 }
1086 } else if (number=='p') {
1087 if (editaction=='p' && editnumber!="") {
1088 $("#poslines").load("invoice.php?action=updateprice&token=<?php echo currentToken(); ?>&place="+place+"&idline="+selectedline+"&number="+editnumber+"&invoiceid="+invoiceid, function() {
1089 editnumber="";
1090 //$('#poslines').scrollTop($('#poslines')[0].scrollHeight);
1091 $("#price").html("<?php echo $langs->trans("Price"); ?>").removeClass('clicked');
1092 });
1093
1094 ClearSearch(false);
1095 return;
1096 }
1097 else {
1098 editaction="p";
1099 }
1100 } else if (number=='r') {
1101 if (editaction=='r' && editnumber!="") {
1102 $("#poslines").load("invoice.php?action=updatereduction&token=<?php echo currentToken(); ?>&place="+place+"&idline="+selectedline+"&number="+editnumber+"&invoiceid="+invoiceid, function() {
1103 editnumber="";
1104 //$('#poslines').scrollTop($('#poslines')[0].scrollHeight);
1105 $("#reduction").html("<?php echo $langs->trans("LineDiscountShort"); ?>").removeClass('clicked');
1106 });
1107
1108 ClearSearch(false);
1109 return;
1110 }
1111 else {
1112 editaction="r";
1113 }
1114 }
1115 else {
1116 editnumber=editnumber+number;
1117 }
1118 if (editaction=='qty'){
1119 text=text+"<?php echo $langs->trans("Modify")." -> ".$langs->trans("Qty").": "; ?>";
1120 $("#qty").html("OK").addClass("clicked");
1121 $("#price").html("<?php echo $langs->trans("Price"); ?>").removeClass('clicked');
1122 $("#reduction").html("<?php echo $langs->trans("LineDiscountShort"); ?>").removeClass('clicked');
1123 }
1124 if (editaction=='p'){
1125 text=text+"<?php echo $langs->trans("Modify")." -> ".$langs->trans("Price").": "; ?>";
1126 $("#qty").html("<?php echo $langs->trans("Qty"); ?>").removeClass('clicked');
1127 $("#price").html("OK").addClass("clicked");
1128 $("#reduction").html("<?php echo $langs->trans("LineDiscountShort"); ?>").removeClass('clicked');
1129 }
1130 if (editaction=='r'){
1131 text=text+"<?php echo $langs->trans("Modify")." -> ".$langs->trans("LineDiscountShort").": "; ?>";
1132 $("#qty").html("<?php echo $langs->trans("Qty"); ?>").removeClass('clicked');
1133 $("#price").html("<?php echo $langs->trans("Price"); ?>").removeClass('clicked');
1134 $("#reduction").html("OK").addClass("clicked");
1135 }
1136 $('#'+selectedline).find("td:first").html(text+editnumber);
1137}
1138
1139
1140function TakeposPrintingOrder(){
1141 console.log("TakeposPrintingOrder output invoice to print order");
1142 $("#poslines").load("invoice.php?action=order&token=<?php echo currentToken();?>&place="+place, function() {
1143 //$('#poslines').scrollTop($('#poslines')[0].scrollHeight);
1144 });
1145}
1146
1147function OpenDrawer(){
1148 console.log("OpenDrawer call ajax url http://<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>:8111/print");
1149 $.ajax({
1150 type: "POST",
1151 data: { token: 'notrequired' },
1152 <?php
1153 if (getDolGlobalString('TAKEPOS_PRINT_SERVER') && filter_var($conf->global->TAKEPOS_PRINT_SERVER, FILTER_VALIDATE_URL) == true) {
1154 echo "url: '".getDolGlobalString('TAKEPOS_PRINT_SERVER', 'localhost')."/printer/drawer.php',";
1155 } else {
1156 echo "url: 'http://".getDolGlobalString('TAKEPOS_PRINT_SERVER', 'localhost').":8111/print',";
1157 }
1158 ?>
1159 data: "opendrawer"
1160 });
1161}
1162
1163/* Click on button to open drawer */
1164function DolibarrOpenDrawer() {
1165 console.log("DolibarrOpenDrawer call ajax url /takepos/ajax/ajax.php?action=opendrawer&token=<?php echo currentToken();?>&term=<?php print urlencode(empty($_SESSION["takeposterminal"]) ? '' : $_SESSION["takeposterminal"]); ?>");
1166 $.ajax({
1167 type: "GET",
1168 data: { token: '<?php echo currentToken(); ?>' },
1169 url: "<?php print DOL_URL_ROOT.'/takepos/ajax/ajax.php?action=opendrawer&token='.currentToken().'&term='.urlencode(empty($_SESSION["takeposterminal"]) ? '' : $_SESSION["takeposterminal"]); ?>",
1170 });
1171}
1172
1173function MoreActions(totalactions) {
1174 for (i = 0; i <= totalactions; i++) {
1175 $("#action" + i).toggle();
1176 }
1177 $("#actionnext").toggle();
1178 $("#actionprevious").toggle();
1179}
1180
1181function ControlCashOpening()
1182{
1183 $.colorbox({href:"../compta/cashcontrol/cashcontrol_card.php?action=create&contextpage=takepos", width:"90%", height:"60%", transition:"none", iframe:"true", title:"<?php echo $langs->trans("NewCashFence"); ?>"});
1184}
1185
1186function CloseCashFence(rowid)
1187{
1188 $.colorbox({href:"../compta/cashcontrol/cashcontrol_card.php?id="+rowid+"&contextpage=takepos", width:"90%", height:"90%", transition:"none", iframe:"true", title:"<?php echo $langs->trans("NewCashFence"); ?>"});
1189}
1190
1191function CashReport(rowid)
1192{
1193 $.colorbox({href:"../compta/cashcontrol/report.php?id="+rowid+"&contextpage=takepos", width:"60%", height:"90%", transition:"none", iframe:"true", title:"<?php echo $langs->trans("CashReport"); ?>"});
1194}
1195
1196/*
1197 * TakePOS Popup
1198 * Open the <div id='ModalID'>in a popup. Example with ModalID='ModalCreditNote'
1199 */
1200function ModalBox(ModalID)
1201{
1202 var modal = document.getElementById(ModalID);
1203 modal.style.display = "block";
1204}
1205
1206function DirectPayment(){
1207 console.log("DirectPayment");
1208 $("#poslines").load("invoice.php?place="+place+"&action=valid&token=<?php echo currentToken(); ?>&pay=LIQ", function() {
1209 $('#invoiceid').val("");
1210 });
1211}
1212
1213function FullScreen() {
1214 document.documentElement.requestFullscreen();
1215}
1216
1217function WeighingScale(callback) {
1218 console.log("Weighing Scale: invoiceid = " + placeid + ", lineid = " + selectedline);
1219 <?php if (getDolGlobalString('TAKEPOS_CONNECTOR_TO_WHB_SCALE')) {?>
1220 <?php if (getDolGlobalString('WEIGHINGSCALE_PROTOCOL') == "diag06") { ?>
1221 // Protocole Dialog-06, il a besoin du prix unitaire, le demander s'il manque
1222 var urlProduct;
1223 if (idproduct == "" && selectedline > 0) {
1224 urlProduct = "<?php echo DOL_URL_ROOT; ?>/api/index.php/takeposconnector/invoices/" + placeid + "/lines/" + selectedline + "/product";
1225 } else {
1226 urlProduct = "<?php echo DOL_URL_ROOT; ?>/api/index.php/products/" + idproduct;
1227 }
1228 $.ajax({
1229 type: "GET",
1230 headers: { "DOLAPIKEY": '<?php echo $user->api_key; ?>' },
1231 url: urlProduct,
1232 })
1233 .done(function(product) {
1234 if (callback === undefined) {
1235 callback = function(qty) {
1236 $("#poslines").load("invoice.php?token=<?php echo currentToken(); ?>&action=updateqty&place="+place+"&idline="+selectedline+"&number="+qty);
1237 };
1238 }
1239 if (product.fk_unit == "2") {
1240 askForWeight(product.multiprices_ttc[1], callback, function (errorMessage) {
1241 console.log("Erreur: " + errorMessage);
1242 });
1243 }
1244 });
1245 <?php } else { ?>
1246 // Default takeposconnector protocol: continuous reception of weight/stability
1247 editnumber = globalWeight;
1248 $("#poslines").load("invoice.php?token=<?php echo currentToken(); ?>&action=updateqty&place="+place+"&idline="+selectedline+"&number="+editnumber, function() {
1249 editnumber="";
1250 });
1251 <?php } ?>
1252 <?php } else { ?> // utilisation du new TakePOS-Connector PHP: envoie "$" à la balance pour avoir le poids
1253 $.ajax({
1254 type: "POST",
1255 data: { token: 'notrequired' },
1256 url: '<?php print getDolGlobalString('TAKEPOS_PRINT_SERVER'); ?>/scale/index.php',
1257 })
1258 .done(function( editnumber ) {
1259 $("#poslines").load("invoice.php?token=<?php echo currentToken(); ?>&action=updateqty&place="+place+"&idline="+selectedline+"&number="+editnumber, function() {
1260 editnumber="";
1261 });
1262 });
1263 <?php } ?>
1264}
1265
1266$( document ).ready(function() {
1267 PrintCategories(0);
1268 LoadProducts(0);
1269 Refresh();
1270 <?php
1271 // IF NO TERMINAL SELECTED
1272 if (empty($_SESSION["takeposterminal"]) || $_SESSION["takeposterminal"] == "") {
1273 print "ModalBox('ModalTerminal');";
1274 }
1275
1276 if (getDolGlobalString('TAKEPOS_CONTROL_CASH_OPENING')) {
1277 // Look for any cash control fence created today on this terminal, regardless of its status,
1278 // so the auto-open popup only fires on the first cash control of a calendar day. Without this,
1279 // refreshing the browser the same day after closing a fence used to immediately re-fire the
1280 // popup because the closed fences were filtered out by the status check (#38597).
1281 $sql = "SELECT rowid, status FROM ".MAIN_DB_PREFIX."pos_cash_fence WHERE";
1282 $sql .= " entity = ".((int) $conf->entity)." AND ";
1283 $sql .= " posnumber = ".((int) $_SESSION["takeposterminal"])." AND ";
1284 $sql .= " date_creation > '".$db->idate(dol_get_first_hour(dol_now()))."'";
1285 $resql = $db->query($sql);
1286 if ($resql) {
1287 $obj = $db->fetch_object($resql);
1288 // If there is no cash control from today open it
1289 if (!isset($obj->rowid) || is_null($obj->rowid)) {
1290 print "ControlCashOpening();";
1291 }
1292 }
1293 }
1294 ?>
1295
1296 /* For Header Scroll */
1297 var elem1 = $("#topnav-left")[0];
1298 var elem2 = $("#topnav-right")[0];
1299 var checkOverflow = function() {
1300 if (scrollBars().horizontal) $("#topnav").addClass("overflow");
1301 else $("#topnav").removeClass("overflow");
1302 }
1303
1304 var scrollBars = function(){
1305 var container= $('#topnav')[0];
1306 return {
1307 vertical:container.scrollHeight > container.clientHeight,
1308 horizontal:container.scrollWidth > container.clientWidth
1309 }
1310 }
1311
1312 $(window).resize(function(){
1313 checkOverflow();
1314 });
1315
1316 let resizeObserver = new ResizeObserver(() => {
1317 checkOverflow();
1318 });
1319 resizeObserver.observe(elem1);
1320 resizeObserver.observe(elem2);
1321 checkOverflow();
1322
1323 var pressTimer = [];
1324 var direction = 1;
1325 var step = 200;
1326
1327 $(".indicator").mousedown(function(){
1328 direction = $(this).hasClass("left") ? -1 : 1;
1329 scrollTo();
1330 pressTimer.push(setInterval(scrollTo, 100));
1331 });
1332
1333 $(".indicator").mouseup(function(){
1334 pressTimer.forEach(clearInterval);
1335 });
1336
1337 $("body").mouseup(function(){
1338 pressTimer.forEach(clearInterval);
1339 console.log("body mouseup");
1340 });
1341
1342 function scrollTo(){
1343 console.log("here");
1344 var pos = $("#topnav").scrollLeft();
1345 document.getElementById("topnav").scrollTo({ left: $("#topnav").scrollLeft() + direction * step, behavior: 'smooth' })
1346 }
1347
1348 $("#topnav").scroll(function(){
1349 if (($("#topnav").offsetWidth + $("#topnav").scrollLeft >= $("#topnav").scrollWidth)) {
1350 console.log("end");
1351 }
1352 });
1353 /* End Header Scroll */
1354});
1355</script>
1356
1357<div class="container">
1358
1359<?php
1360if (!getDolGlobalString('TAKEPOS_HIDE_HEAD_BAR')) {
1361 ?>
1362 <div class="header">
1363 <div id="topnav" class="topnav">
1364 <div id="topnav-left" class="topnav-left">
1365 <div class="inline-block valignmiddle">
1366 <a class="topnav-terminalhour" onclick="ModalBox('ModalTerminal')">
1367 <span class="fa fa-cash-register"></span>
1368 <span class="hideonsmartphone">
1369 <?php
1370 if (!empty($_SESSION["takeposterminal"])) {
1371 echo getDolGlobalString("TAKEPOS_TERMINAL_NAME_".$_SESSION["takeposterminal"], $langs->trans("TerminalName", $_SESSION["takeposterminal"]));
1372 }
1373 ?>
1374 </span>
1375 <?php
1376 echo '<span class="hideonsmartphone"> - '.dol_print_date(dol_now(), "day").'</span>'; ?>
1377 </a>
1378 <?php
1379 if (isModEnabled('multicurrency')) {
1380 print '<a class="valignmiddle tdoverflowmax100" id="multicurrency" onclick="ModalBox(\'ModalCurrency\')" title=""><span class="fas fa-coins paddingrightonly"></span>';
1381 print '<span class="hideonsmartphone">'.$langs->trans("Currency").'</span>';
1382 print '</a>';
1383 } ?>
1384 </div>
1385 <!-- section for customer -->
1386 <div class="inline-block valignmiddle" id="customerandsales"></div>
1387 <input type="hidden" id="idcustomer" value="">
1388 <!-- section for shopping carts -->
1389 <div class="inline-block valignmiddle" id="shoppingcart"></div>
1390 <!-- More info about customer -->
1391 <div class="inline-block valignmiddle tdoverflowmax150onsmartphone" id="moreinfo"></div>
1392 <?php
1393 if (isModEnabled('stock')) {
1394 ?>
1395 <!-- More info about warehouse -->
1396 <div class="inline-block valignmiddle tdoverflowmax150onsmartphone" id="infowarehouse"></div>
1397 <?php
1398 } ?>
1399 </div>
1400 <div id="topnav-right" class="topnav-right">
1401 <?php
1402 $reshook = $hookmanager->executeHooks('takepos_login_block_other');
1403 if ($reshook == 0) { //Search method
1404 ?>
1405 <div class="login_block_other takepos">
1406 <input type="text" id="search" name="search" class="input-nobottom" onkeyup="Search2(<?php echo "'".dol_escape_js($keyCodeForEnter)."'" ; ?>, null);" placeholder="<?php echo dol_escape_htmltag($langs->trans("Search")); ?>" autofocus>
1407 <a onclick="ClearSearch(false);" class="nohover"><span class="fa fa-backspace"></span></a>
1408 <a href="<?php echo DOL_URL_ROOT.'/'; ?>" target="backoffice" rel="opener"><!-- we need rel="opener" here, we are on same domain and we need to be able to reuse this tab several times -->
1409 <span class="fas fa-home"></span></a>
1410 <?php if (empty($conf->dol_use_jmobile)) { ?>
1411 <a class="hideonsmartphone" onclick="FullScreen();" title="<?php echo dol_escape_htmltag($langs->trans("ClickFullScreenEscapeToLeave")); ?>"><span class="fa fa-expand-arrows-alt"></span></a>
1412 <?php } ?>
1413 </div>
1414 <?php
1415 }
1416 ?>
1417 <div class="login_block_user">
1418 <?php
1419 print top_menu_user(1, DOL_URL_ROOT.'/user/logout.php?token='.newToken().'&urlfrom='.urlencode('/takepos/?setterminal='.((int) $term)));
1420 ?>
1421 </div>
1422 </div>
1423 <div class="arrows">
1424 <span class="indicator left"><i class="fa fa-arrow-left"></i></span>
1425 <span class="indicator right"><i class="fa fa-arrow-right"></i></span>
1426 </div>
1427 </div>
1428 </div>
1429 <?php
1430}
1431?>
1432
1433<!-- Modal terminal box -->
1434<div id="ModalTerminal" class="modal">
1435 <div class="modal-content">
1436 <div class="modal-header">
1437 <?php
1438 if (!getDolGlobalString('TAKEPOS_FORCE_TERMINAL_SELECT')) {
1439 ?>
1440 <span class="close" href="#" onclick="document.getElementById('ModalTerminal').style.display = 'none';">&times;</span>
1441 <?php
1442 } ?>
1443 <h3><?php print $langs->trans("TerminalSelect"); ?></h3>
1444 </div>
1445 <div class="modal-body">
1446 <?php
1447 foreach (takeposEnabledTerminals() as $i) {
1448 print '<button type="button" class="block" onclick="location.href=\'index.php?setterminal='.$i.'\'">'.getDolGlobalString("TAKEPOS_TERMINAL_NAME_".$i, $langs->trans("TerminalName", $i)).'</button>';
1449 }
1450 ?>
1451 </div>
1452</div>
1453</div>
1454
1455<!-- Modal multicurrency box -->
1456<?php if (isModEnabled('multicurrency')) { ?>
1457<div id="ModalCurrency" class="modal">
1458 <div class="modal-content">
1459 <div class="modal-header">
1460 <span class="close" href="#" onclick="document.getElementById('ModalCurrency').style.display = 'none';">&times;</span>
1461 <h3><?php print $langs->trans("SetMultiCurrencyCode"); ?></h3>
1462 </div>
1463 <div class="modal-body">
1464 <?php
1465 $sql = 'SELECT code FROM '.MAIN_DB_PREFIX.'multicurrency';
1466 $sql .= " WHERE entity IN ('".getEntity('multicurrency')."')";
1467 $resql = $db->query($sql);
1468 if ($resql) {
1469 while ($obj = $db->fetch_object($resql)) {
1470 print '<button type="button" class="block" onclick="location.href=\'index.php?setcurrency='.urlencode($obj->code).'\'">'.$obj->code.'</button>';
1471 }
1472 }
1473 ?>
1474 </div>
1475 </div>
1476</div>
1477<?php } ?>
1478
1479<!-- Modal popup to create a Credit Note -->
1480<div id="ModalCreditNote" class="modal">
1481 <div class="modal-content">
1482 <div class="modal-header">
1483 <span class="close" href="#" onclick="document.getElementById('ModalCreditNote').style.display = 'none';">&times;</span>
1484 <h3><?php print $langs->trans("invoiceAvoirWithLines"); ?></h3>
1485 </div>
1486 <div class="modal-body">
1487 <button type="button" class="block" onclick="CreditNote(); document.getElementById('ModalCreditNote').style.display = 'none';"><?php print $langs->trans("Yes"); ?></button>
1488 <button type="button" class="block" onclick="document.getElementById('ModalCreditNote').style.display = 'none';"><?php print $langs->trans("No"); ?></button>
1489 </div>
1490</div>
1491</div>
1492
1493<!-- Modal Note -->
1494<div id="ModalNote" class="modal">
1495 <div class="modal-content">
1496 <div class="modal-header">
1497 <span class="close" href="#" onclick="document.getElementById('ModalNote').style.display = 'none';">&times;</span>
1498 <h3><?php print $langs->trans("Note"); ?></h3>
1499 </div>
1500 <div class="modal-body">
1501 <input type="text" class="block" id="textinput">
1502 <button type="button" class="block" onclick="SetNote(); document.getElementById('ModalNote').style.display = 'none';">OK</button>
1503 </div>
1504</div>
1505</div>
1506
1507 <div class="row1<?php if (!getDolGlobalString('TAKEPOS_HIDE_HEAD_BAR')) {
1508 print 'withhead';
1509 } ?>">
1510
1511 <div id="poslines" class="div1">
1512 </div>
1513
1514 <div class="div2">
1515 <button type="button" class="calcbutton" onclick="Edit(7);">7</button>
1516 <button type="button" class="calcbutton" onclick="Edit(8);">8</button>
1517 <button type="button" class="calcbutton" onclick="Edit(9);">9</button>
1518 <button type="button" id="qty" class="calcbutton2" onclick="Edit('qty')"><?php echo $langs->trans("Qty"); ?></button>
1519 <button type="button" class="calcbutton" onclick="Edit(4);">4</button>
1520 <button type="button" class="calcbutton" onclick="Edit(5);">5</button>
1521 <button type="button" class="calcbutton" onclick="Edit(6);">6</button>
1522 <button type="button" id="price" class="calcbutton2" onclick="Edit('p')"><?php echo $langs->trans("Price"); ?></button>
1523 <button type="button" class="calcbutton" onclick="Edit(1);">1</button>
1524 <button type="button" class="calcbutton" onclick="Edit(2);">2</button>
1525 <button type="button" class="calcbutton" onclick="Edit(3);">3</button>
1526 <button type="button" id="reduction" class="calcbutton2" onclick="Edit('r')"><?php echo $langs->trans("LineDiscountShort"); ?></button>
1527 <button type="button" class="calcbutton" onclick="Edit(0);">0</button>
1528 <button type="button" class="calcbutton" onclick="Edit('.')">.</button>
1529 <button type="button" class="calcbutton poscolorblue" onclick="Edit('c')">C</button>
1530 <?php if ($user->hasRight('takepos', 'editlines')) { ?>
1531 <button type="button" class="calcbutton2 poscolordelete" id="delete" onclick="deleteline()"><span class="fa fa-trash"></span></button>
1532 <?php } ?>
1533 </div>
1534
1535<?php
1536
1537// Dependency modulecheck
1538if (!isModEnabled('invoice')) {
1539 setEventMessages($langs->trans("ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv("Invoice")), null, 'errors');
1540}
1541
1542// TakePOS setup check
1543if (isset($_SESSION["takeposterminal"]) && $_SESSION["takeposterminal"]) {
1544 $sql = "SELECT code, libelle FROM " . MAIN_DB_PREFIX . "c_paiement";
1545 $sql .= " WHERE entity IN (" . getEntity('c_paiement') . ")";
1546 $sql .= " AND active = 1";
1547 $sql .= " ORDER BY libelle";
1548
1549 $resql = $db->query($sql);
1550 $paiementsModes = array();
1551 if ($resql) {
1552 while ($obj = $db->fetch_object($resql)) {
1553 $paycode = $obj->code;
1554 if ($paycode == 'LIQ') {
1555 $paycode = 'CASH';
1556 }
1557 if ($paycode == 'CHQ') {
1558 $paycode = 'CHEQUE';
1559 }
1560
1561 $constantforkey = "CASHDESK_ID_BANKACCOUNT_" . $paycode . $_SESSION["takeposterminal"];
1562 //var_dump($constantforkey.' '.getDolGlobalInt($constantforkey));
1563 if (getDolGlobalInt($constantforkey) > 0) {
1564 array_push($paiementsModes, $obj);
1565 }
1566 }
1567 }
1568
1569 if (empty($paiementsModes) && isModEnabled("bank")) {
1570 $langs->load('errors');
1571 setEventMessages($langs->trans("ErrorModuleSetupNotComplete", $langs->transnoentitiesnoconv("TakePOS")), null, 'errors');
1572 setEventMessages($langs->trans("ProblemIsInSetupOfTerminal", $_SESSION["takeposterminal"]), null, 'errors');
1573 }
1574}
1575
1576if (count($maincategories) == 0) {
1577 if (getDolGlobalInt('TAKEPOS_ROOT_CATEGORY_ID') > 0) {
1578 $tmpcategory = new Categorie($db);
1579 $tmpcategory->fetch(getDolGlobalInt('TAKEPOS_ROOT_CATEGORY_ID'));
1580 setEventMessages($langs->trans("TakeposNeedsAtLeastOnSubCategoryIntoParentCategory", $tmpcategory->label), null, 'errors');
1581 } else {
1582 setEventMessages($langs->trans("TakeposNeedsCategories"), null, 'errors');
1583 }
1584}
1585// User menu and external TakePOS modules
1586$menus = array();
1587$r = 0;
1588
1589if (! getDolGlobalString('TAKEPOS_HIDE_HISTORY')) {
1590 $menus[$r++] = array('title' => '<span class="fa fa-history paddingrightonly"></span><div class="trunc">'.$langs->trans("History").'</div>', 'action' => 'History();');
1591}
1592
1593if (getDolGlobalString('TAKEPOS_HIDE_HEAD_BAR')) {
1594 if (getDolGlobalString('TAKEPOS_CHOOSE_CONTACT')) {
1595 $menus[$r++] = array('title' => '<span class="far fa-building paddingrightonly"></span><div class="trunc">'.$langs->trans("Contact").'</div>', 'action' => 'Contact();');
1596 } else {
1597 $menus[$r++] = array('title' => '<span class="far fa-building paddingrightonly"></span><div class="trunc">'.$langs->trans("Customer").'</div>', 'action' => 'Customer();');
1598 }
1599}
1600
1601if (!getDolGlobalString('TAKEPOS_BAR_RESTAURANT')) {
1602 $menus[$r++] = array('title' => '<span class="fa fa-layer-group paddingrightonly"></span><div class="trunc">'.$langs->trans("New").'</div>', 'action' => 'New();');
1603} else {
1604 // BAR RESTAURANT specific menu
1605 $menus[$r++] = array('title' => '<span class="fa fa-layer-group paddingrightonly"></span><div class="trunc">'.$langs->trans("Place").'</div>', 'action' => 'Floors();');
1606}
1607
1608// Add a non predefined product
1609if (!getDolGlobalString('TAKEPOS_NO_FREE_ZONE_PRODUCT')) {
1610 $menus[$r++] = array('title' => '<span class="fa fa-cube paddingrightonly"></span><div class="trunc">'.$langs->trans("FreeZone").'</div>', 'action' => 'FreeZone();');
1611}
1612
1613// BAR RESTAURANT specific menu "Print on kitchen/order printer"
1614if (getDolGlobalString('TAKEPOS_BAR_RESTAURANT')) {
1615 if (getDolGlobalString('TAKEPOS_SUPPLEMENTS')) {
1616 $menus[$r++] = array('title' => '<span class="fa fa-cube paddingrightonly"></span><div class="trunc">'.$langs->trans("ProductSupplements").'</div>', 'action' => 'LoadProducts(\'supplements\');');
1617 }
1618
1619 if (getDolGlobalString('TAKEPOS_ORDER_PRINTERS')) {
1620 $menus[$r++] = array('title' => '<span class="fa fa-blender-phone paddingrightonly"></span><div class="trunc">'.$langs->trans("SentOrderToKitchen").'</span>', 'action' => 'TakeposPrintingOrder();');
1621 }
1622}
1623
1624// Add a discount
1625$menus[$r++] = array('title' => '<span class="fa fa-percent paddingrightonly"></span><div class="trunc">'.$langs->trans("InvoiceDiscountShort").'</div>', 'action' => 'Reduction();');
1626
1627if (!getDolGlobalString('TAKEPOS_NO_SPLIT_SALE')) {
1628 $menus[$r++] = array('title' => '<span class="fas fa-cut paddingrightonly"></span><div class="trunc">'.$langs->trans("SplitSale").'</div>', 'action' => 'Split();');
1629}
1630
1631// Last action that close the sell (payments)
1632$menus[$r++] = array('title' => '<span class="far fa-money-bill-alt paddingrightonly"></span><div class="trunc">'.$langs->trans("Payment").'</div>', 'action' => 'CloseBill();');
1633if (getDolGlobalString('TAKEPOS_DIRECT_PAYMENT')) {
1634 $menus[$r++] = array('title' => '<span class="far fa-money-bill-alt paddingrightonly"></span><div class="trunc">'.$langs->trans("DirectPayment").' <span class="opacitymedium">('.$langs->trans("Cash").')</span></div>', 'action' => 'DirectPayment();');
1635}
1636
1637$customprinterallowed = false;
1638$customprinttemplateallowed = true;
1639
1640// BAR RESTAURANT specific menu
1641if (getDolGlobalString('TAKEPOS_BAR_RESTAURANT')) {
1642 // Button to print receipt before payment
1643 $customprinterallowed = true;
1644 $customprinttemplateallowed = true;
1645}
1646
1647include_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
1648if (isALNERunningVersion()) {
1649 // Custom printer may be allowed if mandatory information in template are guaranteed. For the moment, we prefer not allow this.
1650 $customprinttemplateallowed = false;
1651}
1652
1653// Button to print receipt
1654// This section should be same than into invoice.php
1655if (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") { // deprecated method
1656 if (getDolGlobalString('TAKEPOS_PRINT_SERVER') && filter_var(getDolGlobalString('TAKEPOS_PRINT_SERVER'), FILTER_VALIDATE_URL) == true) {
1657 // If TAKEPOS_PRINT_SERVER is an URL
1658 $menus[$r++] = array('title' => '<span class="fa fa-receipt paddingrightonly"></span><div class="trunc">'.$langs->trans("PrintTicket").'</div>', 'action' => 'PrintByESCPOSOld(placeid);');
1659 } else {
1660 // If TAKEPOS_PRINT_SERVER is an IP
1661 // Print by calling the receipt.php to get HTML content and send the HTML content to TAKEPOS_PRINT_SERVER:8111/print
1662 $menus[$r++] = array('title' => '<span class="fa fa-receipt paddingrightonly"></span><div class="trunc">'.$langs->trans("PrintTicket").'</div>', 'action' => 'PrintHTMLToSlashPrint(placeid);');
1663 }
1664} elseif ($customprinterallowed && $customprinttemplateallowed && (isModEnabled('receiptprinter') && getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term) > 0) || getDolGlobalString('TAKEPOS_PRINT_METHOD') == "receiptprinter") { // @phpstan-ignore-line
1665 // Button Print Receipt on special custom printer using custom template
1666 $nameOfPrinter = dol_getIdFromCode($db, getDolGlobalInt('TAKEPOS_PRINTER_TO_USE'.$term), 'printer_receipt', 'rowid', 'name', 1);
1667 $menus[$r++] = array('title' => '<div title="'.dolPrintHTMLForAttribute($langs->trans("PrintOn", $nameOfPrinter)).'"><span class="fa fa-receipt paddingrightonly"></span><div class="trunc">'.$langs->trans("PrintTicket").'</div></div>', 'action' => 'PrintByESCPOS(placeid);');
1668} else {
1669 // Button Print Receipt on browser
1670 $menus[$r++] = array('title' => '<span class="fa fa-receipt paddingrightonly"></span><div class="trunc">'.$langs->trans("PrintTicket").'</div>', 'action' => 'PrintByBrowser(placeid);');
1671}
1672
1673if (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector" && getDolGlobalString('TAKEPOS_ORDER_NOTES') == 1) {
1674 $menus[$r++] = array('title' => '<span class="fa fa-sticky-note paddingrightonly"></span><div class="trunc">'.$langs->trans("OrderNotes").'</div>', 'action' => 'TakeposOrderNotes();');
1675}
1676
1677
1678if (getDolGlobalString('TAKEPOS_PRINT_METHOD') == "takeposconnector") {
1679 $menus[$r++] = array('title' => '<span class="fa fa-receipt paddingrightonly"></span><div class="trunc">'.$langs->trans("DOL_OPEN_DRAWER").'</div>', 'action' => 'OpenDrawer();');
1680}
1681if (getDolGlobalInt('TAKEPOS_ADD_BUTTON_OPEN_DRAWER'.$term) > 0) {
1682 $menus[$r++] = array(
1683 'title' => '<span class="fa fa-receipt paddingrightonly"></span><div class="trunc">'.$langs->trans("DOL_OPEN_DRAWER").'</div>',
1684 'action' => 'DolibarrOpenDrawer();',
1685 );
1686}
1687
1688// If there is an open cash control started
1689$sql = "SELECT rowid, status, entity FROM ".MAIN_DB_PREFIX."pos_cash_fence WHERE";
1690$sql .= " entity = ".((int) $conf->entity)." AND ";
1691$sql .= " posnumber = ".((int) empty($_SESSION["takeposterminal"]) ? 0 : $_SESSION["takeposterminal"])." AND ";
1692$sql .= " date_creation > '".$db->idate(dol_get_first_hour(dol_now()))."'";
1693$sql .= " AND status = 0";
1694
1695$resql = $db->query($sql);
1696if ($resql) {
1697 $num = $db->num_rows($resql);
1698 if ($num) {
1699 $obj = $db->fetch_object($resql);
1700 $menus[$r++] = array('title' => '<span class="fas fa-file-invoice-dollar paddingrightonly"></span><div class="trunc">'.$langs->trans("CashReport").'</div>', 'action' => 'CashReport('.$obj->rowid.');');
1701 if ($obj->status == 0) {
1702 $menus[$r++] = array('title' => '<span class="fas fa-cash-register paddingrightonly"></span><div class="trunc">'.$langs->trans("CloseCashFence").'</div>', 'action' => 'CloseCashFence('.$obj->rowid.');');
1703 }
1704 }
1705}
1706
1707if (getDolGlobalString('TAKEPOS_HIDE_HEAD_BAR')) {
1708 $menus[$r++] = array('title' => '<span class="fa fa-sign-out-alt pictofixedwidth"></span><div class="trunc">'.$langs->trans("Logout").'</div>', 'action' => 'window.location.href=\''.DOL_URL_ROOT.'/user/logout.php?token='.newToken().'\';');
1709}
1710
1711if (getDolGlobalString('TAKEPOS_WEIGHING_SCALE')) {
1712 $menus[$r++] = array('title' => '<span class="fa fa-balance-scale pictofixedwidth"></span><div class="trunc">'.$langs->trans("WeighingScale").'</div>', 'action' => 'WeighingScale();');
1713}
1714
1715// Button to delete (discard) the current sale
1716/* Hide this. This button must appear only if is_erasable() is true. So it must depend on open invoice. For this reason,
1717 * the button could not be in this panel but must be on the left side inside the invoice.php file.
1718$menus[$r++] = array('title' => '<span class="fa fa-trash-alt paddingrightonly"></span><div class="trunc truncdeletesale">'.$langs->trans("DeleteSale").'</div>', 'action' => 'DeleteSale();', 'class' => 'actionbuttondelete');
1719*/
1720
1721$parameters = array('menus' => $menus);
1722$reshook = $hookmanager->executeHooks('ActionButtons', $parameters);
1723if ($reshook == 0) { //add buttons
1724 if (is_array($hookmanager->resArray)) {
1725 foreach ($hookmanager->resArray as $resArray) {
1726 foreach ($resArray as $butmenu) {
1727 $menus[$r++] = $butmenu;
1728 }
1729 }
1730 }
1731} elseif ($reshook == 1) {
1732 $r = 0; //replace buttons
1733 if (is_array($hookmanager->resArray)) {
1734 foreach ($hookmanager->resArray as $resArray) {
1735 foreach ($resArray as $butmenu) {
1736 $menus[$r++] = $butmenu;
1737 }
1738 }
1739 }
1740}
1741
1742?>
1743 <!-- Show buttons -->
1744 <div id="dialogforpopuptakepos"></div>
1745 <style>
1746 /* Style de la popup */
1747 #dialogforpopuptakepos {
1748 display: none;
1749 position: fixed;
1750 top: 20px;
1751 right: 20px;
1752 background: #333;
1753 color: #fff;
1754 padding: 15px 20px;
1755 border-radius: 8px;
1756 box-shadow: 0 0 10px rgba(0,0,0,0.3);
1757 z-index: 1000;
1758 font-family: sans-serif;
1759 }
1760 </style>
1761
1762 <div class="div3">
1763 <?php
1764 $i = 0;
1765 foreach ($menus as $menu) {
1766 $i++;
1767 if (count($menus) > 12 and $i == 12) {
1768 echo '<button style="'.(empty($menu['style']) ? '' : $menu['style']).'" type="button" id="actionnext" class="actionbutton" onclick="MoreActions('.count($menus).')">'.$langs->trans("Next").'</button>';
1769 echo '<button style="display: none;" type="button" id="actionprevious" class="actionbutton" onclick="MoreActions('.count($menus).')">'.$langs->trans("Previous").'</button>';
1770 echo '<button style="display: none;" type="button" id="action'.$i.'" class="actionbutton'.(empty($menu['class']) ? '' : ' '.dol_escape_htmltag($menu['class'])).'" onclick="'.(empty($menu['action']) ? '' : $menu['action']).'">'.$menu['title'].'</button>';
1771 } elseif ($i > 12) {
1772 echo '<button style="display: none;" type="button" id="action'.$i.'" class="actionbutton'.(empty($menu['class']) ? '' : ' '.dol_escape_htmltag($menu['class'])).'" onclick="'.(empty($menu['action']) ? '' : $menu['action']).'">'.$menu['title'].'</button>';
1773 // TODO keep style but hide button
1774 } else {
1775 echo '<button style="'.(empty($menu['style']) ? '' : $menu['style']).'" type="button" id="action'.$i.'" class="actionbutton'.(empty($menu['class']) ? '' : ' '.dol_escape_htmltag($menu['class'])).'" onclick="'.(empty($menu['action']) ? '' : $menu['action']).'">'.$menu['title'].'</button>';
1776 }
1777 }
1778
1779 if (getDolGlobalString('TAKEPOS_HIDE_HEAD_BAR') && !getDolGlobalString('TAKEPOS_HIDE_SEARCH')) {
1780 print '<!-- Show the search input text -->'."\n";
1781 print '<div class="margintoponly">';
1782 print '<input type="text" id="search" class="input-search-takepos input-nobottom" name="search" onkeyup="Search2(\''.dol_escape_js($keyCodeForEnter).'\', null);" style="width: 80%; width:calc(100% - 51px); font-size: 150%;" placeholder="'.dol_escape_htmltag($langs->trans("Search")).'" autofocus> ';
1783 print '<a class="marginleftonly hideonsmartphone" onclick="ClearSearch(false);">'.img_picto('', 'searchclear.png').'</a>';
1784 print '</div>';
1785 }
1786 ?>
1787 </div>
1788 </div>
1789
1790 <div class="row2<?php if (!getDolGlobalString('TAKEPOS_HIDE_HEAD_BAR')) {
1791 print 'withhead';
1792 } ?>">
1793
1794 <!-- Show categories -->
1795 <?php
1796 if (getDolGlobalInt('TAKEPOS_HIDE_CATEGORIES') == 1) {
1797 print '<div class="div4" style= "display: none;">';
1798 } else {
1799 print '<div class="div4">';
1800 }
1801
1802 $count = 0;
1803 while ($count < $MAXCATEG) {
1804 ?>
1805 <div class="wrapper" <?php if ($count == ($MAXCATEG - 2)) {
1806 echo 'onclick="MoreCategories(\'less\')"';
1807 } elseif ($count == ($MAXCATEG - 1)) {
1808 echo 'onclick="MoreCategories(\'more\')"';
1809 } else {
1810 echo 'onclick="LoadProducts('.$count.')"';
1811 } ?> id="catdiv<?php echo $count; ?>">
1812 <?php
1813 if ($count == ($MAXCATEG - 2)) {
1814 //echo '<img class="imgwrapper" src="img/arrow-prev-top.png" height="100%" id="catimg'.$count.'" />';
1815 echo '<span class="fa fa-chevron-left centerinmiddle" style="font-size: 5em; cursor: pointer;"></span>';
1816 } elseif ($count == ($MAXCATEG - 1)) {
1817 //echo '<img class="imgwrapper" src="img/arrow-next-top.png" height="100%" id="catimg'.$count.'" />';
1818 echo '<span class="fa fa-chevron-right centerinmiddle" style="font-size: 5em; cursor: pointer;"></span>';
1819 } else {
1820 if (!getDolGlobalString('TAKEPOS_HIDE_CATEGORY_IMAGES')) {
1821 echo '<img class="imgwrapper" id="catimg'.$count.'" />';
1822 }
1823 } ?>
1824 <?php if ($count != $MAXCATEG - 2 && $count != $MAXCATEG - 1) { ?>
1825 <div class="description" id="catdivdesc<?php echo $count; ?>">
1826 <div class="description_content" id="catdesc<?php echo $count; ?>"></div>
1827 </div>
1828 <?php } ?>
1829 <div class="catwatermark" id='catwatermark<?php echo $count; ?>'>...</div>
1830 </div>
1831 <?php
1832 $count++;
1833 }
1834 ?>
1835 </div>
1836
1837 <!-- Show product -->
1838 <div class="div5<?php if (getDolGlobalInt('TAKEPOS_HIDE_CATEGORIES') == 1) {
1839 print ' centpercent';
1840 } ?>">
1841 <?php
1842 $count = 0;
1843
1844 while ($count < $MAXPRODUCT) {
1845 print '<div class="wrapper2'.(($count >= ($MAXPRODUCT - 2)) ? ' arrow' : '').'" id="prodiv'.$count.'" '; ?>
1846 <?php if ($count == ($MAXPRODUCT - 2)) {
1847 ?> onclick="MoreProducts('less')" <?php
1848 }
1849 if ($count == ($MAXPRODUCT - 1)) {
1850 ?> onclick="MoreProducts('more')" <?php
1851 } else {
1852 echo 'onclick="ClickProduct('.((int) $count).')"';
1853 } ?>>
1854 <?php
1855 if ($count == ($MAXPRODUCT - 2)) {
1856 //echo '<img class="imgwrapper" src="img/arrow-prev-top.png" height="100%" id="proimg'.$count.'" />';
1857 print '<span class="fa fa-chevron-left centerinmiddle" style="font-size: 5em; cursor: pointer;"></span>';
1858 } elseif ($count == ($MAXPRODUCT - 1)) {
1859 //echo '<img class="imgwrapper" src="img/arrow-next-top.png" height="100%" id="proimg'.$count.'" />';
1860 print '<span class="fa fa-chevron-right centerinmiddle" style="font-size: 5em; cursor: pointer;"></span>';
1861 } else {
1862 if (!getDolGlobalString('TAKEPOS_HIDE_PRODUCT_PRICES')) {
1863 print '<div class="" id="proprice'.$count.'"></div>';
1864 }
1865 if (getDolGlobalString('TAKEPOS_HIDE_PRODUCT_IMAGES')) {
1866 print '<button type="button" id="probutton'.$count.'" class="productbutton" style="display: none;"></button>';
1867 } else {
1868 print '<img class="imgwrapper" title="" id="proimg'.$count.'">';
1869 }
1870 } ?>
1871 <?php if ($count != $MAXPRODUCT - 2 && $count != $MAXPRODUCT - 1 && !getDolGlobalString('TAKEPOS_HIDE_PRODUCT_IMAGES')) { ?>
1872 <div class="description" id="prodivdesc<?php echo $count; ?>">
1873 <div class="description_content" id="prodesc<?php echo $count; ?>"></div>
1874 </div>
1875 <?php } ?>
1876 <div class="catwatermark" id='prowatermark<?php echo $count; ?>'>...</div>
1877 </div>
1878 <?php
1879 $count++;
1880 }
1881 ?>
1882 <input type="hidden" id="search_start_less" value="0">
1883 <input type="hidden" id="search_start_more" value="0">
1884 <input type="hidden" id="search_pagination" value="">
1885 </div>
1886 </div>
1887</div>
1888</body>
1889<?php
1890
1891llxFooter();
1892
1893$db->close();
$propal type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition propal.php:280
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
print $object position
Definition edit.php:206
Class to manage categories.
Class to manage contact/addresses.
Class to manage generation of HTML components Only common components must be here.
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:169
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:676
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
dol_now($mode='gmt')
Return date for now.
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.
dolSetCookie(string $cookiename, string $cookievalue, int $expire=-1)
Set a cookie.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into JavaScript code.
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
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, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
multi select button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
editval_textarea active
top_htmlhead($head, $title='', $disablejs=0, $disablehead=0, $arrayofjs=array(), $arrayofcss=array(), $disableforlogin=0, $disablenofollow=0, $disablenoindex=0)
Output html header of a page.
top_menu_user($hideloginname=0, $urllogout='')
Build the tooltip on user login.
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:140
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $nodie=0, $mode='')
Check permissions of a user to show a page and an object.
if(empty( $takeposterminal)) fail($message)
Abort invoice creation with a given error message.
Definition invoice.php:125
takeposEnabledTerminals()
Return the list of the TakePOS terminals that can be used.