Merge lp:~akretion-team/stock-logistic-flows/stock-logistic-flows-61-product_serial into lp:stock-logistic-flows/6.1

Proposed by Sébastien BEAU - http://www.akretion.com
Status: Merged
Approved by: Alexandre Fayolle - camptocamp
Approved revision: 57
Merged at revision: 24
Proposed branch: lp:~akretion-team/stock-logistic-flows/stock-logistic-flows-61-product_serial
Merge into: lp:stock-logistic-flows/6.1
Diff against target: 1355 lines (+1289/-0)
13 files modified
product_serial/__init__.py (+26/-0)
product_serial/__openerp__.py (+47/-0)
product_serial/company.py (+39/-0)
product_serial/company_view.xml (+21/-0)
product_serial/i18n/es.po (+140/-0)
product_serial/i18n/fr_BE.po (+75/-0)
product_serial/i18n/mrp_prodlot_autosplit.pot (+75/-0)
product_serial/i18n/sv.po (+96/-0)
product_serial/prodlot_wizard.py (+119/-0)
product_serial/product.py (+37/-0)
product_serial/product_view.xml (+18/-0)
product_serial/stock.py (+297/-0)
product_serial/stock_view.xml (+299/-0)
To merge this branch: bzr merge lp:~akretion-team/stock-logistic-flows/stock-logistic-flows-61-product_serial
Reviewer Review Type Date Requested Status
Alexis de Lattre (community) code review and tests Approve
Alexandre Fayolle - camptocamp code review, no test Approve
Review via email: mp+162974@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Sébastien BEAU - http://www.akretion.com (sebastien.beau) wrote :

Extract the module product_serial from the extra-addons

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

LGTM

review: Approve (code review, no test)
Revision history for this message
Alexis de Lattre (alexis-via) wrote :

I have checked that the extraction from extra-6.0 is OK and that it works well on OpenERP 6.1. So it's ok to merge.

review: Approve (code review and tests)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'product_serial'
2=== added file 'product_serial/__init__.py'
3--- product_serial/__init__.py 1970-01-01 00:00:00 +0000
4+++ product_serial/__init__.py 2013-05-08 13:17:25 +0000
5@@ -0,0 +1,26 @@
6+# -*- encoding: utf-8 -*-
7+##############################################################################
8+#
9+# Product serial module for OpenERP
10+# Copyright (C) 2008 Raphaël Valyi
11+#
12+# This program is free software: you can redistribute it and/or modify
13+# it under the terms of the GNU Affero General Public License as
14+# published by the Free Software Foundation, either version 3 of the
15+# License, or (at your option) any later version.
16+#
17+# This program is distributed in the hope that it will be useful,
18+# but WITHOUT ANY WARRANTY; without even the implied warranty of
19+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20+# GNU Affero General Public License for more details.
21+#
22+# You should have received a copy of the GNU Affero General Public License
23+# along with this program. If not, see <http://www.gnu.org/licenses/>.
24+#
25+##############################################################################
26+
27+import product
28+import stock
29+import company
30+import prodlot_wizard
31+
32
33=== added file 'product_serial/__openerp__.py'
34--- product_serial/__openerp__.py 1970-01-01 00:00:00 +0000
35+++ product_serial/__openerp__.py 2013-05-08 13:17:25 +0000
36@@ -0,0 +1,47 @@
37+# -*- encoding: utf-8 -*-
38+##############################################################################
39+#
40+# Copyright (C) 2008 Raphaël Valyi
41+#
42+# This program is free software: you can redistribute it and/or modify
43+# it under the terms of the GNU Affero General Public License as
44+# published by the Free Software Foundation, either version 3 of the
45+# License, or (at your option) any later version.
46+#
47+# This program is distributed in the hope that it will be useful,
48+# but WITHOUT ANY WARRANTY; without even the implied warranty of
49+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50+# GNU Affero General Public License for more details.
51+#
52+# You should have received a copy of the GNU Affero General Public License
53+# along with this program. If not, see <http://www.gnu.org/licenses/>.
54+#
55+##############################################################################
56+
57+{
58+ "name" : "Unique serial number management",
59+ "version" : "1.0.0",
60+ "author" : "Akretion, NaN·tic",
61+ "website" : "http://www.akretion.com",
62+ "depends" : ['stock'],
63+ "category" : "Generic Modules/Inventory Control",
64+ "license": "AGPL-3",
65+ "description":"""Turns production lot tracking numbers into unique per product instance code (serial number).
66+ Moreover, it
67+ 1) adds a new selection field on the product form to enable or disable this behavior and with split type choice (you should also enable in/out tracking)
68+ 2) then forbids to perform a move if a move involves more than one product instance
69+ 3) automagically splits up picking list movements into one movement per product instance or logistical unit packing qty (in that case, only the first LU is taken into account at the present time. Improvement to take them all to be done !!!)
70+ 4) turns incoming pickings into an editable grid where you can directly type the codes
71+ of a new production and tracking number/code to create and associate to the move (it also checks it
72+ doesn't exist yet)
73+
74+ We would also like to extend this module to split automatic production orders (from MRP engine) into several individual production orders in order
75+ to make it easy to encode the serial numbers in the production. Let us know if you would like that simple extension to be made.
76+ """,
77+ "init_xml" : [],
78+ "demo_xml" : [],
79+ "update_xml" : ["product_view.xml", "company_view.xml", "stock_view.xml"],
80+ "active": False,
81+ "installable": True
82+}
83+
84
85=== added file 'product_serial/company.py'
86--- product_serial/company.py 1970-01-01 00:00:00 +0000
87+++ product_serial/company.py 2013-05-08 13:17:25 +0000
88@@ -0,0 +1,39 @@
89+# -*- encoding: utf-8 -*-
90+##############################################################################
91+#
92+# Product serial module for OpenERP
93+# Copyright (C) 2010-2011 Anevia. All Rights Reserved
94+# (written by Sebastien Beau <sebastien.beau@akretion.com>)
95+#
96+# This program is free software: you can redistribute it and/or modify
97+# it under the terms of the GNU Affero General Public License as
98+# published by the Free Software Foundation, either version 3 of the
99+# License, or (at your option) any later version.
100+#
101+# This program is distributed in the hope that it will be useful,
102+# but WITHOUT ANY WARRANTY; without even the implied warranty of
103+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
104+# GNU Affero General Public License for more details.
105+#
106+# You should have received a copy of the GNU Affero General Public License
107+# along with this program. If not, see <http://www.gnu.org/licenses/>.
108+#
109+##############################################################################
110+
111+from osv import osv, fields
112+
113+class company(osv.osv):
114+ _inherit = 'res.company'
115+
116+ _columns = {
117+ 'autosplit_is_active': fields.boolean('Active auto split', help="Active the automatic split of move lines on the pickings."),
118+ 'is_group_invoice_line': fields.boolean('Group invoice lines', help="If active, OpenERP will group the identical invoice lines. If inactive, each move line will generate one invoice line."),
119+ }
120+
121+ _defaults = {
122+ 'autosplit_is_active': lambda *a: True,
123+ 'is_group_invoice_line': lambda *a: True,
124+ }
125+
126+company()
127+
128
129=== added file 'product_serial/company_view.xml'
130--- product_serial/company_view.xml 1970-01-01 00:00:00 +0000
131+++ product_serial/company_view.xml 2013-05-08 13:17:25 +0000
132@@ -0,0 +1,21 @@
133+<?xml version="1.0" ?>
134+<openerp>
135+ <data>
136+
137+ <record id="autosplit_company" model="ir.ui.view">
138+ <field name="name">res.company.autosplit.config</field>
139+ <field name="model">res.company</field>
140+ <field name="type">form</field>
141+ <field name="inherit_id" ref="base.view_company_form"/>
142+ <field name="arch" type="xml">
143+ <page string="Configuration" position="inside">
144+ <separator string="Product serial" colspan="4"/>
145+ <field name="autosplit_is_active"/>
146+ <field name="is_group_invoice_line"/>
147+ <newline/>
148+ </page>
149+ </field>
150+ </record>
151+
152+ </data>
153+</openerp>
154
155=== added directory 'product_serial/i18n'
156=== added file 'product_serial/i18n/es.po'
157--- product_serial/i18n/es.po 1970-01-01 00:00:00 +0000
158+++ product_serial/i18n/es.po 2013-05-08 13:17:25 +0000
159@@ -0,0 +1,140 @@
160+# Spanish translation for openobject-addons
161+# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011
162+# This file is distributed under the same license as the openobject-addons package.
163+# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
164+#
165+msgid ""
166+msgstr ""
167+"Project-Id-Version: openobject-addons\n"
168+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
169+"POT-Creation-Date: 2009-11-26 10:28+0000\n"
170+"PO-Revision-Date: 2011-02-15 15:14+0000\n"
171+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
172+"Language-Team: Spanish <es@li.org>\n"
173+"MIME-Version: 1.0\n"
174+"Content-Type: text/plain; charset=UTF-8\n"
175+"Content-Transfer-Encoding: 8bit\n"
176+"X-Launchpad-Export-Date: 2011-07-08 05:57+0000\n"
177+"X-Generator: Launchpad (build 13168)\n"
178+
179+#. module: mrp_prodlot_autosplit
180+#: field:product.product,unique_production_number:0
181+msgid "Unique Production Number"
182+msgstr "Número de lote de producción único (número de serie)"
183+
184+#. module: mrp_prodlot_autosplit
185+#: constraint:ir.ui.view:0
186+msgid "Invalid XML for View Architecture!"
187+msgstr "¡XML no válido para la definición de la vista!"
188+
189+#. module: mrp_prodlot_autosplit
190+#: model:ir.module.module,description:mrp_prodlot_autosplit.module_meta_information
191+msgid ""
192+"Turns production lot tracking numbers into unique per product instance code "
193+"(serial number).\n"
194+" Moreover, it\n"
195+" 1) adds a new checkbox on the product form to enable or disable this "
196+"behavior (you should also enable in/out tracking)\n"
197+" 2) then forbids to perform a move if a move involves more than one "
198+"product instance\n"
199+" 3) automagically splits up picking list movements into one movement per "
200+"product instance\n"
201+" 4) turns incoming pickings into an editable grid where you can directly "
202+"type the code\n"
203+" of a new production number/code to create and associate to the move (it "
204+"also checks it\n"
205+" doesn't exist yet)\n"
206+" \n"
207+" Important Note 1: serial numbers are more easily encode using an "
208+"editable tree grid, including a special field with new serial to be "
209+"created.\n"
210+" However, there is currently a limitation in the OpenObject framework "
211+"preventing from easily changing non editable trees to editable trees\n"
212+" by simple extension. Rather than overwriting all views, we prefer give "
213+"only one example: the active customied view for easy serial encoding\n"
214+" is available using Stock Management > Incoming Products. Looking that "
215+"that view definition, the same thing is easily achieved in\n"
216+" other picking list, like out going products for instance. However it's "
217+"not \"on\" by default, you would need to work it out for your case.\n"
218+" Meanwhile, we hope Tiny add a third \"merge_attributes\" view extension "
219+"point to the 3 existing ones: \"before\", \"after\" and \"replace\".\n"
220+" It would basically simply merge the attributes given (redefined) in the "
221+"original view XML and let inner content unchanged.\n"
222+" Blueprint is registred here: https://blueprints.launchpad.net/openobject-"
223+"server/+spec/merge-attributes-view-extension-point\n"
224+" \n"
225+" Important Note 2: this module doesn't split product bill of materials in "
226+"MRP since they don't use pickings\n"
227+" A good workaround when generating production orders manually one by one "
228+"is too define several lines of individual products in nomemclatures\n"
229+" and produce 1 by 1 (if possible) to make it easier to encode unique "
230+"prodlot in production orders too.\n"
231+" We would also like to extend this module to split automatic production "
232+"orders (from MRP engine) into several individual production orders in order\n"
233+" to make it easy to encode the serial numbers in the production. Let us "
234+"know if you would like that simple extension to be made.\n"
235+" "
236+msgstr ""
237+"Convierte los números de lote en uno único por producto (número de serie)\n"
238+" Más aún,\n"
239+" 1) Añade una nueva casilla de verificación en el formulario de producto "
240+"para activar o desactivar esta funcionalidad(debería también activar lotes "
241+"en entrada/salida\n"
242+" 2) Prohibe realizar un movimiento si el movimiento requiere más de una "
243+"instancia de producto\n"
244+" 3) Automágicamente desglosa la línea de movimientos para varios "
245+"productos en un único movimiento por cada producto\n"
246+" 4) Convierte los albaranes de entrada en una tabla editable donde puede "
247+"directamente escribir el número de serie de un nuevo número de serie para "
248+"crearlo y asociarlo al movimiento (también verifica que no exista antes)\n"
249+"\n"
250+" Importante Nota 1: Los número de serie se codifican mejor utilizando una "
251+"tabla editable, que incluye un campo especial con el nuevo número de serie "
252+"para ser creado. En cualquier caso hay actualmente una limitación en el "
253+"framework de OpenObject que previene de cambiar fácilmente grids no "
254+"editables a editables por una simple extensión. En vez de sobreescribir "
255+"todas las vistas, preferimos dar un único ejemplo: La vista activa "
256+"modificada para facilitar la codificación de números de serie está "
257+"disponible utilizando Fabricación / productos entrantes. Buscando esta "
258+"definción de la vista, esto mismo es fácilmente trasladable a otros "
259+"albaranes, como por ejemplo los de salida. De todas formas no está activo "
260+"por defecto, necesitaría trabajar con ello para su caso específico.\n"
261+"Mientras tanto, esperamos que Tiny añada una tercera vista "
262+"\"merge_attributes\" a los 3 existentes: \"antes\", \"despues\" y "
263+"\"reemplazar\". Básicamente permitiría combinar los atributos dados "
264+"(redefinidos) en la vista origial XML y dejar el contenido sin cambiar.\n"
265+"La solicitud de mejora está registrada aquí: "
266+"https://blueprints.launchpad.net/openobject-server/+spec/merge-attributes-"
267+"view-extension-point\n"
268+"\n"
269+"Importante Nota 2: Este módulo no desglos la lista de materiales en MRP ya "
270+"que no usa albaranes.\n"
271+"Una buena aproximación al generar órdenes de fabricación manualmente una por "
272+"una es definir varias líneas de productos individuales en nomenclaturas y "
273+"producir uno a uno ( si es posible) para hacer más fácil la codificación de "
274+"un único número de serie también en las órdenes de producción.\n"
275+"También queremos extender este módulo para desglosar automáticamente órdenes "
276+"de producción (desde el motor MRP) en varias órdenes individuales para "
277+"faciliar la codificación de los números de serie en producción. Haznos saber "
278+"si te gustaría que abordásemos el desarrollo de esta extensión.\n"
279+" "
280+
281+#. module: mrp_prodlot_autosplit
282+#: field:stock.production.lot,last_location_id:0
283+msgid "Last Location"
284+msgstr "Última ubicación"
285+
286+#. module: mrp_prodlot_autosplit
287+#: model:ir.module.module,shortdesc:mrp_prodlot_autosplit.module_meta_information
288+msgid "Unique serial number management"
289+msgstr "Gestión de número de serie único"
290+
291+#. module: mrp_prodlot_autosplit
292+#: field:stock.move,new_prodlot_code:0
293+msgid "Production Tracking Code To Create"
294+msgstr "Número de tracking de producción para crear"
295+
296+#. module: mrp_prodlot_autosplit
297+#: view:stock.picking:0
298+msgid "Stock Moves"
299+msgstr "Movimientos de stock"
300
301=== added file 'product_serial/i18n/fr_BE.po'
302--- product_serial/i18n/fr_BE.po 1970-01-01 00:00:00 +0000
303+++ product_serial/i18n/fr_BE.po 2013-05-08 13:17:25 +0000
304@@ -0,0 +1,75 @@
305+# Translation of OpenERP Server.
306+# This file contains the translation of the following modules:
307+# * mrp_prodlot_autosplit
308+#
309+msgid ""
310+msgstr ""
311+"Project-Id-Version: OpenERP Server 5.0.6\n"
312+"Report-Msgid-Bugs-To: support@openerp.com\n"
313+"POT-Creation-Date: 2009-11-26 10:28:43+0000\n"
314+"PO-Revision-Date: 2009-11-26 10:28:43+0000\n"
315+"Last-Translator: <>\n"
316+"Language-Team: \n"
317+"MIME-Version: 1.0\n"
318+"Content-Type: text/plain; charset=UTF-8\n"
319+"Content-Transfer-Encoding: \n"
320+"Plural-Forms: \n"
321+
322+#. module: mrp_prodlot_autosplit
323+#: field:product.product,unique_production_number:0
324+msgid "Unique Production Number"
325+msgstr ""
326+
327+#. module: mrp_prodlot_autosplit
328+#: constraint:ir.ui.view:0
329+msgid "Invalid XML for View Architecture!"
330+msgstr ""
331+
332+#. module: mrp_prodlot_autosplit
333+#: model:ir.module.module,description:mrp_prodlot_autosplit.module_meta_information
334+msgid "Turns production lot tracking numbers into unique per product instance code (serial number).\n"
335+" Moreover, it\n"
336+" 1) adds a new checkbox on the product form to enable or disable this behavior (you should also enable in/out tracking)\n"
337+" 2) then forbids to perform a move if a move involves more than one product instance\n"
338+" 3) automagically splits up picking list movements into one movement per product instance\n"
339+" 4) turns incoming pickings into an editable grid where you can directly type the code\n"
340+" of a new production number/code to create and associate to the move (it also checks it\n"
341+" doesn't exist yet)\n"
342+" \n"
343+" Important Note 1: serial numbers are more easily encode using an editable tree grid, including a special field with new serial to be created.\n"
344+" However, there is currently a limitation in the OpenObject framework preventing from easily changing non editable trees to editable trees\n"
345+" by simple extension. Rather than overwriting all views, we prefer give only one example: the active customied view for easy serial encoding\n"
346+" is available using Stock Management > Incoming Products. Looking that that view definition, the same thing is easily achieved in\n"
347+" other picking list, like out going products for instance. However it's not \"on\" by default, you would need to work it out for your case.\n"
348+" Meanwhile, we hope Tiny add a third \"merge_attributes\" view extension point to the 3 existing ones: \"before\", \"after\" and \"replace\".\n"
349+" It would basically simply merge the attributes given (redefined) in the original view XML and let inner content unchanged.\n"
350+" Blueprint is registred here: https://blueprints.launchpad.net/openobject-server/+spec/merge-attributes-view-extension-point\n"
351+" \n"
352+" Important Note 2: this module doesn't split product bill of materials in MRP since they don't use pickings\n"
353+" A good workaround when generating production orders manually one by one is too define several lines of individual products in nomemclatures\n"
354+" and produce 1 by 1 (if possible) to make it easier to encode unique prodlot in production orders too.\n"
355+" We would also like to extend this module to split automatic production orders (from MRP engine) into several individual production orders in order\n"
356+" to make it easy to encode the serial numbers in the production. Let us know if you would like that simple extension to be made.\n"
357+" "
358+msgstr ""
359+
360+#. module: mrp_prodlot_autosplit
361+#: field:stock.production.lot,last_location_id:0
362+msgid "Last Location"
363+msgstr ""
364+
365+#. module: mrp_prodlot_autosplit
366+#: model:ir.module.module,shortdesc:mrp_prodlot_autosplit.module_meta_information
367+msgid "Unique serial number management"
368+msgstr ""
369+
370+#. module: mrp_prodlot_autosplit
371+#: field:stock.move,new_prodlot_code:0
372+msgid "Production Tracking Code To Create"
373+msgstr ""
374+
375+#. module: mrp_prodlot_autosplit
376+#: view:stock.picking:0
377+msgid "Stock Moves"
378+msgstr ""
379+
380
381=== added file 'product_serial/i18n/mrp_prodlot_autosplit.pot'
382--- product_serial/i18n/mrp_prodlot_autosplit.pot 1970-01-01 00:00:00 +0000
383+++ product_serial/i18n/mrp_prodlot_autosplit.pot 2013-05-08 13:17:25 +0000
384@@ -0,0 +1,75 @@
385+# Translation of OpenERP Server.
386+# This file contains the translation of the following modules:
387+# * mrp_prodlot_autosplit
388+#
389+msgid ""
390+msgstr ""
391+"Project-Id-Version: OpenERP Server 5.0.6\n"
392+"Report-Msgid-Bugs-To: support@openerp.com\n"
393+"POT-Creation-Date: 2009-11-26 10:28:43+0000\n"
394+"PO-Revision-Date: 2009-11-26 10:28:43+0000\n"
395+"Last-Translator: <>\n"
396+"Language-Team: \n"
397+"MIME-Version: 1.0\n"
398+"Content-Type: text/plain; charset=UTF-8\n"
399+"Content-Transfer-Encoding: \n"
400+"Plural-Forms: \n"
401+
402+#. module: mrp_prodlot_autosplit
403+#: field:product.product,unique_production_number:0
404+msgid "Unique Production Number"
405+msgstr ""
406+
407+#. module: mrp_prodlot_autosplit
408+#: constraint:ir.ui.view:0
409+msgid "Invalid XML for View Architecture!"
410+msgstr ""
411+
412+#. module: mrp_prodlot_autosplit
413+#: model:ir.module.module,description:mrp_prodlot_autosplit.module_meta_information
414+msgid "Turns production lot tracking numbers into unique per product instance code (serial number).\n"
415+" Moreover, it\n"
416+" 1) adds a new checkbox on the product form to enable or disable this behavior (you should also enable in/out tracking)\n"
417+" 2) then forbids to perform a move if a move involves more than one product instance\n"
418+" 3) automagically splits up picking list movements into one movement per product instance\n"
419+" 4) turns incoming pickings into an editable grid where you can directly type the code\n"
420+" of a new production number/code to create and associate to the move (it also checks it\n"
421+" doesn't exist yet)\n"
422+" \n"
423+" Important Note 1: serial numbers are more easily encode using an editable tree grid, including a special field with new serial to be created.\n"
424+" However, there is currently a limitation in the OpenObject framework preventing from easily changing non editable trees to editable trees\n"
425+" by simple extension. Rather than overwriting all views, we prefer give only one example: the active customied view for easy serial encoding\n"
426+" is available using Stock Management > Incoming Products. Looking that that view definition, the same thing is easily achieved in\n"
427+" other picking list, like out going products for instance. However it's not \"on\" by default, you would need to work it out for your case.\n"
428+" Meanwhile, we hope Tiny add a third \"merge_attributes\" view extension point to the 3 existing ones: \"before\", \"after\" and \"replace\".\n"
429+" It would basically simply merge the attributes given (redefined) in the original view XML and let inner content unchanged.\n"
430+" Blueprint is registred here: https://blueprints.launchpad.net/openobject-server/+spec/merge-attributes-view-extension-point\n"
431+" \n"
432+" Important Note 2: this module doesn't split product bill of materials in MRP since they don't use pickings\n"
433+" A good workaround when generating production orders manually one by one is too define several lines of individual products in nomemclatures\n"
434+" and produce 1 by 1 (if possible) to make it easier to encode unique prodlot in production orders too.\n"
435+" We would also like to extend this module to split automatic production orders (from MRP engine) into several individual production orders in order\n"
436+" to make it easy to encode the serial numbers in the production. Let us know if you would like that simple extension to be made.\n"
437+" "
438+msgstr ""
439+
440+#. module: mrp_prodlot_autosplit
441+#: field:stock.production.lot,last_location_id:0
442+msgid "Last Location"
443+msgstr ""
444+
445+#. module: mrp_prodlot_autosplit
446+#: model:ir.module.module,shortdesc:mrp_prodlot_autosplit.module_meta_information
447+msgid "Unique serial number management"
448+msgstr ""
449+
450+#. module: mrp_prodlot_autosplit
451+#: field:stock.move,new_prodlot_code:0
452+msgid "Production Tracking Code To Create"
453+msgstr ""
454+
455+#. module: mrp_prodlot_autosplit
456+#: view:stock.picking:0
457+msgid "Stock Moves"
458+msgstr ""
459+
460
461=== added file 'product_serial/i18n/sv.po'
462--- product_serial/i18n/sv.po 1970-01-01 00:00:00 +0000
463+++ product_serial/i18n/sv.po 2013-05-08 13:17:25 +0000
464@@ -0,0 +1,96 @@
465+# Translation of OpenERP Server.
466+# This file contains the translation of the following modules:
467+# * mrp_prodlot_autosplit
468+#
469+msgid ""
470+msgstr ""
471+"Project-Id-Version: OpenERP Server 5.0.14\n"
472+"Report-Msgid-Bugs-To: support@openerp.com\n"
473+"POT-Creation-Date: 2009-11-26 10:28+0000\n"
474+"PO-Revision-Date: 2011-02-15 15:14+0000\n"
475+"Last-Translator: Olivier Dony (OpenERP) <Unknown>\n"
476+"Language-Team: \n"
477+"MIME-Version: 1.0\n"
478+"Content-Type: text/plain; charset=UTF-8\n"
479+"Content-Transfer-Encoding: 8bit\n"
480+"X-Launchpad-Export-Date: 2011-07-08 05:57+0000\n"
481+"X-Generator: Launchpad (build 13168)\n"
482+
483+#. module: mrp_prodlot_autosplit
484+#: field:product.product,unique_production_number:0
485+msgid "Unique Production Number"
486+msgstr ""
487+
488+#. module: mrp_prodlot_autosplit
489+#: constraint:ir.ui.view:0
490+msgid "Invalid XML for View Architecture!"
491+msgstr ""
492+
493+#. module: mrp_prodlot_autosplit
494+#: model:ir.module.module,description:mrp_prodlot_autosplit.module_meta_information
495+msgid ""
496+"Turns production lot tracking numbers into unique per product instance code "
497+"(serial number).\n"
498+" Moreover, it\n"
499+" 1) adds a new checkbox on the product form to enable or disable this "
500+"behavior (you should also enable in/out tracking)\n"
501+" 2) then forbids to perform a move if a move involves more than one "
502+"product instance\n"
503+" 3) automagically splits up picking list movements into one movement per "
504+"product instance\n"
505+" 4) turns incoming pickings into an editable grid where you can directly "
506+"type the code\n"
507+" of a new production number/code to create and associate to the move (it "
508+"also checks it\n"
509+" doesn't exist yet)\n"
510+" \n"
511+" Important Note 1: serial numbers are more easily encode using an "
512+"editable tree grid, including a special field with new serial to be "
513+"created.\n"
514+" However, there is currently a limitation in the OpenObject framework "
515+"preventing from easily changing non editable trees to editable trees\n"
516+" by simple extension. Rather than overwriting all views, we prefer give "
517+"only one example: the active customied view for easy serial encoding\n"
518+" is available using Stock Management > Incoming Products. Looking that "
519+"that view definition, the same thing is easily achieved in\n"
520+" other picking list, like out going products for instance. However it's "
521+"not \"on\" by default, you would need to work it out for your case.\n"
522+" Meanwhile, we hope Tiny add a third \"merge_attributes\" view extension "
523+"point to the 3 existing ones: \"before\", \"after\" and \"replace\".\n"
524+" It would basically simply merge the attributes given (redefined) in the "
525+"original view XML and let inner content unchanged.\n"
526+" Blueprint is registred here: https://blueprints.launchpad.net/openobject-"
527+"server/+spec/merge-attributes-view-extension-point\n"
528+" \n"
529+" Important Note 2: this module doesn't split product bill of materials in "
530+"MRP since they don't use pickings\n"
531+" A good workaround when generating production orders manually one by one "
532+"is too define several lines of individual products in nomemclatures\n"
533+" and produce 1 by 1 (if possible) to make it easier to encode unique "
534+"prodlot in production orders too.\n"
535+" We would also like to extend this module to split automatic production "
536+"orders (from MRP engine) into several individual production orders in order\n"
537+" to make it easy to encode the serial numbers in the production. Let us "
538+"know if you would like that simple extension to be made.\n"
539+" "
540+msgstr ""
541+
542+#. module: mrp_prodlot_autosplit
543+#: field:stock.production.lot,last_location_id:0
544+msgid "Last Location"
545+msgstr ""
546+
547+#. module: mrp_prodlot_autosplit
548+#: model:ir.module.module,shortdesc:mrp_prodlot_autosplit.module_meta_information
549+msgid "Unique serial number management"
550+msgstr "Unique serial number management"
551+
552+#. module: mrp_prodlot_autosplit
553+#: field:stock.move,new_prodlot_code:0
554+msgid "Production Tracking Code To Create"
555+msgstr ""
556+
557+#. module: mrp_prodlot_autosplit
558+#: view:stock.picking:0
559+msgid "Stock Moves"
560+msgstr ""
561
562=== added file 'product_serial/prodlot_wizard.py'
563--- product_serial/prodlot_wizard.py 1970-01-01 00:00:00 +0000
564+++ product_serial/prodlot_wizard.py 2013-05-08 13:17:25 +0000
565@@ -0,0 +1,119 @@
566+# -*- encoding: utf-8 -*-
567+##############################################################################
568+#
569+# Product serial module for OpenERP
570+# Copyright (C) 2010 NaN Projectes de Programari Lliure, S.L.
571+# http://www.NaN-tic.com
572+#
573+# This program is free software: you can redistribute it and/or modify
574+# it under the terms of the GNU Affero General Public License as
575+# published by the Free Software Foundation, either version 3 of the
576+# License, or (at your option) any later version.
577+#
578+# This program is distributed in the hope that it will be useful,
579+# but WITHOUT ANY WARRANTY; without even the implied warranty of
580+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
581+# GNU Affero General Public License for more details.
582+#
583+# You should have received a copy of the GNU Affero General Public License
584+# along with this program. If not, see <http://www.gnu.org/licenses/>.
585+#
586+##############################################################################
587+
588+from osv import osv, fields
589+from tools.translate import _
590+
591+def is_integer(value):
592+ try:
593+ int(value)
594+ return True
595+ except:
596+ return False
597+
598+class stock_picking_prodlot_selection_wizard(osv.osv_memory):
599+ _name = 'stock.picking.prodlot.selection'
600+
601+ _columns = {
602+ 'product_id': fields.many2one('product.product', 'Product', required=True),
603+ 'first_lot': fields.char('First Lot Number', size=256),
604+ 'last_lot': fields.char('Last Lot Number', size=256),
605+ }
606+
607+ def action_cancel(self, cr, uid, ids, context=None):
608+ return {}
609+
610+ def action_accept(self, cr, uid, ids, context=None):
611+ if context is None:
612+ context = {}
613+ if not ids:
614+ return {}
615+ if not 'active_id' in context:
616+ return {}
617+
618+ record = self.browse(cr, uid, ids[0], context)
619+ first = record.first_lot
620+ last = record.last_lot
621+ if len(first) != len(last):
622+ raise osv.except_osv(_('Invalid lot numbers'), _('First and last lot numbers must have the same length.'))
623+
624+
625+ first_number = ''
626+ last_number = ''
627+ position = -1
628+ for x in xrange(len(first)):
629+ if not position and first[x] == last[x]:
630+ continue
631+ if not position:
632+ position = x
633+ if not is_integer(first[x]) or not is_integer(last[x]):
634+ raise osv.except_osv(_('Invalid lot numbers'), _('First and last lot numbers differ in non-numeric values.'))
635+ first_number += first[x]
636+ last_number += last[x]
637+
638+ if position >= 0:
639+ prefix = first[:position-1]
640+ else:
641+ prefix = ''
642+
643+ number_fill = len(first_number)
644+ first_number = int(first_number)
645+ last_number = int(last_number)
646+
647+ if last_number < first_number:
648+ raise osv.except_osv(_('Invalid lot numbers'), _('First lot number is greater than the last one.'))
649+
650+ picking_id = context['active_id']
651+ current_number = first_number
652+ for move in self.pool.get('stock.picking').browse(cr, uid, picking_id, context).move_lines:
653+ if move.prodlot_id or move.product_id != record.product_id:
654+ continue
655+
656+ current_lot = '%%s%%0%dd' % number_fill % (prefix, current_number)
657+ lot_ids = self.pool.get('stock.production.lot').search(cr, uid, [('name','=',current_lot)], limit=1, context=context)
658+ if not lot_ids:
659+ raise osv.except_osv(_('Invalid lot numbers'), _('Production lot %s not found.') % current_lot)
660+
661+ ctx = context.copy()
662+ ctx['location_id'] = move.location_id.id
663+ prodlot = self.pool.get('stock.production.lot').browse(cr, uid, lot_ids[0], ctx)
664+
665+ if prodlot.product_id != record.product_id:
666+ raise osv.except_osv(_('Invalid lot numbers'), _('Production lot %s exists but not for product %s.') % (current_lot, record.product_id.name))
667+
668+ if prodlot.stock_available < move.product_qty:
669+ raise osv.except_osv(_('Invalid lot numbers'), _('Not enough stock available of production lot %s.') % current_lot)
670+
671+ self.pool.get('stock.move').write(cr, uid, [move.id], {
672+ 'prodlot_id': lot_ids[0],
673+ }, context)
674+
675+ current_number += 1
676+ if current_number > last_number:
677+ break
678+
679+ return {}
680+
681+
682+
683+stock_picking_prodlot_selection_wizard()
684+
685
686=== added file 'product_serial/product.py'
687--- product_serial/product.py 1970-01-01 00:00:00 +0000
688+++ product_serial/product.py 2013-05-08 13:17:25 +0000
689@@ -0,0 +1,37 @@
690+# -*- encoding: utf-8 -*-
691+##############################################################################
692+#
693+# Product serial module for OpenERP
694+# Copyright (C) 2008 Raphaël Valyi
695+#
696+# This program is free software: you can redistribute it and/or modify
697+# it under the terms of the GNU Affero General Public License as
698+# published by the Free Software Foundation, either version 3 of the
699+# License, or (at your option) any later version.
700+#
701+# This program is distributed in the hope that it will be useful,
702+# but WITHOUT ANY WARRANTY; without even the implied warranty of
703+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
704+# GNU Affero General Public License for more details.
705+#
706+# You should have received a copy of the GNU Affero General Public License
707+# along with this program. If not, see <http://www.gnu.org/licenses/>.
708+#
709+##############################################################################
710+
711+from osv import fields, osv
712+
713+class product_product(osv.osv):
714+ _inherit = "product.product"
715+
716+ _columns = {
717+ 'lot_split_type': fields.selection([('none','None'),
718+ ('single','Single'),
719+ ('lu','Logistical Unit')], 'Lot split type', required=True, help="None: no split ; single: 1 line/product unit ; Logistical Unit: split using the 1st Logistical Unit quantity of the product form packaging tab (to be improved to take into account all LU)"),
720+ }
721+ _defaults = {
722+ 'lot_split_type': lambda *a: 'none',
723+ }
724+
725+product_product()
726+
727
728=== added file 'product_serial/product_view.xml'
729--- product_serial/product_view.xml 1970-01-01 00:00:00 +0000
730+++ product_serial/product_view.xml 2013-05-08 13:17:25 +0000
731@@ -0,0 +1,18 @@
732+<?xml version="1.0" encoding="utf-8"?>
733+<openerp>
734+ <data>
735+
736+ <record id="view_normal_unique_production_number_form" model="ir.ui.view">
737+ <field name="name">product.normal.stock.form.unique_production_number.inherit</field>
738+ <field name="model">product.product</field>
739+ <field name="type">form</field>
740+ <field name="inherit_id" ref="stock.view_normal_stock_property_form"/>
741+ <field name="arch" type="xml">
742+ <field name="track_outgoing" position="after">
743+ <field name="lot_split_type" />
744+ </field>
745+ </field>
746+ </record>
747+
748+ </data>
749+</openerp>
750
751=== added file 'product_serial/stock.py'
752--- product_serial/stock.py 1970-01-01 00:00:00 +0000
753+++ product_serial/stock.py 2013-05-08 13:17:25 +0000
754@@ -0,0 +1,297 @@
755+# -*- encoding: utf-8 -*-
756+##############################################################################
757+#
758+# Product serial module for OpenERP
759+# Copyright (C) 2008 Raphaël Valyi
760+# Copyright (C) 2011 Anevia S.A. - Ability to group invoice lines
761+# written by Alexis Demeaulte <alexis.demeaulte@anevia.com>
762+# Copyright (C) 2011 Akretion - Ability to split lines on logistical units
763+# written by Emmanuel Samyn
764+#
765+# This program is free software: you can redistribute it and/or modify
766+# it under the terms of the GNU Affero General Public License as
767+# published by the Free Software Foundation, either version 3 of the
768+# License, or (at your option) any later version.
769+#
770+# This program is distributed in the hope that it will be useful,
771+# but WITHOUT ANY WARRANTY; without even the implied warranty of
772+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
773+# GNU Affero General Public License for more details.
774+#
775+# You should have received a copy of the GNU Affero General Public License
776+# along with this program. If not, see <http://www.gnu.org/licenses/>.
777+#
778+##############################################################################
779+
780+from osv import fields, osv
781+import hashlib
782+from tools.translate import _
783+
784+
785+class stock_move(osv.osv):
786+ _inherit = "stock.move"
787+ # We order by product name because otherwise, after the split,
788+ # the products are "mixed" and not grouped by product name any more
789+ _order = "picking_id, name, id"
790+
791+ def copy(self, cr, uid, id, default=None, context=None):
792+ if not default:
793+ default = {}
794+ default['new_prodlot_code'] = False
795+ return super(stock_move, self).copy(cr, uid, id, default, context=context)
796+
797+ def _get_prodlot_code(self, cr, uid, ids, field_name, arg, context=None):
798+ res = {}
799+ for move in self.browse(cr, uid, ids):
800+ res[move.id] = move.prodlot_id and move.prodlot_id.name or False
801+ return res
802+
803+ def _set_prodlot_code(self, cr, uid, ids, name, value, arg, context=None):
804+ if not value: return False
805+
806+ if isinstance(ids, (int, long)):
807+ ids = [ids]
808+
809+ for move in self.browse(cr, uid, ids, context=context):
810+ product_id = move.product_id.id
811+ existing_prodlot = move.prodlot_id
812+ if existing_prodlot: #avoid creating a prodlot twice
813+ self.pool.get('stock.production.lot').write(cr, uid, existing_prodlot.id, {'name': value})
814+ else:
815+ prodlot_id = self.pool.get('stock.production.lot').create(cr, uid, {
816+ 'name': value,
817+ 'product_id': product_id,
818+ })
819+ move.write({'prodlot_id' : prodlot_id})
820+
821+ def _get_tracking_code(self, cr, uid, ids, field_name, arg, context=None):
822+ res = {}
823+ for move in self.browse(cr, uid, ids):
824+ res[move.id] = move.tracking_id and move.tracking_id.name or False
825+ return res
826+
827+ def _set_tracking_code(self, cr, uid, ids, name, value, arg, context=None):
828+ if not value: return False
829+
830+ if isinstance(ids, (int, long)):
831+ ids = [ids]
832+
833+ for move in self.browse(cr, uid, ids, context=context):
834+ product_id = move.product_id.id
835+ existing_tracking = move.tracking_id
836+ if existing_tracking: #avoid creating a tracking twice
837+ self.pool.get('stock.tracking').write(cr, uid, existing_tracking.id, {'name': value})
838+ else:
839+ tracking_id = self.pool.get('stock.tracking').create(cr, uid, {
840+ 'name': value,
841+ })
842+ move.write({'tracking_id' : tracking_id})
843+
844+ _columns = {
845+ 'new_prodlot_code': fields.function(_get_prodlot_code, fnct_inv=_set_prodlot_code,
846+ method=True, type='char', size=64,
847+ string='Prodlot fast input', select=1
848+ ),
849+ 'new_tracking_code': fields.function(_get_tracking_code, fnct_inv=_set_tracking_code,
850+ method=True, type='char', size=64,
851+ string='Tracking fast input', select=1
852+ ),
853+ }
854+
855+ def action_done(self, cr, uid, ids, context=None):
856+ """
857+ If we autosplit moves without reconnecting them 1 by 1, at least when some move which has descendants is split
858+ The following situation would happen (alphabetical order is order of creation, initially b and a pre-exists, then a is split, so a might get assigned and then split too):
859+ Incoming moves b, c, d
860+ Outgoing moves a, e, f
861+ Then we have those links: b->a, c->a, d->a
862+ and: b->, b->e, b->f
863+ The following code will detect this situation and reconnect properly the moves into only: b->a, c->e and d->f
864+ """
865+ result = super(stock_move, self).action_done(cr, uid, ids, context)
866+ for move in self.browse(cr, uid, ids):
867+ if move.product_id.lot_split_type and move.move_dest_id and move.move_dest_id.id:
868+ cr.execute("select stock_move.id from stock_move_history_ids left join stock_move on stock_move.id = stock_move_history_ids.child_id where parent_id=%s and stock_move.product_qty=1", (move.id,))
869+ unitary_out_moves = cr.fetchall()
870+ if unitary_out_moves and len(unitary_out_moves) > 1:
871+ unitary_in_moves = []
872+ out_node = False
873+ counter = 0
874+ while len(unitary_in_moves) != len(unitary_out_moves) and counter < len(unitary_out_moves):
875+ out_node = unitary_out_moves[counter][0]
876+ cr.execute("select stock_move.id from stock_move_history_ids left join stock_move on stock_move.id = stock_move_history_ids.parent_id where child_id=%s and stock_move.product_qty=1", (out_node,))
877+ unitary_in_moves = cr.fetchall()
878+ counter += 1
879+
880+ if len(unitary_in_moves) == len(unitary_out_moves):
881+ unitary_out_moves.reverse()
882+ unitary_out_moves.pop()
883+ unitary_in_moves.reverse()
884+ unitary_in_moves.pop()
885+ counter = 0
886+ for unitary_in_move in unitary_in_moves:
887+ cr.execute("delete from stock_move_history_ids where parent_id=%s and child_id=%s", (unitary_in_moves[counter][0], out_node))
888+ cr.execute("update stock_move_history_ids set parent_id=%s where parent_id=%s and child_id=%s", (unitary_in_moves[counter][0], move.id, unitary_out_moves[counter][0]))
889+ counter += 1
890+
891+ return result
892+
893+ def split_move(self, cr, uid, ids, context=None):
894+ all_ids = list(ids)
895+ for move in self.browse(cr, uid, ids, context=context):
896+ qty = move.product_qty
897+ lu_qty = False
898+ if move.product_id.lot_split_type == 'lu':
899+ if not move.product_id.packaging:
900+ raise osv.except_osv(_('Error :'), _("Product '%s' has 'Lot split type' = 'Logistical Unit' but is missing packaging information.") % (move.product_id.name))
901+ lu_qty = move.product_id.packaging[0].qty
902+ elif move.product_id.lot_split_type == 'single':
903+ lu_qty = 1
904+ if lu_qty and qty > 1:
905+ # Set existing move to LU quantity
906+ self.write(cr, uid, move.id, {'product_qty': lu_qty, 'product_uos_qty': move.product_id.uos_coeff})
907+ qty -= lu_qty
908+ # While still enough qty to create a new move, create it
909+ while qty >= lu_qty:
910+ all_ids.append( self.copy(cr, uid, move.id, {'state': move.state, 'prodlot_id': None}) )
911+ qty -= lu_qty
912+ # Create a last move for the remainder qty
913+ if qty > 0:
914+ all_ids.append( self.copy(cr, uid, move.id, {'state': move.state, 'prodlot_id': None, 'product_qty': qty}) )
915+ return all_ids
916+
917+stock_move()
918+
919+
920+class stock_picking(osv.osv):
921+ _inherit = "stock.picking"
922+
923+ def action_assign_wkf(self, cr, uid, ids):
924+ result = super(stock_picking, self).action_assign_wkf(cr, uid, ids)
925+
926+ for picking in self.browse(cr, uid, ids):
927+ if picking.company_id.autosplit_is_active:
928+ for move in picking.move_lines:
929+ # Auto split
930+ if ((move.product_id.track_production and move.location_id.usage == 'production') or \
931+ (move.product_id.track_production and move.location_dest_id.usage == 'production') or \
932+ (move.product_id.track_incoming and move.location_id.usage == 'supplier') or \
933+ (move.product_id.track_outgoing and move.location_dest_id.usage == 'customer')):
934+ self.pool.get('stock.move').split_move(cr, uid, [move.id])
935+
936+ return result
937+
938+ # Because stock move line can be splitted by the module, we merge
939+ # invoice lines (if option 'is_group_invoice_line' is activated for the company)
940+ # at the following conditions :
941+ # - the product is the same and
942+ # - the discount is the same and
943+ # - the unit price is the same and
944+ # - the description is the same and
945+ # - taxes are the same
946+ # - they are from the same sale order lines (requires extra-code)
947+ # we merge invoice line together and do the sum of quantity and
948+ # subtotal.
949+ def action_invoice_create(self, cursor, user, ids, journal_id=False,
950+ group=False, type='out_invoice', context=None):
951+ invoice_dict = super(stock_picking, self).action_invoice_create(cursor, user,
952+ ids, journal_id, group, type, context=context)
953+
954+ for picking_key in invoice_dict:
955+ invoice = self.pool.get('account.invoice').browse(cursor, user, invoice_dict[picking_key], context=context)
956+ if not invoice.company_id.is_group_invoice_line:
957+ continue
958+
959+ new_line_list = {}
960+
961+ for line in invoice.invoice_line:
962+
963+ # Build a key
964+ key = unicode(line.product_id.id) + ";" \
965+ + unicode(line.discount) + ";" \
966+ + unicode(line.price_unit) + ";" \
967+ + line.name + ";"
968+
969+ # Add the tax key part
970+ tax_tab = []
971+ for tax in line.invoice_line_tax_id:
972+ tax_tab.append(tax.id)
973+ tax_tab.sort()
974+ for tax in tax_tab:
975+ key = key + unicode(tax) + ";"
976+
977+ # Add the sale order line part but check if the field exist because
978+ # it's install by a specific module (not from addons)
979+ if self.pool.get('ir.model.fields').search(cursor, user,
980+ [('name', '=', 'sale_order_lines'), ('model', '=', 'account.invoice.line')], context=context) != []:
981+ order_line_tab = []
982+ for order_line in line.sale_order_lines:
983+ order_line_tab.append(order_line.id)
984+ order_line_tab.sort()
985+ for order_line in order_line_tab:
986+ key = key + unicode(order_line) + ";"
987+
988+
989+ # Get the hash of the key
990+ hash_key = hashlib.sha224(key.encode('utf8')).hexdigest()
991+
992+ # if the key doesn't already exist, we keep the invoice line
993+ # and we add the key to new_line_list
994+ if not new_line_list.has_key(hash_key):
995+ new_line_list[hash_key] = {
996+ 'id': line.id,
997+ 'quantity': line.quantity,
998+ 'price_subtotal': line.price_subtotal,
999+ }
1000+ # if the key already exist, we update new_line_list and
1001+ # we delete the invoice line
1002+ else:
1003+ new_line_list[hash_key]['quantity'] = new_line_list[hash_key]['quantity'] + line.quantity
1004+ new_line_list[hash_key]['price_subtotal'] = new_line_list[hash_key]['price_subtotal'] \
1005+ + line.price_subtotal
1006+ self.pool.get('account.invoice.line').unlink(cursor, user, line.id, context=context)
1007+
1008+ # Write modifications made on invoice lines
1009+ for hash_key in new_line_list:
1010+ line_id = new_line_list[hash_key]['id']
1011+ del new_line_list[hash_key]['id']
1012+ self.pool.get('account.invoice.line').write(cursor, user, line_id, new_line_list[hash_key], context=context)
1013+
1014+ return invoice_dict
1015+
1016+stock_picking()
1017+
1018+
1019+class stock_production_lot(osv.osv):
1020+ _inherit = "stock.production.lot"
1021+
1022+ def _last_location_id(self, cr, uid, ids, field_name, arg, context={}):
1023+ """Retrieves the last location where the product with given serial is.
1024+ Instead of using dates we assume the product is in the location having the
1025+ highest number of products with the given serial (should be 1 if no mistake). This
1026+ is better than using move dates because moves can easily be encoded at with wrong dates."""
1027+ res = {}
1028+
1029+ for prodlot_id in ids:
1030+ cr.execute(
1031+ "select location_dest_id " \
1032+ "from stock_move inner join stock_report_prodlots on stock_report_prodlots.location_id = location_dest_id and stock_report_prodlots.prodlot_id = %s " \
1033+ "where stock_move.prodlot_id = %s and stock_move.state=%s "\
1034+ "order by stock_report_prodlots.qty DESC ",
1035+ (prodlot_id, prodlot_id, 'done'))
1036+ results = cr.fetchone()
1037+
1038+ #TODO return tuple to avoid name_get being requested by the GTK client
1039+ res[prodlot_id] = results and results[0] or False
1040+
1041+ return res
1042+
1043+ _columns = {
1044+ 'last_location_id': fields.function(_last_location_id, method=True,
1045+ type="many2one", relation="stock.location",
1046+ string="Last location",
1047+ help="Display the current stock location of this production lot"),
1048+ }
1049+
1050+stock_production_lot()
1051+
1052
1053=== added file 'product_serial/stock_view.xml'
1054--- product_serial/stock_view.xml 1970-01-01 00:00:00 +0000
1055+++ product_serial/stock_view.xml 2013-05-08 13:17:25 +0000
1056@@ -0,0 +1,299 @@
1057+<?xml version="1.0"?>
1058+<openerp>
1059+<data>
1060+
1061+ <!-- In the form view of Incoming/Outgoing products, make the tree view of move lines editable and set the parameters that are only present in the form view to the fields of the tree view-->
1062+ <record id="view_picking_in_form_editable_move_lines" model="ir.ui.view">
1063+ <field name="name">view.picking.in.form.editable_move_lines</field>
1064+ <field name="model">stock.picking</field>
1065+ <field name="inherit_id" ref="stock.view_picking_in_form" />
1066+ <field name="type">form</field>
1067+ <field name="arch" type="xml">
1068+ <xpath expr="/form/notebook/page/field/tree[@string='Stock Moves']" position="attributes">
1069+ <attribute name="editable">bottom</attribute>
1070+ </xpath>
1071+ <xpath expr="/form/notebook/page/field/tree/field[@name='product_id']" position="attributes">
1072+ <attribute name="on_change">onchange_product_id(product_id,location_id,location_dest_id, parent.address_id)</attribute>
1073+ </xpath>
1074+ <!-- we need to have the "name" field in the tree view, because it is a required field that is set by the on_change on product_id... otherwise we get an error message when adding a new move line via the editable tree view -->
1075+ <xpath expr="/form/notebook/page/field/tree/field[@name='product_id']" position="after">
1076+ <field name="name" invisible="1"/>
1077+ </xpath>
1078+ <xpath expr="/form/notebook/page/field/tree/field[@name='product_qty']" position="attributes">
1079+ <attribute name="on_change">onchange_quantity(product_id, product_qty, product_uom, product_uos)</attribute>
1080+ </xpath>
1081+ <xpath expr="/form/notebook/page/field/tree/field[@name='prodlot_id']" position="attributes">
1082+ <attribute name="context">{'location_id':location_id, 'product_id':product_id}</attribute>
1083+ <attribute name="domain">[('product_id','=?',product_id)]</attribute>
1084+ <attribute name="on_change">onchange_lot_id(prodlot_id, product_qty, location_id, product_id, product_uom)</attribute>
1085+ </xpath>
1086+ <xpath expr="/form/notebook/page/field/tree/field[@name='location_dest_id']" position="attributes">
1087+ <attribute name="domain">[('usage','=','internal')]</attribute>
1088+ </xpath>
1089+ </field>
1090+ </record>
1091+
1092+ <record id="view_picking_out_form_editable_move_lines" model="ir.ui.view">
1093+ <field name="name">view.picking.out.form.editable_move_lines</field>
1094+ <field name="model">stock.picking</field>
1095+ <field name="inherit_id" ref="stock.view_picking_out_form" />
1096+ <field name="type">form</field>
1097+ <field name="arch" type="xml">
1098+ <xpath expr="/form/notebook/page/field/tree[@string='Stock Moves']" position="attributes">
1099+ <attribute name="editable">bottom</attribute>
1100+ </xpath>
1101+ <xpath expr="/form/notebook/page/field/tree/field[@name='product_id']" position="attributes">
1102+ <attribute name="on_change">onchange_product_id(product_id,location_id,location_dest_id, parent.address_id)</attribute>
1103+ </xpath>
1104+ <!-- we need to have the "name" field in the tree view, because it is a required field that is set by the on_change on product_id... otherwise we get an error message when adding a new move line via the editable tree view -->
1105+ <xpath expr="/form/notebook/page/field/tree/field[@name='product_id']" position="after">
1106+ <field name="name" invisible="1"/>
1107+ </xpath>
1108+ <xpath expr="/form/notebook/page/field/tree/field[@name='product_qty']" position="attributes">
1109+ <attribute name="on_change">onchange_quantity(product_id, product_qty, product_uom, product_uos)</attribute>
1110+ </xpath>
1111+ <xpath expr="/form/notebook/page/field/tree/field[@name='product_uos']" position="attributes">
1112+ <attribute name="on_change">onchange_quantity(product_id, product_qty, product_uom, product_uos)</attribute>
1113+ </xpath>
1114+ <xpath expr="/form/notebook/page/field/tree/field[@name='prodlot_id']" position="attributes">
1115+ <attribute name="context">{'location_id':location_id, 'product_id':product_id}</attribute>
1116+ <attribute name="domain">[('product_id','=?',product_id)]</attribute>
1117+ <attribute name="on_change">onchange_lot_id(prodlot_id, product_qty, location_id, product_id, product_uom)</attribute>
1118+ </xpath>
1119+ <xpath expr="/form/notebook/page/field/tree/field[@name='location_id']" position="attributes">
1120+ <attribute name="domain">[('usage','=','internal')]</attribute>
1121+ </xpath>
1122+ </field>
1123+ </record>
1124+
1125+ <!-- In the form view of Incoming products, add the "new_prodlot_code" fields -->
1126+ <record id="view_picking_in_form_new_prodlot_code" model="ir.ui.view">
1127+ <field name="name">view.picking.in.form.new_prodlot_code</field>
1128+ <field name="model">stock.picking</field>
1129+ <field name="inherit_id" ref="stock.view_picking_in_form" />
1130+ <field name="type">form</field>
1131+ <field name="arch" type="xml">
1132+ <xpath expr="/form/notebook/page/field/tree/field[@name='prodlot_id']" position="before">
1133+ <field name="new_prodlot_code" />
1134+ </xpath>
1135+ </field>
1136+ </record>
1137+
1138+ <!-- In the form view of Incoming products, add the "new_tracking_code" fields -->
1139+ <record id="view_picking_in_form_new_tracking_code" model="ir.ui.view">
1140+ <field name="name">view.picking.in.form.new_tracking_code</field>
1141+ <field name="model">stock.picking</field>
1142+ <field name="inherit_id" ref="stock.view_picking_in_form" />
1143+ <field name="type">form</field>
1144+ <field name="arch" type="xml">
1145+ <xpath expr="/form/notebook/page/field/tree/field[@name='tracking_id']" position="before">
1146+ <field name="new_tracking_code" />
1147+ </xpath>
1148+ </field>
1149+ </record>
1150+
1151+ <!-- We should have both source stock + dest location in the form view of Incoming/Outgoing products/Internal moves -->
1152+ <record id="view_picking_in_form_source_stock_location" model="ir.ui.view">
1153+ <field name="name">view.picking.in.form.source_stock_location</field>
1154+ <field name="model">stock.picking</field>
1155+ <field name="inherit_id" ref="stock.view_picking_in_form" />
1156+ <field name="type">form</field>
1157+ <field name="arch" type="xml">
1158+ <xpath expr="/form/notebook/page/field/tree/field[@name='location_dest_id']" position="before">
1159+ <field name="location_id" domain="[('usage','&lt;&gt;','view')]" />
1160+ </xpath>
1161+ </field>
1162+ </record>
1163+
1164+ <record id="view_picking_out_form_dest_stock_location" model="ir.ui.view">
1165+ <field name="name">view.picking.out.form.dest_stock_location</field>
1166+ <field name="model">stock.picking</field>
1167+ <field name="inherit_id" ref="stock.view_picking_out_form" />
1168+ <field name="type">form</field>
1169+ <field name="arch" type="xml">
1170+ <xpath expr="/form/notebook/page/field/tree/field[@name='location_id']" position="after">
1171+ <field name="location_dest_id" domain="[('usage','&lt;&gt;','view')]" />
1172+ </xpath>
1173+ </field>
1174+ </record>
1175+
1176+ <record id="view_picking_form_source_stock_location" model="ir.ui.view">
1177+ <field name="name">view.picking.form.source_stock_location</field>
1178+ <field name="model">stock.picking</field>
1179+ <field name="inherit_id" ref="stock.view_picking_form" />
1180+ <field name="type">form</field>
1181+ <field name="arch" type="xml">
1182+ <xpath expr="/form/notebook/page/field/tree/field[@name='location_dest_id']" position="before">
1183+ <field name="location_id" domain="[('usage','&lt;&gt;','view')]" />
1184+ </xpath>
1185+ </field>
1186+ </record>
1187+
1188+
1189+ <record id="view_picking_in_form_manual_split" model="ir.ui.view">
1190+ <field name="name">view.picking.in.form.manual_split</field>
1191+ <field name="model">stock.picking</field>
1192+ <field name="inherit_id" ref="stock.view_picking_in_form" />
1193+ <field name="type">form</field>
1194+ <field name="priority">24</field> <!-- inherit after product_hardware_revision -->
1195+ <field name="arch" type="xml">
1196+ <xpath expr="/form/notebook/page/field/form/group/button[@string='Split']" position="after">
1197+ <label string="" colspan="3" />
1198+ <button name="split_move" string="Manual split"
1199+ groups="base.group_extended"
1200+ states="draft,waiting,confirmed,assigned"
1201+ type="object" icon="terp-stock_effects-object-colorize"
1202+ colspan="1" />
1203+ </xpath>
1204+ <xpath expr="/form/notebook/page/field/tree/button[@string='Split in production lots']" position="replace">
1205+ <button name="split_move" string="Manual split"
1206+ groups="base.group_extended"
1207+ states="draft,waiting,confirmed,assigned"
1208+ type="object" icon="terp-stock_effects-object-colorize"/>
1209+ </xpath>
1210+ </field>
1211+ </record>
1212+
1213+ <record id="view_picking_out_form_manual_split" model="ir.ui.view">
1214+ <field name="name">view.picking.out.form.manual_split</field>
1215+ <field name="model">stock.picking</field>
1216+ <field name="inherit_id" ref="stock.view_picking_out_form" />
1217+ <field name="type">form</field>
1218+ <field name="priority">24</field> <!-- inherit after product_hardware_revision -->
1219+ <field name="arch" type="xml">
1220+ <xpath expr="/form/notebook/page/field/form/group/button[@string='Split']" position="after">
1221+ <label string="" colspan="3" />
1222+ <button name="split_move" string="Manual split"
1223+ groups="base.group_extended"
1224+ states="draft,waiting,confirmed,assigned"
1225+ type="object" icon="terp-stock_effects-object-colorize"
1226+ colspan="1" />
1227+ </xpath>
1228+ <xpath expr="/form/notebook/page/field/tree/button[@string='Split in production lots']" position="replace">
1229+ <button name="split_move" string="Manual split"
1230+ groups="base.group_extended"
1231+ states="draft,waiting,confirmed,assigned"
1232+ type="object" icon="terp-stock_effects-object-colorize"/>
1233+ </xpath>
1234+ </field>
1235+ </record>
1236+
1237+
1238+ <!-- Internal moves -->
1239+ <record id="view_picking_form_manual_split" model="ir.ui.view">
1240+ <field name="name">view.picking.form.manual_split</field>
1241+ <field name="model">stock.picking</field>
1242+ <field name="inherit_id" ref="stock.view_picking_form" />
1243+ <field name="type">form</field>
1244+ <field name="arch" type="xml">
1245+ <xpath expr="/form/notebook/page/field/form/group/button[@string='Split']" position="after">
1246+ <label string="" colspan="3" />
1247+ <button name="split_move" string="Manual split"
1248+ groups="base.group_extended"
1249+ states="draft,waiting,confirmed,assigned"
1250+ type="object" icon="terp-stock_effects-object-colorize"
1251+ colspan="1" />
1252+ </xpath>
1253+ <xpath expr="/form/notebook/page/field/tree/button[@string='Split in production lots']" position="replace">
1254+ <button name="split_move" string="Manual split"
1255+ groups="base.group_extended"
1256+ states="draft,waiting,confirmed,assigned"
1257+ type="object" icon="terp-stock_effects-object-colorize"/>
1258+ </xpath>
1259+ </field>
1260+ </record>
1261+
1262+
1263+ <!-- Add "last_location_id" on prod lot view -->
1264+ <record id="view_production_lot_form_unique_production_number" model="ir.ui.view">
1265+ <field name="name">view_production_lot_form_unique_production_number</field>
1266+ <field name="model">stock.production.lot</field>
1267+ <field name="inherit_id" ref="stock.view_production_lot_form"/>
1268+ <field name="type">form</field>
1269+ <field name="arch" type="xml">
1270+ <field name="stock_available" position="after">
1271+ <field name="last_location_id"/>
1272+ </field>
1273+ </field>
1274+ </record>
1275+
1276+ <!-- Wizard to help users input production lots in batch -->
1277+<!-- TODO Nan-TIc : port to v6
1278+ <record id="view_stock_picking_prodlot_selection" model="ir.ui.view">
1279+ <field name="name">stock.picking.prodlot.selection</field>
1280+ <field name="model">stock.picking.prodlot.selection</field>
1281+ <field name="type">form</field>
1282+ <field name="arch" type="xml">
1283+ <form string="Select Production Lots">
1284+ <field name="product_id" colspan="4"/>
1285+ <field name="first_lot"/>
1286+ <field name="last_lot"/>
1287+ <button type="object" name="action_cancel" string="Cancel" icon="gtk-cancel" special="cancel" colspan="2"/>
1288+ <button type="object" name="action_accept" string="Accept" icon="gtk-ok" colspan="2"/>
1289+ </form>
1290+ </field>
1291+ </record>
1292+
1293+ <record model="ir.actions.act_window" id="action_prodlot_selection">
1294+ <field name="name">Select Production Lots</field>
1295+ <field name="res_model">stock.picking.prodlot.selection</field>
1296+ <field name="view_type">form</field>
1297+ <field name="view_mode">form</field>
1298+ <field name="target">new</field>
1299+ </record>
1300+
1301+ <record id="view_picking_form" model="ir.ui.view">
1302+ <field name="name">stock.picking.form.prodlot.selection</field>
1303+ <field name="model">stock.picking</field>
1304+ <field name="type">form</field>
1305+ <field name="inherit_id" ref="stock.view_picking_form"/>
1306+ <field name="arch" type="xml">
1307+ <xpath expr="/form/notebook/page/group/label[@colspan='6']" position="replace">
1308+ <label colspan="5"/>
1309+ <button type="action" name="%(action_prodlot_selection)d" string="Spread Production Lots" states="draft,confirmed,assigned"/>
1310+ </xpath>
1311+ </field>
1312+ </record>
1313+
1314+ <record id="view_picking_in_form" model="ir.ui.view">
1315+ <field name="name">stock.picking.in.form.prodlot.selection</field>
1316+ <field name="model">stock.picking</field>
1317+ <field name="type">form</field>
1318+ <field name="inherit_id" ref="stock.view_picking_in_form"/>
1319+ <field name="arch" type="xml">
1320+ <xpath expr="/form/notebook/page/group/label[@colspan='5']" position="replace">
1321+ <label colspan="4"/>
1322+ <button type="action" name="%(action_prodlot_selection)d" string="Spread Production Lots" states="draft,confirmed,assigned"/>
1323+ </xpath>
1324+ </field>
1325+ </record>
1326+
1327+ <record id="view_picking_out_form" model="ir.ui.view">
1328+ <field name="name">stock.picking.out.form</field>
1329+ <field name="model">stock.picking</field>
1330+ <field name="type">form</field>
1331+ <field name="inherit_id" ref="stock.view_picking_out_form"/>
1332+ <field name="arch" type="xml">
1333+ <xpath expr="/form/notebook/page/group/label[@colspan='6']" position="replace">
1334+ <label colspan="5"/>
1335+ <button type="action" name="%(action_prodlot_selection)d" string="Spread Production Lots" states="draft,confirmed,assigned"/>
1336+ </xpath>
1337+ </field>
1338+ </record>
1339+
1340+ <record id="view_picking_delivery_form" model="ir.ui.view">
1341+ <field name="name">stock.picking.delivery.form</field>
1342+ <field name="model">stock.picking</field>
1343+ <field name="type">form</field>
1344+ <field name="inherit_id" ref="stock.view_picking_delivery_form"/>
1345+ <field name="arch" type="xml">
1346+ <xpath expr="/form/notebook/page/group/label[@colspan='6']" position="replace">
1347+ <label colspan="5"/>
1348+ <button type="action" name="%(action_prodlot_selection)d" string="Spread Production Lots" states="draft,confirmed,assigned"/>
1349+ </xpath>
1350+ </field>
1351+ </record>
1352+-->
1353+
1354+</data>
1355+</openerp>

Subscribers

People subscribed via source and target branches