diff --git a/sale_cart/README.rst b/sale_cart/README.rst index 8be55fa41d..e82f1de224 100644 --- a/sale_cart/README.rst +++ b/sale_cart/README.rst @@ -1,7 +1,3 @@ -.. image:: https://odoo-community.org/readme-banner-image - :target: https://odoo-community.org/get-involved?utm_source=readme - :alt: Odoo Community Association - ========= Sale Cart ========= @@ -17,7 +13,7 @@ Sale Cart .. |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/license-AGPL--3-blue.png +.. |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-shopinvader%2Fodoo--shopinvader-lightgray.png?logo=github @@ -26,9 +22,9 @@ Sale Cart |badge1| |badge2| |badge3| -This addon add a typology on sale.order to distinguish the sale orders -that are in the process of being written (cart) and those that are -quotations ready to be confirmed. +This addon adds a "cart" typology on sale.order to distinguish the sale +orders that are in the process of being written (cart) and those that +are quotations ready to be confirmed. It also automatically converts the cart into a sale when the payment is authorized, set as pending, or done. @@ -60,6 +56,7 @@ Contributors ------------ - Laurent Mignon +- Nicolas DELBOVIER Maintainers ----------- diff --git a/sale_cart/__manifest__.py b/sale_cart/__manifest__.py index 105cf2e4fe..0c2ee64d23 100644 --- a/sale_cart/__manifest__.py +++ b/sale_cart/__manifest__.py @@ -8,7 +8,7 @@ "license": "AGPL-3", "author": "ACSONE SA/NV", "website": "https://github.com/shopinvader/odoo-shopinvader", - "depends": ["sale", "sales_team"], + "depends": ["sale", "sales_team", "sale_typology"], "data": ["views/sale_order.xml"], "demo": [], "installable": True, diff --git a/sale_cart/models/sale_order.py b/sale_cart/models/sale_order.py index 5272933187..a7ba537066 100644 --- a/sale_cart/models/sale_order.py +++ b/sale_cart/models/sale_order.py @@ -7,7 +7,12 @@ class SaleOrder(models.Model): _inherit = "sale.order" - typology = fields.Selection([("sale", "Sale"), ("cart", "Cart")], default="sale") + typology = fields.Selection( + selection_add=[("cart", "Cart")], + ondelete={ + "cart": "cascade", + }, + ) def _confirm_cart(self): self.ensure_one() diff --git a/sale_cart/readme/CONTRIBUTORS.md b/sale_cart/readme/CONTRIBUTORS.md index dc42b35f36..489ba24542 100644 --- a/sale_cart/readme/CONTRIBUTORS.md +++ b/sale_cart/readme/CONTRIBUTORS.md @@ -1 +1,2 @@ - Laurent Mignon \ +- Nicolas DELBOVIER \ diff --git a/sale_cart/readme/DESCRIPTION.md b/sale_cart/readme/DESCRIPTION.md index e9082a1669..c0964e8344 100644 --- a/sale_cart/readme/DESCRIPTION.md +++ b/sale_cart/readme/DESCRIPTION.md @@ -1,6 +1,6 @@ -This addon add a typology on sale.order to distinguish the sale orders -that are in the process of being written (cart) and those that are -quotations ready to be confirmed. +This addon adds a "cart" typology on sale.order to distinguish the sale orders that are +in the process of being written (cart) and those that are quotations +ready to be confirmed. It also automatically converts the cart into a sale when the payment is authorized, set as pending, or done. diff --git a/sale_cart/static/description/index.html b/sale_cart/static/description/index.html index 9599548f71..3da65e5502 100644 --- a/sale_cart/static/description/index.html +++ b/sale_cart/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +Sale Cart -
+
+

Sale Cart

- - -Odoo Community Association - -
-

Sale Cart

-

Beta License: AGPL-3 shopinvader/odoo-shopinvader

-

This addon add a typology on sale.order to distinguish the sale orders -that are in the process of being written (cart) and those that are -quotations ready to be confirmed.

+

Beta License: AGPL-3 shopinvader/odoo-shopinvader

+

This addon adds a “cart” typology on sale.order to distinguish the sale +orders that are in the process of being written (cart) and those that +are quotations ready to be confirmed.

It also automatically converts the cart into a sale when the payment is authorized, set as pending, or done.

Table of contents

@@ -393,7 +388,7 @@

Sale Cart

-

Bug Tracker

+

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 to smash it by providing a detailed and welcomed @@ -401,26 +396,26 @@

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ACSONE SA/NV
-

Maintainers

+

Maintainers

This module is part of the shopinvader/odoo-shopinvader project on GitHub.

You are welcome to contribute.

-
diff --git a/sale_cart/views/sale_order.xml b/sale_cart/views/sale_order.xml index 543e037ba2..ec299f946a 100644 --- a/sale_cart/views/sale_order.xml +++ b/sale_cart/views/sale_order.xml @@ -30,7 +30,7 @@ - [('typology', '=', 'sale'), + [('typology', '!=', 'cart'), ('state','in',('draft','sent','cancel'))] diff --git a/sale_cart_quotation/README.rst b/sale_cart_quotation/README.rst new file mode 100644 index 0000000000..7fa20fa403 --- /dev/null +++ b/sale_cart_quotation/README.rst @@ -0,0 +1,61 @@ +=================== +Sale Cart Quotation +=================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:092764e34a3532b13b87a0b07712f405be8de3df4ce5265a1c4f0640ea1f44f8 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-shopinvader%2Fodoo--shopinvader-lightgray.png?logo=github + :target: https://github.com/shopinvader/odoo-shopinvader/tree/18.0/sale_cart_quotation + :alt: shopinvader/odoo-shopinvader + +|badge1| |badge2| |badge3| + +Glue module between sale_quotation and sale_cart, allowing users to +request a quotation directly from a cart. + +**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 to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* ACSONE SA/NV + +Contributors +------------ + +- Nicolas DELBOVIER + +Maintainers +----------- + +This module is part of the `shopinvader/odoo-shopinvader `_ project on GitHub. + +You are welcome to contribute. diff --git a/sale_cart_quotation/__init__.py b/sale_cart_quotation/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/sale_cart_quotation/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/sale_cart_quotation/__manifest__.py b/sale_cart_quotation/__manifest__.py new file mode 100644 index 0000000000..12062fea2f --- /dev/null +++ b/sale_cart_quotation/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2025 ACSONE SA/NV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Sale Cart Quotation", + "summary": """Glue module between sale_quotation and sale_cart, + allowing users to request a quotation directly from a cart.""", + "version": "18.0.1.0.0", + "license": "AGPL-3", + "author": "ACSONE SA/NV", + "website": "https://github.com/shopinvader/odoo-shopinvader", + "depends": ["sale_quotation", "sale_cart"], + "data": [ + "views/sale_order.xml", + ], + "demo": [], +} diff --git a/sale_cart_quotation/models/__init__.py b/sale_cart_quotation/models/__init__.py new file mode 100644 index 0000000000..6aacb75313 --- /dev/null +++ b/sale_cart_quotation/models/__init__.py @@ -0,0 +1 @@ +from . import sale_order diff --git a/sale_cart_quotation/models/sale_order.py b/sale_cart_quotation/models/sale_order.py new file mode 100644 index 0000000000..059f3d942a --- /dev/null +++ b/sale_cart_quotation/models/sale_order.py @@ -0,0 +1,21 @@ +# Copyright 2025 ACSONE SA/NV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import models +from odoo.exceptions import UserError + + +class SaleOrder(models.Model): + _inherit = "sale.order" + + def action_cart_request_quotation(self): + if any(rec.state != "draft" or rec.typology != "cart" for rec in self): + raise UserError( + self.env._( + "Only orders of cart typology in draft state " + "can be converted to quotation" + ) + ) + self.write({"use_customer_quotation_workflow": True}) + self.action_customer_request_quotation() + return True diff --git a/sale_cart_quotation/pyproject.toml b/sale_cart_quotation/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/sale_cart_quotation/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/sale_cart_quotation/readme/CONTRIBUTORS.md b/sale_cart_quotation/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..e617553800 --- /dev/null +++ b/sale_cart_quotation/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- Nicolas DELBOVIER \ diff --git a/sale_cart_quotation/readme/DESCRIPTION.md b/sale_cart_quotation/readme/DESCRIPTION.md new file mode 100644 index 0000000000..c8d2f3515e --- /dev/null +++ b/sale_cart_quotation/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +Glue module between sale_quotation and sale_cart, allowing users to +request a quotation directly from a cart. diff --git a/sale_cart_quotation/static/description/index.html b/sale_cart_quotation/static/description/index.html new file mode 100644 index 0000000000..705ba04fa0 --- /dev/null +++ b/sale_cart_quotation/static/description/index.html @@ -0,0 +1,417 @@ + + + + + +Sale Cart Quotation + + + +
+

Sale Cart Quotation

+ + +

Beta License: AGPL-3 shopinvader/odoo-shopinvader

+

Glue module between sale_quotation and sale_cart, allowing users to +request a quotation directly from a cart.

+

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 to smash it by providing a detailed and welcomed +feedback.

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • ACSONE SA/NV
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is part of the shopinvader/odoo-shopinvader project on GitHub.

+

You are welcome to contribute.

+
+
+
+ + diff --git a/sale_cart_quotation/tests/__init__.py b/sale_cart_quotation/tests/__init__.py new file mode 100644 index 0000000000..43ae815229 --- /dev/null +++ b/sale_cart_quotation/tests/__init__.py @@ -0,0 +1 @@ +from . import test_quotation diff --git a/sale_cart_quotation/tests/test_quotation.py b/sale_cart_quotation/tests/test_quotation.py new file mode 100644 index 0000000000..7c4357ff78 --- /dev/null +++ b/sale_cart_quotation/tests/test_quotation.py @@ -0,0 +1,49 @@ +# Copyright 2025 ACSONE SA/NV +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + +from odoo.addons.base.tests.common import DISABLED_MAIL_CONTEXT + + +class TestQuotation(TransactionCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env = cls.env(context=dict(cls.env.context, **DISABLED_MAIL_CONTEXT)) + product = cls.env["product.product"].create({"name": "Test Product"}) + partner = cls.env["res.partner"].create({"name": "John"}) + cls.so = cls.env["sale.order"].create( + { + "partner_id": partner.id, + "order_line": [(0, 0, {"product_id": product.id})], + } + ) + + def test_request_quotation(self): + self.so.typology = "cart" + self.so.action_cart_request_quotation() + self.assertRecordValues( + self.so, + [ + { + "quotation_state": "customer_request", + "typology": "quote", + } + ], + ) + + def test_send_requested_quotation(self): + self.so.typology = "cart" + self.so.action_cart_request_quotation() + self.so.action_quotation_sent() + self.assertRecordValues( + self.so, + [ + { + "quotation_state": "waiting_acceptation", + "typology": "quote", + } + ], + ) + self.assertEqual(self.so.quotation_state, "waiting_acceptation") diff --git a/sale_cart_quotation/views/sale_order.xml b/sale_cart_quotation/views/sale_order.xml new file mode 100644 index 0000000000..76548b034c --- /dev/null +++ b/sale_cart_quotation/views/sale_order.xml @@ -0,0 +1,21 @@ + + + + + sale.cart.quotation.sale.order.form + sale.order + + + +