diff --git a/pos_lot_selection/README.rst b/pos_lot_selection/README.rst index 08a45d2120..6bee1303c3 100644 --- a/pos_lot_selection/README.rst +++ b/pos_lot_selection/README.rst @@ -71,9 +71,23 @@ Authors Contributors ------------ -- Tecnativa - Camptocamp -- Nguyen Minh Chien + + - Iryna Vyshnevska + - Ivan Todorovich + - Maksym Yankin + +- Dixmit + + - Enric Tobella + +- Tecnativa + + - David Vidal + +- Trobz Consulting + + - Nguyen Minh Chien chien@trobz.com Maintainers ----------- diff --git a/pos_lot_selection/models/__init__.py b/pos_lot_selection/models/__init__.py index ee1c64fbcd..992444490b 100644 --- a/pos_lot_selection/models/__init__.py +++ b/pos_lot_selection/models/__init__.py @@ -1 +1,4 @@ +from . import product_product from . import stock_lot + +from . import pos_session diff --git a/pos_lot_selection/models/pos_session.py b/pos_lot_selection/models/pos_session.py new file mode 100644 index 0000000000..e19dd54ae1 --- /dev/null +++ b/pos_lot_selection/models/pos_session.py @@ -0,0 +1,18 @@ +# Copyright 2024 Dixmit +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import models + + +class PosSession(models.Model): + _inherit = "pos.session" + + def _loader_params_product_product(self): + result = super()._loader_params_product_product() + result["search_params"]["fields"].append("available_lot_for_pos_ids") + return result + + def get_pos_ui_product_product_by_params(self, custom_search_params): + return super( + PosSession, self.with_company(self.company_id.id) + ).get_pos_ui_product_product_by_params(custom_search_params) diff --git a/pos_lot_selection/models/product_product.py b/pos_lot_selection/models/product_product.py new file mode 100644 index 0000000000..b051f4c7e7 --- /dev/null +++ b/pos_lot_selection/models/product_product.py @@ -0,0 +1,48 @@ +# Copyright 2022 Camptocamp SA +# Copyright 2024 Dixmit +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +from odoo import api, fields, models +from odoo.tools import float_compare + + +class ProductProduct(models.Model): + _inherit = "product.product" + + available_lot_for_pos_ids = fields.Json( + compute="_compute_available_lot_for_pos", prefetch=False + ) + + @api.depends() + @api.depends_context("company") + def _compute_available_lot_for_pos(self): + for record in self: + record.available_lot_for_pos_ids = record.get_available_lots_for_pos( + self.env.company.id + ) + + def get_available_lots_for_pos(self, company_id): + self.ensure_one() + if self.type != "product" or self.tracking == "none": + return [] + lots = ( + self.env["stock.lot"] + .sudo() + .search( + [ + "&", + ["product_id", "=", self.id], + "|", + ["company_id", "=", company_id], + ["company_id", "=", False], + ] + ) + ) + + lots = lots.filtered( + lambda lot: float_compare( + lot.product_qty, 0, precision_digits=lot.product_uom_id.rounding + ) + > 0 + ) + return [lot._get_pos_info() for lot in lots] diff --git a/pos_lot_selection/models/stock_lot.py b/pos_lot_selection/models/stock_lot.py index e12a52b1aa..624d1d0456 100644 --- a/pos_lot_selection/models/stock_lot.py +++ b/pos_lot_selection/models/stock_lot.py @@ -1,30 +1,16 @@ # Copyright 2022 Camptocamp SA +# Copyright 2024 Dixmit # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) -from odoo import api, models -from odoo.tools import float_compare +from odoo import models -class ProductionLot(models.Model): +class StockLot(models.Model): _inherit = "stock.lot" - @api.model - def get_available_lots_for_pos(self, product_id, company_id): - lots = self.sudo().search( - [ - "&", - ["product_id", "=", product_id], - "|", - ["company_id", "=", company_id], - ["company_id", "=", False], - ] - ) - - lots = lots.filtered( - lambda rec: float_compare( - rec.product_qty, 0, precision_digits=rec.product_uom_id.rounding - ) - > 0 - ) - - return lots.mapped("name") + def _get_pos_info(self): + # We will add this as a hook to add more fields if necessary + return { + "id": self.id, + "name": self.name, + } diff --git a/pos_lot_selection/readme/CONTRIBUTORS.md b/pos_lot_selection/readme/CONTRIBUTORS.md index 9db880a4a6..8a2cdb44c8 100644 --- a/pos_lot_selection/readme/CONTRIBUTORS.md +++ b/pos_lot_selection/readme/CONTRIBUTORS.md @@ -1,3 +1,10 @@ -- Tecnativa - Camptocamp -- Nguyen Minh Chien \<\> + - Iryna Vyshnevska + - Ivan Todorovich + - Maksym Yankin +- Dixmit + - Enric Tobella +- Tecnativa + - David Vidal +- Trobz Consulting + - Nguyen Minh Chien diff --git a/pos_lot_selection/static/description/index.html b/pos_lot_selection/static/description/index.html index 51cfca8c37..613bf0e973 100644 --- a/pos_lot_selection/static/description/index.html +++ b/pos_lot_selection/static/description/index.html @@ -419,9 +419,24 @@

Authors

Contributors

    -
  • Tecnativa
  • -
  • Camptocamp
  • -
  • Nguyen Minh Chien <chien@trobz.com>
  • +
  • Camptocamp
      +
    • Iryna Vyshnevska
    • +
    • Ivan Todorovich
    • +
    • Maksym Yankin
    • +
    +
  • +
  • Dixmit
      +
    • Enric Tobella
    • +
    +
  • +
  • Tecnativa
      +
    • David Vidal
    • +
    +
  • +
  • Trobz Consulting +
diff --git a/pos_lot_selection/static/src/js/EditListPopup.esm.js b/pos_lot_selection/static/src/js/EditListPopup.esm.js index e23db30b48..39a170fd96 100644 --- a/pos_lot_selection/static/src/js/EditListPopup.esm.js +++ b/pos_lot_selection/static/src/js/EditListPopup.esm.js @@ -1,19 +1,52 @@ /** @odoo-module */ - /* - Copyright 2022 Camptocamp SA + Copyright 2023 Dixmit + Copyright 2022 Camptocamp License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) */ + +import {onWillStart, useState} from "@odoo/owl"; +import {ConnectionLostError} from "@web/core/network/rpc_service"; +import {EditListInput} from "@point_of_sale/app/store/select_lot_popup/edit_list_input/edit_list_input"; import {EditListPopup} from "@point_of_sale/app/store/select_lot_popup/select_lot_popup"; + import {_t} from "@web/core/l10n/translation"; import {patch} from "@web/core/utils/patch"; -import {session} from "@web/session"; +patch(EditListInput.prototype, { + get_lot_name(lot) { + return lot.name; + }, +}); patch(EditListPopup.prototype, { setup() { - super.setup(...arguments); + super.setup(); + this.data = useState({ + lots: this.env.services.pos.selectedProduct.available_lot_for_pos_ids, + }); + onWillStart(this.onWillStart); + }, + async onWillStart() { if (this.props.title === _t("Lot/Serial Number(s) Required")) { - this.props.lots = session.lots; + // We keep this in order to ensure that this call is only done + // when we add a serial + try { + const lots = await this.env.services.orm.call( + "product.product", + "get_available_lots_for_pos", + [ + [this.env.services.pos.selectedProduct.id], + this.env.services.pos.company.id, + ] + ); + this.data.lots = lots; + this.env.services.pos.selectedProduct.available_lot_for_pos_ids = lots; + } catch (error) { + if (error instanceof ConnectionLostError) { + return; + } + throw error; + } } }, }); diff --git a/pos_lot_selection/static/src/js/OrderWidget.esm.js b/pos_lot_selection/static/src/js/OrderWidget.esm.js deleted file mode 100644 index fcc8ee5019..0000000000 --- a/pos_lot_selection/static/src/js/OrderWidget.esm.js +++ /dev/null @@ -1,18 +0,0 @@ -/** @odoo-module */ - -/* - Copyright 2022 Camptocamp SA - License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) -*/ -import {Orderline} from "@point_of_sale/app/store/models"; -import {patch} from "@web/core/utils/patch"; -import {session} from "@web/session"; - -patch(Orderline.prototype, { - async editPackLotLines() { - session.lots = await this.pos.getProductLots(this.product); - const res = await super.editPackLotLines(...arguments); - session.lots = undefined; - return res; - }, -}); diff --git a/pos_lot_selection/static/src/js/Product.esm.js b/pos_lot_selection/static/src/js/Product.esm.js deleted file mode 100644 index 430622fc4a..0000000000 --- a/pos_lot_selection/static/src/js/Product.esm.js +++ /dev/null @@ -1,20 +0,0 @@ -/** @odoo-module */ - -/* - Copyright 2022 Camptocamp SA (https://www.camptocamp.com). - License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -*/ -import {Product} from "@point_of_sale/app/store/models"; -import {patch} from "@web/core/utils/patch"; -import {session} from "@web/session"; - -patch(Product.prototype, { - async getAddProductOptions(code) { - if (["serial", "lot"].includes(this.tracking)) { - session.lots = await this.pos.getProductLots(this); - } - const res = await super.getAddProductOptions(code); - session.lots = undefined; - return res; - }, -}); diff --git a/pos_lot_selection/static/src/js/models.esm.js b/pos_lot_selection/static/src/js/models.esm.js index fe7b3f6fd8..290c64990f 100644 --- a/pos_lot_selection/static/src/js/models.esm.js +++ b/pos_lot_selection/static/src/js/models.esm.js @@ -1,25 +1,21 @@ /** @odoo-module */ - /* - Copyright 2022 Camptocamp SA + Copyright 2023 Dixmit License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) */ -import {PosStore} from "@point_of_sale/app/store/pos_store"; -import {patch} from "@web/core/utils/patch"; -import {session} from "@web/session"; +import {Orderline, Product} from "@point_of_sale/app/store/models"; -patch(PosStore.prototype, { - async getProductLots(product) { - try { - return await this.orm.silent.call( - "stock.lot", - "get_available_lots_for_pos", - [product.id, session.user_companies.current_company] - ); - } catch (error) { - console.error(error); - return []; - } +import {patch} from "@web/core/utils/patch"; +patch(Product.prototype, { + getAddProductOptions() { + this.pos.selectedProduct = this; + return super.getAddProductOptions(...arguments); + }, +}); +patch(Orderline.prototype, { + editPackLotLines() { + this.pos.selectedProduct = this.product; + return super.editPackLotLines(...arguments); }, }); diff --git a/pos_lot_selection/static/src/xml/LotSelectorPopup.xml b/pos_lot_selection/static/src/xml/LotSelectorPopup.xml index 4636bb5d3a..7c222b22ef 100644 --- a/pos_lot_selection/static/src/xml/LotSelectorPopup.xml +++ b/pos_lot_selection/static/src/xml/LotSelectorPopup.xml @@ -5,7 +5,7 @@ - props.lots + data.lots @@ -20,9 +20,9 @@ t-foreach="props.lots" t-as="lot" t-key="lot_index" - t-att-value="lot" + t-att-value="get_lot_name(lot)" > - + diff --git a/pos_lot_selection/static/tests/tours/LotSelection.tour.esm.js b/pos_lot_selection/static/tests/tours/LotSelection.tour.esm.js index 096a88a881..ded1b283f1 100644 --- a/pos_lot_selection/static/tests/tours/LotSelection.tour.esm.js +++ b/pos_lot_selection/static/tests/tours/LotSelection.tour.esm.js @@ -1,4 +1,8 @@ /** @odoo-module */ +/* + Copyright 2023 Trobz Consulting + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +*/ import * as Chrome from "@point_of_sale/../tests/tours/helpers/ChromeTourMethods"; import * as ReceiptScreen from "@point_of_sale/../tests/tours/helpers/ReceiptScreenTourMethods"; diff --git a/pos_lot_selection/tests/test_frontend.py b/pos_lot_selection/tests/test_frontend.py index 0ac59f6d7c..745a7702cb 100644 --- a/pos_lot_selection/tests/test_frontend.py +++ b/pos_lot_selection/tests/test_frontend.py @@ -1,4 +1,5 @@ -# Part of Odoo. See LICENSE file for full copyright and licensing details. +# Copyright 2023 Trobz Consulting +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). import odoo.tests