← Back to team overview

openerp-community-reviewer team mailing list archive

[Merge] lp:~camptocamp/stock-logistic-flows/7.0-stock-obsolete-mdh into lp:stock-logistic-flows

 

Matthieu Dietrich @ camptocamp has proposed merging lp:~camptocamp/stock-logistic-flows/7.0-stock-obsolete-mdh into lp:stock-logistic-flows.

Commit message:
[FIX] port of module stock_obsolete for 7.0

Requested reviews:
  Stock and Logistic Core Editors (stock-logistic-core-editors)

For more details, see:
https://code.launchpad.net/~camptocamp/stock-logistic-flows/7.0-stock-obsolete-mdh/+merge/233313

This is a 7.0 port of the module stock_obsolete.
-- 
https://code.launchpad.net/~camptocamp/stock-logistic-flows/7.0-stock-obsolete-mdh/+merge/233313
Your team Stock and Logistic Core Editors is requested to review the proposed merge of lp:~camptocamp/stock-logistic-flows/7.0-stock-obsolete-mdh into lp:stock-logistic-flows.
=== added directory 'stock_obsolete'
=== added file 'stock_obsolete/__init__.py'
--- stock_obsolete/__init__.py	1970-01-01 00:00:00 +0000
+++ stock_obsolete/__init__.py	2014-09-04 08:30:40 +0000
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (c) 2008-2014 Camtocamp SA
+# @author Joël Grand-Guillaume, Matthieu Dietrich
+# $Id: $
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+import wizard
+import stock_obsolete
+import report

=== added file 'stock_obsolete/__openerp__.py'
--- stock_obsolete/__openerp__.py	1970-01-01 00:00:00 +0000
+++ stock_obsolete/__openerp__.py	2014-09-04 08:30:40 +0000
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# @author Grand-Guillaume Joel, Matthieu Dietrich
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+{
+    "name" : "Stock obsolete",
+    "version" : "1.0",
+    "author" : "Camptocamp",
+    "category" : "Generic Modules/Stock",
+    "module":
+"""
+    Add a special view and wizard on product to check the validity of each stock product, with an amount of depreciation. Your finance can now
+    take in charge a factor for each product, based on the depreciation value for each product. You can set the depreciation value
+    based on the out of stock amount for each product for last 12/24 month.
+""",
+    "website": "http://camptocamp.com";,
+    "depends" : ["stock","product"],
+    "init_xml" : [],
+    "demo_xml" : [],
+    "update_xml" : [
+        "stock_obsolete_view.xml",
+        "stock_obsolete_report.xml",
+    ],
+    "active": False,
+    "installable": True
+}

=== added directory 'stock_obsolete/report'
=== added file 'stock_obsolete/report/__init__.py'
--- stock_obsolete/report/__init__.py	1970-01-01 00:00:00 +0000
+++ stock_obsolete/report/__init__.py	2014-09-04 08:30:40 +0000
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (c) 2008 Camtocamp SA
+# @author Joël Grand-Guillaume
+# $Id: $
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+import product_obsolete

=== added file 'stock_obsolete/report/product_obsolete.py'
--- stock_obsolete/report/product_obsolete.py	1970-01-01 00:00:00 +0000
+++ stock_obsolete/report/product_obsolete.py	2014-09-04 08:30:40 +0000
@@ -0,0 +1,76 @@
+#!/usr/bin/env python2.3
+#
+#  print_invoice_list.py
+#  PEG
+#
+#  Created by Nicolas Bessi on 13.10.08.
+#  Copyright (c) 2008 CamptoCamp. All rights reserved.
+#
+
+import time
+from report import report_sxw
+import re
+
+
+class Product_obsolete(report_sxw.rml_parse):
+    def __init__(self, cr, uid, name, context):
+        super(Product_obsolete, self).__init__(cr, uid, name, context)
+        self.localcontext.update({
+            'time': time,
+            # 'lines': self.lines,
+            'comma_me': self.comma_me,
+            'get_name_of': self.get_depreciation_name,
+        })
+        self.context = context
+
+    def comma_me(self, amount):
+        if type(amount) is float:
+            amount = str('%.2f' % amount)
+        else:
+            amount = str(amount)
+        orig = amount
+        new = re.sub("^(-?\d+)(\d{3})", "\g<1>'\g<2>", amount)
+        if orig == new:
+            return new
+        else:
+            return self.comma_me(new)
+
+    def get_depreciation_name(self, value):
+        if value == 'no':
+            return 'No'
+        elif value == 'half':
+            return 'Half'
+        elif value == 'full':
+            return 'Full'
+        else:
+            return False
+
+    def set_context(self, objects, data, ids, report_type=None):
+        prod_obj = self.pool.get('product.product')
+        if data.get('ids', False) and \
+           data.get('model', False) == 'product.product':
+            ids = [data['ids']]
+        else:
+            ids = prod_obj.search(self.cr, self.uid,
+                                  [('type', '=', 'product')],
+                                  limit=4000)
+
+        objects = prod_obj.browse(self.cr, self.uid, ids)
+
+        def o_compare(x, y):
+            if x.outgoing_qty_till_12m < y.outgoing_qty_till_12m:
+                return 1
+            elif x.outgoing_qty_till_12m == y.outgoing_qty_till_12m:
+                return 0
+            else:  # x<y
+                return -1
+
+        # sort object by depreciation 12 month
+        objects.sort(o_compare)
+        self.ids = [o.id for o in objects]
+        self.localcontext['objects'] = objects
+
+report_sxw.report_sxw('report.product.obsolete',
+                      'product.product',
+                      'addons/stock_obsolete/report/product_obsolete.rml',
+                      parser=Product_obsolete, header=False)

=== added file 'stock_obsolete/report/product_obsolete.rml'
--- stock_obsolete/report/product_obsolete.rml	1970-01-01 00:00:00 +0000
+++ stock_obsolete/report/product_obsolete.rml	2014-09-04 08:30:40 +0000
@@ -0,0 +1,209 @@
+<?xml version="1.0"?>
+<document filename="test.pdf">
+    <template pageSize="(1100.0,770.0)" title="Print invoices" author="JGRANDG"
+        allowSplitting="20">
+        <pageTemplate id="first">
+            <frame id="first" x1="15.0" y1="15.0" width="1000" height="675"/>
+            <pageGraphics>
+                <!--logo-->
+                <!--<fill color="darkblue"/>-->
+                <!--<stroke color="darkblue"/>-->
+
+                <!--TITLE COMPANY-->
+                <!-- <drawString x="4.6cm" y="28.7cm">[[ company.partner_id.name ]]</drawString> -->
+
+                <setFont name="Helvetica-Bold" size="9"/>
+
+
+                <!--COL 1-->
+                <drawString x="1.0cm" y="25.50cm">[[ company.name ]]</drawString>
+                <drawString x="32.0cm" y="25.50cm">Product obsolescence listing</drawString>
+
+                <!--COL 2-->
+                <setFont name="Helvetica" size="9"/>
+                <drawString x="1.0cm" y="0.90cm"> [[ time.strftime("%m-%d-%y %H:%M",time.localtime()) ]]</drawString>
+                <drawString x="35.50cm" y="0.90cm">Page <pageNumber/></drawString>
+
+                <!--<drawRightString x="19.8cm" y="28cm">[[ company.rml_header1 ]]</drawRightString>-->
+
+
+                <lineMode width="0.7"/>
+                <lines>1cm 24.9cm 38cm 24.9cm</lines>
+                <setFont name="Helvetica" size="8"/>
+            </pageGraphics>
+
+        </pageTemplate>
+    </template>
+    <stylesheet>
+        <blockTableStyle id="Standard_Outline">
+            <blockAlignment value="LEFT"/>
+            <blockValign value="TOP"/>
+        </blockTableStyle>
+        <blockTableStyle id="Table1">
+            <blockAlignment value="LEFT"/>
+            <blockValign value="TOP"/>
+            <blockBackground colorName="#e6e6e6" start="0,0" stop="0,0"/>
+            <blockBackground colorName="#e6e6e6" start="1,0" stop="1,0"/>
+            <blockBackground colorName="#e6e6e6" start="2,0" stop="2,0"/>
+            <blockBackground colorName="#e6e6e6" start="0,1" stop="0,1"/>
+            <blockBackground colorName="#e6e6e6" start="1,1" stop="1,1"/>
+            <blockBackground colorName="#e6e6e6" start="2,1" stop="2,1"/>
+        </blockTableStyle>
+        <blockTableStyle id="Table2">
+            <lineStyle kind="LINEBELOW" colorName="#000000" start="0,0" stop="-1,0"/>
+            <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,1" stop="-1,-1"/>
+
+            <blockValign value="TOP"/>
+            <blockAlignment value="RIGHT" start="2,1" stop="-1,-1"/>
+        </blockTableStyle>
+        <blockTableStyle id="Tableau3">
+            <blockAlignment value="LEFT"/>
+            <blockValign value="TOP"/>
+            <lineStyle kind="LINEBELOW" colorName="#e6e6e6"/>
+            <lineStyle kind="OUTLINE" colorName="#e6e6e6"/>
+
+
+            <blockBackground colorName="white" start="0,0" stop="-1,0"/>
+        </blockTableStyle>
+        <blockTableStyle id="Table5">
+            <blockAlignment value="LEFT"/>
+            <blockValign value="TOP"/>
+        </blockTableStyle>
+        <blockTableStyle id="Table4">
+            <blockAlignment value="LEFT"/>
+            <blockValign value="TOP"/>
+            <lineStyle kind="GRID" colorName="black"/>
+        </blockTableStyle>
+        <blockTableStyle id="Theader">
+            <blockAlignment value="LEFT"/>
+            <blockValign value="TOP"/>
+            <lineStyle kind="OUTLINE" colorName="#e6e6e6"/>
+            <blockBackground colorName="white" start="0,0" stop="-1,0"/>
+        </blockTableStyle>
+
+
+        <initialize>
+            <paraStyle name="all" alignment="justify"/>
+        </initialize>
+        <paraStyle name="P1" fontName="Helvetica" fontSize="20.0" leading="25" alignment="CENTER"
+            spaceBefore="0.0" spaceAfter="6.0"/>
+        <paraStyle name="P2" fontName="Helvetica" fontSize="8.0" leading="10" spaceBefore="0.0"
+            spaceAfter="6.0"/>
+        <paraStyle name="P3" fontName="Helvetica" fontSize="8.0" leading="10" alignment="LEFT"
+            spaceBefore="0.0" spaceAfter="6.0"/>
+        <paraStyle name="P4" fontName="Helvetica" fontSize="8.0" leading="10" alignment="RIGHT"
+            spaceBefore="0.0" spaceAfter="6.0"/>
+        <paraStyle name="P5" fontName="Helvetica" fontSize="10.0" leading="13" alignment="RIGHT"
+            spaceBefore="0.0" spaceAfter="6.0"/>
+        <paraStyle name="P6" fontName="Helvetica" alignment="CENTER" spaceBefore="0.0"
+            spaceAfter="6.0"/>
+        <paraStyle name="P7" fontName="Helvetica" fontSize="11.0" leading="14" alignment="RIGHT"
+            spaceBefore="0.0" spaceAfter="6.0"/>
+        <paraStyle name="P8" fontName="Helvetica" fontSize="11.0" leading="14" alignment="RIGHT"
+            spaceBefore="0.0" spaceAfter="6.0"/>
+        <paraStyle name="P9" fontName="Helvetica" fontSize="8.0" leading="10" alignment="RIGHT"
+            spaceBefore="0.0" spaceAfter="6.0"/>
+        <paraStyle name="P9b" fontName="Helvetica-Bold" fontSize="8.0" leading="10"
+            alignment="RIGHT" spaceBefore="0.0" spaceAfter="6.0"/>
+        <paraStyle name="P10" fontName="Helvetica" alignment="CENTER"/>
+        <paraStyle name="P11" fontName="Helvetica" fontSize="11.0" leading="14"/>
+        <paraStyle name="P12" fontName="Helvetica" fontSize="14.0" leading="17"/>
+        <paraStyle name="P13" fontName="Helvetica-Bold" fontSize="10.0" leading="8"
+            alignment="CENTER" spaceBefore="0.0" spaceAfter="6.0"/>
+        <paraStyle name="P14" fontName="Helvetica" fontSize="8.0" leading="10" spaceBefore="0.0"
+            spaceAfter="6.0"/>
+        <paraStyle name="P15" fontName="Helvetica-Bold" spaceBefore="0.0" spaceAfter="6.0"/>
+        <paraStyle name="P16" rightIndent="17.0" leftIndent="-0.0" fontName="Times-Roman"
+            fontSize="8.0" leading="10" spaceBefore="0.0" spaceAfter="6.0"/>
+        <paraStyle name="P17" fontName="Helvetica" alignment="LEFT" fontSize="12.0" spaceAfter="0.0"/>
+        <paraStyle name="Standard" fontName="Helvetica-Bold" size="9"/>
+        <paraStyle name="Account" fontName="Helvetica"/>
+        <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="Table Contents" fontName="Helvetica" spaceBefore="0.0" spaceAfter="6.0"/>
+        <paraStyle name="Table Heading" fontName="Helvetica" alignment="CENTER" spaceBefore="0.0"
+            spaceAfter="6.0"/>
+        <paraStyle name="Caption" fontName="Helvetica" fontSize="10.0" leading="13"
+            spaceBefore="6.0" spaceAfter="6.0"/>
+        <paraStyle name="Index" fontName="Helvetica"/>
+    </stylesheet>
+    <story>
+        <setFont name="Helvetica" size="9"/>
+        <para style="Standard">
+            <font color="white"> </font>
+        </para>
+        <para style="Standard">
+            <font color="white"> </font>
+        </para>
+        <para style="Standard">
+            <font color="white"> </font>
+        </para>
+        <section>
+            <section>
+                <para style="Standard">
+                    <font color="white"> </font>
+                </para>
+                <blockTable colWidths="100,250,80,80,80,80,80,80" repeatRows="1" style="Tableau3">
+                <!-- <blockTable colWidths="50,80,80,250,250,60,130,130" repeatRows="1" style="Tableau3"> -->
+                    <tr>
+                        <td>
+                            <para style="Standard" size="5">Code</para>
+                        </td>
+                        <td>
+                            <para style="Standard" size="5">Name</para>
+                        </td>
+                        <td>
+                            <para style="Standard" alignment="RIGHT" size="5">Real stock</para>
+                        </td>
+
+                        <td>
+                            <para style="Standard" alignment="RIGHT" size="5">Virtual stock</para>
+                        </td>
+                        <td>
+                            <para style="Standard" alignment="RIGHT" size="5">Cost price</para>
+                        </td>
+                        <td>
+                            <para style="Standard" alignment="CENTER" size="5">Depreciation</para>
+                        </td>
+                        <td>
+                            <para alignment="RIGHT" style="Standard" size="5">Out /12 month</para>
+                        </td>
+                         <td>
+                                <para alignment="RIGHT" style="Standard" size="5">Out /24 month</para>
+                        </td>
+
+                    </tr>
+                    <tr>[[ repeatIn(objects,'o') ]] <td>
+                            <para>[[o.code]]</para>
+                        </td>
+                        <td>
+                            <para>[[o.name]]</para>
+                        </td>
+                        <td>
+                            <para alignment="RIGHT">[[o.qty_available or '0.0']]</para>
+                        </td>
+                        <td>
+                            <para alignment="RIGHT">[[o.virtual_available or '0.0']]</para>
+                        </td>
+                        <td>
+                            <para alignment="RIGHT">[[comma_me(o.standard_price)]]</para>
+                        </td>
+                        <td>
+                            <para alignment="CENTER">[[get_name_of(o.depreciation)]]</para>
+                        </td>
+                        <td>
+                            <para alignment="RIGHT">[[o.outgoing_qty_till_12m or '0.0']]</para>
+                        </td>
+                        <td>
+                            <para alignment="RIGHT">[[o.outgoing_qty_till_24m or '0.0']]</para>
+                        </td>
+                    </tr>
+                </blockTable>
+                <para style="Standard">
+                    <font color="white"> </font>
+                </para>
+            </section>
+        </section>
+
+    </story>
+</document>

=== added file 'stock_obsolete/stock_obsolete.py'
--- stock_obsolete/stock_obsolete.py	1970-01-01 00:00:00 +0000
+++ stock_obsolete/stock_obsolete.py	2014-09-04 08:30:40 +0000
@@ -0,0 +1,202 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (c) Camptocamp SA - Joel Grand-Guillaume
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+from datetime import datetime
+from dateutil.relativedelta import relativedelta
+from osv import fields, orm
+
+
+#----------------------------------------------------------
+# Stock Location
+#----------------------------------------------------------
+class StockLocation(orm.Model):
+    _inherit = "stock.location"
+
+    def _product_get_multi_location_for_period(self, cr, uid, ids, period,
+                                               product_ids=False, context={},
+                                               states=['done'],
+                                               what=('in', 'out')):
+        # Compute date from context and period
+        # wich determine reference date for out stock computing
+        if context.get('ref_date', False):
+            date_ref = context['ref_date']
+            past_date_ref = (datetime.strptime(context['ref_date'], '%Y-%m-%d')
+                           + relativedelta(months=-int(period),
+                                       day=1,
+                                       days=-1)).strftime('%Y-%m-%d')
+        # if no date take today
+        else:
+            date_ref = datetime.now()
+            past_date_ref = (datetime.now()
+                           + relativedelta(months=-int(period),
+                                       day=1,
+                                       days=-1)).strftime('%Y-%m-%d')
+        # Construct sql clause
+        sql_clause = "and date_expected between '%s' and '%s' " \
+                                            % (past_date_ref, date_ref)
+        product_obj = self.pool.get('product.product')
+        states_str = ','.join(map(lambda s: "'%s'" % s, states))
+        if not product_ids:
+            product_ids = product_obj.search(cr, uid, [])
+        res = {}
+        for id in product_ids:
+            res[id] = 0.0
+        if not ids:
+            return res
+
+        product2uom = {}
+        for product in product_obj.browse(cr, uid, product_ids,
+                                          context=context):
+            product2uom[product.id] = product.uom_id.id
+
+        prod_ids_str = ','.join(map(str, product_ids))
+        location_ids_str = ','.join(map(str, ids))
+        results = []
+        results2 = []
+        if 'in' in what:
+            # all moves from a location out of the set to a location in the set
+            cr.execute(
+              """select sum(product_qty), product_id, product_uom
+                 from stock_move
+                 where location_id not in (""" + location_ids_str + """)
+                 and location_dest_id in (""" + location_ids_str + """)
+                 and product_id in (""" + prod_ids_str + """)
+                 and state in (""" + states_str + """) """
+               + sql_clause + """group by product_id,product_uom"""
+            )
+            results = cr.fetchall()
+        if 'out' in what:
+            # all moves from a location in the set to a location out of the set
+            cr.execute(
+              """select sum(product_qty), product_id, product_uom
+                 from stock_move
+                 where location_id in (""" + location_ids_str + """)
+                 and location_dest_id not in (""" + location_ids_str + """)
+                 and product_id in (""" + prod_ids_str + """)
+                 and state in (""" + states_str + """) """
+               + sql_clause + """group by product_id,product_uom"""
+            )
+            results2 = cr.fetchall()
+        uom_obj = self.pool.get('product.uom')
+        for amount, prod_id, prod_uom in results:
+            amount = uom_obj._compute_qty(cr, uid, prod_uom, amount,
+                    context.get('uom', False) or product2uom[prod_id])
+            res[prod_id] += amount
+        for amount, prod_id, prod_uom in results2:
+            amount = uom_obj._compute_qty(cr, uid, prod_uom, amount,
+                    context.get('uom', False) or product2uom[prod_id])
+            res[prod_id] -= amount
+        return res
+
+
+class ProductProduct(orm.Model):
+
+    _inherit = "product.product"
+
+    def _get_product_obsolescence_func(states, what, period):
+        def _product_obs(self, cr, uid, ids, name, arg, context={}):
+            loc_obj = self.pool.get('stock.location')
+
+            if context.get('shop', False):
+                cr.execute("""select warehouse_id
+                              from sale_shop
+                              where id=%s""",
+                              (context['shop'],))
+                res2 = cr.fetchone()
+                if res2:
+                    context['warehouse'] = res2[0]
+
+            if context.get('warehouse', False):
+                cr.execute("""select lot_stock_id
+                              from stock_warehouse
+                              where id=%s""",
+                              (context['warehouse'],))
+                res2 = cr.fetchone()
+                if res2:
+                    context['location'] = res2[0]
+
+            if context.get('location', False):
+                location_ids = [context['location']]
+            else:
+                # get the company location id
+                mod_obj = self.pool.get('ir.model.data')
+                result = mod_obj._get_id(cr, uid, 'stock',
+                                         'stock_location_company')
+                location_ids = [mod_obj.read(cr, uid,
+                                             [result],
+                                             ['res_id'])[0]['res_id']]
+
+            # build the list of ids of children of the location given by id
+            location_ids = loc_obj.search(cr, uid,
+                                          [('location_id',
+                                            'child_of',
+                                            location_ids)],
+                                          context=context)
+            res = loc_obj._product_get_multi_location_for_period(cr,
+                                                                 uid,
+                                                                 location_ids,
+                                                                 int(period),
+                                                                 ids,
+                                                                 context,
+                                                                 states,
+                                                                 what)
+            for id in ids:
+                res.setdefault(id, 0.0)
+            return res
+
+        return _product_obs
+
+    # Considering all state for obsolescence
+    # May be only done...
+    _product_out_qty_till_12m = _get_product_obsolescence_func(('confirmed',
+                                                                'waiting',
+                                                                'assigned',
+                                                                'done'),
+                                                               ('out',), 12)
+    _product_out_qty_till_24m = _get_product_obsolescence_func(('confirmed',
+                                                                'waiting',
+                                                                'assigned',
+                                                                'done'),
+                                                               ('out',), 24)
+
+    _columns = {
+        'outgoing_qty_till_12m': fields.function(_product_out_qty_till_12m,
+                                                 method=True, type='float',
+                                                 string='Outgoing last 12 month'),
+        'outgoing_qty_till_24m': fields.function(_product_out_qty_till_24m,
+                                                 method=True, type='float',
+                                                 string='Outgoing last 24 month'),
+
+        'depreciation': fields.selection([('no', 'No'),
+                                          ('half', 'Half'),
+                                          ('full', 'Full')],
+                                         'Depreciation'),
+    }
+
+    _defaults = {
+        'depreciation': lambda *a: 'no',
+    }

=== added file 'stock_obsolete/stock_obsolete_report.xml'
--- stock_obsolete/stock_obsolete_report.xml	1970-01-01 00:00:00 +0000
+++ stock_obsolete/stock_obsolete_report.xml	2014-09-04 08:30:40 +0000
@@ -0,0 +1,13 @@
+<openerp>
+    <data>
+        <report id="product.obsolete"
+            string="Product obsolescence"
+            model="product.product"
+            name="product.obsolete"
+            rml="stock_obsolete/report/product_obsolete.rml"
+            auto="False"
+            menu="False"
+            header="False"
+            />
+    </data>
+</openerp>
\ No newline at end of file

=== added file 'stock_obsolete/stock_obsolete_view.xml'
--- stock_obsolete/stock_obsolete_view.xml	1970-01-01 00:00:00 +0000
+++ stock_obsolete/stock_obsolete_view.xml	2014-09-04 08:30:40 +0000
@@ -0,0 +1,75 @@
+<openerp>
+    <data>
+        <!-- blue: deprecated, red: may be must be deprecated -->
+        <record model="ir.ui.view" id="product_product_obsolet_tree_view">
+            <field name="name">product.product.tree</field>
+            <field name="model">product.product</field>
+            <field name="type">tree</field>
+            <field name="arch" type="xml">
+                <tree string="Products obsolescence" editable="bottom" colors="red:outgoing_qty_till_12m==0.0;blue:depreciation in ['full']">
+                    <field name="default_code"/>
+                    <field name="name"/>
+                    <field name="variants"/>
+                    <field name="qty_available"/>
+                    <field name="virtual_available"/>
+                    <field name="list_price"/>
+                    <field name="standard_price"/>
+                    <field name="depreciation"/>
+                    <field name="outgoing_qty_till_12m" />
+                    <field name="outgoing_qty_till_24m" />
+                </tree>
+            </field>
+        </record>
+
+        <record model="ir.ui.view" id="product_product_obsolet_form_view">
+            <field name="name">product.normal.inherit.stock_obsolete.form</field>
+            <field name="model">product.product</field>
+            <field name="type">form</field>
+            <field name="inherit_id" ref="product.product_normal_form_view"/>
+            <field name="arch" type="xml">
+                <field name="uos_coeff" position="after">
+                    <field name="depreciation"/>
+                    <field name="outgoing_qty_till_12m" />
+                    <field name="outgoing_qty_till_24m" />
+                </field>
+            </field>
+        </record>
+
+        <record id="wizard_product_obsolescence_form_view" model="ir.ui.view">
+            <field name="name">wizard.product.obsolescence.form</field>
+            <field name="model">wizard.product.obsolescence</field>
+            <field name="type">form</field>
+            <field name="arch" type="xml">
+                <form string="Product obsolescence computation">
+                    <group colspan="4" col="2" string="Options">
+                        <field name="to_date" />
+                        <field name="location" />
+                    </group>
+                    <button name="button_open"
+                            string="Open View"
+                            colspan="1"
+                            type="object" icon="gtk-execute"/>
+                    <button name="button_report"
+                            string="Open Report"
+                            colspan="1"
+                            type="object" icon="gtk-execute"/>
+                </form>
+            </field>
+        </record>
+
+        <record id="wizard_product_obsolescence_action" model="ir.actions.act_window">
+            <field name="name">Product obsolescence</field>
+            <field name="type">ir.actions.act_window</field>
+            <field name="res_model">wizard.product.obsolescence</field>
+            <field name="view_type">form</field>
+            <field name="view_mode">form</field>
+            <field name="view_id" ref="wizard_product_obsolescence_form_view"/>
+            <field name="target">new</field>
+        </record>
+
+        <menuitem name="Products/Obsolescence Control" parent="base.menu_product"
+            action="wizard_product_obsolescence_action" id="wizard_list_inv_so_menu"/>
+
+
+    </data>
+</openerp>
\ No newline at end of file

=== added directory 'stock_obsolete/wizard'
=== added file 'stock_obsolete/wizard/__init__.py'
--- stock_obsolete/wizard/__init__.py	1970-01-01 00:00:00 +0000
+++ stock_obsolete/wizard/__init__.py	2014-09-04 08:30:40 +0000
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (c) 2008 Camtocamp SA
+# @author Joël Grand-Guillaume
+# $Id: $
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+import wizard_product_obsolescence
\ No newline at end of file

=== added file 'stock_obsolete/wizard/wizard_product_obsolescence.py'
--- stock_obsolete/wizard/wizard_product_obsolescence.py	1970-01-01 00:00:00 +0000
+++ stock_obsolete/wizard/wizard_product_obsolescence.py	2014-09-04 08:30:40 +0000
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Copyright (c) Camptocamp SA
+# Author: Arnaud Wüst
+#
+#
+#    This file is part of the c2c_planning_management module
+#
+#
+# WARNING: This program as such is intended to be used by professional
+# programmers who take the whole responsability of assessing all potential
+# consequences resulting from its eventual inadequacies and bugs
+# End users who are looking for a ready-to-use solution with commercial
+# garantees and support are strongly adviced to contract a Free Software
+# Service Company
+#
+# This program is Free Software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+##############################################################################
+
+from osv import fields, orm
+
+
+class wizard_product_obsolescence(orm.TransientModel):
+    _name = "wizard.product.obsolescence"
+
+    def _location_default_get(self, cr, uid, context):
+        # get the company location id
+        mod_obj = self.pool.get('ir.model.data')
+        result = mod_obj._get_id(cr, uid, 'stock', 'stock_location_company')
+        stock_location_id = mod_obj.read(cr, uid,
+                                        [result],
+                                        ['res_id'])[0]['res_id']
+        return stock_location_id
+
+    _columns = {
+        'location': fields.many2one('stock.location',
+                                    'From location',
+                                    required=True),
+        'to_date': fields.date('Obsolescence to date',
+                               required=True),
+    }
+
+    _defaults = {
+        'location': lambda self, cr, uid, context:
+                    self._location_default_get(cr, uid, context=context),
+        'to_date': lambda *a: fields.datetime.now(),
+    }
+
+    def button_open(self, cr, uid, ids, context=None):
+        # get view
+        mod_obj = self.pool.get('ir.model.data')
+        result = mod_obj._get_id(cr, uid, 'stock_obsolete',
+                                 'product_product_obsolet_tree_view')
+        tree_view_id = mod_obj.read(cr, uid, [result], ['res_id'])[0]['res_id']
+
+        # take only stockable product type
+        wizard = self.browse(cr, uid, ids, context=context)[0]
+
+        value = {
+            'domain': "[('type','=','product')]",
+            'name': 'Product obsolescence',
+            'view_type': 'tree',
+            'view_mode': 'tree',
+            'res_model': 'product.product',
+            'view_id': [tree_view_id],
+            'type': 'ir.actions.act_window',
+            'limit': 4000,
+            'context': "{'ref_date':'%s','location':%s}" % (wizard['to_date'],
+                                                            wizard['location'].id)
+        }
+        return value
+
+    def button_report(self, cr, uid, ids, context=None):
+        data = {}
+        data['ids'] = context.get('active_ids', [])
+        data['model'] = context.get('active_model', 'ir.ui.menu')
+        data['form'] = self.read(cr, uid, ids, ['location', 'to_date'])[0]
+        return {
+            'type': 'ir.actions.report.xml',
+            'report_name': 'product.obsolete',
+            'datas': data,
+        }


Follow ups