'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
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
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 = {
<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>
<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>
<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>
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:
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"
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>
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
_.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],
cols: {
product: op.product_id[1],
uom: op.product_uom ? product_uom[1] : '',
- qty: op.product_qty,
+ qty: op.product_uom_qty,
}
});
});
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
# 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'),
'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 "
'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
@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}
<!-- 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"/>
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
-
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
<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>
<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','<>','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"
<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','<>','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"/>
<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"/>
<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"/>
<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"/>
<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"
<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"/>
<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"
<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"
<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"/>
<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"/>
<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>
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']
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:
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)!"))
# (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):
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
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,
- 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
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
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):
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
-
-
!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