From d67358cec13cd49d808ec5902e4c5dfbf4923d07 Mon Sep 17 00:00:00 2001 From: Yannick Vaucher Date: Wed, 17 Dec 2014 13:24:39 +0100 Subject: [PATCH 01/17] [ADD] module sale_owner_stock_sourcing This modules allows to choose stock ownership on sale order line --- sale_owner_stock_sourcing/README.rst | 16 ++++++++ sale_owner_stock_sourcing/__init__.py | 2 + sale_owner_stock_sourcing/__openerp__.py | 39 +++++++++++++++++++ sale_owner_stock_sourcing/model/__init__.py | 2 + sale_owner_stock_sourcing/model/sale_order.py | 29 ++++++++++++++ sale_owner_stock_sourcing/view/sale_order.xml | 17 ++++++++ 6 files changed, 105 insertions(+) create mode 100644 sale_owner_stock_sourcing/README.rst create mode 100644 sale_owner_stock_sourcing/__init__.py create mode 100644 sale_owner_stock_sourcing/__openerp__.py create mode 100644 sale_owner_stock_sourcing/model/__init__.py create mode 100644 sale_owner_stock_sourcing/model/sale_order.py create mode 100644 sale_owner_stock_sourcing/view/sale_order.xml diff --git a/sale_owner_stock_sourcing/README.rst b/sale_owner_stock_sourcing/README.rst new file mode 100644 index 00000000000..5c11e3e5923 --- /dev/null +++ b/sale_owner_stock_sourcing/README.rst @@ -0,0 +1,16 @@ +Sale Owner Stock Sourcing +========================= + +This module allow you to choose for every sale order line the owner of the stock that will be dispatched. +By choosing an owner, the generated deliveries will then look for stock of the specified partner. +If no one is available, then the picking will be in waiting availability until stocks of the proper ownership +are replenished. + +Specifying an owner on a line, forces to use the stock of this owner. +Letting the owner empty allows to use stock (quant) without owner. + +Contributors +------------ + +* Yannick Vaucher + diff --git a/sale_owner_stock_sourcing/__init__.py b/sale_owner_stock_sourcing/__init__.py new file mode 100644 index 00000000000..f3fc39f7956 --- /dev/null +++ b/sale_owner_stock_sourcing/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import model diff --git a/sale_owner_stock_sourcing/__openerp__.py b/sale_owner_stock_sourcing/__openerp__.py new file mode 100644 index 00000000000..7ad1bcea579 --- /dev/null +++ b/sale_owner_stock_sourcing/__openerp__.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# +# +# Author: Yannick Vaucher +# Copyright 2014 Camptocamp SA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# +{"name": "Sale Owner Stock Sourcing", + "summary": "Manage stock ownership on sale order lines", + "version": "0.0.1", + "author": "Camptocamp", + "license": "AGPL-3", + "category": "Purchase Management", + 'complexity': "normal", + "images": [], + "website": "http://www.camptocamp.com", + "depends": ['sale_stock' + #'purchase_vendor_consignment_stock', + ], + "demo": [], + "data": ['view/sale_order.xml', + ], + "test": [ ], + 'installable': True, + "auto_install": False, + } diff --git a/sale_owner_stock_sourcing/model/__init__.py b/sale_owner_stock_sourcing/model/__init__.py new file mode 100644 index 00000000000..0226d7680c2 --- /dev/null +++ b/sale_owner_stock_sourcing/model/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import sale_order diff --git a/sale_owner_stock_sourcing/model/sale_order.py b/sale_owner_stock_sourcing/model/sale_order.py new file mode 100644 index 00000000000..374f91f4718 --- /dev/null +++ b/sale_owner_stock_sourcing/model/sale_order.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# +# +# Author: Yannick Vaucher +# Copyright 2014 Camptocamp SA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# +from openerp import models, fields + + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + stock_owner_id = fields.Many2one( + comodel_name='res.partner', + string='Stock Owner') diff --git a/sale_owner_stock_sourcing/view/sale_order.xml b/sale_owner_stock_sourcing/view/sale_order.xml new file mode 100644 index 00000000000..8a227d9718f --- /dev/null +++ b/sale_owner_stock_sourcing/view/sale_order.xml @@ -0,0 +1,17 @@ + + + + + + sale.order.form + sale.order + + + + + + + + + + From 77868058ec0dd1c0a65d4a025110e5b1e551c3ed Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Tue, 6 Jan 2015 16:44:29 +0100 Subject: [PATCH 02/17] propagate the owner from order line to stock move --- sale_owner_stock_sourcing/README.rst | 15 ++++--- sale_owner_stock_sourcing/__openerp__.py | 10 ++--- sale_owner_stock_sourcing/model/__init__.py | 1 + .../model/procurement.py | 28 ++++++++++++ sale_owner_stock_sourcing/tests/__init__.py | 1 + .../tests/test_propagate_owner_to_move.py | 44 +++++++++++++++++++ 6 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 sale_owner_stock_sourcing/model/procurement.py create mode 100644 sale_owner_stock_sourcing/tests/__init__.py create mode 100644 sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py diff --git a/sale_owner_stock_sourcing/README.rst b/sale_owner_stock_sourcing/README.rst index 5c11e3e5923..efa2fa28de9 100644 --- a/sale_owner_stock_sourcing/README.rst +++ b/sale_owner_stock_sourcing/README.rst @@ -1,16 +1,17 @@ Sale Owner Stock Sourcing ========================= -This module allow you to choose for every sale order line the owner of the stock that will be dispatched. -By choosing an owner, the generated deliveries will then look for stock of the specified partner. -If no one is available, then the picking will be in waiting availability until stocks of the proper ownership -are replenished. +This module allow you to choose for every sale order line the owner of the +stock that will be dispatched. By choosing an owner, the generated deliveries +will then look for stock of the specified partner. If no one is available, +then the picking will be in waiting availability until stocks of the proper +ownership are replenished. -Specifying an owner on a line, forces to use the stock of this owner. -Letting the owner empty allows to use stock (quant) without owner. +Specifying an owner on a line, forces to use the stock of this owner. Letting +the owner empty allows to use stock (quant) without owner. Contributors ------------ * Yannick Vaucher - +* Leonardo Pistone diff --git a/sale_owner_stock_sourcing/__openerp__.py b/sale_owner_stock_sourcing/__openerp__.py index 7ad1bcea579..c87a3118c9a 100644 --- a/sale_owner_stock_sourcing/__openerp__.py +++ b/sale_owner_stock_sourcing/__openerp__.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # # -# Author: Yannick Vaucher +# Author: Yannick Vaucher, Leonardo Pistone # Copyright 2014 Camptocamp SA # # This program is free software: you can redistribute it and/or modify @@ -20,20 +20,20 @@ # {"name": "Sale Owner Stock Sourcing", "summary": "Manage stock ownership on sale order lines", - "version": "0.0.1", + "version": "0.1", "author": "Camptocamp", "license": "AGPL-3", "category": "Purchase Management", 'complexity': "normal", "images": [], "website": "http://www.camptocamp.com", - "depends": ['sale_stock' - #'purchase_vendor_consignment_stock', + "depends": ['sale_stock', + 'stock_ownership_availability_rules', + # 'purchase_vendor_consignment_stock', ], "demo": [], "data": ['view/sale_order.xml', ], - "test": [ ], 'installable': True, "auto_install": False, } diff --git a/sale_owner_stock_sourcing/model/__init__.py b/sale_owner_stock_sourcing/model/__init__.py index 0226d7680c2..fdd798b7909 100644 --- a/sale_owner_stock_sourcing/model/__init__.py +++ b/sale_owner_stock_sourcing/model/__init__.py @@ -1,2 +1,3 @@ # -*- coding: utf-8 -*- from . import sale_order +from . import procurement diff --git a/sale_owner_stock_sourcing/model/procurement.py b/sale_owner_stock_sourcing/model/procurement.py new file mode 100644 index 00000000000..8d70244db45 --- /dev/null +++ b/sale_owner_stock_sourcing/model/procurement.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# Author: Leonardo Pistone +# Copyright 2014 Camptocamp SA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from openerp import models, api + + +class Procurement(models.Model): + _inherit = 'procurement.order' + + @api.model + def _run_move_create(self, procurement): + result = super(Procurement, self)._run_move_create(procurement) + result['restrict_partner_id'] = procurement.sale_line_id.stock_owner_id.id + return result diff --git a/sale_owner_stock_sourcing/tests/__init__.py b/sale_owner_stock_sourcing/tests/__init__.py new file mode 100644 index 00000000000..e64e51a6ea0 --- /dev/null +++ b/sale_owner_stock_sourcing/tests/__init__.py @@ -0,0 +1 @@ +from . import test_propagate_owner_to_move diff --git a/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py b/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py new file mode 100644 index 00000000000..bf1fa988048 --- /dev/null +++ b/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py @@ -0,0 +1,44 @@ +# Author: Leonardo Pistone +# Copyright 2014 Camptocamp SA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from openerp.tests.common import TransactionCase + + +class TestPropagateOwner(TransactionCase): + + def test_it_propagates_owner_to_the_move(self): + self.sol.stock_owner_id = self.partner.id + + self.so.action_button_confirm() + + self.assertEqual(1, len(self.so.picking_ids)) + self.assertEqual(self.so.picking_ids.move_lines[0].restrict_partner_id, + self.partner) + + def setUp(self): + super(TestPropagateOwner, self).setUp() + self.SO = self.env['sale.order'] + self.SOL = self.env['sale.order.line'] + self.product = self.env.ref('product.product_product_36') + self.partner = self.env.ref('base.res_partner_2') + + self.so = self.SO.create({ + 'partner_id': self.env.ref('base.res_partner_2').id, + }) + self.sol = self.SOL.create({ + 'name': '/', + 'order_id': self.so.id, + 'product_id': self.product.id, + }) From af12fdab89f4ffe9fb90082ffca4130b96a440eb Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Tue, 6 Jan 2015 17:19:12 +0100 Subject: [PATCH 03/17] lint --- sale_owner_stock_sourcing/model/procurement.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sale_owner_stock_sourcing/model/procurement.py b/sale_owner_stock_sourcing/model/procurement.py index 8d70244db45..d3d1ad98df6 100644 --- a/sale_owner_stock_sourcing/model/procurement.py +++ b/sale_owner_stock_sourcing/model/procurement.py @@ -23,6 +23,6 @@ class Procurement(models.Model): @api.model def _run_move_create(self, procurement): - result = super(Procurement, self)._run_move_create(procurement) - result['restrict_partner_id'] = procurement.sale_line_id.stock_owner_id.id - return result + res = super(Procurement, self)._run_move_create(procurement) + res['restrict_partner_id'] = procurement.sale_line_id.stock_owner_id.id + return res From 93a90432dbc03a27b8515a8a82c6ecae0e5b8b8b Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Tue, 6 Jan 2015 17:22:04 +0100 Subject: [PATCH 04/17] travis: pull stock-logistics-workflow --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 61adcaf6596..dfa9a03c808 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ install: - git clone https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools - export PATH=${HOME}/maintainer-quality-tools/travis:${PATH} - travis_install_nightly + - git clone https://github.com/OCA/stock-logistics-workflow -b ${VERSION} $HOME/stock-logistics-workflow script: - travis_run_tests From cc105dd180ccf0737bec1e12d714f38aac3f2652 Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Tue, 6 Jan 2015 18:15:59 +0100 Subject: [PATCH 05/17] test lines without owner still work --- .../tests/test_propagate_owner_to_move.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py b/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py index bf1fa988048..167af560438 100644 --- a/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py +++ b/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py @@ -18,6 +18,12 @@ class TestPropagateOwner(TransactionCase): + def test_it_propagates_empty_owner_to_the_move(self): + self.so.action_button_confirm() + + self.assertEqual(1, len(self.so.picking_ids)) + self.assertFalse(self.so.picking_ids.move_lines[0].restrict_partner_id) + def test_it_propagates_owner_to_the_move(self): self.sol.stock_owner_id = self.partner.id From 1bea9203b49f08804dd60a75bfadcfcfc07b7a60 Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Tue, 6 Jan 2015 18:16:21 +0100 Subject: [PATCH 06/17] add integration test: order line to reservation --- sale_owner_stock_sourcing/tests/__init__.py | 1 + .../tests/test_int_sale_to_reservation.py | 73 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py diff --git a/sale_owner_stock_sourcing/tests/__init__.py b/sale_owner_stock_sourcing/tests/__init__.py index e64e51a6ea0..531395e6366 100644 --- a/sale_owner_stock_sourcing/tests/__init__.py +++ b/sale_owner_stock_sourcing/tests/__init__.py @@ -1 +1,2 @@ from . import test_propagate_owner_to_move +from . import test_int_sale_to_reservation diff --git a/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py b/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py new file mode 100644 index 00000000000..b288f74cfd6 --- /dev/null +++ b/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py @@ -0,0 +1,73 @@ +# Author: Leonardo Pistone +# Copyright 2014 Camptocamp SA +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +from openerp.tests.common import TransactionCase + + +class TestIntSaleToReservation(TransactionCase): + """Integration tests of the propagation of the owner. + + Here we check the whole trip from the quotation line to the reservation of + the stock. + + """ + + def test_one_line_with_owner_reserves_its_stock(self): + self.sol.stock_owner_id = self.owner1 + self.so.action_button_confirm() + + picking = self.so.picking_ids + picking.action_assign() + self.assertEqual('assigned', picking.state) + self.assertEqual(self.owner1, + picking.move_lines.reserved_quant_ids.owner_id) + + def test_one_line_without_owner_reserves_my_stock(self): + self.so.action_button_confirm() + + picking = self.so.picking_ids + picking.action_assign() + self.assertEqual('assigned', picking.state) + self.assertEqual(self.env.user.company_id.partner_id, + picking.move_lines.reserved_quant_ids.owner_id) + + def setUp(self): + super(TestIntSaleToReservation, self).setUp() + self.SO = self.env['sale.order'] + self.SOL = self.env['sale.order.line'] + self.Quant = self.env['stock.quant'] + + self.owner1 = self.env.ref('base.res_partner_1') + self.owner2 = self.env.ref('base.res_partner_2') + customer = self.env.ref('base.res_partner_3') + self.product = self.env.ref('product.product_product_36') + + quant = self.Quant.create({ + 'qty': 5000, + 'location_id': self.env.ref('stock.stock_location_stock').id, + 'product_id': self.product.id, + }) + + quant.copy({'owner_id': self.owner1.id}) + quant.copy({'owner_id': self.owner2.id}) + + self.so = self.SO.create({ + 'partner_id': customer.id, + }) + self.sol = self.SOL.create({ + 'name': '/', + 'order_id': self.so.id, + 'product_id': self.product.id, + }) From 06a655ff32f042b0ec95b4e4672bc51dd73243b0 Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Tue, 6 Jan 2015 18:28:54 +0100 Subject: [PATCH 07/17] more integration tests --- .../tests/test_int_sale_to_reservation.py | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py b/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py index b288f74cfd6..b262bc63d83 100644 --- a/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py +++ b/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py @@ -40,7 +40,30 @@ def test_one_line_without_owner_reserves_my_stock(self): picking = self.so.picking_ids picking.action_assign() self.assertEqual('assigned', picking.state) - self.assertEqual(self.env.user.company_id.partner_id, + self.assertEqual(self.my_partner, + picking.move_lines.reserved_quant_ids.owner_id) + + def test_two_lines_one_with_owner_reserves_correct_stock(self): + sol2 = self.sol.copy({'stock_owner_id': self.owner1.id}) + self.so.action_button_confirm() + + picking = self.so.picking_ids + picking.action_assign() + self.assertEqual('assigned', picking.state) + + quant_owners = set([move.reserved_quant_ids.owner_id + for move in picking.move_lines]) + + self.assertEqual(set([self.my_partner, self.owner1]), quant_owners) + + def test_one_line_without_owner_insufficient_stock_respects_stock(self): + self.sol.product_uom_qty = 6000 + self.so.action_button_confirm() + + picking = self.so.picking_ids + picking.action_assign() + self.assertEqual('partially_available', picking.state) + self.assertEqual(self.my_partner, picking.move_lines.reserved_quant_ids.owner_id) def setUp(self): @@ -52,6 +75,7 @@ def setUp(self): self.owner1 = self.env.ref('base.res_partner_1') self.owner2 = self.env.ref('base.res_partner_2') customer = self.env.ref('base.res_partner_3') + self.my_partner = self.env.user.company_id.partner_id self.product = self.env.ref('product.product_product_36') quant = self.Quant.create({ From 94e3ad94e2fabb56fa23e1e45b92982c5b7d3cbc Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Wed, 7 Jan 2015 09:34:23 +0100 Subject: [PATCH 08/17] add doc, point to discussion with @jco-odoo --- sale_owner_stock_sourcing/README.rst | 9 +++++++++ sale_owner_stock_sourcing/model/procurement.py | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/sale_owner_stock_sourcing/README.rst b/sale_owner_stock_sourcing/README.rst index efa2fa28de9..d23ac911921 100644 --- a/sale_owner_stock_sourcing/README.rst +++ b/sale_owner_stock_sourcing/README.rst @@ -10,6 +10,15 @@ ownership are replenished. Specifying an owner on a line, forces to use the stock of this owner. Letting the owner empty allows to use stock (quant) without owner. +Note: pickings and moves both have a owner field. Here we only propagate the +owner to moves. We have integration tests that check that this does end up with +the correct reservation of quants, even if two order lines have different +owners. If we decide instead to propagate the owner_id field of the picking as +well, we will have to split pickings accordingly in case a sale order has lines +with different owners. See the discussion on +https://github.com/odoo/odoo/pull/4548 for details. + + Contributors ------------ diff --git a/sale_owner_stock_sourcing/model/procurement.py b/sale_owner_stock_sourcing/model/procurement.py index d3d1ad98df6..ef6961e971b 100644 --- a/sale_owner_stock_sourcing/model/procurement.py +++ b/sale_owner_stock_sourcing/model/procurement.py @@ -23,6 +23,11 @@ class Procurement(models.Model): @api.model def _run_move_create(self, procurement): + """Propagate owner from sale order line to stock move. + + This is run when a quotation is validated into a sale order. + + """ res = super(Procurement, self)._run_move_create(procurement) res['restrict_partner_id'] = procurement.sale_line_id.stock_owner_id.id return res From c7277e19a29bb20df56c4c14b1ae10acc5cca1ba Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Wed, 14 Jan 2015 16:35:27 +0100 Subject: [PATCH 09/17] remove unused local variable --- sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py b/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py index b262bc63d83..64f0601c65c 100644 --- a/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py +++ b/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py @@ -44,7 +44,7 @@ def test_one_line_without_owner_reserves_my_stock(self): picking.move_lines.reserved_quant_ids.owner_id) def test_two_lines_one_with_owner_reserves_correct_stock(self): - sol2 = self.sol.copy({'stock_owner_id': self.owner1.id}) + self.sol.copy({'stock_owner_id': self.owner1.id}) self.so.action_button_confirm() picking = self.so.picking_ids From 57faaf91e0b00f31842919b2584d00a70b0e7e41 Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Thu, 15 Jan 2015 08:48:04 +0100 Subject: [PATCH 10/17] in tests use ipad mini that has stock in demo data Otherwise tests don't pass when run together with sale_exceptions_nostock. --- .../tests/test_int_sale_to_reservation.py | 2 ++ .../tests/test_propagate_owner_to_move.py | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py b/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py index 64f0601c65c..785acb9bdac 100644 --- a/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py +++ b/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py @@ -76,6 +76,8 @@ def setUp(self): self.owner2 = self.env.ref('base.res_partner_2') customer = self.env.ref('base.res_partner_3') self.my_partner = self.env.user.company_id.partner_id + + # this product has no stock in demo data self.product = self.env.ref('product.product_product_36') quant = self.Quant.create({ diff --git a/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py b/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py index 167af560438..d95954875ff 100644 --- a/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py +++ b/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py @@ -37,7 +37,9 @@ def setUp(self): super(TestPropagateOwner, self).setUp() self.SO = self.env['sale.order'] self.SOL = self.env['sale.order.line'] - self.product = self.env.ref('product.product_product_36') + + # this product has some stock in demo data + self.product = self.env.ref('product.product_product_6') self.partner = self.env.ref('base.res_partner_2') self.so = self.SO.create({ From 0559848cc86adfa783fd6b6383537e6a5cbb2296 Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Thu, 15 Jan 2015 08:52:29 +0100 Subject: [PATCH 11/17] remove useless instance variables in tests --- .../tests/test_int_sale_to_reservation.py | 15 ++++++--------- .../tests/test_propagate_owner_to_move.py | 8 ++++---- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py b/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py index 785acb9bdac..beaaebed138 100644 --- a/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py +++ b/sale_owner_stock_sourcing/tests/test_int_sale_to_reservation.py @@ -68,9 +68,6 @@ def test_one_line_without_owner_insufficient_stock_respects_stock(self): def setUp(self): super(TestIntSaleToReservation, self).setUp() - self.SO = self.env['sale.order'] - self.SOL = self.env['sale.order.line'] - self.Quant = self.env['stock.quant'] self.owner1 = self.env.ref('base.res_partner_1') self.owner2 = self.env.ref('base.res_partner_2') @@ -78,22 +75,22 @@ def setUp(self): self.my_partner = self.env.user.company_id.partner_id # this product has no stock in demo data - self.product = self.env.ref('product.product_product_36') + product = self.env.ref('product.product_product_36') - quant = self.Quant.create({ + quant = self.env['stock.quant'].create({ 'qty': 5000, 'location_id': self.env.ref('stock.stock_location_stock').id, - 'product_id': self.product.id, + 'product_id': product.id, }) quant.copy({'owner_id': self.owner1.id}) quant.copy({'owner_id': self.owner2.id}) - self.so = self.SO.create({ + self.so = self.env['sale.order'].create({ 'partner_id': customer.id, }) - self.sol = self.SOL.create({ + self.sol = self.env['sale.order.line'].create({ 'name': '/', 'order_id': self.so.id, - 'product_id': self.product.id, + 'product_id': product.id, }) diff --git a/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py b/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py index d95954875ff..c6547dcd7e1 100644 --- a/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py +++ b/sale_owner_stock_sourcing/tests/test_propagate_owner_to_move.py @@ -39,14 +39,14 @@ def setUp(self): self.SOL = self.env['sale.order.line'] # this product has some stock in demo data - self.product = self.env.ref('product.product_product_6') + product = self.env.ref('product.product_product_6') self.partner = self.env.ref('base.res_partner_2') - self.so = self.SO.create({ + self.so = self.env['sale.order'].create({ 'partner_id': self.env.ref('base.res_partner_2').id, }) - self.sol = self.SOL.create({ + self.sol = self.env['sale.order.line'].create({ 'name': '/', 'order_id': self.so.id, - 'product_id': self.product.id, + 'product_id': product.id, }) From 02fb4d988b46af99434c88e51fe8c08d028666cc Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Thu, 15 Jan 2015 10:00:23 +0100 Subject: [PATCH 12/17] improve doc --- sale_owner_stock_sourcing/README.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sale_owner_stock_sourcing/README.rst b/sale_owner_stock_sourcing/README.rst index d23ac911921..ddee2542d03 100644 --- a/sale_owner_stock_sourcing/README.rst +++ b/sale_owner_stock_sourcing/README.rst @@ -1,16 +1,16 @@ Sale Owner Stock Sourcing ========================= -This module allow you to choose for every sale order line the owner of the +This module allows you to choose for every sale order line the owner of the stock that will be dispatched. By choosing an owner, the generated deliveries -will then look for stock of the specified partner. If no one is available, -then the picking will be in waiting availability until stocks of the proper -ownership are replenished. +will then look for stock belonging to the specified partner. If none is +available, then the picking will be waiting availability until stocks with +proper ownership are replenished. -Specifying an owner on a line, forces to use the stock of this owner. Letting +Specifying an owner on a line forces to use the stock of this owner. Leaving the owner empty allows to use stock (quant) without owner. -Note: pickings and moves both have a owner field. Here we only propagate the +Note: pickings and moves both have an owner field. Here we only propagate the owner to moves. We have integration tests that check that this does end up with the correct reservation of quants, even if two order lines have different owners. If we decide instead to propagate the owner_id field of the picking as From 7e0fced77d0ba9a3e4002b3e2a93f8c7ad945b60 Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Thu, 15 Jan 2015 10:00:32 +0100 Subject: [PATCH 13/17] remove commented out dependency --- sale_owner_stock_sourcing/__openerp__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sale_owner_stock_sourcing/__openerp__.py b/sale_owner_stock_sourcing/__openerp__.py index c87a3118c9a..89ced56070b 100644 --- a/sale_owner_stock_sourcing/__openerp__.py +++ b/sale_owner_stock_sourcing/__openerp__.py @@ -29,7 +29,6 @@ "website": "http://www.camptocamp.com", "depends": ['sale_stock', 'stock_ownership_availability_rules', - # 'purchase_vendor_consignment_stock', ], "demo": [], "data": ['view/sale_order.xml', From 1e43bede533421df662a75d81e1a9776e3ba9bde Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Thu, 15 Jan 2015 10:27:54 +0100 Subject: [PATCH 14/17] 2015 copyright year --- sale_owner_stock_sourcing/__openerp__.py | 2 +- sale_owner_stock_sourcing/model/procurement.py | 2 +- sale_owner_stock_sourcing/model/sale_order.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sale_owner_stock_sourcing/__openerp__.py b/sale_owner_stock_sourcing/__openerp__.py index 89ced56070b..5bc47028fab 100644 --- a/sale_owner_stock_sourcing/__openerp__.py +++ b/sale_owner_stock_sourcing/__openerp__.py @@ -2,7 +2,7 @@ # # # Author: Yannick Vaucher, Leonardo Pistone -# Copyright 2014 Camptocamp SA +# Copyright 2014-2015 Camptocamp SA # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as diff --git a/sale_owner_stock_sourcing/model/procurement.py b/sale_owner_stock_sourcing/model/procurement.py index ef6961e971b..bd6d8e54be7 100644 --- a/sale_owner_stock_sourcing/model/procurement.py +++ b/sale_owner_stock_sourcing/model/procurement.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # Author: Leonardo Pistone -# Copyright 2014 Camptocamp SA +# Copyright 2014-2015 Camptocamp SA # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as diff --git a/sale_owner_stock_sourcing/model/sale_order.py b/sale_owner_stock_sourcing/model/sale_order.py index 374f91f4718..2c19df04269 100644 --- a/sale_owner_stock_sourcing/model/sale_order.py +++ b/sale_owner_stock_sourcing/model/sale_order.py @@ -2,7 +2,7 @@ # # # Author: Yannick Vaucher -# Copyright 2014 Camptocamp SA +# Copyright 2014-2015 Camptocamp SA # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as From 14ebb8406750ec44d1a8f275cb6a37a6ac33adf3 Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Thu, 15 Jan 2015 10:30:24 +0100 Subject: [PATCH 15/17] use oca-dependencies.txt --- oca-dependencies.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 oca-dependencies.txt diff --git a/oca-dependencies.txt b/oca-dependencies.txt new file mode 100644 index 00000000000..4c894df821c --- /dev/null +++ b/oca-dependencies.txt @@ -0,0 +1 @@ +stock-logistics-workflow From 39a1ac1d9700dd10bd6dc2448165ca23d969ec56 Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Thu, 15 Jan 2015 11:04:20 +0100 Subject: [PATCH 16/17] always use the form view for sale order lines --- sale_owner_stock_sourcing/__openerp__.py | 1 + sale_owner_stock_sourcing/security/group.xml | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 sale_owner_stock_sourcing/security/group.xml diff --git a/sale_owner_stock_sourcing/__openerp__.py b/sale_owner_stock_sourcing/__openerp__.py index 5bc47028fab..4229200e675 100644 --- a/sale_owner_stock_sourcing/__openerp__.py +++ b/sale_owner_stock_sourcing/__openerp__.py @@ -32,6 +32,7 @@ ], "demo": [], "data": ['view/sale_order.xml', + 'security/group.xml', ], 'installable': True, "auto_install": False, diff --git a/sale_owner_stock_sourcing/security/group.xml b/sale_owner_stock_sourcing/security/group.xml new file mode 100644 index 00000000000..3e09be43128 --- /dev/null +++ b/sale_owner_stock_sourcing/security/group.xml @@ -0,0 +1,10 @@ + + + + + + + + + + From 105c06363c0592719ccaaf416a3573b3f1d692b9 Mon Sep 17 00:00:00 2001 From: Leonardo Pistone Date: Thu, 15 Jan 2015 11:20:58 +0100 Subject: [PATCH 17/17] add translation template and fr.po --- sale_owner_stock_sourcing/i18n/fr.po | 32 +++++++++++++++++++ .../i18n/sale_owner_stock_sourcing.pot | 32 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 sale_owner_stock_sourcing/i18n/fr.po create mode 100644 sale_owner_stock_sourcing/i18n/sale_owner_stock_sourcing.pot diff --git a/sale_owner_stock_sourcing/i18n/fr.po b/sale_owner_stock_sourcing/i18n/fr.po new file mode 100644 index 00000000000..73dc43d4de4 --- /dev/null +++ b/sale_owner_stock_sourcing/i18n/fr.po @@ -0,0 +1,32 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_owner_stock_sourcing +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-15 10:18+0000\n" +"PO-Revision-Date: 2015-01-15 10:18+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sale_owner_stock_sourcing +#: model:ir.model,name:sale_owner_stock_sourcing.model_procurement_order +msgid "Procurement" +msgstr "Procurement" + +#. module: sale_owner_stock_sourcing +#: model:ir.model,name:sale_owner_stock_sourcing.model_sale_order_line +msgid "Sales Order Line" +msgstr "Sales Order Line" + +#. module: sale_owner_stock_sourcing +#: field:sale.order.line,stock_owner_id:0 +msgid "Stock Owner" +msgstr "Stock Owner" + diff --git a/sale_owner_stock_sourcing/i18n/sale_owner_stock_sourcing.pot b/sale_owner_stock_sourcing/i18n/sale_owner_stock_sourcing.pot new file mode 100644 index 00000000000..e0cf3e2c645 --- /dev/null +++ b/sale_owner_stock_sourcing/i18n/sale_owner_stock_sourcing.pot @@ -0,0 +1,32 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_owner_stock_sourcing +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2015-01-15 10:19+0000\n" +"PO-Revision-Date: 2015-01-15 10:19+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: sale_owner_stock_sourcing +#: model:ir.model,name:sale_owner_stock_sourcing.model_procurement_order +msgid "Procurement" +msgstr "" + +#. module: sale_owner_stock_sourcing +#: model:ir.model,name:sale_owner_stock_sourcing.model_sale_order_line +msgid "Sales Order Line" +msgstr "" + +#. module: sale_owner_stock_sourcing +#: field:sale.order.line,stock_owner_id:0 +msgid "Stock Owner" +msgstr "" +