openerp-community-reviewer team mailing list archive
-
openerp-community-reviewer team
-
Mailing list archive
-
Message #08001
[Merge] lp:~savoirfairelinux-openerp/purchase-wkfl/pallet-delivery-optimized into lp:purchase-wkfl
Maxime Chambreuil (http://www.savoirfairelinux.com) has proposed merging lp:~savoirfairelinux-openerp/purchase-wkfl/pallet-delivery-optimized into lp:purchase-wkfl.
Requested reviews:
Purchase Core Editors (purchase-core-editors)
For more details, see:
https://code.launchpad.net/~savoirfairelinux-openerp/purchase-wkfl/pallet-delivery-optimized/+merge/242604
--
Your team Purchase Core Editors is requested to review the proposed merge of lp:~savoirfairelinux-openerp/purchase-wkfl/pallet-delivery-optimized into lp:purchase-wkfl.
=== added directory 'delivery_editable_dates'
=== added file 'delivery_editable_dates/__init__.py'
=== added file 'delivery_editable_dates/__openerp__.py'
--- delivery_editable_dates/__openerp__.py 1970-01-01 00:00:00 +0000
+++ delivery_editable_dates/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Editable Delivery Dates',
+ 'version': '0.1',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'caterogy': 'sales',
+ 'description': """
+""",
+ 'depends': ['base', 'sale'],
+ 'data': [
+ 'editable_delivery_dates_view.xml',
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added file 'delivery_editable_dates/editable_delivery_dates_view.xml'
--- delivery_editable_dates/editable_delivery_dates_view.xml 1970-01-01 00:00:00 +0000
+++ delivery_editable_dates/editable_delivery_dates_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<openerp>
+ <data>
+ <record id="editable_so_form" model="ir.ui.view">
+ <field name="name">sale.order.editable.form</field>
+ <field name="model">sale.order</field>
+ <field name="inherit_id" ref="sale.view_order_form" />
+ <field name="arch" type="xml">
+ <field name="date_order" position="replace">
+ <field name="date_order" attrs="{'readonly': False}" />
+ </field>
+ </field>
+ </record>
+
+ <record id="editable_do_form" model="ir.ui.view">
+ <field name="name">stock.picking.out.editable.form</field>
+ <field name="model">stock.picking.out</field>
+ <field name="inherit_id" ref="stock.view_picking_out_form" />
+ <field name="arch" type="xml">
+ <field name="min_date" position="replace">
+ <field name="min_date" attrs="{'readonly': False, 'invisible': [('min_date', '=', False)]}" />
+ </field>
+ </field>
+ </record>
+
+ <record id="editable_in_form" model="ir.ui.view">
+ <field name="name">stock.picking.in.editable.form</field>
+ <field name="model">stock.picking.in</field>
+ <field name="inherit_id" ref="stock.view_picking_in_form" />
+ <field name="arch" type="xml">
+ <field name="min_date" position="replace">
+ <field name="min_date" attrs="{'readonly': False, 'invisible': [('min_date', '=', False)]}" />
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'delivery_editable_dates/i18n'
=== added file 'delivery_editable_dates/i18n/delivery_editable_dates.pot'
--- delivery_editable_dates/i18n/delivery_editable_dates.pot 1970-01-01 00:00:00 +0000
+++ delivery_editable_dates/i18n/delivery_editable_dates.pot 2014-11-23 23:06:46 +0000
@@ -0,0 +1,16 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:19+0000\n"
+"PO-Revision-Date: 2013-09-18 14:19+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"
+
=== added directory 'landed_cost_per_pallet'
=== added file 'landed_cost_per_pallet/README'
=== added file 'landed_cost_per_pallet/__init__.py'
--- landed_cost_per_pallet/__init__.py 1970-01-01 00:00:00 +0000
+++ landed_cost_per_pallet/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import purchase
=== added file 'landed_cost_per_pallet/__openerp__.py'
--- landed_cost_per_pallet/__openerp__.py 1970-01-01 00:00:00 +0000
+++ landed_cost_per_pallet/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+# NOTE: The name of the supplied field was initially "display_name", but it seems that OpenERP,
+# whenever it seems "name" in the field, returns the value for "name". Well...
+
+{
+ 'name': 'Landed Cost per Pallet',
+ 'version': '1.1',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'Generic Modules/Purchases',
+ 'description': """
+
+Lets you manage product quantities using crates and pallets
+===========================================================
+
+This module modifies the purchase module to let you manage product
+quantities by specifying a number of pallets and a number of crates
+per pallet.
+
+This also adds a 'Per Pallet' option to landed costs, in order to compute the
+landed costs per pallet.
+""",
+ 'depends': ['base', 'purchase', 'purchase_landed_costs'],
+ 'data': [
+ 'landed_cost_per_pallet_view.xml',
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added directory 'landed_cost_per_pallet/i18n'
=== added file 'landed_cost_per_pallet/i18n/fr.po'
--- landed_cost_per_pallet/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ landed_cost_per_pallet/i18n/fr.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,46 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * landed_cost_per_pallet
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:21+0000\n"
+"PO-Revision-Date: 2013-09-18 14:21+0000\n"
+"Last-Translator: Alexandre Boily <alexandre.boily@xxxxxxxxxxxxxxxxxxxx>\n"
+"Language-Team: Savoir-faire Linux\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: landed_cost_per_pallet
+#: field:purchase.order,landed_cost_base_pallet:0
+msgid "Landed Costs Base Pallet"
+msgstr "Coûts d'aterissage par palette"
+
+#. module: landed_cost_per_pallet
+#: model:ir.model,name:landed_cost_per_pallet.model_purchase_order_line
+msgid "Purchase Order Line"
+msgstr "Ligne de bon de commande"
+
+#. module: landed_cost_per_pallet
+#: model:ir.model,name:landed_cost_per_pallet.model_purchase_order
+msgid "Purchase Order"
+msgstr "Bon de commande"
+
+#. module: landed_cost_per_pallet
+#: field:purchase.order.line,nb_crates_per_pallet:0
+msgid "Crates per pallet"
+msgstr "Caisses par palette"
+
+#. module: landed_cost_per_pallet
+#: field:purchase.order.line,nb_pallets:0
+msgid "Pallets"
+msgstr "Palettes"
+
+#. module: landed_cost_per_pallet
+#: model:ir.model,name:landed_cost_per_pallet.model_landed_cost_position
+msgid "landed.cost.position"
+msgstr "landed.cost.position"
=== added file 'landed_cost_per_pallet/i18n/landed_cost_per_pallet.pot'
--- landed_cost_per_pallet/i18n/landed_cost_per_pallet.pot 1970-01-01 00:00:00 +0000
+++ landed_cost_per_pallet/i18n/landed_cost_per_pallet.pot 2014-11-23 23:06:46 +0000
@@ -0,0 +1,47 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * landed_cost_per_pallet
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:21+0000\n"
+"PO-Revision-Date: 2013-09-18 14:21+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: landed_cost_per_pallet
+#: field:purchase.order,landed_cost_base_pallet:0
+msgid "Landed Costs Base Pallet"
+msgstr ""
+
+#. module: landed_cost_per_pallet
+#: model:ir.model,name:landed_cost_per_pallet.model_purchase_order_line
+msgid "Purchase Order Line"
+msgstr ""
+
+#. module: landed_cost_per_pallet
+#: model:ir.model,name:landed_cost_per_pallet.model_purchase_order
+msgid "Purchase Order"
+msgstr ""
+
+#. module: landed_cost_per_pallet
+#: field:purchase.order.line,nb_crates_per_pallet:0
+msgid "Crates per pallet"
+msgstr ""
+
+#. module: landed_cost_per_pallet
+#: field:purchase.order.line,nb_pallets:0
+msgid "Pallets"
+msgstr ""
+
+#. module: landed_cost_per_pallet
+#: model:ir.model,name:landed_cost_per_pallet.model_landed_cost_position
+msgid "landed.cost.position"
+msgstr ""
+
=== added file 'landed_cost_per_pallet/landed_cost_per_pallet_view.xml'
--- landed_cost_per_pallet/landed_cost_per_pallet_view.xml 1970-01-01 00:00:00 +0000
+++ landed_cost_per_pallet/landed_cost_per_pallet_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="view_purchase_pallet_crate_order_line" model="ir.ui.view">
+ <field name="name">purchase.order.form</field>
+ <field name="model">purchase.order</field>
+ <field name="inherit_id" ref="purchase.purchase_order_form"/>
+ <field name="arch" type="xml">
+ <field name="product_qty" position="before">
+ <field name="nb_pallets"/>
+ <field name="nb_crates_per_pallet"/>
+ </field>
+ </field>
+ </record>
+
+ <record id="view_purchase_pallet_crate_thing" model="ir.ui.view">
+ <field name="name">purchase.order.landing.form</field>
+ <field name="model">purchase.order</field>
+ <field name="inherit_id" ref="purchase_landed_costs.c2c_purchase_order_landed_cost_view" />
+ <field name="arch" type="xml">
+ <field name="landed_cost_base_value" position="after">
+ <field name="landed_cost_base_pallet" />
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added file 'landed_cost_per_pallet/purchase.py'
--- landed_cost_per_pallet/purchase.py 1970-01-01 00:00:00 +0000
+++ landed_cost_per_pallet/purchase.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,125 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+import openerp.addons.decimal_precision as dp
+
+class purchase_order(orm.Model):
+
+ _inherit = 'purchase.order'
+
+ def _landed_cost_base_pallet(self, cr, uid, ids, name, args, context):
+ if not ids:
+ return {}
+
+ result = {}
+ landed_costs_base_pallet = 0.0
+
+ for line in self.browse(cr, uid, ids):
+ if line.landed_cost_line_ids:
+ for costs in line.landed_cost_line_ids:
+ if costs.price_type == 'per_pallet':
+ landed_costs_base_pallet += costs.amount
+ result[line.id] = landed_costs_base_pallet
+
+ return result
+
+ _columns = {
+ 'landed_cost_base_pallet': fields.function(
+ _landed_cost_base_pallet,
+ digits_compute=dp.get_precision('Account'),
+ string='Landed Costs Base Pallet'),
+ }
+
+
+class purchase_order_line(orm.Model):
+
+ _inherit = 'purchase.order.line'
+
+ def _product_quantity(self, cursor, user, ids, name, arg, context=None):
+ res = {}
+ for line in self.browse(cursor, user, ids, context=context):
+ if not line.nb_crates_per_pallet or not line.nb_pallets:
+ res[line.id] = 0
+ else:
+ res[line.id] = line.nb_crates_per_pallet * line.nb_pallets
+ return res
+
+ def _landing_cost_order(self, cr, uid, ids, name, args, context):
+ if not ids:
+ return {}
+
+ result = {}
+
+ lines = self.browse(cr, uid, ids)
+
+ # Pre-compute total number of pallets
+ pallets_total = 0.0
+ for line in lines:
+ for po_line in line.order_id.order_line:
+ if po_line.order_id.landed_cost_line_ids:
+ pallets_total += po_line.nb_pallets
+
+ # Landed costs line by line
+ for line in lines:
+ landed_costs = 0.0
+ # distribution of landed costs of PO
+ if line.order_id.landed_cost_line_ids:
+ # Base value (Absolute Value)
+ landed_costs += line.order_id.landed_cost_base_value / line.order_id.amount_total * line.price_subtotal
+
+ # Base quantity (Per Quantity)
+ landed_costs += line.order_id.landed_cost_base_quantity / line.order_id.quantity_total * line.product_qty
+
+ # Base pallet (Per Pallet)
+ landed_costs += line.order_id.landed_cost_base_pallet / pallets_total * line.nb_pallets
+ result[line.id] = landed_costs
+
+ return result
+
+ _columns = {
+ 'nb_pallets': fields.float('Pallets', required=True),
+ 'nb_crates_per_pallet': fields.integer('Crates per pallet', required=True),
+ 'product_qty': fields.function(_product_quantity,
+ digits_compute=dp.get_precision('Product Unit of Measure'),
+ string="Quantity",
+ type='float'),
+ 'landing_costs_order': fields.function(_landing_cost_order,
+ digits_compute=dp.get_precision('Account'),
+ string='Landing Costs from Order'),
+ }
+
+
+class landed_cost_position(orm.Model):
+
+ _inherit = 'landed.cost.position'
+
+ _columns = {
+ 'price_type': fields.selection(
+ [('per_pallet', 'Per Pallet'), ('per_unit','Per Quantity'), ('value','Absolute Value')],
+ 'Amount Type',
+ required=True,
+ help="Defines if the amount is to be calculated for each quantity or an absolute value"),
+ }
+
+ _defaults = {
+ 'price_type': 'per_pallet',
+ }
=== added directory 'mrp_smart_purchase'
=== renamed directory 'mrp_smart_purchase' => 'mrp_smart_purchase.moved'
=== added file 'mrp_smart_purchase/__init__.py'
--- mrp_smart_purchase/__init__.py 1970-01-01 00:00:00 +0000
+++ mrp_smart_purchase/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Nicolas Bessi
+# Copyright 2012 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import mrp_smart_purchase
=== added file 'mrp_smart_purchase/__openerp__.py'
--- mrp_smart_purchase/__openerp__.py 1970-01-01 00:00:00 +0000
+++ mrp_smart_purchase/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Nicolas Bessi
+# Copyright 2012 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+{'name' : 'Smart MRP Purchase based on supplier price',
+ 'version' : '0.2',
+ 'author' : 'Camptocamp',
+ 'maintainer': 'Camptocamp',
+ 'category': 'version',
+ 'complexity': "normal", # easy, normal, expert
+ 'depends' : ['mrp', 'product', 'purchase'],
+ 'description': """This Module will try to get the lower price for given quantity in PO""",
+ 'website': 'http://www.camptocamp.com',
+ 'init_xml': [],
+ 'update_xml': [],
+ 'demo_xml': [],
+ 'tests': [],
+ 'installable': False,
+ 'auto_install': False,
+ 'license': 'AGPL-3',
+ 'application': True}
+
=== added file 'mrp_smart_purchase/mrp_smart_purchase.py'
--- mrp_smart_purchase/mrp_smart_purchase.py 1970-01-01 00:00:00 +0000
+++ mrp_smart_purchase/mrp_smart_purchase.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,85 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Nicolas Bessi
+# Copyright 2012 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from openerp.osv.orm import Model
+
+class MrpProcurement(Model):
+ """Mrp Procurement we override action_po assing to get the cheapest supplier,
+ if you want to change priority parameters just change the _supplier_to_tuple function
+ TODO remove hack if merge proposal accepted look in action_po_assing for details"""
+
+ _inherit = "procurement.order"
+
+ def action_po_assign(self, cursor, uid, ids, context=None):
+ context = context or {}
+ # stack is prduct id : qty
+ # this is a hack beacause make_po hase no function
+ # get supplier so I pass requiered data in context
+ # I know that sucks but OpenEPR wont change this function in stable relase
+ # Merge proposal for trunkis running
+ context['smart_mrp_stack'] = {}
+ for proc in self.browse(cursor, uid, ids, context):
+ context['smart_mrp_stack'][proc.product_id.id] = proc.product_qty
+ res = super(MrpProcurement, self).action_po_assign(cursor, uid, ids, context=context)
+ return res
+
+class ProductTemplate(Model):
+ """ We overrride the get_main_supplier function
+ that is used to retrieve supplier in function fields"""
+
+ _name = "product.template"
+ _inherit = "product.template"
+
+
+ def _supplier_to_tuple(self, cursor, uid, supplier_id, price, product_id):
+ """ Generate an tuple that can be sorted """
+ # This is not the most performat way but it allows easy overriding
+ # the faster solution will be to populate a mapping hash in _get_main_product_supplier
+ info_obj = self.pool.get('product.supplierinfo')
+ info_id = info_obj.search(cursor, uid, [('product_id', '=', product_id),
+ ('name', '=', supplier_id)], order='sequence')[0]
+ info = info_obj.browse(cursor, uid, info_id)
+ res_tuple = (price, info.delay, info.sequence or 10000, info.id)
+ return res_tuple
+
+
+ def _get_main_product_supplier(self, cursor, uid, product, context=None):
+ """Determines the main (best) product supplier for ``product``,
+ using smart_mrp_stack in context to determine qty else it uses sequence
+ """
+ info_obj = self.pool.get('product.supplierinfo')
+ context = context or {}
+ smart_mrp_stack = context.get('smart_mrp_stack', {})
+ if product.id in smart_mrp_stack:
+ ## we look for best prices based on supplier info
+ sellers = product.seller_ids
+ supplier_ids = [x.name.id for x in sellers]
+ qty = smart_mrp_stack.get(product.id, 1)
+ best_prices_persupplier = info_obj.price_get(cursor, uid, supplier_ids,
+ product.id, qty, context=context)
+ #Assmuption to sort price is more important than delay
+ final_choice = []
+ for supp, price in best_prices_persupplier.items():
+ final_choice.append(self._supplier_to_tuple(cursor, uid, supp, price, product.id))
+ final_choice.sort()
+ return info_obj.browse(cursor, uid, final_choice[0][3])
+ else:
+ return super(ProductTemplate, self)._get_main_product_supplier(cursor, uid, product, context)
+ return False
=== added directory 'pallet_delivery'
=== added file 'pallet_delivery/README'
=== added file 'pallet_delivery/__init__.py'
--- pallet_delivery/__init__.py 1970-01-01 00:00:00 +0000
+++ pallet_delivery/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import stock
=== added file 'pallet_delivery/__openerp__.py'
--- pallet_delivery/__openerp__.py 1970-01-01 00:00:00 +0000
+++ pallet_delivery/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+# NOTE: The name of the supplied field was initially "display_name", but it seems that OpenERP,
+# whenever it seems "name" in the field, returns the value for "name". Well...
+
+{
+ 'name': 'Pallet delivery',
+ 'version': '1.1',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'warehouse',
+ 'description': """
+
+Lets you manage truck deliveries
+===========================================================
+
+This module lets you specify where exactly in the delivery truck
+was the merchandise.
+
+Also lets you give more specific information like the temperature
+at various points.
+
+""",
+ 'depends': [
+ 'base', 'purchase', 'stock',
+ 'landed_cost_per_pallet', 'purchase_lot_tracking',
+ ],
+ 'data': [
+ 'security/ir.model.access.csv',
+ 'stock_workflow.xml',
+ 'pallet_delivery_data.xml',
+ 'pallet_delivery_view.xml',
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added directory 'pallet_delivery/i18n'
=== added file 'pallet_delivery/i18n/fr.po'
--- pallet_delivery/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ pallet_delivery/i18n/fr.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,186 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * pallet_delivery
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-05 14:56+0000\n"
+"PO-Revision-Date: 2013-09-05 14:56+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: pallet_delivery
+#: model:ir.actions.act_window,help:pallet_delivery.action_truck_pending
+msgid "<p class=\"oe_view_nocontent_create\">Click to create a draft truck</p>\n"
+"\n"
+" <p>The truck contains an incoming, physical shipment. With it you can\n"
+" register the truck's details, such as its serial number, sampled\n"
+" temperatures, and other information. Also, the truck serves you as a\n"
+" map of what your company received.</p>\n"
+"\n"
+" <p>When you confirm the truck, it will act as an “Incoming Shipment”\n"
+" confirmation, and the products will be moved from your Suppliers (as\n"
+" listed in Purchase Orders) to your Stock.</p>\n"
+" "
+msgstr "<p class=\"oe_view_nocontent_create\">Cliquez pour créer un camion brouillon</p>\n
+<p>Le camion contient une livraison physique entrante. Avec celui-ci, vous
+pouvez enregistrer les détails du camion, comme son numéro de série, les
+températures échantillonnées, et d'autre informations. De même, le camion est
+utile comme carte des produits reçus.</p>
+<p>Lorsque vous confirmez la réception du camion, ce dernier agira comme une
+\"Livraison entrante\" confirmée, et le produits seront déplacés de vos
+fournisseurs (tels que listés dans vos bons de commandes) vers votre
+entrepôt.</p>"
+
+#. module: pallet_delivery
+#: model:ir.model,name:pallet_delivery.model_purchase_order_line
+msgid "Purchase Order Line"
+msgstr "Ligne de bon d'achat"
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Confirm"
+msgstr "Confirmer"
+
+#. module: pallet_delivery
+#: model:ir.model,name:pallet_delivery.model_stock_truck_line
+msgid "A single pallet shipped in an incoming truck"
+msgstr "Une seule palette livrée dans un camion entrant"
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+#: field:stock.truck.line,crates:0
+msgid "Crates"
+msgstr "Caisses"
+
+#. module: pallet_delivery
+#: field:stock.truck.line,pallet:0
+msgid "Pallet"
+msgstr "Palette"
+
+#. module: pallet_delivery
+#: field:stock.truck,state:0
+msgid "State"
+msgstr "État"
+
+#. module: pallet_delivery
+#: model:ir.model,name:pallet_delivery.model_stock_truck
+msgid "Incoming truck"
+msgstr "Camion entrant"
+
+#. module: pallet_delivery
+#: selection:stock.truck,state:0
+msgid "Draft"
+msgstr "Ébauche"
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Details"
+msgstr "Détails"
+
+#. module: pallet_delivery
+#: field:stock.truck,front_temperature:0
+msgid "Front Temperature"
+msgstr "Température avant"
+
+#. module: pallet_delivery
+#: field:stock.truck,supplier:0
+msgid "Supplier"
+msgstr "Fournisseur"
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Truck Composition"
+msgstr "Composition du camion"
+
+#. module: pallet_delivery
+#: field:stock.truck,back_temperature:0
+msgid "Back Temperature"
+msgstr "Température arrière"
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Serial Number"
+msgstr "Numéro de série"
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Left Pallets"
+msgstr "Palettes gauche"
+
+#. module: pallet_delivery
+#: field:stock.truck,left_pallet_ids:0
+#: field:stock.truck,right_pallet_ids:0
+msgid "Pallets"
+msgstr "Palettes"
+
+#. module: pallet_delivery
+#: field:stock.truck,truck_sn:0
+msgid "Truck S/N"
+msgstr "Numéro de série"
+
+#. module: pallet_delivery
+#: field:stock.truck,name:0
+#: field:stock.truck.line,name:0
+msgid "Name"
+msgstr "Nom"
+
+#. module: pallet_delivery
+#: field:purchase.order,stock_truck_ids:0
+msgid "Trucks"
+msgstr "Camions"
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Search Truck"
+msgstr "Rechercher un camion"
+
+#. module: pallet_delivery
+#: model:ir.model,name:pallet_delivery.model_purchase_order
+msgid "Purchase Order"
+msgstr "Bon d'achat"
+
+#. module: pallet_delivery
+#: field:stock.truck,arrival:0
+msgid "Date of Arrival"
+msgstr "Date d'arrivée"
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+#: field:stock.truck.line,left_id:0
+#: field:stock.truck.line,right_id:0
+msgid "Truck"
+msgstr "Camion"
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Right Pallets"
+msgstr "Palettes droite"
+
+#. module: pallet_delivery
+#: model:ir.actions.act_window,name:pallet_delivery.action_truck_pending
+msgid "On Draft Truck"
+msgstr "Camion en ébauche"
+
+#. module: pallet_delivery
+#: model:ir.ui.menu,name:pallet_delivery.menu_truck
+msgid "Incoming Truck"
+msgstr "Camion entrant"
+
+#. module: pallet_delivery
+#: selection:stock.truck,state:0
+msgid "Done"
+msgstr "Complété"
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+#: field:stock.truck,purchase_order_ids:0
+msgid "Purchase Orders"
+msgstr "Bons d'achats"
+
=== added file 'pallet_delivery/i18n/pallet_delivery.pot'
--- pallet_delivery/i18n/pallet_delivery.pot 1970-01-01 00:00:00 +0000
+++ pallet_delivery/i18n/pallet_delivery.pot 2014-11-23 23:06:46 +0000
@@ -0,0 +1,225 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * pallet_delivery
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-05-04 15:54+0000\n"
+"PO-Revision-Date: 2014-05-04 15:54+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: pallet_delivery
+#: model:ir.actions.act_window,help:pallet_delivery.action_truck_pending
+msgid "<p class=\"oe_view_nocontent_create\">Click to create a draft truck</p>\n"
+"\n"
+" <p>The truck contains an incoming, physical shipment. With it you can\n"
+" register the truck's details, such as its serial number, sampled\n"
+" temperatures, and other information. Also, the truck serves you as a\n"
+" map of what your company received.</p>\n"
+"\n"
+" <p>When you confirm the truck, it will act as an “Incoming Shipment”\n"
+" confirmation, and the products will be moved from your Suppliers (as\n"
+" listed in Purchase Orders) to your Stock.</p>\n"
+" "
+msgstr ""
+
+#. module: pallet_delivery
+#: model:ir.model,name:pallet_delivery.model_purchase_order_line
+msgid "Purchase Order Line"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:stock.truck,back_temperature:0
+msgid "Back Temperature"
+msgstr ""
+
+#. module: pallet_delivery
+#: model:ir.model,name:pallet_delivery.model_stock_picking_in
+msgid "Incoming Shipments"
+msgstr ""
+
+#. module: pallet_delivery
+#: model:ir.model,name:pallet_delivery.model_stock_truck_line
+msgid "A single pallet shipped in an incoming truck"
+msgstr ""
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+#: field:stock.truck.line,crates:0
+msgid "Crates"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:stock.truck.line,pallet:0
+msgid "Pallet"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:stock.truck,state:0
+msgid "State"
+msgstr ""
+
+#. module: pallet_delivery
+#: model:ir.model,name:pallet_delivery.model_stock_truck
+msgid "Incoming truck"
+msgstr ""
+
+#. module: pallet_delivery
+#: selection:stock.truck,state:0
+msgid "Draft"
+msgstr ""
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Details"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:stock.truck,front_temperature:0
+msgid "Front Temperature"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:stock.truck,supplier:0
+msgid "Supplier"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:purchase.order,hidden:0
+msgid "Hidden"
+msgstr ""
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Truck Composition"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:purchase.order,assigned:0
+msgid "unknown"
+msgstr ""
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Confirm"
+msgstr ""
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Serial Number"
+msgstr ""
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Right Pallets"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:stock.truck,left_pallet_ids:0
+#: field:stock.truck,right_pallet_ids:0
+msgid "Pallets"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:stock.truck,truck_sn:0
+msgid "Truck S/N"
+msgstr ""
+
+#. module: pallet_delivery
+#: code:addons/pallet_delivery/stock.py:293
+#, python-format
+msgid "Input Error !"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:stock.truck,name:0
+#: field:stock.truck.line,name:0
+msgid "Name"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:purchase.order,stock_truck_ids:0
+msgid "Trucks"
+msgstr ""
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Search Truck"
+msgstr ""
+
+#. module: pallet_delivery
+#: model:ir.model,name:pallet_delivery.model_purchase_order
+msgid "Purchase Order"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:stock.truck,arrival:0
+msgid "Date of Arrival"
+msgstr ""
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+#: field:stock.truck.line,left_id:0
+#: field:stock.truck.line,right_id:0
+msgid "Truck"
+msgstr ""
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Left Pallets"
+msgstr ""
+
+#. module: pallet_delivery
+#: model:ir.actions.act_window,help:pallet_delivery.purchase_order_hidden
+msgid "<p class=\"oe_view_nocontent_create\">\n"
+" Click to create a quotation that will be converted into a purchase order. \n"
+" </p><p>\n"
+" Use this menu to search within your purchase orders by\n"
+" references, supplier, products, etc. For each purchase order,\n"
+" you can track the related discussion with the supplier, control\n"
+" the products received and control the supplier invoices.\n"
+" </p>\n"
+" "
+msgstr ""
+
+#. module: pallet_delivery
+#: model:ir.actions.act_window,name:pallet_delivery.action_truck_pending
+msgid "On Draft Truck"
+msgstr ""
+
+#. module: pallet_delivery
+#: code:addons/pallet_delivery/stock.py:294
+#, python-format
+msgid "Please enter real numbers."
+msgstr ""
+
+#. module: pallet_delivery
+#: model:ir.model,name:pallet_delivery.model_stock_move
+msgid "Stock Move"
+msgstr ""
+
+#. module: pallet_delivery
+#: model:ir.ui.menu,name:pallet_delivery.menu_truck_purchase
+#: model:ir.ui.menu,name:pallet_delivery.menu_truck_stock
+msgid "Incoming Truck"
+msgstr ""
+
+#. module: pallet_delivery
+#: selection:stock.truck,state:0
+msgid "Done"
+msgstr ""
+
+#. module: pallet_delivery
+#: model:ir.actions.act_window,name:pallet_delivery.purchase_order_hidden
+#: view:stock.truck:0
+#: field:stock.truck,purchase_order_ids:0
+msgid "Purchase Orders"
+msgstr ""
+
=== added file 'pallet_delivery/pallet_delivery_data.xml'
--- pallet_delivery/pallet_delivery_data.xml 1970-01-01 00:00:00 +0000
+++ pallet_delivery/pallet_delivery_data.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data noupdate="1">
+ <record id="pallet_delivery_external_po" model="purchase.order">
+ <field name="partner_id">1</field>
+ <field name="location_id">8</field>
+ <field name="state">cancel</field>
+ <field name="pricelist_id" ref="purchase.list0"/>
+ <field name="hidden">1</field>
+ </record>
+
+ <record id="pallet_delivery_external_line" model="purchase.order.line">
+ <field name="product_uom">1</field>
+ <field name="order_id" ref="pallet_delivery_external_po" />
+ <field name="price_unit">1</field>
+ <field name="name">Not ours</field>
+ <field name="date_planned">2013-01-01</field>
+ <field name="state">confirmed</field>
+ <field name="nb_pallets">1</field>
+ <field name="nb_crates_per_pallet">1</field>
+ </record>
+
+ <record id="seq_type_stock_truck" model="ir.sequence.type">
+ <field name="name">Truck</field>
+ <field name="code">stock.truck</field>
+ </record>
+
+ <record id="seq_stock_truck" model="ir.sequence">
+ <field name="name">Truck</field>
+ <field name="code">stock.truck</field>
+ <field name="prefix">TRK</field>
+ <field name="padding">5</field>
+ </record>
+ </data>
+</openerp>
=== added file 'pallet_delivery/pallet_delivery_view.xml'
--- pallet_delivery/pallet_delivery_view.xml 1970-01-01 00:00:00 +0000
+++ pallet_delivery/pallet_delivery_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <!-- Purchase Order -->
+ <record id="purchase_order_hidden" model="ir.actions.act_window">
+ <field name="name">Purchase Orders</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">purchase.order</field>
+ <field name="view_mode">tree,form,graph,calendar</field>
+ <field name="context">{}</field>
+ <field name="domain">['&', ('state','not in',('draft','sent','confirmed')), ('hidden', '!=', True)]</field>
+ <field name="search_view_id" ref="purchase.view_purchase_order_filter"/>
+ <field name="help" type="html">
+ <p class="oe_view_nocontent_create">
+ Click to create a quotation that will be converted into a purchase order.
+ </p><p>
+ Use this menu to search within your purchase orders by
+ references, supplier, products, etc. For each purchase order,
+ you can track the related discussion with the supplier, control
+ the products received and control the supplier invoices.
+ </p>
+ </field>
+ </record>
+
+ <menuitem
+ id="purchase.menu_purchase_form_action"
+ action="purchase_order_hidden"
+ parent="purchase.menu_procurement_management"
+ sequence="6" />
+
+ <!-- Truck -->
+ <record id="truck_tree" model="ir.ui.view">
+ <field name="name">stock.truck.tree</field>
+ <field name="model">stock.truck</field>
+ <field name="arch" type="xml">
+ <tree string="Truck">
+ <field name="name" />
+ <field name="truck_sn" />
+ <field name="supplier" />
+ <field name="arrival" />
+ </tree>
+ </field>
+ </record>
+
+ <record id="truck_form" model="ir.ui.view">
+ <field name="name">stock.truck.form</field>
+ <field name="model">stock.truck</field>
+ <field eval="1" name="priority" />
+ <field name="arch" type="xml">
+ <form string="Truck" version="7.0">
+ <header>
+ <button
+ name="action_done"
+ type="object"
+ states="draft"
+ string="Confirm"
+ class="oe_highlight" />
+
+ <field
+ name="state"
+ widget="statusbar"
+ statusbar_visible="draft,done"
+ statusbar_colors='{"draft":"blue","done":"blue"}' />
+ </header>
+
+ <sheet>
+ <group>
+ <group name="pedigree" string="Details" colspan="4" col="4">
+ <group>
+ <field name="truck_sn" />
+ <field name="supplier" />
+ <field name="arrival" on_change="onchange_arrival(arrival)" />
+ </group>
+
+ <group>
+ <field name="front_temperature" on_change="validate_temperature(front_temperature, 'front_temperature')" />
+ <field name="back_temperature" on_change="validate_temperature(back_temperature, 'back_temperature')" />
+ </group>
+ </group>
+
+ <group name="purchase_orders" string="Purchase Orders" colspan="4">
+ <field name="purchase_order_ids" nolabel="1" domain="[('state', 'not in', ['draft', 'done']), ('assigned', '=', True)]">
+ <tree>
+ <field name="name" />
+ </tree>
+ </field>
+ </group>
+
+ <group name="pallets" string="Truck Composition" colspan="4">
+ <group>
+ <field name="left_pallet_ids" nolabel="1">
+ <tree editable="bottom">
+ <field name="pallet" string="Left Pallets" context="{'nice':'nice','parent':parent}" />
+ <field name="crates" string="Crates" />
+ </tree>
+ </field>
+ </group>
+
+ <group>
+ <field name="right_pallet_ids" nolabel="1">
+ <tree editable="bottom">
+ <field name="pallet" string="Right Pallets" context="{'nice':'nice','parent':parent}" />
+ <field name="crates" string="Crates" />
+ </tree>
+ </field>
+ </group>
+ </group>
+ </group>
+ </sheet>
+ </form>
+ </field>
+ </record>
+
+ <record id="view_truck_filter" model="ir.ui.view">
+ <field name="name">stock.truck.select</field>
+ <field name="model">stock.truck</field>
+ <field name="arch" type="xml">
+ <search string="Search Truck">
+ <field name="truck_sn" string="Serial Number" filter_domain="[('truck_sn', '=', self)]" />
+ </search>
+ </field>
+ </record>
+
+ <!-- Menu -->
+ <record id="action_truck_pending" model="ir.actions.act_window">
+ <field name="name">On Draft Truck</field>
+ <field name="res_model">stock.truck</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ <field eval="False" name="view_id" />
+ <field name="search_view_id" ref="pallet_delivery.view_truck_filter" />
+ <field name="help" type="html">
+ <p class="oe_view_nocontent_create">Click to create a draft truck</p>
+
+ <p>The truck contains an incoming, physical shipment. With it you can
+ register the truck's details, such as its serial number, sampled
+ temperatures, and other information. Also, the truck serves you as a
+ map of what your company received.</p>
+
+ <p>When you confirm the truck, it will act as an “Incoming Shipment”
+ confirmation, and the products will be moved from your Suppliers (as
+ listed in Purchase Orders) to your Stock.</p>
+ </field>
+ </record>
+
+ <menuitem
+ name="Incoming Truck"
+ id="menu_truck_purchase"
+ action="action_truck_pending"
+ parent="purchase.menu_procurement_management_inventory"
+ sequence="8" />
+
+ <menuitem
+ name="Incoming Truck"
+ id="menu_truck_stock"
+ action="action_truck_pending"
+ parent="stock.menu_stock_warehouse_mgmt"
+ sequence="0" />
+ </data>
+</openerp>
=== added directory 'pallet_delivery/security'
=== added file 'pallet_delivery/security/ir.model.access.csv'
--- pallet_delivery/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ pallet_delivery/security/ir.model.access.csv 2014-11-23 23:06:46 +0000
@@ -0,0 +1,5 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_stock_truck_stock,stock.truck all,model_stock_truck,stock.group_stock_user,1,1,1,1
+access_stock_truck_purchase,stock.truck all,model_stock_truck,purchase.group_purchase_user,1,1,1,1
+access_stock_truck_line_stock,stock.truck.line all,model_stock_truck_line,stock.group_stock_user,1,1,1,1
+access_stock_truck_line_purchase,stock.truck.line all,model_stock_truck_line,purchase.group_purchase_user,1,1,1,1
=== added file 'pallet_delivery/stock.py'
--- pallet_delivery/stock.py 1970-01-01 00:00:00 +0000
+++ pallet_delivery/stock.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,310 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from collections import defaultdict
+from openerp.tools.translate import _
+from openerp.osv import orm, fields
+
+def group(lst):
+ """Saner group function than the one found in itertools
+
+ This one mimics Haskell's group from Data.List:
+ group :: Eq a => [a] -> [[a]]
+ """
+
+ if not lst:
+ return []
+
+ res = []
+ current = lst[0]
+
+ grp = []
+ for x in lst:
+ if x != current:
+ res.append(grp)
+ grp = []
+ grp.append(x)
+ current = x
+
+ if grp:
+ res.append(grp)
+
+ return res
+
+
+class stock_move(orm.Model):
+
+ _inherit = 'stock.move'
+
+ def _find_hidden(self, cr, uid, ids, context=None):
+ po_pool = self.pool.get("purchase.order")
+ hidden_id = po_pool.search(cr, uid, [('hidden', '=', True)], context=context)[0]
+ return po_pool.browse(cr, uid, hidden_id, context)
+
+ @staticmethod
+ def _unique_line(seq):
+ seen = set()
+ seen_add = seen.add
+ return [ x for x in seq if x not in seen and not seen_add(x)]
+
+ @staticmethod
+ def _get_line_name(line, crates=None, force_total_qty=False):
+ available = None
+ nice = '%s' % line.product_id.name
+ incoming_crates = line.product_qty
+ if crates:
+ # Incoming crates
+ available = max(0, incoming_crates - crates[line.id])
+ elif force_total_qty:
+ available = incoming_crates
+
+ nice += " / %s" % line.prodlot_id.name
+
+ if available is not None:
+ nice += " (%d)" % available
+
+ return nice, available
+
+ def name_get(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+
+ if isinstance(ids, (int, long)):
+ ids = [ids]
+
+ stl_pool = self.pool.get('stock.truck.line')
+ spi_pool = self.pool.get('stock.picking.in')
+ # Out from selection; display name
+
+ #hidden = self._find_hidden(cr, uid, ids, context=context)
+ res = []
+ if not context.has_key('nice'):
+ for line in self.browse(cr, uid, ids, context=context):
+ name, available = self._get_line_name(line)
+ res.append((line.id, name))
+
+ # Add special 'not ours' line
+ #res.append((hidden.id, hidden.name))
+ return res
+
+ # Doing a selection
+ # Add special 'not ours' line
+ #res.append((hidden.id, hidden.name))
+
+ # Retrieve entered form data
+ parent = context['parent']
+ all_pallets = parent['left_pallet_ids'] + parent['right_pallet_ids']
+ po_ids = parent['purchase_order_ids'][0][2]
+
+ # find list of stock picking in
+ spi_ids = spi_pool.search(cr, uid, [('purchase_id', '=', po_ids)],
+ context=context)
+
+ # Build crate structure
+ crates = defaultdict(lambda: 0)
+ for pallet_struct in all_pallets:
+ if pallet_struct[0] == 4:
+ st_line = stl_pool.browse(cr, uid, pallet_struct[1],
+ context=context)
+ crates[st_line.pallet.id] += st_line.crates
+ else:
+ fields = pallet_struct[2]
+ if fields and 'pallet' in fields:
+ crates[fields['pallet']] += fields['crates']
+
+ spi_lines = spi_pool.browse(cr, uid, spi_ids, context=context)
+ all_lines = [line for lines in spi_lines for line in lines.move_lines
+ if line.state == "assigned"]
+ move_line = self._unique_line(all_lines)
+
+ # Prettify data to be displayed
+ for line in move_line:
+ force_total_qty = not crates
+ name, available = self._get_line_name(line, crates=crates,
+ force_total_qty=force_total_qty)
+ if available:
+ res.append((line.id, name))
+
+ return res
+
+
+class purchase_order(orm.Model):
+
+ _inherit = 'purchase.order'
+
+ def _assigned(self, cr, uid, obj, name, args, context=None):
+ '''Domain filter on corresponding entries in stock.picking where state is assigned'''
+
+ if context is None:
+ context = {}
+
+ picking_pool = self.pool.get('stock.picking')
+ ids = picking_pool.search(cr, uid, [('state', '=', 'assigned')], context=context)
+ po_ids = [po.purchase_id.id for po in picking_pool.browse(cr, uid, ids, context=context)]
+
+ return [('id', 'in', po_ids)]
+
+ _columns = {
+ 'hidden': fields.boolean('Hidden'),
+ 'stock_truck_ids': fields.many2many(
+ 'stock.truck', 'truck_order_rel', 'order_id', 'truck_id', 'Trucks'),
+ 'assigned': fields.function(lambda **x: True, fnct_search=_assigned, type='boolean', method=True),
+ }
+
+
+class stock_truck_line(orm.Model):
+
+ _name = 'stock.truck.line'
+ _description = 'A single pallet shipped in an incoming truck'
+
+ _columns = {
+ 'name': fields.char('Name', size=64),
+ 'left_id': fields.many2one('stock.truck', 'Truck'),
+ 'right_id': fields.many2one('stock.truck', 'Truck'),
+ 'pallet': fields.many2one('stock.move', 'Pallet', required=True),
+ 'crates': fields.integer('Crates', required=True),
+ }
+
+
+class stock_truck(orm.Model):
+
+ _name = 'stock.truck'
+ _description = 'Incoming truck'
+
+ def onchange_arrival(self, cr, uid, ids, arrival, context=None):
+ '''Force seconds to zero'''
+
+ arrival = arrival[:-2] + '00'
+
+ return {'value': {'arrival': arrival}}
+
+ def action_done(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+
+ truck = self.browse(cr, uid, ids, context=context)[0]
+
+ # Build a dictionary of:
+ # - key: Purchase Order
+ # - value: a dictionary of:
+ # - key: Lot Number
+ # - value: tuple of
+ # - Purchase Order Line
+ # - Crate count
+ products = defaultdict(dict)
+
+ def _process_pallets(column):
+ for line in column:
+ pallet = line.pallet
+ pi = pallet.picking_id
+ po = pallet.purchase_line_id.order_id
+ lot = pallet.prodlot_id if pallet.prodlot_id else None
+ # Skip over fake 'not ours' line
+ if po and po.hidden:
+ continue
+
+ if not products[pi.id].has_key(lot):
+ products[pi.id][lot] = (pallet, 0)
+
+ lot_product = products[pi.id][lot]
+ count = lot_product[1]
+ products[pi.id][lot] = (lot_product[0], count + line.crates)
+
+ _process_pallets(truck.left_pallet_ids)
+ _process_pallets(truck.right_pallet_ids)
+
+ # Make the calls to the Pickings stock moves
+
+ picking_pool = self.pool.get('stock.picking')
+
+ for po in truck.purchase_order_ids:
+ pi = None
+ pi_ids = picking_pool.search(
+ cr, uid,
+ ['&', ('purchase_id', '=', po.id), ('state', '=', 'assigned')],
+ context=context)
+ if pi_ids:
+ # take the last one
+ pi = pi_ids[-1]
+
+ if not pi or not products.has_key(pi):
+ # Purchase Order was added to the list, but there are not
+ # pallets pertaining to that PO.
+ continue
+
+ partial_data = {'delivery_date': truck.arrival}
+
+
+ for move_line, count in products[pi].values():
+ # Skip over the fake 'not ours' line
+ po_line = move_line.purchase_line_id
+ if po_line and po_line.order_id.hidden:
+ continue
+
+ partial_data['move%s' % (move_line.id, )] = {
+ 'product_id': move_line.product_id.id,
+ 'product_qty': count,
+ 'product_uom': 1,
+ 'prodlot_id': move_line.prodlot_id.id,
+ }
+
+ picking_pool.do_partial(cr, uid, [pi], partial_data, context=context)
+
+ self.write(cr, uid, ids, {'state': 'done'})
+
+ return True
+
+ @staticmethod
+ def validate_temperature(cr, uid, ids, temperature, field_name,
+ context=None):
+ try:
+ float(temperature)
+ except ValueError:
+ warning = {'title': _('Input Error !'),
+ 'message': _('Please enter real numbers.')}
+ return {'value': {field_name: ""}, 'warning': warning}
+ return True
+
+ _columns = {
+ # Overhead
+ 'name': fields.char('Name', size=64),
+ 'state': fields.selection([
+ ('draft', 'Draft'),
+ ('done', 'Done'),
+ ], 'State', readonly=True, select=True, track_visibility='onchange'),
+
+ # Display
+ 'front_temperature': fields.char('Front Temperature', required=True),
+ 'back_temperature': fields.char('Back Temperature', required=True),
+ 'truck_sn': fields.char('Truck S/N', size=64),
+ 'supplier': fields.many2one('res.partner', 'Supplier', required=True),
+ 'arrival': fields.datetime('Date of Arrival', required=True),
+ 'purchase_order_ids': fields.many2many(
+ 'purchase.order', 'truck_order_rel', 'truck_id', 'order_id', 'Purchase Orders'),
+ 'left_pallet_ids': fields.one2many('stock.truck.line', 'left_id', 'Pallets'),
+ 'right_pallet_ids': fields.one2many('stock.truck.line', 'right_id', 'Pallets'),
+ }
+
+ _defaults = {
+ 'name': lambda self, cr, uid, ctx={}: self.pool.get('ir.sequence').get(cr, uid, 'stock.truck'),
+ 'state': 'draft',
+ 'front_temperature': None,
+ }
=== added file 'pallet_delivery/stock_workflow.xml'
--- pallet_delivery/stock_workflow.xml 1970-01-01 00:00:00 +0000
+++ pallet_delivery/stock_workflow.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="wkf_stock_truck" model="workflow">
+ <field name="name">stock.truck</field>
+ <field name="osv">stock.truck</field>
+ <field name="on_create">True</field>
+ </record>
+
+ <record id="act_draft" model="workflow.activity">
+ <field name="wkf_id" ref="wkf_stock_truck" />
+ <field name="name">draft</field>
+ <field name="flow_start">True</field>
+ </record>
+
+ <record id="act_done" model="workflow.activity">
+ <field name="wkf_id" ref="wkf_stock_truck" />
+ <field name="name">done</field>
+ <field name="flow_stop">True</field>
+ <field name="kind">function</field>
+ <field name="action">action_done()</field>
+ </record>
+
+ <record id="trans_draft_done" model="workflow.transition">
+ <field name="act_from" ref="act_draft" />
+ <field name="act_to" ref="act_done" />
+ <field name="signal">button_done</field>
+ </record>
+ </data>
+</openerp>
=== added directory 'partner_discount'
=== added file 'partner_discount/__init__.py'
--- partner_discount/__init__.py 1970-01-01 00:00:00 +0000
+++ partner_discount/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###############################################################################
+
+import res_partner
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'partner_discount/__openerp__.py'
--- partner_discount/__openerp__.py 1970-01-01 00:00:00 +0000
+++ partner_discount/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,41 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###############################################################################
+
+{
+ 'name': 'Partner Discount',
+ 'version': '1.0',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'sale',
+ 'description': """\
+Adds a discount percentage to the partner form.
+""",
+ 'depends': [],
+ 'data': ['res_partner_view.xml'],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added directory 'partner_discount/i18n'
=== added file 'partner_discount/i18n/fr.po'
--- partner_discount/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ partner_discount/i18n/fr.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,36 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * partner_discount
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-11-01 15:41+0000\n"
+"PO-Revision-Date: 2013-11-01 15:41+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: partner_discount
+#: field:res.partner,discount:0
+msgid "Discount"
+msgstr "Ristourne"
+
+#. module: partner_discount
+#: help:res.partner,discount:0
+msgid "For percent enter a ratio between 0-1."
+msgstr "Pour être en pourcentage, saisir une valeur entre 0 et 1."
+
+#. module: partner_discount
+#: view:res.partner:0
+msgid "Sales & Purchases"
+msgstr "Achats-Ventes"
+
+#. module: partner_discount
+#: model:ir.model,name:partner_discount.model_res_partner
+msgid "Partner"
+msgstr "Partenaire"
=== added file 'partner_discount/i18n/partner_discount.pot'
--- partner_discount/i18n/partner_discount.pot 1970-01-01 00:00:00 +0000
+++ partner_discount/i18n/partner_discount.pot 2014-11-23 23:06:46 +0000
@@ -0,0 +1,36 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * partner_discount
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-11-01 15:41+0000\n"
+"PO-Revision-Date: 2013-11-01 15:41+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: partner_discount
+#: field:res.partner,discount:0
+msgid "Discount"
+msgstr ""
+
+#. module: partner_discount
+#: help:res.partner,discount:0
+msgid "For percent enter a ratio between 0-1."
+msgstr ""
+
+#. module: partner_discount
+#: view:res.partner:0
+msgid "Sales & Purchases"
+msgstr ""
+
+#. module: partner_discount
+#: model:ir.model,name:partner_discount.model_res_partner
+msgid "Partner"
+msgstr ""
=== added file 'partner_discount/res_partner.py'
--- partner_discount/res_partner.py 1970-01-01 00:00:00 +0000
+++ partner_discount/res_partner.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,36 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###############################################################################
+
+from openerp.osv import orm, fields
+
+
+class res_partner(orm.Model):
+ """ Inherits partner and adds discount percentage """
+ _inherit = 'res.partner'
+ _columns = {
+ 'discount': fields.float('Discount', digits=(1, 4),
+ help="For percent enter a ratio between 0-1."),
+ }
+ _defaults = {'discount': 0.0}
+
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'partner_discount/res_partner_view.xml'
--- partner_discount/res_partner_view.xml 1970-01-01 00:00:00 +0000
+++ partner_discount/res_partner_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,19 @@
+<?xml version = "1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="view_partner_discount_form" model="ir.ui.view">
+ <field name="name">res.partner.discount.form.inherit</field>
+ <field name="model">res.partner</field>
+ <field name="inherit_id" ref="base.view_partner_form"/>
+ <field name="arch" type="xml">
+ <page string="Sales & Purchases">
+ <group>
+ <group>
+ <field name="discount"/>
+ </group>
+ </group>
+ </page>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'produce_details'
=== added file 'produce_details/__init__.py'
--- produce_details/__init__.py 1970-01-01 00:00:00 +0000
+++ produce_details/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import product
=== added file 'produce_details/__openerp__.py'
--- produce_details/__openerp__.py 1970-01-01 00:00:00 +0000
+++ produce_details/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Produce Details',
+ 'version': '0.1',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'product',
+ 'description': """
+Agricultural produce details
+============================
+
+This module adds four descriptive fields for produce-related products, namely:
+
+* A variety (e.g. Haden)
+* An origin (Brazil)
+* Conditioning weight (10 kg)
+* A size category (#12)
+* PLU code (4216)
+""",
+ 'depends': ['base', 'purchase'],
+ 'data': [
+ 'produce_details_view.xml',
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added directory 'produce_details/i18n'
=== added file 'produce_details/i18n/fr.po'
--- produce_details/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ produce_details/i18n/fr.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,41 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * produce_details
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:22+0000\n"
+"PO-Revision-Date: 2013-09-18 14:22+0000\n"
+"Last-Translator: Alexandre Boily <alexandre.boily@xxxxxxxxxxxxxxxxxxxx>\n"
+"Language-Team: Savoir-faire Linux\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: produce_details
+#: field:product.product,origin:0
+msgid "Origin"
+msgstr "Origine"
+
+#. module: produce_details
+#: model:ir.model,name:produce_details.model_product_product
+msgid "Product"
+msgstr "Produit"
+
+#. module: produce_details
+#: field:product.product,variety:0
+msgid "Variety"
+msgstr "Variété"
+
+#. module: produce_details
+#: field:product.product,cond_weight:0
+msgid "Conditioning weight"
+msgstr "Poids de conditionnement"
+
+#. module: produce_details
+#: field:product.product,size_category:0
+msgid "Size"
+msgstr "Taille"
=== added file 'produce_details/i18n/produce_details.pot'
--- produce_details/i18n/produce_details.pot 1970-01-01 00:00:00 +0000
+++ produce_details/i18n/produce_details.pot 2014-11-23 23:06:46 +0000
@@ -0,0 +1,42 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * produce_details
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:22+0000\n"
+"PO-Revision-Date: 2013-09-18 14:22+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: produce_details
+#: field:product.product,origin:0
+msgid "Origin"
+msgstr ""
+
+#. module: produce_details
+#: model:ir.model,name:produce_details.model_product_product
+msgid "Product"
+msgstr ""
+
+#. module: produce_details
+#: field:product.product,variety:0
+msgid "Variety"
+msgstr ""
+
+#. module: produce_details
+#: field:product.product,cond_weight:0
+msgid "Conditioning weight"
+msgstr ""
+
+#. module: produce_details
+#: field:product.product,size_category:0
+msgid "Size"
+msgstr ""
+
=== added file 'produce_details/produce_details_view.xml'
--- produce_details/produce_details_view.xml 1970-01-01 00:00:00 +0000
+++ produce_details/produce_details_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<openerp>
+ <data>
+ <record id="produce_details_form" model="ir.ui.view">
+ <field name="name">product.product.produce.details.form</field>
+ <field name="model">product.product</field>
+ <field name="inherit_id" ref="product.product_normal_form_view" />
+ <field name="arch" type="xml">
+ <field name="description" position="before">
+ <group>
+ <group>
+ <field name="variety" />
+ <field name="origin" />
+ </group>
+
+ <group>
+ <field name="cond_weight" />
+ <field name="size_category" />
+ </group>
+ </group>
+ <group>
+ <group>
+ <label for="plu1"/>
+ <field name="plu1" nolabel="1" />
+ <div />
+ <field name="plu2" nolabel="1" />
+ </group>
+ <group/>
+ </group>
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added file 'produce_details/product.py'
--- produce_details/product.py 1970-01-01 00:00:00 +0000
+++ produce_details/product.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import openerp.addons.decimal_precision as dp
+from openerp.osv import orm, fields
+
+class product_product(orm.Model):
+
+ _inherit = 'product.product'
+
+ _columns = {
+ 'variety': fields.char('Variety', size=64),
+ 'origin': fields.many2one('res.country', 'Origin'),
+ 'cond_weight': fields.float('Conditioning weight', digits_compute=dp.get_precision('Stock Weight'), help='Conditioning weight in kg.'),
+ 'size_category': fields.char('Size', size=16),
+ 'plu1': fields.char('PLU', size=8),
+ 'plu2': fields.char('PLU2', size=8),
+ }
=== added directory 'product_reserve_forecast'
=== added file 'product_reserve_forecast/__init__.py'
--- product_reserve_forecast/__init__.py 1970-01-01 00:00:00 +0000
+++ product_reserve_forecast/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import product
+import sale_stock
=== added file 'product_reserve_forecast/__openerp__.py'
--- product_reserve_forecast/__openerp__.py 1970-01-01 00:00:00 +0000
+++ product_reserve_forecast/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Reserve Product Quantity on Forecast',
+ 'version': '0.1',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'product',
+ 'description': """
+Put aside an unsaleable quantity for a product
+==============================================
+
+This reduces the forecasted quantity by a given amount.
+""",
+ 'depends': ['base', 'product', 'sale', 'sale_stock', 'stock'],
+ 'data': [
+ 'security/product_reserve_forecast_security.xml',
+ 'product_reserve_forecast_view.xml',
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added directory 'product_reserve_forecast/i18n'
=== added file 'product_reserve_forecast/i18n/fr.po'
--- product_reserve_forecast/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ product_reserve_forecast/i18n/fr.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,67 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * product_reserve_forecast
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-26 11:42+0000\n"
+"PO-Revision-Date: 2013-09-26 11:42+0000\n"
+"Last-Translator: Alexandre Boily <alexandre.boily@xxxxxxxxxxxxxxxxxxxx>\n"
+"Language-Team: Savoir-faire Linux\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: product_reserve_forecast
+#: field:product.product,virtual_clone:0
+msgid "Forecasted Quantity"
+msgstr "Quantité prévue"
+
+#. module: product_reserve_forecast
+#: model:ir.model,name:product_reserve_forecast.model_product_product
+msgid "Product"
+msgstr "Produit"
+
+#. module: product_reserve_forecast
+#: code:addons/product_reserve_forecast/sale_stock.py:85
+#, python-format
+msgid "Not enough stock ! : "
+msgstr "Pas assez de stock: "
+
+#. module: product_reserve_forecast
+#: code:addons/product_reserve_forecast/sale_stock.py:81
+#, python-format
+msgid "You plan to sell %.2f %s but you only have %.2f %s available !\n"
+"The real stock is %.2f %s. (without reservations)"
+msgstr "Vous planifiez vendre %.2f %s, mais seulement %.2f %s sont disponibles.
+La vraie quantité en stock est %.2f %s (sans réservations)."
+
+#. module: product_reserve_forecast
+#: model:res.groups,name:product_reserve_forecast.group_product_reserve
+msgid "Define product reserve quantity"
+msgstr "Définir la quantié réservée sur un produit"
+
+#. module: product_reserve_forecast
+#: code:addons/product_reserve_forecast/sale_stock.py:90
+#, python-format
+msgid "Configuration Error!"
+msgstr "Erreur de configuration!"
+
+#. module: product_reserve_forecast
+#: field:product.product,reserved:0
+msgid "Reserved Quantity"
+msgstr "Quantité réservée"
+
+#. module: product_reserve_forecast
+#: model:ir.model,name:product_reserve_forecast.model_sale_order_line
+msgid "Sales Order Line"
+msgstr "Ligne de vente"
+
+#. module: product_reserve_forecast
+#: model:res.groups,comment:product_reserve_forecast.group_product_reserve
+msgid "Can see and set the per product reserve quantity."
+msgstr "Peut voir et modifier la quantité réservée d'un produit."
+
=== added file 'product_reserve_forecast/i18n/product_reserve_forecast.pot'
--- product_reserve_forecast/i18n/product_reserve_forecast.pot 1970-01-01 00:00:00 +0000
+++ product_reserve_forecast/i18n/product_reserve_forecast.pot 2014-11-23 23:06:46 +0000
@@ -0,0 +1,66 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * product_reserve_forecast
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-26 11:42+0000\n"
+"PO-Revision-Date: 2013-09-26 11:42+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: product_reserve_forecast
+#: field:product.product,virtual_clone:0
+msgid "Forecasted Quantity"
+msgstr ""
+
+#. module: product_reserve_forecast
+#: model:ir.model,name:product_reserve_forecast.model_product_product
+msgid "Product"
+msgstr ""
+
+#. module: product_reserve_forecast
+#: code:addons/product_reserve_forecast/sale_stock.py:85
+#, python-format
+msgid "Not enough stock ! : "
+msgstr ""
+
+#. module: product_reserve_forecast
+#: code:addons/product_reserve_forecast/sale_stock.py:81
+#, python-format
+msgid "You plan to sell %.2f %s but you only have %.2f %s available !\n"
+"The real stock is %.2f %s. (without reservations)"
+msgstr ""
+
+#. module: product_reserve_forecast
+#: model:res.groups,name:product_reserve_forecast.group_product_reserve
+msgid "Define product reserve quantity"
+msgstr ""
+
+#. module: product_reserve_forecast
+#: code:addons/product_reserve_forecast/sale_stock.py:90
+#, python-format
+msgid "Configuration Error!"
+msgstr ""
+
+#. module: product_reserve_forecast
+#: field:product.product,reserved:0
+msgid "Reserved Quantity"
+msgstr ""
+
+#. module: product_reserve_forecast
+#: model:ir.model,name:product_reserve_forecast.model_sale_order_line
+msgid "Sales Order Line"
+msgstr ""
+
+#. module: product_reserve_forecast
+#: model:res.groups,comment:product_reserve_forecast.group_product_reserve
+msgid "Can see and set the per product reserve quantity."
+msgstr ""
+
=== added file 'product_reserve_forecast/product.py'
--- product_reserve_forecast/product.py 1970-01-01 00:00:00 +0000
+++ product_reserve_forecast/product.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import openerp.addons.decimal_precision as dp
+from openerp.osv import orm, fields
+
+class product_product(orm.Model):
+
+ _inherit = 'product.product'
+
+ def _virtual_available(self, cr, uid, ids, names, arg, context=None):
+ orig = self._product_available(cr, uid, ids, names, arg, context=context)
+ product_pool = self.pool.get('product.product')
+ for product_id in orig.keys():
+ reserved = product_pool.browse(cr, uid, product_id, context=context).reserved
+ orig[product_id]['virtual_available'] -= reserved
+
+ return orig
+
+ def _virtual_clone(self, cr, uid, ids, names, arg, context=None):
+ '''Small hack to get priority over the Stock module's virtual_available'''
+
+ res = {}
+
+ for line in self.browse(cr, uid, ids, context=context):
+ res[line.id] = line.virtual_available
+
+ return res
+
+ _columns = {
+ 'reserved': fields.integer('Reserved Quantity'),
+
+ 'virtual_clone':
+ fields.function(_virtual_clone, type='float',
+ digits_compute=dp.get_precision('Product Unit of Measure'), string='Forecasted Quantity'),
+
+ 'virtual_available': fields.function(_virtual_available, multi='qty_available',
+ type='float', digits_compute=dp.get_precision('Product Unit of Measure'),
+ string='Forecasted Quantity',
+ help="Forecast quantity (computed as Quantity On Hand "
+ "- Outgoing - Reserved + Incoming)\n"
+ "In a context with a single Stock Location, this includes "
+ "goods stored in this location, or any of its children.\n"
+ "In a context with a single Warehouse, this includes "
+ "goods stored in the Stock Location of this Warehouse, or any "
+ "of its children.\n"
+ "In a context with a single Shop, this includes goods "
+ "stored in the Stock Location of the Warehouse of this Shop, "
+ "or any of its children.\n"
+ "Otherwise, this includes goods stored in any Stock Location "
+ "with 'internal' type."),
+ }
=== added file 'product_reserve_forecast/product_reserve_forecast_view.xml'
--- product_reserve_forecast/product_reserve_forecast_view.xml 1970-01-01 00:00:00 +0000
+++ product_reserve_forecast/product_reserve_forecast_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf8" ?>
+<openerp>
+ <data>
+ <record id="product_reserve_forecast_form" model="ir.ui.view">
+ <field name="name">product.product.reserve.form</field>
+ <field name="model">product.product</field>
+ <field name="inherit_id" ref="stock.view_normal_procurement_locations_form" />
+ <field name="arch" type="xml">
+ <field name="virtual_available" position="replace">
+ <field name="virtual_clone" />
+ <field name="reserved" groups="product_reserve_forecast.group_product_reserve" />
+ </field>
+ </field>
+ </record>
+
+ <record id="product_reserve_forecast_tree" model="ir.ui.view">
+ <field name="name">product.product.reserve.tree</field>
+ <field name="model">product.product</field>
+ <field name="inherit_id" ref="product.product_product_tree_view" />
+ <field name="arch" type="xml">
+ <field name="virtual_available" position="replace">
+ <field name="virtual_available" invisible="1" />
+ <field name="virtual_clone" />
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added file 'product_reserve_forecast/sale_stock.py'
--- product_reserve_forecast/sale_stock.py 1970-01-01 00:00:00 +0000
+++ product_reserve_forecast/sale_stock.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import fields, orm
+from openerp.tools import float_compare
+from openerp.tools.translate import _
+
+class sale_order_line(orm.Model):
+
+ _inherit = 'sale.order.line'
+
+ 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):
+ '''Slightly tweaked copy from sale_stock
+
+ The only difference resides in the way the compare_qty is computed: in
+ this implementation, take into account the product's reserved quantity.
+ '''
+
+ context = context or {}
+ product_uom_obj = self.pool.get('product.uom')
+ partner_obj = self.pool.get('res.partner')
+ product_obj = self.pool.get('product.product')
+ warning = {}
+ res = super(sale_order_line, self).product_id_change(cr, uid, ids, pricelist, product, qty=qty,
+ uom=uom, qty_uos=qty_uos, uos=uos, name=name, partner_id=partner_id,
+ lang=lang, update_tax=update_tax, date_order=date_order, packaging=packaging, fiscal_position=fiscal_position, flag=flag, context=context)
+
+ if not product:
+ res['value'].update({'product_packaging': False})
+ return res
+
+ #update of result obtained in super function
+ product_obj = product_obj.browse(cr, uid, product, context=context)
+ res['value']['delay'] = (product_obj.sale_delay or 0.0)
+ res['value']['type'] = product_obj.procure_method
+
+ #check if product is available, and if not: raise an error
+ uom2 = False
+ if uom:
+ uom2 = product_uom_obj.browse(cr, uid, uom)
+ if product_obj.uom_id.category_id.id != uom2.category_id.id:
+ uom = False
+ if not uom2:
+ uom2 = product_obj.uom_id
+
+ # Calling product_packaging_change function after updating UoM
+ res_packing = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context)
+ res['value'].update(res_packing.get('value', {}))
+ warning_msgs = res_packing.get('warning') and res_packing['warning']['message'] or ''
+
+ # Original comparison did not substract reserved quantity
+ avail = product_obj.virtual_available - product_obj.reserved
+ compare_qty = float_compare(
+ avail * uom2.factor,
+ qty * product_obj.uom_id.factor,
+ precision_rounding=product_obj.uom_id.rounding)
+
+ if (product_obj.type=='product') and int(compare_qty) == -1 \
+ and (product_obj.procure_method=='make_to_stock'):
+ warn_msg = _('You plan to sell %.2f %s but you only have %.2f %s available !\nThe real stock is %.2f %s. (without reservations)') % \
+ (qty, uom2 and uom2.name or product_obj.uom_id.name,
+ max(0,product_obj.virtual_available), product_obj.uom_id.name,
+ max(0,product_obj.qty_available), product_obj.uom_id.name)
+ warning_msgs += _("Not enough stock ! : ") + warn_msg + "\n\n"
+
+ #update of warning messages
+ if warning_msgs:
+ warning = {
+ 'title': _('Configuration Error!'),
+ 'message' : warning_msgs
+ }
+ res.update({'warning': warning})
+ return res
=== added directory 'product_reserve_forecast/security'
=== added file 'product_reserve_forecast/security/ir.model.access.csv'
--- product_reserve_forecast/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ product_reserve_forecast/security/ir.model.access.csv 2014-11-23 23:06:46 +0000
@@ -0,0 +1,1 @@
+access_sale_order_warn,access_sale_order_warn,model_sale_order_warn,,1,1,1,1
=== added file 'product_reserve_forecast/security/product_reserve_forecast_security.xml'
--- product_reserve_forecast/security/product_reserve_forecast_security.xml 1970-01-01 00:00:00 +0000
+++ product_reserve_forecast/security/product_reserve_forecast_security.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<openerp>
+ <data>
+ <record id="group_product_reserve" model="res.groups">
+ <field name="name">Define product reserve quantity</field>
+ <field name="category_id" ref="base.module_category_hidden" />
+ <field name="comment">Can see and set the per product reserve quantity.</field>
+ <field name="implied_ids" eval="[(4, ref('base.group_user'))]" />
+ </record>
+ </data>
+</openerp>
=== added directory 'purchase_delivery_term'
=== renamed directory 'purchase_delivery_term' => 'purchase_delivery_term.moved'
=== added file 'purchase_delivery_term/AUTHORS.txt'
--- purchase_delivery_term/AUTHORS.txt 1970-01-01 00:00:00 +0000
+++ purchase_delivery_term/AUTHORS.txt 2014-11-23 23:06:46 +0000
@@ -0,0 +1,1 @@
+Lorenzo Battistini <lorenzo.battistini@xxxxxxxxxxx>
=== added file 'purchase_delivery_term/__init__.py'
--- purchase_delivery_term/__init__.py 1970-01-01 00:00:00 +0000
+++ purchase_delivery_term/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2012-2013 Agile Business Group sagl
+# (<http://www.agilebg.com>)
+# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import purchase
=== added file 'purchase_delivery_term/__openerp__.py'
--- purchase_delivery_term/__openerp__.py 1970-01-01 00:00:00 +0000
+++ purchase_delivery_term/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2012-2013 Agile Business Group sagl
+# (<http://www.agilebg.com>)
+# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+{
+ 'name': "Purchase delivery terms",
+ 'version': '0.2',
+ 'category': 'Purchase Management',
+ 'description': """
+Delivery term for purchase orders.
+You can configure delivery terms specifying the quantity percentage and the delay for every term line.
+You can then associate the term to the 'main' order line and generate the 'detailed' order lines which in turn will generate several pickings according to delivery term (thanks to 'purchase_multi_picking' module).
+""",
+ 'author': 'Agile Business Group',
+ 'website': 'http://www.agilebg.com',
+ 'license': 'AGPL-3',
+ "depends" : ['purchase_multi_picking'],
+ "data" : [
+ 'purchase_view.xml',
+ 'security/ir.model.access.csv',
+ ],
+ "demo" : [],
+ "active": False,
+ "installable": True
+}
=== added directory 'purchase_delivery_term/i18n'
=== added file 'purchase_delivery_term/purchase.py'
--- purchase_delivery_term/purchase.py 1970-01-01 00:00:00 +0000
+++ purchase_delivery_term/purchase.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,222 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2012-2013 Agile Business Group sagl
+# (<http://www.agilebg.com>)
+# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import fields, orm
+from openerp.tools.translate import _
+import openerp.addons.decimal_precision as dp
+from datetime import datetime, timedelta
+from openerp.tools import DEFAULT_SERVER_DATE_FORMAT, DEFAULT_SERVER_DATETIME_FORMAT
+
+class purchase_delivery_term(orm.Model):
+ _name = 'purchase.delivery.term'
+ _columns = {
+ 'name': fields.char('Name', size=64, required=True),
+ 'line_ids': fields.one2many('purchase.delivery.term.line', 'term_id', 'Lines', required=True),
+ 'company_id': fields.many2one('res.company','Company',required=True,select=1),
+ }
+ _defaults = {
+ 'company_id': lambda self,cr,uid,c: self.pool.get(
+ 'res.company')._company_default_get(cr, uid, 'purchase.delivery.term', context=c),
+ }
+
+ def is_total_percentage_correct(self, cr, uid, term_ids, context=None):
+ for term in self.browse(cr, uid, term_ids, context=context):
+ total = 0.0
+ for line in term.line_ids:
+ total += line.quantity_perc
+ if total != 1 :
+ return False
+ return True
+
+
+class purchase_delivery_term_line(orm.Model):
+
+ _name = 'purchase.delivery.term.line'
+ _rec_name = 'term_id'
+ _columns = {
+ 'term_id': fields.many2one('purchase.delivery.term', 'Term', ondelete='cascade'),
+ 'quantity_perc': fields.float('Quantity percentage',
+ required=True, help="For 20% set '0.2'"),
+ 'delay': fields.float('Delivery Lead Time', required=True,
+ help="Number of days between the order confirmation and the shipping of the products from the supplier"),
+ }
+
+class purchase_order_line_master(orm.Model):
+
+ def onchange_product_id(self, cr, uid, ids, pricelist_id, product_id, qty, uom_id,
+ partner_id, date_order=False, fiscal_position_id=False, date_planned=False,
+ name=False, price_unit=False, context=None):
+ return self.pool.get('purchase.order.line').onchange_product_id(
+ cr, uid, ids, pricelist_id, product_id, qty, uom_id,
+ partner_id, date_order=date_order, fiscal_position_id=fiscal_position_id, date_planned=date_planned,
+ name=name, price_unit=price_unit, context=context)
+
+ def onchange_product_uom(self, cr, uid, ids, pricelist_id, product_id, qty, uom_id,
+ partner_id, date_order=False, fiscal_position_id=False, date_planned=False,
+ name=False, price_unit=False, context=None):
+ return self.pool.get('purchase.order.line').onchange_product_uom(cr, uid, ids, pricelist_id, product_id, qty, uom_id,
+ partner_id, date_order=date_order, fiscal_position_id=fiscal_position_id, date_planned=date_planned,
+ name=name, price_unit=price_unit, context=context)
+
+ def _amount_line(self, cr, uid, ids, prop, arg, context=None):
+ res = {}
+ cur_obj=self.pool.get('res.currency')
+ tax_obj = self.pool.get('account.tax')
+ for line in self.browse(cr, uid, ids, context=context):
+ taxes = tax_obj.compute_all(cr, uid, line.taxes_id, line.price_unit, line.product_qty)
+ cur = line.order_id.pricelist_id.currency_id
+ res[line.id] = cur_obj.round(cr, uid, cur, taxes['total'])
+ return res
+
+ _name = 'purchase.order.line.master'
+ _columns = {
+ 'order_id': fields.many2one('purchase.order', 'Order Reference',
+ select=True, required=True, ondelete='cascade'),
+ 'delivery_term_id': fields.many2one('purchase.delivery.term',
+ 'Delivery term', required=True, ondelete='restrict'),
+ 'name': fields.char('Description', size=256, required=True),
+ 'product_id': fields.many2one('product.product', 'Product',
+ domain=[('purchase_ok','=',True)], change_default=True),
+ 'price_unit': fields.float('Unit Price', required=True,
+ digits_compute= dp.get_precision('Purchase Price')),
+ 'price_subtotal': fields.function(_amount_line, string='Subtotal',
+ digits_compute= dp.get_precision('Purchase Price')),
+ 'product_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product UoM'), required=True),
+ 'product_uom': fields.many2one('product.uom', 'Product UOM', required=True),
+ 'order_line_ids': fields.one2many('purchase.order.line',
+ 'master_line_id', 'Detailed lines'),
+ 'taxes_id': fields.many2many('account.tax', 'purchase_master_order_line_tax', 'ord_line_id', 'tax_id', 'Taxes'),
+ 'date_planned': fields.date('Scheduled Date', required=True, select=True),
+ }
+ _defaults = {
+ 'product_qty': 1.0,
+ }
+
+ def _prepare_order_line(self, cr, uid, term_line, master_line, group_index=0, context=None):
+ order_line_pool = self.pool.get('purchase.order.line')
+ group_pool = self.pool.get('purchase.order.line.group')
+ group_ids = group_pool.search(cr, uid, [])
+ product_qty = master_line.product_qty * term_line.quantity_perc
+ order_line_vals = {}
+ on_change_res = order_line_pool.onchange_product_id(cr, uid, [],
+ master_line.order_id.pricelist_id.id, master_line.product_id.id,
+ master_line.product_qty, master_line.product_uom.id,
+ master_line.order_id.partner_id.id, date_order=master_line.order_id.date_order,
+ fiscal_position_id=master_line.order_id.fiscal_position.id, date_planned=master_line.date_planned,
+ name=master_line.name, price_unit=master_line.price_unit, context=context)
+ order_line_vals.update(on_change_res['value'])
+ date_planned = datetime.strptime(master_line.date_planned,
+ DEFAULT_SERVER_DATE_FORMAT) + timedelta(term_line.delay)
+ order_line_vals.update({
+ 'order_id': master_line.order_id.id,
+ 'name': master_line.name,
+ 'price_unit': master_line.price_unit,
+ 'product_qty': product_qty,
+ 'product_uom': master_line.product_uom.id,
+ 'product_id': master_line.product_id and master_line.product_id.id or False,
+ 'master_line_id': master_line.id,
+ 'date_planned': date_planned,
+ 'picking_group_id': group_ids[group_index],
+ 'taxes_id': [(6,0, [tax.id for tax in master_line.taxes_id])],
+ })
+ return order_line_vals
+
+ def generate_detailed_lines(self, cr, uid, ids, context=None):
+ group_pool = self.pool.get('purchase.order.line.group')
+ order_line_pool = self.pool.get('purchase.order.line')
+ group_ids = group_pool.search(cr, uid, [])
+ for master_line in self.browse(cr, uid, ids):
+ if master_line.order_line_ids:
+ raise orm.except_orm(_('Error'),
+ _("Detailed lines generated yet (for master line '%s'). Remove them first") % master_line.name)
+ if len(master_line.delivery_term_id.line_ids) > len(group_ids):
+ raise orm.except_orm(_('Error'),
+ _("Delivery term lines are %d. Order line groups are %d. Please create more groups")
+ % (len(master_line.delivery_term_id.line_ids), len(group_ids)))
+ if not master_line.delivery_term_id.is_total_percentage_correct():
+ raise orm.except_orm(_('Error'),
+ _("Total percentage of delivery term %s is not equal to 1") % master_line.delivery_term_id.name)
+ for group_index, term_line in enumerate(master_line.delivery_term_id.line_ids):
+ order_line_vals = self._prepare_order_line(cr, uid, term_line,
+ master_line, group_index=group_index, context=context)
+ order_line_pool.create(cr, uid, order_line_vals, context=context)
+ return True
+
+ def copy_data(self, cr, uid, id, default=None, context=None):
+ if not default:
+ default = {}
+ default.update({
+ 'order_line_ids': [],
+ })
+ return super(purchase_order_line_master, self).copy_data(
+ cr, uid, id, default, context=context)
+
+ def check_master_line_total(self, cr, uid, ids, context=None):
+ for master_line in self.browse(cr, uid, ids, context):
+ master_qty = master_line.product_qty
+ total_qty = 0.0
+ for order_line in master_line.order_line_ids:
+ total_qty += order_line.product_qty
+ if master_qty != total_qty:
+ raise orm.except_orm(_('Error'), _('Order lines total quantity %s is different from master line quantity %s') % (total_qty, master_qty))
+
+class purchase_order_line(orm.Model):
+ _inherit = 'purchase.order.line'
+ _columns = {
+ 'master_line_id': fields.many2one('purchase.order.line.master', 'Master Line'),
+ }
+
+ def copy_data(self, cr, uid, id, default=None, context=None):
+ if not default:
+ default = {}
+ default.update({'master_line_id': False})
+ return super(purchase_order_line, self).copy_data(cr, uid, id, default, context=context)
+
+
+class purchase_order(orm.Model):
+ _inherit = 'purchase.order'
+ _columns = {
+ 'master_order_line': fields.one2many('purchase.order.line.master',
+ 'order_id', 'Master Order Lines', readonly=True,
+ states={'draft': [('readonly', False)]}),
+ }
+
+ def copy(self, cr, uid, id, default=None, context=None):
+ if not default:
+ default = {}
+ default.update({
+ 'order_line': [],
+ })
+ return super(purchase_order, self).copy(cr, uid, id, default, context=context)
+
+ def generate_detailed_lines(self, cr, uid, ids, context=None):
+ for order in self.browse(cr, uid, ids, context):
+ for master_line in order.master_order_line:
+ master_line.generate_detailed_lines()
+ return True
+
+ def wkf_approve_order(self, cr, uid, ids, context=None):
+ for order in self.browse(cr, uid, ids, context):
+ for master_line in order.master_order_line:
+ master_line.check_master_line_total()
+ return super(purchase_order,self).wkf_approve_order(cr, uid, ids, context=context)
+
=== added file 'purchase_delivery_term/purchase_view.xml'
--- purchase_delivery_term/purchase_view.xml 1970-01-01 00:00:00 +0000
+++ purchase_delivery_term/purchase_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,79 @@
+<openerp>
+ <data>
+ <record id="purchase_delivery_term_form" model="ir.ui.view">
+ <field name="name">purchase.delivery.term.form</field>
+ <field name="model">purchase.delivery.term</field>
+ <field name="arch" type="xml">
+ <form string="Delivery term">
+ <field name="name" select="1"/>
+ <field name="line_ids" string="Term Lines" colspan="4" nolabel="1">
+ <form>
+ <field name="quantity_perc"></field>
+ <field name="delay"></field>
+ </form>
+ <tree editable="bottom">
+ <field name="quantity_perc"></field>
+ <field name="delay"></field>
+ </tree>
+ </field>
+ </form>
+ </field>
+ </record>
+ <record id="action_delivery_term_form" model="ir.actions.act_window">
+ <field name="name">Delivery Terms</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">purchase.delivery.term</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+
+ <menuitem action="action_delivery_term_form" id="menu_action_delivery_term_form" parent="purchase.menu_purchase_config_purchase" />
+
+ <record id="purchase_order_line_master_form" model="ir.ui.view">
+ <field name="name">purchase_order_line_master_form</field>
+ <field name="model">purchase.order.line.master</field>
+ <field name="arch" type="xml">
+ <form string="Master order line">
+ <field name="product_id" on_change="onchange_product_id(parent.pricelist_id,product_id,product_qty,product_uom,parent.partner_id, parent.date_order,parent.fiscal_position,date_planned,name,price_unit,context)" required="1"/>
+ <field name="product_qty" on_change="onchange_product_id(parent.pricelist_id,product_id,product_qty,product_uom,parent.partner_id,parent.date_order,parent.fiscal_position,date_planned,name,price_unit,context)"/>
+ <field name="product_uom" on_change="onchange_product_uom(parent.pricelist_id,product_id,product_qty,product_uom,parent.partner_id, parent.date_order,parent.fiscal_position,date_planned,name,price_unit,context)"/>
+ <newline></newline>
+ <field name="name" colspan="4"/>
+ <field name="date_planned" widget="date"/>
+ <field name="price_unit" />
+ <field name="delivery_term_id" />
+ <separator colspan="4" string="Taxes"/>
+ <field colspan="4" nolabel="1" name="taxes_id"
+ domain="[('parent_id','=',False),('type_tax_use','!=','sale')]"/>
+ </form>
+ </field>
+ </record>
+ <record id="purchase_order_line_master_tree" model="ir.ui.view">
+ <field name="name">purchase_order_line_master_tree</field>
+ <field name="model">purchase.order.line.master</field>
+ <field name="arch" type="xml">
+ <tree string="Master order lines">
+ <field name="date_planned" />
+ <field name="name" />
+ <field name="price_unit" />
+ <field name="product_qty" />
+ <field name="product_uom" />
+ <field name="price_subtotal" />
+ <field name="delivery_term_id" />
+ </tree>
+ </field>
+ </record>
+
+ <record id="purchase_order_form" model="ir.ui.view">
+ <field name="name">purchase.order.form</field>
+ <field name="model">purchase.order</field>
+ <field name="inherit_id" ref="purchase.purchase_order_form"></field>
+ <field name="arch" type="xml">
+ <field name="order_line" position="before">
+ <field colspan="4" name="master_order_line" nolabel="1"></field>
+ <button name="generate_detailed_lines" string="Generate detailed lines" icon="gtk-go-forward" type="object" colspan="2"/>
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'purchase_delivery_term/security'
=== added file 'purchase_delivery_term/security/ir.model.access.csv'
--- purchase_delivery_term/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ purchase_delivery_term/security/ir.model.access.csv 2014-11-23 23:06:46 +0000
@@ -0,0 +1,10 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_purchase_order_line_master,purchase.order.line_master user,model_purchase_order_line_master,purchase.group_purchase_user,1,1,1,1
+access_purchase_order_line_master_stock_worker,purchase.order.line_master stock,model_purchase_order_line_master,stock.group_stock_user,1,0,0,0
+access_purchase_order_line_master_manager,purchase.order.line_master manager,model_purchase_order_line_master,purchase.group_purchase_manager,1,1,1,1
+access_purchase_delivery_term,purchase_delivery_term user,model_purchase_delivery_term,purchase.group_purchase_user,1,0,0,0
+access_purchase_delivery_term_stock_worker,purchase_delivery_term stock,model_purchase_delivery_term,stock.group_stock_user,1,0,0,0
+access_purchase_delivery_term_manager,purchase_delivery_term manager,model_purchase_delivery_term,purchase.group_purchase_manager,1,1,1,1
+access_purchase_delivery_term_line,purchase_delivery_term_line user,model_purchase_delivery_term_line,purchase.group_purchase_user,1,0,0,0
+access_purchase_delivery_term_line_stock_worker,purchase_delivery_term_line stock,model_purchase_delivery_term_line,stock.group_stock_user,1,0,0,0
+access_purchase_delivery_term_line_manager,purchase_delivery_term_line manager,model_purchase_delivery_term_line,purchase.group_purchase_manager,1,1,1,1
=== added directory 'purchase_gains'
=== added file 'purchase_gains/__init__.py'
--- purchase_gains/__init__.py 1970-01-01 00:00:00 +0000
+++ purchase_gains/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import report
+import purchase
=== added file 'purchase_gains/__init__.pyc'
Binary files purchase_gains/__init__.pyc 1970-01-01 00:00:00 +0000 and purchase_gains/__init__.pyc 2014-11-23 23:06:46 +0000 differ
=== added file 'purchase_gains/__openerp__.py'
--- purchase_gains/__openerp__.py 1970-01-01 00:00:00 +0000
+++ purchase_gains/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+# NOTE: The name of the supplied field was initially "display_name", but it seems that OpenERP,
+# whenever it seems "name" in the field, returns the value for "name". Well...
+
+{
+ 'name': 'Purchase gain',
+ 'version': '1.1',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'Generic Modules/Purchases',
+ 'description': """
+Create a menu in reporting for Purchase gains
+====================================================
+""",
+ 'depends': ['base', 'purchase'],
+ 'data': [
+ 'purchase_report.xml',
+ 'purchase_view.xml',
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added file 'purchase_gains/purchase.py'
--- purchase_gains/purchase.py 1970-01-01 00:00:00 +0000
+++ purchase_gains/purchase.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,106 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+import openerp.addons.decimal_precision as dp
+
+class purchase_order(orm.Model):
+
+ _inherit = 'purchase.order'
+
+ def get_profit_all(self, cr, uid, ids, name, args, context):
+ if not ids:
+ return {}
+ res = {}
+ for line in self.browse(cr, uid, ids):
+ res[line.id] = {
+ 'profit_po': 0.0,
+ 'amount_total_discount': 0.0,
+ 'amount_landing_cost': 0.0,
+ 'amount_total_price_unit': 0.0,
+ 'amount_total_sale_order': 0.0
+ }
+ total_landed_cost_po = 0.0
+ if line.landed_cost_line_ids:
+ for costs in line.landed_cost_line_ids:
+ total_landed_cost_po += costs.amount
+ res[line.id]['amount_landing_cost'] = total_landed_cost_po
+ total_price_unit = 0.0
+
+ amount_total_sale_order = 0.0
+ amount_total_discounts = 0.0
+ total_landed_cost_so = 0.0
+ if line.order_line:
+ for one_line in line.order_line:
+ acc_id = one_line.account_analytic_id.id
+ total_price_unit += one_line.price_unit
+ ids_stock_prod_lot = self.pool.get('stock.production.lot').search(cr, uid, [('account_analytic_id', '=', acc_id)], context=context)[0]
+ id_stock_prod_lot = self.pool.get('stock.production.lot').browse(cr, uid, ids_stock_prod_lot).id
+ stock_move_ids = self.pool.get('stock.move').search(cr, uid, [('prodlot_id', '=', id_stock_prod_lot)], context=context)
+
+ list_stock_move = self.pool.get('stock.move').browse(cr, uid, stock_move_ids, context)
+ amount_total_sale_order = 0.0
+ amount_total_discounts = 0.0
+ if list_stock_move:
+ for one_move_line in list_stock_move:
+ if one_move_line.picking_id.sale_id:
+ amount_total_sale_order += one_move_line.picking_id.sale_id.amount_total
+ amount_total_discounts += one_move_line.picking_id.sale_id.amount_total * (1-(one_move_line.picking_id.sale_id.partner_id.discount or 0.0))
+ total_landed_cost_so = 0.0
+ if one_move_line.picking_id.sale_id.landed_cost_line_ids:
+ for costs_so in one_move_line.picking_id.sale_id.landed_cost_line_ids:
+ total_landed_cost_so += costs_so.amount
+ res[line.id]['total_landed_cost_so'] = total_landed_cost_so
+ res[line.id]['amount_total_price_unit'] = total_price_unit
+ res[line.id]['amount_total_discount'] = amount_total_discounts
+ res[line.id]['amount_total_sale_order'] = amount_total_sale_order
+ res[line.id]['profit_po'] = res[line.id]['amount_total_sale_order'] - (res[line.id]['total_landed_cost_so'] + res[line.id]['amount_total_price_unit'] + res[line.id]['amount_total_discount'] + res[line.id]['amount_landing_cost'])
+ return res
+
+
+ _columns = {
+ 'profit_po': fields.function(
+ get_profit_all,
+ digits_compute=dp.get_precision('Account'),
+ string='Profit', multi='all'),
+ 'amount_total_discount': fields.function(
+ get_profit_all,
+ digits_compute=dp.get_precision('Account'),
+ string='Total amount discount', multi='all'),
+ 'amount_landing_cost': fields.function(
+ get_profit_all,
+ digits_compute=dp.get_precision('Account'),
+ string='Total amount landing cost', multi='all'),
+ 'amount_total_price_unit': fields.function(
+ get_profit_all,
+ digits_compute=dp.get_precision('Account'),
+ string='Total amount price unit', multi='all'),
+ 'amount_total_sale_order': fields.function(
+ get_profit_all,
+ digits_compute=dp.get_precision('Account'),
+ string='Total amount sale order', multi='all'),
+ 'total_landed_cost_so': fields.function(
+ get_profit_all,
+ digits_compute=dp.get_precision('Account'),
+ string='Total amount landing cost sale order', multi='all'),
+ }
+
+
=== added file 'purchase_gains/purchase.pyc'
Binary files purchase_gains/purchase.pyc 1970-01-01 00:00:00 +0000 and purchase_gains/purchase.pyc 2014-11-23 23:06:46 +0000 differ
=== added file 'purchase_gains/purchase_report.xml'
--- purchase_gains/purchase_report.xml 1970-01-01 00:00:00 +0000
+++ purchase_gains/purchase_report.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <report auto="False" id="report_purchase_order_gains" model="purchase.order"
+ name="purchase.order.gains" rml="purchase_gains/report/order.rml"
+ usage="default" string="Purchase Order gains"/>
+
+ </data>
+</openerp>
\ No newline at end of file
=== added file 'purchase_gains/purchase_view.xml'
--- purchase_gains/purchase_view.xml 1970-01-01 00:00:00 +0000
+++ purchase_gains/purchase_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,14 @@
+<openerp>
+ <data>
+ <record id="purchase_order_tree_inherit44" model="ir.ui.view">
+ <field name="name">purchase.order.tree.inherit44</field>
+ <field name="model">purchase.order</field>
+ <field name="inherit_id" ref="purchase.purchase_order_tree"></field>
+ <field name="arch" type="xml">
+ <field name="state" position="after">
+ <field name="profit_po"></field>
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'purchase_gains/report'
=== added file 'purchase_gains/report/__init__.py'
--- purchase_gains/report/__init__.py 1970-01-01 00:00:00 +0000
+++ purchase_gains/report/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import order
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
\ No newline at end of file
=== added file 'purchase_gains/report/order.py'
--- purchase_gains/report/order.py 1970-01-01 00:00:00 +0000
+++ purchase_gains/report/order.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import time
+from openerp.report import report_sxw
+from openerp.osv import osv
+from openerp import pooler
+
+class order(report_sxw.rml_parse):
+ def __init__(self, cr, uid, name, context):
+ super(order, self).__init__(cr, uid, name, context=context)
+ self.localcontext.update({'time': time})
+
+report_sxw.report_sxw('report.purchase.order.gains','purchase.order','addons/purchase_gains/report/order.rml',parser=order)
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+
=== added file 'purchase_gains/report/order.rml'
--- purchase_gains/report/order.rml 1970-01-01 00:00:00 +0000
+++ purchase_gains/report/order.rml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,172 @@
+<?xml version="1.0"?>
+<document filename="Purchase Order.pdf">
+ <template title="Purchase Order" author="OpenERP S.A.(sales@xxxxxxxxxxx)" allowSplitting="20">
+ <pageTemplate id="first">
+ <frame id="first" x1="18.0" y1="42.0" width="535" height="758"/>
+ </pageTemplate>
+ </template>
+ <stylesheet>
+ <blockTableStyle id="Standard_Outline">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <blockTableStyle id="Tableau1">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <blockTableStyle id="Tableau2">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <blockTableStyle id="Header_Order_Reference_Tbl">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="0,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="0,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="1,0" stop="1,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="1,0" stop="1,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="2,0" stop="2,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="2,0" stop="2,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
+ <lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="3,0" stop="3,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="4,0" stop="4,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ </blockTableStyle>
+ <blockTableStyle id="Content_Order_Reference_Table">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="0,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="0,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="1,0" stop="1,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="1,0" stop="1,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="2,0" stop="2,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="2,0" stop="2,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
+ <lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="3,0" stop="3,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="4,0" stop="4,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ </blockTableStyle>
+ <blockTableStyle id="Table_Header_Pur_ord_Line">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="4,-1" stop="4,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="5,-1" stop="5,-1"/>
+ </blockTableStyle>
+ <blockTableStyle id="Table_Order_Pur_line_Content">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="5,-1" stop="5,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="5,-1" stop="5,-1"/>
+ </blockTableStyle>
+ <blockTableStyle id="Table_All_Total_Detail">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEABOVE" colorName="#ffffff" start="0,0" stop="0,0"/>
+ <lineStyle kind="LINEABOVE" colorName="#000000" start="1,0" stop="1,0"/>
+ <lineStyle kind="LINEABOVE" colorName="#000000" start="2,0" stop="2,0"/>
+ <lineStyle kind="LINEABOVE" colorName="#000000" start="1,2" stop="1,2"/>
+ <lineStyle kind="LINEABOVE" colorName="#000000" start="2,2" stop="2,2"/>
+ </blockTableStyle>
+ <blockTableStyle id="Table_Outer_Notes">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <initialize>
+ <paraStyle name="all" alignment="justify"/>
+ </initialize>
+ <paraStyle name="terp_header" fontSize="12.0" leading="15" alignment="LEFT" spaceBefore="12.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_tblheader_General" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="6.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_default_8" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_tblheader_General_Centre" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="6.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_tblheader_General_Right" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="6.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_default_Centre_8" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_9" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Bold_9" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Right_9" fontSize="9.0" leading="11" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Bold_9_Right" fontSize="9.0" leading="11" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <images/>
+ </stylesheet>
+ <story>
+ <pto>
+ <!--<para style="terp_default_8">[[ setLang(o.partner_id.lang) ]]</para>-->
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ <para style="terp_header"><b>Purchase Order gains </b></para>
+ <para style="terp_default_8">
+ <font color="white"> </font>
+ </para>
+ <blockTable colWidths="136.0,132.0,96.0,100.0,70.0" style="Header_Order_Reference_Tbl">
+ <tr>
+ <td>
+ <para style="terp_tblheader_General_Centre"><b>Our Order Reference</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Centre"><b>Your Order Reference</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Centre"><b>Order Date</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Centre"><b>Validated By</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Centre"><b>Profit</b></para>
+ </td>
+ </tr>
+ </blockTable>
+ <section>
+ <para style="terp_default_8">[[repeatIn(objects,'o')]]</para>
+ <blockTable colWidths="136.0,132.0,96.0,100.0,70.0" style="Content_Order_Reference_Table">
+ <tr>
+ <td>
+ <para style="terp_default_Centre_8">[[ o.name or '' ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Centre_8">[[ o.partner_ref or '' ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Centre_8">[[formatLang(o.date_order,date=True) ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Centre_8">[[ (o.validator and o.validator.name) or '' ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Centre_8">[[ formatLang(o.profit_po, digits=get_digits(dp='Account'), currency_obj=o.pricelist_id.currency_id ) ]]</para>
+ <para style="terp_default_Centre_8"></para>
+ </td>
+ </tr>
+ </blockTable>
+ </section>
+ </pto>
+ </story>
+</document>
=== added directory 'purchase_group_orders'
=== renamed directory 'purchase_group_orders' => 'purchase_group_orders.moved'
=== added file 'purchase_group_orders/__init__.py'
--- purchase_group_orders/__init__.py 1970-01-01 00:00:00 +0000
+++ purchase_group_orders/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Alexandre Fayolle
+# Copyright 2012 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from . import purchase_group_orders
=== added file 'purchase_group_orders/__openerp__.py'
--- purchase_group_orders/__openerp__.py 1970-01-01 00:00:00 +0000
+++ purchase_group_orders/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Alexandre Fayolle
+# Copyright 2012 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+{'name' : 'Purchase Group Orders by Shop and Carrier',
+ 'version' : '0.4',
+ 'author' : 'Camptocamp',
+ 'maintainer': 'Camptocamp',
+ 'category': 'Purchase Management',
+ 'complexity': "normal", # easy, normal, expert
+ 'depends' : ['delivery', 'sale', 'purchase',
+ ],
+ 'description': """Only merge PO with the same shop and carrier.
+
+ This eases the warehouse managements as the incoming pickings are grouped
+ in a more convenient way.
+ """,
+ 'website': 'http://www.camptocamp.com/',
+ 'init_xml': [],
+ 'update_xml': ['purchase_group_orders_view.xml'],
+ 'demo_xml': [],
+ 'tests': [],
+ 'installable': False,
+ 'auto_install': False,
+ 'license': 'AGPL-3',
+ 'application': False
+ }
=== added directory 'purchase_group_orders/i18n'
=== added file 'purchase_group_orders/i18n/en.po'
--- purchase_group_orders/i18n/en.po 1970-01-01 00:00:00 +0000
+++ purchase_group_orders/i18n/en.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,103 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * purchase_group_orders
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 6.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 07:26+0000\n"
+"PO-Revision-Date: 2012-06-25 09:27+0200\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: purchase_group_orders
+#: sql_constraint:purchase.order:0
+#: sql_constraint:sale.order:0
+msgid "Order Reference must be unique per Company!"
+msgstr "Order Reference must be unique per Company!"
+
+#. module: purchase_group_orders
+#: field:purchase.order,shop_id:0
+msgid "Shop"
+msgstr "Shop"
+
+#. module: purchase_group_orders
+#: help:procurement.order,sale_id:0
+msgid "the sale order which generated the procurement"
+msgstr "the sale order which generated the procurement"
+
+#. module: purchase_group_orders
+#: help:purchase.order,carrier_partner_id:0
+msgid "Name of the carrier partner"
+msgstr "Name of the carrier partner"
+
+#. module: purchase_group_orders
+#: field:purchase.order,carrier_partner_id:0
+msgid "Carrier Name"
+msgstr "Carrier Name"
+
+#. module: purchase_group_orders
+#: field:procurement.order,sale_id:0
+msgid "Sale Order"
+msgstr "Sale Order"
+
+#. module: purchase_group_orders
+#: model:ir.model,name:purchase_group_orders.model_purchase_order
+msgid "Purchase Order"
+msgstr "Bon de commande"
+
+#. module: purchase_group_orders
+#: model:ir.model,name:purchase_group_orders.model_procurement_order
+msgid "Procurement"
+msgstr "Approvisionnement"
+
+#. module: purchase_group_orders
+#: field:purchase.order,carrier_id:0
+msgid "Carrier"
+msgstr "Carrier"
+
+#. module: purchase_group_orders
+#: help:purchase.order,carrier_id:0
+msgid "the carrier in charge for delivering the related sale order"
+msgstr "the carrier in charge for delivering the related sale order"
+
+#. module: purchase_group_orders
+#: help:purchase.order,shop_id:0
+msgid "the shop which generated the sale which triggered the PO"
+msgstr "the shop which generated the sale which triggered the PO"
+
+#. module: purchase_group_orders
+#: model:ir.model,name:purchase_group_orders.model_sale_order
+msgid "Sales Order"
+msgstr "Commande de ventes"
+
+#. module: purchase_group_orders
+#: view:purchase.order.group:0
+msgid " Please note that: \n"
+" \n"
+" Orders will only be merged if: \n"
+" * Purchase Orders are in draft \n"
+" * Purchase Orders belong to the same supplier \n"
+" * Purchase Orders are have same stock location, same pricelist \n"
+" * Purchase Orders have been generated from Sale Orders issued by the same Shop, and having the same Carrier \n"
+" \n"
+" Lines will only be merged if: \n"
+" * Order lines are exactly the same except for the product,quantity and unit \n"
+" "
+msgstr " Please note that: \n"
+" \n"
+" Orders will only be merged if: \n"
+" * Purchase Orders are in draft \n"
+" * Purchase Orders belong to the same supplier \n"
+" * Purchase Orders are have same stock location, same pricelist \n"
+" * Purchase Orders have been generated from Sale Orders issued by the same Shop, and having the same Carrier \n"
+" \n"
+" Lines will only be merged if: \n"
+" * Order lines are exactly the same except for the product,quantity and unit \n"
+" "
+
=== added file 'purchase_group_orders/i18n/fr.po'
--- purchase_group_orders/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ purchase_group_orders/i18n/fr.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,109 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * purchase_group_orders
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 6.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-06-25 07:26+0000\n"
+"PO-Revision-Date: 2012-06-25 09:34+0200\n"
+"Last-Translator: Alexandre Fayolle - Camptocamp<>\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: purchase_group_orders
+#: sql_constraint:purchase.order:0
+#: sql_constraint:sale.order:0
+msgid "Order Reference must be unique per Company!"
+msgstr "La référence de commande doit être unique par société !"
+
+#. module: purchase_group_orders
+#: field:purchase.order,shop_id:0
+msgid "Shop"
+msgstr "Magasin"
+
+#. module: purchase_group_orders
+#: help:procurement.order,sale_id:0
+msgid "the sale order which generated the procurement"
+msgstr "Le bon de commande client qui a généré la commande"
+
+#. module: purchase_group_orders
+#: help:purchase.order,carrier_partner_id:0
+msgid "Name of the carrier partner"
+msgstr "Nom du transporteur"
+
+#. module: purchase_group_orders
+#: field:purchase.order,carrier_partner_id:0
+msgid "Carrier Name"
+msgstr "Transporteur"
+
+#. module: purchase_group_orders
+#: field:procurement.order,sale_id:0
+msgid "Sale Order"
+msgstr "Bon de commande client"
+
+#. module: purchase_group_orders
+#: model:ir.model,name:purchase_group_orders.model_purchase_order
+msgid "Purchase Order"
+msgstr "Bon de commande"
+
+#. module: purchase_group_orders
+#: model:ir.model,name:purchase_group_orders.model_procurement_order
+msgid "Procurement"
+msgstr "Approvisionnement"
+
+#. module: purchase_group_orders
+#: field:purchase.order,carrier_id:0
+msgid "Carrier"
+msgstr "Transporteur"
+
+#. module: purchase_group_orders
+#: help:purchase.order,carrier_id:0
+msgid "the carrier in charge for delivering the related sale order"
+msgstr "Le transporteur chargé de livrer la commande client"
+
+#. module: purchase_group_orders
+#: help:purchase.order,shop_id:0
+msgid "the shop which generated the sale which triggered the PO"
+msgstr "Le magasin où a été effectué la vente qui a généré le Bon de Commande"
+
+#. module: purchase_group_orders
+#: model:ir.model,name:purchase_group_orders.model_sale_order
+msgid "Sales Order"
+msgstr "Commande de ventes"
+
+#. module: purchase_group_orders
+#: view:purchase.order.group:0
+msgid " Please note that: \n"
+" \n"
+" Orders will only be merged if: \n"
+" * Purchase Orders are in draft \n"
+" * Purchase Orders belong to the same supplier \n"
+" * Purchase Orders are have same stock location, same pricelist \n"
+" * Purchase Orders have been generated from Sale Orders issued by the same Shop, and having the same Carrier \n"
+" \n"
+" Lines will only be merged if: \n"
+" * Order lines are exactly the same except for the product,quantity and unit \n"
+" "
+msgstr ""
+"Veuillez noter que:\n"
+"\n"
+"Les commandes seront fusionnées seulement si:\n"
+" * Les bons de commande sont à l'état 'Brouillon'\n"
+" * Les bons de commande sont pour le même fournisseur\n"
+" * les bons de commande sont pour le même emplacement et la même liste de\n"
+"prix\n"
+" * pour les bons de commandes qui ont été générés par une commande\n"
+" client, la commande client a été passée depuis le même magasin et\n"
+" doit être livrée par le même transporteur\n"
+"\n"
+"Les lignes seront fusionnées seulement si:\n"
+" * les lignes de commandes sont exactement les mêmes sauf pour le\n"
+" produit, la quantité et l'unité.\n"
+"\n"
+" "
+
=== added file 'purchase_group_orders/purchase_group_orders.py'
--- purchase_group_orders/purchase_group_orders.py 1970-01-01 00:00:00 +0000
+++ purchase_group_orders/purchase_group_orders.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,188 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Author: Alexandre Fayolle
+# Copyright 2012 Camptocamp SA
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+import logging
+
+from openerp.osv.orm import Model, browse_record, browse_null
+from openerp.osv import fields
+from openerp import netsvc
+
+class procurement_order(Model):
+ _inherit = 'procurement.order'
+
+ _columns = {'sale_id': fields.many2one('sale.order', 'Sale Order',
+ help='the sale order which generated the procurement'),
+ 'origin': fields.char('Source Document', size=512,
+ help="Reference of the document that created this Procurement.\n"
+ "This is automatically completed by OpenERP."),
+ }
+ def create_procurement_purchase_order(self, cr, uid, procurement, po_vals, line_vals, context=None):
+ """Create the purchase order from the procurement, using
+ the provided field values, after adding the given purchase
+ order line in the purchase order.
+
+ :params procurement: the procurement object generating the purchase order
+ :params dict po_vals: field values for the new purchase order (the
+ ``order_line`` field will be overwritten with one
+ single line, as passed in ``line_vals``).
+ :params dict line_vals: field values of the single purchase order line that
+ the purchase order will contain.
+ :return: id of the newly created purchase order
+ :rtype: int
+ """
+ po_vals.update({'order_line': [(0,0,line_vals)]})
+ if procurement.sale_id:
+ sale = procurement.sale_id
+ update = {'shop_id': sale.shop_id.id,
+ 'carrier_id': sale.carrier_id.id}
+ po_vals.update(update)
+ return self.pool.get('purchase.order').create(cr, uid, po_vals, context=context)
+
+class sale_order(Model):
+ _inherit = 'sale.order'
+
+ def _prepare_order_line_procurement(self, cr, uid, order, line, move_id, date_planned, context=None):
+ proc_data = super(sale_order, self)._prepare_order_line_procurement(cr, uid, order, line,
+ move_id, date_planned,
+ context)
+ proc_data['sale_id'] = order.id
+ return proc_data
+
+class purchase_order(Model):
+ _inherit = 'purchase.order'
+
+ _columns = {
+ 'shop_id': fields.many2one('sale.shop', 'Shop',
+ help='the shop which generated the sale which triggered the PO'),
+ 'carrier_id': fields.many2one('delivery.carrier', 'Carrier',
+ help='the carrier in charge for delivering the related sale order'),
+ 'carrier_partner_id': fields.related('carrier_id', 'partner_id',
+ type='many2one',
+ relation='res.partner',
+ string='Carrier Name',
+ readonly=True,
+ help="Name of the carrier partner in charge of delivering the related sale order"),
+ 'origin': fields.char('Source Document', size=512,
+ help="Reference of the document that generated this purchase order request."),
+
+ }
+ def do_merge(self, cr, uid, ids, context=None):
+ """
+ To merge similar type of purchase orders.
+ Orders will only be merged if:
+ * Purchase Orders are in draft
+ * Purchase Orders belong to the same partner
+ * Purchase Orders have same stock location, same pricelist
+ * Purchase Orders have the same shop and the same carrier (NEW in this module)
+ Lines will only be merged if:
+ * Order lines are exactly the same except for the quantity and unit
+ """
+ #TOFIX: merged order line should be unlink
+ wf_service = netsvc.LocalService("workflow")
+ def make_key(br, fields):
+ list_key = []
+ for field in fields:
+ field_val = getattr(br, field)
+ if field in ('product_id', 'move_dest_id', 'account_analytic_id'):
+ if not field_val:
+ field_val = False
+ if isinstance(field_val, browse_record):
+ field_val = field_val.id
+ elif isinstance(field_val, browse_null):
+ field_val = False
+ elif isinstance(field_val, list):
+ field_val = ((6, 0, tuple([v.id for v in field_val])),)
+ list_key.append((field, field_val))
+ list_key.sort()
+ return tuple(list_key)
+
+ # compute what the new orders should contain
+ new_orders = {}
+ for porder in [order for order in self.browse(cr, uid, ids, context=context) if order.state == 'draft']:
+ order_key = make_key(porder, ('partner_id', 'location_id', 'pricelist_id',
+ 'shop_id', 'carrier_id')) # added line
+ new_order = new_orders.setdefault(order_key, ({}, []))
+ new_order[1].append(porder.id)
+ order_infos = new_order[0]
+ if not order_infos:
+ order_infos.update({
+ 'origin': porder.origin,
+ 'date_order': porder.date_order,
+ 'partner_id': porder.partner_id.id,
+ 'partner_address_id': porder.partner_address_id.id,
+ 'dest_address_id': porder.dest_address_id.id,
+ 'warehouse_id': porder.warehouse_id.id,
+ 'location_id': porder.location_id.id,
+ 'pricelist_id': porder.pricelist_id.id,
+ 'state': 'draft',
+ 'order_line': {},
+ 'notes': '%s' % (porder.notes or '',),
+ 'fiscal_position': porder.fiscal_position and porder.fiscal_position.id or False,
+ 'shop_id': porder.shop_id and porder.shop_id.id, # added line
+ 'carrier_id': porder.carrier_id and porder.carrier_id.id, # added line
+ })
+ else:
+ if porder.date_order < order_infos['date_order']:
+ order_infos['date_order'] = porder.date_order
+ if porder.notes:
+ order_infos['notes'] = (order_infos['notes'] or '') + ('\n%s' % (porder.notes,))
+ if porder.origin:
+ order_infos['origin'] = (order_infos['origin'] or '') + ' ' + porder.origin
+
+ for order_line in porder.order_line:
+ line_key = make_key(order_line, ('name', 'date_planned', 'taxes_id', 'price_unit', 'notes', 'product_id', 'move_dest_id', 'account_analytic_id'))
+ o_line = order_infos['order_line'].setdefault(line_key, {})
+ if o_line:
+ # merge the line with an existing line
+ o_line['product_qty'] += order_line.product_qty * order_line.product_uom.factor / o_line['uom_factor']
+ else:
+ # append a new "standalone" line
+ for field in ('product_qty', 'product_uom'):
+ field_val = getattr(order_line, field)
+ if isinstance(field_val, browse_record):
+ field_val = field_val.id
+ o_line[field] = field_val
+ o_line['uom_factor'] = order_line.product_uom and order_line.product_uom.factor or 1.0
+
+
+ allorders = []
+ orders_info = {}
+ for order_key, (order_data, old_ids) in new_orders.iteritems():
+ # skip merges with only one order
+ if len(old_ids) < 2:
+ allorders += (old_ids or [])
+ continue
+
+ # cleanup order line data
+ for key, value in order_data['order_line'].iteritems():
+ del value['uom_factor']
+ value.update(dict(key))
+ order_data['order_line'] = [(0, 0, value) for value in order_data['order_line'].itervalues()]
+
+ # create the new order
+ neworder_id = self.create(cr, uid, order_data)
+ orders_info.update({neworder_id: old_ids})
+ allorders.append(neworder_id)
+
+ # make triggers pointing to the old orders point to the new order
+ for old_id in old_ids:
+ wf_service.trg_redirect(uid, 'purchase.order', old_id, neworder_id, cr)
+ wf_service.trg_validate(uid, 'purchase.order', old_id, 'purchase_cancel', cr)
+ return orders_info
=== added file 'purchase_group_orders/purchase_group_orders_view.xml'
--- purchase_group_orders/purchase_group_orders_view.xml 1970-01-01 00:00:00 +0000
+++ purchase_group_orders/purchase_group_orders_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="view_purchase_order_group_shop_carrier" model="ir.ui.view">
+ <field name="name">Merger Purchase Orders</field>
+ <field name="model">purchase.order.group</field>
+ <field name="inherit_id" ref='purchase.view_purchase_order_group'/>
+ <field name="type">form</field>
+ <field name="arch" type="xml">
+ <xpath expr="/form/label" position="replace">
+ <label string="
+Please note that:
+Orders will only be merged if:
+ * Purchase Orders are in draft
+ * Purchase Orders belong to the same supplier
+ * Purchase Orders are have same stock location, same pricelist
+ * Purchase Orders have been generated from Sale Orders issued by the same Shop, and having the same Carrier
+Lines will only be merged if:
+ * Order lines are exactly the same except for the product,quantity and unit
+" colspan="4"/>
+ </xpath>
+ </field>
+ </record>
+
+ <record id="purchase_order_form_shop_carrier" model="ir.ui.view">
+ <field name="name">purchase.order.form</field>
+ <field name="model">purchase.order</field>
+ <field name="type">form</field>
+ <field name="inherit_id" ref='purchase.purchase_order_form'/>
+ <field name="arch" type="xml">
+ <field name="company_id" position="after">
+ <field name="shop_id" readonly="1" />
+ <field name="carrier_partner_id" readonly="1" />
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'purchase_lot_tracking'
=== added file 'purchase_lot_tracking/README'
=== added file 'purchase_lot_tracking/__init__.py'
--- purchase_lot_tracking/__init__.py 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import purchase_lot_tracking
+import product
+import purchase
+import stock
+import wizard
+import account
+import sale
=== added file 'purchase_lot_tracking/__openerp__.py'
--- purchase_lot_tracking/__openerp__.py 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,52 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+# NOTE: The name of the supplied field was initially "display_name", but it seems that OpenERP,
+# whenever it seems "name" in the field, returns the value for "name". Well...
+
+{
+ 'name': 'purchase_lot_tracking',
+ 'version': '1.1',
+ 'author': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'Generic Modules/Purchases',
+ 'description': """
+Lets you track expenses using product's lots numbers
+====================================================
+
+This module lets you track expenses using a product's lot
+number.
+
+If you create an analytic account for a product
+
+
+""",
+ 'depends': ['base', 'purchase', 'purchase_landed_costs', 'analytic', 'sale'],
+ 'data': [
+ 'purchase_lot_tracking_view.xml',
+ 'purchase_workflow.xml',
+ 'account_view.xml'
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added file 'purchase_lot_tracking/account.py'
--- purchase_lot_tracking/account.py 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/account.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,169 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+import openerp.addons.decimal_precision as dp
+
+
+class account_analytic_account(orm.Model):
+
+ _inherit = 'account.analytic.account'
+
+ def _calculate_total_in_out(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+
+ move_pool = self.pool.get('stock.move')
+
+ for account in self.browse(cr, uid, ids):
+ res[account.id] = {
+ 'total_in_qty': 0.0,
+ 'total_out_qty': 0.0
+ }
+ total_moves_in = 0.0
+ total_moves_out = 0.0
+ production_pool = self.pool.get('stock.production.lot')
+ lot_ids = production_pool.search(
+ cr, uid, [('name', '=', account.name)])
+
+ for lot in production_pool.browse(cr, uid, lot_ids):
+ move_ids = move_pool.search(
+ cr, uid, [('prodlot_id', '=', lot.id)])
+ for move in move_pool.browse(cr, uid, move_ids):
+
+ # Add in purchases, remove sales
+ if move.type == 'in':
+ total_moves_in += move.product_qty
+ elif move.type == 'out':
+ total_moves_out += move.product_qty
+
+ res[account.id] = {
+ 'total_in_qty': max(total_moves_in, 0),
+ 'total_out_qty': max(total_moves_out, 0)
+ }
+
+ return res
+
+ def _get_stock_move_ids(self, cr, uid, ids, context=None):
+ context = context or {}
+
+ res = []
+
+ analytic_account_pool = self.pool.get('account.analytic.account')
+
+ for move in self.pool.get('stock.move').browse(
+ cr, uid, ids, context=context):
+ if move.prodlot_id:
+ query = [('code', '=', move.prodlot_id.name)]
+
+ res += analytic_account_pool.search(
+ cr, uid, query, context=context)
+
+ return res
+
+ def _get_analytic_account_line_ids(self, cr, uid, ids, context=None):
+ context = context or {}
+
+ res = []
+
+ for line in self.pool.get('account.analytic.line').browse(
+ cr, uid, ids, context=context):
+ res.append(line.account_id.id)
+
+ return list(set(res))
+
+ def _calculate_tcu(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+ for account in self.browse(cr, uid, ids):
+ res[account.id] = 0.0
+ if account.total_in_qty > 0:
+ res[account.id] = account.credit / account.total_in_qty
+ return res
+
+ def _estimated_tcu(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+ po_line_pool = self.pool.get('purchase.order.line')
+ for line in self.browse(cr, uid, ids):
+ if line.code.startswith('LOT'):
+ po_line_ids = po_line_pool.search(cr, uid, [('account_analytic_id', '=', line.id)])
+ if po_line_ids:
+ po_line_id = po_line_ids[0]
+ po_line = po_line_pool.browse(cr, uid, po_line_id, context)
+ if po_line.product_qty == 0:
+ res[line.id] = 0
+ else:
+ res[line.id] = po_line.landed_costs / po_line.product_qty
+ else:
+ res[line.id] = 0.0
+ else:
+ res[line.id] = 0.0
+ return res
+
+ _columns = {
+ 'purchase_order': fields.many2one(
+ 'purchase.order',
+ 'Purchase Order',
+ help='Issuing Purchase Order'),
+ 'total_cost_unit': fields.function(
+ _calculate_tcu,
+ string='Total Cost Unit',
+ type='float',
+ store={
+ 'account.analytic.account': (lambda self, cr, uid, ids, context: ids,
+ ['name', 'code', 'line_ids'],
+ 10),
+ 'account.analytic.line': (_get_analytic_account_line_ids,
+ ['amount', 'unit_amount'],
+ 10),
+ 'stock.move': (_get_stock_move_ids,
+ ['product_qty'],
+ 10)
+ }),
+ 'total_in_qty': fields.function(
+ _calculate_total_in_out,
+ string='Total Received Quantity',
+ type='float',
+ multi=True,
+ store={
+ 'account.analytic.account': (lambda self, cr, uid, ids, context: ids,
+ ['name', 'code', 'line_ids'],
+ 10),
+ 'stock.move': (_get_stock_move_ids,
+ ['product_qty'],
+ 10)
+ }),
+ 'total_out_qty': fields.function(
+ _calculate_total_in_out,
+ string='Total Delivered Quantity',
+ type='float',
+ multi=True,
+ store={
+ 'account.analytic.account': (lambda self, cr, uid, ids, context: ids,
+ ['name', 'code', 'line_ids'],
+ 10),
+ 'stock.move': (_get_stock_move_ids,
+ ['product_qty'],
+ 10)
+ }),
+ 'estimated_tcu': fields.function(
+ _estimated_tcu,
+ string='Estimated Total Cost per Unit',
+ type='float'),
+ }
=== added file 'purchase_lot_tracking/account_view.xml'
--- purchase_lot_tracking/account_view.xml 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/account_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="lot_total_cost_unit" model="ir.ui.view">
+ <field name="name">Total Cost Unit</field>
+ <field name="model">account.analytic.account</field>
+ <field name="inherit_id" ref="account.view_account_analytic_account_tree" />
+ <field name="arch" type="xml">
+ <field name="type" position="before">
+ <field name="total_in_qty" />
+ <field name="estimated_tcu" />
+ <field name="total_cost_unit"/>
+ </field>
+ </field>
+ </record>
+
+ <record id="lot_purchase_order" model="ir.ui.view">
+ <field name="name">Purchase Order</field>
+ <field name="model">account.analytic.account</field>
+ <field name="inherit_id" ref="account.view_account_analytic_account_tree" />
+ <field name="arch" type="xml">
+ <field name="code" position="before">
+ <field name="purchase_order" />
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'purchase_lot_tracking/i18n'
=== added file 'purchase_lot_tracking/i18n/fr.po'
--- purchase_lot_tracking/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/i18n/fr.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,109 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * purchase_lot_tracking
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:23+0000\n"
+"PO-Revision-Date: 2013-09-18 14:23+0000\n"
+"Last-Translator: Alexandre Boily <alexandre.boily@xxxxxxxxxxxxxxxxxxxx>\n"
+"Language-Team: Savoir-faire Linux\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: purchase_lot_tracking
+#: field:sale.order.line,average:0
+msgid "Avg."
+msgstr "Moy."
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_product_category
+msgid "Product Category"
+msgstr "Catégorie de produit"
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_stock_invoice_onshipping
+msgid "Stock Invoice Onshipping"
+msgstr "Stock Invoice Onshipping"
+
+#. module: purchase_lot_tracking
+#: field:sale.order.line,minimum:0
+msgid "Min."
+msgstr "Min."
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_purchase_order_line
+msgid "Purchase Order Line"
+msgstr "Ligne de bon de commande"
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_stock_partial_picking_line
+msgid "stock.partial.picking.line"
+msgstr "stock.partial.picking.line"
+
+#. module: purchase_lot_tracking
+#: field:product.category,account_id:0
+#: field:product.product,account_id:0
+msgid "Analytical Account"
+msgstr "Compte analytique"
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_product_product
+msgid "Product"
+msgstr "Produit"
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_account_analytic_account
+#: view:product.category:0
+#: field:stock.production.lot,account_analytic_id:0
+msgid "Analytic Account"
+msgstr "Compte analytique"
+
+#. module: purchase_lot_tracking
+#: field:purchase.order.line,lot:0
+msgid "Lot Number"
+msgstr "Numéro de lot"
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_stock_production_lot
+msgid "Serial Number"
+msgstr "Numéro de série"
+
+#. module: purchase_lot_tracking
+#: field:sale.order.line,maximum:0
+msgid "Max."
+msgstr "Max."
+
+#. module: purchase_lot_tracking
+#: field:account.analytic.account,estimated_tcu:0
+msgid "Estimated Total Cost per Unit"
+msgstr "Coût total estimé par unité"
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_account_invoice
+msgid "Invoice"
+msgstr "Facture"
+
+#. module: purchase_lot_tracking
+#: field:account.analytic.account,total_cost_unit:0
+msgid "Total Cost Unit"
+msgstr "Coût total unitaire"
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_purchase_order
+msgid "Purchase Order"
+msgstr "Bon de commande"
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_sale_order_line
+msgid "Sales Order Line"
+msgstr "Ligne de bon d'achat"
+
+#. module: purchase_lot_tracking
+#: field:account.analytic.account,total_in_qty:0
+msgid "Total Received Quantity"
+msgstr "Quantité reçue totale"
=== added file 'purchase_lot_tracking/i18n/purchase_lot_tracking.pot'
--- purchase_lot_tracking/i18n/purchase_lot_tracking.pot 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/i18n/purchase_lot_tracking.pot 2014-11-23 23:06:46 +0000
@@ -0,0 +1,110 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * purchase_lot_tracking
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:23+0000\n"
+"PO-Revision-Date: 2013-09-18 14:23+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: purchase_lot_tracking
+#: field:sale.order.line,average:0
+msgid "Avg."
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_product_category
+msgid "Product Category"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_stock_invoice_onshipping
+msgid "Stock Invoice Onshipping"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: field:sale.order.line,minimum:0
+msgid "Min."
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_purchase_order_line
+msgid "Purchase Order Line"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_stock_partial_picking_line
+msgid "stock.partial.picking.line"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: field:product.category,account_id:0
+#: field:product.product,account_id:0
+msgid "Analytical Account"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_product_product
+msgid "Product"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_account_analytic_account
+#: view:product.category:0
+#: field:stock.production.lot,account_analytic_id:0
+msgid "Analytic Account"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: field:purchase.order.line,lot:0
+msgid "Lot Number"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_stock_production_lot
+msgid "Serial Number"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: field:sale.order.line,maximum:0
+msgid "Max."
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: field:account.analytic.account,estimated_tcu:0
+msgid "Estimated Total Cost per Unit"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_account_invoice
+msgid "Invoice"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: field:account.analytic.account,total_cost_unit:0
+msgid "Total Cost Unit"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_purchase_order
+msgid "Purchase Order"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: model:ir.model,name:purchase_lot_tracking.model_sale_order_line
+msgid "Sales Order Line"
+msgstr ""
+
+#. module: purchase_lot_tracking
+#: field:account.analytic.account,total_in_qty:0
+msgid "Total Received Quantity"
+msgstr ""
+
=== added file 'purchase_lot_tracking/product.py'
--- purchase_lot_tracking/product.py 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/product.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+
+class product_category(orm.Model):
+ """
+ Adds an analytical account to a purchase category
+ """
+
+ _inherit = 'product.category'
+
+ _columns = {
+ 'account_id': fields.many2one('account.analytic.account', 'Analytical Account', required=False)
+ }
+
+class product_product(orm.Model):
+ """
+ Adds an analytical account to a purchase category
+ """
+
+ _inherit = 'product.product'
+
+ _columns = {
+ 'account_id': fields.many2one('account.analytic.account', 'Analytical Account', required=False)
+ }
=== added file 'purchase_lot_tracking/purchase.py'
--- purchase_lot_tracking/purchase.py 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/purchase.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,265 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+from openerp import netsvc
+
+
+def assign_lot_number(pool, cr, uid, line_orders, context=None):
+ """
+ Manages and tracks a lot number for this production line
+
+ Generates a lot number, a stock.production.lot and an analytic
+ account for this purchase order line.
+ """
+ stock_prod_lot_obj = pool.get('stock.production.lot')
+ ir_sequence_obj = pool.get('ir.sequence')
+
+ for line_order in line_orders:
+ order_id = line_order.order_id.id
+
+ lot_number = ir_sequence_obj.get(cr, uid, 'ls.lot')
+ product = line_order.product_id
+
+ # Creates the analytic account
+ account_id = _analytic_account_from_product(pool,
+ cr,
+ uid,
+ order_id,
+ product,
+ lot_number,
+ context=context)
+
+ # Creates the stock.production.line
+ serial_number_data = {
+ 'name': lot_number,
+ 'product_id': product.id,
+ 'account_analytic_id': account_id,
+ }
+
+ serial_number_id = stock_prod_lot_obj.create(cr, uid,
+ serial_number_data,
+ context=context)
+
+ return serial_number_id, account_id
+
+
+def _analytic_account_from_product(pool, cr, uid, order_id, product,
+ lot_number, context=None):
+ """
+ Creates an analytic account for the lot number and places it
+ as a children of the product's analytic account.
+
+ Assumes two variables in the context
+ - product: parent product id
+ - lot_number: lot_number to create analytic account for
+ """
+ account_analytic_obj = pool.get('account.analytic.account')
+ parent_account = product.account_id
+
+ account_values = {
+ 'name': lot_number,
+ 'complete_name': lot_number,
+ 'purchase_order': order_id,
+ 'code': lot_number,
+ 'type': 'normal',
+ 'parent_id': parent_account.id,
+ 'balance': 0.0,
+ 'debit': 0.0,
+ 'credit': 0.0,
+ 'quantity': 0.0,
+ 'date_start': parent_account.date_start,
+ 'date': parent_account.date,
+ 'state': parent_account.state,
+ }
+
+ if parent_account.currency_id:
+ account_values['currency_id'] = parent_account.currency_id.id
+
+ analytic_account_id = account_analytic_obj.create(cr, uid,
+ account_values,
+ context=context)
+
+ return analytic_account_id
+
+
+class purchase_order_line(orm.Model):
+ """
+ Adds an analytical account to a product
+ """
+
+ _inherit = 'purchase.order.line'
+
+ def must_be_tracked(self, cr, uid, ids):
+ """
+ Determines if this purchase order line for this product must be tracked
+ """
+ return True
+
+
+
+
+ _columns = {
+ 'lot': fields.char('Lot Number', size=64, required=False,
+ translate=True),
+ }
+
+
+class purchase_order(orm.Model):
+ _inherit = "purchase.order"
+
+ def _create_pickings(self, cr, uid, order, order_lines, picking_id=False,
+ context=None):
+ if not picking_id:
+ picking_id = self.pool.get('stock.picking').create(
+ cr, uid,
+ self._prepare_order_picking(cr, uid, order, context=context))
+
+ todo_moves = []
+ stock_move = self.pool.get('stock.move')
+ wf_service = netsvc.LocalService("workflow")
+
+ for order_line in order_lines:
+ if not order_line.product_id:
+ continue
+ if order_line.product_id.type in ('product', 'consu'):
+ move = stock_move.create(
+ cr, uid,
+ self._prepare_order_line_move(cr, uid, order, order_line,
+ picking_id, context=context))
+
+ if order_line.move_dest_id:
+ order_line.move_dest_id.write(
+ {'location_id': order.location_id.id})
+
+ todo_moves.append(move)
+
+ stock_move.action_confirm(cr, uid, todo_moves)
+ stock_move.force_assign(cr, uid, todo_moves)
+ wf_service.trg_validate(uid, 'stock.picking', picking_id,
+ 'button_confirm', cr)
+
+ res = [picking_id]
+ pick_id = int(res[0])
+
+ invoice_obj = self.pool.get('account.invoice')
+ invoice_line_obj = self.pool.get('account.invoice.line')
+ journal_obj = self.pool.get('account.journal')
+ journal_ids = journal_obj.search(
+ cr, uid, [('type', '=', 'purchase'),
+ ('company_id', '=', order.company_id.id)], limit=1)
+
+ # Create the analytic account
+
+ stock_picking_id = self.pool.get('stock.picking.in').search(cr, uid, [
+ ('origin', 'like', order.name)])
+ stock_picking = \
+ self.pool.get('stock.picking.in').browse(cr, uid,
+ stock_picking_id)[0]
+
+ all_lines_tracked = True
+ total_pallets = 0.0
+
+ for po_line in order.order_line:
+ if not po_line.product_id.track_production:
+ all_lines_tracked = False
+ else:
+ lot_number, account_id = assign_lot_number(self.pool, cr, uid, [po_line], context=context)
+ matching_lines = [line for line in stock_picking.move_lines
+ if line.product_qty == po_line.product_qty
+ and line.product_id.id == po_line.product_id.id
+ and not line.prodlot_id]
+ if matching_lines:
+ matching_lines[0].write({'prodlot_id': lot_number})
+
+ po_line.write({'account_analytic_id': account_id})
+ po_line.refresh()
+ stock_picking.refresh()
+
+ total_pallets += po_line.nb_pallets
+
+ for order_cost in order.landed_cost_line_ids:
+ fiscal_position = False
+ if order.partner_id.property_account_position:
+ fiscal_position = order.partner_id.property_account_position.id
+
+ vals_inv = {
+ 'partner_id': order_cost.partner_id.id,
+ 'currency_id': order_cost.currency_id.id or order.company_id.currency_id.id,
+ 'account_id': order_cost.partner_id.property_account_payable.id,
+ 'type': 'in_invoice',
+ 'origin': order.name,
+ 'fiscal_position': fiscal_position,
+ 'company_id': order.company_id.id,
+ 'journal_id': len(journal_ids) and journal_ids[0] or False,
+ }
+
+ inv_id = invoice_obj.create(cr, uid, vals_inv, context=None)
+
+ if all_lines_tracked:
+ for po_line in order.order_line:
+ factor = 0.0
+
+ if order_cost.price_type == 'per_unit':
+ factor = po_line.product_qty / po_line.order_id.quantity_total
+
+ elif order_cost.price_type == 'value':
+ factor = po_line.price_subtotal / po_line.order_id.amount_total
+
+ elif order_cost.price_type == 'per_pallet':
+ factor = po_line.nb_pallets / total_pallets
+
+ else:
+ raise ValueError(
+ 'Unknown price type (neither "per_unit", "value" nor "per_pallet")')
+
+ amount = order_cost.amount * factor
+ vals_line = {
+ 'product_id': order_cost.product_id.id,
+ 'name': order_cost.product_id.name,
+ 'account_id': self._get_product_account_expense_id(
+ order_cost.product_id),
+ 'partner_id': order_cost.partner_id.id,
+ 'invoice_id': inv_id,
+ 'origin': order.name,
+ 'account_analytic_id': po_line.account_analytic_id.id,
+ 'price_unit': amount,
+ 'invoice_line_tax_id': [(6, 0, [x.id for x in
+ order_cost.product_id.supplier_taxes_id])],
+ }
+
+ invoice_line_obj.create(cr, uid, vals_line, context=None)
+ else:
+ vals_line = {
+ 'product_id': order_cost.product_id.id,
+ 'name': order_cost.product_id.name,
+ 'account_id': self._get_product_account_expense_id(
+ order_cost.product_id),
+ 'partner_id': order_cost.partner_id.id,
+ 'invoice_id': inv_id,
+ 'price_unit': order_cost.amount,
+ 'invoice_line_tax_id': [(6, 0, [x.id for x in
+ order_cost.product_id.supplier_taxes_id])],
+ }
+
+ invoice_line_obj.create(cr, uid, vals_line, context=None)
+
+ return res
=== added file 'purchase_lot_tracking/purchase_lot_tracking.py'
--- purchase_lot_tracking/purchase_lot_tracking.py 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/purchase_lot_tracking.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields, osv
+from openerp import netsvc
+import openerp.addons.decimal_precision as dp
+
+from datetime import datetime
+
+
+
+
+#class stock_partial_picking(orm.Model):
+
+# _inherit = 'stock.picking.in'
+
+# def action_process(self, cr, uid, ids, context=None):
+
+# if context is None:
+# context = {}
+# """Open the partial picking wizard"""
+# context.update({
+# 'active_model': self._name,
+# 'active_ids': ids,
+# 'active_id': len(ids) and ids[0] or False
+# })
+#
+# for stock_picking in self.browse(cr, uid, ids):
+# import ipdb; ipdb.set_trace()
+# ref_po_id = self.pool.get('purchase.order').search(cr, uid, [('name', 'like', stock_picking.origin)])
+# ref_po = self.pool.get('purchase.order').browse(cr, uid, ref_po_id)[0]
+#
+# for stock_picking_line in stock_picking.move_lines:
+#
+# matching_line = [po_line for po_line in ref_po.order_line if\
+# po_line.product_qty == stock_picking_line.product_qty and \
+# po_line.product_id.id == stock_picking_line.product_id.id][0]
+#
+## matching_lot = self.pool.get('stock.production.lot').search(cr, uid, [('name', 'like', matching_line.lot)])[0]
+#
+# stock_picking_line.write({'prodlot_id': matching_lot})
+# stock_picking_line.refresh()
+
+
+
+# return {
+# 'view_type': 'form',
+# 'view_mode': 'form',
+# 'res_model': 'stock.partial.picking',
+# 'type': 'ir.actions.act_window',
+# 'target': 'new',
+# 'context': context,
+# 'nodestroy': True,
+# }
=== added file 'purchase_lot_tracking/purchase_lot_tracking_view.xml'
--- purchase_lot_tracking/purchase_lot_tracking_view.xml 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/purchase_lot_tracking_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="purchase_lot_tracking_product" model="ir.ui.view">
+ <field name="name">purchase_lot_tracking.product.view</field>
+ <field name="model">product.product</field>
+ <field name="inherit_id" ref="product.product_normal_form_view"/>
+ <field name="arch" type="xml">
+ <field name="taxes_id" position="after">
+ <field name="account_id"/>
+ </field>
+ </field>
+ </record>
+
+ <record id="purchase_lot_tracking_product_category" model="ir.ui.view">
+ <field name="name">purchase_lot_tracking.product_category.view</field>
+ <field name="model">product.category</field>
+ <field name="inherit_id" ref="product.product_category_form_view"/>
+ <field name="arch" type="xml">
+ <field name="type" position="after">
+ <group name="analytic_account" string="Analytic Account" colspan="2">
+ <field name="account_id"/>
+ </group>
+ </field>
+ </field>
+ </record>
+
+ <record id="purchase_order_line_readonly_aa" model="ir.ui.view">
+ <field name="name">purchase.order.readonly.aa</field>
+ <field name="model">purchase.order</field>
+ <field name="inherit_id" ref="purchase.purchase_order_form" />
+ <field name="arch" type="xml">
+ <field name="account_analytic_id" position="replace">
+ <field
+ name="account_analytic_id"
+ colspan="2"
+ groups="purchase.group_analytic_accounting"
+ attrs="{'readonly': True}" />
+ </field>
+ </field>
+ </record>
+
+ <record id="purchase_lot_tracking_sale_order" model="ir.ui.view">
+ <field name="name">purchase_lot_tracking.sale.order.view</field>
+ <field name="model">sale.order</field>
+ <field name="inherit_id" ref="sale.view_order_form"/>
+ <field name="arch" type="xml">
+ <xpath expr="/form/sheet/notebook/page/field[@name='order_line']/tree/field[@name='price_unit']" position="before">
+ <field name="minimum" />
+ <field name="average" />
+ <field name="maximum" />
+ </xpath>
+ </field>
+ </record>
+
+ <!-- Sequence -->
+ <record id="seq_type_lot" model="ir.sequence.type">
+ <field name="name">ls.lot</field>
+ <field name="code">ls.lot</field>
+ </record>
+
+ <record id="seq_lot" model="ir.sequence">
+ <field name="name">ls.lot</field>
+ <field name="code">ls.lot</field>
+ <field name="prefix">LOT</field>
+ <field name="padding">6</field>
+ </record>
+ </data>
+</openerp>
=== added file 'purchase_lot_tracking/purchase_workflow.xml'
--- purchase_lot_tracking/purchase_workflow.xml 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/purchase_workflow.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="act_confirmed" model="workflow.activity">
+ <field name="wkf_id" ref="purchase.purchase_order"/>
+ <field name="name">confirmed</field>
+ <field name="split_mode">OR</field>
+ <field name="kind">function</field>
+ <field name="action">wkf_confirm_order()</field>
+ </record>
+ </data>
+</openerp>
=== added file 'purchase_lot_tracking/sale.py'
--- purchase_lot_tracking/sale.py 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/sale.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,123 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+import logging
+
+_logger = logging.getLogger(__name__)
+
+
+class sale(orm.Model):
+
+ _inherit = 'sale.order.line'
+
+ def _get_min_max_avg(self, cr, uid, ids, fields, args, context=None):
+ context = context or {}
+
+ res = {}
+
+ analytic_account_pool = self.pool.get('account.analytic.account')
+
+ for line in self.browse(cr, uid, ids, context=context):
+ account_id = line.product_id.account_id
+ res[line.id] = {
+ 'minimum': 0.0,
+ 'average': 0.0,
+ 'maximum': 0.0
+ }
+
+ if account_id:
+ query = [
+ ('parent_id', '=', account_id.id),
+ ('total_in_qty', '!=', 0)
+ ]
+ child_ids = analytic_account_pool.search(
+ cr, uid, query, context=context)
+
+ if child_ids:
+ values = analytic_account_pool.read(
+ cr, uid, child_ids,
+ ['estimated_tcu', 'total_in_qty'], context=context)
+ res[line.id]['minimum'] = min(
+ [v['estimated_tcu'] for v in values])
+
+ res[line.id]['maximum'] = max(
+ [v['estimated_tcu'] for v in values])
+
+ average = sum(
+ [v['estimated_tcu'] * v['total_in_qty']
+ for v in values])
+ if average:
+ res[line.id]['average'] = average / sum(
+ [v['total_in_qty'] for v in values])
+ else:
+ res[line.id]['average'] = 0
+
+ return res
+
+ def _get_sale_order_ids(self, cr, uid, ids, context=None):
+ context = context or {}
+
+ query = [('order_id', 'in', ids)]
+
+ return self.pool.get('sale.order.line').search(cr, uid, query, context)
+
+ _columns = {
+ 'minimum': fields.function(
+ _get_min_max_avg,
+ string='Min.',
+ type='float',
+ multi=True,
+ store={
+ 'sale.order.line': (lambda self, cr, uid, ids, context: ids,
+ ['product_id', 'price_unit'],
+ 10),
+ 'sale.order': (_get_sale_order_ids,
+ ['amount_untaxed'],
+ 10)
+ }),
+ 'average': fields.function(
+ _get_min_max_avg,
+ string='Avg.',
+ type='float',
+ multi=True,
+ store={
+ 'sale.order.line': (lambda self, cr, uid, ids, context: ids,
+ ['product_id', 'price_unit'],
+ 10),
+ 'sale.order': (_get_sale_order_ids,
+ ['amount_untaxed'],
+ 10)
+ }),
+ 'maximum': fields.function(
+ _get_min_max_avg,
+ string='Max.',
+ type='float',
+ multi=True,
+ store={
+ 'sale.order.line': (lambda self, cr, uid, ids, context: ids,
+ ['product_id', 'price_unit'],
+ 10),
+ 'sale.order': (_get_sale_order_ids,
+ ['amount_untaxed'],
+ 10)
+ })
+ }
=== added file 'purchase_lot_tracking/stock.py'
--- purchase_lot_tracking/stock.py 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/stock.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,141 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+from openerp.tools.translate import _
+
+class stock_production_lot(orm.Model):
+
+ _inherit = 'stock.production.lot'
+
+ _columns = {
+ 'account_analytic_id': fields.many2one('account.analytic.account', 'Analytic Account', required=False)
+ }
+
+
+class stock_invoice_onshipping(orm.TransientModel):
+
+ _inherit = 'stock.invoice.onshipping'
+
+ def retrieve_move_lines(self, cr, uid, ids, context=None):
+ """Retrieves all different move lines from the stock picking
+ """
+ move_lines = []
+ for pick in self.pool.get('stock.picking').browse(cr, uid,
+ context['active_ids'],
+ context=context):
+ move_lines += pick.move_lines
+
+ return move_lines
+
+ def _retrieve_invoice_lines(self, cr, uid, ids, context=None):
+ """Retrieves invoice lines of a newly created invoice
+
+ expects invoice_id to be passed in context
+ """
+ invoice = self.pool.get('account.invoice')\
+ .browse(cr,uid, context['invoice_id'])
+ return invoice.invoice_line
+
+ def _find_matching_move_line(self, invoice_line, move_lines):
+ """Finds the matching invoice line in the move lines list
+
+ It is considered matching if they have the same product quantity
+ and the same product id.
+ """
+ matching_move_lines = [line for line in move_lines if
+ line.product_qty == invoice_line.quantity and
+ line.product_id.id == invoice_line.product_id.id]
+
+ if matching_move_lines:
+ return matching_move_lines[0]
+ return None
+
+ def create_invoice(self, cr, uid, ids, context=None):
+ """
+ Creates an invoice when the delivery lots are confirmed
+
+ Iterates through all the lines of the invoice to specify
+ the proper analytic_account
+ """
+ prod_lot_pool = self.pool.get('stock.production.lot')
+ # creates the invoice properly
+ res = super(stock_invoice_onshipping, self)\
+ .create_invoice(cr, uid, ids, context=context)
+
+ context['invoice_id'] = res.values()[0]
+
+ # retrieve move lines of stock pickings
+ move_lines = self.retrieve_move_lines(cr, uid, ids, context=context)
+
+ # retrieve invoice lines of newly create invoice
+ invoice_lines = self._retrieve_invoice_lines(cr, uid, ids,
+ context=context)
+
+ # first iteration, check if matching
+ lst_match = []
+ for invoice_line in invoice_lines:
+ # don't add service to analytic account
+ if invoice_line.product_id.type == u'service':
+ continue
+ matching_move_line = self._find_matching_move_line(invoice_line,
+ move_lines)
+ name = invoice_line.name
+ if not matching_move_line:
+ msg = _("The item %s is not in stock picking." % name)
+ raise orm.except_orm(_("Missed line!"), msg)
+
+ # search account analytic
+ prod_lot_id = matching_move_line.prodlot_id
+ if not prod_lot_id:
+ msg = _("The item '%s' missed 'prodlot_id' on associated move \
+ item, origin %s." % (name, matching_move_line.origin))
+ raise orm.except_orm(_("Missed Serial Number!"), msg)
+
+ matching_prod_lot = prod_lot_pool.browse(cr, uid, prod_lot_id.id)
+ matching_account = matching_prod_lot.account_analytic_id.id
+
+ lst_match.append((invoice_line, matching_account))
+
+ # transaction
+ for invoice_line, matching_account in lst_match:
+ invoice_line.write({'account_analytic_id': matching_account})
+
+ return res
+
+
+class stock_picking_out(orm.Model):
+
+ _inherit = 'stock.picking.out'
+
+ def action_process(self, cr, uid, ids, context={}):
+ '''Check if tracked products have their lot number specified'''
+
+ picking = self.browse(cr, uid, ids, context=context)[0]
+
+ for line in picking.move_lines:
+ if line.product_id.track_production and not line.prodlot_id.id:
+ message = ' '.join([
+ _('Please specify a lot number for all products of type:'),
+ line.product_id.name_template])
+ raise orm.except_orm(_('Missing lot number'), message)
+
+ return super(stock_picking_out, self).action_process(cr, uid, ids, context)
=== added directory 'purchase_lot_tracking/wizard'
=== added file 'purchase_lot_tracking/wizard/__init__.py'
--- purchase_lot_tracking/wizard/__init__.py 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/wizard/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,1 @@
+import stock_partial_picking
=== added file 'purchase_lot_tracking/wizard/stock_partial_picking.py'
--- purchase_lot_tracking/wizard/stock_partial_picking.py 1970-01-01 00:00:00 +0000
+++ purchase_lot_tracking/wizard/stock_partial_picking.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-TODAY OpenERP SA (<http://openerp.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import time
+from lxml import etree
+from openerp.osv import fields, osv
+from openerp.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
+from openerp.tools.float_utils import float_compare
+import openerp.addons.decimal_precision as dp
+from openerp.tools.translate import _
+
+class stock_partial_picking_line(osv.TransientModel):
+
+ def _tracking(self, cursor, user, ids, name, arg, context=None):
+ res = {}
+ for tracklot in self.browse(cursor, user, ids, context=context):
+ tracking = False
+ if (tracklot.move_id.picking_id.type == 'in' and tracklot.product_id.track_incoming == True) or \
+ (tracklot.move_id.picking_id.type == 'out' and tracklot.product_id.track_outgoing == True):
+ tracking = True
+ res[tracklot.id] = tracking
+ return res
+
+ _inherit = "stock.partial.picking.line"
+
+ def onchange_product_id(self, cr, uid, ids, product_id, context=None):
+
+ raise Exception()
+
+ uom_id = False
+ if product_id:
+ product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
+ uom_id = product.uom_id.id
+ return {'value': {'product_uom': uom_id}}
+
=== added directory 'purchase_multi_picking'
=== renamed directory 'purchase_multi_picking' => 'purchase_multi_picking.moved'
=== added file 'purchase_multi_picking/AUTHORS.txt'
--- purchase_multi_picking/AUTHORS.txt 1970-01-01 00:00:00 +0000
+++ purchase_multi_picking/AUTHORS.txt 2014-11-23 23:06:46 +0000
@@ -0,0 +1,1 @@
+Lorenzo Battistini <lorenzo.battistini@xxxxxxxxxxx>
=== added file 'purchase_multi_picking/__init__.py'
--- purchase_multi_picking/__init__.py 1970-01-01 00:00:00 +0000
+++ purchase_multi_picking/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2012-2013 Agile Business Group sagl
+# (<http://www.agilebg.com>)
+# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+from . import purchase
=== added file 'purchase_multi_picking/__openerp__.py'
--- purchase_multi_picking/__openerp__.py 1970-01-01 00:00:00 +0000
+++ purchase_multi_picking/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2012-2013 Agile Business Group sagl
+# (<http://www.agilebg.com>)
+# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+{
+ 'name': "Multi Pickings from Purchase Orders",
+ 'version': '0.2',
+ 'category': 'Purchase Management',
+ 'description': """
+This module allows to generate several pickings from the same purchase order.
+You just have to indicate which order lines have to be grouped in the same picking. When confirming the order, for each group a picking is generated.
+""",
+ 'author': 'Agile Business Group',
+ 'website': 'http://www.agilebg.com',
+ 'license': 'AGPL-3',
+ "depends" : ['purchase', 'stock'],
+ "data" : [
+ 'purchase_view.xml',
+ 'security/ir.model.access.csv',
+ ],
+ "demo" : [],
+ "active": False,
+ "installable": True
+}
=== added directory 'purchase_multi_picking/i18n'
=== added file 'purchase_multi_picking/purchase.py'
--- purchase_multi_picking/purchase.py 1970-01-01 00:00:00 +0000
+++ purchase_multi_picking/purchase.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2012-2013 Agile Business Group sagl
+# (<http://www.agilebg.com>)
+# Copyright (C) 2012 Domsense srl (<http://www.domsense.com>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import fields, orm
+
+class purchase_order_line_group(orm.Model):
+ _name = 'purchase.order.line.group'
+ _columns = {
+ 'name': fields.char('Group', size=64, required=True),
+ 'company_id': fields.many2one('res.company','Company',required=True,select=1),
+ }
+ _defaults = {
+ 'company_id': lambda self,cr,uid,c: self.pool.get(
+ 'res.company')._company_default_get(cr, uid, 'purchase.order.line.group', context=c),
+ }
+
+
+class purchase_order_line(orm.Model):
+ _inherit = 'purchase.order.line'
+ _columns = {
+ 'picking_group_id': fields.many2one('purchase.order.line.group',
+ 'Group', help="This is used by 'multi-picking' to group order lines in one picking"),
+ }
+
+
+class purchase_order(orm.Model):
+ _inherit = 'purchase.order'
+
+ def action_picking_create(self, cr, uid, ids, context=None):
+ picking_pool = self.pool.get('stock.picking')
+ picking_ids = []
+ for order in self.browse(cr, uid, ids, context=context):
+ lines_by_group = {}
+ for line in order.order_line:
+ group_id = line.picking_group_id.id if line.picking_group_id else 0
+ lines_by_group.setdefault(group_id, []).append(line)
+ for group in lines_by_group:
+ if not group:
+ picking_id = None
+ else:
+ picking_vals = super(purchase_order, self)._prepare_order_picking(cr, uid, order, context=context)
+ picking_id = picking_pool.create(cr, uid, picking_vals, context=context)
+ picking_ids.extend(super(purchase_order, self)._create_pickings(
+ cr, uid, order, lines_by_group[group], picking_id, context=context))
+ return picking_ids[0] if picking_ids else False # ?
+
=== added file 'purchase_multi_picking/purchase_view.xml'
--- purchase_multi_picking/purchase_view.xml 1970-01-01 00:00:00 +0000
+++ purchase_multi_picking/purchase_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,23 @@
+<openerp>
+ <data>
+ <record id="purchase_order_line_form" model="ir.ui.view">
+ <field name="name">purchase.order.line.form</field>
+ <field name="model">purchase.order.line</field>
+ <field name="inherit_id" ref="purchase.purchase_order_line_form"></field>
+ <field name="arch" type="xml">
+ <field name="account_analytic_id" position="after">
+ <field name="picking_group_id"/>
+ </field>
+ </field>
+ </record>
+ <record id="action_purchase_order_line_group_form" model="ir.actions.act_window">
+ <field name="name">Purchase order line Groups</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">purchase.order.line.group</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">tree,form</field>
+ </record>
+
+ <menuitem action="action_purchase_order_line_group_form" id="menu_action_purchase_order_line_group_form" parent="purchase.menu_purchase_config_purchase" />
+ </data>
+</openerp>
=== added directory 'purchase_multi_picking/security'
=== added file 'purchase_multi_picking/security/ir.model.access.csv'
--- purchase_multi_picking/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ purchase_multi_picking/security/ir.model.access.csv 2014-11-23 23:06:46 +0000
@@ -0,0 +1,5 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_purchase_order_line_group,purchase.order.line_group user,model_purchase_order_line_group,purchase.group_purchase_user,1,1,1,1
+access_purchase_order_line_group_manager,purchase.order.line_group manager,model_purchase_order_line_group,purchase.group_purchase_manager,1,0,0,0
+access_purchase_order_line_group_stock_worker,purchase.order.line_group manager,model_purchase_order_line_group,stock.group_stock_user,1,0,0,0
+access_purchase_order_line_group_manager,purchase.order.line_group manager,model_purchase_order_line_group,purchase.group_purchase_manager,1,1,1,1
=== added directory 'purchase_order_force_number'
=== renamed directory 'purchase_order_force_number' => 'purchase_order_force_number.moved'
=== added file 'purchase_order_force_number/AUTHORS.txt'
--- purchase_order_force_number/AUTHORS.txt 1970-01-01 00:00:00 +0000
+++ purchase_order_force_number/AUTHORS.txt 2014-11-23 23:06:46 +0000
@@ -0,0 +1,1 @@
+Lorenzo Battistini <lorenzo.battistini@xxxxxxxxxxx>
=== added file 'purchase_order_force_number/__init__.py'
--- purchase_order_force_number/__init__.py 1970-01-01 00:00:00 +0000
+++ purchase_order_force_number/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2013 Agile Business Group sagl
+# (<http://www.agilebg.com>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
=== added file 'purchase_order_force_number/__openerp__.py'
--- purchase_order_force_number/__openerp__.py 1970-01-01 00:00:00 +0000
+++ purchase_order_force_number/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,38 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (C) 2013 Agile Business Group sagl
+# (<http://www.agilebg.com>)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': "Purchase orders - Force number",
+ 'version': '0.1',
+ 'category': 'Purchase Management',
+ 'description': """This simple module allows to specify the number to use when creating purchase orders.
+If user does not change the default value ('/'), the standard sequence is used.""",
+ 'author': 'Agile Business Group',
+ 'website': 'http://www.agilebg.com',
+ 'license': 'AGPL-3',
+ "depends" : ['purchase'],
+ "data" : [
+ 'purchase_view.xml',
+ ],
+ "demo" : [],
+ "active": False,
+ "installable": True
+}
=== added file 'purchase_order_force_number/purchase_view.xml'
--- purchase_order_force_number/purchase_view.xml 1970-01-01 00:00:00 +0000
+++ purchase_order_force_number/purchase_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+<data>
+
+ <record id="purchase_order_form" model="ir.ui.view">
+ <field name="name">purchase.order.form</field>
+ <field name="model">purchase.order</field>
+ <field name="inherit_id" ref="purchase.purchase_order_form"></field>
+ <field name="arch" type="xml">
+ <xpath expr="/form/sheet/div/h1/field[@name='name']" position="attributes">
+ <attribute name="readonly">0</attribute>
+ </xpath>
+ </field>
+ </record>
+
+</data>
+</openerp>
=== added directory 'purchase_order_pick_up_date'
=== added file 'purchase_order_pick_up_date/__init__.py'
--- purchase_order_pick_up_date/__init__.py 1970-01-01 00:00:00 +0000
+++ purchase_order_pick_up_date/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import purchase
=== added file 'purchase_order_pick_up_date/__openerp__.py'
--- purchase_order_pick_up_date/__openerp__.py 1970-01-01 00:00:00 +0000
+++ purchase_order_pick_up_date/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Purchase Order Pick Up Date',
+ 'version': '0.1',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'purchase',
+ 'description': """
+Add a field for a purchase pick up date
+=======================================
+
+This module lets you specify a scheduled pick up date for a purchase order.
+""",
+ 'depends': ['base', 'purchase'],
+ 'data': [
+ 'purchase_order_pick_up_date_report.xml',
+ 'purchase_order_pick_up_date_view.xml',
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added directory 'purchase_order_pick_up_date/i18n'
=== added file 'purchase_order_pick_up_date/i18n/fr.po'
--- purchase_order_pick_up_date/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ purchase_order_pick_up_date/i18n/fr.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,31 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * purchase_order_pick_up_date
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:24+0000\n"
+"PO-Revision-Date: 2013-09-18 14:24+0000\n"
+"Last-Translator: Alexandre Boily <alexandre.boily@xxxxxxxxxxxxxxxxxxxx>\n"
+"Language-Team: Savoir-faire Linux\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: purchase_order_pick_up_date
+#: help:purchase.order,date_pick_up:0
+msgid "Scheduled date where the purchase will arrive at one of your warehouses"
+msgstr "Date prévue à laquelle l'achat arrivera à l'un de vos entrepôts"
+
+#. module: purchase_order_pick_up_date
+#: field:purchase.order,date_pick_up:0
+msgid "Pick Up Date"
+msgstr "Date de pick up"
+
+#. module: purchase_order_pick_up_date
+#: model:ir.model,name:purchase_order_pick_up_date.model_purchase_order
+msgid "Purchase Order"
+msgstr "Bon de commande"
=== added file 'purchase_order_pick_up_date/i18n/purchase_order_pick_up_date.pot'
--- purchase_order_pick_up_date/i18n/purchase_order_pick_up_date.pot 1970-01-01 00:00:00 +0000
+++ purchase_order_pick_up_date/i18n/purchase_order_pick_up_date.pot 2014-11-23 23:06:46 +0000
@@ -0,0 +1,32 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * purchase_order_pick_up_date
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:24+0000\n"
+"PO-Revision-Date: 2013-09-18 14:24+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: purchase_order_pick_up_date
+#: help:purchase.order,date_pick_up:0
+msgid "Scheduled date where the purchase will arrive at one of your warehouses"
+msgstr ""
+
+#. module: purchase_order_pick_up_date
+#: field:purchase.order,date_pick_up:0
+msgid "Pick Up Date"
+msgstr ""
+
+#. module: purchase_order_pick_up_date
+#: model:ir.model,name:purchase_order_pick_up_date.model_purchase_order
+msgid "Purchase Order"
+msgstr ""
+
=== added file 'purchase_order_pick_up_date/purchase.py'
--- purchase_order_pick_up_date/purchase.py 1970-01-01 00:00:00 +0000
+++ purchase_order_pick_up_date/purchase.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+
+class purchase_order(orm.Model):
+
+ _inherit = 'purchase.order'
+
+ _columns = {
+ 'date_pick_up':
+ fields.date(
+ 'Pick Up Date',
+ help='''Scheduled date where the purchase will arrive at one of your warehouses'''),
+ }
=== added file 'purchase_order_pick_up_date/purchase_order_pick_up_date_report.xml'
--- purchase_order_pick_up_date/purchase_order_pick_up_date_report.xml 1970-01-01 00:00:00 +0000
+++ purchase_order_pick_up_date/purchase_order_pick_up_date_report.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<openerp>
+ <data>
+ <report
+ auto="False"
+ id="purchase.report_purchase_quotation"
+ model="purchase.order"
+ name="purchase.quotation"
+ rml="purchase_order_pick_up_date/report/request_quotation.rml"
+ usage="default"
+ string="Request for Quotation" />
+
+ <report
+ auto="False"
+ id="purchase.report_purchase_order"
+ model="purchase.order"
+ name="purchase.order"
+ rml="purchase_order_pick_up_date/report/order.rml"
+ string="Purchase Order" />
+ </data>
+</openerp>
=== added file 'purchase_order_pick_up_date/purchase_order_pick_up_date_view.xml'
--- purchase_order_pick_up_date/purchase_order_pick_up_date_view.xml 1970-01-01 00:00:00 +0000
+++ purchase_order_pick_up_date/purchase_order_pick_up_date_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<openerp>
+ <data>
+ <record id="purchase_order_pick_up_date_tree" model="ir.ui.view">
+ <field name="name">purchase.order.pick.tree</field>
+ <field name="model">purchase.order</field>
+ <field name="inherit_id" ref="purchase.purchase_order_tree" />
+ <field name="arch" type="xml">
+ <field name="minimum_planned_date" position="after">
+ <field name="date_pick_up" />
+ </field>
+ </field>
+ </record>
+
+ <record id="purchase_order_pick_up_date_form" model="ir.ui.view">
+ <field name="name">purchase.order.pick.form</field>
+ <field name="model">purchase.order</field>
+ <field name="inherit_id" ref="purchase.purchase_order_form" />
+ <field name="arch" type="xml">
+ <field name="date_order" position="after">
+ <field name="date_pick_up" />
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'purchase_order_pick_up_date/report'
=== added file 'purchase_order_pick_up_date/report/order.rml'
--- purchase_order_pick_up_date/report/order.rml 1970-01-01 00:00:00 +0000
+++ purchase_order_pick_up_date/report/order.rml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,335 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<document filename="Purchase Order.pdf">
+ <template title="Purchase Order" author="Savoir-faire Linux (support@xxxxxxxxxxxxxxxxxxxx)" allowSplitting="20">
+ <pageTemplate id="first">
+ <frame id="first" x1="18.0" y1="42.0" width="535" height="758"/>
+ </pageTemplate>
+ </template>
+ <stylesheet>
+ <blockTableStyle id="Standard_Outline">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <blockTableStyle id="Tableau1">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <blockTableStyle id="Tableau2">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <blockTableStyle id="Header_Order_Reference_Tbl">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="0,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="0,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="1,0" stop="1,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="1,0" stop="1,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="2,0" stop="2,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="2,0" stop="2,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="3,0" stop="3,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
+ <lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="4,0" stop="4,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ </blockTableStyle>
+ <blockTableStyle id="Content_Order_Reference_Table">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="0,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="0,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="1,0" stop="1,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="1,0" stop="1,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="2,0" stop="2,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="2,0" stop="2,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="3,0" stop="3,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
+ <lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="4,0" stop="4,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ </blockTableStyle>
+ <blockTableStyle id="Table_Header_Pur_ord_Line">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="4,-1" stop="4,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="5,-1" stop="5,-1"/>
+ </blockTableStyle>
+ <blockTableStyle id="Table_Order_Pur_line_Content">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="5,-1" stop="5,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="5,-1" stop="5,-1"/>
+ </blockTableStyle>
+ <blockTableStyle id="Table_All_Total_Detail">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEABOVE" colorName="#ffffff" start="0,0" stop="0,0"/>
+ <lineStyle kind="LINEABOVE" colorName="#000000" start="1,0" stop="1,0"/>
+ <lineStyle kind="LINEABOVE" colorName="#000000" start="2,0" stop="2,0"/>
+ <lineStyle kind="LINEABOVE" colorName="#000000" start="1,2" stop="1,2"/>
+ <lineStyle kind="LINEABOVE" colorName="#000000" start="2,2" stop="2,2"/>
+ </blockTableStyle>
+ <blockTableStyle id="Table_Outer_Notes">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <initialize>
+ <paraStyle name="all" alignment="justify"/>
+ </initialize>
+ <paraStyle name="terp_header" fontSize="12.0" leading="15" alignment="LEFT" spaceBefore="12.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_tblheader_General" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="6.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_default_8" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_tblheader_General_Centre" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="6.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_tblheader_General_Right" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="6.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_default_Centre_8" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_9" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Bold_9" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Right_9" fontSize="9.0" leading="11" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Bold_9_Right" fontSize="9.0" leading="11" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <images/>
+ </stylesheet>
+ <story>
+ <pto>
+ <para style="terp_default_8">[[repeatIn(objects,'o')]]</para>
+ <para style="terp_default_8">[[ setLang(o.partner_id.lang) ]]</para>
+ <pto_header>
+ <blockTable colWidths="180.0,70.0,60.0,80.0,60.0,85.0" repeatRows="1" style="Table_Header_Pur_ord_Line">
+ <tr>
+ <td>
+ <para style="terp_tblheader_General"><b>Description</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General"><b>Taxes</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General"><b>Date Req.</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Right"><b>Qty</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Right"><b>Unit Price</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Right"><b>Net Price</b></para>
+ </td>
+ </tr>
+ </blockTable>
+ </pto_header>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ <blockTable colWidths="253.0,59.0,223.0" style="Tableau1">
+ <tr>
+ <td>
+ <blockTable colWidths="253.0" style="Tableau2">
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"><b>Shipping address :</b></para>
+ <para style="terp_default_9">[[ (o.dest_address_id and o.dest_address_id.name) or (o.warehouse_id and o.warehouse_id.name) or '']]</para>
+ <para style="terp_default_9">[[ (o.dest_address_id and display_address(o.dest_address_id)) or (o.warehouse_id and display_address(o.warehouse_id.partner_id)) or '']]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ </td>
+ <td>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ </td>
+ <td>
+ <para style="terp_default_9">[[ (o.partner_id and o.partner_id.title and o.partner_id.title.name) or '' ]] [[ (o.partner_id and o.partner_id.name) or '' ]]</para>
+ <para style="terp_default_9">[[ o.partner_id and display_address(o.partner_id) ]] </para>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ <para style="terp_default_9">Tel : [[ (o.partner_id.phone) or removeParentNode('para') ]]</para>
+ <para style="terp_default_9">Fax : [[ (o.partner_id.fax) or removeParentNode('para') ]]</para>
+ <para style="terp_default_9">TIN : [[ (o.partner_id.vat) or removeParentNode('para') ]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ <para style="terp_header"><b>[[ o.state=='draft' and removeParentNode('para') ]] Purchase Order Confirmation N° [[ o.name ]]</b></para>
+ <para style="terp_header"><b>[[ o.state<>'draft' and removeParentNode('para') ]] Request for Quotation N° [[ o.name ]]</b></para>
+ <para style="terp_default_8">
+ <font color="white"> </font>
+ </para>
+ <blockTable colWidths="106.8,106.8,106.8,106.8,106.8" style="Header_Order_Reference_Tbl">
+ <tr>
+ <td>
+ <para style="terp_tblheader_General_Centre"><b>Our Order Reference</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Centre"><b>Your Order Reference</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Centre"><b>Order Date</b></para>
+ </td>
+
+ <td>
+ <para style="terp_tblheader_General_Centre"><b>Pick Up Date</b></para>
+ </td>
+
+ <td>
+ <para style="terp_tblheader_General_Centre"><b>Validated By</b></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable colWidths="106.8,106.8,106.8,106.8,106.8" style="Content_Order_Reference_Table">
+ <tr>
+ <td>
+ <para style="terp_default_Centre_8">[[ o.name or '' ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Centre_8">[[ o.partner_ref or '' ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Centre_8">[[formatLang(o.date_order,date=True) ]]</para>
+ </td>
+
+ <td>
+ <para style="terp_default_Centre_8">[[ formatLang(o.date_pick_up, date=True) ]]</para>
+ </td>
+
+ <td>
+ <para style="terp_default_Centre_8">[[ (o.validator and o.validator.name) or '' ]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ <blockTable colWidths="180.0,70.0,60.0,80.0,60.0,85.0" repeatRows="1" style="Table_Header_Pur_ord_Line">
+ <tr>
+ <td>
+ <para style="terp_tblheader_General"><b>Description</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General"><b>Taxes</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General"><b>Date Req.</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Right"><b>Qty</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Right"><b>Unit Price</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Right"><b>Net Price</b></para>
+ </td>
+ </tr>
+ </blockTable>
+ <section>
+ <para style="terp_default_8">[[repeatIn(o.order_line,'line')]]</para>
+ <blockTable colWidths="180.0,70.0,60.0,80.0,60.0,85.0" style="Table_Order_Pur_line_Content">
+ <tr>
+ <td>
+ <para style="terp_default_9">[[ line.name ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_9">[[ ', '.join(map(lambda x: x.name, line.taxes_id)) ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_9">[[ formatLang( line.date_planned, date=True) ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Right_9">[[ formatLang(line.product_qty ) ]] [[ line.product_uom.name ]] </para>
+ </td>
+ <td>
+ <para style="terp_default_Right_9">[[ formatLang(line.price_unit, digits=get_digits(dp='Product Price') ) ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Right_9">[[ formatLang(line.price_subtotal, digits=get_digits(dp='Account'), currency_obj=o.pricelist_id.currency_id ) ]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ </section>
+ <blockTable colWidths="375.0,60.0,100.0" style="Table_All_Total_Detail">
+ <tr>
+ <td>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ </td>
+ <td>
+ <para style="terp_default_9">Net Total :</para>
+ </td>
+ <td>
+ <para style="terp_default_Right_9">[[ formatLang(o.amount_untaxed, digits=get_digits(dp='Account'), currency_obj=o.pricelist_id.currency_id ) ]]</para>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ </td>
+ <td>
+ <para style="terp_default_9">Taxes :</para>
+ </td>
+ <td>
+ <para style="terp_default_Right_9">[[ formatLang(o.amount_tax, dp='Account', currency_obj=o.pricelist_id.currency_id) ]]</para>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ </td>
+ <td>
+ <para style="terp_default_Bold_9"><b>Total :</b></para>
+ </td>
+ <td>
+ <para style="terp_default_Bold_9_Right"><b>[[ formatLang(o.amount_total, digits=get_digits(dp='Account') , currency_obj=o.pricelist_id.currency_id) ]]</b></para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_default_8">
+ <font color="white"> </font>
+ </para>
+ <blockTable colWidths="535.0" style="Table_Outer_Notes">
+ <tr>
+ <td>
+ <para style="terp_default_9">[[ format(o.notes or '') ]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ </pto>
+ </story>
+</document>
=== added file 'purchase_order_pick_up_date/report/request_quotation.rml'
--- purchase_order_pick_up_date/report/request_quotation.rml 1970-01-01 00:00:00 +0000
+++ purchase_order_pick_up_date/report/request_quotation.rml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<document filename="requestforquotation.pdf">
+ <template pageSize="(595.0,842.0)" title="Test" author="Savoir-faire Linux (support@xxxxxxxxxxxxxxxxxxxx)" allowSplitting="20">
+ <pageTemplate id="first">
+ <frame id="first" x1="23.0" y1="43.0" width="530" height="799"/>
+ </pageTemplate>
+ </template>
+ <stylesheet>
+ <blockTableStyle id="Standard_Outline">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <blockTableStyle id="Tableau1">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <blockTableStyle id="Tableau2">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+ <blockTableStyle id="Table_Product_Header_Title">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="2,-1" stop="2,-1"/>
+ </blockTableStyle>
+ <blockTableStyle id="Table_Product_Line">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ </blockTableStyle>
+ <initialize>
+ <paraStyle name="all" alignment="justify"/>
+ </initialize>
+ <paraStyle name="P1" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="Standard"/>
+ <paraStyle name="terp_header" fontSize="12.0" leading="15" alignment="LEFT" spaceBefore="12.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_tblheader_Details" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="6.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_default_8" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_tblheader_Details_Centre" fontSize="9.0" leading="11" alignment="CENTER" spaceBefore="6.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_default_9" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Bold_9" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Centre_9" fontSize="9.0" leading="11" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Right_9" fontSize="9.0" leading="11" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="Space bet user and signature" fontSize="4.0" leading="5" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <images/>
+ </stylesheet>
+ <story>
+ <para style="terp_default_9">[[repeatIn(objects,'order')]]</para>
+ <para style="terp_default_9">[[ setLang(order.partner_id.lang) ]]</para>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ <blockTable colWidths="250.0,59.0,221.0" style="Tableau1">
+ <tr>
+ <td>
+ <blockTable colWidths="250.0" style="Tableau2">
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"><b>Expected Delivery address:</b></para>
+ <para style="terp_default_9">[[ (order.dest_address_id and order.dest_address_id.name) or (order.warehouse_id and order.warehouse_id.name) or '']]</para>
+ <para style="P1">[[ order.dest_address_id and display_address(order.dest_address_id) ]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ </td>
+ <td>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ </td>
+ <td>
+ <para style="terp_default_9">[[ (order .partner_id and order.partner_id.title and order.partner_id.title.name) or '' ]] [[ (order .partner_id and order.partner_id.name) or '' ]] </para>
+ <para style="terp_default_9">[[ order.partner_id and display_address(order .partner_id) ]] </para>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ <para style="terp_default_9">Tel.: [[ (order.partner_id and order.partner_id.phone) or removeParentNode('para') ]]</para>
+ <para style="terp_default_9">Fax: [[ (order.partner_id and order.partner_id.fax) or removeParentNode('para') ]]</para>
+ <para style="P1">TVA: [[ (order.partner_id and order.partner_id.vat) or removeParentNode('para') ]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="Standard">
+ <font color="white"> </font>
+ </para>
+
+ <blockTable colWidths="524.0" style="Tableau1">
+ <tr>
+ <td>
+ <para style="terp_default_9">Expected Pick Up Date: [[ (order.date_pick_up and formatLang(order.date_pick_up, date=True)) or removeParentNode('para') and '']]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_header"><b>Request for Quotation : [[order.name]]</b></para>
+
+ <para style="terp_default_8">
+ <font color="white"> </font>
+ </para>
+
+ <blockTable colWidths="371.0,98.0,61.0" repeatRows="1" style="Table_Product_Header_Title">
+ <tr>
+ <td>
+ <para style="terp_tblheader_Details"><b>Description</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_Details_Centre"><b>Expected Date</b></para>
+ </td>
+ <td>
+ <para style="terp_tblheader_Details_Centre"><b>Qty</b></para>
+ </td>
+ </tr>
+ </blockTable>
+ <section>
+ <para style="terp_default_9">[[ repeatIn(order.order_line,'order_line') ]]</para>
+ <blockTable colWidths="371.0,98.0,61.0" style="Table_Product_Line">
+ <tr>
+ <td>
+ <para style="terp_default_9">[[ order_line.name ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Centre_9">[[ formatLang(order_line.date_planned, date = True) ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Right_9">
+ [[ formatLang(order_line.product_qty )]]
+ <i>[[ (order_line.product_uom and order_line.product_uom.name) or '' ]]</i>
+ </para>
+ </td>
+ </tr>
+ </blockTable>
+ </section>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ <para style="terp_default_9">[[ format(order.notes or '') ]]</para>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ <para style="terp_default_9">Regards,</para>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ <para style="Space bet user and signature">
+ <font color="white"> </font>
+ </para>
+ <para style="terp_default_9">[[ user.signature or '' ]]</para>
+ </story>
+</document>
=== added directory 'sale_improved_slip'
=== added file 'sale_improved_slip/__init__.py'
--- sale_improved_slip/__init__.py 1970-01-01 00:00:00 +0000
+++ sale_improved_slip/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import report
+import sale
=== added file 'sale_improved_slip/__openerp__.py'
--- sale_improved_slip/__openerp__.py 1970-01-01 00:00:00 +0000
+++ sale_improved_slip/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Improved Delivery Slip',
+ 'version': '0.1',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'sale',
+ 'description': """
+Improved Delivery Slip
+======================
+
+This module adds new information on delivery slips.
+""",
+ 'depends': [
+ 'base', 'account_accountant', 'sale', 'stock',
+ 'produce_details', 'purchase_lot_tracking', 'supplier_register_identification_number'
+ ],
+ 'data': [
+ 'sale_improved_slip_report.xml',
+ 'sale_improved_slip_view.xml',
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added directory 'sale_improved_slip/i18n'
=== added file 'sale_improved_slip/i18n/fr.po'
--- sale_improved_slip/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ sale_improved_slip/i18n/fr.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,266 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * sale_improved_slip
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-03-11 13:50+0000\n"
+"PO-Revision-Date: 2014-03-11 14:58-0500\n"
+"Last-Translator: Pierre Lamarche <pierre.lamarche@xxxxxxxxxxxxxxxxxxxx>\n"
+"Language-Team: \n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: \n"
+"X-Generator: Poedit 1.6.4\n"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "CHEP"
+msgstr "CHEP"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Floor"
+msgstr "Au Sol"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "CPC"
+msgstr "CPC"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Schedule Date"
+msgstr "Date Prévue"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Unit weight"
+msgstr "Poids unitaire"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Total crates:"
+msgstr "Total Caisses :"
+
+#. module: sale_improved_slip
+#: model:ir.actions.report.xml,name:sale_improved_slip.report_picking_list_out
+msgid "Delivery Slip"
+msgstr "Bon de Livraison"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid ""
+"We acknowledge that all marchandise received is in good condition. No claims "
+"after 24 hours."
+msgstr ""
+"Nous reconnaissons que toute la marchandise reçue est en bonne condition. "
+"Aucune réclamation ne sera accepté après 24 heures."
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Temperature:"
+msgstr "Température :"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Description"
+msgstr "Description"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Internal Shipment:"
+msgstr "Livraison Interne :"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Journal"
+msgstr "Journal"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Billing Address:"
+msgstr "Adresse de Facturation :"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Owner:"
+msgstr "Exploitant :"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Delivery Order:"
+msgstr "Bon de Livraison :"
+
+#. module: sale_improved_slip
+#: field:sale.order,client_purchase_order:0
+msgid "Client Purchase Order"
+msgstr "Bon de Commande d'Achat du Client"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Received"
+msgstr "Reçu"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Driver:"
+msgstr "Chauffeur :"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Comment:"
+msgstr "Commentaire :"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Client Purchase Order"
+msgstr "Bon de Commande d'Achat du Client"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Incoming Shipment:"
+msgstr "Camion en Réception :"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Shipped"
+msgstr "Livré"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Delivery Address:"
+msgstr "Adresse de Livraison :"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Command"
+msgstr "Commande"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Truck:"
+msgstr "Camion :"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Signature:_____________________________________________"
+msgstr "Signature : _____________________________________________"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Total weight:"
+msgstr "Poids total :"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Total"
+msgstr "Total"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Seller:"
+msgstr "Vendeur :"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Total price:"
+msgstr "Prix total :"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "#Lot"
+msgstr "#Lot"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Unit price"
+msgstr "Prix unitaire"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Order(Origin)"
+msgstr "Bon de commande (Origine)"
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "NIR:"
+msgstr "NIR :"
+
+#. module: sale_improved_slip
+#: model:ir.model,name:sale_improved_slip.model_sale_order
+msgid "Sales Order"
+msgstr "Bon de Commande"
+
+#~ msgid "Purchase Order Line"
+#~ msgstr "Ligne de Bon de Commande d'Achat"
+
+#~ msgid "Confirm"
+#~ msgstr "Confirmer"
+
+#~ msgid "Crates"
+#~ msgstr "Caisses"
+
+#~ msgid "Pallet"
+#~ msgstr "Palette"
+
+#~ msgid "State"
+#~ msgstr "État"
+
+#~ msgid "Draft"
+#~ msgstr "Brouillon"
+
+#~ msgid "Details"
+#~ msgstr "Détails"
+
+#~ msgid "Front Temperature"
+#~ msgstr "Température Avant"
+
+#~ msgid "Supplier"
+#~ msgstr "Fournisseurs"
+
+#~ msgid "Truck Composition"
+#~ msgstr "Composition du Camion"
+
+#~ msgid "Serial Number"
+#~ msgstr "Numéro de série"
+
+#~ msgid "Left Pallets"
+#~ msgstr "Palettes de gauche"
+
+#~ msgid "Pallets"
+#~ msgstr "Palettes"
+
+#~ msgid "Truck S/N"
+#~ msgstr "Numéro du Camion"
+
+#~ msgid "Name"
+#~ msgstr "Nom"
+
+#~ msgid "Trucks"
+#~ msgstr "Camions"
+
+#~ msgid "Search Truck"
+#~ msgstr "Rechercher un Camion"
+
+#~ msgid "Date of Arrival"
+#~ msgstr "Date d'Arrivée"
+
+#~ msgid "Right Pallets"
+#~ msgstr "Palettes de droite"
+
+#~ msgid "On Draft Truck"
+#~ msgstr "Camion en Brouillon"
+
+#~ msgid "Incoming Truck"
+#~ msgstr "Camion en Réception"
+
+#~ msgid "Done"
+#~ msgstr "Terminé"
+
+#~ msgid "Purchase Orders"
+#~ msgstr "Bon de Commande d'Achat"
=== added file 'sale_improved_slip/i18n/sale_improved_slip.pot'
--- sale_improved_slip/i18n/sale_improved_slip.pot 1970-01-01 00:00:00 +0000
+++ sale_improved_slip/i18n/sale_improved_slip.pot 2014-11-23 23:06:46 +0000
@@ -0,0 +1,192 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * sale_improved_slip
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-03-10 16:15+0000\n"
+"PO-Revision-Date: 2014-03-10 16:15+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: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "CHEP"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Floor"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "CPC"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Schedule Date"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Unit weight"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Total crates:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: model:ir.actions.report.xml,name:sale_improved_slip.report_picking_list_out
+msgid "Delivery Slip"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "We acknowledge that all marchandise received is in good condition. No claims after 24 hours."
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Temperature:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Description"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Internal Shipment:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Journal"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Billing Address:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Owner:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Delivery Order:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: field:sale.order,client_purchase_order:0
+msgid "Client Purchase Order"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Received"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Driver:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Comment:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Client Purchase Order"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Incoming Shipment:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Shipped"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Delivery Address:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Command"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Truck:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Signature:_____________________________________________"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Total weight:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Total"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Seller:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Total price:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "#Lot"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Unit price"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "Order(Origin)"
+msgstr ""
+
+#. module: sale_improved_slip
+#: report:stock.picking.list:0
+msgid "NIR:"
+msgstr ""
+
+#. module: sale_improved_slip
+#: model:ir.model,name:sale_improved_slip.model_sale_order
+msgid "Sales Order"
+msgstr ""
+
=== added directory 'sale_improved_slip/report'
=== added file 'sale_improved_slip/report/__init__.py'
--- sale_improved_slip/report/__init__.py 1970-01-01 00:00:00 +0000
+++ sale_improved_slip/report/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,1 @@
+import picking
=== added file 'sale_improved_slip/report/picking.py'
--- sale_improved_slip/report/picking.py 1970-01-01 00:00:00 +0000
+++ sale_improved_slip/report/picking.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import time
+
+from netsvc import Service
+from openerp.report import report_sxw
+
+class picking(report_sxw.rml_parse):
+
+ def __init__(self, cr, uid, name, context):
+ super(picking, self).__init__(cr, uid, name, context=context)
+
+ self.localcontext.update({
+ 'time': time,
+ 'total_crates': self.total_crates,
+ 'total_weight': self.total_weight,
+ 'get_product_desc': self.get_product_desc,
+ 'total_price': self.total_price,
+ 'to_int': self.to_int,
+ })
+
+ def total_crates(self, picking):
+ return sum(line.product_qty for line in picking.move_lines)
+
+ def total_weight(self, picking):
+ return sum(
+ line.product_qty * line.product_id.cond_weight
+ for line in picking.move_lines
+ )
+
+ def total_price(self, picking):
+ lst_sum = []
+ for no_line in range(len(picking.move_lines)):
+ line = picking.move_lines[no_line]
+ lst_sum.append(line.product_qty * line.sale_line_id.price_unit)
+ return sum(lst_sum)
+
+ def get_product_desc(self, move_line):
+ desc = move_line.product_id.name
+ if move_line.product_id.default_code:
+ desc = '[' + move_line.product_id.default_code + ']' + ' ' + desc
+ return desc
+
+ def to_int(self, num_float):
+ return int(num_float)
+
+del Service._services['report.stock.picking.list']
+
+report_sxw.report_sxw(
+ 'report.stock.picking.list',
+ 'stock.picking',
+ 'addons/sale_improved_slip/report/picking.rml',
+ parser=picking)
=== added file 'sale_improved_slip/report/picking.rml'
--- sale_improved_slip/report/picking.rml 1970-01-01 00:00:00 +0000
+++ sale_improved_slip/report/picking.rml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,427 @@
+<?xml version="1.0"?>
+<document filename="Packing List.pdf">
+ <template pageSize="(595.0,842.0)" title="Packing List" author="Savoir-faire Linux (support@xxxxxxxxxxxxxxxxxxxx)" allowSplitting="20">
+ <pageTemplate id="first">
+ <frame id="first" x1="0.0" y1="57.0" width="538" height="728"/>
+ </pageTemplate>
+ </template>
+ <stylesheet>
+ <blockTableStyle id="Standard_Outline">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Table_Address_detail">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Table_Title_String">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Header_Order_Reference_Tbl">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="GRID" colorName="#e6e6e6"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="General_Tbl">
+ <blockFont name="Courier-Bold" size="9"/>
+ <blockAlignment value="CENTER"/>
+ <blockValign value="MIDDLE"/>
+
+ <lineStyle kind="LINEABOVE" colorName="black" start="1,0" stop="2,0"/>
+ <lineStyle kind="LINEABOVE" colorName="black" start="0,1" stop="2,1"/>
+ <lineStyle kind="LINEABOVE" colorName="black" start="0,2" stop="2,2"/>
+ <lineStyle kind="LINEABOVE" colorName="black" start="0,3" stop="2,3"/>
+ <lineStyle kind="LINEBEFORE" colorName="black" start="0,1" stop="1,2"/>
+ <lineStyle kind="LINEBEFORE" colorName="black" start="1,0" stop="1,2"/>
+ <lineStyle kind="LINEBEFORE" colorName="black" start="2,0" stop="2,2"/>
+ <lineStyle kind="LINEBEFORE" colorName="black" start="3,0" stop="3,2"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Move_Line_Header">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="0,-1" stop="8,-1"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Move_Line_Contact_Assign_State">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="MIDDLE"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="8,-1"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Table1">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Table2">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEABOVE" colorName="#000000" start="1,0" stop="1,0"/>
+ <lineStyle kind="LINEABOVE" colorName="#000000" start="2,0" stop="2,0"/>
+ </blockTableStyle>
+
+ <initialize>
+ <paraStyle name="all" alignment="justify"/>
+ </initialize>
+ <paraStyle name="Standard" fontName="Helvetica"/>
+ <paraStyle name="Heading" fontName="Helvetica" fontSize="14.0" leading="17" spaceBefore="12.0" spaceAfter="6.0"/>
+ <paraStyle name="Text body" fontName="Helvetica" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="List" fontName="Helvetica" spaceBefore="0.0" spaceAfter="6.0"/>
+ <paraStyle name="Caption" fontName="Helvetica-Oblique" fontSize="12.0" leading="15" spaceBefore="6.0" spaceAfter="6.0"/>
+ <paraStyle name="Index" fontName="Helvetica"/>
+ <paraStyle name="terp_header" fontName="Helvetica-Bold" fontSize="12.0" leading="15" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_header_Centre" fontName="Helvetica-Bold" fontSize="12.0" leading="15" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_8" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Bold_8" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_tblheader_Details" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_tblheader_Details_Centre" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Centre_8" fontName="Helvetica" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Centre_9" fontName="Helvetica" fontSize="9.0" leading="11" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_tblheader_General" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="6.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_tblheader_General_Centre" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="Table Contents" fontName="Helvetica"/>
+ <paraStyle name="Footer" fontName="Helvetica"/>
+ <paraStyle name="Table Heading" fontName="Helvetica" alignment="CENTER"/>
+ <paraStyle name="Horizontal Line" fontName="Helvetica" fontSize="6.0" leading="8" spaceBefore="0.0" spaceAfter="14.0"/>
+ <paraStyle name="Heading 9" fontName="Helvetica-Bold" fontSize="75%" leading="NaN" spaceBefore="12.0" spaceAfter="6.0"/>
+ <paraStyle name="terp_tblheader_General_Right" fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_tblheader_Details_Right" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Right_8" fontName="Helvetica" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_header_Right" fontName="Helvetica-Bold" fontSize="15.0" leading="19" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_address" fontName="Helvetica" fontSize="10.0" leading="13" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_9" fontName="Helvetica" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Bold_9" fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_Right_9" fontName="Helvetica" fontSize="9.0" leading="11" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_2" fontName="Helvetica" fontSize="2.0" leading="3" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_5cm_Above_Space" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="6.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_default_1cm_above_space" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="3.0" spaceAfter="0.0"/>
+ <images/>
+ </stylesheet>
+ <story>
+ <pto>
+ <para style="terp_default_8">[[ repeatIn(objects,'picking') ]] </para>
+ <para style="terp_default_8">[[ setLang(objects.partner_id.lang) ]]</para>
+ <para style="terp_default_8">[[ picking.type == 'out' and picking.partner_id and setLang(picking.partner_id.lang) or '' ]]</para>
+ <para style="terp_default_9">
+ <font color="white"> </font>
+ </para>
+ <blockTable colWidths="269.0,269.0" style="Table_Address_detail">
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9">Delivery Address: [[ (picking.type == 'out' or removeParentNode('para')) and '' ]]</para>
+ <para style="terp_default_9">[[ (picking.partner_id and picking.partner_id.id and picking.partner_id.title.name) or '' ]] [[ picking.partner_id and picking.partner_id.id and picking.partner_id.name ]]</para>
+ <para style="terp_default_9">[[ picking.partner_id and display_address(picking.partner_id) ]]</para>
+ <para style="terp_default_9">[[ picking.partner_id.phone or picking.partner_id.email or removeParentNode('para')]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Bold_9">Billing Address:</para>
+ <para style="terp_default_9">[[ picking.move_lines[0].sale_line_id.order_id.partner_invoice_id and picking.move_lines[0].sale_line_id.order_id.partner_invoice_id.title.name or '' ]] [[ picking.move_lines[0].sale_line_id.order_id.partner_invoice_id and picking.move_lines[0].sale_line_id.order_id.partner_invoice_id.name or '' ]]</para>
+ <para style="terp_default_9">[[ picking.move_lines[0].sale_line_id.order_id.partner_invoice_id and display_address(picking.move_lines[0].sale_line_id.order_id.partner_invoice_id) ]] </para>
+ <para style="terp_default_9">[[ picking.move_lines[0].sale_line_id.order_id.partner_invoice_id.phone or picking.move_lines[0].sale_line_id.order_id.partner_invoice_id.email or removeParentNode('para')]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable colWidths="538.0" style="Table_Title_String">
+ <tr>
+ <td>
+ <para style="terp_header">Delivery Order: [[ (picking.type == 'out' or removeParentNode('para')) and '' ]] [[ picking.name ]]</para>
+ <para style="terp_header">Incoming Shipment: [[ (picking.type == 'in' or removeParentNode('para')) and '' ]] [[ picking.name ]]</para>
+ <para style="terp_header">Internal Shipment: [[ (picking.type == 'internal' or removeParentNode('para')) and '' ]] [[ picking.name ]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_default_5cm_Above_Space">
+ <font color="white"> </font>
+ </para>
+ <blockTable colWidths="104.8,104.8,115.0,104.8" style="Header_Order_Reference_Tbl">
+ <tr>
+ <td>
+ <para style="terp_tblheader_General_Centre">Journal</para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Centre">Order(Origin)</para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Centre">Schedule Date</para>
+ </td>
+ <td>
+ <para style="terp_tblheader_General_Centre">Client Purchase Order</para>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <para style="terp_default_Centre_8">[[ picking.stock_journal_id.name]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Centre_8">[[ picking.origin or '']]</para>
+ </td>
+ <td>
+ <para style="terp_default_Centre_8">[[ formatLang(picking.min_date,date_time = True) ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Centre_8">[[ picking.sale_id.client_purchase_order or '' ]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_default_5cm_Above_Space">
+ <font color="white"> </font>
+ </para>
+ <blockTable colWidths="50.0,50.0,50.0,200.0,60.0,60.0,60.0" repeatRows="1" style="Move_Line_Header">
+ <tr>
+ <td>
+ <para style="terp_tblheader_Details_Centre">Command</para>
+ </td>
+ <td>
+ <para style="terp_tblheader_Details_Centre">Shipped</para>
+ </td>
+ <td>
+ <para style="terp_tblheader_Details_Centre">Received</para>
+ </td>
+ <td>
+ <para style="terp_tblheader_Details">Description</para>
+ </td>
+ <td>
+ <para style="terp_tblheader_Details_Right">Unit price</para>
+ </td>
+ <td>
+ <para style="terp_tblheader_Details_Right">Unit weight</para>
+ </td>
+ <td>
+ <para style="terp_tblheader_Details_Right">#Lot</para>
+ </td>
+ </tr>
+ </blockTable>
+ <section>
+ <para style="terp_default_2">[[ repeatIn([line for line in picking.move_lines if (not line.scrapped)],'move_line') ]]</para>
+ <para style="terp_default_2">[[ (picking.move_lines!=[] and removeParentNode('para')) or removeParentNode('section')]]</para>
+ <blockTable colWidths="50.0,50.0,50.0,200.0,60.0,60.0,60.0" style="Move_Line_Contact_Assign_State">
+ <tr>
+ <td>
+ <para style="terp_default_9"><font face="Helvetica" size="9.0">[[ to_int(move_line.product_qty) ]]</font></para>
+ </td>
+ <td>
+ </td>
+ <td>
+ </td>
+ <td>
+ <para style="terp_default_9"><font face="Helvetica" size="9.0">[[ get_product_desc(move_line) ]] </font></para>
+ </td>
+ <td>
+ <para style="terp_default_Right_9">[[ move_line.sale_line_id.price_unit ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Right_9">[[ move_line.product_id.cond_weight or '0.0' ]]</para>
+ </td>
+ <td>
+ <para style="terp_default_Right_9">[[ move_line.sale_line_id.order_id.project_id.id or '']]</para>
+ </td>
+ </tr>
+ </blockTable>
+ </section>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable colWidths="1.6cm,1.6cm,1.6cm,7cm,6cm" rowHeights="0.5cm,0.5cm,0.5cm,0.5cm" style="General_Tbl">
+ <tr>
+ <td>
+ </td>
+ <td>
+ <para style="terp_default_Bold_9">Floor</para>
+ </td>
+ <td>
+ <para style="terp_default_Bold_9">Total</para>
+ </td>
+ <td>
+ <para style="terp_default_9">Temperature:</para>
+ </td>
+ <td>
+ <para style="terp_default_Bold_9">Total crates: [[ to_int(total_crates(picking)) or "0" ]]</para>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9">CPC</para>
+ </td>
+ <td>
+ </td>
+ <td>
+ </td>
+ <td>
+ <para style="terp_default_9">Owner:</para>
+ </td>
+ <td>
+ <para style="terp_default_Bold_9">Total weight: [[ total_weight(picking) or "0.0" ]]</para>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9">CHEP</para>
+ </td>
+ <td>
+ </td>
+ <td>
+ </td>
+ <td>
+ <para style="terp_default_9">Driver:</para>
+ </td>
+ <td>
+ <para style="terp_default_Bold_9">Seller: [[ picking.move_lines[0].sale_line_id.salesman_id.name ]]</para>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ </td>
+ <td>
+ </td>
+ <td>
+ </td>
+ <td>
+ <para style="terp_default_9">Truck:</para>
+ </td>
+ <td>
+ <para style="terp_default_Bold_9">NIR: [[ picking.partner_id.rin or '' ]]</para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_default_Bold_9">Total price: [[ formatLang(total_price(picking), digits=2, currency_obj=picking.move_lines[0].sale_line_id.order_id.currency_id) ]]</para>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_default_Bold_9"></para>
+ <para style="terp_default_9">Signature:_____________________________________________</para>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_default_9">We acknowledge that all marchandise received is in good condition. No claims after 24 hours.</para>
+ <blockTable>
+ <tr>
+ <td>
+ <para style="terp_default_Bold_9"></para>
+ </td>
+ </tr>
+ </blockTable>
+ <para style="terp_default_Bold_9">Comment:</para>
+ </pto>
+ </story>
+</document>
=== added file 'sale_improved_slip/sale.py'
--- sale_improved_slip/sale.py 1970-01-01 00:00:00 +0000
+++ sale_improved_slip/sale.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import fields, orm
+
+class sale(orm.Model):
+
+ _inherit = 'sale.order'
+
+ _columns = {
+ 'client_purchase_order': fields.char('Client Purchase Order', size=32),
+ }
=== added file 'sale_improved_slip/sale_improved_slip_report.xml'
--- sale_improved_slip/sale_improved_slip_report.xml 1970-01-01 00:00:00 +0000
+++ sale_improved_slip/sale_improved_slip_report.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<openerp>
+ <data>
+ <report
+ id="report_picking_list_out"
+ model="stock.picking.out"
+ name="stock.picking.list"
+ string="Delivery Slip"
+ rml="sale_improved_slip/report/picking.rml" />
+ </data>
+</openerp>
=== added file 'sale_improved_slip/sale_improved_slip_view.xml'
--- sale_improved_slip/sale_improved_slip_view.xml 1970-01-01 00:00:00 +0000
+++ sale_improved_slip/sale_improved_slip_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<openerp>
+ <data>
+ <record id="improved_sale_order" model="ir.ui.view">
+ <field name="name">Improved Sale Order</field>
+ <field name="model">sale.order</field>
+ <field name="inherit_id" ref="sale.view_order_form" />
+ <field name="arch" type="xml">
+ <field name="client_order_ref" position="after">
+ <field name="client_purchase_order" />
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'sale_landed_cost_per_pallet'
=== added file 'sale_landed_cost_per_pallet/__init__.py'
--- sale_landed_cost_per_pallet/__init__.py 1970-01-01 00:00:00 +0000
+++ sale_landed_cost_per_pallet/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,23 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import sale
=== added file 'sale_landed_cost_per_pallet/__openerp__.py'
--- sale_landed_cost_per_pallet/__openerp__.py 1970-01-01 00:00:00 +0000
+++ sale_landed_cost_per_pallet/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,50 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Sale Landed Cost per Pallet',
+ 'version': '1.1',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'Generic Modules/Purchases',
+ 'description': """
+Lets you manage product quantities using crates and pallets for sales
+=====================================================================
+
+This module modifies the sale module to let you manage product
+quantities by specifying a number of pallets and a number of crates
+per pallet.
+
+This also adds a 'Per Pallet' option to landed costs, in order to compute the
+landed costs per pallet.
+""",
+ 'depends': ['base', 'sale_landed_costs', ],
+ 'external_dependencies': {},
+ 'data': ['sale_cost_per_pallet_view.xml', ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'sale_landed_cost_per_pallet/sale.py'
--- sale_landed_cost_per_pallet/sale.py 1970-01-01 00:00:00 +0000
+++ sale_landed_cost_per_pallet/sale.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,96 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+
+from openerp.osv import orm, fields
+import openerp.addons.decimal_precision as dp
+
+
+class sale_order(orm.Model):
+ """Adding landed costs per pallet"""
+ _inherit = 'sale.order'
+
+ def _landed_cost_base_pallet(self, cr, uid, ids, name, args, context):
+ """Calculate total of landed costs per pallet"""
+ ret = {}
+ for line in self.browse(cr, uid, ids):
+ ret[line.id] = sum(costs.amount for costs in line.landed_cost_line_ids if costs.price_type == 'per_pallet')
+ return ret
+
+ _columns = {
+ 'landed_cost_base_pallet': fields.function(_landed_cost_base_pallet,
+ digits_compute=dp.get_precision('Account'),
+ string='Landed Costs Base Pallet'),
+ }
+
+
+class sale_order_line(orm.Model):
+ """Add pallet information to sale order lines"""
+ _inherit = 'sale.order.line'
+
+ def _product_quantity(self, cursor, user, ids, name, arg, context=None):
+ """Calculate quantity if there are pallets and crates per pallet"""
+ ret = {}
+ for line in self.browse(cursor, user, ids, context=context):
+ ret[line.id] = (line.nb_crates_per_pallet or 0) * (line.nb_pallets or 0)
+ return ret
+
+ def _landing_cost_order(self, cr, uid, ids, name, args, context):
+ """Compute Landing costs including palet costs"""
+ ret = super(sale_order_line, self)._landing_cost_order(cr, uid, ids, name, args, context)
+ lines = self.browse(cr, uid, ids)
+ # Pre-compute total number of pallets
+ pallets_total = sum(line.nb_pallets for line in lines if line.order_id.landed_cost_line_ids)
+ # Landed costs line by line
+ for line in lines:
+ if line.order_id.landed_cost_line_ids and pallets_total:
+ ret[line.id] += line.order_id.landed_cost_base_pallet/pallets_total * line.nb_pallets
+ return ret
+
+ _columns = {
+ 'nb_pallets': fields.float('Pallets', required=True),
+ 'nb_crates_per_pallet': fields.integer('Crates per pallet', required=True),
+ 'product_uom_qty': fields.function(_product_quantity,
+ digits_compute=dp.get_precision('Product Unit of Measure'),
+ string="Quantity",
+ type='float'),
+ 'landing_costs_order': fields.function(_landing_cost_order,
+ digits_compute=dp.get_precision('Account'),
+ string='Landing Costs from Order'),
+ }
+
+
+class landed_cost_position(orm.Model):
+ """Add price types"""
+ _inherit = 'landed.cost.position'
+ _columns = {
+ 'price_type': fields.selection([('per_pallet', 'Per Pallet'),
+ ('per_unit', 'Per Quantity'),
+ ('value', 'Absolute Value')],
+ 'Amount Type',
+ required=True,
+ help="""\
+Defines if the amount is to be calculated for each quantity or an absolute value"""),
+ }
+ _defaults = {
+ 'price_type': 'per_pallet',
+ }
=== added file 'sale_landed_cost_per_pallet/sale_cost_per_pallet_view.xml'
--- sale_landed_cost_per_pallet/sale_cost_per_pallet_view.xml 1970-01-01 00:00:00 +0000
+++ sale_landed_cost_per_pallet/sale_cost_per_pallet_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="view_sale_pallet_crate_order_line" model="ir.ui.view">
+ <field name="name">sale.order.form</field>
+ <field name="model">sale.order</field>
+ <field name="inherit_id" ref="sale.view_order_form"/>
+ <field name="arch" type="xml">
+ <xpath expr="//tree//field[@name='product_uom_qty']" position="before">
+ <field name="nb_pallets"/>
+ <field name="nb_crates_per_pallet"/>
+ </xpath>
+ </field>
+ </record>
+
+ <record id="view_sale_pallet_crate_thing" model="ir.ui.view">
+ <field name="name">sale.order.landing.form</field>
+ <field name="model">sale.order</field>
+ <field name="inherit_id" ref="sale_landed_costs.sale_order_landed_cost_view" />
+ <field name="arch" type="xml">
+ <field name="landed_cost_base_value" position="after">
+ <field name="landed_cost_base_pallet" />
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'sale_lot_available'
=== added file 'sale_lot_available/__init__.py'
--- sale_lot_available/__init__.py 1970-01-01 00:00:00 +0000
+++ sale_lot_available/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import wizard
=== added file 'sale_lot_available/__openerp__.py'
--- sale_lot_available/__openerp__.py 1970-01-01 00:00:00 +0000
+++ sale_lot_available/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,43 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'sale_lot_available',
+ 'version': '0.1',
+ 'author': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'sale',
+ 'description': """
+Show available quantities per lot on outbound pickings
+======================================================
+
+This changes the way lot selection is displayed to add available quantities
+when splitting an outbound picking.
+""",
+ 'depends': ['base', 'analytic', 'sale', 'stock', 'purchase_lot_tracking'],
+ 'data': [
+ 'wizard/stock_move_view.xml',
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added directory 'sale_lot_available/wizard'
=== added file 'sale_lot_available/wizard/__init__.py'
--- sale_lot_available/wizard/__init__.py 1970-01-01 00:00:00 +0000
+++ sale_lot_available/wizard/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,1 @@
+import stock_move
=== added file 'sale_lot_available/wizard/stock_move.py'
--- sale_lot_available/wizard/stock_move.py 1970-01-01 00:00:00 +0000
+++ sale_lot_available/wizard/stock_move.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from collections import defaultdict
+
+from openerp.osv import fields, orm
+
+class stock_production_lot(orm.Model):
+
+ _inherit = 'stock.production.lot'
+
+ def name_get(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+
+ # Only override regular behaviour if on stock split wizard
+ view_id = self.fields_view_get(cr, uid)['view_id']
+ view = self.pool.get('ir.ui.view').browse(cr, uid, view_id, context=context)
+ if view.model != 'stock.production.lot':
+ return super(stock_production_lot, self).name_get(cr, uid, ids, context=context)
+
+ if isinstance(ids, (int, long)):
+ ids = [ids]
+
+ if not context.has_key('available'):
+ return super(stock_production_lot, self).name_get(cr, uid, ids, context=context)
+
+ entered = defaultdict(lambda: 0.0)
+ """
+ if not ids:
+ return []
+
+ # ignore ids, redo the research to get all the product
+ # ignore negative stock_available
+ product_id = self.read(cr, uid, ids[0], context=context)['product_id'][0]
+ ids = self.search(cr, uid, [['product_id', '=', product_id], ['stock_available', '>', 0]], context=context)
+
+ for line in context['lines']:
+ values = line[2]
+ entered[values['prodlot_id']] += values['quantity']
+ """
+
+ res = []
+ limit = 10
+ count_limit = 0
+ move_lines_obj = self.pool.get('stock.move')
+ for lot in self.browse(cr, uid, ids, context=context):
+ # remove other draft stock.move prodlot
+ move_lines_ids = move_lines_obj.search(cr, uid, [('prodlot_id', '=', lot.id)], context=context)
+ move_lines = move_lines_obj.browse(cr, uid, move_lines_ids, context=context)
+ other_qty = sum([move.product_qty for move in move_lines if move.state in ['draft', 'waiting', 'confirmed', 'assigned']])
+ net_available = lot.stock_available - entered[lot.id] - other_qty
+ if count_limit >= limit:
+ break
+ """
+ if net_available > 0:
+ count_limit += 1
+ res.append((lot.id, '%s / %.2f' % (lot.name, net_available)))
+ """
+ res.append((lot.id, '%s / %.2f' % (lot.name, net_available)))
+
+ return res
=== added file 'sale_lot_available/wizard/stock_move_view.xml'
--- sale_lot_available/wizard/stock_move_view.xml 1970-01-01 00:00:00 +0000
+++ sale_lot_available/wizard/stock_move_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<openerp>
+ <data>
+ <record id="lot_available_move_wizard" model="ir.ui.view">
+ <field name="name">stock.move.split.available</field>
+ <field name="model">stock.move.split</field>
+ <field name="inherit_id" ref="stock.view_split_in_lots" />
+ <field name="arch" type="xml">
+ <field name="prodlot_id" position="replace">
+ <field name="prodlot_id" string="Serial Number" quick_create="false" domain="[('product_id','=',parent.product_id)]" on_change="onchange_lot_id(prodlot_id, quantity, parent.location_id, parent.product_id, parent.product_uom, context)" context="{'lines': parent.line_exist_ids, 'product_id': parent.product_id, 'available': 1}"/>
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'sale_warn_under'
=== added file 'sale_warn_under/__init__.py'
--- sale_warn_under/__init__.py 1970-01-01 00:00:00 +0000
+++ sale_warn_under/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import sale
+import wizard
=== added file 'sale_warn_under/__openerp__.py'
--- sale_warn_under/__openerp__.py 1970-01-01 00:00:00 +0000
+++ sale_warn_under/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Sale warn under',
+ 'version': '0.1',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'sale',
+ 'description': """
+""",
+ 'depends': ['base', 'sale', 'purchase_lot_tracking'],
+ 'data': [
+ 'security/ir.model.access.csv',
+ 'wizard/sale_wizard.xml',
+ 'sale_warn_under_view.xml',
+ ],
+ 'css': [
+ 'static/src/css/wizard.css'
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added directory 'sale_warn_under/i18n'
=== added file 'sale_warn_under/i18n/fr.po'
--- sale_warn_under/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ sale_warn_under/i18n/fr.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,86 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * sale_warn_under
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:24+0000\n"
+"PO-Revision-Date: 2013-09-18 14:24+0000\n"
+"Last-Translator: Alexandre Boily <alexandre.boily@xxxxxxxxxxxxxxxxxxxx>\n"
+"Language-Team: Savoir-faire Linux\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: sale_warn_under
+#: view:sale.order.warn:0
+msgid "Confirm"
+msgstr "Confirmer"
+
+#. module: sale_warn_under
+#: model:ir.model,name:sale_warn_under.model_sale_order_warn
+msgid "Sale Order Warn"
+msgstr "Avertissement sur devis"
+
+#. module: sale_warn_under
+#: code:addons/sale_warn_under/sale.py:62
+#, python-format
+msgid "Sale Under Minimum Warning"
+msgstr "Avertissement sur vente à perte"
+
+#. module: sale_warn_under
+#: model:ir.actions.act_window,name:sale_warn_under.action_view_sale_warn_under
+msgid "action view name"
+msgstr "action view name"
+
+#. module: sale_warn_under
+#: field:sale.order.warn,sale_order_id:0
+msgid "unknown"
+msgstr "inconnu"
+
+#. module: sale_warn_under
+#: view:sale.order.warn:0
+msgid "Please explain why the following lines are being sold at a unit\n"
+" price lower than the minimum current stock price."
+msgstr "Veuillez expliquer pourquoi les lignes suivantes sont vendues à un prix unitaire plus bas que le minimum enregistré dans l'entrepôt."
+
+#. module: sale_warn_under
+#: field:sale.order.line,under_minimum_reason:0
+msgid "Reason"
+msgstr "Raison"
+
+#. module: sale_warn_under
+#: view:sale.order.warn:0
+msgid "Details"
+msgstr "Détails"
+
+#. module: sale_warn_under
+#: field:sale.order.line,under_id:0
+#: field:sale.order.warn,order_line_id:0
+msgid "Justifications"
+msgstr "Justifications"
+
+#. module: sale_warn_under
+#: view:sale.order.warn:0
+msgid "Cancel"
+msgstr "Annuler"
+
+#. module: sale_warn_under
+#: code:addons/sale_warn_under/sale.py:82
+#: model:ir.model,name:sale_warn_under.model_sale_order
+#, python-format
+msgid "Sales Order"
+msgstr "Commande de vente"
+
+#. module: sale_warn_under
+#: model:ir.model,name:sale_warn_under.model_sale_order_line
+msgid "Sales Order Line"
+msgstr "Ligne de commande de vente"
+
+#. module: sale_warn_under
+#: view:sale.order:0
+msgid "Confirm Order"
+msgstr "Confirmer la commande"
=== added file 'sale_warn_under/i18n/sale_warn_under.pot'
--- sale_warn_under/i18n/sale_warn_under.pot 1970-01-01 00:00:00 +0000
+++ sale_warn_under/i18n/sale_warn_under.pot 2014-11-23 23:06:46 +0000
@@ -0,0 +1,87 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * sale_warn_under
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:24+0000\n"
+"PO-Revision-Date: 2013-09-18 14:24+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: sale_warn_under
+#: view:sale.order.warn:0
+msgid "Confirm"
+msgstr ""
+
+#. module: sale_warn_under
+#: model:ir.model,name:sale_warn_under.model_sale_order_warn
+msgid "Sale Order Warn"
+msgstr ""
+
+#. module: sale_warn_under
+#: code:addons/sale_warn_under/sale.py:62
+#, python-format
+msgid "Sale Under Minimum Warning"
+msgstr ""
+
+#. module: sale_warn_under
+#: model:ir.actions.act_window,name:sale_warn_under.action_view_sale_warn_under
+msgid "action view name"
+msgstr ""
+
+#. module: sale_warn_under
+#: field:sale.order.warn,sale_order_id:0
+msgid "unknown"
+msgstr ""
+
+#. module: sale_warn_under
+#: view:sale.order.warn:0
+msgid "Please explain why the following lines are being sold at a unit\n"
+" price lower than the minimum current stock price."
+msgstr ""
+
+#. module: sale_warn_under
+#: field:sale.order.line,under_minimum_reason:0
+msgid "Reason"
+msgstr ""
+
+#. module: sale_warn_under
+#: view:sale.order.warn:0
+msgid "Details"
+msgstr ""
+
+#. module: sale_warn_under
+#: field:sale.order.line,under_id:0
+#: field:sale.order.warn,order_line_id:0
+msgid "Justifications"
+msgstr ""
+
+#. module: sale_warn_under
+#: view:sale.order.warn:0
+msgid "Cancel"
+msgstr ""
+
+#. module: sale_warn_under
+#: code:addons/sale_warn_under/sale.py:82
+#: model:ir.model,name:sale_warn_under.model_sale_order
+#, python-format
+msgid "Sales Order"
+msgstr ""
+
+#. module: sale_warn_under
+#: model:ir.model,name:sale_warn_under.model_sale_order_line
+msgid "Sales Order Line"
+msgstr ""
+
+#. module: sale_warn_under
+#: view:sale.order:0
+msgid "Confirm Order"
+msgstr ""
+
=== added file 'sale_warn_under/sale.py'
--- sale_warn_under/sale.py 1970-01-01 00:00:00 +0000
+++ sale_warn_under/sale.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,92 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp import netsvc
+from openerp.osv import orm, fields
+from openerp.tools.translate import _
+
+class sale_order_line(orm.Model):
+
+ _inherit = 'sale.order.line'
+
+ _columns = {
+ 'under_minimum_reason': fields.text('Reason'),
+ 'under_id': fields.many2one('sale.order.warn', 'Justifications'),
+ }
+
+
+class sale_order(orm.Model):
+
+ _inherit = 'sale.order'
+
+ def action_confirm_warn(self, cr, uid, ids, context=None):
+ '''Either return a warning, or move along'''
+
+ if context is None:
+ context = {}
+
+ if isinstance(ids, (int, long)):
+ ids = [ids]
+
+ assert len(ids) == 1, 'This option should only be used for a single ID at a time.'
+
+ so_lines = self.browse(cr, uid, ids, context=context)[0].order_line
+
+ if any(line.price_unit < line.minimum for line in so_lines):
+ # If there is at least one line where the unit price is lower than
+ # the minimum price in stock, display the warning wizard requiring
+ # a comment over that price
+
+ active = self.browse(cr, uid, ids, context=context)[0].id
+
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': _('Sale Under Minimum Warning'),
+ 'res_model': 'sale.order.warn',
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'target': 'new',
+ 'nodestroy': True,
+ 'context': {'default_sale_order_id': active},
+ }
+
+ # Recreate original behaviour from core action_button_confirm()
+
+ wf_service = netsvc.LocalService('workflow')
+ wf_service.trg_validate(uid, 'sale.order', ids[0], 'order_confirm', cr)
+ self.action_wait(cr, uid, ids, context=context)
+
+ view_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'sale', 'view_order_form')
+ view_id = view_ref and view_ref[1] or False
+
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': _('Sales Order'),
+ 'res_model': 'sale.order',
+ 'res_id': ids[0],
+ 'view_type': 'form',
+ 'view_mode': 'form',
+ 'view_id': view_id,
+ 'target': 'current',
+ 'nodestroy': True,
+ }
+
+ return True
=== added file 'sale_warn_under/sale_warn_under_view.xml'
--- sale_warn_under/sale_warn_under_view.xml 1970-01-01 00:00:00 +0000
+++ sale_warn_under/sale_warn_under_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<openerp>
+ <data>
+ <record id="sale_warn_under_form" model="ir.ui.view">
+ <field name="name">sale.order.warn.form</field>
+ <field name="model">sale.order</field>
+ <field name="inherit_id" ref="sale.view_order_form" />
+ <field name="arch" type="xml">
+ <button name="action_button_confirm" position="replace">
+ <button name="action_confirm_warn" states="draft,sent" string="Confirm Order" type="object" groups="base.group_user" />
+ </button>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added file 'sale_warn_under/sale_warn_under_workflow.xml'
=== added directory 'sale_warn_under/security'
=== added file 'sale_warn_under/security/ir.model.access.csv'
--- sale_warn_under/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ sale_warn_under/security/ir.model.access.csv 2014-11-23 23:06:46 +0000
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_sale_order_warn,sale.order.warn,model_sale_order_warn,base.group_sale_salesman,1,1,1,0
\ No newline at end of file
=== added directory 'sale_warn_under/static'
=== added directory 'sale_warn_under/static/src'
=== added directory 'sale_warn_under/static/src/css'
=== added file 'sale_warn_under/static/src/css/wizard.css'
--- sale_warn_under/static/src/css/wizard.css 1970-01-01 00:00:00 +0000
+++ sale_warn_under/static/src/css/wizard.css 2014-11-23 23:06:46 +0000
@@ -0,0 +1,11 @@
+[role="dialog"] [data-id="name"] {
+ width: 10em;
+}
+
+[data-id="minimum"] {
+ width: 5em;
+}
+
+[data-id="price_unit"] {
+ width: 5em;
+}
=== added directory 'sale_warn_under/wizard'
=== added file 'sale_warn_under/wizard/__init__.py'
--- sale_warn_under/wizard/__init__.py 1970-01-01 00:00:00 +0000
+++ sale_warn_under/wizard/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,1 @@
+import sale_wizard
=== added file 'sale_warn_under/wizard/sale_wizard.py'
--- sale_warn_under/wizard/sale_wizard.py 1970-01-01 00:00:00 +0000
+++ sale_warn_under/wizard/sale_wizard.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,41 @@
+# FIXME license
+
+from openerp import netsvc
+from openerp.osv import fields, orm
+
+class sale_warn_under(orm.Model):
+
+ _name = 'sale.order.warn'
+ _description = 'Sale Order Warn'
+
+ def _default_order_line_id(self, cr, uid, context=None):
+ so_id = context['default_sale_order_id']
+ sol_pool = self.pool.get('sale.order.line')
+
+ # Get all Sale Order Lines for the current Sale Order
+ sol_ids = sol_pool.search(cr, uid, [('order_id', '=', so_id)], context=context)
+
+ # Filter for the relevant lines (unit price lower than minimum)
+ sol_ids = [line.id for line in sol_pool.browse(cr, uid, sol_ids, context=context)
+ if line.price_unit < line.minimum]
+
+ return sol_ids
+
+ def really_confirm(self, cr, uid, ids, context=None):
+ so_id = context['default_sale_order_id']
+
+ wf_service = netsvc.LocalService('workflow')
+ self.pool.get('sale.order')._workflow_signal(cr, uid, [so_id], 'order_confirm', context=context)
+ self.pool.get('sale.order').action_wait(cr, uid, [so_id], context=context)
+
+ return {'type': 'ir.actions.act_window_close'}
+
+ _columns = {
+ 'sale_order_id': fields.many2one('sale.order'),
+ 'order_line_id': fields.one2many('sale.order.line', 'under_id', 'Justifications'),
+ }
+
+ _defaults = {
+ 'order_line_id': lambda self, cr, uid, context=None: self._default_order_line_id(cr, uid, context=context),
+ }
+
=== added file 'sale_warn_under/wizard/sale_wizard.xml'
--- sale_warn_under/wizard/sale_wizard.xml 1970-01-01 00:00:00 +0000
+++ sale_warn_under/wizard/sale_wizard.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<openerp>
+ <data>
+ <record id="view_sale_warn_under" model="ir.ui.view">
+ <field name="name">sale.order.warn.wizard</field>
+ <field name="model">sale.order.warn</field>
+ <field name="arch" type="xml">
+ <form string="Details" version="7.0">
+ <p class="oe_gray">Please explain why the following lines are being sold at a unit
+ price lower than the minimum current stock price.</p>
+
+ <group>
+ <field name="sale_order_id" invisible="1" />
+
+ <field name="order_line_id" nolabel="1">
+ <tree editable="top" create="0" delete="0">
+ <field name="state" invisible="1" />
+ <field name="name" readonly="1" />
+ <field name="minimum" readonly="1" />
+ <field name="price_unit" readonly="1" />
+ <field name="under_minimum_reason" colspan="4" required="1" />
+ </tree>
+ </field>
+ </group>
+
+ <footer>
+ <button name="really_confirm" string="Confirm" type="object" class="or_highlight" />
+ <button string="Cancel" class="oe_link" special="cancel" />
+ </footer>
+ </form>
+ </field>
+ </record>
+
+ <record id="action_view_sale_warn_under" model="ir.actions.act_window">
+ <field name="name">action view name</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">sale.order.warn</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="view_id" ref="view_sale_warn_under" />
+ <field name="target">new</field>
+ </record>
+ </data>
+</openerp>
=== added directory 'stock_delivery_split'
=== added file 'stock_delivery_split/__init__.py'
--- stock_delivery_split/__init__.py 1970-01-01 00:00:00 +0000
+++ stock_delivery_split/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import wizard
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'stock_delivery_split/__openerp__.py'
--- stock_delivery_split/__openerp__.py 1970-01-01 00:00:00 +0000
+++ stock_delivery_split/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,42 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Stock Delivery Split',
+ 'version': '1.0',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'Manufacturing',
+ 'description': """\
+Allows for splitting deliveries to different locations
+""",
+ 'depends': ['stock'],
+ 'external_dependencies': {},
+ 'data': ['wizard/stock_move.xml'],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added directory 'stock_delivery_split/wizard'
=== added file 'stock_delivery_split/wizard/__init__.py'
--- stock_delivery_split/wizard/__init__.py 1970-01-01 00:00:00 +0000
+++ stock_delivery_split/wizard/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,25 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import stock_move
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'stock_delivery_split/wizard/stock_move.py'
--- stock_delivery_split/wizard/stock_move.py 1970-01-01 00:00:00 +0000
+++ stock_delivery_split/wizard/stock_move.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,75 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import fields, orm
+
+
+class split_in_production_lot(orm.TransientModel):
+ """Get location_dest_id from wizard and add to stock.move"""
+ _inherit = "stock.move.split"
+
+ def default_get(self, cr, uid, fields, context=None):
+ """Sets default destination location from stock.move"""
+ res = super(split_in_production_lot, self).default_get(cr, uid, fields, context)
+ if context.get('active_id'):
+ move = self.pool.get('stock.move').browse(cr, uid, context['active_id'], context=context)
+ if 'location_dest_id' in fields:
+ res.update({'location_dest_id': move.location_dest_id.id})
+ return res
+
+ _columns = {
+ 'location_dest_id': fields.many2one('stock.location', 'Destination Location'),
+ }
+
+ def split(self, cr, uid, ids, move_ids, context=None):
+ """Adds location to outputted moves"""
+ new_moves = super(split_in_production_lot, self).split(cr, uid, ids, move_ids, context)
+ move_obj = self.pool.get('stock.move')
+ for data in self.browse(cr, uid, ids, context=context):
+ if data.use_exist:
+ lines = [l for l in data.line_exist_ids if l]
+ else:
+ lines = [l for l in data.line_ids if l]
+ for current_move, line in zip(new_moves, lines):
+ move_obj.write(cr, uid, [current_move], {'location_dest_id': line.location_dest_id.id})
+ return new_moves
+
+
+class stock_move_split_lines_exist(orm.TransientModel):
+ """Adds location_dest_id to split view"""
+ _inherit = "stock.move.split.lines"
+ _columns = {
+ 'location_dest_id': fields.many2one('stock.location', 'Destination Location'),
+ }
+
+ def onchange_lot_id(self, cr, uid, ids, prodlot_id=False, product_qty=False, loc_id=False, product_id=False,
+ uom_id=False, context=None, location_dest_id=False, default_location_dest_id=False):
+ """Adds default location_dest_id based on parent's"""
+ res = super(stock_move_split_lines_exist, self).onchange_lot_id(cr, uid, ids, prodlot_id, product_qty, loc_id,
+ product_id, uom_id, context=context)
+ res['value'] = res.get('value') or {}
+ res['value']['location_dest_id'] = location_dest_id or default_location_dest_id
+ if not res['value']['location_dest_id']:
+ del res['value']['location_dest_id']
+ return res
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'stock_delivery_split/wizard/stock_move.xml'
--- stock_delivery_split/wizard/stock_move.xml 1970-01-01 00:00:00 +0000
+++ stock_delivery_split/wizard/stock_move.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+ <record id="view_split_in_lots" model="ir.ui.view">
+ <field name="name">Split in Serial Numbers</field>
+ <field name="model">stock.move.split</field>
+ <field name="inherit_id" ref="stock.view_split_in_lots"/>
+ <field name="arch" type="xml">
+ <form string="Split in Serial Numbers" version="7.0">
+ <field name="location_dest_id" invisible="1"/>
+ </form>
+ <xpath expr="//field[@name='line_exist_ids']/tree[@string='Serial Numbers']/field[@name='quantity']" position="after">
+ <field name="location_dest_id" domain="[('usage', '=', 'customer')]"/>
+ </xpath>
+ <xpath expr="//field[@name='line_exist_ids']//tree[@string='Serial Numbers']//field[@name='prodlot_id']" position="attributes">
+ <attribute name="on_change">
+ onchange_lot_id(prodlot_id, quantity, parent.location_id, parent.product_id,
+ parent.product_uom, context, location_dest_id, parent.location_dest_id)
+ </attribute>
+ </xpath>
+ <xpath expr="//field[@name='line_exist_ids']//tree[@string='Serial Numbers']//field[@name='quantity']" position="attributes">
+ <attribute name="on_change">
+ onchange_lot_id(prodlot_id, quantity, parent.location_id, parent.product_id,
+ parent.product_uom, context, location_dest_id, parent.location_dest_id)
+ </attribute>
+ </xpath>
+ <xpath expr="//field[@name='line_exist_ids']//form[@string='Serial Number']//field[@name='prodlot_id']" position="attributes">
+ <attribute name="on_change">
+ onchange_lot_id(prodlot_id, quantity, parent.location_id, parent.product_id,
+ parent.product_uom, context, location_dest_id, parent.location_dest_id)
+ </attribute>
+ </xpath>
+ <xpath expr="//field[@name='line_exist_ids']//form[@string='Serial Number']//field[@name='quantity']" position="attributes">
+ <attribute name="on_change">
+ onchange_lot_id(prodlot_id, quantity, parent.location_id, parent.product_id,
+ parent.product_uom, context, location_dest_id, parent.location_dest_id)
+ </attribute>
+ </xpath>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'stock_forecast'
=== added file 'stock_forecast/__init__.py'
--- stock_forecast/__init__.py 1970-01-01 00:00:00 +0000
+++ stock_forecast/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+import report
=== added file 'stock_forecast/__openerp__.py'
--- stock_forecast/__openerp__.py 1970-01-01 00:00:00 +0000
+++ stock_forecast/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Stock Forecast',
+ 'version': '0.1',
+ 'author': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'stock',
+ 'description': """
+""",
+ 'depends': ['base', 'stock', 'sale', 'purchase', 'sale_landed_cost_per_pallet', 'sale_order_dates'],
+ 'data': [
+ 'security/ir.model.access.csv',
+ 'report/stock_forecast_view.xml'
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added directory 'stock_forecast/report'
=== added file 'stock_forecast/report/__init__.py'
--- stock_forecast/report/__init__.py 1970-01-01 00:00:00 +0000
+++ stock_forecast/report/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+import stock_forecast
=== added file 'stock_forecast/report/stock.rml'
--- stock_forecast/report/stock.rml 1970-01-01 00:00:00 +0000
+++ stock_forecast/report/stock.rml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,244 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<document filename="Stock Forecast.pdf">
+ <template pageSize="(595.0,842.0)" title="Stock Forecast" author="Savoir-faire Linux" allowSplitting="20">
+ <pageTemplate id="first">
+ <frame id="first" x1="0.0" y1="57.0" width="538" height="728" />
+ </pageTemplate>
+ </template>
+
+ <stylesheet>
+ <blockTableStyle id="Standard_Outline">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Table_Address_detail">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Table_Title_String">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Header_Order_Reference_Tbl">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="0,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="0,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="1,0" stop="1,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="1,0" stop="1,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="2,0" stop="2,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="2,0" stop="2,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="3,0" stop="3,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
+ <lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="4,0" stop="4,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Content_Order_Reference_Table">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="0,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="0,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="1,0" stop="1,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="1,0" stop="1,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="2,0" stop="2,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="2,0" stop="2,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="3,0" stop="3,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="3,0" stop="3,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
+ <lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="4,0" stop="4,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="4,0" stop="4,0"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Move_Line_Header">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#000000" start="4,-1" stop="4,-1"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Move_Line_Contect_Assign_State">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Table1">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="3,-1" stop="3,-1"/>
+ <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="4,-1" stop="4,-1"/>
+ </blockTableStyle>
+
+ <blockTableStyle id="Table2">
+ <blockAlignment value="LEFT"/>
+ <blockValign value="TOP"/>
+ <lineStyle kind="LINEABOVE" colorName="#000000" start="1,0" stop="1,0"/>
+ <lineStyle kind="LINEABOVE" colorName="#000000" start="2,0" stop="2,0"/>
+ </blockTableStyle>
+
+ <initialize>
+ <paraStyle name="all" alignment="justify"/>
+ </initialize>
+
+ <paraStyle name="Standard" fontName="Helvetica"/>
+
+ <paraStyle
+ name="Heading"
+ fontName="Helvetica"
+ fontSize="14.0"
+ leading="17"
+ spaceBefore="12.0"
+ spaceAfter="6.0" />
+
+ <paraStyle name="Text body" fontName="Helvetica" spaceBefore="0.0" spaceAfter="6.0"/>
+
+ <paraStyle name="List" fontName="Helvetica" spaceBefore="0.0" spaceAfter="6.0"/>
+
+ <paraStyle
+ name="Caption"
+ fontName="Helvetica-Oblique" fontSize="12.0" leading="15" spaceBefore="6.0" spaceAfter="6.0"/>
+
+ <paraStyle name="Index" fontName="Helvetica"/>
+
+ <paraStyle
+ name="terp_header"
+ fontName="Helvetica-Bold" fontSize="12.0" leading="15" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+
+ <paraStyle
+ name="terp_header_Centre"
+ fontName="Helvetica-Bold"
+ fontSize="12.0" leading="15" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
+
+ <paraStyle
+ name="terp_default_8"
+ fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+
+ <paraStyle
+ name="terp_default_Bold_8"
+ fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+
+ <paraStyle
+ name="terp_tblheader_Details"
+ fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+
+ <paraStyle
+ name="terp_tblheader_Details_Centre"
+ fontName="Helvetica-Bold"
+ fontSize="9.0" leading="11" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
+
+ <paraStyle
+ name="terp_default_Centre_8"
+ fontName="Helvetica" fontSize="8.0" leading="10" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
+
+ <paraStyle
+ name="terp_default_Centre_9"
+ fontName="Helvetica" fontSize="9.0" leading="11" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
+
+ <paraStyle
+ name="terp_tblheader_General"
+ fontName="Helvetica-Bold"
+ fontSize="8.0"
+ leading="10"
+ alignment="LEFT"
+ spaceBefore="6.0"
+ spaceAfter="6.0" />
+
+ <paraStyle
+ name="terp_tblheader_General_Centre"
+ fontName="Helvetica-Bold"
+ fontSize="8.0"
+ leading="10"
+ alignment="CENTER"
+ spaceBefore="0.0"
+ spaceAfter="0.0" />
+
+ <paraStyle
+ name="Table Contents"
+ fontName="Helvetica" />
+
+ <paraStyle
+ name="Footer"
+ fontName="Helvetica" />
+
+ <paraStyle
+ name="Table Heading"
+ fontName="Helvetica"
+ alignment="CENTER" />
+
+ <paraStyle
+ name="Horizontal Line"
+ fontName="Helvetica"
+ fontSize="6.0"
+ leading="8"
+ spaceBefore="0.0"
+ spaceAfter="14.0" />
+
+ <paraStyle
+ name="Heading 9" fontName="Helvetica-Bold" fontSize="75%" leading="NaN" spaceBefore="12.0" spaceAfter="6.0"/>
+ <paraStyle
+ name="terp_tblheader_General_Right"
+ fontName="Helvetica-Bold" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle name="terp_tblheader_Details_Right"
+ fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle
+ name="terp_default_Right_8"
+ fontName="Helvetica" fontSize="8.0" leading="10" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle
+ name="terp_header_Right"
+ fontName="Helvetica-Bold" fontSize="15.0" leading="19" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle
+ name="terp_default_address"
+ fontName="Helvetica" fontSize="10.0" leading="13" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle
+ name="terp_default_9"
+ fontName="Helvetica" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle
+ name="terp_default_Bold_9"
+ fontName="Helvetica-Bold" fontSize="9.0" leading="11" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle
+ name="terp_default_Right_9"
+ fontName="Helvetica" fontSize="9.0" leading="11" alignment="RIGHT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle
+ name="terp_default_2"
+ fontName="Helvetica" fontSize="2.0" leading="3" alignment="LEFT" spaceBefore="0.0" spaceAfter="0.0"/>
+ <paraStyle
+ name="terp_default_5cm_Above_Space"
+ fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="6.0" spaceAfter="0.0"/>
+ <paraStyle
+ name="terp_default_1cm_above_space"
+ fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT" spaceBefore="3.0" spaceAfter="0.0"/>
+ <images/>
+ </stylesheet>
+
+ <story>
+ <pto>
+ <pto_header>
+ </pto_header>
+ </pto>
+ </story>
+</document>
=== added file 'stock_forecast/report/stock_forecast.py'
--- stock_forecast/report/stock_forecast.py 1970-01-01 00:00:00 +0000
+++ stock_forecast/report/stock_forecast.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,656 @@
+#-*- coding: utf-8 -*-
+import pytz
+from datetime import datetime, timedelta
+from dateutil.relativedelta import relativedelta
+from collections import defaultdict
+import cgi
+
+from openerp import tools, SUPERUSER_ID
+from openerp.osv import orm, fields
+from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
+from mako.template import Template
+
+# Si le incoming shipment est prévu pour pour les dates AVANT lesquelles
+# on produit le rapport, il n'est pas tenu en compte
+
+REPORT_TEMPLATE = u"""
+<form string="Model" version="7.0">
+ <style type="text/css">
+ td.nom_produit {
+ font-weight: bold;
+ font-size: 12pt;
+ padding: 5px;
+ }
+
+ td.prevision {
+ font-size: 8pt;
+ font-weight: bold;
+ border: 2px black solid;
+ vertical-align: middle;
+ padding: 5px;
+ }
+
+ td.datelabel {
+ text-align: right;
+ font-size: 11pt;
+ padding: 10px;
+ }
+
+ td.alert {
+ color: red;
+ }
+
+ td.warning {
+ color: orange;
+ }
+
+ font.draft {
+ color: green;
+ }
+
+ td.normal {
+ color: black;
+ }
+
+ td.stock {
+ text-align: center;
+ vertical-align: middle;
+ }
+
+ td.alivrer {
+ border: 1px black solid;
+ border-left: 2px black solid;
+ border-top: 2px black solid;
+ }
+
+ td.prevu {
+ border: 1px black solid;
+ border-top: 2px black solid;
+ }
+
+ td.arecevoir {
+ border: 1px black solid;
+ border-right: 2px black solid;
+ border-top: 2px black solid;
+ font-size: 8pt;
+ }
+ </style>
+ % if not display_table:
+ <div>No activity for this period</div>
+ % else:
+ <table>
+ <tr>
+ <td style="text-align: center; vertical-align: middle; "></td>
+ % for product in products:
+ % if product_activity[product.id]:
+ <td colspan="3" class="nom_produit">${product.name}</td>
+ % endif
+ % endfor
+ </tr>
+ <tr>
+ <td></td>
+ % for product in products:
+ % if product_activity[product.id]:
+ <td class="prevision">A livrer</td>
+ <td class="prevision">Stock prevu</td>
+ <td class="prevision">A recevoir</td>
+ % endif
+ % endfor
+ </tr>
+ % for day in days:
+ <tr>
+ <td class="datelabel">
+ ${day['date']}
+ </td>
+ % for product in products:
+ % if product_activity[product.id]:
+ <td class="stock alivrer ${day[product.id]['situation']}">
+ % if day[product.id]['outgoing']:
+ ${day[product.id]['outgoing']}
+ % endif
+ </td>
+ <td class="stock prevu ${day[product.id]['situation']}">
+ ${day[product.id]['forecasted']}
+ </td>
+ <td class="stock arecevoir ${day[product.id]['situation']}">
+ % if day[product.id]['incoming']:
+ ${day[product.id]['incoming']}
+ % if day[product.id]['incoming_draft']:
+ <font class="draft"> | </font>
+ % endif
+ % endif
+ % if day[product.id]['incoming_draft']:
+ <font class="draft">${day[product.id]['incoming_draft']}</font>
+ % endif
+ </td>
+ %endif
+ % endfor
+ </tr>
+
+ % for order in day['orders']:
+ <tr>
+ <td style="text-align: right; padding: 5px;">
+ ${order['label']}
+ </td>
+ % for product in products:
+ % if product_activity[product.id]:
+ <td style="border-bottom: 1px black solid; border-left: 2px black solid; text-align: center; vertical-align: middle; ">
+ % if order[product.id]:
+ ${order[product.id]}
+ % endif
+ </td>
+ <td style="border-bottom: 1px black solid; vertical-align: middle; "></td>
+ <td style="border-right: 2px black solid; border-bottom: 1px black solid; text-align: center; vertical-align: middle; "></td>
+ % endif
+ % endfor
+ </tr>
+ % endfor
+
+ % endfor
+ </table>
+ % endif
+</form>
+"""
+
+
+def tuple_string(my_tuple):
+ if len(my_tuple) == 1:
+ return str(my_tuple)[::-1].replace(',','',1)[::-1]
+ return str(my_tuple)
+
+
+class stock_forecast_config(orm.TransientModel):
+
+ _name = "stock.forecast.config"
+ _description = "Stock Forecast"
+
+ _columns = {
+ 'product_category': fields.many2one(
+ 'product.category', 'Product Category', required=False),
+ 'show_no_activity': fields.boolean(
+ 'Show products without activity', default=True),
+ 'start_date': fields.datetime('Start date'),
+ 'end_date': fields.datetime('End date')
+ }
+
+ _defaults = {
+ 'start_date': lambda *a: datetime.now().strftime('%Y-%m-%d'),
+ 'end_date': lambda *a: (
+ datetime.now() + timedelta(days=14)).strftime("%Y-%m-%d")
+ }
+
+ def analytic_account_chart_open_window(self, cr, uid, ids, context=None):
+ mod_obj = self.pool.get('ir.model.data')
+ act_obj = self.pool.get('ir.actions.act_window')
+ result_context = {}
+
+ if context is None:
+ context = {}
+
+ result = mod_obj.get_object_reference(
+ cr, uid, 'stock_forecast', 'action_stock_forecast_form2')
+
+ id = result and result[1] or False
+ result = act_obj.read(cr, uid, [id], context=context)[0]
+ data = self.read(cr, uid, ids, [])[0]
+
+ result_context.update({
+ 'product_category': data['product_category'][0]
+ })
+ result_context.update({'show_no_activity': data['show_no_activity']})
+ result_context.update({'start_date': data['start_date']})
+ result_context.update({'end_date': data['end_date']})
+ result['context'] = result_context
+
+ return result
+
+
+class stock_forecast(orm.Model):
+
+ _name = "stock.forecast"
+ _description = "Stock forecast"
+ _auto = False
+ _columns = {
+ 'product_category': fields.many2one(
+ 'product.category', 'Product Category', required=False),
+ 'show_no_activity': fields.boolean('Hide products without activity'),
+ 'start_date': fields.datetime('Start date'),
+ 'end_date': fields.datetime('End date')
+ }
+
+ def init(self, cr):
+ tools.drop_view_if_exists(cr, 'stock_forecast')
+ cr.execute("""
+ CREATE OR REPLACE view stock_forecast AS (
+ SELECT
+ 1 as id,
+ to_char(current_date, 'YYYY') as test
+ );
+ """)
+
+ def get_timestamp(self, cr, uid, user_date, context=None):
+ if context and context.get('tz'):
+ tz_name = context['tz']
+ else:
+ tz_name = self.pool.get('res.users').read(
+ cr, SUPERUSER_ID, uid, ['tz'])['tz']
+ if tz_name:
+ utc = pytz.timezone('UTC')
+ context_tz = pytz.timezone(tz_name)
+ user_datetime = user_date + relativedelta(hours=12.0)
+ local_timestamp = context_tz.localize(user_datetime, is_dst=False)
+ user_datetime = local_timestamp.astimezone(utc)
+ return user_datetime.strftime('%Y-%m-%d')
+ return user_date.strftime('%Y-%m-%d')
+
+
+ def get_order_info(self, cr, uid, context=None):
+
+ date_string = self.get_timestamp(cr, uid, context['datetime'])
+
+ order_ids = self.pool.get('sale.order').search(cr, uid, [('state', '=', 'draft'),
+ ('requested_date', '=', date_string)])
+
+ orders = self.pool.get('sale.order').browse(cr, uid, order_ids)
+
+ quantities = {}
+
+ for order in orders:
+ quantity = {}
+ for order_line in order.order_line:
+ qty = quantity.get(order_line.product_id.id, 0)
+ quantity[order_line.product_id.id] = order_line.nb_pallets * order_line.nb_crates_per_pallet + qty
+ # TODO: pas
+ quantities[order.id] = quantity
+
+ return orders, quantities
+
+
+ def get_picking_info(self, cr, uid, context=None):
+
+ date_string = self.get_timestamp(cr, uid, context['datetime'])
+
+
+ date_string = self.get_timestamp(cr, uid, context['datetime'], context)
+ product_ids = tuple_string(tuple(context['product_ids']))
+
+ stock_moves = """SELECT id
+ FROM stock_move
+ WHERE sale_line_id IS NOT NULL
+ AND date_trunc('day', date_expected) = '%s'::timestamp without time zone
+ AND product_id IN %s"""
+
+ stock_moves = stock_moves % (date_string, product_ids)
+
+
+ stock_pickings = """SELECT id
+ FROM stock_picking
+ WHERE id IN (
+ SELECT picking_id FROM stock_move
+ WHERE id IN (
+ %s
+ )
+ )
+ """
+
+ cr.execute(stock_moves)
+ stock_moves_ids = list(sum(cr.fetchall(), ()))
+
+ cr.execute(stock_pickings % stock_moves)
+ stock_picking_ids = list(sum(cr.fetchall(), ()))
+
+# sale_order_lines = """SELECT id FROM sale_order_line
+# WHERE id in (
+# SELECT sale_line_id FROM stock_move
+# WHERE id IN (
+# %s
+# )
+# )
+# """
+
+# sale_order_lines = sale_order_lines % stock_moves
+# cr.execute(sale_order_lines)
+# sale_order_line_ids = cr.fetchall()
+
+# sale_orders = """SELECT id FROM sale_order
+# WHERE id in (
+# SELECT order_id FROM sale_order_line
+# WHERE id IN (
+# %s
+# )
+# )
+# AND state = 'draft'
+# """
+#
+# stock_moves = """
+# SELECT id FROM stock_move
+# WHERE date_expected = %s
+# AND product_id in (%s)
+# """
+# stock_pickings = """
+# SELECT id FROM stock_picking
+# WHERE sale_id
+# """
+
+
+# cr.execute(stock_pickings % sale_order_lines)
+# sale_order_ids = list(sum(cr.fetchall(), ()))
+
+ stock_moves = self.pool.get('stock.move').browse(
+ cr, uid, stock_moves_ids)
+ stock_pickings = self.pool.get('stock.picking').browse(
+ cr, uid, stock_picking_ids)
+
+ quantities = {}
+
+ # Calculates the quantity of each product in every stock picking
+ for picking in stock_pickings:
+ quantity = {}
+
+ for move_line in picking.move_lines:
+ qty = quantity.get(move_line.product_id.id, 0)
+ quantity[move_line.product_id.id] = move_line.product_qty + qty
+
+ quantities[picking.id] = quantity
+
+
+# for order in sale_orders:
+# quantity = {}
+# matching_ol_ids = [so.id for so in order.order_line]
+# for order_line in order.order_line:
+# matching_moves = filter(
+# lambda x: x.product_id == order_line.product_id
+# and x.sale_line_id.id in matching_ol_ids,
+# stock_moves
+# )
+#
+# qty = quantity.get(order_line.product_id, 0)
+# quantity[order_line.product_id.id] = (
+# sum(m.product_qty for m in matching_moves) + qty)
+#
+# quantities[order.id] = quantity
+# return sale_orders, quantities
+ return stock_pickings, quantities
+
+
+ def get_stock_outgoing(self, cr, uid, exp_day, context=None):
+ date_string = self.get_timestamp(cr, uid, exp_day)
+
+ product_id = context['product_id']
+
+ query_sales = """SELECT SUM(sol.nb_pallets * sol.nb_crates_per_pallet)
+ FROM sale_order_line sol,
+ sale_order so
+ WHERE product_id = %s
+ AND sol.order_id = so.id
+ AND so.state = 'draft'
+ AND so.requested_date = '%s'"""
+ cr.execute(query_sales % (product_id, date_string))
+
+ sales_sum = cr.fetchone()[0] or 0
+
+ # TODO check sales as well
+ query = """SELECT SUM(product_qty)
+ FROM stock_move
+ WHERE product_id = %s
+ AND sale_line_id IS NOT NULL
+ AND date_trunc('day', date_expected) = '%s'::timestamp without time zone"""
+
+ cr.execute(query % (product_id, date_string))
+ result = cr.fetchone()[0] or 0
+ return int(result + sales_sum)
+
+ def get_stock_incoming(self, cr, uid, exp_day, context=None):
+ date_string = self.get_timestamp(cr, uid, exp_day)
+ product_id = context['product_id']
+
+ query = """SELECT SUM(sm.product_qty)
+ FROM stock_move sm,
+ stock_picking sp
+ WHERE sm.product_id = %s
+ AND sm.purchase_line_id IS NOT NULL
+ AND sm.picking_id = sp.id
+ AND date_trunc('day', sp.min_date) = '%s'
+ AND sp.state = 'assigned';"""
+
+ cr.execute(query % (product_id, date_string))
+ result = cr.fetchone()[0] or 0
+ return int(result)
+
+ def get_stock_incoming_draft(self, cr, uid, exp_day, context=None):
+ date_string = self.get_timestamp(cr, uid, exp_day)
+ product_id = context['product_id']
+ po_line_obj = self.pool.get("purchase.order.line")
+
+ po_line_ids = po_line_obj.search(cr, uid, [
+ ('state', 'in', ['draft', 'sent']),
+ ('product_id', '=', product_id),
+ ('date_planned', '=', date_string)], context=context)
+ po_lines = po_line_obj.browse(cr, uid, po_line_ids, context=context)
+ result = sum([line.product_qty for line in po_lines])
+ return result
+
+ def get_stock_forecast(self, cr, uid, exp_day, context=None):
+ po_line_obj = self.pool.get("purchase.order.line")
+ product_id = context['product_id']
+ product = self.pool.get('product.product').browse(
+ cr, uid, [product_id], context=context)[0]
+
+ day_before = exp_day + timedelta(days=-1)
+ date_before_string = self.get_timestamp(cr, uid, day_before)
+
+ today_string = self.get_timestamp(cr, uid, datetime.now(), context)
+
+ on_hand = product.qty_available
+ # purchase
+ incoming_pickings = self.pool.get('stock.picking').search(
+ cr, uid, [
+ ('min_date', '>=', today_string),
+ ('min_date', '<=', date_before_string),
+ ('state', '=', 'assigned')
+ ]
+ )
+
+ incoming_ids = self.pool.get('stock.move').search(
+ cr, uid, [
+ ('product_id', '=', product_id),
+ '!', ('purchase_line_id', '=', None),
+ ('date_expected', '>=', today_string),
+ ('date_expected', '<=', date_before_string),
+ ('picking_id', 'in', incoming_pickings)
+ ]
+ )
+
+ incoming = self.pool.get('stock.move').browse(cr, uid, incoming_ids)
+
+ incoming_total = sum(i.product_qty for i in incoming)
+
+ # add draft purchase
+ po_line_ids = po_line_obj.search(cr, uid, [
+ ('state', 'in', ['draft', 'sent']),
+ ('product_id', '=', product_id),
+ ('date_planned', '>=', today_string),
+ ('date_planned', '<=', date_before_string),
+ ], context=context)
+ po_lines = po_line_obj.browse(cr, uid, po_line_ids, context=context)
+ incoming_draft_total = sum([line.product_qty for line in po_lines])
+
+ outgoing_ids = self.pool.get('stock.move').search(
+ cr, uid, [
+ ('product_id', '=', product_id),
+ '!', ('sale_line_id', '=', None),
+ ('date_expected', '>=', today_string),
+ ('date_expected', '<=', date_before_string)
+ ]
+ )
+
+ outgoing = self.pool.get('stock.move').browse(cr, uid, outgoing_ids)
+#
+#
+ outgoing_orders = self.pool.get('sale.order').search(
+ cr, uid, [
+ ('requested_date', '>=', today_string),
+ ('requested_date', '<=', date_before_string),
+ ('state', '=', 'draft')
+ ]
+ )
+
+ outgoing_order_lines = self.pool.get('sale.order.line').search(
+ cr, uid, [
+ ('product_id', '=', product_id),
+ ('order_id', 'in', outgoing_orders),
+ ]
+ )
+
+# if date_before_string == '2013-11-14':
+# import pdb; pdb.set_trace()
+
+ order_lines = self.pool.get('sale.order.line').browse(cr, uid, outgoing_order_lines)
+
+ outgoing_total = sum(o.product_qty for o in outgoing) + sum(o.nb_pallets * o.nb_crates_per_pallet for o in order_lines)
+
+ forecasted = on_hand + incoming_total + incoming_draft_total - outgoing_total
+
+ return int(forecasted)
+
+ def get_situation(self, day_product):
+ there = day_product['forecasted'] + day_product['incoming'] + day_product['incoming_draft']
+
+ if day_product['outgoing'] > there:
+ return 'alert'
+ elif day_product['outgoing'] > day_product['forecasted']:
+ return 'warning'
+ else:
+ return 'normal'
+
+ def fields_view_get(
+ self, cr, uid, view_id=None, view_type='tree', context=None,
+ toolbar=False, submenu=False):
+ result = super(stock_forecast, self).fields_view_get(
+ cr, uid, view_id=view_id, view_type=view_type, context=context,
+ toolbar=toolbar, submenu=submenu)
+
+ today = datetime.now()
+
+ if context is None:
+ context = {}
+
+ start_date = datetime.strptime(
+ context.get(
+ 'start_date',
+ datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
+ "%Y-%m-%d %H:%M:%S")
+ end_date = datetime.strptime(
+ context.get(
+ 'end_date',
+ datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
+ '%Y-%m-%d %H:%M:%S')
+
+ categ_id = context.get('product_category', 1)
+ product_ids = self.pool.get('product.product').search(
+ cr, uid, [('categ_id', '=', categ_id)])
+ products = self.pool.get('product.product').browse(
+ cr, uid, product_ids)
+
+ show_products = context.get('show_no_activity', False)
+ product_activity = dict([(p.id, show_products) for p in products])
+
+ days = []
+ for day in range((end_date - start_date).days):
+ product_strings = []
+ exp_day = today + timedelta(days=day)
+
+ day_has_moves = False
+
+ day_values = {}
+ day_values['date'] = self.get_timestamp(cr, uid, exp_day)
+ day_values['orders'] = []
+
+ for product_id in product_ids:
+ day_product = {}
+
+ forecast_context = {
+ 'product_id': product_id,
+ 'datetime': exp_day
+ }
+
+ glob_context = context.copy()
+ glob_context.update(forecast_context)
+
+ product = self.pool.get('product.product').browse(
+ cr, uid, [product_id], context=context)[0]
+
+ day_product['forecasted'] = self.get_stock_forecast(
+ cr, uid, exp_day, context=glob_context)
+ day_product['outgoing'] = self.get_stock_outgoing(
+ cr, uid, exp_day, context=glob_context)
+ day_product['incoming'] = self.get_stock_incoming(
+ cr, uid, exp_day, context=glob_context)
+ day_product['incoming_draft'] = self.get_stock_incoming_draft(
+ cr, uid, exp_day, context=glob_context)
+ day_product['situation'] = self.get_situation(day_product)
+
+ if day_product['outgoing'] or day_product['incoming'] or day_product['incoming_draft']:
+ product_activity[product_id] = True
+
+ if day_product['outgoing'] > 0:
+ day_has_moves = True
+
+ day_values[product_id] = day_product
+
+ if day_has_moves:
+
+ orders, order_quantities = self.get_order_info(cr, uid, {
+ 'datetime': exp_day, 'product_ids': product_ids
+ })
+
+
+ order_lines, picking_quantities = self.get_picking_info(cr, uid, {
+ 'datetime': exp_day, 'product_ids': product_ids
+ })
+
+
+ def get_day_values(orders, quantities, model="stock.picking"):
+
+ day_values = []
+ for order in orders:
+
+ cells = []
+ order_values = {}
+ for product_id in product_ids:
+ qty = quantities[order.id].get(product_id, 0)
+ order_values[product_id] = int(qty)
+
+ customer_name = order.partner_id.name
+ order_label = "%s (%s)" % (order.name, customer_name)
+ order_values['label'] = order_label
+ order_values['link'] = "#id=%(id)s&view_type=form&model=%(model)s" % {'id': order.id, 'model': model}
+
+ day_values.append(order_values)
+ return day_values
+
+ day_values['orders'] = []
+ day_values['orders'].extend(get_day_values(orders,
+ order_quantities,
+ model='sale.order'))
+ day_values['orders'].extend(get_day_values(order_lines,
+ picking_quantities,
+ model="stock.picking.out"))
+ days.append(day_values)
+
+ display_table = True
+
+ if not any(product_activity.values()):
+ display_table = False
+
+ report = Template(REPORT_TEMPLATE).render_unicode(
+ products=products,
+ days=days,
+ product_activity=product_activity,
+ display_table=display_table,
+ )
+
+ if view_type == 'form':
+ result['arch'] = report.replace("&","")
+
+ return result
=== added file 'stock_forecast/report/stock_forecast_view.xml'
--- stock_forecast/report/stock_forecast_view.xml 1970-01-01 00:00:00 +0000
+++ stock_forecast/report/stock_forecast_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+ <data>
+
+ <!-- Formulaire -->
+ <record id="stock_forecast_form2" model="ir.ui.view">
+ <field eval="1" name="priority"/>
+ <field name="name">stock.forecast.form2</field>
+ <field name="model">stock.forecast</field>
+ <field name="arch" type="xml">
+ <tree string="Stock Forecast" create="false">
+ <field name="product_category" invisible="0"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="stock_forecast_form" model="ir.ui.view">
+ <field eval="1" name="priority" />
+ <field name="name">stock.forecast.form</field>
+ <field name="model">stock.forecast.config</field>
+ <field name="arch" type="xml">
+ <form string="Model" version="7.0">
+ <group string="Stock Forecast">
+ <field name="product_category" />
+ <field name="show_no_activity" />
+ <field name="start_date" />
+ <field name="end_date" />
+ </group>
+ <footer>
+ <button name="analytic_account_chart_open_window" string="Open Charts" type="object" class="oe_highlight"/>
+ or
+ <button string="Cancel" class="oe_link" special="cancel"/>
+ </footer>
+
+ </form>
+ </field>
+ </record>
+
+ <record id="action_stock_forecast_form2" model="ir.actions.act_window">
+ <field name="name">Stock Forecast</field>
+ <field name="res_model">stock.forecast</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="view_id" ref="stock_forecast_form"/>
+ </record>
+
+ <record id="action_stock_forecast_report_po" model="ir.actions.act_window">
+ <field name="name">Stock Forecast</field>
+ <field name="res_model">stock.forecast.config</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ </record>
+
+ <record id="action_stock_forecast_config" model="ir.actions.act_window">
+ <field name="name">Stock Forecast Config</field>
+ <field name="type">ir.actions.act_window</field>
+ <field name="res_model">stock.forecast.config</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="view_id" ref="stock_forecast_form"/>
+ <field name="target">new</field>
+ </record>
+
+ <menuitem action="action_stock_forecast_config"
+ id="menu_action_stock_forecast_config"
+ parent="stock.next_id_61" />
+
+ </data>
+</openerp>
=== added directory 'stock_forecast/security'
=== added file 'stock_forecast/security/ir.model.access.csv'
--- stock_forecast/security/ir.model.access.csv 1970-01-01 00:00:00 +0000
+++ stock_forecast/security/ir.model.access.csv 2014-11-23 23:06:46 +0000
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_stock_forecast,access_stock_forecast,model_stock_forecast,,1,1,1,1
\ No newline at end of file
=== added directory 'stock_lot_valuation'
=== added file 'stock_lot_valuation/__init__.py'
--- stock_lot_valuation/__init__.py 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2014 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import stock_lot_valuation
+import wizard
=== added file 'stock_lot_valuation/__openerp__.py'
--- stock_lot_valuation/__openerp__.py 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Stock Lot Valuation',
+ 'version': '1.0',
+ 'author': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'Stock',
+ 'description': """
+Creates a report with the product valuation by lot
+==================================================
+
+This module creates a report that shows the stock valuation between a certain
+period.
+
+Contribuitors:
+Joao Alfredo Gama Batista <joao.gama@xxxxxxxxxxxxxxxxxxxx>
+
+""",
+ 'depends': ['purchase_lot_tracking'],
+ 'data': [
+ 'wizard/stock_lot_valuation_wizard_view.xml',
+ 'stock_lot_valuation_view.xml',
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added directory 'stock_lot_valuation/i18n'
=== added file 'stock_lot_valuation/i18n/fr.po'
--- stock_lot_valuation/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/i18n/fr.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,131 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * stock_lot_valuation
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-09-11 12:29+0000\n"
+"PO-Revision-Date: 2014-09-11 11:38-0500\n"
+"Last-Translator: Pierre Lamarche <pierre.lamarche@xxxxxxxxxxxxxxxxxxxx>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: \n"
+"X-Generator: Poedit 1.5.4\n"
+
+#. module: stock_lot_valuation
+#: model:ir.model,name:stock_lot_valuation.model_stock_lot_valuation
+msgid "Stock Lot Valuation Report"
+msgstr "Rapport sur la Valeur des Lots du Stock"
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation:0
+msgid "Group By..."
+msgstr "Regroupé par"
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation:0
+msgid "product_qty"
+msgstr "Qté de Produit"
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation.wizard,date_start:0
+msgid "Start date"
+msgstr "Date de début"
+
+#. module: stock_lot_valuation
+#: model:ir.actions.act_window,name:stock_lot_valuation.action_stock_lot_valuation_wizard
+#: model:ir.ui.menu,name:stock_lot_valuation.menu_stock_lot_valuation
+#: view:stock.lot.valuation.wizard:0
+msgid "Stock Valuation by Lot"
+msgstr "Valeur du Stock par Lot"
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,product_qty:0
+msgid "Quantity on hand"
+msgstr "Qté en stock"
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation:0 field:stock.lot.valuation,product_id:0
+msgid "Product"
+msgstr "Produit"
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation:0
+msgid "Serial Number"
+msgstr "Numéro de série"
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,company_id:0
+msgid "Company"
+msgstr "Compagnie"
+
+#. module: stock_lot_valuation
+#: code:addons/stock_lot_valuation/wizard/stock_lot_valuation_wizard.py:48
+#: view:stock.lot.valuation:0
+#, python-format
+msgid "Stock Lot Valuation"
+msgstr "Valeur du Stock par Lot"
+
+#. module: stock_lot_valuation
+#: model:ir.model,name:stock_lot_valuation.model_stock_lot_valuation_wizard
+msgid "Stock Lot Valuation Wizard"
+msgstr "Assistant pour la valeur du Stock par Lot"
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,valuation:0
+msgid "Valuation"
+msgstr "Valeur"
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,name:0
+msgid "Name"
+msgstr "Nom"
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation:0
+msgid "valuation"
+msgstr "Valeur"
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation.wizard,date_end:0
+msgid "End date"
+msgstr "Date de fin"
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,location_dest_id:0
+msgid "Dest Location"
+msgstr "Emplacement de destination"
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,location_id:0
+msgid "Source Location"
+msgstr "Emplacement d'origine"
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,date:0
+msgid "Move date"
+msgstr "Date du mouvement"
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,move_id:0
+msgid "Stock Move"
+msgstr "Mouvement de stock"
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation.wizard:0
+msgid "Done"
+msgstr "Terminé"
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation.wizard:0
+msgid "Cancel"
+msgstr "Annule"
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,prodlot_id:0
+msgid "Lot #"
+msgstr "Lot #"
=== added file 'stock_lot_valuation/i18n/stock_lot_valuation.pot'
--- stock_lot_valuation/i18n/stock_lot_valuation.pot 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/i18n/stock_lot_valuation.pot 2014-11-23 23:06:46 +0000
@@ -0,0 +1,132 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * stock_lot_valuation
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2014-09-11 12:29+0000\n"
+"PO-Revision-Date: 2014-09-11 12:29+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: stock_lot_valuation
+#: model:ir.model,name:stock_lot_valuation.model_stock_lot_valuation
+msgid "Stock Lot Valuation Report"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation:0
+msgid "Group By..."
+msgstr ""
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation:0
+msgid "product_qty"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation.wizard,date_start:0
+msgid "Start date"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: model:ir.actions.act_window,name:stock_lot_valuation.action_stock_lot_valuation_wizard
+#: model:ir.ui.menu,name:stock_lot_valuation.menu_stock_lot_valuation
+#: view:stock.lot.valuation.wizard:0
+msgid "Stock Valuation by Lot"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,product_qty:0
+msgid "Quantity on hand"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation:0
+#: field:stock.lot.valuation,product_id:0
+msgid "Product"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation:0
+msgid "Serial Number"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,company_id:0
+msgid "Company"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: code:addons/stock_lot_valuation/wizard/stock_lot_valuation_wizard.py:48
+#: view:stock.lot.valuation:0
+#, python-format
+msgid "Stock Lot Valuation"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: model:ir.model,name:stock_lot_valuation.model_stock_lot_valuation_wizard
+msgid "Stock Lot Valuation Wizard"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,valuation:0
+msgid "Valuation"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,name:0
+msgid "Name"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation:0
+msgid "valuation"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation.wizard,date_end:0
+msgid "End date"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,location_dest_id:0
+msgid "Dest Location"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,location_id:0
+msgid "Source Location"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,date:0
+msgid "Move date"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,move_id:0
+msgid "Stock Move"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation.wizard:0
+msgid "Done"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: view:stock.lot.valuation.wizard:0
+msgid "Cancel"
+msgstr ""
+
+#. module: stock_lot_valuation
+#: field:stock.lot.valuation,prodlot_id:0
+msgid "Lot #"
+msgstr ""
+
=== added file 'stock_lot_valuation/stock_lot_valuation.py'
--- stock_lot_valuation/stock_lot_valuation.py 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/stock_lot_valuation.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,166 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2014 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+from openerp.tools.translate import _
+from openerp import tools
+
+
+class stock_lot_valuation(orm.Model):
+ """Stock Lot Valuation Report"""
+
+ _name = 'stock.lot.valuation'
+ _description = _(__doc__)
+ _auto = False
+
+ def _product_qty(self, cr, uid, ids, field, args, context=None):
+ context = context or {}
+
+ res = {}
+
+ location_id = self.pool.get('res.users').browse(
+ cr, uid, uid, context=context
+ ).company_id.partner_id.property_stock_customer.id
+
+ for line in self.browse(cr, uid, ids, context=context):
+ if line.move_id.location_id.id == location_id:
+ res[line.id] = line.move_id.product_qty
+ elif line.move_id.location_dest_id.id == location_id:
+ res[line.id] = line.move_id.product_qty * (-1)
+ else:
+ res[line.id] = 0.0
+
+ return res
+
+ _columns = {
+ 'name': fields.char('Name'),
+ 'move_id': fields.many2one('stock.move', 'Stock Move'),
+ 'product_id': fields.many2one('product.product', 'Product'),
+ 'prodlot_id': fields.many2one('stock.production.lot', 'Lot #'),
+ 'product_qty': fields.float('Quantity on hand'),
+ 'location_id': fields.many2one('stock.location', 'Source Location'),
+ 'location_dest_id': fields.many2one('stock.location', 'Dest Location'),
+ 'valuation': fields.float('Valuation'),
+ 'date': fields.datetime('Move date'),
+ 'company_id': fields.many2one('res.company', 'Company', readonly=True),
+ }
+
+ def init(self, cr):
+ tools.drop_view_if_exists(cr, 'stock_lot_valuation')
+ cr.execute("""
+ CREATE OR REPLACE FUNCTION get_company_stock_location(integer) RETURNS integer AS $$
+ DECLARE
+ company_id ALIAS FOR $1;
+ partner_rec RECORD;
+ property_rec RECORD;
+ res TEXT;
+ BEGIN
+ EXECUTE 'SELECT partner_id FROM res_company WHERE id = $1'
+ INTO partner_rec
+ USING company_id;
+
+ res := 'res.partner,'||partner_rec.partner_id;
+
+ SELECT a.value_reference INTO property_rec FROM ir_property a WHERE a.name = 'property_stock_customer' AND a.res_id = res;
+
+ RETURN substring(property_rec.value_reference from position(',' in property_rec.value_reference)+1)::integer;
+ END;
+ $$ LANGUAGE plpgsql;
+
+
+ CREATE OR REPLACE FUNCTION valuation_by_move(integer, integer) RETURNS numeric AS $$
+ DECLARE
+ move_id ALIAS FOR $1;
+ account_id ALIAS FOR $2;
+ valuation numeric;
+ aaa_values RECORD;
+ move_values RECORD;
+ BEGIN
+ EXECUTE 'SELECT
+ CASE
+ WHEN location_id = get_company_stock_location(company_id) THEN product_qty * -1
+ WHEN location_dest_id = get_company_stock_location(company_id) THEN product_qty
+ END AS product_qty
+ FROM stock_move
+ WHERE id = $1'
+ INTO move_values
+ USING move_id;
+
+ EXECUTE 'SELECT
+ a.id,
+ sum(
+ CASE WHEN l.amount > 0
+ THEN l.amount
+ ELSE 0.0
+ END
+ ) as debit,
+ sum(
+ CASE WHEN l.amount < 0
+ THEN -l.amount
+ ELSE 0.0
+ END
+ ) as credit,
+ COALESCE(SUM(l.amount),0) AS balance,
+ COALESCE(SUM(l.unit_amount),0) AS quantity,
+ total_in_qty,
+ total_cost_unit
+ FROM account_analytic_account a
+ LEFT JOIN account_analytic_line l ON (a.id = l.account_id)
+ WHERE a.id = $1
+ GROUP BY a.id'
+ INTO aaa_values
+ USING account_id;
+ valuation := aaa_values.total_cost_unit * move_values.product_qty;
+ RETURN valuation;
+ END;
+ $$ LANGUAGE plpgsql;
+
+ CREATE OR REPLACE VIEW stock_lot_valuation AS (
+ SELECT
+ a.id AS id,
+ a.id AS move_id,
+ b.name_template AS name,
+ a.product_id AS product_id,
+ a.prodlot_id,
+ a.location_id,
+ a.location_dest_id,
+ 12 AS stock_location_id,
+ CASE
+ WHEN a.location_id = get_company_stock_location(a.company_id) THEN a.product_qty * -1
+ WHEN a.location_dest_id = get_company_stock_location(a.company_id) THEN a.product_qty
+ END AS product_qty,
+ a.date,
+ valuation_by_move(a.id, c.id) as valuation,
+ date_trunc('day',a.create_date) as create_date,
+ a.company_id
+ FROM
+ stock_move a,
+ product_product b,
+ account_analytic_account c,
+ stock_production_lot d,
+ res_company f
+ WHERE
+ a.product_id = b.id AND
+ a.state = 'done' AND
+ a.prodlot_id = d.id AND
+ d.name = c.code AND
+ f.id = a.company_id
+ )""")
=== added file 'stock_lot_valuation/stock_lot_valuation_view.xml'
--- stock_lot_valuation/stock_lot_valuation_view.xml 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/stock_lot_valuation_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,45 @@
+<openerp>
+ <data>
+ <record id="view_stock_lot_valuation_tree" model="ir.ui.view">
+ <field name="name">Stock Lot Valuation</field>
+ <field name="model">stock.lot.valuation</field>
+ <field name="arch" type="xml">
+ <tree string="Stock Lot Valuation" create="false">
+ <field name="product_id" />
+ <field name="prodlot_id" />
+ <field name="move_id" />
+ <field name="product_qty" sum="product_qty"/>
+ <field name="valuation" sum="valuation"/>
+ </tree>
+ </field>
+ </record>
+
+ <record id="view_stock_lot_valuation_search" model="ir.ui.view">
+ <field name="name">Stock Lot Valuation</field>
+ <field name="model">stock.lot.valuation</field>
+ <field name="arch" type="xml">
+ <search>
+ <group expand="0" string="Group By...">
+ <filter string="Product" name="by_product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/>
+ <filter string="Serial Number" name="groupby_prodlot_id" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'prodlot_id'}"/>
+ </group>
+ </search>
+ </field>
+ </record>
+
+ <record id="action_stock_lot_valuation_wizard" model="ir.actions.act_window">
+ <field name="name">Stock Valuation by Lot</field>
+ <field name="res_model">stock.lot.valuation.wizard</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="target">new</field>
+ </record>
+
+ <menuitem id="menu_stock_lot_valuation"
+ name="Stock Valuation by Lot"
+ action="action_stock_lot_valuation_wizard"
+ parent="stock.next_id_61"/>
+
+ </data>
+</openerp>
+
=== added directory 'stock_lot_valuation/wizard'
=== added file 'stock_lot_valuation/wizard/__init__.py'
--- stock_lot_valuation/wizard/__init__.py 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/wizard/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2014 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import stock_lot_valuation_wizard
=== added file 'stock_lot_valuation/wizard/stock_lot_valuation_wizard.py'
--- stock_lot_valuation/wizard/stock_lot_valuation_wizard.py 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/wizard/stock_lot_valuation_wizard.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,64 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2014 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+from openerp.tools.translate import _
+
+
+class stock_lot_valuation_wizard(orm.TransientModel):
+ """Stock Lot Valuation Wizard"""
+
+ _name = 'stock.lot.valuation.wizard'
+ _description = _(__doc__)
+
+ _columns = {
+ 'date_start': fields.datetime('Start date'),
+ 'date_end': fields.datetime('End date'),
+ }
+
+ _defaults = {
+ 'date_end': fields.datetime.now
+ }
+
+ def done(self, cr, uid, ids, context=None):
+ context = context or {}
+
+ wizard = self.browse(cr, uid, ids[0], context=context)
+
+ return {
+ 'type': 'ir.actions.act_window',
+ 'name': _('Stock Lot Valuation'),
+ 'res_model': 'stock.lot.valuation',
+ 'view_type': 'form',
+ 'view_mode': 'tree',
+ 'target': 'current',
+ 'context': {
+ 'date_start': wizard.date_start,
+ 'date_end': wizard.date_end,
+ 'search_default_by_product': 1,
+ 'search_default_groupby_prodlot_id': 1,
+ 'group_by': []
+ },
+ 'domain': [
+ ('date', '>=', wizard.date_start),
+ ('date', '<=', wizard.date_end),
+ ]
+ }
=== added file 'stock_lot_valuation/wizard/stock_lot_valuation_wizard_view.xml'
--- stock_lot_valuation/wizard/stock_lot_valuation_wizard_view.xml 1970-01-01 00:00:00 +0000
+++ stock_lot_valuation/wizard/stock_lot_valuation_wizard_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,20 @@
+<openerp>
+ <data>
+ <record id="view_stock_lot_valuation_wizard_form" model="ir.ui.view">
+ <field name="name">Stock Valuation by Lot</field>
+ <field name="model">stock.lot.valuation.wizard</field>
+ <field name="arch" type="xml">
+ <form string="Stock Valuation by Lot" version="7.0">
+ <group>
+ <field name="date_start" />
+ <field name="date_end" />
+ </group>
+ <footer>
+ <button class="oe_highlight" name="done" string="Done" type="object" />
+ <button class="oe_link" special="cancel" string="Cancel" />
+ </footer>
+ </form>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'stock_move_autolot'
=== added file 'stock_move_autolot/__init__.py'
--- stock_move_autolot/__init__.py 1970-01-01 00:00:00 +0000
+++ stock_move_autolot/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,26 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###############################################################################
+
+import stock
+import account
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'stock_move_autolot/__openerp__.py'
--- stock_move_autolot/__openerp__.py 1970-01-01 00:00:00 +0000
+++ stock_move_autolot/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,41 @@
+# -*- encoding: utf-8 -*-
+###############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+###############################################################################
+
+{
+ 'name': 'Auto-Consume lot',
+ 'version': '1.0',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'Manufacturing',
+ 'description': """\
+Auto lot assignment when consuming product.
+""",
+ 'depends': ['mrp', 'purchase_lot_tracking'],
+ 'data': [],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'stock_move_autolot/account.py'
--- stock_move_autolot/account.py 1970-01-01 00:00:00 +0000
+++ stock_move_autolot/account.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,71 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+
+
+class account_analytic_account(orm.Model):
+ _inherit = 'account.analytic.account'
+
+ def _estimated_tcu(self, cr, uid, ids, name, arg, context=None):
+ # Pools
+ stock_move_pool = self.pool.get('stock.move')
+ po_line_pool = self.pool.get('purchase.order.line')
+
+ def transformed_tcu():
+
+ # Get the stock move id of the transformed product
+ stock_move_ids = stock_move_pool.search(cr, uid, [('prodlot_id.name', '=', line.code)], context=context)
+ if not stock_move_ids:
+ return 0
+ stock_move = stock_move_pool.browse(cr, uid, stock_move_ids[0], context=context)
+
+ # Get the stock move id of the initial product
+ # We can safely assume there is only one
+ if not stock_move.production_id:
+ return 0
+ initial_stock_move = stock_move.production_id.move_lines2[0]
+ initial_analytic_id = initial_stock_move.prodlot_id.account_analytic_id.id
+
+ """Get parent_po_line and calculate price based on transformation"""
+ parent_po_line_ids = po_line_pool.search(cr, uid, [('account_analytic_id', '=', initial_analytic_id)], context=context)
+ if not parent_po_line_ids:
+ return 0
+ parent_po_line = po_line_pool.browse(cr, uid, parent_po_line_ids[0], context=context)
+
+ # Calculate transformed price
+ return parent_po_line.landed_costs / (parent_po_line.product_qty * stock_move.production_id.bom_id.product_qty)
+
+ # Call super
+ res = super(account_analytic_account, self)._estimated_tcu(cr, uid, ids, name, arg, context)
+ for line in self.browse(cr, uid, ids):
+ if line.code.startswith('LOT') and not po_line_pool.search(cr, uid, [('account_analytic_id', '=', line.id)]):
+ res[line.id] = transformed_tcu()
+
+ return res
+
+ # Overwrite estimated_tcu
+ _columns = {
+ 'estimated_tcu': fields.function(_estimated_tcu, string='Estimated Total Cost per Unit', type='float'),
+ }
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'stock_move_autolot/stock.py'
--- stock_move_autolot/stock.py 1970-01-01 00:00:00 +0000
+++ stock_move_autolot/stock.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,86 @@
+# -*- encoding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm
+
+
+class stock_move(orm.Model):
+ _inherit = "stock.move"
+
+ def action_consume(self, cr, uid, ids, quantity, location_id=False, context=None):
+ """ Consumed product with specific quatity from specific source location
+ @param cr: the database cursor
+ @param uid: the user id
+ @param ids: ids of stock move object to be consumed
+ @param quantity : specify consume quantity
+ @param location_id : specify source location
+ @param context: context arguments
+ @return: Consumed lines
+ """
+ stock_move_obj = self.browse(cr, uid, ids, context=context)[0]
+ if stock_move_obj and stock_move_obj.location_id and stock_move_obj.location_id.name == 'Production':
+ self.autoassign_newlot(cr, uid, ids, stock_move_obj, context=context)
+ return super(stock_move, self).action_consume(cr, uid, ids, quantity, location_id, context=context)
+
+ def autoassign_newlot(self, cr, uid, ids, stock_move_obj, context=None):
+ """
+ Generate and assign a new stock_production_lot to consumable product.
+ @param self: The object pointer.
+ @param cr: A database cursor
+ @param uid: ID of the user currently logged in
+ @param ids: the ID or list of IDs if we want more than one
+ @param stock_move_obj: the browse object of the stock
+ @param context: A standard dictionary
+ @return:
+ """
+ # Pools
+ stock_move_pool = self.pool.get('stock.move')
+ # Get product account
+ consumed_stock_move_id = stock_move_pool.search(cr, uid, [('move_dest_id', '=', stock_move_obj.id)])[0]
+ consumed_stock_move = stock_move_pool.browse(cr, uid, consumed_stock_move_id, context=context)
+ product_account = consumed_stock_move.prodlot_id.account_analytic_id
+ # Generate next Lot name
+ new_lot_name = self.pool.get('ir.sequence').next_by_code(cr, uid, 'ls.lot', context=context)
+ # Create new analytic account
+ vals = {
+ 'name': new_lot_name,
+ 'code': new_lot_name,
+ 'parent_id': stock_move_obj.product_id.account_id.id,
+ 'state': product_account.state,
+ 'type': product_account.type,
+ 'company_id': product_account.company_id and product_account.company_id.id,
+ 'manager_id': product_account.manager_id and product_account.manager_id.id,
+ 'template_id': product_account.template_id and product_account.template_id.id,
+ 'purchase_order': product_account.purchase_order and product_account.purchase_order.id,
+ }
+ new_analytic_account_id = self.pool.get('account.analytic.account').create(cr, uid, vals)
+ # Create new lot id
+ vals = {
+ 'name': new_lot_name,
+ 'account_analytic_id': new_analytic_account_id,
+ 'product_id': stock_move_obj.product_id and stock_move_obj.product_id.id,
+ }
+ new_lot_id = self.pool.get('stock.production.lot').create(cr, uid, vals, context=context)
+ # Assign new lot number
+ self.write(cr, uid, stock_move_obj.id, {'prodlot_id': new_lot_id})
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added directory 'stock_picking_create_lot_button'
=== added file 'stock_picking_create_lot_button/__init__.py'
--- stock_picking_create_lot_button/__init__.py 1970-01-01 00:00:00 +0000
+++ stock_picking_create_lot_button/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from . import stock
=== added file 'stock_picking_create_lot_button/__openerp__.py'
--- stock_picking_create_lot_button/__openerp__.py 1970-01-01 00:00:00 +0000
+++ stock_picking_create_lot_button/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+# #############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+# NOTE: The name of the supplied field was initially "display_name", but it seems that OpenERP,
+# whenever it seems "name" in the field, returns the value for "name". Well...
+
+{
+ 'name': 'Stock Picking Create "Lot Button"',
+ 'version': '1.0',
+ 'author': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'Generic Modules/Purchases',
+ 'description': """
+Lets you track expenses using product's lots numbers
+====================================================
+
+This module lets you track expenses using a product's lot
+number.
+
+If you create an analytic account for a product
+
+
+""",
+ 'depends': [
+ 'purchase_lot_tracking',
+ 'stock',
+ ],
+ 'data': [
+ 'stock_view.xml'
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added directory 'stock_picking_create_lot_button/static'
=== added directory 'stock_picking_create_lot_button/static/src'
=== added directory 'stock_picking_create_lot_button/static/src/img'
=== added file 'stock_picking_create_lot_button/static/src/img/icon.png'
Binary files stock_picking_create_lot_button/static/src/img/icon.png 1970-01-01 00:00:00 +0000 and stock_picking_create_lot_button/static/src/img/icon.png 2014-11-23 23:06:46 +0000 differ
=== added file 'stock_picking_create_lot_button/stock.py'
--- stock_picking_create_lot_button/stock.py 1970-01-01 00:00:00 +0000
+++ stock_picking_create_lot_button/stock.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,70 @@
+# -*- coding: utf-8 -*-
+# #############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm
+from openerp.tools.translate import _
+from purchase_lot_tracking import purchase
+
+
+class stock_move_create_lot_button(orm.Model):
+ _inherit = "stock.move"
+
+ def btn_new_lot(self, cr, uid, ids, context=None):
+ # suppose the button is call for only one id
+ if not ids:
+ return
+ i_id = ids[0]
+ actual_move = self.browse(cr, uid, i_id, context=context)
+ # only generate for stock move in
+ if actual_move.type != u'in':
+ raise orm.except_orm('Error', 'Cannot create a lot in other situation of stock.move.in')
+ if actual_move.prodlot_id:
+ name = actual_move.prodlot_id.name
+ msg = _("This move line has already an prodlot_id, ") + name
+ raise orm.except_orm(_('Error'), msg)
+
+ picking_id = actual_move.picking_id
+
+ dct_po_line = {
+ "order_id": picking_id.purchase_id,
+ "product_id": actual_move.product_id,
+ }
+
+ po_line = self.Struct(**dct_po_line)
+ lot_number, account_id = purchase.assign_lot_number(self.pool, cr, uid,
+ [po_line],
+ context=context)
+ move_value = {
+ 'prodlot_id': lot_number,
+ 'partner_id': picking_id.partner_id.id,
+ 'price_unit': 0.0,
+ 'product_uos': 1,
+ 'state': 'assigned',
+ }
+ actual_move.write(move_value)
+ # did we need to create a po line? No
+ # po_line.write({'account_analytic_id': account_id})
+ return True
+
+ # transform dict to object
+ class Struct:
+ def __init__(self, **entries):
+ self.__dict__.update(entries)
=== added file 'stock_picking_create_lot_button/stock_view.xml'
--- stock_picking_create_lot_button/stock_view.xml 1970-01-01 00:00:00 +0000
+++ stock_picking_create_lot_button/stock_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<openerp>
+ <data>
+
+ <record model="ir.ui.view" id="view_move_picking_btn_new_lot_tree">
+ <field name="name">view_move_picking_btn_new_lot_tree</field>
+ <field name="model">stock.move</field>
+ <field name="inherit_id" ref="stock.view_move_picking_tree"/>
+ <field name="arch" type="xml">
+ <field name="prodlot_id" position="after">
+ <button name="btn_new_lot" string="Create new lot"
+ groups="stock.group_production_lot" type="object"
+ icon="gtk-new"
+ states="draft,waiting,confirmed,assigned"
+ attrs="{'invisible': [('prodlot_id', '<>', False)]}"
+ />
+ </field>
+ </field>
+ </record>
+
+ </data>
+</openerp>
=== added directory 'supplier_register_identification_number'
=== added file 'supplier_register_identification_number/__init__.py'
--- supplier_register_identification_number/__init__.py 1970-01-01 00:00:00 +0000
+++ supplier_register_identification_number/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+import res_partner
=== added file 'supplier_register_identification_number/__openerp__.py'
--- supplier_register_identification_number/__openerp__.py 1970-01-01 00:00:00 +0000
+++ supplier_register_identification_number/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+{
+ 'name': 'Supplier Register Identification Number',
+ 'version': '0.1',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'crm',
+ 'description': """
+Add a Register Identification Number field to your suppliers
+============================================================
+
+The RIN (French: Numéro d'Identification au Registre, NIR) is a number provided
+by the Québec Government to [owners and operators of heavy
+vehicles](http://www.ctq.gouv.qc.ca/en/owners_and_operators_of_heavy_vehicles.html)
+([French
+ version](http://www.ctq.gouv.qc.ca/proprietaires_et_exploitants_de_vehicules_lourds.html)).
+This module adds such a field to suppliers marked as companies.
+""",
+ 'depends': ['base', 'crm'],
+ 'data': [
+ 'supplier_register_identification_number_view.xml',
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added directory 'supplier_register_identification_number/i18n'
=== added file 'supplier_register_identification_number/i18n/fr.po'
--- supplier_register_identification_number/i18n/fr.po 1970-01-01 00:00:00 +0000
+++ supplier_register_identification_number/i18n/fr.po 2014-11-23 23:06:46 +0000
@@ -0,0 +1,36 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * supplier_register_identification_number
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:25+0000\n"
+"PO-Revision-Date: 2013-09-18 14:25+0000\n"
+"Last-Translator: Alexandre Boily <alexandre.boily@xxxxxxxxxxxxxxxxxxxx>\n"
+"Language-Team: Savoir-faire Linux\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: supplier_register_identification_number
+#: help:res.partner,rin:0
+msgid "A Registry Identification Number, such as 'R-123456-7'"
+msgstr "Un Numéro d'Identification au Registre, tel que 'R-123456-7'"
+
+#. module: supplier_register_identification_number
+#: model:ir.model,name:supplier_register_identification_number.model_res_partner
+msgid "Partner"
+msgstr "Partenaire"
+
+#. module: supplier_register_identification_number
+#: field:res.partner,rin:0
+msgid "Registry Identification Number"
+msgstr "Numéro d'Identification au Registre"
+
+#. module: supplier_register_identification_number
+#: view:res.partner:0
+msgid "e.g. R-123456-7"
+msgstr "e.g. R-123456-7"
=== added file 'supplier_register_identification_number/i18n/supplier_register_identification_number.pot'
--- supplier_register_identification_number/i18n/supplier_register_identification_number.pot 1970-01-01 00:00:00 +0000
+++ supplier_register_identification_number/i18n/supplier_register_identification_number.pot 2014-11-23 23:06:46 +0000
@@ -0,0 +1,37 @@
+# Translation of OpenERP Server.
+# This file contains the translation of the following modules:
+# * supplier_register_identification_number
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: OpenERP Server 7.0-20130811-231021\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-09-18 14:25+0000\n"
+"PO-Revision-Date: 2013-09-18 14:25+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: supplier_register_identification_number
+#: help:res.partner,rin:0
+msgid "A Registry Identification Number, such as 'R-123456-7'"
+msgstr ""
+
+#. module: supplier_register_identification_number
+#: model:ir.model,name:supplier_register_identification_number.model_res_partner
+msgid "Partner"
+msgstr ""
+
+#. module: supplier_register_identification_number
+#: field:res.partner,rin:0
+msgid "Registry Identification Number"
+msgstr ""
+
+#. module: supplier_register_identification_number
+#: view:res.partner:0
+msgid "e.g. R-123456-7"
+msgstr ""
+
=== added file 'supplier_register_identification_number/res_partner.py'
--- supplier_register_identification_number/res_partner.py 1970-01-01 00:00:00 +0000
+++ supplier_register_identification_number/res_partner.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import fields, orm
+
+class res_partner(orm.Model):
+
+ _inherit = 'res.partner'
+
+ _columns = {
+ 'rin':
+ fields.char(
+ 'Registry Identification Number', size=32,
+ help='''A Registry Identification Number, such as 'R-123456-7\''''),
+ }
=== added file 'supplier_register_identification_number/supplier_register_identification_number_view.xml'
--- supplier_register_identification_number/supplier_register_identification_number_view.xml 1970-01-01 00:00:00 +0000
+++ supplier_register_identification_number/supplier_register_identification_number_view.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<openerp>
+ <data>
+ <record id="rin_form" model="ir.ui.view">
+ <field name="name">res.partner.rin.form</field>
+ <field name="model">res.partner</field>
+ <field name="inherit_id" ref="base.view_partner_form" />
+ <field name="arch" type="xml">
+ <field name="website" position="before">
+ <field name="rin" attrs="{'invisible':['|',('is_company','=',False),('supplier','=',False)]}" placeholder="e.g. R-123456-7" />
+ </field>
+ </field>
+ </record>
+ </data>
+</openerp>
=== added directory 'whole_quantity'
=== added file 'whole_quantity/__init__.py'
--- whole_quantity/__init__.py 1970-01-01 00:00:00 +0000
+++ whole_quantity/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,22 @@
+# -*- encoding: utf-8 -*-
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'whole_quantity/__openerp__.py'
--- whole_quantity/__openerp__.py 1970-01-01 00:00:00 +0000
+++ whole_quantity/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,40 @@
+# -*- encoding: utf-8 -*-
+#
+# OpenERP, Open Source Management Solution
+# This module copyright (C) 2013 Savoir-faire Linux
+# (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+{
+ 'name': 'Whole Quantity Display',
+ 'version': '1.0',
+ 'author': 'Savoir-faire Linux',
+ 'maintainer': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'sale',
+ 'description': """\
+Sets decimal places of Product Unit of Measure to zero
+""",
+ 'depends': ['product'],
+ 'external_dependencies': {},
+ 'data': ['whole_quantity_data.xml'],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
+
+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
=== added file 'whole_quantity/whole_quantity_data.xml'
--- whole_quantity/whole_quantity_data.xml 1970-01-01 00:00:00 +0000
+++ whole_quantity/whole_quantity_data.xml 2014-11-23 23:06:46 +0000
@@ -0,0 +1,8 @@
+<?xml version = "1.0" encoding="utf-8"?>
+<openerp>
+ <data noupdate="1">
+ <record id="product.decimal_product_uom" model="decimal.precision">
+ <field name="digits" eval="0"/>
+ </record>
+ </data>
+</openerp>
=== added directory 'writeoff_lot_tracking'
=== added file 'writeoff_lot_tracking/__init__.py'
--- writeoff_lot_tracking/__init__.py 1970-01-01 00:00:00 +0000
+++ writeoff_lot_tracking/__init__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,1 @@
+import account
=== added file 'writeoff_lot_tracking/__openerp__.py'
--- writeoff_lot_tracking/__openerp__.py 1970-01-01 00:00:00 +0000
+++ writeoff_lot_tracking/__openerp__.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+# NOTE: The name of the supplied field was initially "display_name", but it seems that OpenERP,
+# whenever it seems "name" in the field, returns the value for "name". Well...
+
+{
+ 'name': 'writeoff_lot_tracking',
+ 'version': '1.0',
+ 'author': 'Savoir-faire Linux',
+ 'website': 'http://www.savoirfairelinux.com',
+ 'category': 'Generic Modules/Purchases',
+ 'description': """
+Lets you track expenses using product's lots numbers
+====================================================
+
+This module lets you track writeoffs using a product's lot
+number.
+
+""",
+ 'depends': ['purchase_lot_tracking'],
+ 'data': [
+
+ ],
+ 'demo': [],
+ 'test': [],
+ 'installable': True,
+ 'active': False,
+}
=== added file 'writeoff_lot_tracking/account.py'
--- writeoff_lot_tracking/account.py 1970-01-01 00:00:00 +0000
+++ writeoff_lot_tracking/account.py 2014-11-23 23:06:46 +0000
@@ -0,0 +1,177 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# OpenERP, Open Source Management Solution
+# Copyright (C) 2013 Savoir-faire Linux (<http://www.savoirfairelinux.com>).
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+##############################################################################
+
+from openerp.osv import orm, fields
+import openerp.addons.decimal_precision as dp
+
+class account_voucher(orm.Model):
+
+ _inherit = "account.voucher"
+
+ def writeoff_move_line_get(self, cr, uid, voucher_id, line_total, move_id, name, company_currency, current_currency, context=None):
+ '''
+ Set a dict to be use to create the writeoff move line.
+
+ :param voucher_id: Id of voucher what we are creating account_move.
+ :param line_total: Amount remaining to be allocated on lines.
+ :param move_id: Id of account move where this line will be added.
+ :param name: Description of account move line.
+ :param company_currency: id of currency of the company to which the voucher belong
+ :param current_currency: id of currency of the voucher
+ :return: mapping between fieldname and value of account move line to create
+ :rtype: dict
+ '''
+
+ currency_obj = self.pool.get('res.currency')
+ move_lines = []
+
+ voucher = self.pool.get('account.voucher').browse(cr,uid,voucher_id,context)
+ if voucher.type == u'payment':
+ return super(account_voucher, self).writeoff_move_line_get(cr, uid, voucher_id, line_total, move_id, name, company_currency, current_currency, context=context)
+ current_currency_obj = voucher.currency_id or voucher.journal_id.company_id.currency_id
+
+ if not currency_obj.is_zero(cr, uid, current_currency_obj, line_total):
+ diff = line_total
+ account_id = False
+ write_off_name = ''
+ if voucher.payment_option == 'with_writeoff':
+ account_id = voucher.writeoff_acc_id.id
+ write_off_name = voucher.comment
+ elif voucher.type in ('sale', 'receipt'):
+ account_id = voucher.partner_id.property_account_receivable.id
+ else:
+ account_id = voucher.partner_id.property_account_payable.id
+ sign = voucher.type == 'payment' and -1 or 1
+
+ # Create multiple move lines, one for each analytic account
+
+ voucher_total = sum([l.amount for l in voucher.line_ids
+ if l.reconcile])
+
+ invoice_obj = self.pool.get('account.invoice')
+
+ for voucher_line in voucher.line_ids:
+
+ if voucher_line.reconcile:
+
+ invoice_ids = invoice_obj.search(cr, uid, [('number', '=', voucher_line.name)])
+ invoices = invoice_obj.browse(cr, uid, invoice_ids)
+
+ invoice_ratio = voucher_line.amount / voucher_total
+ invoice_writeoff = diff * invoice_ratio
+
+ for invoice in invoices:
+ for invoice_line in invoice.invoice_line:
+ invoice_line_ratio = invoice_line.price_subtotal / invoice.amount_untaxed
+ invoice_line_writeoff = round(invoice_writeoff * invoice_line_ratio, 2)
+
+ move_line = {
+ 'name': write_off_name or name,
+ 'account_id': account_id,
+ 'move_id': move_id,
+ 'partner_id': voucher.partner_id.id,
+ 'date': voucher.date,
+ 'credit': invoice_line_writeoff > 0 and invoice_line_writeoff or 0.0,
+ 'debit': invoice_line_writeoff < 0 and -invoice_line_writeoff or 0.0,
+ 'amount_currency': company_currency <> current_currency and (sign * -1 * voucher.writeoff_amount) or 0.0,
+ 'currency_id': company_currency <> current_currency and current_currency or False,
+ 'analytic_account_id': invoice_line.account_analytic_id.id or False,
+ }
+
+ move_lines.append(move_line)
+
+
+ writeoff_debit = sum([l['debit'] for l in move_lines])
+ writeoff_credit = sum([l['credit'] for l in move_lines])
+
+ if writeoff_debit > 0 and writeoff_debit != -diff:
+ diff_writeoff = round(-diff - writeoff_debit, 2)
+ move_lines[0]['debit'] = move_lines[0]['debit'] + diff_writeoff
+
+ if writeoff_credit > 0 and writeoff_credit != diff:
+ pass
+
+
+
+
+
+ return move_lines
+
+
+
+ def action_move_line_create(self, cr, uid, ids, context=None):
+ '''
+ Confirm the vouchers given in ids and create the journal entries for each of them
+ '''
+
+ if context is None:
+ context = {}
+ move_pool = self.pool.get('account.move')
+ move_line_pool = self.pool.get('account.move.line')
+ for voucher in self.browse(cr, uid, ids, context=context):
+ if voucher.move_id:
+ continue
+ if voucher.type == u'payment':
+ super(account_voucher, self).action_move_line_create(cr, uid, ids, context=context)
+ continue
+ company_currency = self._get_company_currency(cr, uid, voucher.id, context)
+ current_currency = self._get_current_currency(cr, uid, voucher.id, context)
+ # we select the context to use accordingly if it's a multicurrency case or not
+ context = self._sel_context(cr, uid, voucher.id, context)
+ # But for the operations made by _convert_amount, we always need to give the date in the context
+ ctx = context.copy()
+ ctx.update({'date': voucher.date})
+ # Create the account move record.
+ move_id = move_pool.create(cr, uid, self.account_move_get(cr, uid, voucher.id, context=context), context=context)
+ # Get the name of the account_move just created
+ name = move_pool.browse(cr, uid, move_id, context=context).name
+ # Create the first line of the voucher
+ move_line_id = move_line_pool.create(cr, uid, self.first_move_line_get(cr,uid,voucher.id, move_id, company_currency, current_currency, context), context)
+ move_line_brw = move_line_pool.browse(cr, uid, move_line_id, context=context)
+ line_total = move_line_brw.debit - move_line_brw.credit
+ rec_list_ids = []
+ if voucher.type == 'sale':
+ line_total = line_total - self._convert_amount(cr, uid, voucher.tax_amount, voucher.id, context=ctx)
+ elif voucher.type == 'purchase':
+ line_total = line_total + self._convert_amount(cr, uid, voucher.tax_amount, voucher.id, context=ctx)
+ # Create one move line per voucher line where amount is not 0.0
+ line_total, rec_list_ids = self.voucher_move_line_create(cr, uid, voucher.id, line_total, move_id, company_currency, current_currency, context)
+
+ # Create the writeoff line if needed
+ ml_writeoff = self.writeoff_move_line_get(cr, uid, voucher.id, line_total, move_id, name, company_currency, current_currency, context)
+
+ if ml_writeoff:
+ for move_line in ml_writeoff:
+ move_line_pool.create(cr, uid, move_line, context)
+ # We post the voucher.
+ self.write(cr, uid, [voucher.id], {
+ 'move_id': move_id,
+ 'state': 'posted',
+ 'number': name,
+ })
+ if voucher.journal_id.entry_posted:
+ move_pool.post(cr, uid, [move_id], context={})
+ # We automatically reconcile the account move lines.
+ reconcile = False
+ for rec_ids in rec_list_ids:
+ if len(rec_ids) >= 2:
+ reconcile = move_line_pool.reconcile_partial(cr, uid, rec_ids, writeoff_acc_id=voucher.writeoff_acc_id.id, writeoff_period_id=voucher.period_id.id, writeoff_journal_id=voucher.journal_id.id)
+ return True