I have been working on a module in Odoo8 on Ubuntu 14.04. I have come up to a strange issue when saving a form record based on some One2many fields. The error says
ValueError
Expected singleton: hr.employee.pay.change(84, 85)
My Python code is as below
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')
I am unable to get this issue . I tried to remove the 'readonly=True' property of the field and the issue gets fixed but I need to have them as readonly . Hopes for suggestion
答案 0 :(得分:7)
预期的单身人士:
类方法需要单个调用对象(Single Browsable Record)来调用该方法并假设它将通过多个调用对象(可浏览记录集)调用然后方法不能确定它应该处理哪个对象,因此会引发错误预期单身。
新的API装饰器用于定义方法调用模式,方法是否只允许单个对象或多个对象调用此方法。
<强> @ api.one 强>
这个装饰器会自动在RecordSet记录上循环。 Self被重新定义为当前记录
注意:强> 警告:返回的值放在列表中。 Web客户端并不总是支持这一点,例如按钮动作 方法。在这种情况下,您应该使用 @ api.multi 来装饰您的方法,并可能在 self.ensure_one()中调用 方法定义。
<强> @ api.multi 强>
Self将是没有迭代的当前RecordSet。这是默认行为(多个可浏览对象)。返回非premitive类型数据(列表,字典,函数)的方法必须用 @ api.multi
进行修饰@ api.model
此装饰器会将旧的API调用转换为装饰函数,以转换为新的API签名。它允许礼貌的时候 迁移代码。 Self在此装饰器修饰的方法中不包含任何记录/记录集。
所以简单地这样打电话
<强> self.env [ 'MODEL_NAME']。METHOD_NAME(参数)强>
你应该尝试以下,
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")