OpenERP fields.related crashing - odoo

Followup question from openerp override onchange behavior without affecting base
15244031
The following code does get fired but I get server error 500 when any of the related fields has a value.
When I look at the log, it says JSON serialization issue.
TypeError: browse_record(product.mycount, 1) is not JSON serializable
Please suggest a solution.
class purchase_order_line_custom(osv.osv):
_name = 'purchase.order.line'
_inherit = 'purchase.order.line'
def onchange_product_id(self, cr, uid, ids, pricelist_id, product_id, qty, uom_id, partner_id, date_order=False, fiscal_position_id=False, date_planned=False, name=False, price_unit=False, context=None):
values = super(purchase_order_line_custom, self).onchange_product_id(cr, uid, ids, pricelist_id, product_id, qty, uom_id, partner_id, date_order, fiscal_position_id, date_planned,name, price_unit, context=context)
if product_id:
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
values['value'].update({
'qualified_name':product.qualified_name,
'product_type' : product.product_type or None,
'product_subtype' : product.product_subtype,
'count_id':product.count_id or None
})
return values
_columns={
'product_type': fields.related('product_id','product_type',type='selection', string='Product Type', selection=[('X','X'),('Y','Y'),('Z','Z')]),
'product_subtype': fields.related('product_id','product_subtype',type='char', size=64, string='Sub-Type'),
'qualified_name': fields.related('product_id','qualified_name',type='char', size=64, string='Qualified Name'),
'count_id': fields.related('product_id','count_id',type='many2one',relation='product.mycount',string='Count')
}
purchase_order_line_custom()

in the line 'count_id':product.count_id or None, I think count_id is a many2one field in product.you are trying to pass object to the count_id field in product.order.line, you need to pass product.count_id.id to get the id.

Related

Odoo validate invoice from code

I creating an invoice from another model, and want to get validated not draft
But internal number and total are not generated with my code.
invoice_id = self.pool.get('account.invoice').create(cr, uid,{
'partner_id':self.supplier.id,
'name' : 'Faltante mercaderia',
'journal_id': journal_id,
'account_id':account_id,
'type': 'in_refund',
})
self.pool.get('account.invoice.line').create(cr, uid,{
'invoice_id' : invoice_id,
'name' : 'Faltante mercaderia %s: %s' %(self.type,self.number),
'quantity' : self.dif_final,
'price_unit':self.tarifa_dif / 1000,
})
a = self.env['account.invoice'].browse([invoice_id])
a.invoice_validate()
I also try adding a.action_number()
This code should work for you:
inv_obj = self.pool.get('account.invoice')
inv_obj.button_compute(cr, uid, [invoice_id], context=context, set_total=True)
inv_obj.action_date_assign(cr, uid, invoice_id, context=context)
inv_obj.action_move_create(cr, uid, invoice_id, context=context)
inv_obj.action_number(cr, uid, invoice_id, context=context)
inv_obj.invoice_validate(cr, uid, invoice_id, context=context)
You can check by calling all above methods and let me know.
validate button sends a signal to a workflow, you just need to send the same signal:
a.signal_workflow('invoice_open')

Openerp - AttributeError in function of stock.picking.in

Really struggling with this one:
I have inherited from stock.picking.in and have added a few columns. I then added a function field.
In the function that the function field refers to, it works if I do not use any attribute from the stock.picking.in object. The moment I use any value from the object, it starts giving 'AttributeError: ' and some attribute at random. It doesn't specify any other reasons or causes.
Code:
class stock_picking_custom(osv.osv):
_name = 'stock.picking.in'
_inherit = 'stock.picking.in'
_table = "stock_picking"
def calc_royalty(self, cr, uid, ids, field_name, arg, context=None):
if not ids: return {}
res = {}
for line in self.browse(cr, uid, ids, context=context):
res[line.id] = 0 #line.royalty_rate * line.loading_netweight
return res
_columns = {
'loading_netweight': fields.float('Net weight at loading', digits=(16,2), help="Net weight at loading (interior weight)"),
'royalty_date': fields.date('Royalty Issue date'),
'royalty_number' : fields.char('Royalty Number', size=64),
'royalty_rate' : fields.float('Royalty Rate (p. ton)', digits=(16,2)),
'royalty_amount' : fields.function(calc_royalty, type='float', digits=(16,2), string='Royalty Amount', store=True, select=True)
}
stock_picking_custom()
I have commented out the line that I want to use. The moment I put this line back in the code, it would give attribute error on royalty_date (for example) which is not even mentioned in the function.
Please guide.
EDIT: I tried the exact same code with purchase.order and it works perfectly. What is different about stock.picking.in?
Thanks
Ok, found the answer in stock module in delivery addon. So this is a framework limitation issue related to inheritance order etc.
Sharing here in case someone ends up in a similar situation.
To solve, I repeated the same fields in stock.picking and stock.picking.in. Then I called the calc function of the picking class from the picking.in class.
Code:
class stock_picking_custom(osv.osv):
_name = 'stock.picking'
_inherit = 'stock.picking'
def calc_royalty(self, cr, uid, ids, field_name, arg, context=None):
if not ids: return {}
res = {}
for line in self.browse(cr, uid, ids, context=context):
res[line.id] = line.royalty_rate * line.loading_netweight
return res
_columns = {
'loading_netweight': fields.float('Net weight at loading', digits=(16,2), help="Net weight at loading (interior weight)"),
'royalty_date': fields.date('Royalty Issue date'),
'royalty_number' : fields.char('Royalty Number', size=64),
'royalty_rate' : fields.float('Royalty Rate (p. ton)', digits=(16,2)),
'royalty_amount' : fields.function(calc_royalty, type='float', digits=(16,2), string='Royalty Amount', store=True, select=True)
}
stock_picking_custom()
class stock_picking_in_custom(osv.osv):
_name = 'stock.picking.in'
_inherit = 'stock.picking.in'
_table = "stock_picking"
def calc_royalty(self, cr, uid, ids, field_name, arg, context=None):
return self.pool.get('stock.picking').calc_royalty(cr,uid,ids,field_name,arg,context=context)
_columns = {
'loading_netweight': fields.float('Net weight at loading', digits=(16,2), help="Net weight at loading (interior weight)"),
'royalty_date': fields.date('Royalty Issue date'),
'royalty_number' : fields.char('Royalty Number', size=64),
'royalty_rate' : fields.float('Royalty Rate (p. ton)', digits=(16,2)),
'royalty_amount' : fields.function(calc_royalty, type='float', digits=(16,2), string='Royalty Amount', store=True, select=True)
}
stock_picking_in_custom()
I did not get much time to spend on it but I came to know that line is coming with stock.picking.in object and fields, you defined, are stored in stock_picking table that's why it may going to search that field with stock.picking.in, not getting and error is coming.
There may be issue with fields defined in object and table, but not sure.

openerp override onchange behavior without affecting base

I have inherited from purchase.order.line. I have added a bunch of related fields. They are all related to fields in product.product via product_id in order_line.
What I want to achieve is that when a user selects or changes a product in the purchase order line form, the related fields should get refreshed/updated/populated with values of the selected product.
I have written the onchange method for this but I'm not sure how to invoke it from the inherited view? The product_id field was already there in the (parent) order_line view and it already has an onchange defined. How do I get the system to use my onchange as well?
I don't want to disturb the onchange_productid method that is already there in purchase.order.line. So either before my onchange or after it, it should continue with its standard functioning.
Thanks
EDIT: latest version (getting errors when any of the related many2one or selection fields has a value).
class purchase_order_line_custom(osv.osv):
_name = 'purchase.order.line'
_inherit = 'purchase.order.line'
def onchange_product_id(self, cr, uid, ids, pricelist_id, product_id, qty, uom_id, partner_id, date_order=False, fiscal_position_id=False, date_planned=False, name=False, price_unit=False, context=None):
values = super(purchase_order_line_custom, self).onchange_product_id(cr, uid, ids, pricelist_id, product_id, qty, uom_id, partner_id, date_order, fiscal_position_id, date_planned,name, price_unit, context=context)
if product_id:
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
values['value'].update({
'qualified_name':product.qualified_name,
'product_type' : product.product_type or None,
'product_subtype' : product.product_subtype,
'count_id':product.count_id or None
})
return values
_columns={
'product_type': fields.related('product_id','product_type',type='selection', string='Product Type', selection=[('X','X'),('Y','Y'),('Z','Z')]),
'product_subtype': fields.related('product_id','product_subtype',type='char', size=64, string='Sub-Type'),
'qualified_name': fields.related('product_id','qualified_name',type='char', size=64, string='Qualified Name'),
'count_id': fields.related('product_id','count_id',type='many2one',relation='product.mycount',string='Count')
}
purchase_order_line_custom()
you need to overide the onchange function(you can use super() ) for the field 'product_id' and update the result.
for example
def onchange_product(self,cr,uid,ids,product_id,context=None):
values = super(<your_class_name>,self).onchange_product(cr, uid,ids,product_id,context=context)
# values will be a dictionary containing 'value' as a key.
# You need to add all the newly added related fields and other fields to the values['value'].
# if 'aaa' is the newly added field, then values['value'].update({'aaa':<value for aaa>})
# then return values
return values
modify you onchange to the following
def onchange_product_id(self, cr, uid, ids, pricelist_id, product_id, qty, uom_id,
partner_id, date_order=False, fiscal_position_id=False, date_planned=False,
name=False, price_unit=False, context=None):
values = super(purchase_order_line_custom, self).onchange_product_id(cr, uid, ids, pricelist_id, product_id, qty, uom_id, partner_id, date_order, fiscal_position_id, date_planned,name, price_unit, context=context)
if product_id:
product = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
values['value'].update({
'product_type' : product.product_type,
'product_subtype' : product.product_subtype,
'qualified_name' : product.qualified_name,
'count_id' : product.count_id
})
return values
First let's understand why fields.related is used?
fields.related field that points to some data inside another field of the current record.
That means, fields which are related will be filled automatically when you will select the value of other field.
Example:
_columns = {
'product_id': fields.many2one('product.product', 'Product'),
'product_name': fields.related('product_id', 'name', type='char', string='Product Name'),
}
In this example product_name will be filled automatically when you will select the product_id. You don't have to write onchange for that.
You can find many examples for fields.related.

Confirm a sale quotation into a sale order with some quantities set to 0

In my custom sale quotation report I want to show some products with a 0 quantity and therefore have created sale order lines for some products with their quantities set to 0. It works fine and shows in the sale quotation report.
But when I confirm that same sale quotation into a sale order OpenERP throws the following message:
"Data Insufficient !
Please check the quantity in procurement order(s), it should not be 0 or less!"
How can I confirm an order with some quantities set to 0?
First you have to inherit the Procurement and then override the action_confirm method in your custom module.
In procurement.py, find "def action_confirm()" on line: 320. Copy and past the whole method and remove those lines which raise the exception.
Hope this will solve your problem.
Thank You.
class procurement_order(osv.osv):
_inherit = 'procurement.order'
def action_confirm(self, cr, uid, ids, context=None):
move_obj = self.pool.get('stock.move')
for procurement in self.browse(cr, uid, ids, context=context):
#if procurement.product_qty <= 0.00:
#raise osv.except_osv(_('Data Insufficient !'),_('Please check the quantity in procurement order(s), it should not be 0 or less!'))
if procurement.product_id.type in ('product', 'consu'):
if not procurement.move_id:
source = procurement.location_id.id
if procurement.procure_method == 'make_to_order':
source = procurement.product_id.product_tmpl_id.property_stock_procurement.id
id = move_obj.create(cr, uid, {
'name': procurement.name,
'location_id': source,
'location_dest_id': procurement.location_id.id,
'product_id': procurement.product_id.id,
'product_qty': procurement.product_qty,
'product_uom': procurement.product_uom.id,
'date_expected': procurement.date_planned,
'state': 'draft',
'company_id': procurement.company_id.id,
'auto_validate': True,
})
move_obj.action_confirm(cr, uid, [id], context=context)
self.write(cr, uid, [procurement.id], {'move_id': id, 'close_move': 1})
self.write(cr, uid, ids, {'state': 'confirmed', 'message': ''})
return True

How can i use onchange function to change price of account invoice line price_unit

I would like to use onchange to set account invoice price to a default price set in res.partner. Could anyone give me an example of this ?
Thanks,
Joe
There are lots of examples of onchange in addons.
For example, if you want to change the value of 'name' field and want to set product's name based on selected product:
def onchange_product_id(self, cr, uid, ids, product_id, context=None):
if product_id:
prod = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
return {'value': {'name': prod.name}}
return {}
Write this in your_invoice_view.xml:
<field name="product_id" on_change="product_id_change(product_id, parent.partner_id, context)"/>
Write onchange in your_invoice.py under "invoice_line" model(class):
def onchange_product_id_change(self, cr, uid, ids, product_id, partner_id context=None):
if product_id and partner_id:
product_brw = self.pool.get('product.product').browse(cr, uid, product_id, context=context)
partner_brw = self.pool.get('res.partner').browse(cr, uid, partner_id, context=context)
/*write your logic */
return {'value': {'price_unit': your calculated value}}
return {}