diff --git a/pos_place/__manifest__.py b/pos_place/__manifest__.py index 5f23953b27..c9872c1f4b 100644 --- a/pos_place/__manifest__.py +++ b/pos_place/__manifest__.py @@ -20,6 +20,14 @@ "views/view_pos_place.xml", "views/view_pos_order.xml", ], + "assets": { + "point_of_sale.assets": [ + "pos_place/static/src/js/models.esm.js", + "pos_place/static/src/xml/ChromeWidgets/PosPlaceName.xml", + "pos_place/static/src/xml/ChromeWidgets/PosPlaceName.js", + "pos_place/static/src/xml/Chrome.xml", + ], + }, # "qweb": [ # "static/src/xml/pos_place.xml", # ], diff --git a/pos_place/models/pos_session.py b/pos_place/models/pos_session.py new file mode 100644 index 0000000000..e506c2c165 --- /dev/null +++ b/pos_place/models/pos_session.py @@ -0,0 +1,24 @@ +# Copyright (C) 2024 - Today: GRAP (http://www.grap.coop) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import models + + +class PosSession(models.Model): + _inherit = "pos.session" + + def _pos_ui_models_to_load(self): + result = super()._pos_ui_models_to_load() + if self.env.user.has_group("pos_place.group_pos_place_user"): + result.append("pos.place") + return result + + def _loader_params_pos_place(self): + return { + "search_params": { + "fields": ["code", "name"], + }, + } + + def _get_pos_ui_pos_place(self, params): + return self.env["pos.place"].search_read(**params["search_params"]) diff --git a/pos_place/static/src/js/models.esm.js b/pos_place/static/src/js/models.esm.js new file mode 100644 index 0000000000..0be73e539d --- /dev/null +++ b/pos_place/static/src/js/models.esm.js @@ -0,0 +1,141 @@ +/** @odoo-module **/ + +import {Order, PosGlobalState} from "point_of_sale.models"; +import Registries from "point_of_sale.Registries"; + +const OverloadPosGlobalState = (PosGlobalState) => + class extends PosGlobalState { + async _processData(loadedData) { + await super._processData(...arguments); + if (this.config.module_pos_hr) { + this.employees = loadedData["hr.employee"]; + this.employee_by_id = loadedData.employee_by_id; + this.reset_cashier(); + } + } + async after_load_server_data() { + await super.after_load_server_data(...arguments); + if (this.config.module_pos_hr) { + this.hasLoggedIn = !this.config.module_pos_hr; + } + } + reset_cashier() { + this.cashier = { + name: null, + id: null, + barcode: null, + user_id: null, + pin: null, + role: null, + }; + } + set_cashier(employee) { + this.cashier = employee; + const selectedOrder = this.get_order(); + if (selectedOrder && !selectedOrder.get_orderlines().length) { + // Order without lines can be considered to be un-owned by any employee. + // We set the cashier on that order to the currently set employee. + selectedOrder.cashier = employee; + } + if (!this.cashierHasPriceControlRights() && this.numpadMode === "price") { + this.numpadMode = "quantity"; + } + } + + /** {name: null, id: null, barcode: null, user_id:null, pin:null} + * If pos_hr is activated, return {name: string, id: int, barcode: string, pin: string, user_id: int} + * @returns {null|*} + */ + get_cashier() { + if (this.config.module_pos_hr) { + return this.cashier; + } + return super.get_cashier(); + } + get_cashier_user_id() { + if (this.config.module_pos_hr) { + return this.cashier.user_id ? this.cashier.user_id : null; + } + return super.get_cashier_user_id(); + } + }; +Registries.Model.extend(PosGlobalState, PosHrPosGlobalState); + +export const OverloadOrder = (OriginalOrder) => + class extends OriginalOrder { + get_place() { + return this.current_place; + // || this.db.load("current_place") + } + set_place(place) { + this.current_place = place; + // This.db.save("current_place", place || null); + } + + export_for_printing() { + var result = super.export_for_printing(...arguments); + result.place = this.get_place(); + return res; + } + + export_as_JSON() { + const json = super.export_as_JSON(...arguments); + /* Const place = this.pos.get_place(); + json.place = place ? place.id : false; +*/ + json.place = this.get_place(); + return json; + } + + init_from_JSON(json) { + super.init_from_JSON(...arguments); + this.set_place(json.place); + } + }; + +Registries.Model.extend(Order, OverloadOrder); + +/* Odoo.define("pos_place.models", function (require) { + "use strict"; + + var models = require("point_of_sale.models"); + var _super_order = models.Order.prototype; + + // Load pos.place model + models.load_models({ + model: "pos.place", + loaded: function (self, places) { + self.places = []; + for (var i = 0; i < places.length; i++) { + self.places.push(places[i]); + } + }, + });*/ + +/* // Make place persistent in the session + models.PosModel = models.PosModel.extend({ + get_place: function () { + return this.get("current_place") || this.db.load("current_place"); + }, + set_place: function (place) { + this.set("current_place", place); + this.db.save("current_place", place || null); + }, + }); +*/ +/* models.Order = models.Order.extend({ + export_for_printing: function () { + var result = super.export_for_printing(...arguments); + result.place = this.pos.get_place(); + return res; + }, + + export_as_JSON: function () { + var json = _super_order.export_as_JSON.apply(this, arguments); + var place = this.pos.get_place(); + json.place_id = place ? place.id : false; + return json; + }, + }); +}); +*/ diff --git a/pos_place/static/src/js/models.js b/pos_place/static/src/js/models.js deleted file mode 100644 index 4efc4cb471..0000000000 --- a/pos_place/static/src/js/models.js +++ /dev/null @@ -1,49 +0,0 @@ -/** -Copyright (C) 2015 - Today: GRAP (http://www.grap.coop) -@author: Sylvain LE GAL (https://twitter.com/legalsylvain) -License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -**/ - -odoo.define("pos_place.models", function (require) { - "use strict"; - - var models = require("point_of_sale.models"); - var _super_order = models.Order.prototype; - - // Load pos.place model - models.load_models({ - model: "pos.place", - loaded: function (self, places) { - self.places = []; - for (var i = 0; i < places.length; i++) { - self.places.push(places[i]); - } - }, - }); - - // Make place persistent in the session - models.PosModel = models.PosModel.extend({ - get_place: function () { - return this.get("current_place") || this.db.load("current_place"); - }, - set_place: function (place) { - this.set("current_place", place); - this.db.save("current_place", place || null); - }, - }); - - models.Order = models.Order.extend({ - export_for_printing: function () { - var res = _super_order.export_for_printing.apply(this, arguments); - res.place = this.pos.get_place(); - return res; - }, - - export_as_JSON: function () { - var json = _super_order.export_as_JSON.apply(this, arguments); - var place = this.pos.get_place(); - json.place_id = place ? place.id : false; - return json; - }, - }); -}); diff --git a/pos_place/static/src/xml/Chrome.xml b/pos_place/static/src/xml/Chrome.xml new file mode 100644 index 0000000000..186be46887 --- /dev/null +++ b/pos_place/static/src/xml/Chrome.xml @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/pos_place/static/src/xml/ChromeWidgets/PosPlaceName.js b/pos_place/static/src/xml/ChromeWidgets/PosPlaceName.js new file mode 100644 index 0000000000..5475e47893 --- /dev/null +++ b/pos_place/static/src/xml/ChromeWidgets/PosPlaceName.js @@ -0,0 +1,61 @@ +odoo.define("pos_place.PosPlaceName", function (require) { + "use strict"; + + const PosComponent = require("point_of_sale.PosComponent"); + const Registries = require("point_of_sale.Registries"); + + // Previously UsernameWidget + class PosPlaceName extends PosComponent { + /** + * Select a place, the returning value will either be an object or nothing (undefined) + */ + async selectPosPlace() { + if (this.env.pos.config.module_pos_hr) { + const employeesList = this.env.pos.employees + .filter((employee) => employee.id !== this.env.pos.get_cashier().id) + .map((employee) => { + return { + id: employee.id, + item: employee, + label: employee.name, + isSelected: false, + }; + }); + let {confirmed, payload: employee} = await this.showPopup( + "SelectionPopup", + { + title: this.env._t("Change Cashier"), + list: employeesList, + } + ); + + if (!confirmed) { + return; + } + + if (employee && employee.pin) { + employee = await this.askPin(employee); + } + if (employee) { + this.env.pos.set_cashier(employee); + } + return employee; + } + } + + get username() { + const {name} = this.env.pos.get_cashier(); + return name ? name : ""; + } + get avatar() { + const user_id = this.env.pos.get_cashier_user_id(); + const id = user_id ? user_id : -1; + return `/web/image/res.users/${id}/avatar_128`; + } + } + PosPlaceName.template = "PosPlaceName"; + + Registries.Component.add(PosPlaceName); + + return PosPlaceName; +}); diff --git a/pos_place/static/src/xml/ChromeWidgets/PosPlaceName.xml b/pos_place/static/src/xml/ChromeWidgets/PosPlaceName.xml new file mode 100644 index 0000000000..cf9b26cf31 --- /dev/null +++ b/pos_place/static/src/xml/ChromeWidgets/PosPlaceName.xml @@ -0,0 +1,15 @@ + + + + +
+ BOB + +
+
+ +
diff --git a/pos_place/static/src/xml/PosPlaceName.xml b/pos_place/static/src/xml/PosPlaceName.xml new file mode 100644 index 0000000000..2531d23f81 --- /dev/null +++ b/pos_place/static/src/xml/PosPlaceName.xml @@ -0,0 +1,14 @@ + + + + +
+ +
+
+ +