[IMP] wizard to get the stock valuation for a past date

bzr revid: qdp-launchpad@openerp.com-20131204105920-565t0ijcyue6ydkx
This commit is contained in:
Quentin (OpenERP) 2013-12-04 11:59:20 +01:00
parent f89b39c799
commit cdf7f97389
8 changed files with 218 additions and 110 deletions

View File

@ -20,7 +20,6 @@
##############################################################################
import product
import standard_prices
import stock_account
import stock
import wizard

View File

@ -52,6 +52,7 @@ Dashboard / Reports for Warehouse Management will include:
'stock_account_data.xml',
'wizard/stock_change_standard_price_view.xml',
'wizard/stock_invoice_onshipping_view.xml',
'wizard/stock_valuation_history_view.xml',
'product_data.xml',
'product_view.xml',
'stock_account_view.xml',

View File

@ -21,10 +21,55 @@
from openerp.osv import fields, osv
from openerp.tools.translate import _
import time
class prices_history(osv.osv):
"""
Keep track of the ``product.product`` standard prices as they are changed.
"""
_name = 'prices.history'
_rec_name = 'datetime'
_order = 'datetime desc'
_columns = {
'company_id': fields.many2one('res.company', required=True),
'product_id': fields.many2one('product.product', 'Product', required=True),
'datetime': fields.datetime('Historization Time'),
'cost': fields.float('Historized Cost'),
'reason': fields.char('Reason'),
# TODO 'origin': openerp.osv.fields.reference(),
#'quant_id': openerp.osv.fields.many2one('stock.quant'),
}
def _get_default_company(self, cr, uid, context=None):
if 'force_company' in context:
return context['force_company']
else:
company = self.pool['res.users'].browse(cr, uid, uid,
context=context).company_id
return company.id if company else False
_defaults = {
#'quant_id': False,
'datetime': fields.datetime.now,
'company_id': _get_default_company,
}
class product_product(osv.osv):
_inherit = "product.product"
def get_history_price(self, cr, uid, product_id, company_id, context=None):
if context is None:
context = {}
date = context.get('history_date', time.strftime('%Y-%m-%d %H:%M:%s'))
prices_history_obj = self.pool.get('prices.history')
history_ids = prices_history_obj.search(cr, uid, [('company_id', '=', company_id), ('product_id', '=', product_id), ('datetime', '<=', date)], limit=1)
if history_ids:
return prices_history_obj.read(cr, uid, history_ids[0], ['cost'], context=context)['cost']
raise osv.except_osv(_('Error!'), _("No standard price associated for product %d for the given date" % (product_id)))
def get_product_accounts(self, cr, uid, product_id, context=None):
""" To get the stock input account, stock output account and stock journal related to product.
@param product_id: product id
@ -173,7 +218,7 @@ class product_product(osv.osv):
price_history_obj.create(cr, uid, {
'product_id': product_id,
'cost': vals.get('standard_price', 0.0),
'reason': 'standard_price is set',
'reason': _('Product created and standard price set'),
}, context=context)
return product_id

View File

@ -91,34 +91,5 @@
</xpath>
</field>
</record>
<record model="ir.ui.view" id="view_stock_history_tree">
<field name="name">stock.history.tree</field>
<field name="model">stock.history</field>
<field eval="12" name="priority"/>
<field name="arch" type="xml">
<tree string="Stock">
<field name="move_id" invisible="1"/>
<field name="location_id"/>
<field name="product_id"/>
<field name="quantity"/>
<field name="date"/>
<field name="cost"/>
</tree>
</field>
</record>
<record id="action_stock_history_report" model="ir.actions.act_window">
<field name="name">Stock History</field>
<field name="res_model">stock.history</field>
<field name="view_type">form</field>
<field name="view_mode">tree,graph,form</field>
<field name="view_id" ref="view_stock_history_tree"/>
<!--<field name="context">{'search_default_real':1, 'search_default_inmovesremaining':1 ,'group_by':['company_id', 'product_id'], 'group_by_no_leaf':0}</field>
<field name="help">Inventory Analysis allows you to easily check and analyse your company stock levels. Sort and group by selection criteria in order to better analyse and manage your company activities.</field>-->
</record>
<menuitem action="action_stock_history_report"
id="menu_action_stock_history_report"
parent="stock.next_id_61" sequence="5"/>
</data>
</openerp>

View File

@ -1,79 +0,0 @@
from openerp import tools
from openerp.osv import fields, osv
class prices_history(osv.osv):
"""
Keep track of the ``product.product`` standard prices as they are changed.
"""
_name = 'prices.history'
_rec_name = 'datetime'
_columns = {
'company_id': fields.many2one('res.company', required=True),
'product_id': fields.many2one('product.product', 'Product', required=True),
'datetime': fields.datetime('Historization Time'),
'cost': fields.float('Historized Cost'),
'reason': fields.char('Reason'),
# TODO 'origin': openerp.osv.fields.reference(),
#'quant_id': openerp.osv.fields.many2one('stock.quant'),
}
def _get_default_company(self, cr, uid, context=None):
if 'force_company' in context:
return context['force_company']
else:
company = self.pool['res.users'].browse(cr, uid, uid,
context=context).company_id
return company.id if company else False
_defaults = {
#'quant_id': False,
'datetime': fields.datetime.now,
'company_id': _get_default_company,
}
class stock_history(osv.osv):
_name = 'stock.history'
_auto = False
_columns = {
'move_id': fields.many2one('stock.move', 'Stock Move'),
#'quant_id': fields.many2one('stock.quant'),
'location_id': fields.many2one('stock.location', 'Location'),
'product_id': fields.many2one('product.product', 'Product'),
'quantity': fields.integer('Quantity'),
'date': fields.datetime('Date'),
'cost': fields.float('Value'),
'cost_method': fields.char('Cost Method'),
}
def init(self, cr):
tools.drop_view_if_exists(cr, 'stock_history')
cr.execute("""
CREATE OR REPLACE VIEW stock_history AS (
SELECT
stock_move.id AS id,
stock_move.id AS move_id,
stock_move.location_id AS location_id,
stock_move.product_id AS product_id,
stock_move.product_qty AS quantity,
stock_move.date AS date,
ir_property.value_text AS cost_method,
CASE
WHEN ir_property.value_text <> 'real'
THEN (SELECT prices_history.cost FROM prices_history WHERE prices_history.datetime <= stock_move.date AND prices_history.product_id = stock_move.product_id ORDER BY prices_history.datetime ASC limit 1)
ELSE stock_move.price_unit
END AS cost
FROM
stock_move
LEFT JOIN
product_product ON product_product.id = stock_move.product_id
LEFT JOIN
product_template ON product_template.id = product_product.product_tmpl_id
LEFT JOIN
ir_property ON (ir_property.name = 'cost_method' and ir_property.res_id = 'product.template,' || product_template.id::text)
WHERE stock_move.state = 'done'
)""")

View File

@ -21,3 +21,4 @@
import stock_change_standard_price
import stock_invoice_onshipping
import stock_valuation_history

View File

@ -0,0 +1,99 @@
from openerp import tools
from openerp.osv import fields, osv
class wizard_valuation_history(osv.osv_memory):
_name = 'wizard.valuation.history'
_description = 'Wizard that opens the stock valuation history table'
_columns = {
'date': fields.datetime('Date', required=True),
}
_defaults = {
'date': fields.datetime.now,
}
def open_table(self, cr, uid, ids, context=None):
if context is None:
context = {}
data = self.read(cr, uid, ids, context=context)[0]
ctx = context.copy()
ctx['history_date'] = data['date']
ctx['group_by'] = ['product_id']
return {
'domain': "[('date', '<=', '" + data['date'] + "')]",
'name': 'Stock Valuation History',
'view_type': 'form',
'view_mode': 'tree',
'res_model': 'stock.history',
'type': 'ir.actions.act_window',
'context': ctx,
}
class stock_history(osv.osv):
_name = 'stock.history'
_auto = False
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False):
res = super(stock_history, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby)
if 'inventory_value' in fields:
for line in res:
if '__domain' in line:
lines = self.search(cr, uid, line['__domain'], context=context)
inv_value = 0.0
for line2 in self.browse(cr, uid, lines, context=context):
inv_value += line2.inventory_value
line['inventory_value'] = inv_value
return res
def _get_inventory_value(self, cr, uid, ids, name, attr, context=None):
product_obj = self.pool.get("product.product")
res = {}
for line in self.browse(cr, uid, ids, context=context):
if line.product_id.cost_method == 'real':
res[line.id] = line.quantity * line.price_unit_on_move
else:
res[line.id] = line.quantity * product_obj.get_history_price(cr, uid, line.product_id.id, line.company_id.id, context=context)
return res
_columns = {
'move_id': fields.many2one('stock.move', 'Stock Move', required=True),
#'quant_id': fields.many2one('stock.quant'),
'company_id': fields.related('move_id', 'company_id', type='many2one', relation='res.company', string='Company', required=True, select=True),
'location_id': fields.many2one('stock.location', 'Location', required=True),
'product_id': fields.many2one('product.product', 'Product', required=True),
'product_categ_id': fields.many2one('product.category', 'Product Category', required=True),
'quantity': fields.integer('Quantity'),
'date': fields.datetime('Operation Date'),
'price_unit_on_move': fields.float('Value'),
'cost_method': fields.char('Cost Method'),
'inventory_value': fields.function(_get_inventory_value, string="Inventory Value", type='float', readonly=True),
}
def init(self, cr):
tools.drop_view_if_exists(cr, 'stock_history')
cr.execute("""
CREATE OR REPLACE VIEW stock_history AS (
SELECT
stock_move.id AS id,
stock_move.id AS move_id,
stock_move.location_dest_id AS location_id,
stock_move.product_id AS product_id,
product_template.categ_id AS product_categ_id,
stock_move.product_qty AS quantity,
stock_move.date AS date,
ir_property.value_text AS cost_method,
stock_move.price_unit as price_unit_on_move
FROM
stock_move
LEFT JOIN
product_product ON product_product.id = stock_move.product_id
LEFT JOIN
product_template ON product_template.id = product_product.product_tmpl_id
LEFT JOIN
ir_property ON (ir_property.name = 'cost_method' and ir_property.res_id = 'product.template,' || product_template.id::text)
WHERE stock_move.state = 'done'
)""")

View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_wizard_valuation_history" model="ir.ui.view">
<field name="name">Stock Valuation History</field>
<field name="model">wizard.valuation.history</field>
<field name="arch" type="xml">
<form string="Choose your date" version="7.0">
<p class="oe_gray">
Choose the date for wich you want to get the stock valuation of your products.
This will filter the stock operation that weren't done at the selected date, to retreive the quantity
you had, and gives you the inventory value according to the standard price used at that time.
</p>
<group>
<field name="date"/>
</group>
<footer>
<button name="open_table" string="Retrieve the Inventory Value" type="object" class="oe_highlight" />
or
<button string="Cancel" class="oe_link" special="cancel" />
</footer>
</form>
</field>
</record>
<record id="action_wizard_stock_valuation_history" model="ir.actions.act_window">
<field name="name">Stock Valuation History</field>
<field name="res_model">wizard.valuation.history</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="view_id" ref="view_wizard_valuation_history"/>
<field name="target">new</field>
</record>
<menuitem id="menu_action_wizard_valuation_history" action="action_wizard_stock_valuation_history" parent="stock.next_id_61"/>
<record id="view_stock_history_report_tree" model="ir.ui.view">
<field name="name">Stock Valuation History</field>
<field name="model">stock.history</field>
<field name="arch" type="xml">
<tree string="Stock Valuation History">
<field name="location_id" invisible="1"/>
<field name="product_id" invisible="1"/>
<field name="move_id"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="date"/>
<field name="quantity" sum="# of Products "/>
<field name="inventory_value"/>
</tree>
</field>
</record>
<record id="view_stock_history_report_search" model="ir.ui.view">
<field name="name">stock.history.report.search</field>
<field name="model">stock.history</field>
<field name="arch" type="xml">
<search string="Stock Valuation History">
<field name="product_id"/>
<field name="location_id" filter_domain="[('name', 'child_of', self)]"/>
<field name="company_id" groups="base.group_multi_company"/>
<group expand="1" string="Group By...">
<filter string="Product" icon="terp-accessories-archiver" context="{'group_by':'product_id'}" name='group_by_product'/>
<filter string="Product Category" icon="terp-accessories-archiver" context="{'group_by':'product_categ_id'}"/>
<filter string="Location" icon="terp-accessories-archiver" context="{'group_by':'location_id'}"/>
<filter string="Company" icon="terp-go-home" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
</group>
</search>
</field>
</record>
</data>
</openerp>