ValueError Se esperaba un singleton, Odoo8

He estado trabajando en un módulo en Odoo8 en Ubuntu 14.04. He encontrado un problema extraño al guardar un registro de formulario basado en algunos campos One2many. El error dice

ValueError Expected singleton: hr.employee.pay.change(84, 85) 

Mi código de Python es el siguiente

 class hr_employee_pay_change(models.Model): _name='hr.employee.pay.change' hr_payroll_change_ids = fields.Many2one("employee.salary.change", "Employee", ondelete="cascade") @api.onchange('emp_basic', 'emp_allowance') @api.depends('emp_basic', 'emp_allowance') def _current_total(self): self.emp_current_total = self.emp_basic + self.emp_allowance @api.onchange('emp_propose_allowance', 'emp_propose_basic') @api.depends('emp_propose_allowance', 'emp_propose_basic') def _proposed_total(self): data_val={} self.emp_propose_total = self.emp_propose_basic + self.emp_propose_allowance cr=self._cr uid=self._uid ids=self._ids val=int(self.employee_name) if val: cr.execute("select max_salary,min_salary from hr_job where id in (select job_id from hr_employee where id='"+str(val)+"')") res=cr.fetchall() for data_val in res: max_sal=data_val[0] min_sal=data_val[1] if not min_sal < self.emp_propose_total < max_sal: self.emp_propose_basic = 0.0 self.emp_propose_allowance = 0.0 return {'warning':{'title':'warning','message':'Out of Range, Proposed Total must be in between "'+str(max_sal)+'"to"'+str(min_sal)+'"'}} else: cr.execute("select wage from hr_contract where employee_id=0") @api.onchange('employee_name') @api.depends('employee_name') def get_data(self): data={} cr=self._cr uid=self._uid ids=self._ids value=int(self.employee_name) if(self.employee_name): cr.execute("select wage,allowance from hr_contract where employee_id ='"+str(value)+"'") res=cr.fetchall() for data in res: self.emp_basic=data[0] self.emp_allowance = data[1] else: cr.execute("select wage,allowance from hr_contract where employee_id=0") employee_name = fields.Many2one('hr.employee', 'Employee Name', required=True ) zeo_number = fields.Char(related='employee_name.zeo_number', string='ZEO Number', readonly=True ) emp_basic = fields.Float('Basic Salary', compute='get_data',readonly=True, store=True ) emp_allowance = fields.Float('Allowance', compute='get_data',readonly=True, store=True ) emp_current_total = fields.Float('Totals', compute='_current_total', store=True, track_visibility='always') emp_propose_basic = fields.Float('Proposed Basic') emp_propose_allowance = fields.Float('Proposed Allowance') emp_propose_total = fields.Float('Proposed Totals', compute='_proposed_total', store=True, track_visibility='always') 

No puedo conseguir este problema. Intenté eliminar la propiedad ‘readonly = True’ del campo y el problema se solucionó, pero necesito tenerlos como de solo lectura. Esperanzas de sugerencia

Singleton esperado:

Los métodos de clase requieren un solo objeto invocador (Registro de un solo navegador) para invocar el método y suponen que invocará varios objetos que invocan (Conjuntos de registros con capacidad de navegación), entonces el método no puede identificar el objeto que debe procesar, por lo tanto generará un error. .

El nuevo decorador de API se utiliza para definir el patrón de llamada de método, ya que los métodos permiten que solo un objeto único o múltiple invoque este método.

@ api.one

Este decorador recorre automáticamente los Registros de RecordSet para usted. El yo se redefine como registro actual

Nota: Precaución: el valor devuelto se coloca en una lista. Esto no siempre es compatible con el cliente web, por ejemplo, en los métodos de acción de los botones. En ese caso, debe usar @ api.multi para decorar su método, y probablemente llamar self.ensure_one () en la definición del método.

@ api.multi

Self será el RecordSet actual sin iteración. Es el comportamiento por defecto (múltiples objetos navegables). Los métodos que devuelven datos de tipo no premitivo (lista, diccionario, función) deben decorarse con @ api.multi

@ api.model

Este decorador convertirá las llamadas API antiguas a la función decorada en una nueva firma API. Permite ser educado al migrar código. Self no contiene ningún registro / conjunto de registros en los métodos decorados por este decorador.

Así que simplemente llama así

self.env [‘model_name’]. method_name (argumentos)

Debes intentar seguir,

 class hr_employee_pay_change(models.Model): _name='hr.employee.pay.change' hr_payroll_change_ids = fields.Many2one("employee.salary.change", "Employee", ondelete="cascade") @api.onchange('emp_basic', 'emp_allowance') @api.depends('emp_basic', 'emp_allowance') def _current_total(self): for rec in self: rec.emp_current_total = rec.emp_basic + rec.emp_allowance @api.onchange('emp_propose_allowance', 'emp_propose_basic') @api.depends('emp_propose_allowance', 'emp_propose_basic') def _proposed_total(self): for rec in self: data_val={} rec.emp_propose_total = rec.emp_propose_basic + rec.emp_propose_allowance cr=self._cr uid=self._uid ids=self._ids val=int(rec.employee_name) if val: cr.execute("select max_salary,min_salary from hr_job where id in (select job_id from hr_employee where id='"+str(val)+"')") res=cr.fetchall() for data_val in res: max_sal=data_val[0] min_sal=data_val[1] if not min_sal < self.emp_propose_total < max_sal: self.emp_propose_basic = 0.0 self.emp_propose_allowance = 0.0 return {'warning':{'title':'warning','message':'Out of Range, Proposed Total must be in between "'+str(max_sal)+'"to"'+str(min_sal)+'"'}} else: cr.execute("select wage from hr_contract where employee_id=0") @api.onchange('employee_name') @api.depends('employee_name') def get_data(self): for rec in self: data={} cr=self._cr uid=rec._uid ids=rec._ids value=int(rec.employee_name) if(rec.employee_name): cr.execute("select wage,allowance from hr_contract where employee_id ='"+str(value)+"'") res=cr.fetchall() for data in res: rec.emp_basic=data[0] rec.emp_allowance = data[1] else: cr.execute("select wage,allowance from hr_contract where employee_id=0")