[IMP] wizard to get the stock valuation for a past date
bzr revid: qdp-launchpad@openerp.com-20131204105920-565t0ijcyue6ydkx
This commit is contained in:
parent
f89b39c799
commit
cdf7f97389
|
@ -20,7 +20,6 @@
|
|||
##############################################################################
|
||||
|
||||
import product
|
||||
import standard_prices
|
||||
import stock_account
|
||||
import stock
|
||||
import wizard
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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'
|
||||
)""")
|
|
@ -21,3 +21,4 @@
|
|||
|
||||
import stock_change_standard_price
|
||||
import stock_invoice_onshipping
|
||||
import stock_valuation_history
|
||||
|
|
|
@ -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'
|
||||
)""")
|
|
@ -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>
|
||||
|
Loading…
Reference in New Issue