[FIX] hr_work_entry: Closed contract
When a contract is closed, set the date of the day. In the contract cron, ensure that all closed contracts have an end date if it is followed by a new contract. Add multi-edit on work_entry list closes odoo/odoo#44118 Taskid: 2180263 X-original-commit: 0b5d8ce756eac904a040ca700f44ea860daefcb4 Related: odoo/enterprise#7991 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This commit is contained in:
committed by
Yannick Tivisse
parent
9d98c43581
commit
41a465bc86
@@ -19,9 +19,9 @@ class Contract(models.Model):
|
||||
employee_id = fields.Many2one('hr.employee', string='Employee', tracking=True, domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
|
||||
department_id = fields.Many2one('hr.department', domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", string="Department")
|
||||
job_id = fields.Many2one('hr.job', domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]", string='Job Position')
|
||||
date_start = fields.Date('Start Date', required=True, default=fields.Date.today,
|
||||
date_start = fields.Date('Start Date', required=True, default=fields.Date.today, tracking=True,
|
||||
help="Start date of the contract.")
|
||||
date_end = fields.Date('End Date',
|
||||
date_end = fields.Date('End Date', tracking=True,
|
||||
help="End date of the contract (if it's a fixed-term contract).")
|
||||
trial_date_end = fields.Date('End of Trial Period',
|
||||
help="End date of the trial period (if there is one).")
|
||||
@@ -133,6 +133,26 @@ class Contract(models.Model):
|
||||
self.search([('state', '=', 'draft'), ('kanban_state', '=', 'done'), ('date_start', '<=', fields.Date.to_string(date.today())),]).write({
|
||||
'state': 'open'
|
||||
})
|
||||
|
||||
contract_ids = self.search([('date_end', '=', False), ('state', '=', 'close'), ('employee_id', '!=', False)])
|
||||
# Ensure all closed contract followed by a new contract have a end date.
|
||||
# If closed contract has no closed date, the work entries will be generated for an unlimited period.
|
||||
for contract in contract_ids:
|
||||
next_contract = self.search([
|
||||
('employee_id', '=', contract.employee_id.id),
|
||||
('state', 'not in', ['cancel', 'new']),
|
||||
('date_start', '>', contract.date_start)
|
||||
], order="date_start asc", limit=1)
|
||||
if next_contract:
|
||||
contract.date_end = next_contract.date_start - relativedelta(days=1)
|
||||
continue
|
||||
next_contract = self.search([
|
||||
('employee_id', '=', contract.employee_id.id),
|
||||
('date_start', '>', contract.date_start)
|
||||
], order="date_start asc", limit=1)
|
||||
if next_contract:
|
||||
contract.date_end = next_contract.date_start - relativedelta(days=1)
|
||||
|
||||
return True
|
||||
|
||||
def _assign_open_contract(self):
|
||||
@@ -143,6 +163,9 @@ class Contract(models.Model):
|
||||
res = super(Contract, self).write(vals)
|
||||
if vals.get('state') == 'open':
|
||||
self._assign_open_contract()
|
||||
if vals.get('state') == 'close':
|
||||
for contract in self.filtered(lambda c: not c.date_end):
|
||||
contract.date_end = max(date.today(), contract.date_start)
|
||||
|
||||
calendar = vals.get('resource_calendar_id')
|
||||
if calendar:
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<field name="arch" type="xml">
|
||||
<form string="Work Entry" >
|
||||
<header>
|
||||
<field name="state" widget="statusbar" options="{'clickable': '1'}"/>
|
||||
<field name="state" widget="statusbar" options="{'clickable': '1'}" statusbar_visible="draft,validated,conflict"/>
|
||||
</header>
|
||||
<sheet>
|
||||
<div class="oe_title">
|
||||
@@ -73,8 +73,8 @@
|
||||
<field name="model">hr.work.entry</field>
|
||||
<field name="arch" type="xml">
|
||||
<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="name"/>
|
||||
<field name="work_entry_type_id" options="{'no_create': True, 'no_open': True}"/>
|
||||
<field name="duration" readonly="1"/>
|
||||
<field name="state"/>
|
||||
<field name="date_start" string="Beginning" readonly="1"/>
|
||||
@@ -93,9 +93,13 @@
|
||||
<filter name="work_entries_error" string="Conflicting" domain="[('state', '=', 'conflict')]"/>
|
||||
<separator/>
|
||||
<filter name="date_filter" string="Date" date="date_start"/>
|
||||
<filter name="current_month" string="Current Month" domain="[
|
||||
('date_stop', '>=', (context_today()).strftime('%Y-%m-01')),
|
||||
('date_start', '<', (context_today() + relativedelta(months=1)).strftime('%Y-%m-01'))]"/>
|
||||
<separator/>
|
||||
<filter name="group_employee" string="Employee" context="{'group_by': 'employee_id'}"/>
|
||||
<filter name="group_work_entry_type" string="Type" context="{'group_by': 'work_entry_type_id'}"/>
|
||||
<filter name="group_start_date" string="Start Date" context="{'group_by': 'date_start'}"/>
|
||||
<separator/>
|
||||
<filter name="archived" string="Archived" domain="[('active', '=', False)]"/>
|
||||
</search>
|
||||
|
||||
@@ -316,9 +316,9 @@ class ResourceCalendar(models.Model):
|
||||
# --------------------------------------------------
|
||||
# Computation API
|
||||
# --------------------------------------------------
|
||||
def _attendance_intervals(self, start_dt, end_dt, resource=None, domain=None):
|
||||
def _attendance_intervals(self, start_dt, end_dt, resource=None, domain=None, tz=None):
|
||||
""" Return the attendance intervals in the given datetime range.
|
||||
The returned intervals are expressed in the resource's timezone.
|
||||
The returned intervals are expressed in specified tz or in the resource's timezone.
|
||||
"""
|
||||
assert start_dt.tzinfo and end_dt.tzinfo
|
||||
combine = datetime.combine
|
||||
@@ -331,8 +331,8 @@ class ResourceCalendar(models.Model):
|
||||
('display_type', '=', False),
|
||||
]])
|
||||
|
||||
# express all dates and times in the resource's timezone
|
||||
tz = timezone((resource or self).tz)
|
||||
# express all dates and times in specified tz or in the resource's timezone
|
||||
tz = tz if tz else timezone((resource or self).tz)
|
||||
start_dt = start_dt.astimezone(tz)
|
||||
end_dt = end_dt.astimezone(tz)
|
||||
|
||||
@@ -366,9 +366,9 @@ class ResourceCalendar(models.Model):
|
||||
|
||||
return Intervals(result)
|
||||
|
||||
def _leave_intervals(self, start_dt, end_dt, resource=None, domain=None):
|
||||
def _leave_intervals(self, start_dt, end_dt, resource=None, domain=None, tz=None):
|
||||
""" Return the leave intervals in the given datetime range.
|
||||
The returned intervals are expressed in the calendar's timezone.
|
||||
The returned intervals are expressed in specified tz or in the calendar's timezone.
|
||||
"""
|
||||
assert start_dt.tzinfo and end_dt.tzinfo
|
||||
self.ensure_one()
|
||||
@@ -385,7 +385,7 @@ class ResourceCalendar(models.Model):
|
||||
]
|
||||
|
||||
# retrieve leave intervals in (start_dt, end_dt)
|
||||
tz = timezone((resource or self).tz)
|
||||
tz = tz if tz else timezone((resource or self).tz)
|
||||
start_dt = start_dt.astimezone(tz)
|
||||
end_dt = end_dt.astimezone(tz)
|
||||
result = []
|
||||
@@ -396,10 +396,10 @@ class ResourceCalendar(models.Model):
|
||||
|
||||
return Intervals(result)
|
||||
|
||||
def _work_intervals(self, start_dt, end_dt, resource=None, domain=None):
|
||||
def _work_intervals(self, start_dt, end_dt, resource=None, domain=None, tz=None):
|
||||
""" Return the effective work intervals between the given datetimes. """
|
||||
return (self._attendance_intervals(start_dt, end_dt, resource) -
|
||||
self._leave_intervals(start_dt, end_dt, resource, domain))
|
||||
return (self._attendance_intervals(start_dt, end_dt, resource, tz=tz) -
|
||||
self._leave_intervals(start_dt, end_dt, resource, domain, tz=tz))
|
||||
|
||||
# --------------------------------------------------
|
||||
# Private Methods / Helpers
|
||||
|
||||
Reference in New Issue
Block a user