Skip to content

Commit e7bb010

Browse files
committed
[ADD] delivery_fee: new module
MT-13311
1 parent a2ef455 commit e7bb010

File tree

19 files changed

+830
-0
lines changed

19 files changed

+830
-0
lines changed

delivery_fee/README.rst

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
============
2+
Delivery Fee
3+
============
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:4c253e6785c07c573bd715e0dc0f06ddeb3e4da298b98b0b91be2e180f50ff69
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Alpha
16+
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
18+
:alt: License: LGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fdelivery--carrier-lightgray.png?logo=github
20+
:target: https://github.com/OCA/delivery-carrier/tree/16.0/delivery_fee
21+
:alt: OCA/delivery-carrier
22+
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
23+
:target: https://translation.odoo-community.org/projects/delivery-carrier-16-0/delivery-carrier-16-0-delivery_fee
24+
:alt: Translate me on Weblate
25+
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
26+
:target: https://runboat.odoo-community.org/builds?repo=OCA/delivery-carrier&target_branch=16.0
27+
:alt: Try me on Runboat
28+
29+
|badge1| |badge2| |badge3| |badge4| |badge5|
30+
31+
This module enables you to add delivery fees independently of regular
32+
shipping charges. These fees are invoiced separately and may have
33+
different tax implications.
34+
35+
.. IMPORTANT::
36+
This is an alpha version, the data model and design can change at any time without warning.
37+
Only for development or testing purpose, do not use in production.
38+
`More details on development status <https://odoo-community.org/page/development-status>`_
39+
40+
**Table of contents**
41+
42+
.. contents::
43+
:local:
44+
45+
Configuration
46+
=============
47+
48+
49+
50+
Usage
51+
=====
52+
53+
Once you configured you delivery fees setup, you can start applying
54+
them.
55+
56+
1. Place a new sales order.
57+
2. Choose a delivery method with delivery fees.
58+
3. Confirm the order.
59+
4. Deliver the products.
60+
5. Once the delivery picking is done, the delivey fees line will be
61+
added to the sale.
62+
6. In the delivery slip, a message will be printed advising about these
63+
extra charges.
64+
7. When the fees are invoiced, the same advicing message will be printed
65+
in the printed invoice as well.
66+
67+
Bug Tracker
68+
===========
69+
70+
Bugs are tracked on `GitHub Issues <https://github.com/OCA/delivery-carrier/issues>`_.
71+
In case of trouble, please check there if your issue has already been reported.
72+
If you spotted it first, help us to smash it by providing a detailed and welcomed
73+
`feedback <https://github.com/OCA/delivery-carrier/issues/new?body=module:%20delivery_fee%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
74+
75+
Do not contact contributors directly about support or help with technical issues.
76+
77+
Credits
78+
=======
79+
80+
Authors
81+
-------
82+
83+
* Moduon
84+
85+
Contributors
86+
------------
87+
88+
- David Vidal (`Moduon <https://www.moduon.team/>`__)
89+
- Emilio Pascual (`Moduon <https://www.moduon.team/>`__)
90+
- Rafael Blasco (`Moduon <https://www.moduon.team/>`__)
91+
92+
Maintainers
93+
-----------
94+
95+
This module is maintained by the OCA.
96+
97+
.. image:: https://odoo-community.org/logo.png
98+
:alt: Odoo Community Association
99+
:target: https://odoo-community.org
100+
101+
OCA, or the Odoo Community Association, is a nonprofit organization whose
102+
mission is to support the collaborative development of Odoo features and
103+
promote its widespread use.
104+
105+
.. |maintainer-chienandalu| image:: https://github.com/chienandalu.png?size=40px
106+
:target: https://github.com/chienandalu
107+
:alt: chienandalu
108+
.. |maintainer-rafaelbn| image:: https://github.com/rafaelbn.png?size=40px
109+
:target: https://github.com/rafaelbn
110+
:alt: rafaelbn
111+
112+
Current `maintainers <https://odoo-community.org/page/maintainer-role>`__:
113+
114+
|maintainer-chienandalu| |maintainer-rafaelbn|
115+
116+
This module is part of the `OCA/delivery-carrier <https://github.com/OCA/delivery-carrier/tree/16.0/delivery_fee>`_ project on GitHub.
117+
118+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

delivery_fee/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models

delivery_fee/__manifest__.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Copyright 2026 Moduon
2+
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
3+
{
4+
"name": "Delivery Fee",
5+
"summary": "Charge extra fees on deliveries",
6+
"version": "16.0.1.0.0",
7+
"development_status": "Alpha",
8+
"category": "Inventory/Delivery",
9+
"author": "Moduon, Odoo Community Association (OCA)",
10+
"website": "https://github.com/OCA/delivery-carrier",
11+
"maintainers": ["chienandalu", "rafaelbn"],
12+
"license": "LGPL-3",
13+
"depends": ["delivery"],
14+
"data": [
15+
"views/res_partner_views.xml",
16+
"views/delivery_carrier_views.xml",
17+
"reports/delivery_slip_report.xml",
18+
"reports/invoice_report.xml",
19+
],
20+
}

delivery_fee/models/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from . import delivery_carrier
2+
from . import res_partner
3+
from . import sale_order
4+
from . import stock_picking
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2026 Moduon
2+
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
3+
from odoo import fields, models
4+
5+
6+
class DeliveryCarrier(models.Model):
7+
_inherit = "delivery.carrier"
8+
9+
fee_product_id = fields.Many2one(
10+
comodel_name="product.product",
11+
ondelete="restrict",
12+
domain="[('type', '=', 'service')]",
13+
)

delivery_fee/models/res_partner.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright 2026 Moduon
2+
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
3+
from odoo import fields, models
4+
5+
6+
class ResPartner(models.Model):
7+
_inherit = "res.partner"
8+
9+
delivery_fee_exemption = fields.Boolean()

delivery_fee/models/sale_order.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Copyright 2026 Moduon
2+
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
3+
from odoo import api, fields, models
4+
5+
6+
class SaleOrder(models.Model):
7+
_inherit = "sale.order"
8+
9+
def _prepare_delivery_fee_line_vals(self, picking):
10+
# Based on core `_prepare_delivery_line_vals`
11+
carrier = picking.carrier_id
12+
context = {}
13+
if self.partner_id:
14+
# Set delivery detail in the customer language
15+
context["lang"] = self.partner_id.lang
16+
carrier = carrier.with_context(lang=self.partner_id.lang)
17+
# Apply fiscal position
18+
taxes = carrier.fee_product_id.taxes_id.filtered(
19+
lambda t: t.company_id.id == self.company_id.id
20+
)
21+
taxes_ids = taxes.ids
22+
if self.partner_id and self.fiscal_position_id:
23+
taxes_ids = self.fiscal_position_id.map_tax(taxes).ids
24+
# Create the sales order line
25+
so_description = (
26+
carrier.fee_product_id.description_sale
27+
or carrier.fee_product_id.display_name
28+
)
29+
so_description = f"{picking.name}: {so_description}"
30+
values = {
31+
"order_id": self.id,
32+
"name": so_description,
33+
"product_uom_qty": 1,
34+
"product_uom": carrier.fee_product_id.uom_id.id,
35+
"product_id": carrier.fee_product_id.id,
36+
"tax_id": [(6, 0, taxes_ids)],
37+
"price_unit": carrier.fee_product_id.list_price,
38+
"is_delivery_fee": True,
39+
}
40+
if self.order_line:
41+
values["sequence"] = self.order_line[-1].sequence + 1
42+
del context
43+
return values
44+
45+
def _create_delivery_fee_line(self, carrier):
46+
values = self._prepare_delivery_fee_line_vals(carrier)
47+
return self.env["sale.order.line"].sudo().create(values)
48+
49+
50+
class SaleOrderLine(models.Model):
51+
_inherit = "sale.order.line"
52+
53+
is_delivery_fee = fields.Boolean(string="Is a Delivery Fee", default=False)
54+
delivery_fee_picking_id = fields.Many2one(comodel_name="stock.picking")
55+
56+
def _is_not_sellable_line(self):
57+
return self.is_delivery_fee or super()._is_not_sellable_line()
58+
59+
def _compute_pricelist_item_id(self):
60+
delivery_fee_lines = self.filtered("is_delivery_fee")
61+
res = super(
62+
SaleOrderLine, self - delivery_fee_lines
63+
)._compute_pricelist_item_id()
64+
delivery_fee_lines.pricelist_item_id = False
65+
return res
66+
67+
@api.model_create_multi
68+
def create(self, vals_list):
69+
lines = super().create(vals_list)
70+
# Push fee lines to the bottom always
71+
# TODO: It'd be nice to have them in a section
72+
for order in lines.order_id:
73+
fee_lines = order.order_line.filtered("is_delivery_fee")
74+
last_sequence = order.order_line[-1].sequence
75+
for fee_line, increase in zip(fee_lines, range(1, len(fee_lines) + 1)):
76+
fee_line.sequence = last_sequence + increase
77+
return lines
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright 2026 Moduon
2+
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
3+
from odoo import models
4+
5+
6+
class StockPicking(models.Model):
7+
_inherit = "stock.picking"
8+
9+
def _add_delivery_cost_to_so(self):
10+
res = super()._add_delivery_cost_to_so()
11+
self._add_delivery_fee_to_order()
12+
return res
13+
14+
def _add_delivery_fee_to_order(self):
15+
if (
16+
not self.sale_id
17+
or self.partner_id.delivery_fee_exemption
18+
or not self.carrier_id.fee_product_id
19+
):
20+
return
21+
self.sale_id._create_delivery_fee_line(self)

delivery_fee/readme/CONFIGURE.md

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
- David Vidal ([Moduon](https://www.moduon.team/))
2+
- Emilio Pascual ([Moduon](https://www.moduon.team/))
3+
- Rafael Blasco ([Moduon](https://www.moduon.team/))

0 commit comments

Comments
 (0)