ValueError Expected singleton , Odoo8

时间:2015-06-26 10:16:28

标签: python openerp odoo

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

1 个答案:

答案 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")