Skip to content

Commit

Permalink
Merge 7729079 into 3639077
Browse files Browse the repository at this point in the history
  • Loading branch information
hurrinico committed May 28, 2015
2 parents 3639077 + 7729079 commit 7966eda
Show file tree
Hide file tree
Showing 10 changed files with 403 additions and 0 deletions.
30 changes: 30 additions & 0 deletions sale_order_lot_selection/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:alt: License

Sale Order Lot Selection
========================

This Module Allows you to select on sale order the production lot that will be delivered
You can select a lot for every sale order line, and it will be proposed on the delivery

Credits
=======

Contributors
------------

* Nicola Malcontenti <nicola.malcontenti@agilebg.com>
* Lorenzo Battistini <lorenzo.battistini@agilebg.com>

Maintainer
----------

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

This module is maintained by the OCA.

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.

To contribute to this module, please visit http://odoo-community.org.
22 changes: 22 additions & 0 deletions sale_order_lot_selection/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
#########################################################################
# #
# Copyright (C) 2015 Agile Business Group #
# #
# 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 Licensefor more details. #
# #
# You should have received a copy of the #
# GNU Affero General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
#########################################################################

from . import model
36 changes: 36 additions & 0 deletions sale_order_lot_selection/__openerp__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
#########################################################################
# #
# Copyright (C) 2015 Agile Business Group #
# #
# 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 Licensefor more details. #
# #
# You should have received a copy of the #
# GNU Affero General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
#########################################################################


{
'name': 'Sale Order Lot Selection',
'version': '1.0',
'category': 'Sales Management',
'author': "Odoo Community Association (OCA), Agile Business Group",
'website': 'http://www.agilebg.com',
'license': 'AGPL-3',
'depends': ['sale', 'sale_stock', 'procurement', 'stock'],
'data': ['view/sale_view.xml'],
'installable': True,
'active': False,
}

# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
23 changes: 23 additions & 0 deletions sale_order_lot_selection/model/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
#########################################################################
# #
# Copyright (C) 2015 Agile Business Group #
# #
# 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 Licensefor more details. #
# #
# You should have received a copy of the #
# GNU Affero General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
#########################################################################

from . import sale
from . import procurement
43 changes: 43 additions & 0 deletions sale_order_lot_selection/model/procurement.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
#########################################################################
# #
# Copyright (C) 2015 Agile Business Group #
# #
# 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 Licensefor more details. #
# #
# You should have received a copy of the #
# GNU Affero General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
#########################################################################

from openerp import fields, models, api


class procurement_order(models.Model):
_inherit = 'procurement.order'

lot_id = fields.Many2one('stock.production.lot', 'Lot')

@api.model
def _run(self, procurement):
res = super(
procurement_order, self)._run(procurement)
for move in procurement.move_ids:
move.action_assign()
return True

@api.model
def _run_move_create(self, procurement):
res = super(
procurement_order, self)._run_move_create(procurement)
res['restrict_lot_id'] = procurement.lot_id.id
return res
101 changes: 101 additions & 0 deletions sale_order_lot_selection/model/sale.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# -*- coding: utf-8 -*-
#########################################################################
# #
# Copyright (C) 2015 Agile Business Group #
# #
# 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 Licensefor more details. #
# #
# You should have received a copy of the #
# GNU Affero General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
#########################################################################

from openerp import fields, models, api, _
from openerp.exceptions import Warning
from openerp.tools import float_compare


class sale_order_line(models.Model):
_inherit = 'sale.order.line'

lot_id = fields.Many2one('stock.production.lot', 'Lot')

@api.onchange('lot_id')
def on_change_lot_id(self):
res = {}
warning = {}

product_obj = self.env['product.product'].with_context(
lot_id=self.lot_id.id).browse(self.lot_id.product_id.id)
compare_qty = float_compare(product_obj.virtual_available,
self.product_uom_qty,
precision_rounding=(
product_obj.uom_id.rounding))
if compare_qty == -1:
warn_msg = _('You plan to sell %.2f %s but you'
' only have %.2f %s available !'
'\nThe real stock is %.2f %s.'
' (without reservations)') % \
(self.product_uom_qty, product_obj.uom_id.name,
max(0, product_obj.virtual_available),
product_obj.uom_id.name,
max(0, product_obj.qty_available),
product_obj.uom_id.name)
warning = {'title': _('Configuration Error!'),
'message': _(
"Not enough stock ! : ") + warn_msg + "\n\n"}
res.update({'warning': warning})
return res


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

@api.model
def _prepare_order_line_procurement(self, order, line, group_id=False):
res = super(
sale_order, self)._prepare_order_line_procurement(
order, line, group_id)
res['lot_id'] = line.lot_id.id
return res

@api.model
def get_move_from_line(self, line):
move = self.env['stock.move']
# i create this counter to check lot's univocity on move line
lot_count = 0
for p in line.order_id.picking_ids:
for m in p.move_lines:
if line.lot_id == m.restrict_lot_id:
move = m
lot_count += 1
# if counter is 0 or >1 means thar something goes wrong
if lot_count != 1:
raise Warning(_('Can\'t retrieve lot on stock'))
return move

@api.model
def action_ship_create(self):
super(sale_order, self).action_ship_create()
for line in self.order_line:
if line.lot_id:
move = self.get_move_from_line(line)
if move.state != 'confirmed':
raise Warning(_('Can\'t reserve products for lot %s') %
line.lot_id.name)
else:
move.action_assign()
move.refresh()
if move.state != 'assigned':
raise Warning(_('Can\'t reserve products for lot %s') %
line.lot_id.name)
return True
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 22 additions & 0 deletions sale_order_lot_selection/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
#########################################################################
# #
# Copyright (C) 2015 Agile Business Group #
# #
# 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 Licensefor more details. #
# #
# You should have received a copy of the #
# GNU Affero General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
#########################################################################

from . import test_sale_order_lot_selection
106 changes: 106 additions & 0 deletions sale_order_lot_selection/tests/test_sale_order_lot_selection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# -*- coding: utf-8 -*-
#########################################################################
# #
# Copyright (C) 2015 Agile Business Group #
# #
# 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 Licensefor more details. #
# #
# You should have received a copy of the #
# GNU Affero General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
#########################################################################
import openerp.tests.common as test_common


class TestSaleOrderLotSelection(test_common.SingleTransactionCase):
def setUp(self):
"""
Set up a sale order a particular lot.
I confirm it, transfer the delivery order and check lot on picking
Set up a sale order with two lines with different products and lots.
I confirm it, transfer the delivery order and check lots on picking
"""
super(TestSaleOrderLotSelection, self).setUp()
self.product_11 = self.env.ref('product.product_product_11')
self.lot = self.env['stock.production.lot'].create(
{
'name': "0000010",
'product_id': self.product_11.id
})
self.order = self.env['sale.order'].create(
{
'partner_id': self.env.ref('base.res_partner_1').id,
})
self.sol1 = self.env['sale.order.line'].create({
'name': 'sol1',
'order_id': self.order.id,
'lot_id': self.lot.id,
'product_id': self.product_11.id,
})
self.product_13 = self.env.ref('product.product_product_13')
self.lot13 = self.env['stock.production.lot'].create(
{
'name': "0000011",
'product_id': self.product_13.id
})
self.product_12 = self.env.ref('product.product_product_12')
self.lot12 = self.env['stock.production.lot'].create(
{
'name': "0000012",
'product_id': self.product_12.id
})
self.order2 = self.env['sale.order'].create(
{
'partner_id': self.env.ref('base.res_partner_1').id,
})
self.sol2a = self.env['sale.order.line'].create({
'name': 'sol2a',
'order_id': self.order2.id,
'lot_id': self.lot13.id,
'product_id': self.product_13.id,
})
self.sol2b = self.env['sale.order.line'].create({
'name': 'sol2b',
'order_id': self.order2.id,
'lot_id': self.lot12.id,
'product_id': self.product_12.id,
})

def test_order_confirm_and_picking_transfer_one_lot(self):
self.order.action_button_confirm()
picking = self.order.picking_ids
picking.action_assign()
picking.do_enter_transfer_details()
wiz = self.env['stock.transfer_details'].search([
['picking_id', '=', picking.id]])
wiz.do_detailed_transfer()
for pack in picking.pack_operation_ids:
if pack.product_id.id == self.product_11.id:
self.assertEqual(pack.lot_id, self.lot)

def test_order_confirm_and_picking_transfer_2_products_2_lots(self):
self.order2.action_button_confirm()
picking = self.order2.picking_ids
picking.action_assign()
picking.do_enter_transfer_details()
wiz = self.env['stock.transfer_details'].search([
['picking_id', '=', picking.id]])
wiz.do_detailed_transfer()
for pack in picking.pack_operation_ids:
if pack.product_id.id == self.product_13.id:
self.assertEqual(pack.lot_id, self.lot13)
else:
self.assertEqual(pack.lot_id, self.lot12)
Loading

0 comments on commit 7966eda

Please sign in to comment.