[IMP] hr_[contract,employee,recruitment,work_entry]: Add multi edit in view
Make some fields editable in multi edit. Some onchange are tranformed in compute fields. id=2078674 closes odoo/odoo#39711 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This commit is contained in:
@@ -29,7 +29,9 @@ class HrEmployeeBase(models.AbstractModel):
|
||||
resource_id = fields.Many2one('resource.resource')
|
||||
resource_calendar_id = fields.Many2one('resource.calendar', domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
|
||||
parent_id = fields.Many2one('hr.employee', 'Manager', domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
|
||||
coach_id = fields.Many2one('hr.employee', 'Coach', domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
|
||||
coach_id = fields.Many2one(
|
||||
'hr.employee', 'Coach', compute='_compute_coach', store=True, readonly=False,
|
||||
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
|
||||
tz = fields.Selection(
|
||||
string='Timezone', related='resource_id.tz', readonly=False,
|
||||
help="This field is used in order to define in which timezone the resources will work.")
|
||||
@@ -77,9 +79,10 @@ class HrEmployeeBase(models.AbstractModel):
|
||||
employee.last_activity = False
|
||||
employee.last_activity_time = False
|
||||
|
||||
@api.onchange('parent_id')
|
||||
def _onchange_parent_id(self):
|
||||
manager = self.parent_id
|
||||
previous_manager = self._origin.parent_id
|
||||
if manager and (self.coach_id == previous_manager or not self.coach_id):
|
||||
self.coach_id = manager
|
||||
@api.depends('parent_id')
|
||||
def _compute_coach(self):
|
||||
for employee in self:
|
||||
manager = employee.parent_id
|
||||
previous_manager = employee._origin.parent_id
|
||||
if manager and (employee.coach_id == previous_manager or not employee.coach_id):
|
||||
employee.coach_id = manager
|
||||
|
||||
@@ -200,14 +200,15 @@
|
||||
<field name="name">hr.employee.tree</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Employees">
|
||||
<field name="name"/>
|
||||
<field name="work_phone"/>
|
||||
<tree string="Employees" multi_edit="1">
|
||||
<field name="name" readonly="1"/>
|
||||
<field name="work_phone" readonly="1"/>
|
||||
<field name="work_email"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="company_id" groups="base.group_multi_company" readonly="1"/>
|
||||
<field name="department_id"/>
|
||||
<field name="job_id"/>
|
||||
<field name="parent_id"/>
|
||||
<field name="work_location" optional="hide"/>
|
||||
<field name="coach_id" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
|
||||
@@ -145,8 +145,8 @@ class Contract(models.Model):
|
||||
self._assign_open_contract()
|
||||
|
||||
calendar = vals.get('resource_calendar_id')
|
||||
if calendar and (self.state == 'open' or (self.state == 'draft' and self.kanban_state == 'done')):
|
||||
self.mapped('employee_id').write({'resource_calendar_id': calendar})
|
||||
if calendar:
|
||||
self.filtered(lambda c: c.state == 'open' or (c.state == 'draft' and c.kanban_state == 'done')).mapped('employee_id').write({'resource_calendar_id': calendar})
|
||||
|
||||
if 'state' in vals and 'kanban_state' not in vals:
|
||||
self.write({'kanban_state': 'normal'})
|
||||
|
||||
@@ -206,18 +206,19 @@
|
||||
decoration-bf="message_needaction == True"
|
||||
decoration-info="state == 'draft'"
|
||||
decoration-muted="state in ('close', 'cancel')"
|
||||
decoration-danger="state == 'pending'">
|
||||
<field name="name"/>
|
||||
<field name="employee_id"/>
|
||||
decoration-danger="state == 'pending'"
|
||||
multi_edit="1">
|
||||
<field name="name" readonly="1"/>
|
||||
<field name="employee_id" readonly="1"/>
|
||||
<field name="job_id"/>
|
||||
<field name="resource_calendar_id"/>
|
||||
<field name="date_start"/>
|
||||
<field name="date_end"/>
|
||||
<field name="date_start" readonly="1"/>
|
||||
<field name="date_end" readonly="1"/>
|
||||
<field name="state"/>
|
||||
<field name="kanban_state" widget="state_selection" readonly="1"/>
|
||||
<field name="wage" invisible="1"/>
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="company_id" groups="base.group_multi_company" readonly="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -20,15 +20,16 @@ class Employee(models.Model):
|
||||
expense_manager_id = fields.Many2one(
|
||||
'res.users', string='Expense',
|
||||
domain=_group_hr_expense_user_domain,
|
||||
compute='_compute_expense_manager', store=True, readonly=False,
|
||||
help="User responsible of expense approval. Should be Expense approver.")
|
||||
|
||||
@api.onchange('parent_id')
|
||||
def _onchange_parent_id(self):
|
||||
super(Employee, self)._onchange_parent_id()
|
||||
previous_manager = self._origin.parent_id.user_id
|
||||
manager = self.parent_id.user_id
|
||||
if manager and manager.has_group('hr_expense.group_hr_expense_user') and (self.expense_manager_id == previous_manager or not self.expense_manager_id):
|
||||
self.expense_manager_id = manager
|
||||
@api.depends('parent_id')
|
||||
def _compute_expense_manager(self):
|
||||
for employee in self:
|
||||
previous_manager = employee._origin.parent_id.user_id
|
||||
manager = employee.parent_id.user_id
|
||||
if manager and manager.has_group('hr_expense.group_hr_expense_user') and (employee.expense_manager_id == previous_manager or not employee.expense_manager_id):
|
||||
employee.expense_manager_id = manager
|
||||
|
||||
|
||||
class EmployeePublic(models.Model):
|
||||
|
||||
@@ -12,6 +12,17 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_employee_tree_inherit_expense" model="ir.ui.view">
|
||||
<field name="name">hr.employee.tree.expense</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="inherit_id" ref="hr.view_employee_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='work_location']" position="after">
|
||||
<field name="expense_manager_id" optional="hide"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="res_users_view_form_preferences" model="ir.ui.view">
|
||||
<field name="name">hr.user.preferences.form.inherit.hr.expense</field>
|
||||
<field name="model">res.users</field>
|
||||
|
||||
@@ -12,6 +12,7 @@ class HrEmployeeBase(models.AbstractModel):
|
||||
|
||||
leave_manager_id = fields.Many2one(
|
||||
'res.users', string='Time Off',
|
||||
compute='_compute_leave_manager', store=True, readonly=False,
|
||||
help="User responsible of leaves approval.")
|
||||
remaining_leaves = fields.Float(
|
||||
compute='_compute_remaining_leaves', string='Remaining Paid Time Off',
|
||||
@@ -119,13 +120,13 @@ class HrEmployeeBase(models.AbstractModel):
|
||||
employee.current_leave_id = leave_data.get(employee.id, {}).get('current_leave_id')
|
||||
employee.is_absent = leave_data.get(employee.id) and leave_data.get(employee.id, {}).get('current_leave_state') not in ['cancel', 'refuse', 'draft']
|
||||
|
||||
@api.onchange('parent_id')
|
||||
def _onchange_parent_id(self):
|
||||
super(HrEmployeeBase, self)._onchange_parent_id()
|
||||
previous_manager = self._origin.parent_id.user_id
|
||||
manager = self.parent_id.user_id
|
||||
if manager and self.leave_manager_id == previous_manager or not self.leave_manager_id:
|
||||
self.leave_manager_id = manager
|
||||
@api.depends('parent_id')
|
||||
def _compute_leave_manager(self):
|
||||
for employee in self:
|
||||
previous_manager = employee._origin.parent_id.user_id
|
||||
manager = employee.parent_id.user_id
|
||||
if manager and employee.leave_manager_id == previous_manager or not employee.leave_manager_id:
|
||||
employee.leave_manager_id = manager
|
||||
|
||||
def _compute_show_leaves(self):
|
||||
show_leaves = self.env['res.users'].has_group('hr_holidays.group_hr_holidays_user')
|
||||
@@ -144,20 +145,7 @@ class HrEmployeeBase(models.AbstractModel):
|
||||
])
|
||||
return [('id', 'in', holidays.mapped('employee_id').ids)]
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
if 'parent_id' in values:
|
||||
manager = self.env['hr.employee'].browse(values['parent_id']).user_id
|
||||
values['leave_manager_id'] = values.get('leave_manager_id', manager.id)
|
||||
return super(HrEmployeeBase, self).create(values)
|
||||
|
||||
def write(self, values):
|
||||
if 'parent_id' in values:
|
||||
manager = self.env['hr.employee'].browse(values['parent_id']).user_id
|
||||
if manager:
|
||||
to_change = self.filtered(lambda e: e.leave_manager_id == e.parent_id.user_id or not e.leave_manager_id)
|
||||
to_change.write({'leave_manager_id': values.get('leave_manager_id', manager.id)})
|
||||
|
||||
res = super(HrEmployeeBase, self).write(values)
|
||||
if 'parent_id' in values or 'department_id' in values:
|
||||
today_date = fields.Datetime.now()
|
||||
|
||||
@@ -182,6 +182,17 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_employee_tree_inherit_leave" model="ir.ui.view">
|
||||
<field name="name">hr.employee.tree.leave</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="inherit_id" ref="hr.view_employee_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='work_location']" position="after">
|
||||
<field name="leave_manager_id" optional="hide"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_employee_public_form_view_inherit" model="ir.ui.view">
|
||||
<field name="name">hr.employee.public.leave.form.inherit</field>
|
||||
<field name="model">hr.employee.public</field>
|
||||
|
||||
@@ -93,45 +93,26 @@ class Applicant(models.Model):
|
||||
_order = "priority desc, id desc"
|
||||
_inherit = ['mail.thread.cc', 'mail.activity.mixin', 'utm.mixin']
|
||||
|
||||
def _default_stage_id(self):
|
||||
if self._context.get('default_job_id'):
|
||||
return self.env['hr.recruitment.stage'].search([
|
||||
'|',
|
||||
('job_ids', '=', False),
|
||||
('job_ids', '=', self._context['default_job_id']),
|
||||
('fold', '=', False)
|
||||
], order='sequence asc', limit=1).id
|
||||
return False
|
||||
|
||||
def _default_company_id(self):
|
||||
company_id = False
|
||||
if self._context.get('default_department_id'):
|
||||
department = self.env['hr.department'].browse(self._context['default_department_id'])
|
||||
company_id = department.company_id.id
|
||||
if not company_id and self.job_id:
|
||||
company_id = self.env['hr.job'].browse(self._context['default_job_id']).company_id.ids
|
||||
if not company_id:
|
||||
company_id = self.env.company
|
||||
return company_id
|
||||
|
||||
name = fields.Char("Subject / Application Name", required=True)
|
||||
active = fields.Boolean("Active", default=True, help="If the active field is set to false, it will allow you to hide the case without removing it.")
|
||||
description = fields.Text("Description")
|
||||
email_from = fields.Char("Email", size=128, help="Applicant email")
|
||||
email_from = fields.Char("Email", size=128, help="Applicant email", compute='_compute_partner_phone_email', store=True, readonly=False)
|
||||
probability = fields.Float("Probability")
|
||||
partner_id = fields.Many2one('res.partner', "Contact", copy=False)
|
||||
create_date = fields.Datetime("Creation Date", readonly=True, index=True)
|
||||
stage_id = fields.Many2one('hr.recruitment.stage', 'Stage', ondelete='restrict', tracking=True,
|
||||
compute='_compute_stage', store=True, readonly=False,
|
||||
domain="['|', ('job_ids', '=', False), ('job_ids', '=', job_id)]",
|
||||
copy=False, index=True,
|
||||
group_expand='_read_group_stage_ids',
|
||||
default=_default_stage_id)
|
||||
group_expand='_read_group_stage_ids')
|
||||
last_stage_id = fields.Many2one('hr.recruitment.stage', "Last Stage",
|
||||
help="Stage of the applicant before being in the current stage. Used for lost cases analysis.")
|
||||
categ_ids = fields.Many2many('hr.applicant.category', string="Tags")
|
||||
company_id = fields.Many2one('res.company', "Company", default=_default_company_id)
|
||||
user_id = fields.Many2one('res.users', "Responsible", tracking=True, default=lambda self: self.env.uid)
|
||||
date_closed = fields.Datetime("Closed", readonly=True, index=True)
|
||||
company_id = fields.Many2one('res.company', "Company", compute='_compute_company', store=True, readonly=False)
|
||||
user_id = fields.Many2one(
|
||||
'res.users', "Responsible", compute='_compute_user',
|
||||
tracking=True, default=lambda self: self.env.uid, store=True, readonly=False)
|
||||
date_closed = fields.Datetime("Closed", compute='_compute_date_closed', store=True, index=True)
|
||||
date_open = fields.Datetime("Assigned", readonly=True, index=True)
|
||||
date_last_stage_update = fields.Datetime("Last Stage Update", index=True, default=fields.Datetime.now)
|
||||
priority = fields.Selection(AVAILABLE_PRIORITIES, "Appreciation", default='0')
|
||||
@@ -142,10 +123,12 @@ class Applicant(models.Model):
|
||||
salary_expected = fields.Float("Expected Salary", group_operator="avg", help="Salary Expected by Applicant")
|
||||
availability = fields.Date("Availability", help="The date at which the applicant will be available to start working")
|
||||
partner_name = fields.Char("Applicant's Name")
|
||||
partner_phone = fields.Char("Phone", size=32)
|
||||
partner_mobile = fields.Char("Mobile", size=32)
|
||||
partner_phone = fields.Char("Phone", size=32, compute='_compute_partner_phone_email', store=True, readonly=False)
|
||||
partner_mobile = fields.Char("Mobile", size=32, compute='_compute_partner_phone_email', store=True, readonly=False)
|
||||
type_id = fields.Many2one('hr.recruitment.degree', "Degree")
|
||||
department_id = fields.Many2one('hr.department', "Department", domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
|
||||
department_id = fields.Many2one(
|
||||
'hr.department', "Department", compute='_compute_department', store=True, readonly=False,
|
||||
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
|
||||
day_open = fields.Float(compute='_compute_day', string="Days to Open", compute_sudo=True)
|
||||
day_close = fields.Float(compute='_compute_day', string="Days to Close", compute_sudo=True)
|
||||
delay_close = fields.Float(compute="_compute_day", string='Delay to Close', readonly=True, group_operator="avg", help="Number of days to close", store=True)
|
||||
@@ -220,38 +203,41 @@ class Applicant(models.Model):
|
||||
stage_ids = stages._search(search_domain, order=order, access_rights_uid=SUPERUSER_ID)
|
||||
return stages.browse(stage_ids)
|
||||
|
||||
@api.onchange('job_id')
|
||||
def onchange_job_id(self):
|
||||
vals = self._onchange_job_id_internal(self.job_id.id)
|
||||
self.department_id = vals['value']['department_id']
|
||||
self.user_id = vals['value']['user_id']
|
||||
self.stage_id = vals['value']['stage_id']
|
||||
@api.depends('job_id', 'department_id')
|
||||
def _compute_company(self):
|
||||
for applicant in self:
|
||||
company_id = False
|
||||
if applicant.department_id:
|
||||
company_id = applicant.department_id.company_id.id
|
||||
if not company_id and applicant.job_id:
|
||||
company_id = applicant.job_id.company_id.id
|
||||
applicant.company_id = company_id or self.env.company.id
|
||||
|
||||
def _onchange_job_id_internal(self, job_id):
|
||||
department_id = False
|
||||
user_id = False
|
||||
company_id = False
|
||||
stage_id = self.stage_id.id or self._context.get('default_stage_id')
|
||||
if job_id:
|
||||
job = self.env['hr.job'].browse(job_id)
|
||||
department_id = job.department_id.id
|
||||
user_id = job.user_id.id
|
||||
company_id = job.company_id.id
|
||||
if not stage_id:
|
||||
stage_ids = self.env['hr.recruitment.stage'].search([
|
||||
'|',
|
||||
('job_ids', '=', False),
|
||||
('job_ids', '=', job.id),
|
||||
('fold', '=', False)
|
||||
], order='sequence asc', limit=1).ids
|
||||
stage_id = stage_ids[0] if stage_ids else False
|
||||
@api.depends('job_id')
|
||||
def _compute_department(self):
|
||||
for applicant in self.filtered(lambda a: a.job_id):
|
||||
applicant.department_id = applicant.job_id.department_id.id
|
||||
|
||||
@api.depends('job_id')
|
||||
def _compute_stage(self):
|
||||
for applicant in self:
|
||||
if applicant.job_id:
|
||||
if not applicant.stage_id:
|
||||
stage_ids = self.env['hr.recruitment.stage'].search([
|
||||
'|',
|
||||
('job_ids', '=', False),
|
||||
('job_ids', '=', applicant.job_id.id),
|
||||
('fold', '=', False)
|
||||
], order='sequence asc', limit=1).ids
|
||||
applicant.stage_id = stage_ids[0] if stage_ids else False
|
||||
else:
|
||||
applicant.stage_id = False
|
||||
|
||||
@api.depends('job_id')
|
||||
def _compute_user(self):
|
||||
for applicant in self.filtered(lambda a: a.job_id):
|
||||
applicant.user_id = applicant.job_id.user_id.id
|
||||
|
||||
return {'value': {
|
||||
'department_id': department_id,
|
||||
'company_id': company_id,
|
||||
'user_id': user_id,
|
||||
'stage_id': stage_id
|
||||
}}
|
||||
|
||||
@api.onchange('email_from')
|
||||
def onchange_email_from(self):
|
||||
@@ -268,39 +254,27 @@ class Applicant(models.Model):
|
||||
if self.partner_id and self.partner_mobile and not self.partner_id.mobile:
|
||||
self.partner_id.mobile = self.partner_mobile
|
||||
|
||||
@api.onchange('partner_id')
|
||||
def onchange_partner_id(self):
|
||||
self.partner_phone = self.partner_id.phone
|
||||
self.partner_mobile = self.partner_id.mobile
|
||||
self.email_from = self.partner_id.email
|
||||
@api.depends('partner_id')
|
||||
def _compute_partner_phone_email(self):
|
||||
for applicant in self:
|
||||
applicant.partner_phone = applicant.partner_id.phone
|
||||
applicant.partner_mobile = applicant.partner_id.mobile
|
||||
applicant.email_from = applicant.partner_id.email
|
||||
|
||||
@api.onchange('stage_id')
|
||||
def onchange_stage_id(self):
|
||||
vals = self._onchange_stage_id_internal(self.stage_id.id)
|
||||
if vals['value'].get('date_closed'):
|
||||
self.date_closed = vals['value']['date_closed']
|
||||
|
||||
def _onchange_stage_id_internal(self, stage_id):
|
||||
if not stage_id:
|
||||
return {'value': {}}
|
||||
stage = self.env['hr.recruitment.stage'].browse(stage_id)
|
||||
if stage.fold:
|
||||
return {'value': {'date_closed': fields.datetime.now()}}
|
||||
return {'value': {'date_closed': False}}
|
||||
@api.depends('stage_id')
|
||||
def _compute_date_closed(self):
|
||||
for applicant in self:
|
||||
if applicant.stage_id and applicant.stage_id.fold:
|
||||
applicant.date_closed = fields.datetime.now()
|
||||
else:
|
||||
applicant.date_closed = False
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('department_id') and not self._context.get('default_department_id'):
|
||||
self = self.with_context(default_department_id=vals.get('department_id'))
|
||||
if vals.get('job_id') or self._context.get('default_job_id'):
|
||||
job_id = vals.get('job_id') or self._context.get('default_job_id')
|
||||
for key, value in self._onchange_job_id_internal(job_id)['value'].items():
|
||||
if key not in vals:
|
||||
vals[key] = value
|
||||
if vals.get('user_id'):
|
||||
vals['date_open'] = fields.Datetime.now()
|
||||
if 'stage_id' in vals:
|
||||
vals.update(self._onchange_stage_id_internal(vals.get('stage_id'))['value'])
|
||||
return super(Applicant, self).create(vals)
|
||||
|
||||
def write(self, vals):
|
||||
@@ -310,7 +284,6 @@ class Applicant(models.Model):
|
||||
# stage_id: track last stage before update
|
||||
if 'stage_id' in vals:
|
||||
vals['date_last_stage_update'] = fields.Datetime.now()
|
||||
vals.update(self._onchange_stage_id_internal(vals.get('stage_id'))['value'])
|
||||
if 'kanban_state' not in vals:
|
||||
vals['kanban_state'] = 'normal'
|
||||
for applicant in self:
|
||||
|
||||
@@ -24,25 +24,25 @@
|
||||
<field name="name">Applicants</field>
|
||||
<field name="model">hr.applicant</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Applicants" decoration-bf="message_needaction==True">
|
||||
<tree string="Applicants" decoration-bf="message_needaction==True" multi_edit="1">
|
||||
<field name="message_needaction" invisible="1"/>
|
||||
<field name="last_stage_id" invisible="1"/>
|
||||
<field name="create_date"/>
|
||||
<field name="create_date" readonly="1"/>
|
||||
<field name="date_last_stage_update" invisible="1"/>
|
||||
<field name="name"/>
|
||||
<field name="partner_name"/>
|
||||
<field name="email_from"/>
|
||||
<field name="partner_phone" widget="phone"/>
|
||||
<field name="name" readonly="1"/>
|
||||
<field name="partner_name" readonly="1"/>
|
||||
<field name="email_from" readonly="1"/>
|
||||
<field name="partner_phone" widget="phone" readonly="1"/>
|
||||
<field name="job_id"/>
|
||||
<field name="stage_id"/>
|
||||
<field name="medium_id"/>
|
||||
<field name="source_id"/>
|
||||
<field name="source_id" readonly="1"/>
|
||||
<field name="priority"/>
|
||||
<field name="type_id" invisible="1"/>
|
||||
<field name="availability" invisible="1"/>
|
||||
<field name="department_id" invisible="context.get('invisible_department', True)"/>
|
||||
<field name="department_id" invisible="context.get('invisible_department', True)" readonly="1"/>
|
||||
<field name="user_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="company_id" groups="base.group_multi_company" readonly="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
@@ -35,7 +35,7 @@ class HrWorkEntry(models.Model):
|
||||
('_work_entry_start_before_end', 'check (date_stop > date_start)', 'Starting time should be before end time.')
|
||||
]
|
||||
|
||||
@api.onchange('state')
|
||||
@api.depends('state')
|
||||
def _compute_conflict(self):
|
||||
for rec in self:
|
||||
rec.conflict = rec.state == 'conflict'
|
||||
|
||||
@@ -72,12 +72,12 @@
|
||||
<field name="name">hr.work.entry.tree</field>
|
||||
<field name="model">hr.work.entry</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="name"/>
|
||||
<field name="work_entry_type_id"/>
|
||||
<field name="duration"/>
|
||||
<tree multi_edit="1">
|
||||
<field name="name" readonly="1"/>
|
||||
<field name="work_entry_type_id" attrs="{'readonly': [('state', '=', 'validated')]}" options="{'no_create': True, 'no_open': True}"/>
|
||||
<field name="duration" readonly="1"/>
|
||||
<field name="state"/>
|
||||
<field name="date_start" string="Beginning"/>
|
||||
<field name="date_start" string="Beginning" readonly="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
Reference in New Issue
Block a user