Skip to content

Commit

Permalink
Merge PR OCA#334 into 14.0
Browse files Browse the repository at this point in the history
  • Loading branch information
nilshamerlinck committed Aug 13, 2021
2 parents 6877e28 + e36a882 commit dd48e57
Show file tree
Hide file tree
Showing 17 changed files with 889 additions and 0 deletions.
93 changes: 93 additions & 0 deletions delivery_carrier_pricelist/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
=========================
Shipping Method Pricelist
=========================

.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! 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-OCA%2Fdelivery--carrier-lightgray.png?logo=github
:target: https://github.com/OCA/delivery-carrier/tree/14.0/delivery_carrier_pricelist
:alt: OCA/delivery-carrier
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/delivery-carrier-14-0/delivery-carrier-14-0-delivery_carrier_pricelist
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/99/14.0
:alt: Try me on Runbot

|badge1| |badge2| |badge3| |badge4| |badge5|

Compute shipping methods fees based on Product Pricelists.

It allows to have different pricing per customer, prices depending on dates, ...
The pricelist based cost is computed from the shipping method's product and the
sales order's pricelist.

It supports the following use cases:

* When no "external" provider (e.g. DHL, UPS, ...) is used, a new provider
"Based on Product Pricelist" is available.
* When an external provider is used, a new option in the "Invoice Policy"
selection, named "Pricelist Cost", overrides the provider's cost by the
pricelist based cost.

**Table of contents**

.. contents::
:local:

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

Bugs are tracked on `GitHub Issues <https://github.com/OCA/delivery-carrier/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 <https://github.com/OCA/delivery-carrier/issues/new?body=module:%20delivery_carrier_pricelist%0Aversion:%2014.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
~~~~~~~

* Camptocamp

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

* Guewen Baconnier <[email protected]>
* Phuc Tran Thanh <[email protected]>

Other credits
~~~~~~~~~~~~~

The development of this module has been financially supported by:

* Camptocamp

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

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

This module is part of the `OCA/delivery-carrier <https://github.com/OCA/delivery-carrier/tree/14.0/delivery_carrier_pricelist>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
2 changes: 2 additions & 0 deletions delivery_carrier_pricelist/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import models
from . import wizards
14 changes: 14 additions & 0 deletions delivery_carrier_pricelist/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright 2020 Camptocamp
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Shipping Method Pricelist",
"summary": "Compute method method fees based on the product's pricelist.",
"version": "14.0.1.0.0",
"category": "Delivery",
"website": "https://github.com/OCA/delivery-carrier",
"author": "Camptocamp, Odoo Community Association (OCA)",
"installable": True,
"license": "AGPL-3",
"depends": ["delivery"],
"data": ["security/ir.model.access.csv"],
}
2 changes: 2 additions & 0 deletions delivery_carrier_pricelist/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import delivery_carrier
from . import stock_picking
159 changes: 159 additions & 0 deletions delivery_carrier_pricelist/models/delivery_carrier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# Copyright 2020 Camptocamp
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from lxml import etree

from odoo import _, fields, models
from odoo.osv import expression
from odoo.tools.safe_eval import safe_eval

from odoo.addons.base.models.ir_ui_view import (
transfer_modifiers_to_node,
transfer_node_to_modifiers,
)


class DeliveryCarrier(models.Model):
_inherit = "delivery.carrier"

delivery_type = fields.Selection(
selection_add=[("pricelist", "Based on Product Pricelist")],
ondelete={"pricelist": "set default"},
)
invoice_policy = fields.Selection(
selection_add=[("pricelist", "Pricelist Cost")],
ondelete={"pricelist": "set default"},
help="Estimated Cost: the customer will be invoiced the estimated"
" cost of the shipping.\n"
"Real Cost: the customer will be invoiced the real cost of the"
" shipping, the cost of the shipping will be updated on the"
" SO after the delivery.\n"
"Pricelist Cost: the customer will be invoiced the price of the "
"product based on the pricelist of the sales order. The provider's "
"cost is ignored.",
)

def rate_shipment(self, order):
if self.invoice_policy == "pricelist":
current_type = self.delivery_type
# force computation from pricelist when the invoicing policy says
# so
self.delivery_type = "pricelist"
result = super().rate_shipment(order)
self.delivery_type = current_type
return result
else:
return super().rate_shipment(order)

def send_shipping(self, pickings):
result = super().send_shipping(pickings)
if self.invoice_policy == "pricelist":
# force computation from pricelist when the invoicing policy says
# so
rates = self.pricelist_send_shipping(pickings)
for index, rate in enumerate(rates):
result[index]["exact_price"] = rate["exact_price"]
return result

def _pricelist_get_price(self, order):
product = self.product_id.with_context(
pricelist=order.pricelist_id.id,
partner=order.partner_id,
quantity=1,
date=order.date_order,
uom=self.product_id.uom_id.id,
)
price = order.currency_id._convert(
product.price,
order.company_id.currency_id,
order.company_id,
order.date_order or fields.Date.today(),
)
return price

def pricelist_rate_shipment(self, order):
carrier = self._match_address(order.partner_shipping_id)
if not carrier:
return {
"success": False,
"price": 0.0,
"error_message": _(
"Error: this delivery method is not available for this address."
),
"warning_message": False,
}
price = self._pricelist_get_price(order)
return {
"success": True,
"price": price,
"error_message": False,
"warning_message": False,
}

def pricelist_send_shipping(self, pickings):
res = []
for picking in pickings:
carrier = picking.carrier_id
sale = picking.sale_id
price = carrier._pricelist_get_price(sale) if sale else 0.0
res = res + [{"exact_price": price, "tracking_number": False}]
return res

def pricelist_get_tracking_link(self, picking):
return False

def pricelist_cancel_shipment(self, pickings):
raise NotImplementedError()

def fields_view_get(
self, view_id=None, view_type="form", toolbar=False, submenu=False
):
result = super().fields_view_get(
view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu
)
if result["name"] == "delivery.carrier.form":
result["arch"] = self._fields_view_get_adapt_attrs(result["arch"])
return result

def _add_pricelist_domain(
self,
doc,
xpath_expr,
attrs_key,
domain_operator=expression.OR,
field_operator="=",
):
"""Add the delivery type domain for 'pricelist' in attrs"""
nodes = doc.xpath(xpath_expr)
for field in nodes:
attrs = safe_eval(field.attrib.get("attrs", "{}"))
if not attrs[attrs_key]:
continue

invisible_domain = domain_operator(
[attrs[attrs_key], [("delivery_type", field_operator, "pricelist")]]
)
attrs[attrs_key] = invisible_domain
field.set("attrs", str(attrs))
modifiers = {}
transfer_node_to_modifiers(
field, modifiers, self.env.context, current_node_path=["tree"]
)
transfer_modifiers_to_node(modifiers, field)

def _fields_view_get_adapt_attrs(self, view_arch):
"""Adapt the attrs of elements in the view with 'pricelist' delivery type"""
doc = etree.XML(view_arch)
# hide all these fields and buttons for delivery providers which have already
# an attrs with a domain we can't extend...
self._add_pricelist_domain(
doc, "//button[@name='toggle_prod_environment']", "invisible"
)
self._add_pricelist_domain(doc, "//button[@name='toggle_debug']", "invisible")
self._add_pricelist_domain(
doc, "//field[@name='integration_level']", "invisible"
)
self._add_pricelist_domain(doc, "//field[@name='invoice_policy']", "invisible")

new_view = etree.tostring(doc, encoding="unicode")
return new_view
39 changes: 39 additions & 0 deletions delivery_carrier_pricelist/models/stock_picking.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright 2020 Camptocamp
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from lxml import etree

from odoo import models
from odoo.osv import expression


class StockPicking(models.Model):
_inherit = "stock.picking"

def fields_view_get(
self, view_id=None, view_type="form", toolbar=False, submenu=False
):
result = super().fields_view_get(
view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu
)
if result.get("name") == "stock.picking.form":
result["arch"] = self._fields_view_get_adapt_attrs(result["arch"])
return result

def _fields_view_get_adapt_attrs(self, view_arch):
doc = etree.XML(view_arch)
# hide all these fields and buttons for delivery providers which have already
# an attrs with a domain we can't extend...
self.env["delivery.carrier"]._add_pricelist_domain(
doc, "//button[@name='cancel_shipment']", "invisible"
)
self.env["delivery.carrier"]._add_pricelist_domain(
doc, "//button[@name='send_to_shipper']", "invisible"
)
self.env["delivery.carrier"]._add_pricelist_domain(
doc,
"//field[@name='partner_id']",
"required",
domain_operator=expression.AND,
field_operator="!=",
)
return etree.tostring(doc, encoding="unicode")
2 changes: 2 additions & 0 deletions delivery_carrier_pricelist/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Guewen Baconnier <[email protected]>
* Phuc Tran Thanh <[email protected]>
3 changes: 3 additions & 0 deletions delivery_carrier_pricelist/readme/CREDITS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The development of this module has been financially supported by:

* Camptocamp
13 changes: 13 additions & 0 deletions delivery_carrier_pricelist/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Compute shipping methods fees based on Product Pricelists.

It allows to have different pricing per customer, prices depending on dates, ...
The pricelist based cost is computed from the shipping method's product and the
sales order's pricelist.

It supports the following use cases:

* When no "external" provider (e.g. DHL, UPS, ...) is used, a new provider
"Based on Product Pricelist" is available.
* When an external provider is used, a new option in the "Invoice Policy"
selection, named "Pricelist Cost", overrides the provider's cost by the
pricelist based cost.
2 changes: 2 additions & 0 deletions delivery_carrier_pricelist/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_choose_delivery_carrier,choose.delivery.carrier.user,model_choose_delivery_carrier,stock.group_stock_user,1,1,1,1
Loading

0 comments on commit dd48e57

Please sign in to comment.