From 8698340826eccc8698bb38faf54d6596a56f0eb1 Mon Sep 17 00:00:00 2001 From: Denis Roussel Date: Fri, 17 Jan 2020 11:44:05 +0100 Subject: [PATCH 1/2] [10.0][IMP] shopinvader: Allow to copy a previous sale This allows to copy a previous confirmed cart to a new one. If there is an existing cart, it will be replaced. --- .isort.cfg | 2 +- shopinvader/services/cart.py | 80 ++++++++++++++++++++++++++++- shopinvader/tests/__init__.py | 1 + shopinvader/tests/test_cart_copy.py | 35 +++++++++++++ 4 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 shopinvader/tests/test_cart_copy.py diff --git a/.isort.cfg b/.isort.cfg index 5861afcb46..8aba7bf289 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -6,4 +6,4 @@ force_grid_wrap=0 combine_as_imports=True use_parentheses=True line_length=79 -known_third_party = StringIO,mock,odoo,openupgradelib,psycopg2,requests,setuptools,urllib2,urlparse,vcr,vcr_unittest,werkzeug +known_third_party = StringIO,cerberus,mock,odoo,openupgradelib,psycopg2,requests,setuptools,urllib2,urlparse,vcr,vcr_unittest,werkzeug diff --git a/shopinvader/services/cart.py b/shopinvader/services/cart.py index 536e6e7ad4..ecff93a4cd 100644 --- a/shopinvader/services/cart.py +++ b/shopinvader/services/cart.py @@ -3,9 +3,9 @@ # Sébastien BEAU # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). # pylint: disable=consider-merging-classes-inherited - import logging +from cerberus import Validator from odoo.addons.base_rest.components.service import to_int from odoo.addons.component.core import Component from odoo.exceptions import UserError @@ -68,7 +68,85 @@ def clear(self): cart = self._clear_cart(cart) return self._to_json(cart) + def _get_validator_cart_by_id_domain(self, value): + """ + Get cart by id domain. Limiting to session partner. + :param value: + :return: + """ + return [("partner_id", "=", self.partner.id), ("id", "=", value)] + + def _get_line_copy_vals(self, line): + """ + Prepare copy values to be passed to _add_item + :param line: sale.order.line + :return: dict + """ + return { + "product_id": line.product_id.id, + "item_qty": line.product_uom_qty, + } + + def _get_lines_to_copy(self, cart): + return cart.order_line + + # pylint: disable=W8102,W8106 + def copy(self, **params): + """ + This service allows + :param params: + :return: + """ + return self._copy(**params) + + def _copy(self, **params): + """ + Copy the cart given by id without the lines + They will be re-added + :return: dict/json + """ + cart = self.env["sale.order"].search( + self._get_validator_cart_by_id_domain(params.get("id")) + ) + # Copy the existing cart + # Delete all lines and re-add them with 'shopinvader' flavour + new_cart = cart.copy({"order_line": False, "typology": "cart"}) + for line in self._get_lines_to_copy(cart): + vals = self._get_line_copy_vals(line) + self._add_item(new_cart, vals) + + return self._to_json(new_cart) + # Validator + def _cart_validator_exists(self, field, value, error): + """ + Implements 'check_with' validation + :param field: + :param value: + :param error: + :return: + """ + cart = self.env["sale.order"].search( + self._get_validator_cart_by_id_domain(value) + ) + if len(cart) != 1: + error( + field, _("The cart does not exists or does not belong to you!") + ) + + def _validator_copy(self): + return { + "id": { + "coerce": to_int, + "required": True, + "type": "integer", + "check_with": self._cart_validator_exists, + } + } + + def _validator_return_copy(self): + return Validator({}, allow_unknown=True) + def _validator_search(self): return {} diff --git a/shopinvader/tests/__init__.py b/shopinvader/tests/__init__.py index 9fd78a66f9..041cf6a0bd 100644 --- a/shopinvader/tests/__init__.py +++ b/shopinvader/tests/__init__.py @@ -3,6 +3,7 @@ from . import test_controller from . import test_backend from . import test_cart +from . import test_cart_copy from . import test_cart_item from . import test_address from . import test_product diff --git a/shopinvader/tests/test_cart_copy.py b/shopinvader/tests/test_cart_copy.py new file mode 100644 index 0000000000..4223ce0514 --- /dev/null +++ b/shopinvader/tests/test_cart_copy.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- +# Copyright 2020 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo.exceptions import UserError + +from .test_cart import CommonConnectedCartCase + + +class TestCartCopy(CommonConnectedCartCase): + @classmethod + def setUpClass(cls): + super(TestCartCopy, cls).setUpClass() + cls.product_copy = cls.env.ref("product.product_product_24") + cls.product_copy.list_price = 500.0 + + def test_cart_copy(self): + # Copy existing cart + # Check if we return a new one with new values + result = self.service.dispatch("copy", params={"id": self.cart.id}) + cart_data = result.get("data") + new_id = cart_data.get("id") + self.assertNotEquals(new_id, self.cart.id) + copy_cart = self.env["sale.order"].browse(new_id) + self.assertEquals("cart", copy_cart.typology) + line = copy_cart.order_line.filtered( + lambda l: l.product_id == self.product_copy + ) + self.assertEquals(500.0, line.price_unit) + + def test_cart_copy_does_not_exist(self): + cart_id = self.cart.id + self.cart.unlink() + # Check validator + with self.assertRaises(UserError): + self.service.dispatch("copy", params={"id": cart_id}) From 52cc5898edf0778eab1d34703d679189313fd4e3 Mon Sep 17 00:00:00 2001 From: Denis Roussel Date: Fri, 7 Feb 2020 15:59:45 +0100 Subject: [PATCH 2/2] [10.0][IMP] shopinvader_delivery_carrier: Don't copy delivery lines --- shopinvader_delivery_carrier/services/cart.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/shopinvader_delivery_carrier/services/cart.py b/shopinvader_delivery_carrier/services/cart.py index 17ab61d61a..1f88f3c329 100644 --- a/shopinvader_delivery_carrier/services/cart.py +++ b/shopinvader_delivery_carrier/services/cart.py @@ -123,3 +123,12 @@ def _set_carrier(self, cart, carrier_id): def _unset_carrier(self, cart): cart.write({"carrier_id": False}) cart._delivery_unset() + + def _get_lines_to_copy(self, cart): + """ + Don't copy delivery lines + :param cart: + :return: + """ + res = super(CartService, self)._get_lines_to_copy(cart) + return res.filtered(lambda l: not l.is_delivery)