summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorjbm-odoo <jbm@odoo.com>2020-01-24 10:32:46 +0000
committerYannick Tivisse <yti@odoo.com>2020-01-28 14:16:21 +0000
commit41a465bc869a96b7a4e2b49a691360827019b0ea (patch)
tree4128dd65027b0b3ee36fc42a61c5820e5df7694f /addons
parent9d98c43581e2579f43b35541b43264866dede5a5 (diff)
[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>
Diffstat (limited to 'addons')
-rw-r--r--addons/hr_contract/models/hr_contract.py27
-rw-r--r--addons/hr_work_entry/views/hr_work_entry_views.xml10
-rw-r--r--addons/resource/models/resource.py20
3 files changed, 42 insertions, 15 deletions
diff --git a/addons/hr_contract/models/hr_contract.py b/addons/hr_contract/models/hr_contract.py
index 4b931f9e50c..b3b59023949 100644
--- a/addons/hr_contract/models/hr_contract.py
+++ b/addons/hr_contract/models/hr_contract.py
@@ -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:
diff --git a/addons/hr_work_entry/views/hr_work_entry_views.xml b/addons/hr_work_entry/views/hr_work_entry_views.xml
index 3fefedddf6a..b04e84e644f 100644
--- a/addons/hr_work_entry/views/hr_work_entry_views.xml
+++ b/addons/hr_work_entry/views/hr_work_entry_views.xml
@@ -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', '&gt;=', (context_today()).strftime('%Y-%m-01')),
+ ('date_start', '&lt;', (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>
diff --git a/addons/resource/models/resource.py b/addons/resource/models/resource.py
index 24977ae0284..d24820b1c7d 100644
--- a/addons/resource/models/resource.py
+++ b/addons/resource/models/resource.py
@@ -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