Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 775a6a9

Browse files
committedMay 29, 2024·
Merge PR #1559 into 16.0
Signed-off-by pedrobaeza
2 parents 89e7fa2 + 5731d17 commit 775a6a9

19 files changed

+917
-0
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../stock_landed_costs_delivery
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import setuptools
2+
3+
setuptools.setup(
4+
setup_requires=['setuptools-odoo'],
5+
odoo_addon=True,
6+
)
+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
===========================
2+
Stock landed costs delivery
3+
===========================
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:a1ff3f74ed89cad18c0fd8fe165e2930769f00e48c602cf148cfe5fb6095b395
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Beta
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
18+
:alt: License: AGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstock--logistics--workflow-lightgray.png?logo=github
20+
:target: https://github.com/OCA/stock-logistics-workflow/tree/16.0/stock_landed_costs_delivery
21+
:alt: OCA/stock-logistics-workflow
22+
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
23+
:target: https://translation.odoo-community.org/projects/stock-logistics-workflow-16-0/stock-logistics-workflow-16-0-stock_landed_costs_delivery
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/stock-logistics-workflow&target_branch=16.0
27+
:alt: Try me on Runboat
28+
29+
|badge1| |badge2| |badge3| |badge4| |badge5|
30+
31+
This addon adds a cost line with the carrier of the purchase order and the price.
32+
33+
**Table of contents**
34+
35+
.. contents::
36+
:local:
37+
38+
Usage
39+
=====
40+
41+
#. Go to Inventory > Configuration > Shipping methods
42+
#. Create a record with Allow create landed cost lines option checked.
43+
#. Go to Purchase > Orders > Requests for Quotation.
44+
#. Create an order with 2 lines: storable product + service product (landed cost).
45+
#. Set Custom carrier.
46+
#. Confirm Order.
47+
#. Receives products and done picking.
48+
#. Go to Inventory > Operations > Landed Costs.
49+
#. A record related to the delivery purchase order lines and a cost line was created with the shipping price.
50+
#. Landed Cost will be validated when linked purchase picking are done.
51+
52+
Bug Tracker
53+
===========
54+
55+
Bugs are tracked on `GitHub Issues <https://github.com/OCA/stock-logistics-workflow/issues>`_.
56+
In case of trouble, please check there if your issue has already been reported.
57+
If you spotted it first, help us to smash it by providing a detailed and welcomed
58+
`feedback <https://github.com/OCA/stock-logistics-workflow/issues/new?body=module:%20stock_landed_costs_delivery%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
59+
60+
Do not contact contributors directly about support or help with technical issues.
61+
62+
Credits
63+
=======
64+
65+
Authors
66+
~~~~~~~
67+
68+
* Tecnativa
69+
70+
Contributors
71+
~~~~~~~~~~~~
72+
73+
* `Tecnativa <https://www.tecnativa.com>`_
74+
75+
* Pedro M. Baeza
76+
* Víctor Martínez
77+
* Carolina Fernandez
78+
79+
Maintainers
80+
~~~~~~~~~~~
81+
82+
This module is maintained by the OCA.
83+
84+
.. image:: https://odoo-community.org/logo.png
85+
:alt: Odoo Community Association
86+
:target: https://odoo-community.org
87+
88+
OCA, or the Odoo Community Association, is a nonprofit organization whose
89+
mission is to support the collaborative development of Odoo features and
90+
promote its widespread use.
91+
92+
.. |maintainer-victoralmau| image:: https://github.com/victoralmau.png?size=40px
93+
:target: https://github.com/victoralmau
94+
:alt: victoralmau
95+
96+
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
97+
98+
|maintainer-victoralmau|
99+
100+
This module is part of the `OCA/stock-logistics-workflow <https://github.com/OCA/stock-logistics-workflow/tree/16.0/stock_landed_costs_delivery>`_ project on GitHub.
101+
102+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import models
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2021 Tecnativa - Víctor Martínez
2+
# Copyright 2024 Tecnativa - Carolina Fernandez
3+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
4+
{
5+
"name": "Stock landed costs delivery",
6+
"version": "16.0.1.0.0",
7+
"category": "Inventory",
8+
"website": "https://github.com/OCA/stock-logistics-workflow",
9+
"author": "Tecnativa, Odoo Community Association (OCA)",
10+
"license": "AGPL-3",
11+
"depends": ["delivery_purchase", "stock_landed_costs_purchase_auto"],
12+
"data": ["views/delivery_carrier_view.xml"],
13+
"installable": True,
14+
"maintainers": ["victoralmau"],
15+
}
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Translation of Odoo Server.
2+
# This file contains the translation of the following modules:
3+
# * stock_landed_costs_delivery
4+
#
5+
msgid ""
6+
msgstr ""
7+
"Project-Id-Version: Odoo Server 15.0\n"
8+
"Report-Msgid-Bugs-To: \n"
9+
"PO-Revision-Date: 2023-12-19 15:37+0000\n"
10+
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
11+
"Language-Team: none\n"
12+
"Language: it\n"
13+
"MIME-Version: 1.0\n"
14+
"Content-Type: text/plain; charset=UTF-8\n"
15+
"Content-Transfer-Encoding: \n"
16+
"Plural-Forms: nplurals=2; plural=n != 1;\n"
17+
"X-Generator: Weblate 4.17\n"
18+
19+
#. module: stock_landed_costs_delivery
20+
#: model:ir.model.fields,field_description:stock_landed_costs_delivery.field_delivery_carrier__create_landed_cost_line
21+
msgid "Allow create landed cost lines"
22+
msgstr "Consente creazione righe costi accessori"
23+
24+
#. module: stock_landed_costs_delivery
25+
#: model:ir.model,name:stock_landed_costs_delivery.model_purchase_order
26+
msgid "Purchase Order"
27+
msgstr "Ordine di acquisto"
28+
29+
#. module: stock_landed_costs_delivery
30+
#: model:ir.model,name:stock_landed_costs_delivery.model_delivery_carrier
31+
msgid "Shipping Methods"
32+
msgstr "Metodi di spedizione"
33+
34+
#. module: stock_landed_costs_delivery
35+
#: model:ir.model.fields,field_description:stock_landed_costs_delivery.field_delivery_carrier__split_method_landed_cost_line
36+
msgid "Split method"
37+
msgstr "Metodo di divisione"
38+
39+
#. module: stock_landed_costs_delivery
40+
#: model:ir.model.fields,help:stock_landed_costs_delivery.field_delivery_carrier__split_method_landed_cost_line
41+
msgid "Split method used in landed cost lines"
42+
msgstr "Metodo di divisione utilizzato nelle righe costi accessori"
43+
44+
#. module: stock_landed_costs_delivery
45+
#: model:ir.model,name:stock_landed_costs_delivery.model_stock_picking
46+
msgid "Transfer"
47+
msgstr "Trasferimento"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Translation of Odoo Server.
2+
# This file contains the translation of the following modules:
3+
# * stock_landed_costs_delivery
4+
#
5+
msgid ""
6+
msgstr ""
7+
"Project-Id-Version: Odoo Server 15.0\n"
8+
"Report-Msgid-Bugs-To: \n"
9+
"Last-Translator: \n"
10+
"Language-Team: \n"
11+
"MIME-Version: 1.0\n"
12+
"Content-Type: text/plain; charset=UTF-8\n"
13+
"Content-Transfer-Encoding: \n"
14+
"Plural-Forms: \n"
15+
16+
#. module: stock_landed_costs_delivery
17+
#: model:ir.model.fields,field_description:stock_landed_costs_delivery.field_delivery_carrier__create_landed_cost_line
18+
msgid "Allow create landed cost lines"
19+
msgstr ""
20+
21+
#. module: stock_landed_costs_delivery
22+
#: model:ir.model,name:stock_landed_costs_delivery.model_purchase_order
23+
msgid "Purchase Order"
24+
msgstr ""
25+
26+
#. module: stock_landed_costs_delivery
27+
#: model:ir.model,name:stock_landed_costs_delivery.model_delivery_carrier
28+
msgid "Shipping Methods"
29+
msgstr ""
30+
31+
#. module: stock_landed_costs_delivery
32+
#: model:ir.model.fields,field_description:stock_landed_costs_delivery.field_delivery_carrier__split_method_landed_cost_line
33+
msgid "Split method"
34+
msgstr ""
35+
36+
#. module: stock_landed_costs_delivery
37+
#: model:ir.model.fields,help:stock_landed_costs_delivery.field_delivery_carrier__split_method_landed_cost_line
38+
msgid "Split method used in landed cost lines"
39+
msgstr ""
40+
41+
#. module: stock_landed_costs_delivery
42+
#: model:ir.model,name:stock_landed_costs_delivery.model_stock_picking
43+
msgid "Transfer"
44+
msgstr ""
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
2+
from . import delivery_carrier
3+
from . import purchase_order
4+
from . import stock_picking
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright 2021 Tecnativa - Víctor Martínez
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
from odoo import api, fields, models
4+
5+
6+
class DeliveryCarrier(models.Model):
7+
_inherit = "delivery.carrier"
8+
9+
@api.model
10+
def _get_selection_split_method_landed_cost_line(self):
11+
model = self.env["stock.landed.cost.lines"]
12+
return model.fields_get(allfields=["split_method"])["split_method"]["selection"]
13+
14+
create_landed_cost_line = fields.Boolean(
15+
string="Allow create landed cost lines", default=True
16+
)
17+
split_method_landed_cost_line = fields.Selection(
18+
selection="_get_selection_split_method_landed_cost_line",
19+
string="Split method",
20+
default="by_quantity",
21+
help="Split method used in landed cost lines",
22+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Copyright 2021-2024 Tecnativa - Víctor Martínez
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
from odoo import models
4+
5+
6+
class PurchaseOrder(models.Model):
7+
_inherit = "purchase.order"
8+
9+
def _prepare_landed_cost_line_delivery_values(self, carrier, price_unit):
10+
return {
11+
"product_id": carrier.product_id.id,
12+
"name": carrier.name,
13+
"price_unit": price_unit,
14+
"split_method": carrier.split_method_landed_cost_line,
15+
}
16+
17+
def _create_delivery_line(self, carrier, price_unit):
18+
"""Auto-add delivery line to first draft Landed cost.
19+
We need to add the line to the first Landed cost due to the process:
20+
1- A new landed cost is created, if applicable (backorder).
21+
2- The _create_delivery_line() method is called."""
22+
res = super()._create_delivery_line(carrier=carrier, price_unit=price_unit)
23+
if carrier.create_landed_cost_line:
24+
vals = self._prepare_landed_cost_line_delivery_values(carrier, price_unit)
25+
lc = self.sudo().landed_cost_ids.filtered(lambda x: x.state == "draft")
26+
# Use the context to identify which picking is being generated from and
27+
# set cost lines in the correct Landed cost.
28+
if self.env.context.get("from_picking"):
29+
picking = self.env.context.get("from_picking")
30+
lc = lc.filtered(lambda x: picking in x.picking_ids)
31+
if lc:
32+
lc[0].cost_lines = [(0, 0, vals)]
33+
return res
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Copyright 2023-2024 Tecnativa - Víctor Martínez
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
from odoo import models
4+
from odoo.tools import config
5+
6+
7+
class StockPicking(models.Model):
8+
_inherit = "stock.picking"
9+
10+
def _add_delivery_cost_to_po(self):
11+
"""We add the context to identify in _create_delivery_line() method the picking."""
12+
self.ensure_one()
13+
self = self.with_context(from_picking=self)
14+
return super()._add_delivery_cost_to_po()
15+
16+
def _action_done(self):
17+
"""Validate Landed costs linked to the purchase and picking."""
18+
res = super()._action_done()
19+
if not config["test_enable"] or self.env.context.get(
20+
"test_stock_landed_costs_delivery"
21+
):
22+
for item in self:
23+
landed_cost = item.purchase_id.sudo().landed_cost_ids.filtered(
24+
lambda x: item in x.picking_ids
25+
and x.state == "draft"
26+
and x.cost_lines
27+
)
28+
if landed_cost:
29+
landed_cost.button_validate()
30+
return res
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
* `Tecnativa <https://www.tecnativa.com>`_
2+
3+
* Pedro M. Baeza
4+
* Víctor Martínez
5+
* Carolina Fernandez
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This addon adds a cost line with the carrier of the purchase order and the price.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#. Go to Inventory > Configuration > Shipping methods
2+
#. Create a record with Allow create landed cost lines option checked.
3+
#. Go to Purchase > Orders > Requests for Quotation.
4+
#. Create an order with 2 lines: storable product + service product (landed cost).
5+
#. Set Custom carrier.
6+
#. Confirm Order.
7+
#. Receives products and done picking.
8+
#. Go to Inventory > Operations > Landed Costs.
9+
#. A record related to the delivery purchase order lines and a cost line was created with the shipping price.
10+
#. Landed Cost will be validated when linked purchase picking are done.
Loading

‎stock_landed_costs_delivery/static/description/index.html

+443
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
2+
3+
from . import test_purchase_order
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Copyright 2021-2024 Tecnativa - Víctor Martínez
2+
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
3+
4+
from odoo.tests.common import users
5+
6+
from odoo.addons.stock_landed_costs_purchase_auto.tests.common import (
7+
TestPurchaseOrderBase,
8+
)
9+
10+
11+
class TestPurchaseOrder(TestPurchaseOrderBase):
12+
@classmethod
13+
def setUpClass(cls):
14+
super().setUpClass()
15+
cls.env = cls.env(
16+
context=dict(
17+
cls.env.context,
18+
test_stock_landed_costs_delivery=True,
19+
)
20+
)
21+
product_carrier = cls.env["product.product"].create(
22+
{"name": "Carrier", "type": "service", "categ_id": cls.category.id}
23+
)
24+
cls.carrier = cls.env["delivery.carrier"].create(
25+
{
26+
"name": "Test carrier",
27+
"product_id": product_carrier.id,
28+
"fixed_price": 10,
29+
}
30+
)
31+
cls.order.carrier_id = cls.carrier
32+
cls.purchase_user.write(
33+
{"groups_id": [(4, cls.env.ref("stock.group_stock_user").id)]}
34+
)
35+
36+
@users("test_purchase_user")
37+
def test_order_with_lc_basic_user(self):
38+
self.order = self.order.with_user(self.env.user)
39+
self.order.button_confirm()
40+
lc = self.order.landed_cost_ids
41+
self.assertTrue(lc.state, "draft")
42+
picking = self.order.picking_ids
43+
self._action_picking_validate(picking)
44+
self.assertTrue(lc.state, "done")
45+
46+
def test_order_with_lc_carrier_id(self):
47+
self.order.button_confirm()
48+
picking = self.order.picking_ids
49+
lc = self.order.landed_cost_ids
50+
self.assertEqual(len(lc.cost_lines), 0)
51+
self.assertEqual(lc.state, "draft")
52+
self._action_picking_validate(picking)
53+
self.assertEqual(len(lc.cost_lines), 1)
54+
self.assertEqual(lc.state, "done")
55+
self.assertIn(self.carrier.product_id, lc.cost_lines.mapped("product_id"))
56+
lc_cost_line = lc.cost_lines.filtered(
57+
lambda x: x.product_id == self.carrier.product_id
58+
)
59+
self.assertEqual(lc_cost_line.price_unit, 10)
60+
self.assertEqual(
61+
lc_cost_line.split_method, self.carrier.split_method_landed_cost_line
62+
)
63+
64+
def test_order_with_lc_carrier_id_multi_01(self):
65+
"""Order > Carrier. Picking 1 > Carrier. Picking 2 > Carrier."""
66+
self.order.order_line.product_qty = 2
67+
self.order.button_confirm()
68+
picking = self.order.picking_ids
69+
self.assertEqual(len(self.order.landed_cost_ids), 1)
70+
lc = self.order.landed_cost_ids
71+
self.assertEqual(len(lc.cost_lines), 0)
72+
self.assertEqual(lc.state, "draft")
73+
for move in picking.move_ids_without_package:
74+
move.quantity_done = 1
75+
self._action_picking_validate(picking)
76+
self.assertEqual(len(self.order.landed_cost_ids), 2)
77+
extra_lc = self.order.landed_cost_ids - lc
78+
self.assertEqual(len(lc.cost_lines), 1)
79+
self.assertEqual(lc.state, "done")
80+
self.assertEqual(extra_lc.state, "draft")
81+
self.assertEqual(lc.cost_lines.price_unit, 10)
82+
new_picking = self.order.picking_ids - picking
83+
self._action_picking_validate(new_picking)
84+
self.assertEqual(len(extra_lc.cost_lines), 1)
85+
self.assertEqual(extra_lc.state, "done")
86+
self.assertEqual(self.carrier.product_id, extra_lc.cost_lines.product_id)
87+
self.assertEqual(extra_lc.cost_lines.price_unit, 10)
88+
self.assertEqual(
89+
self.carrier.split_method_landed_cost_line,
90+
extra_lc.cost_lines.split_method,
91+
)
92+
93+
def test_order_with_lc_carrier_id_multi_02(self):
94+
"""Order > No Carrier. Picking 1 > No Carrier. Picking 2 > Carrier."""
95+
self.order.carrier_id = False
96+
self.order.order_line.product_qty = 2
97+
self.order.button_confirm()
98+
picking = self.order.picking_ids
99+
self.assertEqual(len(self.order.landed_cost_ids), 1)
100+
lc = self.order.landed_cost_ids
101+
self.assertEqual(len(lc.cost_lines), 0)
102+
self.assertEqual(lc.state, "draft")
103+
for move in picking.move_ids_without_package:
104+
move.quantity_done = 1
105+
self._action_picking_validate(picking)
106+
# Picking without carrier and LC without cost lines and draft state
107+
self.assertFalse(picking.carrier_id)
108+
self.assertEqual(len(self.order.landed_cost_ids), 2)
109+
extra_lc = self.order.landed_cost_ids - lc
110+
self.assertEqual(len(lc.cost_lines), 0)
111+
self.assertEqual(lc.state, "draft")
112+
self.assertEqual(extra_lc.state, "draft")
113+
new_picking = self.order.picking_ids - picking
114+
new_picking.carrier_id = self.carrier
115+
self._action_picking_validate(new_picking)
116+
# Order with carrier, delivery price and delivery line
117+
self.assertEqual(self.order.carrier_id, self.carrier)
118+
self.assertEqual(self.order.delivery_price, 10)
119+
self.assertEqual(
120+
len(self.order.order_line.filtered(lambda x: x.is_delivery)), 1
121+
)
122+
# LC keep draft state
123+
self.assertEqual(lc.state, "draft")
124+
# Extra LC done (cost line from delivery)
125+
self.assertEqual(len(extra_lc.cost_lines), 1)
126+
self.assertEqual(extra_lc.state, "done")
127+
self.assertEqual(self.carrier.product_id, extra_lc.cost_lines.product_id)
128+
self.assertEqual(extra_lc.cost_lines.price_unit, 10)
129+
self.assertEqual(
130+
self.carrier.split_method_landed_cost_line,
131+
extra_lc.cost_lines.split_method,
132+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<!-- Copyright 2021 Tecnativa - Víctor Martínez
3+
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
4+
<odoo>
5+
<record id="view_delivery_carrier_form" model="ir.ui.view">
6+
<field name="model">delivery.carrier</field>
7+
<field name="inherit_id" ref="delivery.view_delivery_carrier_form" />
8+
<field name="arch" type="xml">
9+
<field name="integration_level" position="after">
10+
<field name="create_landed_cost_line" />
11+
<field
12+
name="split_method_landed_cost_line"
13+
attrs="{'invisible': [('create_landed_cost_line', '=', False)]}"
14+
/>
15+
</field>
16+
</field>
17+
</record>
18+
</odoo>

0 commit comments

Comments
 (0)
Please sign in to comment.