diff options
| author | jbm-odoo <jbm@odoo.com> | 2020-01-24 10:32:46 +0000 |
|---|---|---|
| committer | Yannick Tivisse <yti@odoo.com> | 2020-01-28 14:16:21 +0000 |
| commit | 41a465bc869a96b7a4e2b49a691360827019b0ea (patch) | |
| tree | 4128dd65027b0b3ee36fc42a61c5820e5df7694f /addons | |
| parent | 9d98c43581e2579f43b35541b43264866dede5a5 (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.py | 27 | ||||
| -rw-r--r-- | addons/hr_work_entry/views/hr_work_entry_views.xml | 10 | ||||
| -rw-r--r-- | addons/resource/models/resource.py | 20 |
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', '>=', (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> 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 |
