openerp-community-reviewer team mailing list archive
-
openerp-community-reviewer team
-
Mailing list archive
-
Message #06576
[Merge] lp:~savoirfairelinux-openerp/purchase-wkfl/pallet-delivery-missing-security-access into lp:purchase-wkfl
Mathieu Benoit has proposed merging lp:~savoirfairelinux-openerp/purchase-wkfl/pallet-delivery-missing-security-access into lp:purchase-wkfl.
Requested reviews:
Maxime Chambreuil (http://www.savoirfairelinux.com) (max3903)
Joao Alfredo Gama Batista (joao-gama)
For more details, see:
https://code.launchpad.net/~savoirfairelinux-openerp/purchase-wkfl/pallet-delivery-missing-security-access/+merge/218508
The module stock_forecast missing security access. The other module is ok.
--
https://code.launchpad.net/~savoirfairelinux-openerp/purchase-wkfl/pallet-delivery-missing-security-access/+merge/218508
Your team Purchase Core Editors is subscribed to branch 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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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.integer('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 '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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +0000
@@ -0,0 +1,178 @@
+# 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 ""
+
+#. module: pallet_delivery
+#: model:ir.model,name:pallet_delivery.model_purchase_order_line
+msgid "Purchase Order Line"
+msgstr ""
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Confirm"
+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
+#: view:stock.truck:0
+msgid "Truck Composition"
+msgstr ""
+
+#. module: pallet_delivery
+#: field:stock.truck,back_temperature:0
+msgid "Back Temperature"
+msgstr ""
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Serial Number"
+msgstr ""
+
+#. module: pallet_delivery
+#: view:stock.truck:0
+msgid "Left 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
+#: 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 "Right Pallets"
+msgstr ""
+
+#. module: pallet_delivery
+#: model:ir.actions.act_window,name:pallet_delivery.action_truck_pending
+msgid "On Draft Truck"
+msgstr ""
+
+#. module: pallet_delivery
+#: model:ir.ui.menu,name:pallet_delivery.menu_truck
+msgid "Incoming Truck"
+msgstr ""
+
+#. module: pallet_delivery
+#: selection:stock.truck,state:0
+msgid "Done"
+msgstr ""
+
+#. module: pallet_delivery
+#: 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-05-06 20:52:40 +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">2</field>
+ <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-05-06 20:52:40 +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" />
+ <field name="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-05-06 20:52:40 +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-05-06 20:52:40 +0000
@@ -0,0 +1,288 @@
+# -*- 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 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 purchase_order_line(orm.Model):
+
+ _inherit = 'purchase.order.line'
+
+ def _find_hidden(self, cr, uid, ids, context=None):
+ hidden_id = self.search(cr, uid, [('order_id.hidden', '=', True)], context=context)[0]
+ return self.browse(cr, uid, hidden_id, context)
+
+ def name_get(self, cr, uid, ids, context=None):
+ if context is None:
+ context = {}
+
+ if isinstance(ids, (int, long)):
+ ids = [ids]
+
+ # Out from selection; display name
+
+ if not context.has_key('nice'):
+ res = []
+
+ for line in self.browse(cr, uid, ids, context=context):
+ nice = '%s / %s' % (line.name, line.account_analytic_id.code)
+ res.append((line.id, nice))
+
+ hidden = self._find_hidden(cr, uid, ids, context=context)
+ res.append((hidden.id, hidden.name))
+
+ return res
+
+ # Doing a selection
+
+ res = []
+
+ # Add special 'not ours' line
+ hidden = self._find_hidden(cr, uid, ids, context=context)
+ 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]
+
+ stl_pool = self.pool.get('stock.truck.line')
+ pallet_ids = []
+
+ # 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]
+ crates[fields['pallet']] += fields['crates']
+
+ move_pool = self.pool.get('stock.move')
+ po_line_ids = self.search(cr, uid, [('order_id', 'in', po_ids)], context=context)
+ po_lines = self.browse(cr, uid, po_line_ids, context=context)
+
+ # Prettify data to be displayed
+ for line in po_lines:
+ nice = ''
+
+ if line.order_id.hidden:
+ nice = line.name + ' / None'
+ else:
+ # Incoming crates
+ move_ids = [move.id for move in line.move_ids]
+ incoming_id = move_pool.search(
+ cr, uid,
+ ['&', ('state', '=', 'assigned'), ('id', 'in', move_ids)],
+ context=context)[0]
+ incoming = move_pool.browse(cr, uid, incoming_id, context=context)
+ incoming_crates = incoming.product_qty
+
+ available = max(0, incoming_crates - crates[line.id])
+ nice = '%s / %s (%d)' % (line.name, line.account_analytic_id.code, available)
+
+ res.append((line.id, nice))
+
+ 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('purchase.order.line', '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 = {}
+
+ def _process_pallets(column):
+ for line in column:
+ # Skip over fake 'not ours' line
+ if line.pallet.order_id.hidden:
+ continue
+
+ po = line.pallet.order_id
+ lot = line.pallet.account_analytic_id.code
+
+ if not products.has_key(po.id):
+ products[po.id] = {}
+
+ if not products[po.id].has_key(lot):
+ products[po.id][lot] = (line.pallet, 0)
+
+ count = products[po.id][lot][1]
+ products[po.id][lot] = (products[po.id][lot][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')
+ move_pool = self.pool.get('stock.move')
+
+ for po in truck.purchase_order_ids:
+ if not products.has_key(po.id):
+ # Purchase Order was added to the list, but there are not
+ # pallets pertaining to that PO.
+ continue
+
+ partial_data = {'delivery_date': truck.arrival}
+
+ picking_id = picking_pool.search(
+ cr, uid,
+ ['&', ('purchase_id', '=', po.id), ('state', '=', 'assigned')],
+ context=context)[0]
+
+ for po_line, count in products[po.id].itervalues():
+ # Skip over the fake 'not ours' line
+ if po_line.order_id.hidden:
+ continue
+
+ move_id = move_pool.search(
+ cr, uid,
+ ['&', ('picking_id', '=', picking_id), ('purchase_line_id', '=', po_line.id)],
+ context=context)[0]
+
+ prodlot_id = move_pool.browse(cr, uid, move_id, context=context).prodlot_id.id
+
+ partial_data['move%s' % (move_id, )] = {
+ 'product_id': po_line.product_id.id,
+ 'product_qty': count,
+ 'product_uom': 1,
+ 'prodlot_id': prodlot_id,
+ }
+
+ picking_pool.do_partial(cr, uid, [picking_id], partial_data, context=context)
+
+ self.write(cr, uid, ids, {'state': 'done'})
+
+ 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.float('Front Temperature', required=True),
+ 'back_temperature': fields.float('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',
+ }
=== 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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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/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-05-06 20:52:40 +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_gains'
=== added file 'purchase_gains/__init__.py'
--- purchase_gains/__init__.py 1970-01-01 00:00:00 +0000
+++ purchase_gains/__init__.py 2014-05-06 20:52:40 +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-05-06 20:52:40 +0000 differ
=== added file 'purchase_gains/__openerp__.py'
--- purchase_gains/__openerp__.py 1970-01-01 00:00:00 +0000
+++ purchase_gains/__openerp__.py 2014-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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_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-05-06 20:52:40 +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-05-06 20:52:40 +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.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': ['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-05-06 20:52:40 +0000
@@ -0,0 +1,88 @@
+# -*- 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(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] = 0.0
+ total_moves = 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 += move.product_qty
+ #else:
+ # total_moves -= move.product_qty
+
+ total_moves = max(total_moves, 0)
+ res[account.id] = total_moves
+
+ return 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'),
+ 'estimated_tcu': fields.function(_estimated_tcu, string='Estimated Total Cost per Unit', type='float'),
+ 'total_in_qty': fields.function(_calculate_total_in, string='Total Received Quantity', 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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +0000
@@ -0,0 +1,244 @@
+# -*- 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
+
+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
+
+ def assign_lot_number(self, cr, uid, ids):
+ """
+ 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.
+ """
+ for line_order in self.browse(cr, uid, ids):
+
+ lot_number = self.pool.get('ir.sequence').get(cr, uid, 'ls.lot')
+ product = line_order.product_id
+
+ # Creates the analytic account
+ account_id = self._analytic_account_from_product(cr,
+ uid,
+ ids,
+ {'product': product,
+ 'lot_number': lot_number })
+
+ # Creates the stock.production.line
+ serial_number_data = {
+ 'name': lot_number,
+ 'product_id': line_order.product_id.id,
+ 'account_analytic_id': account_id,
+ }
+
+ serial_number_id = self.pool.get('stock.production.lot')\
+ .create(cr, uid, serial_number_data)
+
+ return serial_number_id, account_id
+
+
+ def _analytic_account_from_product(self, cr, uid, ids, context):
+ """
+ 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
+ """
+
+ for line_order in self.browse(cr, uid, ids):
+
+ product = context['product']
+ parent_account = product.account_id
+
+ account_values = {
+ 'name': context['lot_number'],
+ 'complete_name': context['lot_number'],
+ 'purchase_order': line_order.order_id.id,
+ 'code': context['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 = self.pool.get('account.analytic.account')\
+ .create(cr, uid, account_values)
+
+ return analytic_account_id
+
+
+ _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 = po_line.assign_lot_number()
+
+ matching_line = [
+ 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
+ ][0]
+
+ matching_line.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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +0000
@@ -0,0 +1,95 @@
+# -*- 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
+
+class sale(orm.Model):
+
+ _inherit = 'sale.order.line'
+ _logger = logging.Logger(__name__)
+
+ def _minimum(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+
+ for order_line in self.browse(cr, uid, ids, context):
+ account = order_line.product_id.account_id
+ minimum = 0.0
+
+ if account:
+ values = [lot.estimated_tcu for lot in account.child_ids
+ if lot.total_in_qty != 0]
+
+ if values:
+ minimum = min(values)
+
+ res[order_line.id] = minimum
+
+ return res
+
+ def _average(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+
+ for order_line in self.browse(cr, uid, ids, context):
+ account = order_line.product_id.account_id
+ average = 0.0
+
+ total_count = 0
+
+ if account:
+ for lot in account.child_ids:
+ quantity = lot.total_in_qty
+ tcu = lot.estimated_tcu
+
+ if quantity != 0:
+ average += quantity * tcu
+ total_count += quantity
+
+ if total_count == 0:
+ res[order_line.id] = 0
+ else:
+ res[order_line.id] = average / total_count
+
+ return res
+
+ def _maximum(self, cr, uid, ids, name, arg, context=None):
+ res = {}
+
+ for order_line in self.browse(cr, uid, ids, context):
+ account = order_line.product_id.account_id
+ maximum = 0.0
+
+ if account:
+ values = [lot.estimated_tcu for lot in account.child_ids
+ if lot.total_in_qty != 0]
+
+ if values:
+ maximum = max(values)
+
+ res[order_line.id] = maximum
+
+ return res
+
+ _columns = {
+ 'minimum': fields.function(_minimum, string='Min.', type='float'),
+ 'average': fields.function(_average, string='Avg.', type='float'),
+ 'maximum': fields.function(_maximum, string='Max.', type='float')
+ }
=== 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-05-06 20:52:40 +0000
@@ -0,0 +1,138 @@
+# -*- 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:
+ 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-05-06 20:52:40 +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-05-06 20:52:40 +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_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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +0000
@@ -0,0 +1,429 @@
+<?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="LINEBEFORE" colorName="black" start="0,0" stop="0,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="black" start="0,0" stop="0,0"/>
+ <lineStyle kind="LINEBELOW" colorName="black" start="0,-1" stop="0,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="black" start="1,0" stop="1,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="black" start="1,0" stop="1,0"/>
+ <lineStyle kind="LINEBELOW" colorName="black" start="1,-1" stop="1,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="black" start="2,0" stop="2,-1"/>
+ <lineStyle kind="LINEABOVE" colorName="black" start="2,0" stop="2,0"/>
+ <lineStyle kind="LINEBELOW" colorName="black" start="2,-1" stop="2,-1"/>
+ <lineStyle kind="LINEBEFORE" colorName="black" start="3,0" stop="3,-1"/>
+ </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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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.integer('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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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 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)
+
+ for line in context['lines']:
+ values = line[2]
+ entered[values['prodlot_id']] += values['quantity']
+
+ res = []
+
+ for lot in self.browse(cr, uid, ids, context=context):
+ net_available = lot.stock_available - entered[lot.id]
+ res.append((lot.id, '%s / %.2f' % (lot.name, net_available)))
+
+ return res
+
+if 0:
+ class stock_move_split_lines(orm.TransientModel):
+
+ _inherit = 'stock.move.split.lines'
+
+ def _prodlot_id(self, cr, uid, ids, name, arg, context=None):
+ import ipdb; ipdb.set_trace()
+ if context is None:
+ context = {}
+
+ res = {}
+
+ for thing in self.browse(cr, uid, ids, context=context):
+ res[thing.id] = 'thing %d' % (thing.id, )
+
+ return res
+
+ def _prodlot_id_inv(self, cr, uid, ids, name, value, arg, context=None):
+ import ipdb; ipdb.set_trace()
+ return True
+
+ def _prodlot_id_search(self, cr, uid, obj, name, arg, context=None):
+ import ipdb; ipdb.set_trace()
+ return [('id', 'in', [1])]
+
+ _columns = {
+ 'prodlot_id': fields.function(
+ _prodlot_id,
+ fnct_inv=_prodlot_id_inv,
+ type='many2one',
+ fnct_search=_prodlot_id_search,
+ method=True,
+ store=True,
+ string='Serial Number'),
+ }
=== 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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +0000
@@ -0,0 +1,619 @@
+#-*- coding: utf-8 -*-
+import pytz
+from datetime import datetime, timedelta
+from dateutil.relativedelta import relativedelta
+from collections import defaultdict
+
+
+from openerp import tools, SUPERUSER_ID
+from openerp.osv import osv, 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;
+ }
+
+ 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'] != 0:
+ ${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'] != 0:
+ ${day[product.id]['incoming']}
+ % 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; ">
+ ${order[product.id]}
+ </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(osv.osv_memory):
+
+ _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(osv.osv):
+
+ _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 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 result
+
+ def get_stock_forecast(self, cr, uid, exp_day, context=None):
+
+ 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)
+
+ 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 - outgoing_total
+
+
+ return on_hand + incoming_total - outgoing_total
+
+ def get_situation(self, day_product):
+ there = day_product['forecasted'] + day_product['incoming']
+
+ 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['situation'] = self.get_situation(day_product)
+
+ if day_product['outgoing'] or day_product['incoming']:
+ 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] = 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
+
+ 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-05-06 20:52:40 +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-05-06 20:52:40 +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_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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +0000
@@ -0,0 +1,67 @@
+# -*- 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_id = stock_move_pool.search(cr, uid, [('prodlot_id.name', '=', line.code)], context=context)[0]
+ stock_move = stock_move_pool.browse(cr, uid, stock_move_id, 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_id = po_line_pool.search(cr, uid, [('account_analytic_id', '=', initial_analytic_id)], context=context)[0]
+ parent_po_line = po_line_pool.browse(cr, uid, parent_po_line_id, 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-05-06 20:52:40 +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 '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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +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-05-06 20:52:40 +0000
@@ -0,0 +1,174 @@
+# -*- 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_line = {}
+
+ voucher = self.pool.get('account.voucher').browse(cr,uid,voucher_id,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')
+
+ move_lines = []
+
+ 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
+ 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