3
votes

I am trying to create a fine allocation functionality in hr.employee.This module inherits from hr.employee. The process is:

  1. Click the Fine Allocation menu that opens a wizard. The wizard has a many2many relation field called employee_ids related to hr.employee. This should enable you to select batch employees and allocate fines together.

2.There being a field with name fine_amount, allocate individual fines for employees in each of the lines and then allocate fines by click of a button.

My question is, how do I extend this many2many field with the fine_amount field?

If I extend the hr.employee form with this field, it is not among the selected fields in the many2many lines.

My code looks like this

class FineAllocation(models.TransientModel):
_name = 'fine.allocation'
_description = 'Fine Allocation'

@api.model
def action_allocate_fine(self):
    pass

employee_ids = fields.Many2many('hr.employee','hr_employee_group_rel', 'deductions_id' 'Employees')
fine_amount = fields.Float(string='Fine Amount')

And this is for the wizard record view

<record id="employee_fine_allocation_form" model="ir.ui.view">
        <field name="name">Employee Fine Allocation Form</field>
        <field name="model">fine.allocation</field>
        <field name="arch" type="xml">
            <form string="Employee Fine Allocation">
                <group>
                    <span colspan="4" nolabel="1">This wizard will allocate fines for all selected employee(s) equalling the input fine amount.</span>
                </group>

                <group colspan="4">
                    <separator string="Employees" colspan="4" />
                    <newline />
                    <field name="employee_ids" nolabel="1" />
                </group>

                <footer>
                    <button name="action_allocate_fine" string="Allocate Fines" type="object" class="btn-primary" />
                    <button string="Cancel" class="btn-secondary" special="cancel" />
                </footer>
            </form>
        </field>
    </record>
2
You need a One2many field for this kind of behavior, create a new model to link between your Wizard and the employee model. And the new model will have three field m2o for wizard, m2o for employee, fine_amountCharif DZ
Thank you @CharifDZ, let me try that.Eric
You want to specify fine amount for each employee?Charif DZ
Yes, like the amount can be different for an employeeEric

2 Answers

2
votes

By default, the many2many field shows the default view.

When a view is requested by (model, type), the view matching the model and the type, with the lowest priority will be returned (it is the default view).

To show the field in the many2many list you can extend the default view or define your view, try one of the followings:

  1. Extend the default tree view hr.view_employee_tree:

     <record id="view_employee_tree" model="ir.ui.view">
         <field name="name">hr.employee.tree</field>
         <field name="model">hr.employee</field>
         <field name="inherit_id" ref="hr.view_employee_tree"/>
         <field name="arch" type="xml">
             <tree>
                 <field name="fine_amount"/>
             </tree>
         </field>
     </record>
    
  2. Define a new tree view and force the many2many field to show it:

     <record id="view_employee_tree_allocate_fine" model="ir.ui.view">
     <field name="name">hr.employee.tree.allocate.fine</field>
     <field name="model">hr.employee</field>
     <field name="arch" type="xml">
         <tree string="Employees" decoration-bf="message_needaction==True">
             <field name="name"/>
             <field name="work_phone" class="o_force_ltr"/>
             <field name="work_email"/>
             <field name="company_id" groups="base.group_multi_company"/>
             <field name="department_id"/>
             <field name="job_id"/>
             <field name="parent_id"/>
             <field name="coach_id" invisible="1"/>
             <field name="message_needaction" invisible="1"/>
    
             <field name="fine_amount"/>
         </tree>
     </field>
     </record>
    

    To force the many2many field to show a specific view, pass tree_view_ref in context:

    <field name="employee_ids" nolabel="1" context="{'tree_view_ref': 'module_name.view_employee_tree_allocate_fine'}"/>
    
  3. Define the tree view in place:

     <field name="employee_ids">
         <tree editable="bottom">
             <field name="name"/>
             <field name="work_phone" class="o_force_ltr"/>
             <field name="work_email"/>
             <field name="company_id" groups="base.group_multi_company"/>
             <field name="department_id"/>
             <field name="job_id"/>
             <field name="parent_id"/>
             <field name="coach_id" invisible="1"/>
             <field name="message_needaction" invisible="1"/>
    
             <field name="fine_amount"/>
         </tree>
     </field>
    

Edit:

Set editable option to bottom when defining tree view in place.

Edit2:

With the following definition:

employee_ids = fields.Many2many('hr.employee', 'hr_employee_rel', 'payslip_id', 'Employees')

Odoo will try to create records and setting the value of column2 (It is not passed explicitly in the example above ) to Employees which will raise the following error:

the “employees” column of the “hr_employee_rel” relationship does not exist
LINE 2: ...   INSERT INTO hr_employee_rel (payslip_id, Employees)...

employee_id is missing if you compare it to employee_ids in hr_payroll wizard model.

In your question, you can see that there is no comma between deductions_id and Employees, Python will concatenate the two strings and you will end with column1 set to deductions_idEmployees. Odoo should raise the following error:

psycopg2.errors.UndefinedColumn: ERROR: the column « deductions_idemployees » of the relation « hr_employee_group_rel » does not exist
LINE 2: ... INSERT INTO hr_employee_group_rel (deductions ...

You could avoid that error if you passed Employees as the string attribute, the second column (column2 attribute) should be generated automatically as it is an optional. You can try the following definition:

employee_ids = fields.Many2many('hr.employee', 'hr_employee_fine_allocation_rel', 'payslip_id', string='Employees')

The attributes relation, column1 and column2 are optional. If not given, names are automatically generated from model names.

If you do not need to set them explicitly, the field declaration can be reduced to:

employee_ids = fields.Many2many('hr.employee', string='Employees')
1
votes

Ok try this, In python side:

class FineAllocation(models.TransientModel):
    _name = 'fine.allocation'
    _description = 'Fine Allocation'
    
    # Use one two many field because you need to information an employee and fine amount
    employee_allocation_ids = fields.One2many('fine.allocation.amount', 'Employees allocations')
    
    def action_allocate_fine(self):
        for rec in self.employee_allocation_ids:
            for rec in self.employee_allocation_ids:
               vals = {
                 'deduction_id': 1,
                 'computation': 'fixed',
                 'fixed': rec.fine_amount,
                 'employee_id': rec.employee_id.id,
               }
               self.env['ke.deductions'].sudo().create(vals)
    

# create the model that will hold the two information and link them to the wizard 
class FineAllocationAmount(models.TransientModel):
    _name = 'fine.allocation.amount'
    _description = 'Fine Allocation'
    
    fine_allocation_id = fields.Many2one('fine.allocation')
    
    employee_id = fields.Many2one('hr.employee', 'Employee', required=True)
    fine_amount = fields.Float('Fine amount')

In your Form view:

<record id="employee_fine_allocation_form" model="ir.ui.view">
        <field name="name">Employee Fine Allocation Form</field>
        <field name="model">fine.allocation</field>
        <field name="arch" type="xml">
            <form string="Employee Fine Allocation">
                <group>
                    <span colspan="4" nolabel="1">This wizard will allocate fines for all selected employee(s) equalling the input fine amount.</span>
                </group>

                <group colspan="4">
                    <separator string="Employees" colspan="4" />
                    <newline />
                    <field name="employee_allocation_ids" nolabel="1" >
                         <!-- Use tree view to fill the information no need to open anather popup -->
                        <tree editable="bottom">
                          <field name="employee_id"/>
                          <field name="fine_amount"/>
                        </tree>
                    </field>
                </group>

                <footer>
                    <button name="action_allocate_fine" string="Allocate Fines" type="object" class="btn-primary" />
                    <button string="Cancel" class="btn-secondary" special="cancel" />
                </footer>
            </form>
        </field>
    </record>

I hope this helps you.