field.function - KeyError: 40 - odoo

Created a column 'line_no' when i updated the value it throws the KeyError: 40
My code:
def _get_line_no(self, cr, uid, ids, line_no, arg, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
nextno =0
no = record.next_line_no
next_no = nextno + no
total =+ next_no
res={
'next_line_no':next_no,
'line_no': total
}
return res
_columns = {
'line_no':fields.function(_get_line_no,string='Line No',type='integer'),
'next_line_no':fields.integer(' Next Line No'),
}
_defaults = {
'next_line_no':1
}
Throws Error : KeyError: 40
How do i resolve?

next_line_no is a database field, So it won't effect the dynamic way.
You need to modify this way,
def _get_line_no(self, cr, uid, ids, line_no, arg, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
nextno =0
no = record.next_line_no
next_no = nextno + no
total += next_no
res[record.id]={
'next_line_no':next_no,
'line_no': total
}
return res
_columns = {
'line_no':fields.function(_get_line_no,string='Line No',type='integer', multi="lineno"),
'next_line_no': function(_get_line_no,string='Next Line No',type='integer', multi="lineno", store=True),
}
_defaults = {
'next_line_no':1
}
I hope this will yelp you.

Change the columns by,
_columns = {
'line_no':fields.function(_get_line_no,string='Line No',type='integer', multi="line"),
'next_line_no':fields.function(_get_line_no, type='integer', string='next line number' ,multi="line"),
}
and your method like,
def _get_line_no(self, cr, uid, ids, field_names, args, context=None):
res = {}
for record in self.browse(cr, uid, ids, context=context):
nextno =0
no = record.next_line_no
next_no = nextno + no
total += next_no
res[record.id]={
'next_line_no':next_no,
'line_no': total
}
return res
This will work.

Related

Calculate two fields with on function

I have this function that calculates qty_incoming, but there is an outgoing_qty field that I want to calculate with the same function and not to create separate function for its calculation. how can I do this?
_columns = {
'
'incoming_qty': fields.function(_product_inc_out_qty, type='float',
digits_compute=dp.get_precision('Product Unit of Measure'),
string='Incoming'
),
'outgoing_qty': fields.function(_product_inc_out_qty, type='float',
digits_compute=dp.get_precision('Product Unit of Measure'),
string='Outgoing'
),
}
function:
def _product_inc_out_qty(self, cr, uid, ids, field_names=None, arg=False, context=None):
if context is None:
context = {}
res = {}
for move_id in ids:
move = self.browse(cr, uid, move_id, context=context)
res[move.id] = move.product_id.incoming_qty or 0.0
return res
if I do something like this, then I get error TypeError: float() argument must be a string or a number
def _product_inc_out_qty(self, cr, uid, ids, field_names=None, arg=False, context=None):
if context is None:
context = {}
res = {}
vals = {
'outgoing_qty': 0.0,
'incoming_qty': 0.0,
}
for move_id in ids:
move = self.browse(cr, uid, move_id, context=context)
vals['outgoing_qty'] = move.product_id.qty_available or 0.0
vals['incoming_qty'] = move.product_id.incoming_qty or 0.0
res[move.id] = vals
return res
Multiple fields can be computed at the same time by the same method, just use the same method on all fields and set all of them:
discount_value = fields.Float(compute='_apply_discount')
total = fields.Float(compute='_apply_discount')
#depends('value', 'discount')
def _apply_discount(self):
for record in self:
# compute actual discount from discount percentage
discount = record.value * record.discount
record.discount_value = discount
record.total = record.value - discount
You can find an example in old api at sale_order
The problem in my code was that in old API if you want to return values for more than 1 field you need to add multi="any_string" to your field
So my fields should look like this
'incoming_qty': fields.function(_product_inc_out_qty, type='float',
digits_compute=dp.get_precision('Product Unit of Measure'),
multi='all',
string='Incoming'
),

How to use many2one field in the function in openerp

how can I use many2one field in the function?
this is my code:
def _get_unit(self, cr, uid, ids, fields,arg, context=None):
res = {}
list_data = []
for record in self.browse(cr, uid, ids,unit):
list_data.append(record[unit.id])
return super(learning_course, self)._get_unit(cr, uid, ids, context=context)
_columns = {
'unit': fields.many2one('hr.department', 'unit'),
'department': fields.function(_get_unit, string='department' , store=True ,type='many2one' ,relation='hr.department'),
}
def onchange_user(self, cr, uid, ids, user_id, context=None):
unit = False
if user_id:
unit = self.pool.get('res.users').browse(cr, uid, user_id, context=context).context_department_id.id
return {'value': {'unit' : unit }}
return {'value': {} }
but I get this error:
for record in self.browse(cr, uid, ids,unit):
AttributeError: 'browse_record_list' object has no attribute 'id'
what should I do?
def _get_unit(self, cr, uid, ids, prop, unknow_none, context=None):
res = {}
for record in self.browse(cr, uid, ids):
res [record.id] = record.user_id.context_department_id.id
return res
_columns = {
'user_id': fields.many2one('res.users', 'user', readonly=True),
'unit_id': fields.function(_get_unit, string='dep' , store=True ,type='many2one',relation='hr.department'),
}

How to display name_get() in openerp?

I have tried to display name , description fields for the many to one field. The code is as follows, help me to resolve this problem
from openerp.osv import orm, fields
class post_branch(orm.Model):
_name = "branches"
_columns = {
'name':fields.char("Name", size=50, required=True),
'description':fields.text("Description",),
'emp_id':fields.one2many("man", "branch_id", "lines")
# 'emp_id':fields.many2one("man","lines",required=True)
}
def name_get(self, cr, uid, ids, context=None):
res = []
for r in self.read(cr, uid, ids['name', 'description']):
res.append(r['id'], '%s,%s' (r['name'],r['description']))
return res
# def name_des(self, cr,uid, context=None):
# obj_name=self.pool.get('')
Try following,
def name_get(self, cr, uid, ids, context=None):
res = []
if not ids:
return res
for r in self.browse(cr, uid, ids, context=context):
name = str(r.name) + ',' + str(r.description or '')
res.append((r.id, name))
return res

indent using condition

please help me..what's wrong
def _amount_all(self, cr, uid, ids, name, args, context=None):
res = {}
for invoice in self.browse(cr, uid, ids, context=context):
res[invoice.id] = {
'amount_untaxed': 0.0,
'amount_tax': 0.0,
'amount_total': 0.0
}
for line in invoice.invoice_line:
res[invoice.id]['amount_untaxed'] += line.price_subtotal
for line in invoice.tax_line:
res[invoice.id]['amount_tax'] += line.amount
res[invoice.id]['amount_total'] = res[invoice.id]['amount_tax'] + res[invoice.id]['amount_untaxed']
cr.execute('select payment from sale_order where name = %s',(invoice.origin,))
ads = cr.fetchone()
pay = ads and ads[0] or None
if pay == 'deposit':
if invoice.partner_id.avail < 0:
raise osv.except_osv(_('Invalid action !'), _('Deposit must be recharged')
if invoice.amount_total != res[invoice.id]['amount_total']:
temp = invoice.partner_id.depot - res[invoice.id]['amount_total']
cr.execute('update res_partner set depot=%s where id = %s', (temp, invoice.partner_id.id,))
return res
I checked the condition that if he paid using a deposit and is available if less than zero if not then deposit reduction is done. I think..this is correct..but when I running, appear like this
if invoice.amount_total != res[invoice.id]['amount_total']:
SyntaxError: invalid syntax
Why have you given 2tabs(8 spaces) after the line raise osv.except_osv()
Your code should be like
def _amount_all(self, cr, uid, ids, name, args, context=None):
res = {}
for invoice in self.browse(cr, uid, ids, context=context):
res[invoice.id] = {
'amount_untaxed': 0.0,
'amount_tax': 0.0,
'amount_total': 0.0
}
for line in invoice.invoice_line:
res[invoice.id]['amount_untaxed'] += line.price_subtotal
for line in invoice.tax_line:
res[invoice.id]['amount_tax'] += line.amount
res[invoice.id]['amount_total'] = res[invoice.id]['amount_tax'] + res[invoice.id]['amount_untaxed']
cr.execute('select payment from sale_order where name = %s',(invoice.origin,))
ads = cr.fetchone()
pay = ads and ads[0] or None
if pay == 'deposit':
if invoice.partner_id.avail < 0:
raise osv.except_osv(_('Invalid action !'), _('Deposit must be recharged')
if invoice.amount_total != res[invoice.id]['amount_total']:
temp = invoice.partner_id.depot - res[invoice.id]['amount_total']
cr.execute('update res_partner set depot=%s where id = %s', (temp, invoice.partner_id.id,))
return res

take field date from another database

in ticket.py. I have two class. class deposit.line and res_partner (inherit). I want to take the date of the class deposit.line but its function in the class res_partner(inherit)
def _compute_dept2(self, cr, uid, ids, amount, arg, context=None):
result = {}
obj2 = self.pool.get('deposit.line')
for record in obj2.deposit_line:
temp1 = record.date
print temp1
print result
return result
but the results of its existing print false. what wrong ? please correct my code
PS:
My explanation is less good. but look at my code,surely knowing my explanation.
THIS MY COMPLETE CODE:
class deposit_line(osv.osv):
_name ="deposit.line"
_description = "Deposit Line"
_columns = {
'name': fields.char('Name', size=64),
'ref': fields.char('Reference', size=64),
'amount': fields.float('Amount'),
'date': fields.date('Date', required=True),
'deposit_id': fields.many2one('res.partner', 'Deposit ', required=True, ondelete='cascade'),
}
deposit_line()
class res_partner(osv.osv):
_inherit = 'res.partner'
def _compute_age(self, cr, uid, ids,date_birth,age,arg, context=None):
result = {}
for r in self.browse(cr, uid, ids, context=context):
age=0
if r.date_birth:
age = (datetime.now()-datetime.strptime(r.date_birth,"%Y-%m-%d")).days/365.25
result[r.id] = age
return result
def _compute_dept(self, cr, uid, ids, deposit, available, arg, context=None):
result = {}
for r in self.browse(cr, uid, ids, context=context):
avail=0
temp = r.available
if r.deposit:
avail = r.deposit + temp
result[r.id] = avail
return result
def _compute_dept2(self, cr, uid, ids, amount, arg, context=None):
result = {}
obj2 = self.pool.get('deposit.line')
for record in obj2.deposit_line:
temp1 = record.date
print temp1
print result
return result
_columns = {
'speaker': fields.boolean('Leader'),
'event_ids': fields.one2many('event.event','main_speaker_id', readonly=True),
'event_registration_ids': fields.one2many('event.registration','partner_id', readonly=True),
'airline': fields.boolean('Airlines'),
'hotel': fields.boolean('Hotel'),
'date_birth': fields.date('Date of Birth'),
'id_no': fields.char('ID. No', size=20),
'id_expired': fields.date('Expired Date'),
'sex':fields.selection([('male','Male'),('female','Female')],'Sex'),
'age' : fields.function(_compute_age, type='float', method=True, store=True, string='Age', readonly=True),
'deposit': fields.function(_compute_dept2, type='float', method=True, store=True, string='Deposit', readonly=True),
'available': fields.function(_compute_dept, type='float', method=True, store=True, string='Available', readonly=True),
'deposit_ids':fields.one2many('deposit.line', 'deposit_id', 'Deposit Line'),
}
res_partner()
Since you have one2many field for deposit_line defined in the res.partner model, you do not need the to access deposit_line object directly.
def _compute_dept2(self, cr, uid, ids, amount, arg, context=None):
result = {}
for partner in self.browse(cr, uid, id, context=context)
result[partner.id]=0
for deposit_line in partner.deposit_ids:
result[partner.id] += deposit_line.amount
return result
After line 3, you forgot to:
obj2.browse(cr, uid, ids, context=context)
You should learn to use the debugger:
Add the line import pdb; pdb.set_trace() where you want to place a breakpoint. When the Python reaches the breakpoint it stops at the console with a (pdb) prompt. There type p obj to print variable obj, n to step to the next instruction, and hfor help. You might find more info in this post and in the docs.