odoo.define("lacagette_custom_pos.screens", function (require) { "use strict"; var screens = require("point_of_sale.screens"); var models = require('point_of_sale.models'); var core = require('web.core'); var dataModel = require('web.DataModel'); var lacagette_products = new dataModel('lacagette.products'); var _t = core._t; const interval = 60 * 60 * 1000; // used for last_price_change call var reload_on_prices_change = false; models.load_fields("pos.config", ['reload_on_prices_change', 'can_cclose_pos_with_ongoing_order']); var close_button_action_setup = false; const update_last_price_change_data = async function () { /* Ask odoo server data about last prices change According to response, pos_session variables will be set in order to make decision about reloading or not pos data */ lacagette_products.call('get_last_price_change') .then( function(received) { if (typeof received.data !== "undefined" && received.data.length > 0) { if (typeof posmodel.pos_session.last_price_update != "undefined") { posmodel.pos_session.previous_price_update = posmodel.pos_session.last_price_update } posmodel.pos_session.last_price_update = received.data[0].write_date posmodel.pos_session.last_price_update_load = Date.now(); if (posmodel.pos_session.last_price_update != posmodel.pos_session.previous_price_update) posmodel.pos_session.needs_reload = true; } } ) .fail(function(result, ev){ // Store event date. Used to make the "reloading" decision posmodel.pos_session.last_network_failure = Date.now(); ev.preventDefault(); }) } screens.ClientListScreenWidget.include({ init: function(parent, options) { this._super(parent, options); reload_on_prices_change = this.pos.config.reload_on_prices_change; if (reload_on_prices_change) { posmodel.pos_session.load_at = Date.now(); posmodel.pos_session.needs_reload = false; update_last_price_change_data(); // don't wait for timer for first time const confirmRefresh = event => { // Called when unload is unsafe event.preventDefault(); const message = _t("Are you sure you want to refresh the page?") (event || window.event).returnValue = confirmationMessage; //Gecko + IE return message; //Gecko + Webkit, Safari, Chrome etc. }; const checkUnload = event => { try { if (window.navigator.onLine == true) { return undefined; } else { return confirmRefresh(event); } } catch(err) { return confirmRefresh(event); } } window.addEventListener("beforeunload", checkUnload, { capture: true }); // Let's init a perpetual regular call to prices update data setInterval(() => { // catch all the errors. update_last_price_change_data().catch(console.log); }, interval); } }, show: function(){ if (typeof posmodel.pos_session.previous_price_update != "undefined" && posmodel.pos_session.needs_reload == true) { /* At least one product price has been changed since pos session has been started We can't reload page without having a look to network state If page reload is called while network is down, the browser will show a blank page and there will be no way to show POS screens again. A smarter way to refresh products data would be to process products data retrieve, in ajax mode, without having to reload whole page code. It could be the next improve step for this module. */ const now = Date.now(); let can_reload_page = false; if (typeof posmodel.pos_session.last_network_failure == "undefined") { /* no network failure while retreiving price change data. It doesn't mean that network is now available, since it could be shutdown after last call Let reload available only if wifi icon is green is better but not safe at all ! beforeunload event capture will ask user for confirmation if network has gone */ if ($('.js_connected.oe_icon.oe_green').length > 0) can_reload_page = true; } else { // one network failure occured if (posmodel.pos_session.last_price_update_load > posmodel.pos_session.last_network_failure) { can_reload_page = true; } } if (can_reload_page === true) { this.gui.show_popup("alert", { 'title': _t("POS data must been refreshed"), 'body': _t("Some product prices have been changed, page will be refreshed") }); setTimeout(function(){ window.location.reload(); }, 5000); } else { this._super(); } } else { this._super(); } } }); screens.ScreenWidget.include({ init: function(parent,options){ this._super(parent,options); /* * If activated in this pos session, prevent closing the session if there is an ongoing order. * This is a hacky DOM manipulation: the user can technically close the session if he closes the popup and press 'Close' again in less than 2s. * But this is very unlikely. * * ScreenWidget is a base widget extended by many others, we do this here to be sure this code is called... */ if (close_button_action_setup === false) { // ... but we need to make sure it is called only once close_button_action_setup = true; if (this.pos.config.can_close_pos_with_ongoing_order === false) { let header_nodes = document.querySelectorAll(".pos-topheader .pos-rightheader div"); let close_button_div = header_nodes[header_nodes.length- 1]; let self = this; close_button_div.addEventListener("click", function(e) { let order = self.pos.get_order(); if (!order.is_empty()) { if (close_button_div.classList.contains("confirm")) { close_button_div.classList.remove("confirm"); close_button_div.textContent = _t('Close'); } self.gui.show_popup("alert", { 'title': _t("Impossible de fermer la caisse"), 'body': _t("Des commandes sont encore en cours.") }); } }); } } }, }); });