diff --git a/pos_partner_pricelist_load_background/README.rst b/pos_partner_pricelist_load_background/README.rst new file mode 100644 index 0000000000..b0ff278f77 --- /dev/null +++ b/pos_partner_pricelist_load_background/README.rst @@ -0,0 +1,66 @@ +===================================== +POS Partner Pricelist Load Background +===================================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-camptocamp%2Fpos-lightgray.png?logo=github + :target: https://github.com/camptocamp/pos/tree/16.0/pos_partner_pricelist_load_background + :alt: camptocamp/pos + +|badge1| |badge2| |badge3| + +This module allow you to load a pricelist for a customer in the background. + +**Context** +In the POS, we can configure a list of available pricelists. These price lists are loaded during start-up and only these can be chosen for any order. +When a customer is selected, the POS will try to find the customer's pricelist (property_pricelist_id) among the available pricelists. +If it's found, the pricelist is selected otherwise a default one will be selected instead. + +**With this module** +When a customer is selected, his pricelist (property_pricelist_id) is loaded and available to be chosen. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Camptocamp + +Contributors +~~~~~~~~~~~~ + +* Telmo Santos +* Iván Todorovich + +Maintainers +~~~~~~~~~~~ + +This module is part of the `camptocamp/pos `_ project on GitHub. + +You are welcome to contribute. diff --git a/pos_partner_pricelist_load_background/__init__.py b/pos_partner_pricelist_load_background/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/pos_partner_pricelist_load_background/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/pos_partner_pricelist_load_background/__manifest__.py b/pos_partner_pricelist_load_background/__manifest__.py new file mode 100644 index 0000000000..4d9dbf0233 --- /dev/null +++ b/pos_partner_pricelist_load_background/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2024 Camptocamp (https://www.camptocamp.com). +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "POS Partner Pricelist Load Background", + "summary": "Pos ", + "version": "16.0.1.0.0", + "author": "Camptocamp, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/pos", + "license": "AGPL-3", + "category": "Point of Sale", + "depends": ["point_of_sale"], + "installable": True, + "assets": { + "point_of_sale.assets": [ + "pos_partner_pricelist_load_background/static/src/js/**/*.js", + ], + }, +} diff --git a/pos_partner_pricelist_load_background/models/__init__.py b/pos_partner_pricelist_load_background/models/__init__.py new file mode 100644 index 0000000000..f7116e3d45 --- /dev/null +++ b/pos_partner_pricelist_load_background/models/__init__.py @@ -0,0 +1 @@ +from . import pos_session diff --git a/pos_partner_pricelist_load_background/models/pos_session.py b/pos_partner_pricelist_load_background/models/pos_session.py new file mode 100644 index 0000000000..1d66854f9a --- /dev/null +++ b/pos_partner_pricelist_load_background/models/pos_session.py @@ -0,0 +1,34 @@ +# Copyright 2024 Camptocamp +# 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 get_pos_ui_partner_pricelist_background(self, pricelist_id, product_ids): + params = self._loader_params_product_pricelist() + fnames = params["search_params"]["fields"] + pricelist_rec = self.env["product.pricelist"].browse(pricelist_id) + pricelist = pricelist_rec.read(fnames)[0] + pricelist["items"] = [] + + products = ( + self.env["product.product"].browse(product_ids) + | pricelist_rec.item_ids.product_id + ) + templates = products.product_tmpl_id | pricelist_rec.item_ids.product_tmpl_id + pricelist_item_domain = [ + ("pricelist_id", "=", pricelist_id), + "|", + ("product_tmpl_id", "=", False), + ("product_tmpl_id", "in", templates.ids), + "|", + ("product_id", "=", False), + ("product_id", "in", products.ids), + ] + for item in self.env["product.pricelist.item"].search_read( + pricelist_item_domain, self._product_pricelist_item_fields() + ): + pricelist["items"].append(item) + return [pricelist] diff --git a/pos_partner_pricelist_load_background/readme/CONTRIBUTORS.rst b/pos_partner_pricelist_load_background/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..5c9f1e3d54 --- /dev/null +++ b/pos_partner_pricelist_load_background/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Telmo Santos +* Iván Todorovich diff --git a/pos_partner_pricelist_load_background/readme/DESCRIPTION.rst b/pos_partner_pricelist_load_background/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..dd4bdd573b --- /dev/null +++ b/pos_partner_pricelist_load_background/readme/DESCRIPTION.rst @@ -0,0 +1,9 @@ +This module allow you to load a pricelist for a customer in the background. + +**Context** +In the POS, we can configure a list of available pricelists. These price lists are loaded during start-up and only these can be chosen for any order. +When a customer is selected, the POS will try to find the customer's pricelist (property_pricelist_id) among the available pricelists. +If it's found, the pricelist is selected otherwise a default one will be selected instead. + +**With this module** +When a customer is selected, his pricelist (property_pricelist_id) is loaded and available to be chosen. diff --git a/pos_partner_pricelist_load_background/static/description/index.html b/pos_partner_pricelist_load_background/static/description/index.html new file mode 100644 index 0000000000..d4b3c4ac51 --- /dev/null +++ b/pos_partner_pricelist_load_background/static/description/index.html @@ -0,0 +1,421 @@ + + + + + + +POS Partner Pricelist Load Background + + + +
+

POS Partner Pricelist Load Background

+ + +

Beta License: AGPL-3 camptocamp/pos

+

This module allow you to load a pricelist for a customer in the background.

+

Context +In the POS, we can configure a list of available pricelists. These price lists are loaded during start-up and only these can be chosen for any order. +When a customer is selected, the POS will try to find the customer’s pricelist (property_pricelist_id) among the available pricelists. +If it’s found, the pricelist is selected otherwise a default one will be selected instead.

+

With this module +When a customer is selected, his pricelist (property_pricelist_id) is loaded and available to be chosen.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Camptocamp
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is part of the camptocamp/pos project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/pos_partner_pricelist_load_background/static/src/js/Order.esm.js b/pos_partner_pricelist_load_background/static/src/js/Order.esm.js new file mode 100644 index 0000000000..cedd05c943 --- /dev/null +++ b/pos_partner_pricelist_load_background/static/src/js/Order.esm.js @@ -0,0 +1,20 @@ +/** @odoo-module **/ +/* + Copyright 2024 Camptocamp SA (https://www.camptocamp.com). + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +*/ + +import {Order} from "point_of_sale.models"; +import Registries from "point_of_sale.Registries"; + +const PosPartnerPricelistLoadBackgroundOrder = (Order) => + class PosPartnerPricelistLoadBackgroundOrder extends Order { + /** @override **/ + init_from_JSON(json) { + super.init_from_JSON(json); + if (json.pricelist_id) + this.pos._loadPartnerPricelistBackground(json.pricelist_id); + } + }; + +Registries.Model.extend(Order, PosPartnerPricelistLoadBackgroundOrder); diff --git a/pos_partner_pricelist_load_background/static/src/js/PartnerListScreen.esm.js b/pos_partner_pricelist_load_background/static/src/js/PartnerListScreen.esm.js new file mode 100644 index 0000000000..b90a23d1a3 --- /dev/null +++ b/pos_partner_pricelist_load_background/static/src/js/PartnerListScreen.esm.js @@ -0,0 +1,24 @@ +/** @odoo-module **/ +/* + Copyright 2024 Camptocamp SA (https://www.camptocamp.com). + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +*/ +import PartnerListScreen from "point_of_sale.PartnerListScreen"; +import Registries from "point_of_sale.Registries"; + +const PosPartnerPricelistLoadBackgroundPartnerListScreen = (PartnerListScreen) => + class extends PartnerListScreen { + async clickPartner(partner) { + if (partner && partner.property_product_pricelist) { + await this.env.pos._loadPartnerPricelistBackground( + Number(partner.property_product_pricelist[0]) + ); + } + await super.clickPartner(partner); + } + }; + +Registries.Component.extend( + PartnerListScreen, + PosPartnerPricelistLoadBackgroundPartnerListScreen +); diff --git a/pos_partner_pricelist_load_background/static/src/js/PosGlobalState.esm.js b/pos_partner_pricelist_load_background/static/src/js/PosGlobalState.esm.js new file mode 100644 index 0000000000..a7af57bc27 --- /dev/null +++ b/pos_partner_pricelist_load_background/static/src/js/PosGlobalState.esm.js @@ -0,0 +1,86 @@ +/** @odoo-module **/ +/* + Copyright 2024 Camptocamp SA (https://www.camptocamp.com). + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +*/ + +import {PosGlobalState} from "point_of_sale.models"; +import Registries from "point_of_sale.Registries"; + +const PosPartnerPricelistLoadBackgroundSPosGlobalState = (PosGlobalState) => + class PosPartnerPricelistLoadBackgroundPosGlobalState extends PosGlobalState { + _getLoadedPricelistById(pricelistId) { + return this.env.pos.pricelists.find( + (pricelist) => pricelist.id === pricelistId + ); + } + _assignPricelistApplicableItems(pricelist) { + for (const pricelistItem of pricelist.items) { + if (pricelistItem.product_id) { + const product_id = pricelistItem.product_id[0]; + const correspondingProduct = this.db.get_product_by_id(product_id); + if (!correspondingProduct) continue; + this._assignApplicableItems( + pricelist, + correspondingProduct, + pricelistItem + ); + } + if (pricelistItem.product_tmpl_id) { + for (const product of Object.values(this.db.product_by_id).filter( + (x) => x.product_tmpl_id === pricelistItem.product_tmpl_id[0] + )) { + this._assignApplicableItems(pricelist, product, pricelistItem); + } + } + } + } + + async _loadPartnerPricelistBackground(pricelistId) { + const loadedPricelist = this._getLoadedPricelistById(pricelistId); + if (loadedPricelist) { + this.env.pos.default_pricelist = loadedPricelist; + return; + } + // Block the UI while loading the pricelist + this.env.services.ui.block(); + try { + const productIds = Object.keys(this.db.product_by_id); + const loadedPricelists = await this.env.services.rpc({ + model: "pos.session", + method: "get_pos_ui_partner_pricelist_background", + args: [ + this.pos_session_id, + pricelistId, + productIds.map((id) => Number(id)), + ], + }); + for (const pricelist of loadedPricelists) { + this.pricelists.push(pricelist); + this._assignPricelistApplicableItems(pricelist); + } + } finally { + this.env.services.ui.unblock(); + } + // Now that the partner pricelist is loaded assign it as the defaut one + this.env.pos.selectedOrder.set_pricelist( + this._getLoadedPricelistById(pricelistId) + ); + } + + // @override + add_new_order() { + const order = super.add_new_order(); + order.set_pricelist( + this.env.pos._getLoadedPricelistById( + this.env.pos.config.pricelist_id[0] + ) + ); + return order; + } + }; + +Registries.Model.extend( + PosGlobalState, + PosPartnerPricelistLoadBackgroundSPosGlobalState +); diff --git a/pos_partner_pricelist_load_background/static/src/js/ProductScreen.esm.js b/pos_partner_pricelist_load_background/static/src/js/ProductScreen.esm.js new file mode 100644 index 0000000000..b0def717da --- /dev/null +++ b/pos_partner_pricelist_load_background/static/src/js/ProductScreen.esm.js @@ -0,0 +1,30 @@ +/** @odoo-module **/ +/* + Copyright 2024 Camptocamp SA (https://www.camptocamp.com). + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +*/ +import ProductScreen from "point_of_sale.ProductScreen"; +import Registries from "point_of_sale.Registries"; + +const PosPartnerPricelistLoadBackgroundProductScreen = (ProductScreen) => + class extends ProductScreen { + async onClickPartner() { + await super.onClickPartner(); + if (this.partner && this.partner.property_product_pricelist) { + await this.env.pos._loadPartnerPricelistBackground( + Number(this.partner.property_product_pricelist[0]) + ); + } else { + this.env.pos.selectedOrder.set_pricelist( + this.env.pos._getLoadedPricelistById( + this.env.pos.config.pricelist_id[0] + ) + ); + } + } + }; + +Registries.Component.extend( + ProductScreen, + PosPartnerPricelistLoadBackgroundProductScreen +); diff --git a/pos_partner_pricelist_load_background/static/src/js/SetPricelistButton.esm.js b/pos_partner_pricelist_load_background/static/src/js/SetPricelistButton.esm.js new file mode 100644 index 0000000000..6f51176f91 --- /dev/null +++ b/pos_partner_pricelist_load_background/static/src/js/SetPricelistButton.esm.js @@ -0,0 +1,30 @@ +/** @odoo-module **/ +/* + Copyright 2024 Camptocamp SA (https://www.camptocamp.com). + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +*/ +import Registries from "point_of_sale.Registries"; +import SetPricelistButton from "point_of_sale.SetPricelistButton"; + +const SetPricelistButtonPosTechnicalPricelist = (OriginalSetPricelistButton) => + class extends OriginalSetPricelistButton { + async showPopup(name, props) { + const availablePricelists = Object.values( + this.env.pos.config.available_pricelist_ids + ); + const partner = this.env.pos.selectedOrder.partner; + const partnerPricelistID = + partner && + partner.property_product_pricelist && + partner.property_product_pricelist[0]; + props.list = props.list.filter( + (x) => availablePricelists.includes(x.id) || x.id === partnerPricelistID + ); + return await super.showPopup(name, props); + } + }; + +Registries.Component.extend( + SetPricelistButton, + SetPricelistButtonPosTechnicalPricelist +); diff --git a/setup/pos_partner_pricelist_load_background/odoo/addons/pos_partner_pricelist_load_background b/setup/pos_partner_pricelist_load_background/odoo/addons/pos_partner_pricelist_load_background new file mode 120000 index 0000000000..3c89d4ee9b --- /dev/null +++ b/setup/pos_partner_pricelist_load_background/odoo/addons/pos_partner_pricelist_load_background @@ -0,0 +1 @@ +../../../../pos_partner_pricelist_load_background \ No newline at end of file diff --git a/setup/pos_partner_pricelist_load_background/setup.py b/setup/pos_partner_pricelist_load_background/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/pos_partner_pricelist_load_background/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)