From b6a11865350799384c0e315835e0be11525994cd Mon Sep 17 00:00:00 2001 From: Juan Jose Scarafia Date: Sun, 8 Jun 2014 09:55:09 -0300 Subject: [PATCH 01/75] INIT INIT ADD pot files and module for agrimesores --- product_pack/__init__.py | 33 ++++ product_pack/__openerp__.py | 55 ++++++ product_pack/i18n/ca.po | 163 ++++++++++++++++ product_pack/i18n/de.po | 145 ++++++++++++++ product_pack/i18n/es.po | 164 ++++++++++++++++ product_pack/i18n/it.po | 163 ++++++++++++++++ product_pack/i18n/nan_product_pack.pot | 137 +++++++++++++ product_pack/i18n/pt.po | 149 ++++++++++++++ product_pack/pack.py | 135 +++++++++++++ product_pack/pack_view.xml | 51 +++++ product_pack/sale.py | 228 ++++++++++++++++++++++ product_pack/security/ir.model.access.csv | 3 + product_pack/stock.py | 166 ++++++++++++++++ 13 files changed, 1592 insertions(+) create mode 100755 product_pack/__init__.py create mode 100755 product_pack/__openerp__.py create mode 100755 product_pack/i18n/ca.po create mode 100755 product_pack/i18n/de.po create mode 100755 product_pack/i18n/es.po create mode 100755 product_pack/i18n/it.po create mode 100755 product_pack/i18n/nan_product_pack.pot create mode 100755 product_pack/i18n/pt.po create mode 100755 product_pack/pack.py create mode 100755 product_pack/pack_view.xml create mode 100755 product_pack/sale.py create mode 100755 product_pack/security/ir.model.access.csv create mode 100755 product_pack/stock.py diff --git a/product_pack/__init__.py b/product_pack/__init__.py new file mode 100755 index 00000000..ba80327f --- /dev/null +++ b/product_pack/__init__.py @@ -0,0 +1,33 @@ +# -*- encoding: latin-1 -*- +############################################################################## +# +# Ingenieria ADHOC - ADHOC SA +# https://launchpad.net/~ingenieria-adhoc +# +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import pack +import sale +import stock \ No newline at end of file diff --git a/product_pack/__openerp__.py b/product_pack/__openerp__.py new file mode 100755 index 00000000..4707a750 --- /dev/null +++ b/product_pack/__openerp__.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Ingenieria ADHOC - ADHOC SA +# https://launchpad.net/~ingenieria-adhoc +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +{ + 'name': 'Product Pack', + 'version': '1.0', + 'category': 'Product', + 'sequence': 14, + 'summary': '', + 'description': """ +Product Pack +============ +Allows configuring products as a collection of other products. If such a product is added in a sale order, all the products of the pack will be added automatically (when storing the order) as children of the pack product. + +The module has been made compatible with nan_external_prices and containts code to specifically handle when the module is available but they're still independent and there are no dependencies between them. + """, + 'author': 'Ingenieria ADHOC', + 'website': 'www.ingadhoc.com', + 'images': [ + ], + 'depends': [ + 'sale', + 'stock', + ], + 'data': [ + 'security/ir.model.access.csv', + 'pack_view.xml' + ], + 'demo': [ + ], + 'test': [ + ], + 'installable': False, + 'auto_install': False, + 'application': False, +} +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file diff --git a/product_pack/i18n/ca.po b/product_pack/i18n/ca.po new file mode 100755 index 00000000..276a799b --- /dev/null +++ b/product_pack/i18n/ca.po @@ -0,0 +1,163 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * nan_product_pack +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 5.0.6\n" +"Report-Msgid-Bugs-To: support@openerp.com\n" +"POT-Creation-Date: 2011-01-15 11:45+0000\n" +"PO-Revision-Date: 2011-02-15 14:19+0000\n" +"Last-Translator: Jordi Esteve (Zikzakmedia) \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-04-20 05:29+0000\n" +"X-Generator: Launchpad (build 16567)\n" + +#. module: nan_product_pack +#: constraint:ir.model:0 +msgid "" +"The Object name must start with x_ and not contain any special character !" +msgstr "" +"El nom de l'objecte ha de començar amb x_ i no contenir cap caràcter " +"especial!" + +#. module: nan_product_pack +#: help:product.product,stock_depends:0 +msgid "Mark if pack stock is calcualted from component stock" +msgstr "" +"Marqueu aquest camp si l'estoc del paquet es calcula a partir de l'estoc " +"dels components." + +#. module: nan_product_pack +#: field:sale.order.line,pack_child_line_ids:0 +msgid "Lines in pack" +msgstr "Línies en el paquet" + +#. module: nan_product_pack +#: help:sale.order.line,pack_depth:0 +msgid "Depth of the product if it is part of a pack." +msgstr "Profunditat del producte si forma part d'un paquet." + +#. module: nan_product_pack +#: field:product.pack.line,product_id:0 +msgid "Product" +msgstr "Producte" + +#. module: nan_product_pack +#: view:product.pack.line:0 +msgid "Pack Product Lines" +msgstr "Línies del paquet de productes" + +#. module: nan_product_pack +#: view:product.product:0 +msgid "" +"If you add products in the 'Pack Products' field, all those products will be " +"added automatically when a new quotation or order is created." +msgstr "" +"Si afegiu productes en el camp \"Paquet de productes\", tots els productes " +"s'afegiran automàticament quan creeu un nou pressupost o comanda." + +#. module: nan_product_pack +#: model:ir.module.module,description:nan_product_pack.module_meta_information +msgid "" +"\n" +"Allows configuring products as a collection of other products. If such a " +"product is added in a sale order, all the products of the pack will be added " +"automatically (when storing the order) as children of the pack product.\n" +"\n" +"The module has been made compatible with nan_external_prices and containts " +"code to specifically handle when the module is available but they're still " +"independent and there are no dependencies between them.\n" +" " +msgstr "" +"\n" +"Permet configurar els productes com col·leccions d'altres productes. Si " +"s'afegeix un producte d'aquest tipus en una comanda de venda, tots els " +"productes del paquet s'afegiran automàticament (quan es guardi la comanda) " +"com a fills del producte principal.\n" +"\n" +"Aquest mòdul és compatible amb nan_external_prices i conté codi per " +"funcionar quan està instal·lat encara que ambdós són encara independents i " +"no hi ha dependències entre ells.\n" +" " + +#. module: nan_product_pack +#: view:product.product:0 +#: field:sale.order.line,pack_parent_line_id:0 +msgid "Pack" +msgstr "Paquet" + +#. module: nan_product_pack +#: model:ir.model,name:nan_product_pack.model_product_pack_line +msgid "product.pack.line" +msgstr "producte.paquet.línea" + +#. module: nan_product_pack +#: constraint:ir.ui.view:0 +msgid "Invalid XML for View Architecture!" +msgstr "XML no vàlid per a la definició de la vista!" + +#. module: nan_product_pack +#: model:ir.module.module,shortdesc:nan_product_pack.module_meta_information +msgid "Product Pack" +msgstr "Paquet de productes" + +#. module: nan_product_pack +#: field:product.product,stock_depends:0 +msgid "Stock depends of components" +msgstr "Estoc depen dels components" + +#. module: nan_product_pack +#: help:sale.order.line,pack_parent_line_id:0 +msgid "The pack that contains this product." +msgstr "El paquet que conté aquest producte." + +#. module: nan_product_pack +#: field:sale.order.line,pack_depth:0 +msgid "Depth" +msgstr "Profunditat" + +#. module: nan_product_pack +#: help:product.product,pack_fixed_price:0 +msgid "" +"Mark this field if the public price of the pack should be fixed. Do not mark " +"it if the price should be calculated from the sum of the prices of the " +"products in the pack." +msgstr "" +"Marqueu aquest camp si el preu de venda del paquet ha de ser fix. No ho " +"marqueu si el preu s'ha de calcular a partir de la suma dels preus dels " +"productes del paquet." + +#. module: nan_product_pack +#: field:product.pack.line,quantity:0 +msgid "Quantity" +msgstr "Quantitat" + +#. module: nan_product_pack +#: view:product.product:0 +#: field:product.product,pack_line_ids:0 +msgid "Pack Products" +msgstr "Productes del paquet" + +#. module: nan_product_pack +#: field:product.pack.line,parent_product_id:0 +msgid "Parent Product" +msgstr "Producte pare" + +#. module: nan_product_pack +#: field:product.product,pack_fixed_price:0 +msgid "Pack has fixed price" +msgstr "El paquet té un preu fix" + +#. module: nan_product_pack +#: view:product.pack.line:0 +msgid "Pack Product Line" +msgstr "Línia de paquet de productes" + +#. module: nan_product_pack +#: help:product.product,pack_line_ids:0 +msgid "List of products that are part of this pack." +msgstr "Llista de productes que formen part del paquet." diff --git a/product_pack/i18n/de.po b/product_pack/i18n/de.po new file mode 100755 index 00000000..7a7707ed --- /dev/null +++ b/product_pack/i18n/de.po @@ -0,0 +1,145 @@ +# German translation for openobject-addons +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2011-01-15 11:45+0000\n" +"PO-Revision-Date: 2011-02-15 14:19+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: German \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-04-20 05:29+0000\n" +"X-Generator: Launchpad (build 16567)\n" + +#. module: nan_product_pack +#: constraint:ir.model:0 +msgid "" +"The Object name must start with x_ and not contain any special character !" +msgstr "" + +#. module: nan_product_pack +#: help:product.product,stock_depends:0 +msgid "Mark if pack stock is calcualted from component stock" +msgstr "" + +#. module: nan_product_pack +#: field:sale.order.line,pack_child_line_ids:0 +msgid "Lines in pack" +msgstr "" + +#. module: nan_product_pack +#: help:sale.order.line,pack_depth:0 +msgid "Depth of the product if it is part of a pack." +msgstr "" + +#. module: nan_product_pack +#: field:product.pack.line,product_id:0 +msgid "Product" +msgstr "" + +#. module: nan_product_pack +#: view:product.pack.line:0 +msgid "Pack Product Lines" +msgstr "" + +#. module: nan_product_pack +#: view:product.product:0 +msgid "" +"If you add products in the 'Pack Products' field, all those products will be " +"added automatically when a new quotation or order is created." +msgstr "" + +#. module: nan_product_pack +#: model:ir.module.module,description:nan_product_pack.module_meta_information +msgid "" +"\n" +"Allows configuring products as a collection of other products. If such a " +"product is added in a sale order, all the products of the pack will be added " +"automatically (when storing the order) as children of the pack product.\n" +"\n" +"The module has been made compatible with nan_external_prices and containts " +"code to specifically handle when the module is available but they're still " +"independent and there are no dependencies between them.\n" +" " +msgstr "" + +#. module: nan_product_pack +#: view:product.product:0 +#: field:sale.order.line,pack_parent_line_id:0 +msgid "Pack" +msgstr "" + +#. module: nan_product_pack +#: model:ir.model,name:nan_product_pack.model_product_pack_line +msgid "product.pack.line" +msgstr "" + +#. module: nan_product_pack +#: constraint:ir.ui.view:0 +msgid "Invalid XML for View Architecture!" +msgstr "" + +#. module: nan_product_pack +#: model:ir.module.module,shortdesc:nan_product_pack.module_meta_information +msgid "Product Pack" +msgstr "" + +#. module: nan_product_pack +#: field:product.product,stock_depends:0 +msgid "Stock depends of components" +msgstr "" + +#. module: nan_product_pack +#: help:sale.order.line,pack_parent_line_id:0 +msgid "The pack that contains this product." +msgstr "" + +#. module: nan_product_pack +#: field:sale.order.line,pack_depth:0 +msgid "Depth" +msgstr "" + +#. module: nan_product_pack +#: help:product.product,pack_fixed_price:0 +msgid "" +"Mark this field if the public price of the pack should be fixed. Do not mark " +"it if the price should be calculated from the sum of the prices of the " +"products in the pack." +msgstr "" + +#. module: nan_product_pack +#: field:product.pack.line,quantity:0 +msgid "Quantity" +msgstr "" + +#. module: nan_product_pack +#: view:product.product:0 +#: field:product.product,pack_line_ids:0 +msgid "Pack Products" +msgstr "" + +#. module: nan_product_pack +#: field:product.pack.line,parent_product_id:0 +msgid "Parent Product" +msgstr "" + +#. module: nan_product_pack +#: field:product.product,pack_fixed_price:0 +msgid "Pack has fixed price" +msgstr "" + +#. module: nan_product_pack +#: view:product.pack.line:0 +msgid "Pack Product Line" +msgstr "" + +#. module: nan_product_pack +#: help:product.product,pack_line_ids:0 +msgid "List of products that are part of this pack." +msgstr "" diff --git a/product_pack/i18n/es.po b/product_pack/i18n/es.po new file mode 100755 index 00000000..1c9d7d27 --- /dev/null +++ b/product_pack/i18n/es.po @@ -0,0 +1,164 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * nan_product_pack +# +# Albert Cervera i Areny , 2009. +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 5.0.6\n" +"Report-Msgid-Bugs-To: support@openerp.com\n" +"POT-Creation-Date: 2011-01-15 11:45+0000\n" +"PO-Revision-Date: 2011-02-15 14:19+0000\n" +"Last-Translator: Jordi Esteve (Zikzakmedia) \n" +"Language-Team: Catalan \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-04-20 05:29+0000\n" +"X-Generator: Launchpad (build 16567)\n" + +#. module: nan_product_pack +#: constraint:ir.model:0 +msgid "" +"The Object name must start with x_ and not contain any special character !" +msgstr "" +"¡El nombre del objeto debe empezar con x_ y no contener ningún carácter " +"especial!" + +#. module: nan_product_pack +#: help:product.product,stock_depends:0 +msgid "Mark if pack stock is calcualted from component stock" +msgstr "" +"Marque este campo si el stock del pack se calcula a partir del stock de los " +"componentes." + +#. module: nan_product_pack +#: field:sale.order.line,pack_child_line_ids:0 +msgid "Lines in pack" +msgstr "Líneas en el pack" + +#. module: nan_product_pack +#: help:sale.order.line,pack_depth:0 +msgid "Depth of the product if it is part of a pack." +msgstr "Profundidad del producto si forma parte de un pack." + +#. module: nan_product_pack +#: field:product.pack.line,product_id:0 +msgid "Product" +msgstr "Producto" + +#. module: nan_product_pack +#: view:product.pack.line:0 +msgid "Pack Product Lines" +msgstr "Líneas del pack de productos" + +#. module: nan_product_pack +#: view:product.product:0 +msgid "" +"If you add products in the 'Pack Products' field, all those products will be " +"added automatically when a new quotation or order is created." +msgstr "" +"Si añade productos en el campo \"Pack de productos\", todos los productos se " +"añadirán automáticamente cuando cree un nuevo presupuesto o pedido." + +#. module: nan_product_pack +#: model:ir.module.module,description:nan_product_pack.module_meta_information +msgid "" +"\n" +"Allows configuring products as a collection of other products. If such a " +"product is added in a sale order, all the products of the pack will be added " +"automatically (when storing the order) as children of the pack product.\n" +"\n" +"The module has been made compatible with nan_external_prices and containts " +"code to specifically handle when the module is available but they're still " +"independent and there are no dependencies between them.\n" +" " +msgstr "" +"\n" +"Permite configurar los productos como colecciones de otros productos. Si se " +"añade un producto de este tipo en un pedido de venta, todos los productos " +"del pack se añadirán automáticamente (cuando se guarde el pedido) como hijos " +"del producto principal.\n" +"\n" +"Este módulo es compatible con nan_external_prices y contiene código para " +"funcionar cuando está instalado aunque ambos son todavía independientes y no " +"hay dependencias entre ellos.\n" +" " + +#. module: nan_product_pack +#: view:product.product:0 +#: field:sale.order.line,pack_parent_line_id:0 +msgid "Pack" +msgstr "Pack" + +#. module: nan_product_pack +#: model:ir.model,name:nan_product_pack.model_product_pack_line +msgid "product.pack.line" +msgstr "producto.pack.línea" + +#. module: nan_product_pack +#: constraint:ir.ui.view:0 +msgid "Invalid XML for View Architecture!" +msgstr "¡XML no válido para la definición de la vista!" + +#. module: nan_product_pack +#: model:ir.module.module,shortdesc:nan_product_pack.module_meta_information +msgid "Product Pack" +msgstr "Pack de productos" + +#. module: nan_product_pack +#: field:product.product,stock_depends:0 +msgid "Stock depends of components" +msgstr "Stock depende de los componentes" + +#. module: nan_product_pack +#: help:sale.order.line,pack_parent_line_id:0 +msgid "The pack that contains this product." +msgstr "El pack que contiene este producto." + +#. module: nan_product_pack +#: field:sale.order.line,pack_depth:0 +msgid "Depth" +msgstr "Profundidad" + +#. module: nan_product_pack +#: help:product.product,pack_fixed_price:0 +msgid "" +"Mark this field if the public price of the pack should be fixed. Do not mark " +"it if the price should be calculated from the sum of the prices of the " +"products in the pack." +msgstr "" +"Marque este campo si el precio de venta del pack tiene que ser fijo. No lo " +"marque si el precio se tiene que calcular a partir de la suma de los precios " +"de los productos del pack." + +#. module: nan_product_pack +#: field:product.pack.line,quantity:0 +msgid "Quantity" +msgstr "Cantidad" + +#. module: nan_product_pack +#: view:product.product:0 +#: field:product.product,pack_line_ids:0 +msgid "Pack Products" +msgstr "Productos del pack" + +#. module: nan_product_pack +#: field:product.pack.line,parent_product_id:0 +msgid "Parent Product" +msgstr "Producto padre" + +#. module: nan_product_pack +#: field:product.product,pack_fixed_price:0 +msgid "Pack has fixed price" +msgstr "El pack tiene un precio fijo" + +#. module: nan_product_pack +#: view:product.pack.line:0 +msgid "Pack Product Line" +msgstr "Línea de pack de productos" + +#. module: nan_product_pack +#: help:product.product,pack_line_ids:0 +msgid "List of products that are part of this pack." +msgstr "Lista de productos que forman parte del pack." diff --git a/product_pack/i18n/it.po b/product_pack/i18n/it.po new file mode 100755 index 00000000..3642ba38 --- /dev/null +++ b/product_pack/i18n/it.po @@ -0,0 +1,163 @@ +# Italian translation for openobject-addons +# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2011-01-15 11:45+0000\n" +"PO-Revision-Date: 2011-05-03 10:13+0000\n" +"Last-Translator: FULL NAME \n" +"Language-Team: Italian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-04-20 05:29+0000\n" +"X-Generator: Launchpad (build 16567)\n" + +#. module: nan_product_pack +#: constraint:ir.model:0 +msgid "" +"The Object name must start with x_ and not contain any special character !" +msgstr "" +"Il nome dell'oggetto deve iniziare con x_ e non deve contenere alcun " +"carattere speciale !" + +#. module: nan_product_pack +#: help:product.product,stock_depends:0 +msgid "Mark if pack stock is calcualted from component stock" +msgstr "" +"Selezionare se la giacenza del kit è calcolata sulla base della giacenza dei " +"componenti" + +#. module: nan_product_pack +#: field:sale.order.line,pack_child_line_ids:0 +msgid "Lines in pack" +msgstr "Righe nel kit" + +#. module: nan_product_pack +#: help:sale.order.line,pack_depth:0 +msgid "Depth of the product if it is part of a pack." +msgstr "Profondità del prodotto se è parte di un kit" + +#. module: nan_product_pack +#: field:product.pack.line,product_id:0 +msgid "Product" +msgstr "Prodotto" + +#. module: nan_product_pack +#: view:product.pack.line:0 +msgid "Pack Product Lines" +msgstr "Righe Kit" + +#. module: nan_product_pack +#: view:product.product:0 +msgid "" +"If you add products in the 'Pack Products' field, all those products will be " +"added automatically when a new quotation or order is created." +msgstr "" +"Se si aggiungono prodotti nel campo 'Prodotti Kit', tutti quei prodotti " +"saranno automaticamente aggiunti alla creazione di un preventivo o ordine." + +#. module: nan_product_pack +#: model:ir.module.module,description:nan_product_pack.module_meta_information +msgid "" +"\n" +"Allows configuring products as a collection of other products. If such a " +"product is added in a sale order, all the products of the pack will be added " +"automatically (when storing the order) as children of the pack product.\n" +"\n" +"The module has been made compatible with nan_external_prices and containts " +"code to specifically handle when the module is available but they're still " +"independent and there are no dependencies between them.\n" +" " +msgstr "" +"\n" +"Permette di configurare prosotti come collezioni di altri prodotti. Se uno " +"di questi prodotti viene aggiunto ad un ordine di vendita, tutti i prodotti " +"nel kit saranno aggiunti automaticamente (al salvataggio dell'ordine) come " +"figli del prodotto kit.\n" +"\n" +"Il modulo è stato reso compatibile con nan_external_prices e contiene il " +"codice per gestire entrambi i moduli pur mantenendoli indipendenti.\n" +" " + +#. module: nan_product_pack +#: view:product.product:0 +#: field:sale.order.line,pack_parent_line_id:0 +msgid "Pack" +msgstr "Kit" + +#. module: nan_product_pack +#: model:ir.model,name:nan_product_pack.model_product_pack_line +msgid "product.pack.line" +msgstr "product.pack.line" + +#. module: nan_product_pack +#: constraint:ir.ui.view:0 +msgid "Invalid XML for View Architecture!" +msgstr "XML non valido per l'architettura della vista" + +#. module: nan_product_pack +#: model:ir.module.module,shortdesc:nan_product_pack.module_meta_information +msgid "Product Pack" +msgstr "Kit prodotto" + +#. module: nan_product_pack +#: field:product.product,stock_depends:0 +msgid "Stock depends of components" +msgstr "La giacenza si basa sui componenti" + +#. module: nan_product_pack +#: help:sale.order.line,pack_parent_line_id:0 +msgid "The pack that contains this product." +msgstr "Il kit che contiene questo prodotto." + +#. module: nan_product_pack +#: field:sale.order.line,pack_depth:0 +msgid "Depth" +msgstr "Profondità" + +#. module: nan_product_pack +#: help:product.product,pack_fixed_price:0 +msgid "" +"Mark this field if the public price of the pack should be fixed. Do not mark " +"it if the price should be calculated from the sum of the prices of the " +"products in the pack." +msgstr "" +"Selezionare questo campo se il prezzo pubblico del kit debba essere fisso. " +"Non selezionarlo se il prezzo debba essere calcolato sulla base dei prezzi " +"dei prodotti nel kit." + +#. module: nan_product_pack +#: field:product.pack.line,quantity:0 +msgid "Quantity" +msgstr "Quantità" + +#. module: nan_product_pack +#: view:product.product:0 +#: field:product.product,pack_line_ids:0 +msgid "Pack Products" +msgstr "Prodotti kit" + +#. module: nan_product_pack +#: field:product.pack.line,parent_product_id:0 +msgid "Parent Product" +msgstr "Prodotto genitore" + +#. module: nan_product_pack +#: field:product.product,pack_fixed_price:0 +msgid "Pack has fixed price" +msgstr "Il kit ha prezzo fisso" + +#. module: nan_product_pack +#: view:product.pack.line:0 +msgid "Pack Product Line" +msgstr "Riga prodotto kit" + +#. module: nan_product_pack +#: help:product.product,pack_line_ids:0 +msgid "List of products that are part of this pack." +msgstr "Lista dei prodotti che sono parte di questo kit." diff --git a/product_pack/i18n/nan_product_pack.pot b/product_pack/i18n/nan_product_pack.pot new file mode 100755 index 00000000..4945c1ba --- /dev/null +++ b/product_pack/i18n/nan_product_pack.pot @@ -0,0 +1,137 @@ +# Translation of OpenERP Server. +# This file contains the translation of the following modules: +# * nan_product_pack +# +msgid "" +msgstr "" +"Project-Id-Version: OpenERP Server 5.0.15\n" +"Report-Msgid-Bugs-To: support@openerp.com\n" +"POT-Creation-Date: 2011-01-15 11:45:01+0000\n" +"PO-Revision-Date: 2011-01-15 11:45:01+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: nan_product_pack +#: constraint:ir.model:0 +msgid "The Object name must start with x_ and not contain any special character !" +msgstr "The Object name must start with x_ and not contain any special character !" + +#. module: nan_product_pack +#: help:product.product,stock_depends:0 +msgid "Mark if pack stock is calcualted from component stock" +msgstr "Mark if pack stock is calcualted from component stock" + +#. module: nan_product_pack +#: field:sale.order.line,pack_child_line_ids:0 +msgid "Lines in pack" +msgstr "Lines in pack" + +#. module: nan_product_pack +#: help:sale.order.line,pack_depth:0 +msgid "Depth of the product if it is part of a pack." +msgstr "Depth of the product if it is part of a pack." + +#. module: nan_product_pack +#: field:product.pack.line,product_id:0 +msgid "Product" +msgstr "Product" + +#. module: nan_product_pack +#: view:product.pack.line:0 +msgid "Pack Product Lines" +msgstr "Pack Product Lines" + +#. module: nan_product_pack +#: view:product.product:0 +msgid "If you add products in the 'Pack Products' field, all those products will be added automatically when a new quotation or order is created." +msgstr "If you add products in the 'Pack Products' field, all those products will be added automatically when a new quotation or order is created." + +#. module: nan_product_pack +#: model:ir.module.module,description:nan_product_pack.module_meta_information +msgid "\n" +"Allows configuring products as a collection of other products. If such a product is added in a sale order, all the products of the pack will be added automatically (when storing the order) as children of the pack product.\n" +"\n" +"The module has been made compatible with nan_external_prices and containts code to specifically handle when the module is available but they're still independent and there are no dependencies between them.\n" +" " +msgstr "\n" +"Allows configuring products as a collection of other products. If such a product is added in a sale order, all the products of the pack will be added automatically (when storing the order) as children of the pack product.\n" +"\n" +"The module has been made compatible with nan_external_prices and containts code to specifically handle when the module is available but they're still independent and there are no dependencies between them.\n" +" " + +#. module: nan_product_pack +#: view:product.product:0 +#: field:sale.order.line,pack_parent_line_id:0 +msgid "Pack" +msgstr "Pack" + +#. module: nan_product_pack +#: model:ir.model,name:nan_product_pack.model_product_pack_line +msgid "product.pack.line" +msgstr "product.pack.line" + +#. module: nan_product_pack +#: constraint:ir.ui.view:0 +msgid "Invalid XML for View Architecture!" +msgstr "Invalid XML for View Architecture!" + +#. module: nan_product_pack +#: model:ir.module.module,shortdesc:nan_product_pack.module_meta_information +msgid "Product Pack" +msgstr "Product Pack" + +#. module: nan_product_pack +#: field:product.product,stock_depends:0 +msgid "Stock depends of components" +msgstr "Stock depends of components" + +#. module: nan_product_pack +#: help:sale.order.line,pack_parent_line_id:0 +msgid "The pack that contains this product." +msgstr "The pack that contains this product." + +#. module: nan_product_pack +#: field:sale.order.line,pack_depth:0 +msgid "Depth" +msgstr "Depth" + +#. module: nan_product_pack +#: help:product.product,pack_fixed_price:0 +msgid "Mark this field if the public price of the pack should be fixed. Do not mark it if the price should be calculated from the sum of the prices of the products in the pack." +msgstr "Mark this field if the public price of the pack should be fixed. Do not mark it if the price should be calculated from the sum of the prices of the products in the pack." + +#. module: nan_product_pack +#: field:product.pack.line,quantity:0 +msgid "Quantity" +msgstr "Quantity" + +#. module: nan_product_pack +#: view:product.product:0 +#: field:product.product,pack_line_ids:0 +msgid "Pack Products" +msgstr "Pack Products" + +#. module: nan_product_pack +#: field:product.pack.line,parent_product_id:0 +msgid "Parent Product" +msgstr "Parent Product" + +#. module: nan_product_pack +#: field:product.product,pack_fixed_price:0 +msgid "Pack has fixed price" +msgstr "Pack has fixed price" + +#. module: nan_product_pack +#: view:product.pack.line:0 +msgid "Pack Product Line" +msgstr "Pack Product Line" + +#. module: nan_product_pack +#: help:product.product,pack_line_ids:0 +msgid "List of products that are part of this pack." +msgstr "List of products that are part of this pack." + diff --git a/product_pack/i18n/pt.po b/product_pack/i18n/pt.po new file mode 100755 index 00000000..70935dd0 --- /dev/null +++ b/product_pack/i18n/pt.po @@ -0,0 +1,149 @@ +# Portuguese translation for openobject-addons +# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010 +# This file is distributed under the same license as the openobject-addons package. +# FIRST AUTHOR , 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: openobject-addons\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2011-01-15 11:45+0000\n" +"PO-Revision-Date: 2011-02-15 14:19+0000\n" +"Last-Translator: Luniz \n" +"Language-Team: Portuguese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2013-04-20 05:29+0000\n" +"X-Generator: Launchpad (build 16567)\n" + +#. module: nan_product_pack +#: constraint:ir.model:0 +msgid "" +"The Object name must start with x_ and not contain any special character !" +msgstr "" +"O nome do Objecto deve começar com x_ e não pode conter nenhum caracter " +"especial !" + +#. module: nan_product_pack +#: help:product.product,stock_depends:0 +msgid "Mark if pack stock is calcualted from component stock" +msgstr "" + +#. module: nan_product_pack +#: field:sale.order.line,pack_child_line_ids:0 +msgid "Lines in pack" +msgstr "Linhas em embalagens" + +#. module: nan_product_pack +#: help:sale.order.line,pack_depth:0 +msgid "Depth of the product if it is part of a pack." +msgstr "Profundidade do produto se ele faz parte da embalagem." + +#. module: nan_product_pack +#: field:product.pack.line,product_id:0 +msgid "Product" +msgstr "Produto" + +#. module: nan_product_pack +#: view:product.pack.line:0 +msgid "Pack Product Lines" +msgstr "Linhas de Embalagem de Produto" + +#. module: nan_product_pack +#: view:product.product:0 +msgid "" +"If you add products in the 'Pack Products' field, all those products will be " +"added automatically when a new quotation or order is created." +msgstr "" +"Se adicionar o produto no campo \"Embalagem de Produtos ', todos os produtos " +"serão adicionados automaticamente quando uma nova ordem de cotação é criado." + +#. module: nan_product_pack +#: model:ir.module.module,description:nan_product_pack.module_meta_information +msgid "" +"\n" +"Allows configuring products as a collection of other products. If such a " +"product is added in a sale order, all the products of the pack will be added " +"automatically (when storing the order) as children of the pack product.\n" +"\n" +"The module has been made compatible with nan_external_prices and containts " +"code to specifically handle when the module is available but they're still " +"independent and there are no dependencies between them.\n" +" " +msgstr "" + +#. module: nan_product_pack +#: view:product.product:0 +#: field:sale.order.line,pack_parent_line_id:0 +msgid "Pack" +msgstr "Embalagem" + +#. module: nan_product_pack +#: model:ir.model,name:nan_product_pack.model_product_pack_line +msgid "product.pack.line" +msgstr "product.pack.line" + +#. module: nan_product_pack +#: constraint:ir.ui.view:0 +msgid "Invalid XML for View Architecture!" +msgstr "XML Inválido para a Aquitectura de Vista!" + +#. module: nan_product_pack +#: model:ir.module.module,shortdesc:nan_product_pack.module_meta_information +msgid "Product Pack" +msgstr "Embalagem de Produto" + +#. module: nan_product_pack +#: field:product.product,stock_depends:0 +msgid "Stock depends of components" +msgstr "" + +#. module: nan_product_pack +#: help:sale.order.line,pack_parent_line_id:0 +msgid "The pack that contains this product." +msgstr "A embalagem que contém esse produto." + +#. module: nan_product_pack +#: field:sale.order.line,pack_depth:0 +msgid "Depth" +msgstr "Profundidade" + +#. module: nan_product_pack +#: help:product.product,pack_fixed_price:0 +msgid "" +"Mark this field if the public price of the pack should be fixed. Do not mark " +"it if the price should be calculated from the sum of the prices of the " +"products in the pack." +msgstr "" + +#. module: nan_product_pack +#: field:product.pack.line,quantity:0 +msgid "Quantity" +msgstr "Quantidade" + +#. module: nan_product_pack +#: view:product.product:0 +#: field:product.product,pack_line_ids:0 +msgid "Pack Products" +msgstr "Embalagem de Produtos" + +#. module: nan_product_pack +#: field:product.pack.line,parent_product_id:0 +msgid "Parent Product" +msgstr "Produto Ascendente" + +#. module: nan_product_pack +#: field:product.product,pack_fixed_price:0 +msgid "Pack has fixed price" +msgstr "A Embalagem tem preço fixado" + +#. module: nan_product_pack +#: view:product.pack.line:0 +msgid "Pack Product Line" +msgstr "Linha de Embalagem de Produto" + +#. module: nan_product_pack +#: help:product.product,pack_line_ids:0 +msgid "List of products that are part of this pack." +msgstr "Lista dos produtos que fazem parte desta embalagem." diff --git a/product_pack/pack.py b/product_pack/pack.py new file mode 100755 index 00000000..206f5176 --- /dev/null +++ b/product_pack/pack.py @@ -0,0 +1,135 @@ +# -*- encoding: latin-1 -*- +############################################################################## +# +# Ingenieria ADHOC - ADHOC SA +# https://launchpad.net/~ingenieria-adhoc# +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import math +from openerp.osv import fields,osv + +class product_pack( osv.osv ): + _name = 'product.pack.line' + _rec_name = 'product_id' + _columns = { + 'parent_product_id': fields.many2one( 'product.product', 'Parent Product', ondelete='cascade', required=True ), + 'quantity': fields.float( 'Quantity', required=True ), + 'product_id': fields.many2one( 'product.product', 'Product', required=True ), + } + +product_pack() + +class product_product( osv.osv ): + _inherit = 'product.product' + _columns = { + 'stock_depends': fields.boolean( 'Stock depends of components', help='Mark if pack stock is calcualted from component stock' ), + 'pack_fixed_price': fields.boolean( 'Pack has fixed price', help='Mark this field if the public price of the pack should be fixed. Do not mark it if the price should be calculated from the sum of the prices of the products in the pack.' ), + 'pack_line_ids': fields.one2many( 'product.pack.line','parent_product_id', 'Pack Products', help='List of products that are part of this pack.' ), + } + + def get_product_available( self, cr, uid, ids, context=None ): + """ Calulate stock for packs, return maximum stock that lets complete pack """ + result={} + # for product in self.browse( cr, uid, ids, context=context ): + result = super( product_product, self ).get_product_available( cr, uid, ids, context=context ) + if not isinstance(ids, list): + ids = [ids] + stock_depends_products = self.search(cr, uid, [('stock_depends', '=',True),('id','in',ids)], context=context) + for product in self.browse( cr, uid, stock_depends_products, context=context ): + + first_subproduct = True + pack_stock = 0 + # Check if the pack has subproducts + if product.pack_line_ids: + # Take the stock/virtual stock of all subproducts + subproducts_stock = super( product_product, self ).get_product_available(cr, uid, [ line.product_id.id for line in product.pack_line_ids ], context=context ) + + # Go over all subproducts, take quantity needed for the pack and its available stock + for subproduct in product.pack_line_ids: + if first_subproduct: + subproduct_quantity = subproduct.quantity + subproduct_stock = subproducts_stock[ subproduct.product_id.id ] + # Calculate real stock for current pack from the subproduct stock and needed quantity + pack_stock = math.floor( subproduct_stock / subproduct_quantity ) + first_subproduct = False + continue + # Take the info of the next subproduct + subproduct_quantity_next = subproduct.quantity + subproduct_stock_next = subproducts_stock[ subproduct.product_id.id ] + pack_stock_next = math.floor( subproduct_stock_next / subproduct_quantity_next ) + # compare the stock of a subproduct and the next subproduct + if pack_stock_next < pack_stock: + pack_stock = pack_stock_next + # result is the minimum stock of all subproducts + result[ product.id ] = pack_stock + else: + stock = super( product_product, self ).get_product_available( cr, uid, [ product.id ], context=context ) + result[ product.id ] = stock[ product.id ] + return result + +# back up de funcion + # def get_product_available( self, cr, uid, ids, context=None ): + # """ Calulate stock for packs, return maximum stock that lets complete pack """ + # result={} + # for product in self.browse( cr, uid, ids, context=context ): + # stock = super( product_product, self ).get_product_available( cr, uid, [ product.id ], context=context ) + # print product.id + # # Check if product stock depends on it's subproducts stock. + # if not product.stock_depends: + # result[ product.id ] = stock[ product.id ] + # continue + + # first_subproduct = True + # pack_stock = 0 + + # # Check if the pack has subproducts + # if product.pack_line_ids: + # # Take the stock/virtual stock of all subproducts + # subproducts_stock = self.get_product_available( cr, uid, [ line.product_id.id for line in product.pack_line_ids ], context=context ) + # # Go over all subproducts, take quantity needed for the pack and its available stock + # for subproduct in product.pack_line_ids: + # if first_subproduct: + # subproduct_quantity = subproduct.quantity + # subproduct_stock = subproducts_stock[ subproduct.product_id.id ] + # # Calculate real stock for current pack from the subproduct stock and needed quantity + # pack_stock = math.floor( subproduct_stock / subproduct_quantity ) + # first_subproduct = False + # continue + # # Take the info of the next subproduct + # subproduct_quantity_next = subproduct.quantity + # subproduct_stock_next = subproducts_stock[ subproduct.product_id.id ] + # pack_stock_next = math.floor( subproduct_stock_next / subproduct_quantity_next ) + # # compare the stock of a subproduct and the next subproduct + # if pack_stock_next < pack_stock: + # pack_stock = pack_stock_next + # # result is the minimum stock of all subproducts + # result[ product.id ] = pack_stock + # else: + # result[ product.id ] = stock[ product.id ] + # return result + +product_product() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/product_pack/pack_view.xml b/product_pack/pack_view.xml new file mode 100755 index 00000000..36c553b7 --- /dev/null +++ b/product_pack/pack_view.xml @@ -0,0 +1,51 @@ + + + + + + + product.product.pack.form + product.product + form + + + + + + + + + + + + product.pack.line.form + product.pack.line + form + +
+ + + + +
+ + product.pack.line.tree + product.pack.line + tree + + + + + + + +
+
+ diff --git a/product_pack/sale.py b/product_pack/sale.py new file mode 100755 index 00000000..75816346 --- /dev/null +++ b/product_pack/sale.py @@ -0,0 +1,228 @@ +# -*- encoding: latin-1 -*- +############################################################################## +# +# Ingenieria ADHOC - ADHOC SA +# https://launchpad.net/~ingenieria-adhoc# +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import math +from openerp.osv import fields,osv + + +class sale_order_line(osv.osv): + _inherit = 'sale.order.line' + _columns = { + 'pack_depth': fields.integer('Depth', required=True, help='Depth of the product if it is part of a pack.'), + 'pack_parent_line_id': fields.many2one('sale.order.line', 'Pack', help='The pack that contains this product.'), + 'pack_child_line_ids': fields.one2many('sale.order.line', 'pack_parent_line_id', 'Lines in pack', help=''), + } + _defaults = { + 'pack_depth': lambda *a: 0, + } +sale_order_line() + +class sale_order(osv.osv): + _inherit = 'sale.order' + + def create(self, cr, uid, vals, context=None): + result = super(sale_order,self).create(cr, uid, vals, context) + self.expand_packs(cr, uid, [result], context) + return result + + def write(self, cr, uid, ids, vals, context=None): + result = super(sale_order,self).write(cr, uid, ids, vals, context) + self.expand_packs(cr, uid, ids, context) + return result + + def expand_packs(self, cr, uid, ids, context={}, depth=1): + + + def get_real_price(res_dict, product_id, qty, uom, pricelist): + item_obj = self.pool.get('product.pricelist.item') + price_type_obj = self.pool.get('product.price.type') + product_obj = self.pool.get('product.product') + template_obj = self.pool.get('product.template') + field_name = 'list_price' + + if res_dict.get('item_id',False) and res_dict['item_id'].get(pricelist,False): + item = res_dict['item_id'].get(pricelist,False) + item_base = item_obj.read(cr, uid, [item], ['base'])[0]['base'] + if item_base > 0: + field_name = price_type_obj.browse(cr, uid, item_base).field + + product = product_obj.browse(cr, uid, product_id, context) + product_tmpl_id = product.product_tmpl_id.id + + product_read = template_obj.read(cr, uid, product_tmpl_id, [field_name], context) + + factor = 1.0 + if uom and uom != product.uom_id.id: + product_uom_obj = self.pool.get('product.uom') + uom_data = product_uom_obj.browse(cr, uid, product.uom_id.id) + factor = uom_data.factor + return product_read[field_name] * factor + + if depth == 10: + return + updated_orders = [] + + for order in self.browse(cr, uid, ids, context): + + fiscal_position = order.fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, order.fiscal_position, context) or False + + # The reorder variable is used to ensure lines of the same pack go right after their + # parent. + # What the algorithm does is check if the previous item had children. As children items + # must go right after the parent if the line we're evaluating doesn't have a parent it + # means it's a new item (and probably has the default 10 sequence number - unless the + # appropiate c2c_sale_sequence module is installed). In this case we mark the item for + # reordering and evaluate the next one. Note that as the item is not evaluated and it might + # have to be expanded it's put on the queue for another iteration (it's simple and works well). + # Once the next item has been evaluated the sequence of the item marked for reordering is updated + # with the next value. + + sequence = -1 + reorder = [] + last_had_children = False + for line in order.order_line: + if last_had_children and not line.pack_parent_line_id: + reorder.append( line.id ) + if line.product_id.pack_line_ids and not order.id in updated_orders: + updated_orders.append( order.id ) + continue + + sequence += 1 + + if sequence > line.sequence: + self.pool.get('sale.order.line').write(cr, uid, [line.id], { + 'sequence': sequence, + }, context) + else: + sequence = line.sequence + + if line.state != 'draft': + continue + if not line.product_id: + continue + + # If pack was already expanded (in another create/write operation or in + # a previous iteration) don't do it again. + if line.pack_child_line_ids: + last_had_children = True + continue + last_had_children = False + + for subline in line.product_id.pack_line_ids: + sequence += 1 + + subproduct = subline.product_id + quantity = subline.quantity * line.product_uom_qty + + if line.product_id.pack_fixed_price: + price = 0.0 + discount = 0.0 + else: + pricelist = order.pricelist_id.id + list_price = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist], + subproduct.id, quantity, order.partner_id.id, { + 'uom': subproduct.uom_id.id, + 'date': order.date_order, + }) + price = list_price[pricelist] + + # Added functionality for compatibility with product_visible_discount module + pricelist_obj=self.pool.get('product.pricelist') + pricelists = pricelist_obj.read(cr,uid,[pricelist],['visible_discount']) + new_list_price = get_real_price(list_price, subproduct.id, quantity, subproduct.uom_id.id, pricelist) + discount = line.discount + if pricelists[0].has_key("visible_discount"): + if(len(pricelists)>0 and pricelists[0]['visible_discount'] and list_price[pricelist] != 0): + discount += (new_list_price - price) / new_list_price * 100 + price = new_list_price + + # Obtain product name in partner's language + ctx = {'lang': order.partner_id.lang} + subproduct_name = self.pool.get('product.product').browse(cr, uid, subproduct.id, ctx).name + + tax_ids = self.pool.get('account.fiscal.position').map_tax(cr, uid, fiscal_position, subproduct.taxes_id) + + if subproduct.uos_id: + uos_id = subproduct.uos_id.id + uos_qty = quantity * subproduct.uos_coeff + else: + uos_id = False + uos_qty = quantity + + vals = { + 'order_id': order.id, + 'name': '%s%s' % ('> '* (line.pack_depth+1), subproduct_name), + 'sequence': sequence, + 'delay': subproduct.sale_delay or 0.0, + 'product_id': subproduct.id, + 'procurement_id': line.procurement_id and line.procurement_id.id or False, + 'price_unit': price, + 'tax_id': [(6,0,tax_ids)], + 'type': subproduct.procure_method, + 'property_ids': [(6,0,[])], + 'address_allotment_id': False, + 'product_uom_qty': quantity, + 'product_uom': subproduct.uom_id.id, + 'product_uos_qty': uos_qty, + 'product_uos': uos_id, + 'product_packaging': False, + 'move_ids': [(6,0,[])], + 'discount': discount, + 'number_packages': False, + 'notes': False, + 'th_weight': False, + 'state': 'draft', + 'pack_parent_line_id': line.id, + 'pack_depth': line.pack_depth + 1, + } + + # It's a control for the case that the nan_external_prices was installed with the product pack + if 'prices_used' in line: + vals[ 'prices_used' ] = line.prices_used + + self.pool.get('sale.order.line').create(cr, uid, vals, context) + if not order.id in updated_orders: + updated_orders.append( order.id ) + + for id in reorder: + sequence += 1 + self.pool.get('sale.order.line').write(cr, uid, [id], { + 'sequence': sequence, + }, context) + + if updated_orders: + # Try to expand again all those orders that had a pack in this iteration. + # This way we support packs inside other packs. + self.expand_packs(cr, uid, ids, context, depth+1) + return + +sale_order() + + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/product_pack/security/ir.model.access.csv b/product_pack/security/ir.model.access.csv new file mode 100755 index 00000000..140b1b8d --- /dev/null +++ b/product_pack/security/ir.model.access.csv @@ -0,0 +1,3 @@ +"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" +"access_product_pack_line_manager","product.pack.line manager","model_product_pack_line","base.group_sale_manager",1,1,1,1 +"access_product_pack_line_mployee","product.pack.line employee","model_product_pack_line","base.group_user",1,0,0,0 diff --git a/product_pack/stock.py b/product_pack/stock.py new file mode 100755 index 00000000..1edc90f5 --- /dev/null +++ b/product_pack/stock.py @@ -0,0 +1,166 @@ +# -*- encoding: latin-1 -*- +############################################################################## +# +# Ingenieria ADHOC - ADHOC SA +# https://launchpad.net/~ingenieria-adhoc# +# +# WARNING: This program as such is intended to be used by professional +# programmers who take the whole responsability of assessing all potential +# consequences resulting from its eventual inadequacies and bugs +# End users who are looking for a ready-to-use solution with commercial +# garantees and support are strongly adviced to contract a Free Software +# Service Company +# +# This program is Free Software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################## + +import math +from openerp.osv import fields,osv + +class stock_move(osv.osv): + _inherit = 'stock.move' + + _columns = { + 'pack_depth': fields.integer('Depth', required=True, help='Depth of the product if it is part of a pack.'), + 'pack_parent_line_id': fields.many2one('stock.move', 'Pack', help='The pack that contains this product.'), + 'pack_child_line_ids': fields.one2many('stock.move', 'pack_parent_line_id', 'Lines in pack', help=''), + } + _defaults = { + 'pack_depth': lambda *a: 0, + } + +stock_move() + +class stock_picking(osv.osv): + _inherit = 'stock.picking' + + + def create(self, cr, uid, vals, context=None): + result = super(stock_picking,self).create(cr, uid, vals, context) + self.expand_packs(cr, uid, [result], context) + return result + + def write(self, cr, uid, ids, vals, context=None): + result = super(stock_picking,self).write(cr, uid, ids, vals, context) + self.expand_packs(cr, uid, ids, context) + return result + + def expand_packs(self, cr, uid, ids, context={}, depth=1): + if depth == 10: + return + updated_orders = [] + for order in self.browse(cr, uid, ids, context): + + + # The reorder variable is used to ensure lines of the same pack go right after their + # parent. + # What the algorithm does is check if the previous item had children. As children items + # must go right after the parent if the line we're evaluating doesn't have a parent it + # means it's a new item (and probably has the default 10 sequence number - unless the + # appropiate c2c_sale_sequence module is installed). In this case we mark the item for + # reordering and evaluate the next one. Note that as the item is not evaluated and it might + # have to be expanded it's put on the queue for another iteration (it's simple and works well). + # Once the next item has been evaluated the sequence of the item marked for reordering is updated + # with the next value. + # sequence = -1 + reorder = [] + last_had_children = False + for line in order.move_lines: + if last_had_children and not line.pack_parent_line_id: + reorder.append( line.id ) + if line.product_id.pack_line_ids and not order.id in updated_orders: + updated_orders.append( order.id ) + continue + + if line.sale_line_id or line.sale_line_id: + continue + if line.state != 'draft': + continue + if not line.product_id: + continue + # If pack was already expanded (in another create/write operation or in + # a previous iteration) don't do it again. + if line.pack_child_line_ids: + last_had_children = True + continue + last_had_children = False + + for subline in line.product_id.pack_line_ids: + + subproduct = subline.product_id + # quantity = subline.quantity * line.product_uom_qty + quantity = subline.quantity * line.product_qty + + # if line.product_id.pack_fixed_price: + # # price = 0.0 + # # discount = 0.0 + # else: + # # pricelist = order.pricelist_id.id + # price = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist], + # subproduct.id, quantity, order.partner_id.id, { + # 'uom': subproduct.uom_id.id, + # 'date': order.date_order, + # })[pricelist] + # discount = line.discount + + # Obtain product name in partner's language + ctx = {'lang': order.partner_id.lang} + subproduct_name = self.pool.get('product.product').browse(cr, uid, subproduct.id, ctx).name + + # tax_ids = self.pool.get('account.fiscal.position').map_tax(cr, uid, fiscal_position, subproduct.taxes_id) + + if subproduct.uos_id: + uos_id = subproduct.uos_id.id + uos_qty = quantity * subproduct.uos_coeff + else: + uos_id = False + uos_qty = quantity + + vals = { + 'name': line.picking_id.origin or '' + ':' + subproduct.name, + 'product_id': subproduct.id, + 'product_qty': quantity, + 'product_uos_qty': quantity, + 'product_uom': subproduct.uom_id.id, + 'location_id': line.location_id.id, + 'location_dest_id': line.location_dest_id.id, + 'picking_id': line.picking_id.id, + 'address_id': line.address_id.id, + 'date_expected': line.date_expected, + 'origin': line.origin, + 'purchase_line_id': line.purchase_line_id.id, + 'sale_line_id': line.sale_line_id.id, + 'product_packaging': line.product_packaging, + 'pack_parent_line_id': line.id, + 'pack_depth': line.pack_depth + 1, + } + + self.pool.get('stock.move').create(cr, uid, vals, context) + if not order.id in updated_orders: + updated_orders.append( order.id ) + + for id in reorder: + self.pool.get('stock.move').write(cr, uid, [id], {}, context) + + if updated_orders: + # Try to expand again all those orders that had a pack in this iteration. + # This way we support packs inside other packs. + self.expand_packs(cr, uid, ids, context, depth+1) + return + +stock_picking() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 3fd46eb8382fd2d0de3cf243ae5d11165c81f8e9 Mon Sep 17 00:00:00 2001 From: nicomacr Date: Wed, 24 Sep 2014 14:00:49 -0300 Subject: [PATCH 02/75] [FIX] traslation and clean modules --- product_pack/__init__.py | 30 ++---------------------------- product_pack/__openerp__.py | 20 +------------------- product_pack/pack.py | 28 +--------------------------- product_pack/sale.py | 28 +--------------------------- product_pack/stock.py | 28 +--------------------------- 5 files changed, 6 insertions(+), 128 deletions(-) diff --git a/product_pack/__init__.py b/product_pack/__init__.py index ba80327f..5b963ef6 100755 --- a/product_pack/__init__.py +++ b/product_pack/__init__.py @@ -1,32 +1,6 @@ # -*- encoding: latin-1 -*- -############################################################################## -# -# Ingenieria ADHOC - ADHOC SA -# https://launchpad.net/~ingenieria-adhoc -# -# -# WARNING: This program as such is intended to be used by professional -# programmers who take the whole responsability of assessing all potential -# consequences resulting from its eventual inadequacies and bugs -# End users who are looking for a ready-to-use solution with commercial -# garantees and support are strongly adviced to contract a Free Software -# Service Company -# -# This program is Free Software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -############################################################################## + + import pack import sale diff --git a/product_pack/__openerp__.py b/product_pack/__openerp__.py index 4707a750..672007a9 100755 --- a/product_pack/__openerp__.py +++ b/product_pack/__openerp__.py @@ -1,23 +1,5 @@ # -*- coding: utf-8 -*- -############################################################################## -# -# Ingenieria ADHOC - ADHOC SA -# https://launchpad.net/~ingenieria-adhoc -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# -############################################################################## + { 'name': 'Product Pack', diff --git a/product_pack/pack.py b/product_pack/pack.py index 206f5176..d8ebbefd 100755 --- a/product_pack/pack.py +++ b/product_pack/pack.py @@ -1,31 +1,5 @@ # -*- encoding: latin-1 -*- -############################################################################## -# -# Ingenieria ADHOC - ADHOC SA -# https://launchpad.net/~ingenieria-adhoc# -# -# WARNING: This program as such is intended to be used by professional -# programmers who take the whole responsability of assessing all potential -# consequences resulting from its eventual inadequacies and bugs -# End users who are looking for a ready-to-use solution with commercial -# garantees and support are strongly adviced to contract a Free Software -# Service Company -# -# This program is Free Software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -############################################################################## + import math from openerp.osv import fields,osv diff --git a/product_pack/sale.py b/product_pack/sale.py index 75816346..a22051fd 100755 --- a/product_pack/sale.py +++ b/product_pack/sale.py @@ -1,31 +1,5 @@ # -*- encoding: latin-1 -*- -############################################################################## -# -# Ingenieria ADHOC - ADHOC SA -# https://launchpad.net/~ingenieria-adhoc# -# -# WARNING: This program as such is intended to be used by professional -# programmers who take the whole responsability of assessing all potential -# consequences resulting from its eventual inadequacies and bugs -# End users who are looking for a ready-to-use solution with commercial -# garantees and support are strongly adviced to contract a Free Software -# Service Company -# -# This program is Free Software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -############################################################################## + import math from openerp.osv import fields,osv diff --git a/product_pack/stock.py b/product_pack/stock.py index 1edc90f5..374e4c47 100755 --- a/product_pack/stock.py +++ b/product_pack/stock.py @@ -1,31 +1,5 @@ # -*- encoding: latin-1 -*- -############################################################################## -# -# Ingenieria ADHOC - ADHOC SA -# https://launchpad.net/~ingenieria-adhoc# -# -# WARNING: This program as such is intended to be used by professional -# programmers who take the whole responsability of assessing all potential -# consequences resulting from its eventual inadequacies and bugs -# End users who are looking for a ready-to-use solution with commercial -# garantees and support are strongly adviced to contract a Free Software -# Service Company -# -# This program is Free Software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -############################################################################## + import math from openerp.osv import fields,osv From 36f2c92469c8b8c2875b948be72cfe66bc9f4bc8 Mon Sep 17 00:00:00 2001 From: Juan Jose Scarafia Date: Mon, 26 Jan 2015 10:55:38 -0300 Subject: [PATCH 03/75] [IMP/FIX] product pack IMP product pack to support surveyor packs IMP pack description IMP add product pack standar functionality for v8 and general improvements IMP discounts and portal distributors permissions FIX product_pack license and author FIX prod pack available IMP pack to restrict company in products FIX pack company restriction --- product_pack/__init__.py | 9 +- product_pack/__openerp__.py | 42 ++- product_pack/i18n/ca.po | 163 ---------- product_pack/i18n/de.po | 145 --------- product_pack/i18n/it.po | 163 ---------- product_pack/i18n/nan_product_pack.pot | 137 -------- product_pack/i18n/pt.po | 149 --------- product_pack/pack.py | 202 ++++++------ product_pack/pack_view.xml | 27 +- product_pack/sale.py | 343 +++++++++++++-------- product_pack/sale_view.xml | 51 +++ product_pack/security/ir.model.access.csv | 8 +- product_pack/security/product_security.xml | 11 + product_pack/stock.py | 140 --------- 14 files changed, 443 insertions(+), 1147 deletions(-) delete mode 100755 product_pack/i18n/ca.po delete mode 100755 product_pack/i18n/de.po delete mode 100755 product_pack/i18n/it.po delete mode 100755 product_pack/i18n/nan_product_pack.pot delete mode 100755 product_pack/i18n/pt.po create mode 100644 product_pack/sale_view.xml create mode 100644 product_pack/security/product_security.xml delete mode 100755 product_pack/stock.py diff --git a/product_pack/__init__.py b/product_pack/__init__.py index 5b963ef6..ec3f42b5 100755 --- a/product_pack/__init__.py +++ b/product_pack/__init__.py @@ -1,7 +1,6 @@ -# -*- encoding: latin-1 -*- - - - +# -*- encoding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## import pack import sale -import stock \ No newline at end of file diff --git a/product_pack/__openerp__.py b/product_pack/__openerp__.py index 672007a9..285e3d78 100755 --- a/product_pack/__openerp__.py +++ b/product_pack/__openerp__.py @@ -1,6 +1,23 @@ # -*- coding: utf-8 -*- - - +############################################################################## +# +# Copyright (C) 2009 Àngel Àlvarez - NaN (http://www.nan-tic.com) +# All Rights Reserved. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## { 'name': 'Product Pack', 'version': '1.0', @@ -10,28 +27,29 @@ 'description': """ Product Pack ============ -Allows configuring products as a collection of other products. If such a product is added in a sale order, all the products of the pack will be added automatically (when storing the order) as children of the pack product. - -The module has been made compatible with nan_external_prices and containts code to specifically handle when the module is available but they're still independent and there are no dependencies between them. +# TODO agregar en configuracion si se quiere usar los sale order packs (seria para el group group_pack) y ver que se haga visible la vista form +# TODO implementar totalice en price get +# TODO agregar constraint de no pack dentro de pack +# TODO calcular correctamente pack virtual available para negativos """, - 'author': 'Ingenieria ADHOC', - 'website': 'www.ingadhoc.com', + 'author': 'NaN·tic, ADHOC', 'images': [ ], 'depends': [ 'sale', - 'stock', ], 'data': [ - 'security/ir.model.access.csv', - 'pack_view.xml' + 'security/ir.model.access.csv', + 'security/product_security.xml', + 'pack_view.xml', + 'sale_view.xml', ], 'demo': [ ], 'test': [ ], - 'installable': False, + 'installable': True, 'auto_install': False, 'application': False, } -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: \ No newline at end of file +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/product_pack/i18n/ca.po b/product_pack/i18n/ca.po deleted file mode 100755 index 276a799b..00000000 --- a/product_pack/i18n/ca.po +++ /dev/null @@ -1,163 +0,0 @@ -# Translation of OpenERP Server. -# This file contains the translation of the following modules: -# * nan_product_pack -# -msgid "" -msgstr "" -"Project-Id-Version: OpenERP Server 5.0.6\n" -"Report-Msgid-Bugs-To: support@openerp.com\n" -"POT-Creation-Date: 2011-01-15 11:45+0000\n" -"PO-Revision-Date: 2011-02-15 14:19+0000\n" -"Last-Translator: Jordi Esteve (Zikzakmedia) \n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-04-20 05:29+0000\n" -"X-Generator: Launchpad (build 16567)\n" - -#. module: nan_product_pack -#: constraint:ir.model:0 -msgid "" -"The Object name must start with x_ and not contain any special character !" -msgstr "" -"El nom de l'objecte ha de començar amb x_ i no contenir cap caràcter " -"especial!" - -#. module: nan_product_pack -#: help:product.product,stock_depends:0 -msgid "Mark if pack stock is calcualted from component stock" -msgstr "" -"Marqueu aquest camp si l'estoc del paquet es calcula a partir de l'estoc " -"dels components." - -#. module: nan_product_pack -#: field:sale.order.line,pack_child_line_ids:0 -msgid "Lines in pack" -msgstr "Línies en el paquet" - -#. module: nan_product_pack -#: help:sale.order.line,pack_depth:0 -msgid "Depth of the product if it is part of a pack." -msgstr "Profunditat del producte si forma part d'un paquet." - -#. module: nan_product_pack -#: field:product.pack.line,product_id:0 -msgid "Product" -msgstr "Producte" - -#. module: nan_product_pack -#: view:product.pack.line:0 -msgid "Pack Product Lines" -msgstr "Línies del paquet de productes" - -#. module: nan_product_pack -#: view:product.product:0 -msgid "" -"If you add products in the 'Pack Products' field, all those products will be " -"added automatically when a new quotation or order is created." -msgstr "" -"Si afegiu productes en el camp \"Paquet de productes\", tots els productes " -"s'afegiran automàticament quan creeu un nou pressupost o comanda." - -#. module: nan_product_pack -#: model:ir.module.module,description:nan_product_pack.module_meta_information -msgid "" -"\n" -"Allows configuring products as a collection of other products. If such a " -"product is added in a sale order, all the products of the pack will be added " -"automatically (when storing the order) as children of the pack product.\n" -"\n" -"The module has been made compatible with nan_external_prices and containts " -"code to specifically handle when the module is available but they're still " -"independent and there are no dependencies between them.\n" -" " -msgstr "" -"\n" -"Permet configurar els productes com col·leccions d'altres productes. Si " -"s'afegeix un producte d'aquest tipus en una comanda de venda, tots els " -"productes del paquet s'afegiran automàticament (quan es guardi la comanda) " -"com a fills del producte principal.\n" -"\n" -"Aquest mòdul és compatible amb nan_external_prices i conté codi per " -"funcionar quan està instal·lat encara que ambdós són encara independents i " -"no hi ha dependències entre ells.\n" -" " - -#. module: nan_product_pack -#: view:product.product:0 -#: field:sale.order.line,pack_parent_line_id:0 -msgid "Pack" -msgstr "Paquet" - -#. module: nan_product_pack -#: model:ir.model,name:nan_product_pack.model_product_pack_line -msgid "product.pack.line" -msgstr "producte.paquet.línea" - -#. module: nan_product_pack -#: constraint:ir.ui.view:0 -msgid "Invalid XML for View Architecture!" -msgstr "XML no vàlid per a la definició de la vista!" - -#. module: nan_product_pack -#: model:ir.module.module,shortdesc:nan_product_pack.module_meta_information -msgid "Product Pack" -msgstr "Paquet de productes" - -#. module: nan_product_pack -#: field:product.product,stock_depends:0 -msgid "Stock depends of components" -msgstr "Estoc depen dels components" - -#. module: nan_product_pack -#: help:sale.order.line,pack_parent_line_id:0 -msgid "The pack that contains this product." -msgstr "El paquet que conté aquest producte." - -#. module: nan_product_pack -#: field:sale.order.line,pack_depth:0 -msgid "Depth" -msgstr "Profunditat" - -#. module: nan_product_pack -#: help:product.product,pack_fixed_price:0 -msgid "" -"Mark this field if the public price of the pack should be fixed. Do not mark " -"it if the price should be calculated from the sum of the prices of the " -"products in the pack." -msgstr "" -"Marqueu aquest camp si el preu de venda del paquet ha de ser fix. No ho " -"marqueu si el preu s'ha de calcular a partir de la suma dels preus dels " -"productes del paquet." - -#. module: nan_product_pack -#: field:product.pack.line,quantity:0 -msgid "Quantity" -msgstr "Quantitat" - -#. module: nan_product_pack -#: view:product.product:0 -#: field:product.product,pack_line_ids:0 -msgid "Pack Products" -msgstr "Productes del paquet" - -#. module: nan_product_pack -#: field:product.pack.line,parent_product_id:0 -msgid "Parent Product" -msgstr "Producte pare" - -#. module: nan_product_pack -#: field:product.product,pack_fixed_price:0 -msgid "Pack has fixed price" -msgstr "El paquet té un preu fix" - -#. module: nan_product_pack -#: view:product.pack.line:0 -msgid "Pack Product Line" -msgstr "Línia de paquet de productes" - -#. module: nan_product_pack -#: help:product.product,pack_line_ids:0 -msgid "List of products that are part of this pack." -msgstr "Llista de productes que formen part del paquet." diff --git a/product_pack/i18n/de.po b/product_pack/i18n/de.po deleted file mode 100755 index 7a7707ed..00000000 --- a/product_pack/i18n/de.po +++ /dev/null @@ -1,145 +0,0 @@ -# German translation for openobject-addons -# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 -# This file is distributed under the same license as the openobject-addons package. -# FIRST AUTHOR , 2011. -# -msgid "" -msgstr "" -"Project-Id-Version: openobject-addons\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2011-01-15 11:45+0000\n" -"PO-Revision-Date: 2011-02-15 14:19+0000\n" -"Last-Translator: FULL NAME \n" -"Language-Team: German \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-04-20 05:29+0000\n" -"X-Generator: Launchpad (build 16567)\n" - -#. module: nan_product_pack -#: constraint:ir.model:0 -msgid "" -"The Object name must start with x_ and not contain any special character !" -msgstr "" - -#. module: nan_product_pack -#: help:product.product,stock_depends:0 -msgid "Mark if pack stock is calcualted from component stock" -msgstr "" - -#. module: nan_product_pack -#: field:sale.order.line,pack_child_line_ids:0 -msgid "Lines in pack" -msgstr "" - -#. module: nan_product_pack -#: help:sale.order.line,pack_depth:0 -msgid "Depth of the product if it is part of a pack." -msgstr "" - -#. module: nan_product_pack -#: field:product.pack.line,product_id:0 -msgid "Product" -msgstr "" - -#. module: nan_product_pack -#: view:product.pack.line:0 -msgid "Pack Product Lines" -msgstr "" - -#. module: nan_product_pack -#: view:product.product:0 -msgid "" -"If you add products in the 'Pack Products' field, all those products will be " -"added automatically when a new quotation or order is created." -msgstr "" - -#. module: nan_product_pack -#: model:ir.module.module,description:nan_product_pack.module_meta_information -msgid "" -"\n" -"Allows configuring products as a collection of other products. If such a " -"product is added in a sale order, all the products of the pack will be added " -"automatically (when storing the order) as children of the pack product.\n" -"\n" -"The module has been made compatible with nan_external_prices and containts " -"code to specifically handle when the module is available but they're still " -"independent and there are no dependencies between them.\n" -" " -msgstr "" - -#. module: nan_product_pack -#: view:product.product:0 -#: field:sale.order.line,pack_parent_line_id:0 -msgid "Pack" -msgstr "" - -#. module: nan_product_pack -#: model:ir.model,name:nan_product_pack.model_product_pack_line -msgid "product.pack.line" -msgstr "" - -#. module: nan_product_pack -#: constraint:ir.ui.view:0 -msgid "Invalid XML for View Architecture!" -msgstr "" - -#. module: nan_product_pack -#: model:ir.module.module,shortdesc:nan_product_pack.module_meta_information -msgid "Product Pack" -msgstr "" - -#. module: nan_product_pack -#: field:product.product,stock_depends:0 -msgid "Stock depends of components" -msgstr "" - -#. module: nan_product_pack -#: help:sale.order.line,pack_parent_line_id:0 -msgid "The pack that contains this product." -msgstr "" - -#. module: nan_product_pack -#: field:sale.order.line,pack_depth:0 -msgid "Depth" -msgstr "" - -#. module: nan_product_pack -#: help:product.product,pack_fixed_price:0 -msgid "" -"Mark this field if the public price of the pack should be fixed. Do not mark " -"it if the price should be calculated from the sum of the prices of the " -"products in the pack." -msgstr "" - -#. module: nan_product_pack -#: field:product.pack.line,quantity:0 -msgid "Quantity" -msgstr "" - -#. module: nan_product_pack -#: view:product.product:0 -#: field:product.product,pack_line_ids:0 -msgid "Pack Products" -msgstr "" - -#. module: nan_product_pack -#: field:product.pack.line,parent_product_id:0 -msgid "Parent Product" -msgstr "" - -#. module: nan_product_pack -#: field:product.product,pack_fixed_price:0 -msgid "Pack has fixed price" -msgstr "" - -#. module: nan_product_pack -#: view:product.pack.line:0 -msgid "Pack Product Line" -msgstr "" - -#. module: nan_product_pack -#: help:product.product,pack_line_ids:0 -msgid "List of products that are part of this pack." -msgstr "" diff --git a/product_pack/i18n/it.po b/product_pack/i18n/it.po deleted file mode 100755 index 3642ba38..00000000 --- a/product_pack/i18n/it.po +++ /dev/null @@ -1,163 +0,0 @@ -# Italian translation for openobject-addons -# Copyright (c) 2011 Rosetta Contributors and Canonical Ltd 2011 -# This file is distributed under the same license as the openobject-addons package. -# FIRST AUTHOR , 2011. -# -msgid "" -msgstr "" -"Project-Id-Version: openobject-addons\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2011-01-15 11:45+0000\n" -"PO-Revision-Date: 2011-05-03 10:13+0000\n" -"Last-Translator: FULL NAME \n" -"Language-Team: Italian \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-04-20 05:29+0000\n" -"X-Generator: Launchpad (build 16567)\n" - -#. module: nan_product_pack -#: constraint:ir.model:0 -msgid "" -"The Object name must start with x_ and not contain any special character !" -msgstr "" -"Il nome dell'oggetto deve iniziare con x_ e non deve contenere alcun " -"carattere speciale !" - -#. module: nan_product_pack -#: help:product.product,stock_depends:0 -msgid "Mark if pack stock is calcualted from component stock" -msgstr "" -"Selezionare se la giacenza del kit è calcolata sulla base della giacenza dei " -"componenti" - -#. module: nan_product_pack -#: field:sale.order.line,pack_child_line_ids:0 -msgid "Lines in pack" -msgstr "Righe nel kit" - -#. module: nan_product_pack -#: help:sale.order.line,pack_depth:0 -msgid "Depth of the product if it is part of a pack." -msgstr "Profondità del prodotto se è parte di un kit" - -#. module: nan_product_pack -#: field:product.pack.line,product_id:0 -msgid "Product" -msgstr "Prodotto" - -#. module: nan_product_pack -#: view:product.pack.line:0 -msgid "Pack Product Lines" -msgstr "Righe Kit" - -#. module: nan_product_pack -#: view:product.product:0 -msgid "" -"If you add products in the 'Pack Products' field, all those products will be " -"added automatically when a new quotation or order is created." -msgstr "" -"Se si aggiungono prodotti nel campo 'Prodotti Kit', tutti quei prodotti " -"saranno automaticamente aggiunti alla creazione di un preventivo o ordine." - -#. module: nan_product_pack -#: model:ir.module.module,description:nan_product_pack.module_meta_information -msgid "" -"\n" -"Allows configuring products as a collection of other products. If such a " -"product is added in a sale order, all the products of the pack will be added " -"automatically (when storing the order) as children of the pack product.\n" -"\n" -"The module has been made compatible with nan_external_prices and containts " -"code to specifically handle when the module is available but they're still " -"independent and there are no dependencies between them.\n" -" " -msgstr "" -"\n" -"Permette di configurare prosotti come collezioni di altri prodotti. Se uno " -"di questi prodotti viene aggiunto ad un ordine di vendita, tutti i prodotti " -"nel kit saranno aggiunti automaticamente (al salvataggio dell'ordine) come " -"figli del prodotto kit.\n" -"\n" -"Il modulo è stato reso compatibile con nan_external_prices e contiene il " -"codice per gestire entrambi i moduli pur mantenendoli indipendenti.\n" -" " - -#. module: nan_product_pack -#: view:product.product:0 -#: field:sale.order.line,pack_parent_line_id:0 -msgid "Pack" -msgstr "Kit" - -#. module: nan_product_pack -#: model:ir.model,name:nan_product_pack.model_product_pack_line -msgid "product.pack.line" -msgstr "product.pack.line" - -#. module: nan_product_pack -#: constraint:ir.ui.view:0 -msgid "Invalid XML for View Architecture!" -msgstr "XML non valido per l'architettura della vista" - -#. module: nan_product_pack -#: model:ir.module.module,shortdesc:nan_product_pack.module_meta_information -msgid "Product Pack" -msgstr "Kit prodotto" - -#. module: nan_product_pack -#: field:product.product,stock_depends:0 -msgid "Stock depends of components" -msgstr "La giacenza si basa sui componenti" - -#. module: nan_product_pack -#: help:sale.order.line,pack_parent_line_id:0 -msgid "The pack that contains this product." -msgstr "Il kit che contiene questo prodotto." - -#. module: nan_product_pack -#: field:sale.order.line,pack_depth:0 -msgid "Depth" -msgstr "Profondità" - -#. module: nan_product_pack -#: help:product.product,pack_fixed_price:0 -msgid "" -"Mark this field if the public price of the pack should be fixed. Do not mark " -"it if the price should be calculated from the sum of the prices of the " -"products in the pack." -msgstr "" -"Selezionare questo campo se il prezzo pubblico del kit debba essere fisso. " -"Non selezionarlo se il prezzo debba essere calcolato sulla base dei prezzi " -"dei prodotti nel kit." - -#. module: nan_product_pack -#: field:product.pack.line,quantity:0 -msgid "Quantity" -msgstr "Quantità" - -#. module: nan_product_pack -#: view:product.product:0 -#: field:product.product,pack_line_ids:0 -msgid "Pack Products" -msgstr "Prodotti kit" - -#. module: nan_product_pack -#: field:product.pack.line,parent_product_id:0 -msgid "Parent Product" -msgstr "Prodotto genitore" - -#. module: nan_product_pack -#: field:product.product,pack_fixed_price:0 -msgid "Pack has fixed price" -msgstr "Il kit ha prezzo fisso" - -#. module: nan_product_pack -#: view:product.pack.line:0 -msgid "Pack Product Line" -msgstr "Riga prodotto kit" - -#. module: nan_product_pack -#: help:product.product,pack_line_ids:0 -msgid "List of products that are part of this pack." -msgstr "Lista dei prodotti che sono parte di questo kit." diff --git a/product_pack/i18n/nan_product_pack.pot b/product_pack/i18n/nan_product_pack.pot deleted file mode 100755 index 4945c1ba..00000000 --- a/product_pack/i18n/nan_product_pack.pot +++ /dev/null @@ -1,137 +0,0 @@ -# Translation of OpenERP Server. -# This file contains the translation of the following modules: -# * nan_product_pack -# -msgid "" -msgstr "" -"Project-Id-Version: OpenERP Server 5.0.15\n" -"Report-Msgid-Bugs-To: support@openerp.com\n" -"POT-Creation-Date: 2011-01-15 11:45:01+0000\n" -"PO-Revision-Date: 2011-01-15 11:45:01+0000\n" -"Last-Translator: <>\n" -"Language-Team: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: \n" -"Plural-Forms: \n" - -#. module: nan_product_pack -#: constraint:ir.model:0 -msgid "The Object name must start with x_ and not contain any special character !" -msgstr "The Object name must start with x_ and not contain any special character !" - -#. module: nan_product_pack -#: help:product.product,stock_depends:0 -msgid "Mark if pack stock is calcualted from component stock" -msgstr "Mark if pack stock is calcualted from component stock" - -#. module: nan_product_pack -#: field:sale.order.line,pack_child_line_ids:0 -msgid "Lines in pack" -msgstr "Lines in pack" - -#. module: nan_product_pack -#: help:sale.order.line,pack_depth:0 -msgid "Depth of the product if it is part of a pack." -msgstr "Depth of the product if it is part of a pack." - -#. module: nan_product_pack -#: field:product.pack.line,product_id:0 -msgid "Product" -msgstr "Product" - -#. module: nan_product_pack -#: view:product.pack.line:0 -msgid "Pack Product Lines" -msgstr "Pack Product Lines" - -#. module: nan_product_pack -#: view:product.product:0 -msgid "If you add products in the 'Pack Products' field, all those products will be added automatically when a new quotation or order is created." -msgstr "If you add products in the 'Pack Products' field, all those products will be added automatically when a new quotation or order is created." - -#. module: nan_product_pack -#: model:ir.module.module,description:nan_product_pack.module_meta_information -msgid "\n" -"Allows configuring products as a collection of other products. If such a product is added in a sale order, all the products of the pack will be added automatically (when storing the order) as children of the pack product.\n" -"\n" -"The module has been made compatible with nan_external_prices and containts code to specifically handle when the module is available but they're still independent and there are no dependencies between them.\n" -" " -msgstr "\n" -"Allows configuring products as a collection of other products. If such a product is added in a sale order, all the products of the pack will be added automatically (when storing the order) as children of the pack product.\n" -"\n" -"The module has been made compatible with nan_external_prices and containts code to specifically handle when the module is available but they're still independent and there are no dependencies between them.\n" -" " - -#. module: nan_product_pack -#: view:product.product:0 -#: field:sale.order.line,pack_parent_line_id:0 -msgid "Pack" -msgstr "Pack" - -#. module: nan_product_pack -#: model:ir.model,name:nan_product_pack.model_product_pack_line -msgid "product.pack.line" -msgstr "product.pack.line" - -#. module: nan_product_pack -#: constraint:ir.ui.view:0 -msgid "Invalid XML for View Architecture!" -msgstr "Invalid XML for View Architecture!" - -#. module: nan_product_pack -#: model:ir.module.module,shortdesc:nan_product_pack.module_meta_information -msgid "Product Pack" -msgstr "Product Pack" - -#. module: nan_product_pack -#: field:product.product,stock_depends:0 -msgid "Stock depends of components" -msgstr "Stock depends of components" - -#. module: nan_product_pack -#: help:sale.order.line,pack_parent_line_id:0 -msgid "The pack that contains this product." -msgstr "The pack that contains this product." - -#. module: nan_product_pack -#: field:sale.order.line,pack_depth:0 -msgid "Depth" -msgstr "Depth" - -#. module: nan_product_pack -#: help:product.product,pack_fixed_price:0 -msgid "Mark this field if the public price of the pack should be fixed. Do not mark it if the price should be calculated from the sum of the prices of the products in the pack." -msgstr "Mark this field if the public price of the pack should be fixed. Do not mark it if the price should be calculated from the sum of the prices of the products in the pack." - -#. module: nan_product_pack -#: field:product.pack.line,quantity:0 -msgid "Quantity" -msgstr "Quantity" - -#. module: nan_product_pack -#: view:product.product:0 -#: field:product.product,pack_line_ids:0 -msgid "Pack Products" -msgstr "Pack Products" - -#. module: nan_product_pack -#: field:product.pack.line,parent_product_id:0 -msgid "Parent Product" -msgstr "Parent Product" - -#. module: nan_product_pack -#: field:product.product,pack_fixed_price:0 -msgid "Pack has fixed price" -msgstr "Pack has fixed price" - -#. module: nan_product_pack -#: view:product.pack.line:0 -msgid "Pack Product Line" -msgstr "Pack Product Line" - -#. module: nan_product_pack -#: help:product.product,pack_line_ids:0 -msgid "List of products that are part of this pack." -msgstr "List of products that are part of this pack." - diff --git a/product_pack/i18n/pt.po b/product_pack/i18n/pt.po deleted file mode 100755 index 70935dd0..00000000 --- a/product_pack/i18n/pt.po +++ /dev/null @@ -1,149 +0,0 @@ -# Portuguese translation for openobject-addons -# Copyright (c) 2010 Rosetta Contributors and Canonical Ltd 2010 -# This file is distributed under the same license as the openobject-addons package. -# FIRST AUTHOR , 2010. -# -msgid "" -msgstr "" -"Project-Id-Version: openobject-addons\n" -"Report-Msgid-Bugs-To: FULL NAME \n" -"POT-Creation-Date: 2011-01-15 11:45+0000\n" -"PO-Revision-Date: 2011-02-15 14:19+0000\n" -"Last-Translator: Luniz \n" -"Language-Team: Portuguese \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2013-04-20 05:29+0000\n" -"X-Generator: Launchpad (build 16567)\n" - -#. module: nan_product_pack -#: constraint:ir.model:0 -msgid "" -"The Object name must start with x_ and not contain any special character !" -msgstr "" -"O nome do Objecto deve começar com x_ e não pode conter nenhum caracter " -"especial !" - -#. module: nan_product_pack -#: help:product.product,stock_depends:0 -msgid "Mark if pack stock is calcualted from component stock" -msgstr "" - -#. module: nan_product_pack -#: field:sale.order.line,pack_child_line_ids:0 -msgid "Lines in pack" -msgstr "Linhas em embalagens" - -#. module: nan_product_pack -#: help:sale.order.line,pack_depth:0 -msgid "Depth of the product if it is part of a pack." -msgstr "Profundidade do produto se ele faz parte da embalagem." - -#. module: nan_product_pack -#: field:product.pack.line,product_id:0 -msgid "Product" -msgstr "Produto" - -#. module: nan_product_pack -#: view:product.pack.line:0 -msgid "Pack Product Lines" -msgstr "Linhas de Embalagem de Produto" - -#. module: nan_product_pack -#: view:product.product:0 -msgid "" -"If you add products in the 'Pack Products' field, all those products will be " -"added automatically when a new quotation or order is created." -msgstr "" -"Se adicionar o produto no campo \"Embalagem de Produtos ', todos os produtos " -"serão adicionados automaticamente quando uma nova ordem de cotação é criado." - -#. module: nan_product_pack -#: model:ir.module.module,description:nan_product_pack.module_meta_information -msgid "" -"\n" -"Allows configuring products as a collection of other products. If such a " -"product is added in a sale order, all the products of the pack will be added " -"automatically (when storing the order) as children of the pack product.\n" -"\n" -"The module has been made compatible with nan_external_prices and containts " -"code to specifically handle when the module is available but they're still " -"independent and there are no dependencies between them.\n" -" " -msgstr "" - -#. module: nan_product_pack -#: view:product.product:0 -#: field:sale.order.line,pack_parent_line_id:0 -msgid "Pack" -msgstr "Embalagem" - -#. module: nan_product_pack -#: model:ir.model,name:nan_product_pack.model_product_pack_line -msgid "product.pack.line" -msgstr "product.pack.line" - -#. module: nan_product_pack -#: constraint:ir.ui.view:0 -msgid "Invalid XML for View Architecture!" -msgstr "XML Inválido para a Aquitectura de Vista!" - -#. module: nan_product_pack -#: model:ir.module.module,shortdesc:nan_product_pack.module_meta_information -msgid "Product Pack" -msgstr "Embalagem de Produto" - -#. module: nan_product_pack -#: field:product.product,stock_depends:0 -msgid "Stock depends of components" -msgstr "" - -#. module: nan_product_pack -#: help:sale.order.line,pack_parent_line_id:0 -msgid "The pack that contains this product." -msgstr "A embalagem que contém esse produto." - -#. module: nan_product_pack -#: field:sale.order.line,pack_depth:0 -msgid "Depth" -msgstr "Profundidade" - -#. module: nan_product_pack -#: help:product.product,pack_fixed_price:0 -msgid "" -"Mark this field if the public price of the pack should be fixed. Do not mark " -"it if the price should be calculated from the sum of the prices of the " -"products in the pack." -msgstr "" - -#. module: nan_product_pack -#: field:product.pack.line,quantity:0 -msgid "Quantity" -msgstr "Quantidade" - -#. module: nan_product_pack -#: view:product.product:0 -#: field:product.product,pack_line_ids:0 -msgid "Pack Products" -msgstr "Embalagem de Produtos" - -#. module: nan_product_pack -#: field:product.pack.line,parent_product_id:0 -msgid "Parent Product" -msgstr "Produto Ascendente" - -#. module: nan_product_pack -#: field:product.product,pack_fixed_price:0 -msgid "Pack has fixed price" -msgstr "A Embalagem tem preço fixado" - -#. module: nan_product_pack -#: view:product.pack.line:0 -msgid "Pack Product Line" -msgstr "Linha de Embalagem de Produto" - -#. module: nan_product_pack -#: help:product.product,pack_line_ids:0 -msgid "List of products that are part of this pack." -msgstr "Lista dos produtos que fazem parte desta embalagem." diff --git a/product_pack/pack.py b/product_pack/pack.py index d8ebbefd..8a549746 100755 --- a/product_pack/pack.py +++ b/product_pack/pack.py @@ -1,109 +1,125 @@ -# -*- encoding: latin-1 -*- - - +# -*- encoding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import fields, models, api, _ +from openerp.osv import fields as old_fields +from openerp.exceptions import Warning import math -from openerp.osv import fields,osv -class product_pack( osv.osv ): + +class product_pack(models.Model): _name = 'product.pack.line' _rec_name = 'product_id' - _columns = { - 'parent_product_id': fields.many2one( 'product.product', 'Parent Product', ondelete='cascade', required=True ), - 'quantity': fields.float( 'Quantity', required=True ), - 'product_id': fields.many2one( 'product.product', 'Product', required=True ), - } -product_pack() + parent_product_id = fields.Many2one( + 'product.product', 'Parent Product', + ondelete='cascade', required=True) + quantity = fields.Float( + 'Quantity', required=True) + product_id = fields.Many2one( + 'product.product', 'Product', required=True) + -class product_product( osv.osv ): +class product_product(models.Model): _inherit = 'product.product' - _columns = { - 'stock_depends': fields.boolean( 'Stock depends of components', help='Mark if pack stock is calcualted from component stock' ), - 'pack_fixed_price': fields.boolean( 'Pack has fixed price', help='Mark this field if the public price of the pack should be fixed. Do not mark it if the price should be calculated from the sum of the prices of the products in the pack.' ), - 'pack_line_ids': fields.one2many( 'product.pack.line','parent_product_id', 'Pack Products', help='List of products that are part of this pack.' ), - } - def get_product_available( self, cr, uid, ids, context=None ): - """ Calulate stock for packs, return maximum stock that lets complete pack """ - result={} - # for product in self.browse( cr, uid, ids, context=context ): - result = super( product_product, self ).get_product_available( cr, uid, ids, context=context ) - if not isinstance(ids, list): - ids = [ids] - stock_depends_products = self.search(cr, uid, [('stock_depends', '=',True),('id','in',ids)], context=context) - for product in self.browse( cr, uid, stock_depends_products, context=context ): + pack_line_ids = fields.One2many( + 'product.pack.line', 'parent_product_id', 'Pack Products', + help='List of products that are part of this pack.') + used_pack_line_ids = fields.One2many( + 'product.pack.line', 'product_id', 'Pack Products', + help='List of products that are part of this pack.') + + def _product_available( + self, cr, uid, ids, field_names=None, arg=False, context=None): + pack_product_ids = self.search(cr, uid, [ + ('pack', '=', True), + ('id', 'in', ids), + ]) + res = super(product_product, self)._product_available( + cr, uid, list(set(ids) - set(pack_product_ids)), + field_names, arg, context) + for product in self.browse(cr, uid, pack_product_ids, context=context): + pack_qty_available = [] + pack_virtual_available = [] + for subproduct in product.pack_line_ids: + subproduct_stock = self._product_available( + cr, uid, [subproduct.product_id.id], field_names, arg, + context)[subproduct.product_id.id] + sub_qty = subproduct.quantity + if sub_qty: + pack_qty_available.append(math.floor( + subproduct_stock['qty_available'] / sub_qty)) + pack_virtual_available.append(math.floor( + subproduct_stock['virtual_available'] / sub_qty)) + # TODO calcular correctamente pack virtual available para negativos + res[product.id] = { + 'qty_available': pack_qty_available and min(pack_qty_available) or False, + 'incoming_qty': 0, + 'outgoing_qty': 0, + 'virtual_available': pack_virtual_available and max(min(pack_virtual_available), 0) or False, + } + return res - first_subproduct = True - pack_stock = 0 - # Check if the pack has subproducts - if product.pack_line_ids: - # Take the stock/virtual stock of all subproducts - subproducts_stock = super( product_product, self ).get_product_available(cr, uid, [ line.product_id.id for line in product.pack_line_ids ], context=context ) + def _search_product_quantity(self, cr, uid, obj, name, domain, context): + return super(product_product, self)._search_product_quantity( + cr, uid, obj, name, domain, context) - # Go over all subproducts, take quantity needed for the pack and its available stock - for subproduct in product.pack_line_ids: - if first_subproduct: - subproduct_quantity = subproduct.quantity - subproduct_stock = subproducts_stock[ subproduct.product_id.id ] - # Calculate real stock for current pack from the subproduct stock and needed quantity - pack_stock = math.floor( subproduct_stock / subproduct_quantity ) - first_subproduct = False - continue - # Take the info of the next subproduct - subproduct_quantity_next = subproduct.quantity - subproduct_stock_next = subproducts_stock[ subproduct.product_id.id ] - pack_stock_next = math.floor( subproduct_stock_next / subproduct_quantity_next ) - # compare the stock of a subproduct and the next subproduct - if pack_stock_next < pack_stock: - pack_stock = pack_stock_next - # result is the minimum stock of all subproducts - result[ product.id ] = pack_stock - else: - stock = super( product_product, self ).get_product_available( cr, uid, [ product.id ], context=context ) - result[ product.id ] = stock[ product.id ] - return result + _columns = { + 'qty_available': old_fields.function( + _product_available, multi='qty_available', + fnct_search=_search_product_quantity), + 'virtual_available': old_fields.function( + _product_available, multi='qty_available', + fnct_search=_search_product_quantity), + 'incoming_qty': old_fields.function( + _product_available, multi='qty_available', + fnct_search=_search_product_quantity), + 'outgoing_qty': old_fields.function( + _product_available, multi='qty_available', + fnct_search=_search_product_quantity), + } -# back up de funcion - # def get_product_available( self, cr, uid, ids, context=None ): - # """ Calulate stock for packs, return maximum stock that lets complete pack """ - # result={} - # for product in self.browse( cr, uid, ids, context=context ): - # stock = super( product_product, self ).get_product_available( cr, uid, [ product.id ], context=context ) - # print product.id - # # Check if product stock depends on it's subproducts stock. - # if not product.stock_depends: - # result[ product.id ] = stock[ product.id ] - # continue + @api.one + @api.constrains('company_id', 'pack_line_ids', 'used_pack_line_ids') + def check_pack_line_company(self): + # TODO implementar mejores mensajes + for line in self.pack_line_ids: + if line.product_id.company_id != self.company_id: + raise Warning(_( + 'Pack lines products company must be the same as the\ + parent product company')) + for line in self.used_pack_line_ids: + if line.parent_product_id.company_id != self.company_id: + raise Warning(_( + 'Pack lines products company must be the same as the\ + parent product company')) - # first_subproduct = True - # pack_stock = 0 - # # Check if the pack has subproducts - # if product.pack_line_ids: - # # Take the stock/virtual stock of all subproducts - # subproducts_stock = self.get_product_available( cr, uid, [ line.product_id.id for line in product.pack_line_ids ], context=context ) - # # Go over all subproducts, take quantity needed for the pack and its available stock - # for subproduct in product.pack_line_ids: - # if first_subproduct: - # subproduct_quantity = subproduct.quantity - # subproduct_stock = subproducts_stock[ subproduct.product_id.id ] - # # Calculate real stock for current pack from the subproduct stock and needed quantity - # pack_stock = math.floor( subproduct_stock / subproduct_quantity ) - # first_subproduct = False - # continue - # # Take the info of the next subproduct - # subproduct_quantity_next = subproduct.quantity - # subproduct_stock_next = subproducts_stock[ subproduct.product_id.id ] - # pack_stock_next = math.floor( subproduct_stock_next / subproduct_quantity_next ) - # # compare the stock of a subproduct and the next subproduct - # if pack_stock_next < pack_stock: - # pack_stock = pack_stock_next - # # result is the minimum stock of all subproducts - # result[ product.id ] = pack_stock - # else: - # result[ product.id ] = stock[ product.id ] - # return result +class product_template(models.Model): + _inherit = 'product.template' -product_product() + pack_price_type = fields.Selection([ + ('components_price', 'Components Prices'), + # TODO modify price_get and add this functionality + # ('totalice_price', 'Totalice Price'), + ('fixed_price', 'Fixed Price'), + ], + 'Pack Price Type', + help=""" + * Totalice Price: Sum individual prices on the product pack price. + * Fixed Price: Price of this product instead of components prrices. + * Components Price: Components prices plast pack price. + """ + ) + sale_order_pack = fields.Boolean( + 'Sale Order Pack', + help='Sale order are packs used on sale orders to calculate a price of a line', + ) + pack = fields.Boolean( + 'Pack?', + help='TODO', + ) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/product_pack/pack_view.xml b/product_pack/pack_view.xml index 36c553b7..6d187e75 100755 --- a/product_pack/pack_view.xml +++ b/product_pack/pack_view.xml @@ -6,18 +6,16 @@ product.product.pack.form product.product - form + + + + + - - @@ -30,19 +28,22 @@ form
- - + + + +
+ product.pack.line.tree product.pack.line tree - - + + diff --git a/product_pack/sale.py b/product_pack/sale.py index a22051fd..05a78f3b 100755 --- a/product_pack/sale.py +++ b/product_pack/sale.py @@ -1,112 +1,214 @@ -# -*- encoding: latin-1 -*- - +# -*- encoding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import fields, models, api +import openerp.addons.decimal_precision as dp + + +class sale_order_line_pack_line(models.Model): + _name = 'sale.order.line.pack.line' + _description = 'sale.order.line.pack.line' + + order_line_id = fields.Many2one( + 'sale.order.line', 'Order Line', ondelete='cascade', required=True) + product_id = fields.Many2one( + 'product.product', 'Product', required=True) + price_unit = fields.Float( + 'Unit Price', + required=True, + digits_compute=dp.get_precision('Product Price')) + price_subtotal = fields.Float( + compute="_amount_line", + string='Subtotal', + digits_compute=dp.get_precision('Account')) + product_uom_qty = fields.Float( + 'Quantity', digits_compute=dp.get_precision('Product UoS'), + required=True) + + @api.one + @api.onchange('product_id') + def onchange_product_id(self): + self.price_unit = self.product_id.lst_price + + @api.one + @api.depends('price_unit', 'product_uom_qty') + def _amount_line(self): + self.price_subtotal = self.product_uom_qty * self.price_unit + + +class sale_order_line(models.Model): + _inherit = 'sale.order.line' -import math -from openerp.osv import fields,osv + # Fields for sale order pack + pack_total = fields.Float( + string='Pack total', compute='_get_pack_total') + pack_line_ids = fields.One2many( + 'sale.order.line.pack.line', 'order_line_id', 'Pack Lines') + sale_order_pack = fields.Boolean(related='product_id.sale_order_pack') + + # Fields for common packs + pack_depth = fields.Integer( + 'Depth', + help='Depth of the product if it is part of a pack.' + ) + pack_parent_line_id = fields.Many2one( + 'sale.order.line', 'Pack', + help='The pack that contains this product.', ondelete="cascade" + ) + pack_child_line_ids = fields.One2many( + 'sale.order.line', 'pack_parent_line_id', 'Lines in pack' + ) + + def button_dummy(self, cr, uid, ids, context=None): + return True + + @api.one + @api.depends( + 'pack_line_ids', + 'pack_line_ids.price_subtotal', + ) + def _get_pack_total(self): + pack_total = 0.0 + if self.pack_line_ids: + pack_total = sum(x.price_subtotal for x in self.pack_line_ids) + self.pack_total = pack_total + + @api.one + @api.onchange('pack_total') + def _onchange_pack_line_ids(self): + self.price_unit = self.pack_total + + # onchange para agregar los product en el tipo el pack "sale order pack" + def product_id_change( + self, cr, uid, ids, pricelist, product, qty=0, + uom=False, qty_uos=0, uos=False, name='', partner_id=False, + lang=False, update_tax=True, date_order=False, packaging=False, + fiscal_position=False, flag=False, context=None): + # warning = {} + if not product: + return {'value': { + 'th_weight': 0, + 'product_packaging': False, + 'product_uos_qty': qty}, + 'domain': {'product_uom': [], 'product_uos': []} + } + product_obj = self.pool.get('product.product') + product_info = product_obj.browse(cr, uid, product) + + result = super(sale_order_line, self).product_id_change( + cr, uid, ids, pricelist, product, qty, + uom, qty_uos, uos, name, partner_id, + lang, update_tax, date_order, packaging, + fiscal_position, flag, context) + + pack_line_ids = [(5, False, False)] + if product_info.pack_line_ids and product_info.sale_order_pack: + for pack_line in product_info.pack_line_ids: + price_unit = pack_line.product_id.lst_price + quantity = pack_line.quantity + pack_line_ids.append((0, False, { + 'product_id': pack_line.product_id.id, + 'product_uom_qty': quantity, + 'price_unit': price_unit, + 'price_subtotal': price_unit * quantity, + })) + result['value']['pack_line_ids'] = pack_line_ids + return result -class sale_order_line(osv.osv): - _inherit = 'sale.order.line' - _columns = { - 'pack_depth': fields.integer('Depth', required=True, help='Depth of the product if it is part of a pack.'), - 'pack_parent_line_id': fields.many2one('sale.order.line', 'Pack', help='The pack that contains this product.'), - 'pack_child_line_ids': fields.one2many('sale.order.line', 'pack_parent_line_id', 'Lines in pack', help=''), - } - _defaults = { - 'pack_depth': lambda *a: 0, - } -sale_order_line() - -class sale_order(osv.osv): +class sale_order(models.Model): _inherit = 'sale.order' + # Copia del modulo de pxgeo def create(self, cr, uid, vals, context=None): - result = super(sale_order,self).create(cr, uid, vals, context) + result = super(sale_order, self).create(cr, uid, vals, context) self.expand_packs(cr, uid, [result], context) return result def write(self, cr, uid, ids, vals, context=None): - result = super(sale_order,self).write(cr, uid, ids, vals, context) - self.expand_packs(cr, uid, ids, context) + result = super(sale_order, self).write(cr, uid, ids, vals, context) + if 'order_line' in vals: + self.expand_packs(cr, uid, ids, context) return result - def expand_packs(self, cr, uid, ids, context={}, depth=1): - - - def get_real_price(res_dict, product_id, qty, uom, pricelist): - item_obj = self.pool.get('product.pricelist.item') - price_type_obj = self.pool.get('product.price.type') - product_obj = self.pool.get('product.product') - template_obj = self.pool.get('product.template') - field_name = 'list_price' - - if res_dict.get('item_id',False) and res_dict['item_id'].get(pricelist,False): - item = res_dict['item_id'].get(pricelist,False) - item_base = item_obj.read(cr, uid, [item], ['base'])[0]['base'] - if item_base > 0: - field_name = price_type_obj.browse(cr, uid, item_base).field - - product = product_obj.browse(cr, uid, product_id, context) - product_tmpl_id = product.product_tmpl_id.id - - product_read = template_obj.read(cr, uid, product_tmpl_id, [field_name], context) - - factor = 1.0 - if uom and uom != product.uom_id.id: - product_uom_obj = self.pool.get('product.uom') - uom_data = product_uom_obj.browse(cr, uid, product.uom_id.id) - factor = uom_data.factor - return product_read[field_name] * factor + def copy(self, cr, uid, id, default={}, context=None): + line_obj = self.pool.get('sale.order.line') + result = super(sale_order, self).copy(cr, uid, id, default, context) + sale = self.browse(cr, uid, result, context) + for line in sale.order_line: + if line.pack_parent_line_id: + line_obj.unlink(cr, uid, [line.id], context) + self.expand_packs(cr, uid, sale.id, context) + return result + def expand_packs(self, cr, uid, ids, context={}, depth=1): + if type(ids) in [int, long]: + ids = [ids] if depth == 10: return updated_orders = [] - for order in self.browse(cr, uid, ids, context): - - fiscal_position = order.fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, order.fiscal_position, context) or False - - # The reorder variable is used to ensure lines of the same pack go right after their - # parent. - # What the algorithm does is check if the previous item had children. As children items - # must go right after the parent if the line we're evaluating doesn't have a parent it - # means it's a new item (and probably has the default 10 sequence number - unless the - # appropiate c2c_sale_sequence module is installed). In this case we mark the item for - # reordering and evaluate the next one. Note that as the item is not evaluated and it might - # have to be expanded it's put on the queue for another iteration (it's simple and works well). - # Once the next item has been evaluated the sequence of the item marked for reordering is updated - # with the next value. + fiscal_position = ( + order.fiscal_position + and self.pool.get('account.fiscal.position').browse( + cr, uid, order.fiscal_position.id, context + ) + or False + ) + """ + The reorder variable is used to ensure lines of the same pack go + right after their parent. What the algorithm does is check if the + previous item had children. As children items must go right after + the parent if the line we're evaluating doesn't have a parent it + means it's a new item (and probably has the default 10 sequence + number - unless the appropiate c2c_sale_sequence module is + installed). In this case we mark the item for reordering and + evaluate the next one. Note that as the item is not evaluated and + it might have to be expanded it's put on the queue for another + iteration (it's simple and works well). Once the next item has been + evaluated the sequence of the item marked for reordering is updated + with the next value. + """ sequence = -1 reorder = [] last_had_children = False + lines_to_unlink = [] for line in order.order_line: if last_had_children and not line.pack_parent_line_id: - reorder.append( line.id ) - if line.product_id.pack_line_ids and not order.id in updated_orders: - updated_orders.append( order.id ) + reorder.append(line.id) + if ( + line.product_id.pack_line_ids + and order.id not in updated_orders + ): + updated_orders.append(order.id) continue sequence += 1 if sequence > line.sequence: - self.pool.get('sale.order.line').write(cr, uid, [line.id], { - 'sequence': sequence, - }, context) + self.pool.get('sale.order.line').write( + cr, uid, [line.id], {'sequence': sequence, }, context) else: sequence = line.sequence if line.state != 'draft': continue - if not line.product_id: + if not line.product_id or not line.product_id.pack or line.product_id.sale_order_pack: continue - # If pack was already expanded (in another create/write operation or in - # a previous iteration) don't do it again. + """ If pack was already expanded (in another create/write + operation or in a previous iteration) don't do it again. """ if line.pack_child_line_ids: - last_had_children = True - continue + # Cambiamos esto para que se borren las lienas viejas y se + # creen nuevas + unlink_line_ids = [x.id for x in line.pack_child_line_ids] + lines_to_unlink.extend(unlink_line_ids) + # last_had_children = True + # continue last_had_children = False + pack_price = 0.0 for subline in line.product_id.pack_line_ids: sequence += 1 @@ -114,33 +216,9 @@ def get_real_price(res_dict, product_id, qty, uom, pricelist): subproduct = subline.product_id quantity = subline.quantity * line.product_uom_qty - if line.product_id.pack_fixed_price: - price = 0.0 - discount = 0.0 - else: - pricelist = order.pricelist_id.id - list_price = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist], - subproduct.id, quantity, order.partner_id.id, { - 'uom': subproduct.uom_id.id, - 'date': order.date_order, - }) - price = list_price[pricelist] - - # Added functionality for compatibility with product_visible_discount module - pricelist_obj=self.pool.get('product.pricelist') - pricelists = pricelist_obj.read(cr,uid,[pricelist],['visible_discount']) - new_list_price = get_real_price(list_price, subproduct.id, quantity, subproduct.uom_id.id, pricelist) - discount = line.discount - if pricelists[0].has_key("visible_discount"): - if(len(pricelists)>0 and pricelists[0]['visible_discount'] and list_price[pricelist] != 0): - discount += (new_list_price - price) / new_list_price * 100 - price = new_list_price - - # Obtain product name in partner's language - ctx = {'lang': order.partner_id.lang} - subproduct_name = self.pool.get('product.product').browse(cr, uid, subproduct.id, ctx).name - - tax_ids = self.pool.get('account.fiscal.position').map_tax(cr, uid, fiscal_position, subproduct.taxes_id) + tax_ids = self.pool.get('account.fiscal.position').map_tax( + cr, uid, fiscal_position, subproduct.taxes_id) + tax_id = [(6, 0, tax_ids)] if subproduct.uos_id: uos_id = subproduct.uos_id.id @@ -149,54 +227,71 @@ def get_real_price(res_dict, product_id, qty, uom, pricelist): uos_id = False uos_qty = quantity + if line.product_id.pack_price_type == 'fixed_price': + price = 0.0 + discount = 0.0 + elif line.product_id.pack_price_type == 'totalice_price': + pack_price += (price * uos_qty) + price = 0.0 + discount = 0.0 + tax_id = False + else: + pricelist = order.pricelist_id.id + price = self.pool.get('product.pricelist').price_get( + cr, uid, [pricelist], subproduct.id, quantity, + order.partner_id.id, { + 'uom': subproduct.uom_id.id, + 'date': order.date_order, + } + )[pricelist] + discount = line.discount + + # Obtain product name in partner's language + ctx = {'lang': order.partner_id.lang} + subproduct_name = self.pool.get('product.product').browse( + cr, uid, subproduct.id, ctx).name + vals = { 'order_id': order.id, - 'name': '%s%s' % ('> '* (line.pack_depth+1), subproduct_name), + 'name': '%s%s' % ( + '> ' * (line.pack_depth+1), subproduct_name + ), 'sequence': sequence, - 'delay': subproduct.sale_delay or 0.0, + # 'delay': subproduct.sale_delay or 0.0, 'product_id': subproduct.id, - 'procurement_id': line.procurement_id and line.procurement_id.id or False, + # 'procurement_ids': ( + # [(4, x.id) for x in line.procurement_ids] + # ), 'price_unit': price, - 'tax_id': [(6,0,tax_ids)], - 'type': subproduct.procure_method, - 'property_ids': [(6,0,[])], + 'tax_id': tax_id, 'address_allotment_id': False, 'product_uom_qty': quantity, 'product_uom': subproduct.uom_id.id, 'product_uos_qty': uos_qty, 'product_uos': uos_id, 'product_packaging': False, - 'move_ids': [(6,0,[])], 'discount': discount, 'number_packages': False, - 'notes': False, 'th_weight': False, 'state': 'draft', 'pack_parent_line_id': line.id, 'pack_depth': line.pack_depth + 1, } - # It's a control for the case that the nan_external_prices was installed with the product pack - if 'prices_used' in line: - vals[ 'prices_used' ] = line.prices_used - - self.pool.get('sale.order.line').create(cr, uid, vals, context) - if not order.id in updated_orders: - updated_orders.append( order.id ) + self.pool.get('sale.order.line').create( + cr, uid, vals, context) + if order.id not in updated_orders: + updated_orders.append(order.id) for id in reorder: sequence += 1 - self.pool.get('sale.order.line').write(cr, uid, [id], { - 'sequence': sequence, - }, context) + self.pool.get('sale.order.line').write( + cr, uid, [id], {'sequence': sequence, }, context) - if updated_orders: - # Try to expand again all those orders that had a pack in this iteration. - # This way we support packs inside other packs. - self.expand_packs(cr, uid, ids, context, depth+1) - return - -sale_order() + # Borramos las lienas que se actualizan + self.pool.get('sale.order.line').unlink( + cr, uid, lines_to_unlink, context=context) + return # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/product_pack/sale_view.xml b/product_pack/sale_view.xml new file mode 100644 index 00000000..e2562c6b --- /dev/null +++ b/product_pack/sale_view.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + sale.line.pack.line.tree + sale.order.line.pack.line + + + + + + + + + + + + sale.order.form.inherit + sale.order + + + + +
+
+
+ + + + +
+
+
+
+ +
+
diff --git a/product_pack/security/ir.model.access.csv b/product_pack/security/ir.model.access.csv index 140b1b8d..3e37e925 100755 --- a/product_pack/security/ir.model.access.csv +++ b/product_pack/security/ir.model.access.csv @@ -1,3 +1,5 @@ -"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink" -"access_product_pack_line_manager","product.pack.line manager","model_product_pack_line","base.group_sale_manager",1,1,1,1 -"access_product_pack_line_mployee","product.pack.line employee","model_product_pack_line","base.group_user",1,0,0,0 +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_product_pack_line_manager,product.pack.line manager,model_product_pack_line,base.group_sale_manager,1,1,1,1 +access_product_pack_line_all,product.pack.line,model_product_pack_line,,1,0,0,0 +access_sale_order_line_pack_line_user,sale_order_line_pack_line_user,model_sale_order_line_pack_line,base.group_user,1,1,1,1 +access_sale_order_line_pack_line_all,sale_order_line_pack_line_all,model_sale_order_line_pack_line,,1,0,0,0 diff --git a/product_pack/security/product_security.xml b/product_pack/security/product_security.xml new file mode 100644 index 00000000..72c137b8 --- /dev/null +++ b/product_pack/security/product_security.xml @@ -0,0 +1,11 @@ + + + + + + Manage Packs On Sales Orders + + + + + diff --git a/product_pack/stock.py b/product_pack/stock.py deleted file mode 100755 index 374e4c47..00000000 --- a/product_pack/stock.py +++ /dev/null @@ -1,140 +0,0 @@ -# -*- encoding: latin-1 -*- - - -import math -from openerp.osv import fields,osv - -class stock_move(osv.osv): - _inherit = 'stock.move' - - _columns = { - 'pack_depth': fields.integer('Depth', required=True, help='Depth of the product if it is part of a pack.'), - 'pack_parent_line_id': fields.many2one('stock.move', 'Pack', help='The pack that contains this product.'), - 'pack_child_line_ids': fields.one2many('stock.move', 'pack_parent_line_id', 'Lines in pack', help=''), - } - _defaults = { - 'pack_depth': lambda *a: 0, - } - -stock_move() - -class stock_picking(osv.osv): - _inherit = 'stock.picking' - - - def create(self, cr, uid, vals, context=None): - result = super(stock_picking,self).create(cr, uid, vals, context) - self.expand_packs(cr, uid, [result], context) - return result - - def write(self, cr, uid, ids, vals, context=None): - result = super(stock_picking,self).write(cr, uid, ids, vals, context) - self.expand_packs(cr, uid, ids, context) - return result - - def expand_packs(self, cr, uid, ids, context={}, depth=1): - if depth == 10: - return - updated_orders = [] - for order in self.browse(cr, uid, ids, context): - - - # The reorder variable is used to ensure lines of the same pack go right after their - # parent. - # What the algorithm does is check if the previous item had children. As children items - # must go right after the parent if the line we're evaluating doesn't have a parent it - # means it's a new item (and probably has the default 10 sequence number - unless the - # appropiate c2c_sale_sequence module is installed). In this case we mark the item for - # reordering and evaluate the next one. Note that as the item is not evaluated and it might - # have to be expanded it's put on the queue for another iteration (it's simple and works well). - # Once the next item has been evaluated the sequence of the item marked for reordering is updated - # with the next value. - # sequence = -1 - reorder = [] - last_had_children = False - for line in order.move_lines: - if last_had_children and not line.pack_parent_line_id: - reorder.append( line.id ) - if line.product_id.pack_line_ids and not order.id in updated_orders: - updated_orders.append( order.id ) - continue - - if line.sale_line_id or line.sale_line_id: - continue - if line.state != 'draft': - continue - if not line.product_id: - continue - # If pack was already expanded (in another create/write operation or in - # a previous iteration) don't do it again. - if line.pack_child_line_ids: - last_had_children = True - continue - last_had_children = False - - for subline in line.product_id.pack_line_ids: - - subproduct = subline.product_id - # quantity = subline.quantity * line.product_uom_qty - quantity = subline.quantity * line.product_qty - - # if line.product_id.pack_fixed_price: - # # price = 0.0 - # # discount = 0.0 - # else: - # # pricelist = order.pricelist_id.id - # price = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist], - # subproduct.id, quantity, order.partner_id.id, { - # 'uom': subproduct.uom_id.id, - # 'date': order.date_order, - # })[pricelist] - # discount = line.discount - - # Obtain product name in partner's language - ctx = {'lang': order.partner_id.lang} - subproduct_name = self.pool.get('product.product').browse(cr, uid, subproduct.id, ctx).name - - # tax_ids = self.pool.get('account.fiscal.position').map_tax(cr, uid, fiscal_position, subproduct.taxes_id) - - if subproduct.uos_id: - uos_id = subproduct.uos_id.id - uos_qty = quantity * subproduct.uos_coeff - else: - uos_id = False - uos_qty = quantity - - vals = { - 'name': line.picking_id.origin or '' + ':' + subproduct.name, - 'product_id': subproduct.id, - 'product_qty': quantity, - 'product_uos_qty': quantity, - 'product_uom': subproduct.uom_id.id, - 'location_id': line.location_id.id, - 'location_dest_id': line.location_dest_id.id, - 'picking_id': line.picking_id.id, - 'address_id': line.address_id.id, - 'date_expected': line.date_expected, - 'origin': line.origin, - 'purchase_line_id': line.purchase_line_id.id, - 'sale_line_id': line.sale_line_id.id, - 'product_packaging': line.product_packaging, - 'pack_parent_line_id': line.id, - 'pack_depth': line.pack_depth + 1, - } - - self.pool.get('stock.move').create(cr, uid, vals, context) - if not order.id in updated_orders: - updated_orders.append( order.id ) - - for id in reorder: - self.pool.get('stock.move').write(cr, uid, [id], {}, context) - - if updated_orders: - # Try to expand again all those orders that had a pack in this iteration. - # This way we support packs inside other packs. - self.expand_packs(cr, uid, ids, context, depth+1) - return - -stock_picking() - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From 67b98de915475a8c04bbc7956e35b65d4aa46a99 Mon Sep 17 00:00:00 2001 From: Nicolas Mac Rouillon Date: Wed, 27 May 2015 10:45:35 -0300 Subject: [PATCH 04/75] IMP --- product_pack/pack.py | 69 +++++++++++++++++++++ product_pack/sale.py | 144 ++++++++++++++++++++++--------------------- 2 files changed, 142 insertions(+), 71 deletions(-) diff --git a/product_pack/pack.py b/product_pack/pack.py index 8a549746..060ce771 100755 --- a/product_pack/pack.py +++ b/product_pack/pack.py @@ -20,6 +20,75 @@ class product_pack(models.Model): product_id = fields.Many2one( 'product.product', 'Product', required=True) + @api.multi + def get_sale_order_line_vals(self, line, order, sequence, fiscal_position): + self.ensure_one() + sequence += 1 + # pack_price = 0.0 + subproduct = self.product_id + quantity = self.quantity * line.product_uom_qty + + tax_ids = self.env['account.fiscal.position'].map_tax( + subproduct.taxes_id) + tax_id = [(6, 0, tax_ids)] + + if subproduct.uos_id: + uos_id = subproduct.uos_id.id + uos_qty = quantity * subproduct.uos_coeff + else: + uos_id = False + uos_qty = quantity + + if line.product_id.pack_price_type == 'fixed_price': + price = 0.0 + discount = 0.0 + # TODO this should go in price get of pricelist + # elif line.product_id.pack_price_type == 'totalice_price': + # pack_price += (price * uos_qty) + # price = 0.0 + # discount = 0.0 + # tax_id = False + else: + pricelist = order.pricelist_id.id + price = self.env['product.pricelist'].price_get( + subproduct.id, quantity, + order.partner_id.id, context={ + 'uom': subproduct.uom_id.id, + 'date': order.date_order})[pricelist] + discount = line.discount + + # Obtain product name in partner's language + # ctx = {'lang': order.partner_id.lang} + subproduct_name = subproduct.name + + vals = { + 'order_id': order.id, + 'name': '%s%s' % ( + '> ' * (line.pack_depth + 1), subproduct_name + ), + 'sequence': sequence, + # 'delay': subproduct.sale_delay or 0.0, + 'product_id': subproduct.id, + # 'procurement_ids': ( + # [(4, x.id) for x in line.procurement_ids] + # ), + 'price_unit': price, + 'tax_id': tax_id, + 'address_allotment_id': False, + 'product_uom_qty': quantity, + 'product_uom': subproduct.uom_id.id, + 'product_uos_qty': uos_qty, + 'product_uos': uos_id, + 'product_packaging': False, + 'discount': discount, + 'number_packages': False, + 'th_weight': False, + 'state': 'draft', + 'pack_parent_line_id': line.id, + 'pack_depth': line.pack_depth + 1, + } + return vals + class product_product(models.Model): _inherit = 'product.product' diff --git a/product_pack/sale.py b/product_pack/sale.py index 05a78f3b..1d51d83d 100755 --- a/product_pack/sale.py +++ b/product_pack/sale.py @@ -51,14 +51,14 @@ class sale_order_line(models.Model): pack_depth = fields.Integer( 'Depth', help='Depth of the product if it is part of a pack.' - ) + ) pack_parent_line_id = fields.Many2one( 'sale.order.line', 'Pack', help='The pack that contains this product.', ondelete="cascade" - ) + ) pack_child_line_ids = fields.One2many( 'sale.order.line', 'pack_parent_line_id', 'Lines in pack' - ) + ) def button_dummy(self, cr, uid, ids, context=None): return True @@ -67,7 +67,7 @@ def button_dummy(self, cr, uid, ids, context=None): @api.depends( 'pack_line_ids', 'pack_line_ids.price_subtotal', - ) + ) def _get_pack_total(self): pack_total = 0.0 if self.pack_line_ids: @@ -92,7 +92,7 @@ def product_id_change( 'product_packaging': False, 'product_uos_qty': qty}, 'domain': {'product_uom': [], 'product_uos': []} - } + } product_obj = self.pool.get('product.product') product_info = product_obj.browse(cr, uid, product) @@ -112,7 +112,7 @@ def product_id_change( 'product_uom_qty': quantity, 'price_unit': price_unit, 'price_subtotal': price_unit * quantity, - })) + })) result['value']['pack_line_ids'] = pack_line_ids return result @@ -208,75 +208,77 @@ def expand_packs(self, cr, uid, ids, context={}, depth=1): # last_had_children = True # continue last_had_children = False - pack_price = 0.0 + # pack_price = 0.0 for subline in line.product_id.pack_line_ids: - sequence += 1 - - subproduct = subline.product_id - quantity = subline.quantity * line.product_uom_qty - - tax_ids = self.pool.get('account.fiscal.position').map_tax( - cr, uid, fiscal_position, subproduct.taxes_id) - tax_id = [(6, 0, tax_ids)] - - if subproduct.uos_id: - uos_id = subproduct.uos_id.id - uos_qty = quantity * subproduct.uos_coeff - else: - uos_id = False - uos_qty = quantity - - if line.product_id.pack_price_type == 'fixed_price': - price = 0.0 - discount = 0.0 - elif line.product_id.pack_price_type == 'totalice_price': - pack_price += (price * uos_qty) - price = 0.0 - discount = 0.0 - tax_id = False - else: - pricelist = order.pricelist_id.id - price = self.pool.get('product.pricelist').price_get( - cr, uid, [pricelist], subproduct.id, quantity, - order.partner_id.id, { - 'uom': subproduct.uom_id.id, - 'date': order.date_order, - } - )[pricelist] - discount = line.discount + vals = subline.get_sale_order_line_vals( + line, order, sequence, fiscal_position) + # sequence += 1 + + # subproduct = subline.product_id + # quantity = subline.quantity * line.product_uom_qty + + # tax_ids = self.pool.get('account.fiscal.position').map_tax( + # cr, uid, fiscal_position, subproduct.taxes_id) + # tax_id = [(6, 0, tax_ids)] + + # if subproduct.uos_id: + # uos_id = subproduct.uos_id.id + # uos_qty = quantity * subproduct.uos_coeff + # else: + # uos_id = False + # uos_qty = quantity + + # if line.product_id.pack_price_type == 'fixed_price': + # price = 0.0 + # discount = 0.0 + # elif line.product_id.pack_price_type == 'totalice_price': + # pack_price += (price * uos_qty) + # price = 0.0 + # discount = 0.0 + # tax_id = False + # else: + # pricelist = order.pricelist_id.id + # price = self.pool.get('product.pricelist').price_get( + # cr, uid, [pricelist], subproduct.id, quantity, + # order.partner_id.id, { + # 'uom': subproduct.uom_id.id, + # 'date': order.date_order, + # } + # )[pricelist] + # discount = line.discount # Obtain product name in partner's language - ctx = {'lang': order.partner_id.lang} - subproduct_name = self.pool.get('product.product').browse( - cr, uid, subproduct.id, ctx).name - - vals = { - 'order_id': order.id, - 'name': '%s%s' % ( - '> ' * (line.pack_depth+1), subproduct_name - ), - 'sequence': sequence, - # 'delay': subproduct.sale_delay or 0.0, - 'product_id': subproduct.id, - # 'procurement_ids': ( - # [(4, x.id) for x in line.procurement_ids] - # ), - 'price_unit': price, - 'tax_id': tax_id, - 'address_allotment_id': False, - 'product_uom_qty': quantity, - 'product_uom': subproduct.uom_id.id, - 'product_uos_qty': uos_qty, - 'product_uos': uos_id, - 'product_packaging': False, - 'discount': discount, - 'number_packages': False, - 'th_weight': False, - 'state': 'draft', - 'pack_parent_line_id': line.id, - 'pack_depth': line.pack_depth + 1, - } + # ctx = {'lang': order.partner_id.lang} + # subproduct_name = self.pool.get('product.product').browse( + # cr, uid, subproduct.id, ctx).name + + # vals = { + # 'order_id': order.id, + # 'name': '%s%s' % ( + # '> ' * (line.pack_depth+1), subproduct_name + # ), + # 'sequence': sequence, + # 'delay': subproduct.sale_delay or 0.0, + # 'product_id': subproduct.id, + # 'procurement_ids': ( + # [(4, x.id) for x in line.procurement_ids] + # ), + # 'price_unit': price, + # 'tax_id': tax_id, + # 'address_allotment_id': False, + # 'product_uom_qty': quantity, + # 'product_uom': subproduct.uom_id.id, + # 'product_uos_qty': uos_qty, + # 'product_uos': uos_id, + # 'product_packaging': False, + # 'discount': discount, + # 'number_packages': False, + # 'th_weight': False, + # 'state': 'draft', + # 'pack_parent_line_id': line.id, + # 'pack_depth': line.pack_depth + 1, + # } self.pool.get('sale.order.line').create( cr, uid, vals, context) From adeaa8bfb49b27955e6019eaca5c45095556206f Mon Sep 17 00:00:00 2001 From: Juan Jose Scarafia Date: Thu, 23 Jul 2015 13:33:21 -0300 Subject: [PATCH 05/75] [IMP/FIX] product_pack IMP product_pack format FIX fix_digits_compute_to_digits IMP IMPORTANT imprrovements on product pack, get pack with sale order constraint IMP use constraint on sale line and not sale order for product packs IMP implement totalice price on product pack IMP update pack manifest FIX prod pack copy sale order FIX contraint IMP compt with other modules FIX prod pack @api.multi --- product_pack/README.rst | 74 +++++ product_pack/__init__.py | 3 +- product_pack/__openerp__.py | 20 +- product_pack/demo/demo_data.xml | 302 ++++++++++++++++++ product_pack/models/__init__.py | 10 + product_pack/models/pack.py | 91 ++++++ product_pack/models/product.py | 215 +++++++++++++ product_pack/models/sale_order.py | 18 ++ product_pack/models/sale_order_line.py | 122 +++++++ .../models/sale_order_line_pack_line.py | 54 ++++ product_pack/pack.py | 194 ----------- product_pack/sale.py | 299 ----------------- product_pack/sale_order.py | 0 product_pack/sale_view.xml | 51 --- product_pack/security/product_security.xml | 11 - product_pack/{ => views}/pack_view.xml | 24 +- product_pack/views/sale_view.xml | 67 ++++ 17 files changed, 981 insertions(+), 574 deletions(-) create mode 100644 product_pack/README.rst create mode 100644 product_pack/demo/demo_data.xml create mode 100755 product_pack/models/__init__.py create mode 100755 product_pack/models/pack.py create mode 100644 product_pack/models/product.py create mode 100644 product_pack/models/sale_order.py create mode 100644 product_pack/models/sale_order_line.py create mode 100755 product_pack/models/sale_order_line_pack_line.py delete mode 100755 product_pack/pack.py delete mode 100755 product_pack/sale.py create mode 100644 product_pack/sale_order.py delete mode 100644 product_pack/sale_view.xml delete mode 100644 product_pack/security/product_security.xml rename product_pack/{ => views}/pack_view.xml (52%) create mode 100644 product_pack/views/sale_view.xml diff --git a/product_pack/README.rst b/product_pack/README.rst new file mode 100644 index 00000000..ce89495c --- /dev/null +++ b/product_pack/README.rst @@ -0,0 +1,74 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +============ +Product Pack +============ + +This module add "Product Pack" funcionality to sale orders. For prouct you can add some other product to sell with them, in the sale order you choose the product and then automaticaly added the products that set in Product selected. + +Installation +============ + +To install this module, you need to: + +#. Just install this module. + + +Configuration +============= + +To configure this module, you need to: + +#. Go to product and set "Product Pack", then set the products has to include in the product pack of the product. +#. Set type of product pack. + + + +Usage +===== + +To use this module, you need to: + +#. Create an sale order and set product that has product pack choosed. + + +.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas + :alt: Try me on Runbot + :target: https://runbot.adhoc.com.ar/ + +.. repo_id is available in https://github.com/OCA/maintainer-tools/blob/master/tools/repos_with_ids.txt +.. branch is "9.0" for example + + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smashing it by providing a detailed and welcomed feedback. + +Credits +======= + +Images +------ + +* ADHOC SA: `Icon `_. + +Contributors +------------ + + +Maintainer +---------- + +.. image:: http://fotos.subefotos.com/83fed853c1e15a8023b86b2b22d6145bo.png + :alt: Odoo Community Association + :target: https://www.adhoc.com.ar + +This module is maintained by the ADHOC SA. + +To contribute to this module, please visit https://www.adhoc.com.ar. diff --git a/product_pack/__init__.py b/product_pack/__init__.py index ec3f42b5..49d04ade 100755 --- a/product_pack/__init__.py +++ b/product_pack/__init__.py @@ -2,5 +2,4 @@ ############################################################################## # For copyright and license notices, see __openerp__.py file in root directory ############################################################################## -import pack -import sale +from . import models diff --git a/product_pack/__openerp__.py b/product_pack/__openerp__.py index 285e3d78..f6287680 100755 --- a/product_pack/__openerp__.py +++ b/product_pack/__openerp__.py @@ -20,19 +20,12 @@ ############################################################################## { 'name': 'Product Pack', - 'version': '1.0', + 'version': '9.0.1.1.0', 'category': 'Product', 'sequence': 14, 'summary': '', - 'description': """ -Product Pack -============ -# TODO agregar en configuracion si se quiere usar los sale order packs (seria para el group group_pack) y ver que se haga visible la vista form -# TODO implementar totalice en price get -# TODO agregar constraint de no pack dentro de pack -# TODO calcular correctamente pack virtual available para negativos - """, - 'author': 'NaN·tic, ADHOC', + 'author': 'NaN·tic, ADHOC SA', + 'license': 'AGPL-3', 'images': [ ], 'depends': [ @@ -40,11 +33,11 @@ ], 'data': [ 'security/ir.model.access.csv', - 'security/product_security.xml', - 'pack_view.xml', - 'sale_view.xml', + 'views/pack_view.xml', + 'views/sale_view.xml', ], 'demo': [ + 'demo/demo_data.xml', ], 'test': [ ], @@ -52,4 +45,3 @@ 'auto_install': False, 'application': False, } -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/product_pack/demo/demo_data.xml b/product_pack/demo/demo_data.xml new file mode 100644 index 00000000..e115a9dc --- /dev/null +++ b/product_pack/demo/demo_data.xml @@ -0,0 +1,302 @@ + + + + + + Pack CPU (Detailed Components Price) + + + components_price + 20.5 + 30.75 + service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pack CPU (Detailed Totaliced Price) + + + totalice_price + 20.5 + 30.75 + service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pack CPU (Detailed Fixed Price) + + + fixed_price + 20.5 + 30.75 + service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pack CPU (None Detailed Assisted Price) + + + none_detailed_assited_price + 20.5 + 30.75 + service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pack CPU (None Detailed Totaliced Price) + + + none_detailed_totaliced_price + 20.5 + 30.75 + service + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pack PC (Detailed Components Price) + + + components_price + 20.5 + 30.75 + service + + + + + + + + + + + + + + + + + + + + Pack PC (Detailed Totaliced Price) + + + totalice_price + 20.5 + 30.75 + service + + + + + + + + + + + + + + + + + + + + Pack PC (Detailed Totaliced Price) + + + totalice_price + 20.5 + 30.75 + service + + + + + + + + + + + + + + + + + + + + Pack PC (Detailed Fixed Price) + + + fixed_price + 20.5 + 30.75 + service + + + + + + + + + + + + + + + + + + + + diff --git a/product_pack/models/__init__.py b/product_pack/models/__init__.py new file mode 100755 index 00000000..0b671075 --- /dev/null +++ b/product_pack/models/__init__.py @@ -0,0 +1,10 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## + +from . import pack +from . import product +from . import sale_order_line_pack_line +from . import sale_order_line +from . import sale_order diff --git a/product_pack/models/pack.py b/product_pack/models/pack.py new file mode 100755 index 00000000..6ec0e11b --- /dev/null +++ b/product_pack/models/pack.py @@ -0,0 +1,91 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import fields, models, api +import openerp.addons.decimal_precision as dp + + +class ProductPack(models.Model): + _name = 'product.pack.line' + _rec_name = 'product_id' + + parent_product_id = fields.Many2one( + 'product.product', + 'Parent Product', + ondelete='cascade', + required=True + ) + quantity = fields.Float( + 'Quantity', + required=True, + default=1.0, + digits=dp.get_precision('Product UoS'), + ) + product_id = fields.Many2one( + 'product.product', + 'Product', + ondelete='cascade', + required=True, + ) + discount = fields.Float( + 'Discount (%)', + digits=dp.get_precision('Discount'), + ) + + @api.multi + def get_sale_order_line_vals(self, line, order): + self.ensure_one() + # pack_price = 0.0 + subproduct = self.product_id + quantity = self.quantity * line.product_uom_qty + + taxes = order.fiscal_position_id.map_tax( + subproduct.taxes_id) + tax_id = [(6, 0, taxes.ids)] + + # if pack is fixed price or totlice price we don want amount on + # pack lines + if line.product_id.pack_price_type in [ + 'fixed_price', 'totalice_price']: + price = 0.0 + discount = 0.0 + else: + pricelist = order.pricelist_id.id + price = self.env['product.pricelist'].price_get( + subproduct.id, quantity, + order.partner_id.id, context={ + 'uom': subproduct.uom_id.id, + 'date': order.date_order})[pricelist] + discount = self.discount + + # Obtain product name in partner's language + if order.partner_id.lang: + subproduct = subproduct.with_context( + lang=order.partner_id.lang) + subproduct_name = subproduct.name + + vals = { + 'order_id': order.id, + 'name': '%s%s' % ( + '> ' * (line.pack_depth + 1), subproduct_name + ), + # 'delay': subproduct.sale_delay or 0.0, + 'product_id': subproduct.id, + # 'procurement_ids': ( + # [(4, x.id) for x in line.procurement_ids] + # ), + 'price_unit': price, + 'tax_id': tax_id, + 'address_allotment_id': False, + 'product_uom_qty': quantity, + 'product_uom': subproduct.uom_id.id, + 'product_packaging': False, + 'discount': discount, + 'number_packages': False, + 'th_weight': False, + 'state': 'draft', + 'pack_parent_line_id': line.id, + 'pack_depth': line.pack_depth + 1, + } + return vals diff --git a/product_pack/models/product.py b/product_pack/models/product.py new file mode 100644 index 00000000..3e78d787 --- /dev/null +++ b/product_pack/models/product.py @@ -0,0 +1,215 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import fields, models, api, _ +from openerp.osv import fields as old_fields +from openerp.exceptions import UserError +import math + + +class ProductProduct(models.Model): + _inherit = 'product.product' + + pack_line_ids = fields.One2many( + 'product.pack.line', + 'parent_product_id', + 'Pack Products', + help='List of products that are part of this pack.' + ) + used_pack_line_ids = fields.One2many( + 'product.pack.line', + 'product_id', + 'On Packs', + help='List of packs where product is used.' + ) + + def _product_available( + self, cr, uid, ids, field_names=None, arg=False, context=None): + """ + For product packs we get availability in a different way + """ + pack_product_ids = self.search(cr, uid, [ + ('pack', '=', True), + ('id', 'in', ids), + ]) + res = super(ProductProduct, self)._product_available( + cr, uid, list(set(ids) - set(pack_product_ids)), + field_names, arg, context) + for product in self.browse(cr, uid, pack_product_ids, context=context): + pack_qty_available = [] + pack_virtual_available = [] + for subproduct in product.pack_line_ids: + subproduct_stock = self._product_available( + cr, uid, [subproduct.product_id.id], field_names, arg, + context)[subproduct.product_id.id] + sub_qty = subproduct.quantity + if sub_qty: + pack_qty_available.append(math.floor( + subproduct_stock['qty_available'] / sub_qty)) + pack_virtual_available.append(math.floor( + subproduct_stock['virtual_available'] / sub_qty)) + # TODO calcular correctamente pack virtual available para negativos + res[product.id] = { + 'qty_available': ( + pack_qty_available and min(pack_qty_available) or False), + 'incoming_qty': 0, + 'outgoing_qty': 0, + 'virtual_available': ( + pack_virtual_available and + max(min(pack_virtual_available), 0) or False), + } + return res + + def _search_product_quantity(self, cr, uid, obj, name, domain, context): + """ + We use original search function + """ + return super(ProductProduct, self)._search_product_quantity( + cr, uid, obj, name, domain, context) + + # overwrite ot this fields so that we can modify _product_available + # function to support packs + _columns = { + 'qty_available': old_fields.function( + _product_available, multi='qty_available', + fnct_search=_search_product_quantity), + 'virtual_available': old_fields.function( + _product_available, multi='qty_available', + fnct_search=_search_product_quantity), + 'incoming_qty': old_fields.function( + _product_available, multi='qty_available', + fnct_search=_search_product_quantity), + 'outgoing_qty': old_fields.function( + _product_available, multi='qty_available', + fnct_search=_search_product_quantity), + } + + @api.multi + @api.constrains('pack_line_ids') + def check_recursion(self): + """ + Check recursion on packs + """ + for rec in self: + pack_lines = rec.pack_line_ids + while pack_lines: + if rec in pack_lines.mapped('product_id'): + raise UserError(_( + 'Error! You cannot create recursive packs.\n' + 'Product id: %s') % rec.id) + pack_lines = pack_lines.mapped('product_id.pack_line_ids') + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + # TODO rename a pack_type + pack_price_type = fields.Selection([ + ('components_price', 'Detailed - Components Prices'), + ('totalice_price', 'Detailed - Totaliced Price'), + ('fixed_price', 'Detailed - Fixed Price'), + ('none_detailed_assited_price', 'None Detailed - Assisted Price'), + ('none_detailed_totaliced_price', 'None Detailed - Totaliced Price'), + ], + 'Pack Type', + help="* Detailed - Components Prices: Detail lines with prices on " + "sales order.\n" + "* Detailed - Totaliced Price: Detail lines on sales order totalicing " + "lines prices on pack (don't show component prices).\n" + "* Detailed - Fixed Price: Detail lines on sales order and use product" + " pack price (ignore line prices).\n" + "* None Detailed - Assisted Price: Do not detail lines on sales " + "order. Assist to get pack price using pack lines." + ) + pack = fields.Boolean( + 'Pack?', + help='Is a Product Pack?', + ) + pack_line_ids = fields.One2many( + related='product_variant_ids.pack_line_ids' + ) + used_pack_line_ids = fields.One2many( + related='product_variant_ids.used_pack_line_ids' + ) + + @api.multi + @api.constrains( + 'product_variant_ids', 'pack_price_type') + def check_relations(self): + """ + Check assited packs dont have packs a childs + """ + # check assited price has no packs child of them + for rec in self: + if rec.pack_price_type == 'none_detailed_assited_price': + child_packs = rec.mapped( + 'pack_line_ids.product_id').filtered('pack') + if child_packs: + raise UserError(_( + 'A "None Detailed - Assisted Price Pack" can not have ' + 'a pack as a child!')) + + # TODO we also should check this + # check if we are configuring a pack for a product that is partof a + # assited pack + # if self.pack: + # for product in self.product_variant_ids + # parent_assited_packs = self.env['product.pack.line'].search([ + # ('product_id', '=', self.id), + # ('parent_product_id.pack_price_type', '=', + # 'none_detailed_assited_price'), + # ]) + # print 'parent_assited_packs', parent_assited_packs + # if parent_assited_packs: + # raise Warning(_( + # 'You can not set this product as pack because it is part' + # ' of a "None Detailed - Assisted Price Pack"')) + + @api.multi + @api.constrains('company_id', 'product_variant_ids') + def check_pack_line_company(self): + """ + Check packs are related to packs of same company + """ + for rec in self: + for line in rec.pack_line_ids: + if line.product_id.company_id != rec.company_id: + raise UserError(_( + 'Pack lines products company must be the same as the ' + 'parent product company')) + for line in rec.used_pack_line_ids: + if line.parent_product_id.company_id != rec.company_id: + raise UserError(_( + 'Pack lines products company must be the same as the ' + 'parent product company')) + + @api.multi + def write(self, vals): + """ + We remove from prod.prod to avoid error + """ + if vals.get('pack_line_ids', False): + self.product_variant_ids.write( + {'pack_line_ids': vals.pop('pack_line_ids')}) + return super(ProductTemplate, self).write(vals) + + @api.model + def _price_get(self, products, ptype='list_price'): + res = super(ProductTemplate, self)._price_get( + products, ptype=ptype) + for product in products: + if ( + product.pack and + product.pack_price_type in [ + 'totalice_price', + 'none_detailed_assited_price', + 'none_detailed_totaliced_price']): + pack_price = 0.0 + for pack_line in product.pack_line_ids: + product_line_price = pack_line.product_id.price_get()[ + pack_line.product_id.id] * ( + 1 - (pack_line.discount or 0.0) / 100.0) + pack_price += (product_line_price * pack_line.quantity) + res[product.id] = pack_price + return res diff --git a/product_pack/models/sale_order.py b/product_pack/models/sale_order.py new file mode 100644 index 00000000..bb718ee5 --- /dev/null +++ b/product_pack/models/sale_order.py @@ -0,0 +1,18 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import models, api + + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + @api.one + def copy(self, default=None): + sale_copy = super(SaleOrder, self).copy(default) + # we unlink pack lines that should not be copied + pack_copied_lines = sale_copy.order_line.filtered( + lambda l: l.pack_parent_line_id.order_id == self) + pack_copied_lines.unlink() + return sale_copy diff --git a/product_pack/models/sale_order_line.py b/product_pack/models/sale_order_line.py new file mode 100644 index 00000000..c83c40ec --- /dev/null +++ b/product_pack/models/sale_order_line.py @@ -0,0 +1,122 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import fields, models, api, _ + + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + # Fields for sale order pack + pack_total = fields.Float( + string='Pack total', + compute='_get_pack_total' + ) + pack_line_ids = fields.One2many( + 'sale.order.line.pack.line', + 'order_line_id', + 'Pack Lines' + ) + pack_type = fields.Selection( + related='product_id.pack_price_type', + readonly=True + ) + + # Fields for common packs + pack_depth = fields.Integer( + 'Depth', + help='Depth of the product if it is part of a pack.' + ) + pack_parent_line_id = fields.Many2one( + 'sale.order.line', + 'Pack', + help='The pack that contains this product.', + ondelete="cascade", + # copy=False, + ) + pack_child_line_ids = fields.One2many( + 'sale.order.line', + 'pack_parent_line_id', + 'Lines in pack' + ) + + @api.one + @api.constrains('product_id', 'price_unit', 'product_uom_qty') + def expand_pack_line(self): + detailed_packs = ['components_price', 'totalice_price', 'fixed_price'] + if ( + self.state == 'draft' and + self.product_id.pack and + self.pack_type in detailed_packs): + for subline in self.product_id.pack_line_ids: + vals = subline.get_sale_order_line_vals( + self, self.order_id) + vals['sequence'] = self.sequence + existing_subline = self.search([ + ('product_id', '=', subline.product_id.id), + ('pack_parent_line_id', '=', self.id), + ], limit=1) + # if subline already exists we update, if not we create + if existing_subline: + existing_subline.write(vals) + else: + self.create(vals) + + @api.multi + def button_save_data(self): + return True + + @api.multi + def action_pack_detail(self): + view_id = self.env['ir.model.data'].xmlid_to_res_id( + 'product_pack.view_order_line_form2') + view = { + 'name': _('Details'), + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'sale.order.line', + 'view_id': view_id, + 'type': 'ir.actions.act_window', + 'target': 'new', + 'readonly': True, + 'res_id': self.id, + 'context': self.env.context + } + return view + + @api.one + @api.depends( + 'pack_line_ids', + 'pack_line_ids.price_subtotal', + ) + def _get_pack_total(self): + pack_total = 0.0 + if self.pack_line_ids: + pack_total = sum(x.price_subtotal for x in self.pack_line_ids) + self.pack_total = pack_total + + @api.one + @api.onchange('pack_total') + def _onchange_pack_line_ids(self): + self.price_unit = self.pack_total + + @api.constrains('product_id') + def expand_none_detailed_pack(self): + if self.product_id.pack_price_type == 'none_detailed_assited_price': + # remove previus existing lines + self.pack_line_ids.unlink() + + # create a sale pack line for each product pack line + for pack_line in self.product_id.pack_line_ids: + price_unit = pack_line.product_id.lst_price + quantity = pack_line.quantity + vals = { + 'order_line_id': self.id, + 'product_id': pack_line.product_id.id, + 'product_uom_qty': quantity, + 'price_unit': price_unit, + 'discount': pack_line.discount, + 'price_subtotal': price_unit * quantity, + } + self.pack_line_ids.create(vals) diff --git a/product_pack/models/sale_order_line_pack_line.py b/product_pack/models/sale_order_line_pack_line.py new file mode 100755 index 00000000..3da99980 --- /dev/null +++ b/product_pack/models/sale_order_line_pack_line.py @@ -0,0 +1,54 @@ +# -*- encoding: utf-8 -*- +############################################################################## +# For copyright and license notices, see __openerp__.py file in root directory +############################################################################## +from openerp import fields, models, api +import openerp.addons.decimal_precision as dp + + +class SaleOrderLinePackLine(models.Model): + _name = 'sale.order.line.pack.line' + _description = 'Sale Order None Detailed Pack Lines' + + order_line_id = fields.Many2one( + 'sale.order.line', + 'Order Line', + ondelete='cascade', + required=True + ) + product_id = fields.Many2one( + 'product.product', + 'Product', + required=True + ) + price_unit = fields.Float( + 'Unit Price', + required=True, + digits=dp.get_precision('Product Price') + ) + discount = fields.Float( + 'Discount (%)', + digits=dp.get_precision('Discount'), + ) + price_subtotal = fields.Float( + compute="_amount_line", + string='Subtotal', + digits=dp.get_precision('Account') + ) + product_uom_qty = fields.Float( + 'Quantity', + digits=dp.get_precision('Product UoS'), + required=True + ) + + @api.one + @api.onchange('product_id') + def onchange_product_id(self): + self.price_unit = self.product_id.lst_price + + @api.one + @api.depends('price_unit', 'product_uom_qty') + def _amount_line(self): + self.price_subtotal = ( + self.product_uom_qty * self.price_unit * + (1 - (self.discount or 0.0) / 100.0)) diff --git a/product_pack/pack.py b/product_pack/pack.py deleted file mode 100755 index 060ce771..00000000 --- a/product_pack/pack.py +++ /dev/null @@ -1,194 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## -from openerp import fields, models, api, _ -from openerp.osv import fields as old_fields -from openerp.exceptions import Warning -import math - - -class product_pack(models.Model): - _name = 'product.pack.line' - _rec_name = 'product_id' - - parent_product_id = fields.Many2one( - 'product.product', 'Parent Product', - ondelete='cascade', required=True) - quantity = fields.Float( - 'Quantity', required=True) - product_id = fields.Many2one( - 'product.product', 'Product', required=True) - - @api.multi - def get_sale_order_line_vals(self, line, order, sequence, fiscal_position): - self.ensure_one() - sequence += 1 - # pack_price = 0.0 - subproduct = self.product_id - quantity = self.quantity * line.product_uom_qty - - tax_ids = self.env['account.fiscal.position'].map_tax( - subproduct.taxes_id) - tax_id = [(6, 0, tax_ids)] - - if subproduct.uos_id: - uos_id = subproduct.uos_id.id - uos_qty = quantity * subproduct.uos_coeff - else: - uos_id = False - uos_qty = quantity - - if line.product_id.pack_price_type == 'fixed_price': - price = 0.0 - discount = 0.0 - # TODO this should go in price get of pricelist - # elif line.product_id.pack_price_type == 'totalice_price': - # pack_price += (price * uos_qty) - # price = 0.0 - # discount = 0.0 - # tax_id = False - else: - pricelist = order.pricelist_id.id - price = self.env['product.pricelist'].price_get( - subproduct.id, quantity, - order.partner_id.id, context={ - 'uom': subproduct.uom_id.id, - 'date': order.date_order})[pricelist] - discount = line.discount - - # Obtain product name in partner's language - # ctx = {'lang': order.partner_id.lang} - subproduct_name = subproduct.name - - vals = { - 'order_id': order.id, - 'name': '%s%s' % ( - '> ' * (line.pack_depth + 1), subproduct_name - ), - 'sequence': sequence, - # 'delay': subproduct.sale_delay or 0.0, - 'product_id': subproduct.id, - # 'procurement_ids': ( - # [(4, x.id) for x in line.procurement_ids] - # ), - 'price_unit': price, - 'tax_id': tax_id, - 'address_allotment_id': False, - 'product_uom_qty': quantity, - 'product_uom': subproduct.uom_id.id, - 'product_uos_qty': uos_qty, - 'product_uos': uos_id, - 'product_packaging': False, - 'discount': discount, - 'number_packages': False, - 'th_weight': False, - 'state': 'draft', - 'pack_parent_line_id': line.id, - 'pack_depth': line.pack_depth + 1, - } - return vals - - -class product_product(models.Model): - _inherit = 'product.product' - - pack_line_ids = fields.One2many( - 'product.pack.line', 'parent_product_id', 'Pack Products', - help='List of products that are part of this pack.') - used_pack_line_ids = fields.One2many( - 'product.pack.line', 'product_id', 'Pack Products', - help='List of products that are part of this pack.') - - def _product_available( - self, cr, uid, ids, field_names=None, arg=False, context=None): - pack_product_ids = self.search(cr, uid, [ - ('pack', '=', True), - ('id', 'in', ids), - ]) - res = super(product_product, self)._product_available( - cr, uid, list(set(ids) - set(pack_product_ids)), - field_names, arg, context) - for product in self.browse(cr, uid, pack_product_ids, context=context): - pack_qty_available = [] - pack_virtual_available = [] - for subproduct in product.pack_line_ids: - subproduct_stock = self._product_available( - cr, uid, [subproduct.product_id.id], field_names, arg, - context)[subproduct.product_id.id] - sub_qty = subproduct.quantity - if sub_qty: - pack_qty_available.append(math.floor( - subproduct_stock['qty_available'] / sub_qty)) - pack_virtual_available.append(math.floor( - subproduct_stock['virtual_available'] / sub_qty)) - # TODO calcular correctamente pack virtual available para negativos - res[product.id] = { - 'qty_available': pack_qty_available and min(pack_qty_available) or False, - 'incoming_qty': 0, - 'outgoing_qty': 0, - 'virtual_available': pack_virtual_available and max(min(pack_virtual_available), 0) or False, - } - return res - - def _search_product_quantity(self, cr, uid, obj, name, domain, context): - return super(product_product, self)._search_product_quantity( - cr, uid, obj, name, domain, context) - - _columns = { - 'qty_available': old_fields.function( - _product_available, multi='qty_available', - fnct_search=_search_product_quantity), - 'virtual_available': old_fields.function( - _product_available, multi='qty_available', - fnct_search=_search_product_quantity), - 'incoming_qty': old_fields.function( - _product_available, multi='qty_available', - fnct_search=_search_product_quantity), - 'outgoing_qty': old_fields.function( - _product_available, multi='qty_available', - fnct_search=_search_product_quantity), - } - - @api.one - @api.constrains('company_id', 'pack_line_ids', 'used_pack_line_ids') - def check_pack_line_company(self): - # TODO implementar mejores mensajes - for line in self.pack_line_ids: - if line.product_id.company_id != self.company_id: - raise Warning(_( - 'Pack lines products company must be the same as the\ - parent product company')) - for line in self.used_pack_line_ids: - if line.parent_product_id.company_id != self.company_id: - raise Warning(_( - 'Pack lines products company must be the same as the\ - parent product company')) - - -class product_template(models.Model): - _inherit = 'product.template' - - pack_price_type = fields.Selection([ - ('components_price', 'Components Prices'), - # TODO modify price_get and add this functionality - # ('totalice_price', 'Totalice Price'), - ('fixed_price', 'Fixed Price'), - ], - 'Pack Price Type', - help=""" - * Totalice Price: Sum individual prices on the product pack price. - * Fixed Price: Price of this product instead of components prrices. - * Components Price: Components prices plast pack price. - """ - ) - sale_order_pack = fields.Boolean( - 'Sale Order Pack', - help='Sale order are packs used on sale orders to calculate a price of a line', - ) - pack = fields.Boolean( - 'Pack?', - help='TODO', - ) - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/product_pack/sale.py b/product_pack/sale.py deleted file mode 100755 index 1d51d83d..00000000 --- a/product_pack/sale.py +++ /dev/null @@ -1,299 +0,0 @@ -# -*- encoding: utf-8 -*- -############################################################################## -# For copyright and license notices, see __openerp__.py file in root directory -############################################################################## -from openerp import fields, models, api -import openerp.addons.decimal_precision as dp - - -class sale_order_line_pack_line(models.Model): - _name = 'sale.order.line.pack.line' - _description = 'sale.order.line.pack.line' - - order_line_id = fields.Many2one( - 'sale.order.line', 'Order Line', ondelete='cascade', required=True) - product_id = fields.Many2one( - 'product.product', 'Product', required=True) - price_unit = fields.Float( - 'Unit Price', - required=True, - digits_compute=dp.get_precision('Product Price')) - price_subtotal = fields.Float( - compute="_amount_line", - string='Subtotal', - digits_compute=dp.get_precision('Account')) - product_uom_qty = fields.Float( - 'Quantity', digits_compute=dp.get_precision('Product UoS'), - required=True) - - @api.one - @api.onchange('product_id') - def onchange_product_id(self): - self.price_unit = self.product_id.lst_price - - @api.one - @api.depends('price_unit', 'product_uom_qty') - def _amount_line(self): - self.price_subtotal = self.product_uom_qty * self.price_unit - - -class sale_order_line(models.Model): - _inherit = 'sale.order.line' - - # Fields for sale order pack - pack_total = fields.Float( - string='Pack total', compute='_get_pack_total') - pack_line_ids = fields.One2many( - 'sale.order.line.pack.line', 'order_line_id', 'Pack Lines') - sale_order_pack = fields.Boolean(related='product_id.sale_order_pack') - - # Fields for common packs - pack_depth = fields.Integer( - 'Depth', - help='Depth of the product if it is part of a pack.' - ) - pack_parent_line_id = fields.Many2one( - 'sale.order.line', 'Pack', - help='The pack that contains this product.', ondelete="cascade" - ) - pack_child_line_ids = fields.One2many( - 'sale.order.line', 'pack_parent_line_id', 'Lines in pack' - ) - - def button_dummy(self, cr, uid, ids, context=None): - return True - - @api.one - @api.depends( - 'pack_line_ids', - 'pack_line_ids.price_subtotal', - ) - def _get_pack_total(self): - pack_total = 0.0 - if self.pack_line_ids: - pack_total = sum(x.price_subtotal for x in self.pack_line_ids) - self.pack_total = pack_total - - @api.one - @api.onchange('pack_total') - def _onchange_pack_line_ids(self): - self.price_unit = self.pack_total - - # onchange para agregar los product en el tipo el pack "sale order pack" - def product_id_change( - self, cr, uid, ids, pricelist, product, qty=0, - uom=False, qty_uos=0, uos=False, name='', partner_id=False, - lang=False, update_tax=True, date_order=False, packaging=False, - fiscal_position=False, flag=False, context=None): - # warning = {} - if not product: - return {'value': { - 'th_weight': 0, - 'product_packaging': False, - 'product_uos_qty': qty}, - 'domain': {'product_uom': [], 'product_uos': []} - } - product_obj = self.pool.get('product.product') - product_info = product_obj.browse(cr, uid, product) - - result = super(sale_order_line, self).product_id_change( - cr, uid, ids, pricelist, product, qty, - uom, qty_uos, uos, name, partner_id, - lang, update_tax, date_order, packaging, - fiscal_position, flag, context) - - pack_line_ids = [(5, False, False)] - if product_info.pack_line_ids and product_info.sale_order_pack: - for pack_line in product_info.pack_line_ids: - price_unit = pack_line.product_id.lst_price - quantity = pack_line.quantity - pack_line_ids.append((0, False, { - 'product_id': pack_line.product_id.id, - 'product_uom_qty': quantity, - 'price_unit': price_unit, - 'price_subtotal': price_unit * quantity, - })) - result['value']['pack_line_ids'] = pack_line_ids - return result - - -class sale_order(models.Model): - _inherit = 'sale.order' - - # Copia del modulo de pxgeo - def create(self, cr, uid, vals, context=None): - result = super(sale_order, self).create(cr, uid, vals, context) - self.expand_packs(cr, uid, [result], context) - return result - - def write(self, cr, uid, ids, vals, context=None): - result = super(sale_order, self).write(cr, uid, ids, vals, context) - if 'order_line' in vals: - self.expand_packs(cr, uid, ids, context) - return result - - def copy(self, cr, uid, id, default={}, context=None): - line_obj = self.pool.get('sale.order.line') - result = super(sale_order, self).copy(cr, uid, id, default, context) - sale = self.browse(cr, uid, result, context) - for line in sale.order_line: - if line.pack_parent_line_id: - line_obj.unlink(cr, uid, [line.id], context) - self.expand_packs(cr, uid, sale.id, context) - return result - - def expand_packs(self, cr, uid, ids, context={}, depth=1): - if type(ids) in [int, long]: - ids = [ids] - if depth == 10: - return - updated_orders = [] - for order in self.browse(cr, uid, ids, context): - - fiscal_position = ( - order.fiscal_position - and self.pool.get('account.fiscal.position').browse( - cr, uid, order.fiscal_position.id, context - ) - or False - ) - """ - The reorder variable is used to ensure lines of the same pack go - right after their parent. What the algorithm does is check if the - previous item had children. As children items must go right after - the parent if the line we're evaluating doesn't have a parent it - means it's a new item (and probably has the default 10 sequence - number - unless the appropiate c2c_sale_sequence module is - installed). In this case we mark the item for reordering and - evaluate the next one. Note that as the item is not evaluated and - it might have to be expanded it's put on the queue for another - iteration (it's simple and works well). Once the next item has been - evaluated the sequence of the item marked for reordering is updated - with the next value. - """ - sequence = -1 - reorder = [] - last_had_children = False - lines_to_unlink = [] - for line in order.order_line: - if last_had_children and not line.pack_parent_line_id: - reorder.append(line.id) - if ( - line.product_id.pack_line_ids - and order.id not in updated_orders - ): - updated_orders.append(order.id) - continue - - sequence += 1 - - if sequence > line.sequence: - self.pool.get('sale.order.line').write( - cr, uid, [line.id], {'sequence': sequence, }, context) - else: - sequence = line.sequence - - if line.state != 'draft': - continue - if not line.product_id or not line.product_id.pack or line.product_id.sale_order_pack: - continue - - """ If pack was already expanded (in another create/write - operation or in a previous iteration) don't do it again. """ - if line.pack_child_line_ids: - # Cambiamos esto para que se borren las lienas viejas y se - # creen nuevas - unlink_line_ids = [x.id for x in line.pack_child_line_ids] - lines_to_unlink.extend(unlink_line_ids) - # last_had_children = True - # continue - last_had_children = False - # pack_price = 0.0 - - for subline in line.product_id.pack_line_ids: - vals = subline.get_sale_order_line_vals( - line, order, sequence, fiscal_position) - # sequence += 1 - - # subproduct = subline.product_id - # quantity = subline.quantity * line.product_uom_qty - - # tax_ids = self.pool.get('account.fiscal.position').map_tax( - # cr, uid, fiscal_position, subproduct.taxes_id) - # tax_id = [(6, 0, tax_ids)] - - # if subproduct.uos_id: - # uos_id = subproduct.uos_id.id - # uos_qty = quantity * subproduct.uos_coeff - # else: - # uos_id = False - # uos_qty = quantity - - # if line.product_id.pack_price_type == 'fixed_price': - # price = 0.0 - # discount = 0.0 - # elif line.product_id.pack_price_type == 'totalice_price': - # pack_price += (price * uos_qty) - # price = 0.0 - # discount = 0.0 - # tax_id = False - # else: - # pricelist = order.pricelist_id.id - # price = self.pool.get('product.pricelist').price_get( - # cr, uid, [pricelist], subproduct.id, quantity, - # order.partner_id.id, { - # 'uom': subproduct.uom_id.id, - # 'date': order.date_order, - # } - # )[pricelist] - # discount = line.discount - - # Obtain product name in partner's language - # ctx = {'lang': order.partner_id.lang} - # subproduct_name = self.pool.get('product.product').browse( - # cr, uid, subproduct.id, ctx).name - - # vals = { - # 'order_id': order.id, - # 'name': '%s%s' % ( - # '> ' * (line.pack_depth+1), subproduct_name - # ), - # 'sequence': sequence, - # 'delay': subproduct.sale_delay or 0.0, - # 'product_id': subproduct.id, - # 'procurement_ids': ( - # [(4, x.id) for x in line.procurement_ids] - # ), - # 'price_unit': price, - # 'tax_id': tax_id, - # 'address_allotment_id': False, - # 'product_uom_qty': quantity, - # 'product_uom': subproduct.uom_id.id, - # 'product_uos_qty': uos_qty, - # 'product_uos': uos_id, - # 'product_packaging': False, - # 'discount': discount, - # 'number_packages': False, - # 'th_weight': False, - # 'state': 'draft', - # 'pack_parent_line_id': line.id, - # 'pack_depth': line.pack_depth + 1, - # } - - self.pool.get('sale.order.line').create( - cr, uid, vals, context) - if order.id not in updated_orders: - updated_orders.append(order.id) - - for id in reorder: - sequence += 1 - self.pool.get('sale.order.line').write( - cr, uid, [id], {'sequence': sequence, }, context) - - # Borramos las lienas que se actualizan - self.pool.get('sale.order.line').unlink( - cr, uid, lines_to_unlink, context=context) - - return - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/product_pack/sale_order.py b/product_pack/sale_order.py new file mode 100644 index 00000000..e69de29b diff --git a/product_pack/sale_view.xml b/product_pack/sale_view.xml deleted file mode 100644 index e2562c6b..00000000 --- a/product_pack/sale_view.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - sale.line.pack.line.tree - sale.order.line.pack.line - - - - - - - - - - - - sale.order.form.inherit - sale.order - - - - -
-
-
- - - - -
-
-
-
- -
-
diff --git a/product_pack/security/product_security.xml b/product_pack/security/product_security.xml deleted file mode 100644 index 72c137b8..00000000 --- a/product_pack/security/product_security.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - Manage Packs On Sales Orders - - - - - diff --git a/product_pack/pack_view.xml b/product_pack/views/pack_view.xml similarity index 52% rename from product_pack/pack_view.xml rename to product_pack/views/pack_view.xml index 6d187e75..96d3cad8 100755 --- a/product_pack/pack_view.xml +++ b/product_pack/views/pack_view.xml @@ -3,6 +3,23 @@ + + product.template.pack.form + product.template + + + + + + + + + + + + + + product.product.pack.form product.product @@ -10,11 +27,10 @@ - - + - + @@ -31,6 +47,7 @@ + @@ -44,6 +61,7 @@ + diff --git a/product_pack/views/sale_view.xml b/product_pack/views/sale_view.xml new file mode 100644 index 00000000..8dd2a39b --- /dev/null +++ b/product_pack/views/sale_view.xml @@ -0,0 +1,67 @@ + + + + + + + sale.line.pack.line.tree + sale.order.line.pack.line + + + + + + + + + + + + + view.order.line.button + sale.order.line + + +
+
+ +
+ + +
+
+
+ + + + + +
+
+ +
+ + + + sale.order.form.inherit + sale.order + + + + + +