This question has been flagged
2 Replies
5554 Views

When press the button need list all employee and some data of this.

I create an module class prepare_adv() and other adv(), the second are as One2many fields in the first. 

in prepare_adv have a button that onclick need list in adv() all of employees and some datas of this. 

This is the function of button that need save the recors in adv() and them view in prepare_adv():

def onclick(self, cr, uid, ids, context=None):
        employee_obj = self.pool.get('hr.employee')
        contract_obj = self.pool.get('hr.contract')
        res = {}
        for advances in self.browse(cr,uid,ids,context=context):
            res[advances.id] = {
                'id_intern': 0,
                'employee_name': 0,
                'wage_base': 0,
            }
            for empl in employee_obj.browse(cr,uid,ids,context=context):
                res[advances.id]['wage_base'] = contract_obj.browse(cr,uid,empl.id).wage
                res[advances.id]['id_intern'] = empl.id_inter
                res[advances.id]['employee_name'] = empl.id 
                lines = [(0,0,res)]
                self.write(cr, uid, [advances.id], {'advancs': lines,}, context=context)
        return True

This no save nothing of records. What i do wrong ?

Avatar
Discard
Author

Some can help me please...

Best Answer

Hi,

I believe you do not understand what is a on2many field :

if you display in view prepare_adv the field you defined in on2many field in adv to do the relation between the 2 class, and select an adv in prepare_adv and save your change, the line prepare_adv in one2many view in adv will be displayed automatically (by refreshing the view if you work on 2 notebooks).

I don't know if this is the result you want, but one prepare_adv can be display only in one adv with a one2many field.

If you want to display the list of all employee in adv one2many line corresponding to the prepare_adv id, you must create a field many2many with employee class relation in prepare_adv named employee_ids, and add it the one2many form view in adv by using widget one2many_list.

Your button in prepare adv will be used to update the field employee_ids list.

UPDATE :

button code :

class prepare_adv(models.Model):
    _name = 'prepare.adv'

 @api.one
    def on_click(self):
        self.ensure_one()
        per = time.strftime('%m/%Y')

        cr = self.env.cr
        cr.execute('''SELECT hr_employee.id, id_inter, wage FROM hr_employee, hr_contract WHERE hr_employee.id=employee_id''')
        temp = cr.fetchall()
        adv_to_create = []

        prepare_adv_id = self._ids[0]
        for record in temp:
            adv_to_create += [(0, 0, {'advances_id': prepare_adv_id,' period_id': per, 'id_intern': record[1],
                                                    'employee_name': record[0], 'wage_base': record[2]
                                           })]
        prepare_adv.advancs = adv_to_create
        return True

function field :

    @api.multi

    @api.depends('wage_base')

    def _compute_wage_advance(self):

        for record in self:

            record.advances_40 = record.wage_base * 0.40

Avatar
Discard
Author Best Answer

Hi Cyril Gaspard,

Thanks to you for answer. 

Now, I have this:

prepare_adv()
 _______________________________________________________________________
|      Ref:  ______________                             Period: _________ - ___________       |
|      _button_here                                                                                                   |
|............................................................................................................................|
|      ________________________________________________________________      |
|      |    id     |     employee      |   wage_of_contract   |   compute_40%_of_wage   | <---|----  this is my adv()
|      |-----------|-------------------------|--------------------------------|----------------------------------------|       |


adv.id and adv.employee have in hr_employee, and adv.wage_of_contract have in hr_contract, now, adv.compute_40%_of_wage is automatic compute from adv.wage_of_contract.
I need create this every month but one time, with all employee available. I solved the problem to save datas in adv() and can see this in prepare_adv() but have other problem :)
The problem is the next: when is only one row fine, save and can see perfect; but if it is more than one row show the next error: 

Expected singleton: hr.py.advances(104, 105, 103)

Save the data in adv() but show the error mentioned.
I have understood that need create new rows for news records. 


This is my code of function from button (this are in prepare_adv()): 

def on_click(self, cr, uid, ids, context=None):
        res = {}
        for adv in self.browse(cr,uid,ids):
            cr.execute('''SELECT hr_employee.id, id_inter, wage FROM hr_employee, hr_contract WHERE hr_employee.id=employee_id''')
            temp = cr.fetchall()
            per = time.strftime('%m/%Y')
            for record in temp:
                datas = {'advances_id':adv.id,'period_id':per,'id_intern':record[1],'employee_name':record[0],'wage_base':record[2]}
                crea = self.pool.get('hr.py.advances').create(cr,uid,datas,context=context)
                self.pool.get('hr.py.advances').write(cr,uid,crea,datas,context=context)
            return True

This is my adv() class:

class adv(models.Model):
    _name = 'adv'

    advances_id = fields.Many2one('prepare.adv')
    period_id = fields.Char()
    id_intern = fields.Integer(string='Cod.')
    employee_name = fields.Many2one('hr.employee', string='Funcionario')
    wage_base = fields.Float(string='Salario')
    advances_40 = fields.Integer(compute='_compute_wage_advance', string='40% Adelanto Quinc.')

    @api.depends('wage_base')
    def _compute_wage_advance(self):
        self.advances_40 = self.wage_base * 0.40

This id my prepare_adv() class:

class prepare_adv(models.Model):
    _name = 'prepare.adv'

    state = fields.Selection([('draft','Borrador'),('done','Aprobado')], default='draft', string='Status', select=True, readonly=True, copy=False)
    referenc = fields.Char(string='Referencia',default='Anticipo - ' + time.strftime('%m/%Y'))    
    date_from = fields.Datetime(string='Periodo', default=lambda *a: time.strftime('%Y-%m-01'), required=True, readonly=True, states={'draft': [('readonly', False)]})
    date_to = fields.Datetime(string='-', default=lambda *a: str(datetime.now() + relativedelta.relativedelta(months=+1, day=1, days=-1))[:10], required=True, readonly=True, states={'draft': [('readonly', False)]})
    per_id = fields.Char(string='per', default= time.strftime('%m/%Y'))
    advancs = fields.One2many('adv','advances_id')

This is the view of prepare_adv():

<div class="oe_title">
                            <label for="referenc" class="oe_edit_only"/>
                            <h1>
                                <field name="referenc"/>
                            </h1>
                        </div>
                        <div class="oe_right">
                            <label for="date_from" class="oe_edit_only"/><field name="date_from" class="oe_inline"/><label for="date_to">-</label><field name="date_to" class="oe_inline"/>
                        </div>
                        <group>
                            <button string="Cargar" name="charge_employee" states="draft" type="object" class="oe_highlight"/>
                        </group>
                        <notebook>
                            <page>
                                <field name="advancs" nolabel="1"/>
                            </page>
                        </notebook>

How create news row for view all amount of employee (around of 72 employee)? 
 

 

Avatar
Discard

why did you do a create and after a write with same datas on same model? just need to create => self.pool.get('hr.py.advances').create(cr,uid,datas,context=context) self.pool.get('hr.py.advances').write(cr,uid,crea,datas,context=context) Else error you have is due to: in a write, you must give a list of ids, not just one id, replace in your write call crea by [crea] : self.pool.get('hr.py.advances').write(cr,uid,[crea],datas,context=context)

Author

I have understood that need create and them write this in the database, is wrong ? Try with self.pool.get('hr.py.advances').write(cr,uid,[crea],datas,context=context) but show the same error: Expected singleton: hr.py.advances(108, 109)

in your field advances_id = fields.Many2one('prepare.adv') where is defined the class prepare.adv you are using in this field ????

Author

hr_py_prepare_advances is the prepare.adv, sorry

Author

Now is right.

Author

^^ now is right the previous code, because I modified. The problem not solved it yet :(

Author

Return this with your new code: cr.execute('''SELECT hr_employee.id, id_inter, wage FROM hr_employee, hr_contract WHERE hr_employee.id=employee_id''') NameError: global name 'cr' is not defined

forget to define cr in v8 : cr = self.env.cr , I update the code. bye

Author

Thanks to you for your time to answer me... but the code not save any data in the adv() if change this code [[0, 0, {'advances_id': prepare_adv_id,' period_id': per, 'id_intern': record[1], 'employee_name': record[0], 'wage_base': record[2] }]] for [((0, 0, {'advances_id': prepare_adv_id,' period_id': per, 'id_intern': record[1], 'employee_name': record[0], 'wage_base': record[2] }))] save but show the same erro of Expected singleton: adv(150,151).

your error id due to a function which can be have just one id in input, try to change @api.depends('wage_base') def _compute_wage_advance(self): self.advances_40 = self.wage_base * 0.40 by @api.multi @api.depends('wage_base') def _compute_wage_advance(self): for record in self: record.advances_40 = record.wage_base * 0.40 I update my code with this

Author

Sorry for many thanks but need say to you more one time, Thanks very much, for your time and for you help Problem solved.