[FIX] hr_expense: to give report manager rights and make expense_line_ids editable
1) Now report manager (user_id) (with Team Approver rights) can't see the report. Here we grant him the same rights as the manager (on employee app) of the employee will have. Moreover, he can approve the report as well. 2) Purpose: accountant, manager, should be able to edit expense_line_ids for expense report not only in draft, but also for submitted and approved states. On the other hand, employee can only edit his expense report only in draft state. task - 2768700 closes odoo/odoo#84978 Related: odoo/upgrade#3274 Related: odoo/enterprise#24579 Signed-off-by: Kevin Baptiste <kba@odoo.com>
This commit is contained in:
@@ -577,7 +577,6 @@ Or send your receipts at <a href="mailto:%(email)s?subject=Lunch%%20with%%20cust
|
||||
unit_amount = expense.unit_amount if expense.product_has_cost else expense.total_amount
|
||||
quantity = expense.quantity if expense.unit_amount else 1
|
||||
|
||||
# sgv todo - chage so that we do not recompute again. We have all the info from expense
|
||||
taxes = expense.tax_ids.with_context(round=True).compute_all(unit_amount, expense.currency_id, quantity, expense.product_id)
|
||||
total_amount = 0.0
|
||||
total_amount_currency = 0.0
|
||||
@@ -912,6 +911,7 @@ class HrExpenseSheet(models.Model):
|
||||
|
||||
name = fields.Char('Expense Report Summary', required=True, tracking=True)
|
||||
expense_line_ids = fields.One2many('hr.expense', 'sheet_id', string='Expense Lines', copy=False)
|
||||
is_editable = fields.Boolean("Expense Lines Are Editable By Current User", compute='_compute_is_editable')
|
||||
expense_number = fields.Integer(compute='_compute_expense_number', string='Number of Expenses')
|
||||
state = fields.Selection([
|
||||
('draft', 'Draft'),
|
||||
@@ -1003,6 +1003,20 @@ class HrExpenseSheet(models.Model):
|
||||
sheet.department_id = sheet.employee_id.department_id
|
||||
sheet.user_id = sheet.employee_id.expense_manager_id or sheet.employee_id.parent_id.user_id
|
||||
|
||||
@api.depends_context('uid')
|
||||
@api.depends('employee_id', 'user_id', 'state')
|
||||
def _compute_is_editable(self):
|
||||
is_manager = self.user_has_groups('hr_expense.group_hr_expense_manager')
|
||||
is_approver = self.user_has_groups('hr_expense.group_hr_expense_user')
|
||||
for report in self:
|
||||
# Employee can edit his own expense in draft only
|
||||
is_editable = (report.employee_id.user_id == self.env.user and report.state == 'draft') or (is_manager and report.state in ['draft', 'submit', 'approve'])
|
||||
if not is_editable and report.state in ['draft', 'submit', 'approve']:
|
||||
# expense manager can edit, unless it's own expense
|
||||
current_managers = report.employee_id.expense_manager_id | report.employee_id.parent_id.user_id | report.employee_id.department_id.manager_id.user_id | report.user_id
|
||||
is_editable = (is_approver or self.env.user in current_managers) and report.employee_id.user_id != self.env.user
|
||||
report.is_editable = is_editable
|
||||
|
||||
@api.constrains('expense_line_ids')
|
||||
def _check_payment_mode(self):
|
||||
for sheet in self:
|
||||
@@ -1095,7 +1109,10 @@ class HrExpenseSheet(models.Model):
|
||||
for sheet in self:
|
||||
move = sheet.account_move_id
|
||||
sheet.account_move_id = False
|
||||
move._reverse_moves(cancel=True)
|
||||
if move.state == 'draft':
|
||||
move.unlink()
|
||||
else:
|
||||
move._reverse_moves(cancel=True)
|
||||
sheet.write({'state': 'draft'})
|
||||
|
||||
def action_get_attachment_view(self):
|
||||
@@ -1139,13 +1156,13 @@ class HrExpenseSheet(models.Model):
|
||||
|
||||
def action_submit_sheet(self):
|
||||
self.write({'state': 'submit'})
|
||||
self.activity_update()
|
||||
self.sudo().activity_update()
|
||||
|
||||
def _check_can_approve(self):
|
||||
if not self.user_has_groups('hr_expense.group_hr_expense_team_approver'):
|
||||
raise UserError(_("Only Managers and HR Officers can approve expenses"))
|
||||
elif not self.user_has_groups('hr_expense.group_hr_expense_manager'):
|
||||
current_managers = self.employee_id.expense_manager_id | self.employee_id.parent_id.user_id | self.employee_id.department_id.manager_id.user_id
|
||||
current_managers = self.employee_id.expense_manager_id | self.employee_id.parent_id.user_id | self.employee_id.department_id.manager_id.user_id | self.user_id
|
||||
|
||||
if self.employee_id.user_id == self.env.user:
|
||||
raise UserError(_("You cannot approve your own expenses"))
|
||||
@@ -1197,7 +1214,7 @@ class HrExpenseSheet(models.Model):
|
||||
if not self.user_has_groups('hr_expense.group_hr_expense_team_approver'):
|
||||
raise UserError(_("Only Managers and HR Officers can approve expenses"))
|
||||
elif not self.user_has_groups('hr_expense.group_hr_expense_manager'):
|
||||
current_managers = self.employee_id.expense_manager_id | self.employee_id.parent_id.user_id | self.employee_id.department_id.manager_id.user_id
|
||||
current_managers = self.employee_id.expense_manager_id | self.employee_id.parent_id.user_id | self.employee_id.department_id.manager_id.user_id | self.user_id
|
||||
|
||||
if self.employee_id.user_id == self.env.user:
|
||||
raise UserError(_("You cannot refuse your own expenses"))
|
||||
@@ -1214,7 +1231,7 @@ class HrExpenseSheet(models.Model):
|
||||
if not self.can_reset:
|
||||
raise UserError(_("Only HR Officers or the concerned employee can reset to draft."))
|
||||
self.mapped('expense_line_ids').write({'is_refused': False})
|
||||
self.write({'state': 'draft', 'approval_date': False})
|
||||
self.sudo().write({'state': 'draft', 'approval_date': False})
|
||||
self.activity_update()
|
||||
return True
|
||||
|
||||
|
||||
@@ -12,11 +12,12 @@
|
||||
<record id="ir_rule_hr_expense_approver" model="ir.rule">
|
||||
<field name="name">Team Approver Expense</field>
|
||||
<field name="model_id" ref="model_hr_expense"/>
|
||||
<field name="domain_force">['|', '|', '|',
|
||||
<field name="domain_force">['|', '|', '|', '|',
|
||||
('employee_id.user_id', '=', user.id),
|
||||
('employee_id.department_id.manager_id.user_id', '=', user.id),
|
||||
('employee_id.parent_id.user_id', '=', user.id),
|
||||
('employee_id.expense_manager_id', '=', user.id)]</field>
|
||||
('employee_id.expense_manager_id', '=', user.id),
|
||||
('sheet_id.user_id', '=', user.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('hr_expense.group_hr_expense_team_approver'))]"/>
|
||||
</record>
|
||||
<record id="ir_rule_hr_expense_employee" model="ir.rule">
|
||||
@@ -37,19 +38,29 @@
|
||||
<record id="ir_rule_hr_expense_sheet_approver" model="ir.rule">
|
||||
<field name="name">Approver Expense Sheet</field>
|
||||
<field name="model_id" ref="model_hr_expense_sheet"/>
|
||||
<field name="domain_force">['|', '|', '|',
|
||||
<field name="domain_force">['|', '|', '|', '|',
|
||||
('employee_id.user_id', '=', user.id),
|
||||
('employee_id.department_id.manager_id.user_id', '=', user.id),
|
||||
('employee_id.parent_id.user_id', '=', user.id),
|
||||
('employee_id.expense_manager_id', '=', user.id)]</field>
|
||||
('employee_id.expense_manager_id', '=', user.id),
|
||||
('user_id', '=', user.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('hr_expense.group_hr_expense_team_approver'))]"/>
|
||||
</record>
|
||||
<record id="ir_rule_hr_expense_sheet_employee" model="ir.rule">
|
||||
<field name="name">Employee Expense Sheet</field>
|
||||
<field name="model_id" ref="model_hr_expense_sheet"/>
|
||||
<field name="domain_force">[('employee_id.user_id', '=', user.id)]</field>
|
||||
<field name="domain_force">[('employee_id.user_id', '=', user.id), ('state', '=', 'draft')]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
<record id="ir_rule_hr_expense_sheet_employee_not_draft" model="ir.rule">
|
||||
<field name="name">Employee can't modify expense sheet that is not in draft state</field>
|
||||
<field name="model_id" ref="model_hr_expense_sheet"/>
|
||||
<field name="domain_force">[('employee_id.user_id', '=', user.id), ('state', '!=', 'draft')]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_write" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="hr_expense_comp_rule" model="ir.rule">
|
||||
<field name="name">Expense multi company rule</field>
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<field name="quantity" optional="hide"/>
|
||||
<field name="tax_ids" optional="hide" widget="many2many_tags" groups="account.group_account_invoice,account.group_account_readonly"/>
|
||||
<field name="amount_tax_company" optional="hide" groups="account.group_account_invoice,account.group_account_readonly"/>
|
||||
<field name="attachment_number" nolabel="1" class='fa fa-paperclip float-right pr-0' attrs="{'invisible': [('attachment_number', '=', 0)]}"/>
|
||||
<field name="attachment_number" nolabel="1" class='fa fa-paperclip pr-0' attrs="{'invisible': [('attachment_number', '=', 0)]}"/>
|
||||
<field name="total_amount_company" optional="show" sum="Total Company Currency" widget='monetary' options="{'currency_field': 'company_currency_id'}" decoration-bf="True"/>
|
||||
<field name="total_amount" optional="hide" decoration-bf="True" groups="base.group_multi_currency"/>
|
||||
<field name="currency_id" optional="hide" groups="base.group_multi_currency"/>
|
||||
@@ -731,7 +731,7 @@
|
||||
<div class="oe_title">
|
||||
<label for="name" class="oe_edit_only"/>
|
||||
<h1>
|
||||
<field name="name" placeholder="e.g. Trip to NY" attrs="{'readonly': [('state', 'in', ['post', 'done'])]}"/>
|
||||
<field name="name" placeholder="e.g. Trip to NY" attrs="{'readonly': [('is_editable', '=', False)]}"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
@@ -745,17 +745,18 @@
|
||||
</group>
|
||||
<group>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="user_id" domain="[('share', '=', False)]" widget="many2one_avatar_user"/>
|
||||
<field name="user_id" widget="many2one_avatar_user"/>
|
||||
<field name="accounting_date" groups="account.group_account_invoice,account.group_account_readonly" attrs="{'invisible': [('state', 'not in', ['approve', 'post', 'done'])], 'readonly': [('state', 'in', ['post', 'done'])]}"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page name="expenses" string="Expense">
|
||||
<field name="expense_line_ids" nolabel="1" widget="many2many" domain="[('state', '=', 'draft'), ('employee_id', '=', employee_id), ('company_id', '=', company_id)]" options="{'reload_on_button': True}" context="{'form_view_ref' : 'hr_expense.hr_expense_view_form_without_header', 'default_company_id': company_id, 'default_employee_id': employee_id}" attrs="{'readonly': [('state', '!=', 'draft')]}">
|
||||
<field name="is_editable" invisible="1"/>
|
||||
<field name="expense_line_ids" nolabel="1" widget="many2many" domain="[('state', '=', 'draft'), ('employee_id', '=', employee_id), ('company_id', '=', company_id)]" options="{'reload_on_button': True}" context="{'form_view_ref' : 'hr_expense.hr_expense_view_form_without_header', 'default_company_id': company_id, 'default_employee_id': employee_id}" attrs="{'readonly': [('is_editable', '=', False)]}">
|
||||
<tree decoration-danger="is_refused" editable="bottom" class="o_expense_line_list">
|
||||
<field name="date" optional="show" readonly="True"/>
|
||||
<field name="product_id" readonly="True"/>
|
||||
<field name="name" readonly="True"/>
|
||||
<field name="date" optional="show"/>
|
||||
<field name="product_id"/>
|
||||
<field name="name"/>
|
||||
<field name="state" invisible="1"/>
|
||||
<field name="reference" optional="hide" readonly="True"/>
|
||||
<field name="analytic_account_id" optional="show" domain="['|', ('company_id', '=', parent.company_id), ('company_id', '=', False)]" groups="analytic.group_analytic_accounting"/>
|
||||
@@ -768,9 +769,9 @@
|
||||
<field name="currency_id" optional="hide" readonly="True"/>
|
||||
<field name="quantity" optional="hide" readonly="True"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="tax_ids" string="Taxes" optional="show" widget="many2many_tags" context="{'default_company_id': company_id}" readonly="True"/>
|
||||
<field name="tax_ids" string="Taxes" optional="show" widget="many2many_tags" context="{'default_company_id': company_id}"/>
|
||||
<field name="amount_tax" optional="hide" context="{'default_company_id': company_id}" readonly="True"/>
|
||||
<field name="total_amount" optional="show" readonly="True"/>
|
||||
<field name="total_amount" optional="show"/>
|
||||
<field name="amount_tax_company" optional="hide" readonly="True"/>
|
||||
<field name="company_currency_id" invisible="1"/>
|
||||
<field name="total_amount_company" optional="show" groups="base.group_multi_currency" readonly="True"/>
|
||||
|
||||
Reference in New Issue
Block a user