ValueError Expected singleton, Odoo8

I am working on a module in Odoo8 on Ubuntu 14.04. I came up with a weird problem 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 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 cannot get this problem. I tried removing the "readonly = True" property of this field and the problem is fixed, but I need to have them as read-only. Offer hopes

+3


source to share


1 answer


Expected singleton:

Class methods require one caller (single reachable record) to invoke the method and suppose it will invoke multiple callers (Browsable Recordsets) then the method won't be able to determine which object it should be processed for, so it will throw Expected error singleton .

The new API decorator is used to define a method call pattern when methods allow only one object or multiple objects to call that method.

@ api.one

This decorator will automatically loop over the RecordSet for you. Self is overridden as the current record

Note: Attention: the return value is placed in the list. This is not always supported by the web client for example. button action methods. In this case, you should use @ api.multi to decorate your method and possibly call self.ensure_one () in the method definition.

@ api.multi



Self will be the current RecordSet without iteration. This is the default behavior (multiple objects available for viewing). Methods returning non-transitive data (list, dictionary, function) should be decorated with @ api.multi

@ api.model

This decorator will convert old API calls to a decorated function into a new API signature. This allows you to be polite when the migration code. Self does not contain entries / entries in methods decorated with this decorator.

So just call it

self.env ['model_name']. Method_name (arguments)

You should try

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

      

+5


source







All Articles