Skip to content

Commit

Permalink
Merge pull request #141 from yvaucher/8.0-sale_line_sourcing_procumen…
Browse files Browse the repository at this point in the history
…t_group_name

[REF] sale_quotation_sourcing and sale_sourced_by_line
  • Loading branch information
yvaucher committed May 1, 2015
2 parents 4bb5a44 + 81576e6 commit 8b0e50b
Show file tree
Hide file tree
Showing 15 changed files with 546 additions and 159 deletions.
54 changes: 54 additions & 0 deletions sale_procurement_group_by_line/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:alt: License: AGPL-3

Sale Procurement Group by line
==============================

This module was written to extend the functionality of procurement groups
created from a Sale order.

On itself, this module does nothing it is a requirement for modules which
needs to create procurement group per sale order line basis.

Installation
============

This module is only a base for other modules, see Usage.


Configuration
=============

No special configuration is required.

Usage
=====

To use this module, you need to install
**Sale Sourcing By Line** (`sale_sourcing_by_line`) and/or
**Sale Quotation Sourcing** (`sale_quotation_sourcing`)


Credits
=======

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

* Yannick Vaucher <yannick.vaucher@camptocamp.com>
* Guewen Baconnier <guewen.baconnier@camptocamp.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.
21 changes: 21 additions & 0 deletions sale_procurement_group_by_line/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
#
#
# Author: Yannick Vaucher
# Copyright 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
# 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 <http://www.gnu.org/licenses/>.
#
#
from . import model
38 changes: 38 additions & 0 deletions sale_procurement_group_by_line/__openerp__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
#
#
# Author: Guewen Baconnier
# Copyright 2013-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 <http://www.gnu.org/licenses/>.
#
#

{'name': 'Sale Procurement Group by Line',
'summary': 'Base module for multiple procurement group by Sale order',
'version': '1.0',
'author': "Camptocamp,Odoo Community Association (OCA)",
'category': 'Warehouse',
'license': 'AGPL-3',
'complexity': 'expert',
'images': [],
'website': "http://www.camptocamp.com",
'depends': ['sale_stock',
],
'demo': [],
'data': [],
'test': [],
'auto_install': False,
'installable': True,
}
1 change: 1 addition & 0 deletions sale_procurement_group_by_line/model/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import sale
181 changes: 181 additions & 0 deletions sale_procurement_group_by_line/model/sale.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# -*- coding: utf-8 -*-
#
#
# Author: Guewen Baconnier, Yannick Vaucher
# Copyright 2013-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
# 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 <http://www.gnu.org/licenses/>.
#
#
from openerp import models, api, fields, osv
from openerp.osv import orm


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

@api.model
def _prepare_procurement_group_by_line(self, line):
""" Hook to be able to use line data on procurement group """
return self._prepare_procurement_group(line.order_id)

###
# OVERRIDE to create procurement group by sale order line grouped by
# a key defined by `_get_procurement_group_key`
###
def action_ship_create(self, cr, uid, ids, context=None):
"""Create the required procurements to supply sales order lines, also
connecting the procurements to appropriate stock moves in order to
bring the goods to the sales order's requested location.
:return: True
"""
procurement_obj = self.pool.get('procurement.order')
sale_line_obj = self.pool.get('sale.order.line')
for order in self.browse(cr, uid, ids, context=context):
proc_ids = []

groups = {}

for line in order.order_line:
group_id = groups.get(line._get_procurement_group_key())
if not group_id:
vals = self._prepare_procurement_group_by_line(
cr, uid, line, context=context)
group_id = self.pool["procurement.group"].create(
cr, uid, vals, context=context)
groups[line._get_procurement_group_key()] = group_id
line.write({'procurement_group_id': group_id})
# Try to fix exception procurement (possible when after a
# shipping exception the user choose to recreate)
if line.procurement_ids:
# first check them to see if they are in exception or not
# (one of the related moves is cancelled)
procurement_obj.check(
cr, uid, [x.id for x in line.procurement_ids
if x.state not in ['cancel', 'done']])
line.refresh()
# run again procurement that are in exception in order to
# trigger another move
proc_ids += [x.id for x in line.procurement_ids
if x.state in ('exception', 'cancel')]
elif sale_line_obj.need_procurement(cr, uid, [line.id],
context=context):
if (line.state == 'done') or not line.product_id:
continue
vals = self._prepare_order_line_procurement(
cr, uid, order, line,
group_id=group_id, context=context)
proc_id = procurement_obj.create(
cr, uid, vals, context=context)
proc_ids.append(proc_id)
# Confirm procurement order such that rules will be applied on it
# note that the workflow normally ensure proc_ids isn't an empty
# list
procurement_obj.run(cr, uid, proc_ids, context=context)

# if shipping was in exception and the user choose to recreate the
# delivery order, write the new status of SO
if order.state == 'shipping_except':
val = {'state': 'progress', 'shipped': False}

if (order.order_policy == 'manual'):
for line in order.order_line:
if (not line.invoiced and
line.state not in ('cancel', 'draft')):
val['state'] = 'manual'
break
order.write(val)
return True

###
# OVERRIDE to use sale.order.line's procurement_group_id from lines
###
@api.one
@api.depends('order_line.procurement_group_id.procurement_ids.state')
def _get_shipped(self):
""" As procurement is per sale line basis, we check each line
If at least a line has no procurement group defined, it means it
isn't shipped yet.
Only when all procurement are done or cancelled, we consider
the sale order as being shipped.
And if there is no line, we have nothing to ship, thus it isn't
shipped.
"""
if not self.order_line:
self.shipped = False
return

# keep empty groups
groups = set([line.procurement_group_id
for line in self.order_line
if line.product_id.type != 'service'])
is_shipped = True
for group in groups:
if not group or not group.procurement_ids:
is_shipped = False
break
is_shipped &= all([proc.state in ['cancel', 'done']
for proc in group.procurement_ids])
self.shipped = is_shipped

###
# OVERRIDE to find sale.order.line's picking
###
def _get_picking_ids(self, cr, uid, ids, name, args, context=None):
res = {}
for sale in self.browse(cr, uid, ids, context=context):
group_ids = set([line.procurement_group_id.id
for line in sale.order_line
if line.procurement_group_id])
if not any(group_ids):
res[sale.id] = []
continue
res[sale.id] = self.pool['stock.picking'].search(
cr, uid, [('group_id', 'in', list(group_ids))],
context=context)
return res

_columns = {
'picking_ids': osv.fields.function(
_get_picking_ids, method=True, type='one2many',
relation='stock.picking',
string='Picking associated to this sale'),
}

shipped = fields.Boolean(
compute='_get_shipped',
string='Delivered',
store=True)


class SaleOrderLine(orm.Model):
_inherit = 'sale.order.line'

@api.multi
def _get_procurement_group_key(self):
""" Return a key with priority to be used to regroup lines in multiple
procurement groups
"""
return (8, self.order_id.id)

procurement_group_id = fields.Many2one(
'procurement.group',
'Procurement group',
copy=False)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions sale_quotation_sourcing/__openerp__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Author: Alexandre Fayolle, 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
Expand Down Expand Up @@ -31,7 +31,8 @@
'depends': ['sale_stock',
'purchase',
'stock_dropshipping',
'sale_exceptions'],
'sale_exceptions',
'sale_procurement_group_by_line'],
'data': ['views/sale_order_sourcing.xml',
'views/sale_order.xml',
'security/group.xml',
Expand Down
27 changes: 25 additions & 2 deletions sale_quotation_sourcing/model/sale_order.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Author: Alexandre Fayolle, Leonardo Pistone
# Copyright 2014 Camptocamp SA
# Author: Alexandre Fayolle, Leonardo Pistone, Yannick Vaucher
# 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
Expand Down Expand Up @@ -51,6 +51,15 @@ def action_button_confirm(self):
else:
return super(SaleOrder, self).action_button_confirm()

@api.model
def _prepare_procurement_group_by_line(self, line):
vals = super(SaleOrder, self)._prepare_procurement_group_by_line(line)
# for compatibility with sale_quotation_sourcing
if line._get_procurement_group_key()[0] == 16:
if line.sourced_by:
vals['name'] += '/' + line.sourced_by.order_id.name
return vals

@api.model
def _create_sourcing_wizard(self, lines_to_source):
line_values = []
Expand Down Expand Up @@ -155,3 +164,17 @@ def set_route_form_so(self):
route = self._find_route_from_usage(usage)
if route:
self.route_id = route

@api.multi
def _get_procurement_group_key(self):
""" Return a key with priority to be used to regroup lines in multiple
procurement groups
"""
priority = 16
key = super(SaleOrderLine, self)._get_procurement_group_key()
# Check priority
if key[0] < priority:
if self.sourced_by:
return (priority, self.sourced_by.order_id.id)
return key
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions sale_quotation_sourcing/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@
##############################################################################
from . import test_sourced_by
from . import test_consistent_route
from . import test_procurement_group
Loading

0 comments on commit 8b0e50b

Please sign in to comment.