Merge lp:~camptocamp/stock-logistic-flows/7.0-picking_dispatch_wave-according-defined-number-of-sales_rde into lp:stock-logistic-flows

Proposed by Romain Deheele - Camptocamp
Status: Merged
Merged at revision: 62
Proposed branch: lp:~camptocamp/stock-logistic-flows/7.0-picking_dispatch_wave-according-defined-number-of-sales_rde
Merge into: lp:stock-logistic-flows
Diff against target: 469 lines (+432/-0)
7 files modified
picking_dispatch_wave/__init__.py (+22/-0)
picking_dispatch_wave/__openerp__.py (+46/-0)
picking_dispatch_wave/dispatch_wave.py (+119/-0)
picking_dispatch_wave/dispatch_wave_view.xml (+46/-0)
picking_dispatch_wave/i18n/fr.po (+82/-0)
picking_dispatch_wave/i18n/picking_dispatch_wave.pot (+70/-0)
picking_dispatch_wave/test/test_dispatch_wave.yml (+47/-0)
To merge this branch: bzr merge lp:~camptocamp/stock-logistic-flows/7.0-picking_dispatch_wave-according-defined-number-of-sales_rde
Reviewer Review Type Date Requested Status
Nicolas Bessi - Camptocamp (community) Approve
Yannick Vaucher @ Camptocamp tests Approve
Alexandre Fayolle - camptocamp code review, test Approve
Review via email: mp+214568@code.launchpad.net

Description of the change

Hello,

This MP adds an addon named picking_dispatch_wave, the principle :
 - Allows to set a 'sale order wave' to pick according a number n of sales that you set.
    1.The picker sets a number n of sale orders.
    2.The wizard will select moves from n oldest sales that are linked to ready pickings.
    3.A picking dispatch is created with found moves

Regards,

Romain

To post a comment you must log in.
Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote :

Needs fixing:

* convert the description in __openerp__.py to Restructured Text
* please add a test
* I'm concerned the SQL query may bypass the multicompany security rules
* NEVER DO SQL PARAMETER SUBSTITUTION WITH THE % OPERATOR!!!!

review: Needs Fixing (code review, no test)
Revision history for this message
Romain Deheele - Camptocamp (romaindeheele) wrote :

Hi,

Tests are added.
SQL is removed and replaced by ORM searchs.
Description has been updated.

Romain

Revision history for this message
Alexandre Fayolle - camptocamp (alexandre-fayolle-c2c) wrote :

LGTM

review: Approve (code review, test)
65. By Yannick Vaucher @ Camptocamp

[PEP8]

Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote :

Shouldn't *_to_done private method be *_to_do or _to_be_done ?

Here are few remarks about translations:

* After installatation on fresh install with last code Wizard fields and label aren't translated. (But this may not be related to this MP)

* In translation, in french there should be a space before punctuation.

* "selon le nombre de commandes de vente voulu." I would replace 'voulu' by 'défini'.

* l.291 +msgstr "Prépare un bon de préparation" -> Préparer

* picker_id help message is not translated nor picking_id field name

review: Needs Fixing (code review, no test)
66. By Romain Deheele - Camptocamp

[UPD] terms review and translation changes

Revision history for this message
Romain Deheele - Camptocamp (romaindeheele) wrote :

Thanks Yannick,

I've reworked terms and translation.

Romain

Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote :

Ok translations works now

Thanks for the changes.

review: Approve (tests)
Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote :

(my tests)

- Installed the module
- tried to create a picking dispatch

Revision history for this message
Nicolas Bessi - Camptocamp (nbessi-c2c-deactivatedaccount) wrote :

Need fixing.
Set has a better performance than list and it should avoid duplicate.
Please see inline comment

review: Needs Fixing
Revision history for this message
Nicolas Bessi - Camptocamp (nbessi-c2c-deactivatedaccount) wrote :
67. By Romain Deheele - Camptocamp

use set() instead of [], rename nb variable, moves selected only if picking state is assigned

Revision history for this message
Romain Deheele - Camptocamp (romaindeheele) wrote :

Thanks Nicolas,

I made changes accordingly.
I add a condition : only assigned pickings are selected.

Revision history for this message
Nicolas Bessi - Camptocamp (nbessi-c2c-deactivatedaccount) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'picking_dispatch_wave'
=== added file 'picking_dispatch_wave/__init__.py'
--- picking_dispatch_wave/__init__.py 1970-01-01 00:00:00 +0000
+++ picking_dispatch_wave/__init__.py 2014-06-13 15:52:45 +0000
@@ -0,0 +1,22 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Alexandre Fayolle, Romain Deheele
5# Copyright 2014 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22from . import dispatch_wave # noqa
023
=== added file 'picking_dispatch_wave/__openerp__.py'
--- picking_dispatch_wave/__openerp__.py 1970-01-01 00:00:00 +0000
+++ picking_dispatch_wave/__openerp__.py 2014-06-13 15:52:45 +0000
@@ -0,0 +1,46 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Alexandre Fayolle, Romain Deheele
5# Copyright 2014 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22
23{
24 "name": "Picking Dispatch Wave",
25 "version": "0.1",
26 "depends": ['picking_dispatch', 'sale_stock'],
27 "author": "Camptocamp",
28 'license': 'AGPL-3',
29 "description": """Allows to set a picking dispatch
30including the number maximum of pickings that you want to pick:
31
32* The picker sets a number n of pickings to do.
33
34* The wizard will select moves from n pickings with oldest min_date.
35
36* A picking dispatch is created with found moves
37
38It's sort of basic wave picking.
39""",
40 "website": "http://www.camptocamp.com",
41 "category": "Warehouse Management",
42 "demo": [],
43 "data": ['dispatch_wave_view.xml'],
44 "test": ['test/test_dispatch_wave.yml'],
45 "installable": True,
46}
047
=== added file 'picking_dispatch_wave/dispatch_wave.py'
--- picking_dispatch_wave/dispatch_wave.py 1970-01-01 00:00:00 +0000
+++ picking_dispatch_wave/dispatch_wave.py 2014-06-13 15:52:45 +0000
@@ -0,0 +1,119 @@
1# -*- coding: utf-8 -*-
2##############################################################################
3#
4# Author: Alexandre Fayolle, Romain Deheele
5# Copyright 2014 Camptocamp SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20#############################################################################
21import logging
22
23from openerp.osv import orm, fields
24from openerp.tools.translate import _
25_logger = logging.getLogger(__name__)
26
27
28class StockPickingDispatchWave(orm.TransientModel):
29 _name = "stock.picking.dispatch.wave"
30
31 def _get_pickings_to_do(self, cr, uid, max_nb, context=None):
32 context = context or {}
33 move_obj = self.pool['stock.move']
34 move_ids = []
35 picking_ids = set()
36 move_ids = move_obj.search(cr, uid,
37 [('dispatch_id', '=', False),
38 ('state', '=', 'assigned'),
39 ('type', '=', 'out')],
40 order='date_expected DESC',
41 context=context)
42 for move in move_obj.browse(cr, uid, move_ids, context=context):
43 if len(picking_ids) == max_nb:
44 break
45 if move.picking_id.state == 'assigned' and \
46 move.picking_id.id not in picking_ids:
47 picking_ids.add(move.picking_id.id)
48 return picking_ids
49
50 def _get_moves_from_picking_list(self, cr, uid, picking_ids, context=None):
51 context = context or {}
52 move_obj = self.pool['stock.move']
53 move_ids = move_obj.search(cr, uid,
54 [('picking_id', 'in', picking_ids)],
55 context=context)
56 return move_ids
57
58 def _get_moves_from_pickings_to_do(self, cr, uid, max_nb, context=None):
59 context = context or {}
60 move_ids = []
61 picking_ids = self.\
62 _get_pickings_to_do(cr, uid, max_nb, context=context)
63 if picking_ids:
64 move_ids = self._get_moves_from_picking_list(cr, uid, picking_ids,
65 context=context)
66 return move_ids
67
68 _columns = {
69 'max_pickings_to_do': fields.integer('Number maximum of pickings '
70 'to prepare',
71 help='number maximum of pickings '
72 'that we want to prepare'),
73 'picker_id': fields.many2one('res.users', 'User', required=True,
74 help='the user to which the pickings '
75 'are assigned'),
76 }
77
78 _defaults = {
79 'max_pickings_to_do': 0,
80 'picker_id': lambda self, cr, uid, ctx: uid,
81 }
82
83 def action_create_picking_dispatch(self, cr, uid, ids, context=None):
84 context = context or {}
85 wave = self.browse(cr, uid, ids, context=context)[0]
86 if wave.max_pickings_to_do:
87 move_ids = self.\
88 _get_moves_from_pickings_to_do(cr, uid,
89 wave.max_pickings_to_do,
90 context=context)
91 if move_ids:
92 # create picking_dispatch
93 dispatch_obj = self.pool['picking.dispatch']
94 dispatch_vals = {
95 'picker_id': wave.picker_id.id
96 }
97 dispatch_id = dispatch_obj.create(cr, uid,
98 dispatch_vals,
99 context=context)
100 # affect move_ids on the new dispatch
101 self.pool['stock.move'].write(cr, uid, move_ids,
102 {'dispatch_id': dispatch_id},
103 context=context)
104 context['active_id'] = dispatch_id
105 return {
106 'domain': str([('id', '=', dispatch_id)]),
107 'view_type': 'form',
108 'view_mode': 'form',
109 'res_model': 'picking.dispatch',
110 'type': 'ir.actions.act_window',
111 'context': context,
112 'res_id': dispatch_id,
113 }
114 else:
115 raise orm.except_orm(_('Information'),
116 _('No ready pickings to deliver!'))
117 else:
118 raise orm.except_orm(_('Error'),
119 _('You need to set at least one unit to do.'))
0120
=== added file 'picking_dispatch_wave/dispatch_wave_view.xml'
--- picking_dispatch_wave/dispatch_wave_view.xml 1970-01-01 00:00:00 +0000
+++ picking_dispatch_wave/dispatch_wave_view.xml 2014-06-13 15:52:45 +0000
@@ -0,0 +1,46 @@
1<?xml version="1.0" encoding="utf-8"?>
2<openerp>
3 <data>
4
5 <act_window id="action_prepare_picking_dispatch"
6 name="Picking Wave"
7 res_model="stock.picking.dispatch.wave"
8 view_type="form"
9 view_mode="form"
10 target="new"
11 />
12
13 <menuitem id="menu_prepare_picking_dispatch"
14 parent="stock.menu_stock_warehouse_mgmt"
15 sequence="40"
16 action="action_prepare_picking_dispatch"
17 groups="stock.group_stock_user,stock.group_stock_manager"
18 />
19
20 <record model="ir.ui.view" id="picking_dispatch_prepare_form">
21 <field name="name">stock.picking.dispatch.wave form</field>
22 <field name="model">stock.picking.dispatch.wave</field>
23 <field name="arch" type="xml">
24 <form string="Picking Wave" version="7.0">
25 <group>
26 <p class="oe_grey">
27 This action will prepare you a picking dispatch
28 according the number of pickings that you set.
29 </p>
30 </group>
31 <group>
32 <field name="max_pickings_to_do"/>
33 <field name="picker_id"/>
34 </group>
35 <footer>
36 <button name="action_create_picking_dispatch" string="Create Picking Dispatch" type="object"
37 class="oe_highlight"/>
38 or
39 <button string="Cancel" class="oe_link" special="cancel" />
40 </footer>
41 </form>
42 </field>
43 </record>
44
45 </data>
46</openerp>
047
=== added directory 'picking_dispatch_wave/i18n'
=== added file 'picking_dispatch_wave/i18n/fr.po'
--- picking_dispatch_wave/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ picking_dispatch_wave/i18n/fr.po 2014-06-13 15:52:45 +0000
@@ -0,0 +1,82 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * picking_dispatch_wave
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 7.0\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2014-06-13 15:12+0000\n"
10"PO-Revision-Date: 2014-06-13 15:12+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: picking_dispatch_wave
19#: view:stock.picking.dispatch.wave:0
20msgid "This action will prepare you a picking dispatch\n"
21" according the number of pickings that you set."
22msgstr "Cette action va vous préparer un bon de préparation\n"
23" selon le nombre de livraisons défini."
24
25#. module: picking_dispatch_wave
26#: model:ir.actions.act_window,name:picking_dispatch_wave.action_prepare_picking_dispatch
27#: model:ir.ui.menu,name:picking_dispatch_wave.menu_prepare_picking_dispatch
28#: view:stock.picking.dispatch.wave:0
29msgid "Picking Wave"
30msgstr "Préparer n livraisons"
31
32#. module: picking_dispatch_wave
33#: help:stock.picking.dispatch.wave,max_pickings_to_do:0
34msgid "number maximum of pickings that we want to prepare"
35msgstr "Nombre maximum de livraisons que vous voulez préparez"
36
37#. module: picking_dispatch_wave
38#: field:stock.picking.dispatch.wave,max_pickings_to_do:0
39msgid "Number maximum of pickings to prepare"
40msgstr "Nombre maximum de livraisons à préparer"
41
42#. module: picking_dispatch_wave
43#: field:stock.picking.dispatch.wave,picker_id:0
44msgid "User"
45msgstr "Utilisateur"
46
47#. module: picking_dispatch_wave
48#: view:stock.picking.dispatch.wave:0
49msgid "Cancel"
50msgstr "Annuler"
51
52#. module: picking_dispatch_wave
53#: view:stock.picking.dispatch.wave:0
54msgid "Create Picking Dispatch"
55msgstr "Créer un bon de préparation"
56
57#. module: picking_dispatch_wave
58#: view:stock.picking.dispatch.wave:0
59msgid "or"
60msgstr "ou"
61
62#. module: picking_dispatch_wave
63#: help:stock.picking.dispatch.wave,picker_id:0
64msgid "the user to which the pickings are assigned"
65msgstr "l'utilisateur à qui les livraisons sont attribuées"
66
67#. module: picking_dispatch_wave
68#: model:ir.model,name:picking_dispatch_wave.model_stock_picking_dispatch_wave
69msgid "stock.picking.dispatch.wave"
70msgstr "stock.picking.dispatch.wave"
71
72#. module: picking_dispatch_wave
73#: code:addons/picking_dispatch_wave/dispatch_wave.py:116
74#, python-format
75msgid "You need to set at least one unit to do."
76msgstr "Sélectionner au moins une livraison à préparer"
77
78#. module: picking_dispatch_wave
79#: code:addons/picking_dispatch_wave/dispatch_wave.py:113
80#, python-format
81msgid "No ready pickings to deliver!"
82msgstr "Aucune livraison à préparer !"
083
=== added file 'picking_dispatch_wave/i18n/picking_dispatch_wave.pot'
--- picking_dispatch_wave/i18n/picking_dispatch_wave.pot 1970-01-01 00:00:00 +0000
+++ picking_dispatch_wave/i18n/picking_dispatch_wave.pot 2014-06-13 15:52:45 +0000
@@ -0,0 +1,70 @@
1# Translation of OpenERP Server.
2# This file contains the translation of the following modules:
3# * picking_dispatch_wave
4#
5msgid ""
6msgstr ""
7"Project-Id-Version: OpenERP Server 7.0\n"
8"Report-Msgid-Bugs-To: \n"
9"POT-Creation-Date: 2014-06-13 15:12+0000\n"
10"PO-Revision-Date: 2014-06-13 15:12+0000\n"
11"Last-Translator: <>\n"
12"Language-Team: \n"
13"MIME-Version: 1.0\n"
14"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Transfer-Encoding: \n"
16"Plural-Forms: \n"
17
18#. module: picking_dispatch_wave
19#: view:stock.picking.dispatch.wave:0
20msgid "This action will prepare you a picking dispatch\n"
21" according the number of pickings that you set."
22msgstr ""
23
24#. module: picking_dispatch_wave
25#: model:ir.actions.act_window,name:picking_dispatch_wave.action_prepare_picking_dispatch
26#: model:ir.ui.menu,name:picking_dispatch_wave.menu_prepare_picking_dispatch
27#: view:stock.picking.dispatch.wave:0
28msgid "Picking Wave"
29msgstr ""
30
31#. module: picking_dispatch_wave
32#: help:stock.picking.dispatch.wave,max_pickings_to_do:0
33msgid "number maximum of pickings that we want to prepare"
34msgstr ""
35
36#. module: picking_dispatch_wave
37#: field:stock.picking.dispatch.wave,max_pickings_to_do:0
38msgid "Number maximum of pickings to prepare"
39msgstr ""
40
41#. module: picking_dispatch_wave
42#: field:stock.picking.dispatch.wave,picker_id:0
43msgid "User"
44msgstr ""
45
46#. module: picking_dispatch_wave
47#: view:stock.picking.dispatch.wave:0
48msgid "Cancel"
49msgstr ""
50
51#. module: picking_dispatch_wave
52#: view:stock.picking.dispatch.wave:0
53msgid "Create Picking Dispatch"
54msgstr ""
55
56#. module: picking_dispatch_wave
57#: view:stock.picking.dispatch.wave:0
58msgid "or"
59msgstr ""
60
61#. module: picking_dispatch_wave
62#: help:stock.picking.dispatch.wave,picker_id:0
63msgid "the user to which the pickings are assigned"
64msgstr ""
65
66#. module: picking_dispatch_wave
67#: model:ir.model,name:picking_dispatch_wave.model_stock_picking_dispatch_wave
68msgid "stock.picking.dispatch.wave"
69msgstr ""
70
071
=== added directory 'picking_dispatch_wave/test'
=== added file 'picking_dispatch_wave/test/test_dispatch_wave.yml'
--- picking_dispatch_wave/test/test_dispatch_wave.yml 1970-01-01 00:00:00 +0000
+++ picking_dispatch_wave/test/test_dispatch_wave.yml 2014-06-13 15:52:45 +0000
@@ -0,0 +1,47 @@
1-
2 In order to test stock picking wave
3 I have to ensure when a picking dispatch wave is set, a picking dispatch is well created.
4-
5 I create a product
6-
7 !record {model: product.product, id: prod_wave}:
8 name: product_wave
9 procure_method: make_to_stock
10 supply_method: buy
11-
12 I create a SO
13-
14 !record {model: sale.order, id: so_wave}:
15 partner_id: base.res_partner_2
16 order_policy: 'manual'
17 picking_policy: 'direct'
18 order_line:
19 - product_id: prod_wave
20 product_uom_qty: 3
21-
22 Then I confirm the order
23-
24 !workflow {model: sale.order, action: order_confirm, ref: so_wave}
25-
26 Then (for test needs) I force the picking as ready to deliver
27-
28 !python {model: stock.picking}: |
29 picking = self.search(cr, uid, [('sale_id', '=', ref("so_wave"))])
30 self.force_assign(cr, uid, picking)
31-
32 Then I ask a picking dispatch wave with 1 unit.
33-
34 !record {model: stock.picking.dispatch.wave, id: wiz_wave}:
35 max_pickings_to_do: 1
36 picker_id: base.user_demo
37-
38 Then I confirm the demand
39-
40 !python {model: stock.picking.dispatch.wave}:
41 self.action_create_picking_dispatch(cr, uid, [ref("wiz_wave")], context=context)
42-
43 Then I check if the picking dispatch is created
44-
45 !python {model: picking.dispatch}: |
46 dispatchs = self.search(cr, uid, [('state','=','draft'),('picker_id','=',ref("base.user_demo"))])
47 assert len(dispatchs) == 1, "The dispatch is ready"

Subscribers

People subscribed via source and target branches