Hi, I am working on a module and it requires to update the product stock on clicking a button which calls a function for making picking from the form. I want to know a simple code for updating the stock table directly from the user input values.
Here's the code: from osv import osv, fields import time from datetime import datetime import pooler import decimal_precision as dp
class mass_return(osv.osv):
    _name   =    'mass.return'
    _description    =   'Mass Return of products'
    _inherit    =    'product.template'
    def _line_total_amount(self, cr, uid, ids, field_name, arg,context):
        res={}
        for line in self.browse(cr,uid,ids): 
            res[line.id] = line.unit_sale_price*line.product_uom_qty
        return res
def address_get(self, cr, uid, ids):
    address_obj = self.pool.get('res.partner.address')
    address_ids = address_obj.search(cr, uid, [('partner_id', 'in', ids)])
    res = list((addr['id']) for addr in address_ids)
    adr = dict(res)
    # get the id of the (first) default address if there is one,
    # otherwise get the id of the first address in the list
    if res:
        default_address = adr.get('default', res[0][1])
    else:
        default_address = False
    result = {}
    return result
def onchange_partner_id(self, cr, uid, ids, part):
    if not part:
        return {'value': {'partner_address':False}}
    addr = self.pool.get('res.partner').address_get(cr, uid, [part], ['contact'])
    part = self.pool.get('res.partner').browse(cr, uid, part)
    pricelist = part.property_product_pricelist and part.property_product_pricelist.id or False
    val = {
         'partner_address': addr['contact'],
         }
    if pricelist:
        val['pricelist_id'] = pricelist
    return {'value': val}
def onchange_pricelist_id(self, cr, uid, ids, pricelist_id, return_lines, context={}):
    if (not pricelist_id) or (not return_lines):
        return {}
    warning = {
        'title': _('Pricelist Warning!'),
        'message' : _('If you change the pricelist of this order (and eventually the currency), prices of existing order lines will not be updated.')
    }
    return {'warning': warning}
def _product_lst_price(self, cr, uid, ids):
res = {}
product_uom_obj = self.pool.get('product.uom')
for id in ids:
res.setdefault(id, 0.0)
for product in self.browse(cr, uid, ids, context=context):
if 'uom' in context:
uom = product.uos_id or product.uom_id
res[product.id] = product_uom_obj._compute_price(cr, uid,
uom.id, product.list_price, context['uom'])
else:
res[product.id] = product.list_price
res[product.id] = (res[product.id] or 0.0) * (product.price_margin or 1.0) + product.price_extra
return res
def _compute_price(self, cr, uid, from_uom_id, price, to_uom_id=False):
    if not from_uom_id or not price or not to_uom_id:
        return price
    uoms = self.browse(cr, uid, [from_uom_id, to_uom_id])
    if uoms[0].id == from_uom_id:
        from_unit, to_unit = uoms[0], uoms[-1]
    else:
        from_unit, to_unit = uoms[-1], uoms[0]
    if from_unit.category_id.id <> to_unit.category_id.id:
        return price
    amount = price * from_unit.factor
    if to_uom_id:
        amount = amount / to_unit.factor
    return amount
def price_get(self, cr, uid, ids,product_id,context=None):
    if context is None:
        context = {}
    pricetype_obj = self.pool.get('product.price.type')
    price_type_id = pricetype_obj.search(cr, uid, [('field','=',ptype)])[0]
    res = {}
    product_uom_obj = self.pool.get('product.uom')
    for product in self.browse(cr, uid, ids, context=context):
        res[product.id] = product[ptype] or 0.0
        if ptype == 'list_price':
            res[product.id] = (res[product.id] * (product.price_margin or 1.0)) + \
                    product.price_extra
        if 'uom' in context:
            uom = product.uom_id or product.uos_id
            res[product.id] = product_uom_obj._compute_price(cr, uid,
                    uom.id, res[product.id], context['uom'])
        # Convert from price_type currency to asked one
        if 'currency_id' in context:
            # Take the price_type currency from the product field
            # This is right cause a field cannot be in more than one currency
            res[product.id] = self.pool.get('res.currency').compute(cr, uid, price_type_currency_id,
                context['currency_id'], res[product.id],context=context)
    return res
def _get_returns(self, cr, uid, ids, context=None):
    result = {}
    for line in self.pool.get('mass.return.line').browse(cr, uid, ids, context=context):
        result[line.return_id.id] = True
    return result.keys()
def product_id_change(self,cr,uid,ids,prod):
    if not prod:
        return{'value':{'unit_sale_price':False,'product_uom':False}}
    price_unit=self.pool.get('product.product').price_get(cr,uid,[prod],['list_price'])
    prod=self.pool.get('product.product').browse(cr,uid,prod)
    product_uom_=self.pool.get('product.product').browse(cr,uid,prod)
    val = {
            'unit_sale_price':price_unit['list_price'],
            'product_uom':product_uom_['name']
          }
    return {'value':val}
def _get_uom_id(self, cr, uid, *args):
    try:
        proxy = self.pool.get('ir.model.data')
        result = proxy.get_object_reference(cr, uid, 'product', 'product_uom_unit')
        return result[1]
    except Exception, ex:
        return False
def product_id_change(self, cr, uid, ids, pricelist, product, qty=0,uom=False, partner_id=False,flag=False, context=None):
context = context or {}
if not partner_id:
raise osv.except_osv(_('No Customer Defined !'), _('You have to select a customer in the form !\nPlease set one customer before choosing a product.'))
warning={}
product_uom_obj = self.pool.get('product.uom')
partner_obj = self.pool.get('res.partner')
product_obj = self.pool.get('product.product')
context_partner={'partner_id':partner_id}
if not product:
return {'domain':{'product_uom': []}}
uom2 = False
if uom:
uom2 = product_uom_obj.browse(cr, uid, uom)
if product_obj.uom_id.category_id.id != uom2.category_id.id:
uom = False
if not flag:
result['name'] = self.pool.get('product.product').name_get(cr, uid, [product_obj.id], context=context_partner_id)[0][1]
domain = {}
if not pricelist:
warn_msg = _('You have to select a pricelist or a customer in the sales form !\n'
'Please set one before choosing a product.')
warning_msgs += _("No Pricelist ! : ") + warn_msg +"\n\n"
else:
price = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist],
product, qty or 1.0, partner_id, {
'uom': uom or result.get('product_uom'),
'date': date_order,
})[pricelist]
if price is False:
warn_msg = _("Couldn't find a pricelist line matching this product and quantity.\n"
"You have to change either the product, the quantity or the pricelist.")
##
warning_msgs += _("No valid pricelist line found ! :") + warn_msg +"\n\n"
else:
result.update({'price_unit': price})
if warning_msgs:
warning = {
'title': _('Configuration Error !'),
'message' : warning_msgs
}
return {'value': result, 'domain': domain, 'warning': warning}
_columns    ={
'return_id':fields.integer('Return ID', readonly=True),
    'name':fields.char('Reason', size=128),
            'description': fields.text('Description'),
            'number': fields.char('Number', size=128, help="Company internal claim unique number"),
    'partner_id':fields.many2one('res.partner', 'Partner'),
            'partner_address': fields.many2one('res.partner.address', 'Partner Contact', \
                             domain="[('partner_id','=',partner_id)]"
                             ),
            'partner_phone': fields.char('Phone', size=64),
            'origin': fields.selection([('none','Not specified'),
                                ('legal','Legal retractation'),
                                ('cancellation','Order cancellation'),
                                ('damaged','Damaged delivered product'),                                    
                                ('error','Shipping error'),
                                ('exchange','Exchange request'),
                                ('lost','Lost during transport'),
                                ('other','Other')], 'Return Subject', help="To describe the line product problem"),
    'active': fields.boolean('Active'),
    'cause': fields.text('Root Cause'),
            'return_date':fields.datetime('Date'),
            'prodlot_id': fields.many2one('stock.production.lot', 'Lot',help="The serial/lot of the returned product"),
            'company_id': fields.many2one('res.company', 'Company'),
    'product_id':fields.many2one('product.product', 'Product',help="Returned product"),
            'product_uom_qty': fields.float('Quantity (UoM)', digits_compute= dp.get_precision('Product UoS')),
            'product_uom': fields.many2one('product.uom', 'Unit of Measure '),
            'pricelist_id': fields.many2one('product.pricelist', 'Pricelist',help="Pricelist for current sales order."),
            'unit_sale_price' :fields.float('Unit Price', digits_compute= dp.get_precision('Sale Price'),help="Unit sale price of the product."),
            'subtotal':fields.function(_line_total_amount, string='Subtotal', type="float",digits_compute= dp.get_precision('Account'), store=True),
            'return_location' : fields.many2one('stock.location', 'Dest. Location',help="Location where the system will stock the returned products.", select=True),
            'invoice_line_id': fields.many2one('account.invoice.line', 'Invoice Line', help='The invoice line related to the returned product'),
            }
_defaults={
            'number': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'mass.return'),
            }
def cancel(self, cr, uid, ids, context=None):
    if context is None:
        context = {}
    data = context and context.get('active_ids', []) or []
    return self.pool.get('mass.return').mass_return_cancel(cr, uid, data, context)
def button_compute(self, cr, uid, ids, context=None, set_total=False):
    for line in self.browse(cr, uid, ids, context=context):
        if set_total:
            self.pool.get('mass.return').write(cr, uid, [line.id], {'subtotal': line.subtotal})
    return True
def button_confirm(self, cr, uid, ids, context=None):
    return self.write(cr, uid, ids, {'state': 'confirmed'})
##class make_picking(osv.osv): ##
_name= 'make.picking'
_columns={
'return_location' : fields.many2one('stock.location', 'Source Location',help="Location where the returned products are sent.", required=True),
'return_ids' : fields.many2many('mass.return', 'return_picking', 'return_picking_id', 'Return lines'),
}
def action_make_picking(self,cr,uid,ids,context=None):
    print "context", context
    partner_id = 0
    for picking in self.browse(cr, uid,ids):
        return_id = self.pool.get('mass.return').browse(cr, uid, context['active_id'])
        partner_id = return_id.partner_id.id
        # location type
        location = -1
        if return_id.return_type == "customer":
            location = return_id.partner_id.property_stock_customer.id
        else:
            location = return_id.partner_id.property_stock_supplier.id
        # create picking
        picking_id = self.pool.get('stock.picking').create(cr, uid, {
                    'origin': return_id.id,
                    'type': 'in',
                    'move_type': 'one', # direct
                    'date': time.strftime('%Y-%m-%d %H:%M:%S'),
                    'address_id': return_id.partner_address_id.id,
                    'location_dest_id': picking.return_location.id,
                    'return_id': return_id.id,
                })
        # Create picking lines
        for picking_line in picking.return_id:
            move_id = self.pool.get('stock.move').create(cr, uid, {
                    'name' : picking_line.product_id.name_template, # Motif : crm id ? stock_picking_id ?
                    'priority': '0',
           #'create_date':
                    'date': time.strftime('%Y-%m-%d %H:%M:%S'),
                    'product_id': picking_line.product_id.id,
                    'quantity': picking_line.product_uom_qty,
                    'product_uom': picking_line.product_id.uom_id.id,
                    'address_id': return_id.partner_address_id.id,
           # 'price_currency_id': return_id.company_id.currency_id.id, # from invoice ???
                    'location_dest_id': picking.return_location.id,
                })
            return {
        'name': 'Customer Picking IN',
        'view_type': 'form',
        'view_mode': 'tree,form',
        'view_xml_id': 'mass_return_picking_in_form',
        'view_name' :'mass_return_picking_in_form',
        'domain' : "[('type', '=', 'in'),('partner_id','=',%s)]"%partner_id,
        'res_model': 'stock.picking',
        'type': 'ir.actions.act_window',
    }
def button_return(self, cr, uid, ids, context=None):
    if context is None:
        context = {}
    data = context and context.get('active_ids', []) or []
    return self.pool.get('mass.return').action_make_picking(cr, uid, data, context)
def _get_dest_loc(self, cr, uid,context):
    return self.pool.get('stock.warehouse').read(cr, uid, [1],['lot_input_id'])[0]['lot_input_id'][0]  
_defaults = {
    'return_location' : _get_dest_loc,
}
# If "Cancel" button pressed
def action_cancel(self,cr,uid,ids,conect=None):
    return {'type': 'ir.actions.act_window_close',}
mass_return()
XML:
<openerp>
    <data>
        
        <record model="ir.ui.view" id="mass_return_tree">
            <field name="name">Mass Return Tree</field>
            <field name="model">mass.return</field>
            <field name="type">tree</field>
            <field name="arch" type="xml">
                <tree string="Returned lines">
                    <field name="name"/>
                    <field name="partner_id"/>
                    <field name="return_date"/>
                </tree>
            </field>
        </record>
        
        <record model="ir.ui.view" id="mass_return_form_view">
            <field name="name">Mass Return Form</field>
            <field name="model">mass.return</field>
            <field name="type">form</field>
            <field name="arch" type="xml">
                <form string="Mass Returns">
                    <field name="name"/>
                    <field name="return_date"/>
                    <field name="origin"/>
                    <field name="number"/>
                    <group name="Partner" colspan="4" col="3">
                        <separator name="Partner" colspan="4"/>
                            <field name="partner_id" on_change="onchange_partner_id(partner_id)"/>
                            <field name="partner_address"/>
                            <field name="partner_phone"/>
                    </group>
                    <group name="Return Product" colspan="4" col="4">
                        <separator name="Return Product" colspan="8"/>
                        <field name="product_id" on_change="product_id_change(product_id,product_uom_qty,parent.partner_id,unit_sale_price,context)"/>
                        <field name="product_uom_qty"/>
                        <field name="product_uom"/>
                        <field name="unit_sale_price"/>
                        <field name="subtotal"/>
                        <field name="return_location"/> 
                    </group>
                <group col="4" colspan="4">
                <separator colspan="4"/>
                <button name="button_compute" string="Compute" icon="gtk-execute" type="object"/>
                <button name="case_cancel" string="Cancel" special="cancel" type="object" icon="gtk-cancel" />
                <button name="button_return" string="Return"  type="object" icon="gtk-ok" />
                <button name="refund" string="Refund"  type="object" icon="gtk-ok" />
                </group>
            </form>
        </field>
    </record>
    <!-- <record model="ir.ui.view" id="make_picking_form_view">
        <field name="name">Mass Return Picking Form</field>
        <field name="model">make.picking</field>
        <field name="type">form</field>
        <field name="arch" type="xml">
            <form string="Picking"> 
                <field name="return_location"/>
                <button name="action_make_picking" string="OK" type="object" icon="gtk_ok"/>
                <button name="action_cancel" string="Cancel" type="object" icon="gtk_cancel"/>
            </form>
        </field>
    </record>
    <record model="ir.actions.act_window" id="action_make_picking_form">
        <field name="name">Make Picking</field>
        <field name="res_model">make.picking</field>
    </record> -->
    <record model="ir.actions.act_window" id="action_mass_return_form">
        <field name="name">Mass Returns</field>
        <field name="res_model">mass.return</field>
    </record>
    <record id="action_return_cancel" model="ir.actions.act_window">
        <field name="name">Cancel Return</field>
        <field name="res_model">mass.return</field>
        <field name="view_type">form</field>
        <field name="view_mode">form</field>
        <field name="target">new</field>
    </record>
    <menuitem name="Mass Return" id="menu_mass_return" parent="base.menu_aftersale" sequence="3" action="action_mass_return_form" />
</data>
</openerp>
