[IMP]product_qty -> product_uom_qty, report.stock.move not required anymore as we have product_qty

bzr revid: fp@tinyerp.com-20130630141014-evn6hj7870iphgve
This commit is contained in:
Fabien Pinckaers 2013-06-30 16:10:14 +02:00
parent feaa17f0bb
commit 77ceb83f69
19 changed files with 102 additions and 434 deletions

View File

@ -73,6 +73,7 @@ class product_product(osv.osv):
'property_stock_valuation_account_id': account_valuation
}
# FP Note:;too complex, not good, should be implemented at quant level TODO
def do_change_standard_price(self, cr, uid, ids, datas, context=None):
""" Changes the Standard Price of Product and creates an account move accordingly.
@param datas : dict. contain default datas like new_price, stock_output_account, stock_input_account, stock_journal
@ -196,7 +197,7 @@ class product_product(osv.osv):
return _('Products: ')+self.pool.get('stock.location').browse(cr, user, context['active_id'], context).name
return res
def _get_locations_from_context(self, cr, uid, ids, context=None):
def _get_domain_locations(self, cr, uid, ids, context=None):
'''
Parses the context and returns a list of location_ids based on it.
It will return all stock locations when no parameters are given
@ -226,174 +227,56 @@ class product_product(osv.osv):
wh = warehouse_obj.browse(cr, uid, wids, context=context)
for w in warehouse_obj.browse(cr, uid, wids, context=context):
if not context.get('force_company', False) or w.lot_stock_id.company_id.id == context['force_company']:
location_ids.append(w.lot_stock_id.id)
location_ids.append(w.lot_stock_id.id)
# build the list of ids of children of the location given by id
if context.get('compute_child',True):
if context.get('force_company', False):
child_location_ids = location_obj.search(cr, uid, [('location_id', 'child_of', location_ids), ('company_id', '=', context['force_company'])])
else:
child_location_ids = location_obj.search(cr, uid, [('location_id', 'child_of', location_ids)])
location_ids = child_location_ids or location_ids
return location_ids
operator = context.get('compute_child',True) and 'child_of' or 'in'
domain = context.get('force_company', False) and ['&', ('company_id', '=', context['force_company'])] or []
return (
domain + [('location_id', operator, location_ids)],
domain + ['&', ('location_src_id', operator, location_ids), '!', ('location_dest_id', operator, location_ids)],
domain + ['&', ('location_dest_id', operator, location_ids), '!', ('location_src_id', operator, location_ids)]
)
def _get_date_query(self, cr, uid, ids, context):
'''
Parses the context and returns the dates query string needed to be processed in _get_product_available
It searches for a from_date and to_date
'''
def _get_domain_dates(self, cr, uid, ids, context):
from_date = context.get('from_date',False)
to_date = context.get('to_date',False)
date_str = False
whereadd = []
if from_date and to_date:
date_str = "date>=%s and date<=%s"
whereadd.append(tuple([from_date]))
whereadd.append(tuple([to_date]))
elif from_date:
date_str = "date>=%s"
whereadd.append(tuple([from_date]))
elif to_date:
date_str = "date<=%s"
whereadd.append(tuple([to_date]))
return (whereadd, date_str)
def get_product_available(self, cr, uid, ids, context=None):
""" Finds the quantity available of product(s) depending on parameters in the context
for what, states, locations (company, warehouse, ), date, lot,
states: state of the move
what: in (dest in locations) or out (source in locations) moves
LOCATIONS:
shop: warehouse of the shop
warehouse: stock location of the warehouse
location: name (ilike) or id of the location
force_company: if not warehouse or shop given: will only take from this company
compute_child (True if not specified): will also include child locations of locations above
(when force_company only from that company)
from_date and to_date: dates from or to for the date of the stock move to include (=scheduled of effective date)
prodlot: lot of the move
@return: Dictionary of values for every product id
"""
if context is None:
context = {}
states = context.get('states',[])
what = context.get('what',())
if not ids:
ids = self.search(cr, uid, [])
res = {}.fromkeys(ids, 0.0)
if not ids:
return res
#set_context: refactor code here
location_ids = self._get_locations_from_context(cr, uid, ids, context=context)
if not location_ids: #in case of no locations, query will be empty anyways
return res
# this will be a dictionary of the product UoM by product id
product2uom = {}
uom_ids = []
for product in self.read(cr, uid, ids, ['uom_id'], context=context):
product2uom[product['id']] = product['uom_id'][0]
uom_ids.append(product['uom_id'][0])
# this will be a dictionary of the UoM resources we need for conversion purposes, by UoM id
uoms_o = {}
for uom in self.pool.get('product.uom').browse(cr, uid, uom_ids, context=context):
uoms_o[uom.id] = uom
results = []
results2 = []
where = [tuple(location_ids),tuple(location_ids),tuple(ids),tuple(states)]
where_add, date_str = self._get_date_query(cr, uid, ids, context=context)
if where_add:
where += where_add
lot_id = context.get('lot_id', False)
prodlot_clause = ''
if lot_id:
prodlot_clause = ' and lot_id = %s '
where += [lot_id]
# TODO: perhaps merge in one query.
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 %s '\
'and location_dest_id IN %s '\
'and product_id IN %s '\
'and state IN %s ' + (date_str and 'and '+date_str+' ' or '') +' '\
+ prodlot_clause +
'group by product_id,product_uom',tuple(where))
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 %s '\
'and location_dest_id NOT IN %s '\
'and product_id IN %s '\
'and state in %s ' + (date_str and 'and '+date_str+' ' or '') + ' '\
+ prodlot_clause +
'group by product_id,product_uom',tuple(where))
results2 = cr.fetchall()
# Get the missing UoM resources
uom_obj = self.pool.get('product.uom')
uoms = map(lambda x: x[2], results) + map(lambda x: x[2], results2)
if context.get('uom', False):
uoms += [context['uom']]
uoms = filter(lambda x: x not in uoms_o.keys(), uoms)
if uoms:
uoms = uom_obj.browse(cr, uid, list(set(uoms)), context=context)
for o in uoms:
uoms_o[o.id] = o
#TOCHECK: before change uom of product, stock move line are in old uom.
context.update({'raise-exception': False})
# Count the incoming quantities
for amount, prod_id, prod_uom in results:
amount = uom_obj._compute_qty_obj(cr, uid, uoms_o[prod_uom], amount,
uoms_o[context.get('uom', False) or product2uom[prod_id]], context=context)
res[prod_id] += amount
# Count the outgoing quantities
for amount, prod_id, prod_uom in results2:
amount = uom_obj._compute_qty_obj(cr, uid, uoms_o[prod_uom], amount,
uoms_o[context.get('uom', False) or product2uom[prod_id]], context=context)
res[prod_id] -= amount
return res
domain = []
if from_date:
domain.append(('date','>=',from_date))
if to_date:
domain.append(('date','<=',to_date))
return domain
def _product_available(self, cr, uid, ids, field_names=None, arg=False, context=None):
""" Finds the incoming and outgoing quantity of product.
@return: Dictionary of values
"""
if not field_names:
field_names = []
if context is None:
context = {}
context = context or {}
field_names = field_names or []
domain_quant, domain_move_in, domain_move_out = self._get_domain_locations(cr, uid, ids, key='location_id', context=context)
domain_move_in += self._get_domain_dates(cr, uid, ids, context=context)
domain_move_out += self._get_domain_dates(cr, uid, ids, context=context)
if context.get('lot_id', False):
domain_quants.append(('lot_id','=',context['lot_id']))
moves_in = []
moves_out = []
else:
moves_in = self.pool.get('stock.move').read_group(cr, uid, domain_move_in, ['product_id', 'product_qty'], ['product_id'], context=context)
moves_out = self.pool.get('stock.move').read_group(cr, uid, domain_move_out, ['product_id', 'product_qty'], ['product_id'], context=context)
quants = self.pool.get('stock.quant').read_group(cr, uid, domain_quant, ['product_id', 'qty'], ['product_id'], context=context)
quants = dict(map(lambda x: (x['product_id'], x['qty']), quants))
moves_in = dict(map(lambda x: (x['product_id'], x['product_qty']), moves_in))
moves_out = dict(map(lambda x: (x['product_id'], x['product_qty']), moves_out))
res = {}
for id in ids:
res[id] = {}.fromkeys(field_names, 0.0)
for f in field_names:
c = context.copy()
if f == 'qty_available':
c.update({ 'states': ('done',), 'what': ('in', 'out') })
if f == 'virtual_available':
c.update({ 'states': ('confirmed','waiting','assigned','done'), 'what': ('in', 'out') })
if f == 'incoming_qty':
c.update({ 'states': ('confirmed','waiting','assigned'), 'what': ('in',) })
if f == 'outgoing_qty':
c.update({ 'states': ('confirmed','waiting','assigned'), 'what': ('out',) })
stock = self.get_product_available(cr, uid, ids, context=c)
for id in ids:
res[id][f] = stock.get(id, 0.0)
res[id] = {
'qty_available': quants.get(id, 0.0),
'incoming_qty': moves_in.get(id, 0.0),
'outgoing_qty': moves_out.get(id, 0.0),
'virtual_available': quants.get(id, 0.0) + moves_in.get(id, 0.0) - moves_out.get(id, 0.0),
}
return res
_columns = {

View File

@ -5,7 +5,7 @@
<product type="field" name="product_id.name"/>
<variant type="field" name="product_id.variants"/>
<uom type="field" name="product_uom.name"/>
<quantity type="field" name="product_qty"/>
<quantity type="field" name="product_uom_qty"/>
<tracking type="field" name="tracking_id.name"/>
<serial type="field" name="tracking_id.serial"/>
</lot-line>

View File

@ -257,7 +257,7 @@
<para style="terp_default_Right_9">[[ (move_lines.location_id and move_lines.location_id.name) or '' ]] </para>
</td>
<td>
<para style="terp_default_Right_9">[[ formatLang(move_lines.product_qty) ]] [[ move_lines.product_uom.name ]]</para>
<para style="terp_default_Right_9">[[ formatLang(move_lines.product_uom_qty) ]] [[ move_lines.product_uom.name ]]</para>
</td>
<td>
<barCode code="code128" quiet="9" fontName="Times-Roman" fontSize="50" alignment="CENTER"> [[ move_lines.product_id.ean13 ]] </barCode>
@ -287,7 +287,7 @@
<para style="terp_default_Right_9">[[ (move_lines.location_id and move_lines.location_id.name) or '' ]] </para>
</td>
<td>
<para style="terp_default_Right_9">[[ formatLang(move_lines.product_qty) ]] [[ move_lines.product_uom.name ]]</para>
<para style="terp_default_Right_9">[[ formatLang(move_lines.product_uom_qty) ]] [[ move_lines.product_uom.name ]]</para>
</td>
<td>
<barCode code="code128" quiet="9" fontName="Times-Roman" fontSize="50" alignment="CENTER"> [[ move_lines.product_id.ean13 ]] </barCode>

View File

@ -42,6 +42,8 @@ class external_pdf(render):
return self.pdf
# FP Note: change to use product_qty instead of product_uom_qty to avoid doing conversions
class report_stock(report_int):
def create(self, cr, uid, ids, datas, context=None):
if context is None:

View File

@ -23,123 +23,6 @@ from openerp import tools
from openerp.osv import fields,osv
from openerp.addons.decimal_precision import decimal_precision as dp
class report_stock_move(osv.osv):
_name = "report.stock.move"
_description = "Moves Statistics"
_auto = False
_columns = {
'date': fields.date('Date', readonly=True),
'year': fields.char('Year', size=4, readonly=True),
'day': fields.char('Day', size=128, readonly=True),
'month':fields.selection([('01','January'), ('02','February'), ('03','March'), ('04','April'),
('05','May'), ('06','June'), ('07','July'), ('08','August'), ('09','September'),
('10','October'), ('11','November'), ('12','December')], 'Month',readonly=True),
'partner_id':fields.many2one('res.partner', 'Partner', readonly=True),
'product_id':fields.many2one('product.product', 'Product', readonly=True),
'company_id':fields.many2one('res.company', 'Company', readonly=True),
'picking_id':fields.many2one('stock.picking', 'Shipment', readonly=True),
'type': fields.selection([('out', 'Sending Goods'), ('in', 'Getting Goods'), ('internal', 'Internal'), ('other', 'Others')], 'Shipping Type', required=True, select=True, help="Shipping type specify, goods coming in or going out."),
'location_id': fields.many2one('stock.location', 'Source Location', readonly=True, select=True, help="Sets a location if you produce at a fixed location. This can be a partner location if you subcontract the manufacturing operations."),
'location_dest_id': fields.many2one('stock.location', 'Dest. Location', readonly=True, select=True, help="Location where the system will stock the finished products."),
'state': fields.selection([('draft', 'Draft'), ('waiting', 'Waiting'), ('confirmed', 'Confirmed'), ('assigned', 'Available'), ('done', 'Done'), ('cancel', 'Cancelled')], 'Status', readonly=True, select=True),
'product_qty':fields.integer('Quantity',readonly=True),
'categ_id': fields.many2one('product.category', 'Product Category', ),
'product_qty_in':fields.integer('In Qty',readonly=True),
'product_qty_out':fields.integer('Out Qty',readonly=True),
'value' : fields.float('Total Value', required=True),
'day_diff2':fields.float('Lag (Days)',readonly=True, digits_compute=dp.get_precision('Shipping Delay'), group_operator="avg"),
'day_diff1':fields.float('Planned Lead Time (Days)',readonly=True, digits_compute=dp.get_precision('Shipping Delay'), group_operator="avg"),
'day_diff':fields.float('Execution Lead Time (Days)',readonly=True, digits_compute=dp.get_precision('Shipping Delay'), group_operator="avg"),
'stock_journal': fields.many2one('stock.journal','Stock Journal', select=True),
}
def init(self, cr):
tools.drop_view_if_exists(cr, 'report_stock_move')
cr.execute("""
CREATE OR REPLACE view report_stock_move AS (
SELECT
min(sm_id) as id,
date_trunc('day',al.dp) as date,
al.curr_year as year,
al.curr_month as month,
al.curr_day as day,
al.curr_day_diff as day_diff,
al.curr_day_diff1 as day_diff1,
al.curr_day_diff2 as day_diff2,
al.location_id as location_id,
al.picking_id as picking_id,
al.company_id as company_id,
al.location_dest_id as location_dest_id,
al.product_qty,
al.out_qty as product_qty_out,
al.in_qty as product_qty_in,
al.partner_id as partner_id,
al.product_id as product_id,
al.state as state ,
al.product_uom as product_uom,
al.categ_id as categ_id,
coalesce(al.type, 'other') as type,
al.stock_journal as stock_journal,
sum(al.in_value - al.out_value) as value
FROM (SELECT
CASE WHEN sp.type in ('out') THEN
sum(sm.product_qty * pu.factor / pu2.factor)
ELSE 0.0
END AS out_qty,
CASE WHEN sp.type in ('in') THEN
sum(sm.product_qty * pu.factor / pu2.factor)
ELSE 0.0
END AS in_qty,
CASE WHEN sp.type in ('out') THEN
sum(sm.product_qty * sm.price_unit)
ELSE 0.0
END AS out_value,
CASE WHEN sp.type in ('in') THEN
sum(sm.product_qty * sm.price_unit)
ELSE 0.0
END AS in_value,
min(sm.id) as sm_id,
sm.date as dp,
to_char(date_trunc('day',sm.date), 'YYYY') as curr_year,
to_char(date_trunc('day',sm.date), 'MM') as curr_month,
to_char(date_trunc('day',sm.date), 'YYYY-MM-DD') as curr_day,
avg(date(sm.date)-date(sm.create_date)) as curr_day_diff,
avg(date(sm.date_expected)-date(sm.create_date)) as curr_day_diff1,
avg(date(sm.date)-date(sm.date_expected)) as curr_day_diff2,
sm.location_id as location_id,
sm.location_dest_id as location_dest_id,
sum(sm.product_qty) as product_qty,
pt.categ_id as categ_id ,
sm.partner_id as partner_id,
sm.product_id as product_id,
sm.picking_id as picking_id,
sm.company_id as company_id,
sm.state as state,
sm.product_uom as product_uom,
sp.type as type,
sp.stock_journal_id AS stock_journal
FROM
stock_move sm
LEFT JOIN stock_picking sp ON (sm.picking_id=sp.id)
LEFT JOIN product_product pp ON (sm.product_id=pp.id)
LEFT JOIN product_uom pu ON (sm.product_uom=pu.id)
LEFT JOIN product_uom pu2 ON (sm.product_uom=pu2.id)
LEFT JOIN product_template pt ON (pp.product_tmpl_id=pt.id)
GROUP BY
sm.id,sp.type, sm.date,sm.partner_id,
sm.product_id,sm.state,sm.product_uom,sm.date_expected,
sm.product_id, sm.picking_id, sm.product_qty,
sm.company_id,sm.product_qty, sm.location_id,sm.location_dest_id,pu.factor,pt.categ_id, sp.stock_journal_id)
AS al
GROUP BY
al.out_qty,al.in_qty,al.curr_year,al.curr_month,
al.curr_day,al.curr_day_diff,al.curr_day_diff1,al.curr_day_diff2,al.dp,al.location_id,al.location_dest_id,
al.partner_id,al.product_id,al.state,al.product_uom,
al.picking_id,al.company_id,al.type,al.product_qty, al.categ_id, al.stock_journal
)
""")
# FP Note: TODO: drop this table and use the stock.move table instead
class report_stock_inventory(osv.osv):
_name = "report.stock.inventory"

View File

@ -9,97 +9,6 @@
parent="base.menu_reporting"
groups="group_stock_manager"/>
<record id="view_stock_tree" model="ir.ui.view">
<field name="name">report.stock.move.tree</field>
<field name="model">report.stock.move</field>
<field name="arch" type="xml">
<tree string="Moves Analysis" create="false">
<field name="date" invisible="1"/>
<field name="year" invisible="1" />
<field name="month" invisible="1"/>
<field name="day" invisible="1"/>
<field name="type" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="partner_id" invisible="1" context="{'contact_display':'partner'}" />
<field name="picking_id" invisible="1"/>
<field name="location_id" invisible="1"/>
<field name="location_dest_id" invisible="1"/>
<field name="product_id" invisible="1"/>
<field name="categ_id" invisible="1"/>
<field name="stock_journal" invisible="1"/>
<field name="state" invisible="1"/>
<field name="product_qty" sum="Total quantity"/>
<field name="product_qty_in" sum="Total incoming quantity" />
<field name="product_qty_out" sum="Total outgoing quantity"/>
<field name="value" sum="Total value"/>
<field name="day_diff1"/>
<field name="day_diff"/>
<field name="day_diff2" string="Delay(Days)"/>
</tree>
</field>
</record>
<record id="view_stock_graph" model="ir.ui.view">
<field name="name">report.stock.move.graph</field>
<field name="model">report.stock.move</field>
<field name="arch" type="xml">
<graph string="Moves Analysis" type="bar">
<field name="product_id"/>
<field name="product_qty" operator="+"/>
</graph>
</field>
</record>
<record id="view_stock_search" model="ir.ui.view">
<field name="name">report.stock.move.search</field>
<field name="model">report.stock.move</field>
<field name="arch" type="xml">
<search string="Moves Analysis">
<filter string="Done" name="done" icon="terp-dialog-close" domain="[('state','=','done')]" help = "Completed Stock-Moves"/>
<filter string="Todo" icon="terp-gtk-go-back-rtl" domain="[('state','in',('assigned','waiting','confirmed'))]" help = "Future Stock-Moves"/>
<separator/>
<filter icon="terp-go-home" name="in" string="Incoming" domain="[('type','=','in')]"/>
<filter icon="terp-go-home" name="internal" string="Internal" domain="[('type','=','internal')]"/>
<filter icon="terp-go-home" name="out" string="Outgoing" domain="[('type','=','out')]"/>
<field name="product_id" default_focus="1"/>
<field name="partner_id" context="{'contact_display':'partner'}"/>
<group expand="0" string="Extended Filters...">
<field name="location_id" />
<field name="location_dest_id" />
<field name="categ_id"/>
<field name="stock_journal"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="date"/>
</group>
<group expand="1" string="Group By...">
<filter name="group_partner" string="Partner" icon="terp-partner" context="{'group_by':'partner_id'}"/>
<filter name="group_categ_id" string="Product Category" icon="terp-stock_symbol-selection" context="{'group_by':'categ_id'}"/>
<filter name="group_product" string="Product" icon="terp-accessories-archiver" context="{'group_by':'product_id'}"/>
<filter name="group_picking" string="Shipment" icon="terp-accessories-archiver" context="{'group_by':'picking_id'}"/>
<filter string="Source Location" name="src_location" icon="terp-gtk-jump-to-rtl" context="{'group_by':'location_id'}"/>
<filter string="Dest. Location" name="dest_location" icon="terp-gtk-jump-to-ltr" context="{'group_by':'location_dest_id'}"/>
<filter string="Type" name="group_type" icon="terp-stock_symbol-selection" context="{'group_by':'type'}" help="Shipping type specify, goods coming in or going out"/>
<filter string="Status" name="group_state" icon="terp-stock_effects-object-colorize" context="{'group_by':'state'}"/>
<filter string="Stock journal" name="group_stock_journal" icon="terp-folder-orange" context="{'group_by':'stock_journal'}"/>
<filter string="Company" name="group_state" icon="terp-go-home" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
<filter string="Day" icon="terp-go-today" context="{'group_by':'day'}" help="Day Planned"/>
<filter string="Month" icon="terp-go-month" context="{'group_by':'date'}" help="Month Planned"/>
<filter string="Year" icon="terp-go-year" context="{'group_by':'year'}" help="Year Planned"/>
</group>
</search>
</field>
</record>
<record id="action_stock_move_report" model="ir.actions.act_window">
<field name="name">Moves Analysis</field>
<field name="res_model">report.stock.move</field>
<field name="view_type">form</field>
<field name="view_mode">tree,graph</field>
<field name="search_view_id" ref="view_stock_search"/>
<field name="context">{'contact_display': 'partner','search_default_done':1,'search_default_year':1, 'search_default_month':1, 'search_default_group_type':1, 'group_by': [], 'group_by_no_leaf':1,}</field>
<field name="help">Moves Analysis allows you to easily check and analyse your company stock moves. Use this report when you want to analyse the different routes taken by your products and inventory management performance.</field>
</record>
<menuitem action="action_stock_move_report" id="menu_action_stock_move_report" parent="next_id_61" sequence="3"/>
<!-- Inventory Control -->
<record id="view_stock_inventory_tree" model="ir.ui.view">
<field name="name">report.stock.inventory.tree</field>

View File

@ -26,8 +26,6 @@ access_stock_location_sale_manager,stock.location sale manager,model_stock_locat
access_stock_location_stock_manager,stock.location stock manager,model_stock_location,stock.group_stock_manager,1,0,0,0
access_stock_lines_date_user,report.stock.lines.date user,model_report_stock_lines_date,stock.group_stock_user,1,0,0,0
access_stock_lines_date_manager,report.stock.lines.date manager,model_report_stock_lines_date,stock.group_stock_manager,1,1,1,1
access_report_stock_move_user,report.stock.move user,model_report_stock_move,stock.group_stock_user,1,0,0,0
access_report_stock_move_manager,report.stock.move manager,model_report_stock_move,stock.group_stock_manager,1,1,1,1
access_report_stock_inventory_user,report.stock.inventory user,model_report_stock_inventory,stock.group_stock_user,1,1,1,1
access_product_product_stock_user,product_product_stock_user,product.model_product_product,stock.group_stock_user,1,1,0,0
access_product_template_stock_user,product.template stock user,product.model_product_template,stock.group_stock_user,1,1,0,0

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
26 access_stock_location_stock_manager stock.location stock manager model_stock_location stock.group_stock_manager 1 0 0 0
27 access_stock_lines_date_user report.stock.lines.date user model_report_stock_lines_date stock.group_stock_user 1 0 0 0
28 access_stock_lines_date_manager report.stock.lines.date manager model_report_stock_lines_date stock.group_stock_manager 1 1 1 1
access_report_stock_move_user report.stock.move user model_report_stock_move stock.group_stock_user 1 0 0 0
access_report_stock_move_manager report.stock.move manager model_report_stock_move stock.group_stock_manager 1 1 1 1
29 access_report_stock_inventory_user report.stock.inventory user model_report_stock_inventory stock.group_stock_user 1 1 1 1
30 access_product_product_stock_user product_product_stock_user product.model_product_product stock.group_stock_user 1 1 0 0
31 access_product_template_stock_user product.template stock user product.model_product_template stock.group_stock_user 1 1 0 0

View File

@ -18,7 +18,7 @@ function openerp_picking_widgets(instance){
_.each( model.movelines, function(moveline){
rows.push({
cols: { product: moveline.product_id[1],
qty: moveline.product_qty,
qty: moveline.product_uom_qty,
rem: moveline.remaining_qty,
uom: moveline.product_uom[1],
loc: moveline.location_id[1],
@ -49,7 +49,7 @@ function openerp_picking_widgets(instance){
cols: {
product: op.product_id[1],
uom: op.product_uom ? product_uom[1] : '',
qty: op.product_qty,
qty: op.product_uom_qty,
}
});
});

View File

@ -351,9 +351,8 @@ class stock_quant(osv.osv):
def _location_owner(self, cr, uid, quant, location, context=None):
return location and (location.usage == 'internal') and location.company_id or False
# FP Note: all accounting valuation stuff must be on the quant
# TODO: move this code on the _account_entry_move method above. Should be simpler
#
#def _get_accounting_data_for_valuation(self, cr, uid, move, context=None):
# """
# Return the accounts and journal to use to post Journal Entries for the real-time
@ -1574,6 +1573,13 @@ class stock_move(osv.osv):
# return False
# return True
def _quantity_normalize(self, cr, uid, ids, name, args, context=None):
uom_obj = self.pool.get('product.uom')
res = {}
for m in self.browse(cr, uid, ids, context=context):
res[m.id] = uom_obj._compute_qty_obj(cr, uid, m.product_uom, product_qty, m.product_id.uom_id)
return res
_columns = {
'name': fields.char('Description', required=True, select=True),
'priority': fields.selection([('0', 'Not urgent'), ('1', 'Urgent')], 'Priority'),
@ -1581,7 +1587,9 @@ class stock_move(osv.osv):
'date': fields.datetime('Date', required=True, select=True, help="Move date: scheduled date until move is done, then date of actual move processing", states={'done': [('readonly', True)]}),
'date_expected': fields.datetime('Scheduled Date', states={'done': [('readonly', True)]},required=True, select=True, help="Scheduled date for the processing of this move"),
'product_id': fields.many2one('product.product', 'Product', required=True, select=True, domain=[('type','<>','service')],states={'done': [('readonly', True)]}),
'product_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'),
'product_qty': fields.function(_quantity_normalize, type='float', store=True, string='Quantity',
digits_compute=dp.get_precision('Product Unit of Measure'), 'Quantity in the default UoM of the product'),
'product_uom_qty': fields.float('Quantity', digits_compute=dp.get_precision('Product Unit of Measure'),
required=True,states={'done': [('readonly', True)]},
help="This is the quantity of products from an inventory "
"point of view. For moves in the state 'done', this is the "
@ -1888,7 +1896,6 @@ class stock_move(osv.osv):
'product_uos': uos_id,
'product_qty': 1.00,
'product_uos_qty' : self.pool.get('stock.move').onchange_quantity(cr, uid, ids, prod_id, 1.00, product.uom_id.id, uos_id)['value']['product_uos_qty'],
'lot_id' : False,
}
if not ids:
result['name'] = product.partner_ref
@ -2508,12 +2515,12 @@ class stock_inventory_line(osv.osv):
@return: Dictionary of changed values
"""
if not product:
return {'value': {'product_qty': 0.0, 'product_uom': False, 'prod_lot_id': False}}
return {'value': {'product_qty': 0.0, 'product_uom': False}}
obj_product = self.pool.get('product.product').browse(cr, uid, product)
uom = uom or obj_product.uom_id.id
# FP Note: read quantity on product
amount = 0
result = {'product_qty': amount, 'product_uom': uom, 'prod_lot_id': False}
result = {'product_qty': amount, 'product_uom': uom}
return {'value': result}

View File

@ -53,14 +53,6 @@
<!-- Resource: stock.inventory.line -->
<record id="stock_inventory_line_0" model="stock.inventory.line">
<field name="product_id" ref="product.product_product_3"/>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="inventory_id" ref="stock_inventory_0"/>
<field name="product_qty">14.0</field>
<field name="location_id" ref="stock_location_14"/>
</record>
<record id="stock_inventory_line_1" model="stock.inventory.line">
<field name="product_id" ref="product.product_product_24"/>
<field name="product_uom" ref="product.product_uom_unit"/>

View File

@ -80,7 +80,7 @@
picking_id: outgoing_shipment
product_id: product_icecream
product_uom: product.product_uom_kgm
product_qty: 130.0
product_uom_qty: 130.0
location_id: location_refrigerator
location_dest_id: location_delivery_counter
-
@ -94,6 +94,6 @@
picking_id: incomming_shipment
product_id: product_icecream
product_uom: product.product_uom_kgm
product_qty: 50.0
product_uom_qty: 50.0
location_id: location_convenience_shop
location_dest_id: location_refrigerator

View File

@ -42,7 +42,7 @@
<field name="arch" type="xml">
<tree string="Stock Inventory Lines">
<field name="product_id"/>
<field name="product_qty"/>
<field name="product_uom_qty"/>
<field name="product_uom" groups="product.group_uom"/>
<field name="location_id" groups="stock.group_locations"/>
</tree>
@ -55,7 +55,7 @@
<form string="Stock Inventory Lines" version="7.0">
<group col="4">
<field context="{'location':location_id, 'uom':product_uom, 'to_date':parent.date}" name="product_id" on_change="on_change_product_id(location_id,product_id,product_uom,parent.date)" domain="[('type','&lt;&gt;','service')]"/>
<field name="product_qty"/>
<field name="product_uom_qty"/>
<field name="product_uom" groups="product.group_uom"/>
<field domain="[('usage','=','internal')]" name="location_id"/>
<button name="%(stock.action_view_stock_inventory_line_split)d"
@ -125,7 +125,7 @@
<field name="inventory_line_id">
<tree string="Products" editable="bottom">
<field domain="[('usage','=','internal')]" name="location_id" groups="stock.group_locations"/>
<field context="{'location':location_id, 'uom':product_uom, 'to_date':parent.date}" name="product_id" on_change="on_change_product_id(location_id,product_id,product_uom,parent.date)" domain="[('type','&lt;&gt;','service')]"/>
<field context="{'location':location_id, 'uom':product_uom, 'to_date':parent.date}" name="product_id" on_change="on_change_product_id(location_id,product_id,product_uom,parent.date)" domain="[('type','=','product')]"/>
<field name="product_qty"/>
<field name="product_uom" groups="product.group_uom"/>
<field name="state" invisible="True"/>
@ -151,7 +151,7 @@
<field name="move_ids" context="{'inventory_id':active_id}" >
<tree string="Stock Moves">
<field name="product_id"/>
<field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)"/>
<field name="product_uom_qty" on_change="onchange_quantity(product_id, product_uom_qty, product_uom, product_uos)"/>
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
<field name="quant_ids"/>
<field name="location_id" groups="stock.group_locations"/>
@ -297,7 +297,7 @@
<field name="arch" type="xml">
<tree colors="grey:state == 'cancel'" string="Moves" create="false">
<field name="product_id"/>
<field name="product_qty"/>
<field name="product_uom_qty"/>
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
<field name="product_packaging" domain="[('product_id','=',product_id)]" groups="product.group_stock_packaging"/>
<field name="picking_id"/>
@ -317,7 +317,7 @@
<field name="arch" type="xml">
<tree colors="grey:state == 'cancel'" string="Moves" create="false">
<field name="product_id"/>
<field name="product_qty"/>
<field name="product_uom_qty"/>
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
<field name="product_packaging" domain="[('product_id','=',product_id)]" groups="product.group_stock_packaging"/>
<field name="picking_id"/>
@ -962,7 +962,7 @@
<field name="type" on_change="onchange_move_type(type)"/>
<field name="create_date" invisible="1" groups="base.group_no_one"/>
<field name="product_id" on_change="onchange_product_id(product_id,location_id,location_dest_id, False)"/>
<field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)"/>
<field name="product_uom_qty" on_change="onchange_quantity(product_id, product_uom_qty, product_uom, product_uos)"/>
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
<field name="product_uos" groups="product.group_uos"/>
<button name="%(stock.move_scrap)d"
@ -986,7 +986,7 @@
<field name="arch" type="xml">
<tree colors="grey:scrapped == True" string="Stock Moves">
<field name="product_id"/>
<field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)"/>
<field name="product_uom_qty" on_change="onchange_quantity(product_id, product_uom_qty, product_uom, product_uos)"/>
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
<field name="product_uos" groups="product.group_uos"/>
<field name="location_id" groups="stock.group_locations" invisible="1"/>
@ -1023,10 +1023,10 @@
<group>
<group name="main_grp" string="Details">
<field name="product_id" on_change="onchange_product_id(product_id,location_id,location_dest_id, False)"/>
<label for="product_qty"/>
<label for="product_uom_qty"/>
<div>
<field name="product_qty"
on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)"
<field name="product_uom_qty"
on_change="onchange_quantity(product_id, product_uom_qty, product_uom, product_uos)"
class="oe_inline"/>
<field name="product_uom" groups="product.group_uom" class="oe_inline"/>
<button name="%(stock.move_scrap)d"
@ -1081,9 +1081,9 @@
<field name="name" invisible="1"/>
<field name="product_id" on_change="onchange_product_id(product_id,location_id,location_dest_id, parent.partner_id)"/>
<field name="type" invisible="1"/>
<label for="product_qty"/>
<label for="product_uom_qty"/>
<div>
<field name="product_qty" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)" class="oe_inline"/>
<field name="product_uom_qty" on_change="onchange_quantity(product_id, product_uom_qty, product_uom, product_uos)" class="oe_inline"/>
<field name="product_uom" string="Unit Of Measure" groups="product.group_uom" class="oe_inline"/>
<button name="%(stock.move_scrap)d"
string="Scrap" type="action"
@ -1094,7 +1094,7 @@
<label for="product_uos_qty" groups="product.group_uos"/>
<div groups="product.group_uos">
<field name="product_uos_qty" on_change="onchange_uos_quantity(product_id, product_uos_qty, product_uos, product_uom)" class="oe_inline"/>
<field name="product_uos" on_change="onchange_quantity(product_id, product_qty, product_uom, product_uos)" class="oe_inline"/>
<field name="product_uos" on_change="onchange_quantity(product_id, product_uom_qty, product_uom, product_uos)" class="oe_inline"/>
</div>
<field name="product_packaging" groups="product.group_stock_packaging" domain="[('product_id','=',product_id)]"/>
<field name="partner_id"/>
@ -1195,7 +1195,7 @@
<field name="origin"/>
<field name="partner_id" string="Supplier"/>
<field name="product_id"/>
<field name="product_qty"/>
<field name="product_uom_qty"/>
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
<field name="location_id" invisible="1"/>
<field name="location_dest_id" invisible="1"/>
@ -1225,7 +1225,7 @@
<tree string="Moves">
<field name="picking_id" string="Reference"/>
<field name="product_id"/>
<field name="product_qty"/>
<field name="product_uom_qty"/>
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
<field name="date" groups="base.group_no_one"/>
</tree>

View File

@ -106,10 +106,9 @@ class stock_fill_inventory(osv.osv_memory):
prod_id = move.product_id.id
if move.location_dest_id.id != move.location_id.id:
if move.location_dest_id.id == location:
qty = uom_obj._compute_qty(cr, uid, move.product_uom.id,move.product_qty, move.product_id.uom_id.id)
qty = move.product_qty
else:
qty = -uom_obj._compute_qty(cr, uid, move.product_uom.id,move.product_qty, move.product_id.uom_id.id)
qty = -move.product_qty
if datas.get((prod_id, lot_id)):
qty += datas[(prod_id, lot_id)]['product_qty']

View File

@ -71,9 +71,9 @@ class stock_return_picking(osv.osv_memory):
res.update({'invoice_state': '2binvoiced'})
else:
res.update({'invoice_state': 'none'})
return_history = self.get_return_history(cr, uid, record_id, context)
return_history = self.get_return_history(cr, uid, record_id, context)
for line in pick.move_lines:
qty = line.product_qty - return_history.get(line.id, 0)
qty = line.product_uom_qty - return_history.get(line.id, 0)
if qty > 0:
result1.append({'product_id': line.product_id.id, 'quantity': qty,'move_id':line.id, 'lot_id': line.lot_id and line.lot_id.id or False})
if 'product_return_moves' in fields:
@ -101,7 +101,7 @@ class stock_return_picking(osv.osv_memory):
valid_lines = 0
return_history = self.get_return_history(cr, uid, record_id, context)
for m in pick.move_lines:
if m.state == 'done' and m.product_qty * m.product_uom.factor > return_history.get(m.id, 0):
if m.state == 'done' and m.product_uom_qty * m.product_uom.factor > return_history.get(m.id, 0):
valid_lines += 1
if not valid_lines:
raise osv.except_osv(_('Warning!'), _("No products to return (only lines in Done state and not fully returned yet can be returned)!"))
@ -130,7 +130,7 @@ class stock_return_picking(osv.osv_memory):
# (src location, dest location) <=> (dest location, src location))
if rec.location_dest_id.id == m.location_id.id \
and rec.location_id.id == m.location_dest_id.id:
return_history[m.id] += (rec.product_qty * rec.product_uom.factor)
return_history[m.id] += (rec.product_uom_qty * rec.product_uom.factor)
return return_history
def create_returns(self, cr, uid, ids, context=None):
@ -185,9 +185,9 @@ class stock_return_picking(osv.osv_memory):
new_qty = data_get.quantity
move = move_obj.browse(cr, uid, mov_id, context=context)
new_location = move.location_dest_id.id
returned_qty = move.product_qty
returned_qty = move.product_uom_qty
for rec in move.move_history_ids2:
returned_qty -= rec.product_qty
returned_qty -= rec.product_uom_qty
if returned_qty != new_qty:
set_invoice_state_to_none = False

View File

@ -44,31 +44,31 @@ class stock_split_into(osv.osv_memory):
inventory_obj = self.pool.get('stock.inventory')
quantity = self.browse(cr, uid, data[0], context=context).quantity or 0.0
for move in move_obj.browse(cr, uid, rec_id, context=context):
quantity_rest = move.product_qty - quantity
quantity_rest = move.product_uom_qty - quantity
#if move.tracking_id :
# raise osv.except_osv(_('Error!'), _('The current move line is already assigned to a pack, please remove it first if you really want to change it ' \
# 'for this product: "%s" (id: %d)') % \
# (move.product_id.name, move.product_id.id,))
if quantity > move.product_qty:
if quantity > move.product_uom_qty:
raise osv.except_osv(_('Error!'), _('Total quantity after split exceeds the quantity to split ' \
'for this product: "%s" (id: %d).') % \
(move.product_id.name, move.product_id.id,))
if quantity > 0:
move_obj.setlast_tracking(cr, uid, [move.id], context=context)
move_obj.write(cr, uid, [move.id], {
'product_qty': quantity,
'product_uom_qty': quantity,
'product_uos_qty': quantity,
'product_uos': move.product_uom.id,
})
if quantity_rest>0:
quantity_rest = move.product_qty - quantity
quantity_rest = move.product_uom_qty - quantity
tracking_id = track_obj.create(cr, uid, {}, context=context)
if quantity == 0.0:
move_obj.write(cr, uid, [move.id], {'tracking_id': tracking_id}, context=context)
else:
default_val = {
'product_qty': quantity_rest,
'product_uom_qty': quantity_rest,
'product_uos_qty': quantity_rest,
'tracking_id': tracking_id,
'state': move.state,

View File

@ -11,7 +11,7 @@
- company_id: base.main_company
location_id: stock.stock_location_stock
product_id: product.product_product_3
product_qty: 3.0
product_uom_qty: 3.0
product_uom: product.product_uom_unit
location_dest_id: stock.stock_location_customers
move_type: direct

View File

@ -67,7 +67,7 @@
location_id: stock.stock_location_suppliers
name: 'HP CD writers'
product_id: product_product_hpcdwriters01
product_qty: 6.0
product_uom_qty: 6.0
product_uom: product.product_uom_unit
product_uos_qty: 6.0
name: Pushed Flow Test

View File

@ -25,13 +25,8 @@ from openerp.tools.translate import _
class sale_order(osv.osv):
_inherit = "sale.order"
def action_ship_create(self, cr, uid, ids, context=None):
print "acitonshipcreate"
for order in self.browse(cr, uid, ids, context=context):

View File

@ -102,21 +102,21 @@
name: Tea
product_efficiency: 1.0
product_id: product_product_tea0
product_qty: 200.0
product_uom_qty: 200.0
product_uom: product.product_uom_gram
type: normal
- company_id: base.main_company
name: Sugar
product_efficiency: 1.0
product_id: product_product_sugar0
product_qty: 200.0
product_uom_qty: 200.0
product_uom: product.product_uom_gram
type: normal
- company_id: base.main_company
name: Water
product_efficiency: 1.0
product_id: product_product_milk0
product_qty: 0.5
product_uom_qty: 0.5
product_uom: product.product_uom_litre
type: normal
-
@ -124,7 +124,7 @@
-
!record {model: mrp.production, id: mrp_production_mo0}:
product_id: product_product_cupoftea0
product_qty: 5.0
product_uom_qty: 5.0
product_uom: product.product_uom_litre
product_uos_qty: 0.0
bom_id: mrp_bom_cupoftea0