Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[16.0] [ADD] shopinvader_api_quotation #1573

Open
wants to merge 13 commits into
base: 16.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions sale_quotation/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
==============
Sale Quotation
==============

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:0972668718c1f94591e5cdf8b6a106e4a752d2e8df38a9cbde31bccb14970115
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Production%2FStable-green.png
:target: https://odoo-community.org/page/development-status
:alt: Production/Stable
.. |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/16.0/sale_quotation
:alt: shopinvader/odoo-shopinvader

|badge1| |badge2| |badge3|

This module is used in the context of e-commerce project (like shopinvader)


It allows to specify whether your product requires a quotation.
This can be set per "product.template" or per "product.variant"


For example, you have a product where the supplier price fluctuates a lot,
you can not give a public price but your customer should be able to request a quotation.

.. image:: https://raw.githubusercontent.com/shopinvader/odoo-shopinvader/16.0/sale_quotation/static/description/product.png
:width: 400px
:alt: Widget in action



On your shopinvader website when a customer has added a product that requires a quotation,
instead of validating the cart it will "request a quotation".



On Odoo Backoffice the menu quotation has been improved and a new state (quotation_state) has been added.
So you can easily process and follow the quotation request from your external system.

.. image:: https://raw.githubusercontent.com/shopinvader/odoo-shopinvader/16.0/sale_quotation/static/description/quotation.png
:width: 400px
:alt: Widget in action


**Table of contents**

.. contents::
:local:

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/shopinvader/odoo-shopinvader/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 <https://github.com/shopinvader/odoo-shopinvader/issues/new?body=module:%20sale_quotation%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

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

Credits
=======

Authors
~~~~~~~

* Akretion

Contributors
~~~~~~~~~~~~

* Sebastien BEAU <[email protected]>
* Benoît GUILLOT <[email protected]>
* Matthieu Saison <[email protected]>
* Iván Todorovich <[email protected]>
* Simone Orsi <[email protected]>

Maintainers
~~~~~~~~~~~

This module is part of the `shopinvader/odoo-shopinvader <https://github.com/shopinvader/odoo-shopinvader/tree/16.0/sale_quotation>`_ project on GitHub.

You are welcome to contribute.
1 change: 1 addition & 0 deletions sale_quotation/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
19 changes: 19 additions & 0 deletions sale_quotation/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2018 Akretion (http://www.akretion.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

{
"name": "Sale Quotation",
"summary": "Sale Quotation",
"version": "16.0.0.1.0",
"category": "e-commerce",
"development_status": "Production/Stable",
"website": "https://github.com/shopinvader/odoo-shopinvader",
"author": "Akretion",
"license": "AGPL-3",
"depends": ["sale_cart"],
"data": [
"views/product_view.xml",
"views/sale_view.xml",
],
"installable": True,
}
3 changes: 3 additions & 0 deletions sale_quotation/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import product_product
from . import product_template
from . import sale_order
51 changes: 51 additions & 0 deletions sale_quotation/models/product_template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright 2017-2018 Akretion (http://www.akretion.com).
# Copyright 2021 Camptocamp (https://www.camptocamp.com).
# @author Benoît GUILLOT <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import api, fields, models


class ProductTemplate(models.Model):
_inherit = "product.template"

shop_only_quotation = fields.Selection(
selection=[
("all_variant", "All Variant"),
("manually_on_variant", "Manually on Variant"),
("never", "Never"),
],
string="Shopinvader: Only for Quotation",
compute="_compute_shop_only_quotation",
inverse="_inverse_shop_only_quotation",
store=True,
)

@api.depends("product_variant_ids.shop_only_quotation")
def _compute_shop_only_quotation(self):
# True only if true for all its variants
for rec in self:
if not rec.product_variant_ids or not any(
rec.product_variant_ids.mapped("shop_only_quotation")
):
rec.shop_only_quotation = "never"
elif all(rec.product_variant_ids.mapped("shop_only_quotation")):
rec.shop_only_quotation = "all_variant"
elif any(rec.product_variant_ids.mapped("shop_only_quotation")):
rec.shop_only_quotation = "manually_on_variant"

def _inverse_shop_only_quotation(self):
# Sets the value on all its variants
for rec in self:
if rec.shop_only_quotation == "all_variant":
rec.product_variant_ids.shop_only_quotation = True
elif rec.shop_only_quotation == "never":
rec.product_variant_ids.shop_only_quotation = False

def _create_variant_ids(self):
# Make sure new variants have the same value than the template.
res = super()._create_variant_ids()
for rec in self:
if rec.shop_only_quotation == "all_variant":
rec.product_variant_ids.shop_only_quotation = True
return res
66 changes: 66 additions & 0 deletions sale_quotation/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Copyright 2017-2018 Akretion (http://www.akretion.com).
# Copyright 2021 Camptocamp (http://www.camptocamp.com)
# @author Benoît GUILLOT <[email protected]>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).


from odoo import _, api, fields, models
from odoo.exceptions import UserError


class SaleOrder(models.Model):
_inherit = "sale.order"

quotation_state = fields.Selection(
selection=[
("cancel", "Cancel"),
("draft", "Draft"),
("customer_request", "Customer Request"),
("waiting_acceptation", "Waiting Acceptation"),
("accepted", "Accepted"),
],
compute="_compute_quotation_state",
store=True,
readonly=False,
)
shop_only_quotation = fields.Boolean(compute="_compute_shop_only_quotation")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only quotation is too restrictive. A product could be only available

  • on quotation
  • on quotation and direct sale
  • on direct sale
    Sometimes, you could request a quotation for a set of products in order to get a better price due to the amount total of your order.


def _quotation_state_need_updated(self):
self.ensure_one()
return self.quotation_state not in [
"customer_request",
"waiting_acceptation",
"accepted",
]

@api.depends("state")
def _compute_quotation_state(self):
for record in self:
if record.state == "cancel":
record.quotation_state = "cancel"
elif record.state == "draft" and record._quotation_state_need_updated():
record.quotation_state = "draft"
elif record.state == "sent" and record._quotation_state_need_updated():
record.quotation_state = "waiting_acceptation"
elif record.state == "sale":
record.quotation_state = "accepted"

def action_request_quotation(self):
if any(rec.state != "draft" or rec.typology != "cart" for rec in self):
raise UserError(
_(
"Only orders of cart typology in draft state "
"can be converted to quotation"
)
)
self.write({"quotation_state": "customer_request", "typology": "sale"})
return True

def _compute_shop_only_quotation(self):
for record in self:
record.shop_only_quotation = any(
record.order_line.product_id.mapped("shop_only_quotation")
)

def action_confirm_quotation(self):
self.quotation_state = "accepted"
5 changes: 5 additions & 0 deletions sale_quotation/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
* Sebastien BEAU <[email protected]>
* Benoît GUILLOT <[email protected]>
* Matthieu Saison <[email protected]>
* Iván Todorovich <[email protected]>
* Simone Orsi <[email protected]>
28 changes: 28 additions & 0 deletions sale_quotation/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
This module is used in the context of e-commerce project (like shopinvader)


It allows to specify whether your product requires a quotation.
This can be set per "product.template" or per "product.variant"


For example, you have a product where the supplier price fluctuates a lot,
you can not give a public price but your customer should be able to request a quotation.

.. image:: ../static/description/product.png
:width: 400px
:alt: Widget in action



On your shopinvader website when a customer has added a product that requires a quotation,
instead of validating the cart it will "request a quotation".



On Odoo Backoffice the menu quotation has been improved and a new state (quotation_state) has been added.
So you can easily process and follow the quotation request from your external system.

.. image:: ../static/description/quotation.png
:width: 400px
:alt: Widget in action

Loading
Loading