openerp-community-reviewer team mailing list archive
-
openerp-community-reviewer team
-
Mailing list archive
-
Message #07920
[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