[IMP]product_qty -> product_uom_qty, report.stock.move not required anymore as we...
authorFabien Pinckaers <fp@tinyerp.com>
Sun, 30 Jun 2013 14:10:14 +0000 (16:10 +0200)
committerFabien Pinckaers <fp@tinyerp.com>
Sun, 30 Jun 2013 14:10:14 +0000 (16:10 +0200)
bzr revid: fp@tinyerp.com-20130630141014-evn6hj7870iphgve

19 files changed:
addons/stock/product.py
addons/stock/report/lot_move_label.xml
addons/stock/report/picking.rml
addons/stock/report/product_stock.py
addons/stock/report/report_stock_move.py
addons/stock/report/report_stock_move_view.xml
addons/stock/security/ir.model.access.csv
addons/stock/static/src/js/widgets.js
addons/stock/stock.py
addons/stock/stock_demo.xml
addons/stock/stock_demo.yml
addons/stock/stock_view.xml
addons/stock/wizard/stock_fill_inventory.py
addons/stock/wizard/stock_return_picking.py
addons/stock/wizard/stock_splitinto.py
addons/stock_invoice_directly/test/stock_invoice_directly.yml
addons/stock_location/test/stock_location_push_flow.yml
addons/stock_location_sale/stock_location_sale.py
addons/stock_no_autopicking/test/stock_no_autopicking.yml

index fec2d66..f363700 100644 (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 = {
index 62f26c0..cad14e7 100644 (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>
index c0172e2..e8e1268 100644 (file)
             <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>
index d213db6..db6ac9b 100644 (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:
index 4cb9c0f..c00031e 100644 (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"
index 4675f55..82f7a8c 100644 (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>
index e955071..9f743df 100644 (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
index e1c377d..dfa6774 100644 (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,
                     }
                 });
             });
index cb1f437..a2f01c1 100644 (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}
 
 
index b21757c..2722fd6 100644 (file)
 
         <!-- 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"/>
index 99565f0..36ffb30 100644 (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
index 175366f..f45f0b9 100644 (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"
                         <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"/>
                          <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>
index 7885982..6d3c243 100644 (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']
index cf9f023..b0b152e 100644 (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
index 76a8059..0eb0d19 100644 (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,
index 7ea2f3d..53ecee5 100644 (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
index 9e153b5..ebe0659 100644 (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
index eed8b32..366af26 100644 (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):
index ad0ad0f..ed5459e 100644 (file)
         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