You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
265 lines
12 KiB
265 lines
12 KiB
from odoo import models, fields, api, _
|
|
from odoo.addons.beesdoo_shift.models.cooperative_status import add_days_delta
|
|
from odoo.exceptions import ValidationError, UserError
|
|
|
|
from datetime import timedelta, datetime
|
|
import logging
|
|
|
|
|
|
class CooperativeStatus(models.Model):
|
|
_inherit = 'cooperative.status'
|
|
_period = 28
|
|
|
|
######################################################
|
|
# #
|
|
# Override of method to define status behavior #
|
|
# #
|
|
######################################################
|
|
|
|
future_alert_date = fields.Date(compute='_compute_future_alert_date')
|
|
next_countdown_date = fields.Date(compute='_compute_next_countdown_date')
|
|
|
|
@api.depends('today', 'irregular_start_date', 'sr', 'holiday_start_time',
|
|
'holiday_end_time', 'temporary_exempt_start_date',
|
|
'temporary_exempt_end_date')
|
|
def _compute_future_alert_date(self):
|
|
"""Compute date before which the worker is up to date"""
|
|
for rec in self:
|
|
# Only for irregular worker
|
|
if rec.working_mode != 'irregular' and not rec.irregular_start_date:
|
|
rec.future_alert_date = False
|
|
# Alert start time already set
|
|
elif rec.alert_start_time:
|
|
rec.future_alert_date = False
|
|
# Holidays are not set properly
|
|
elif bool(rec.holiday_start_time) != bool(rec.holiday_end_time):
|
|
rec.future_alert_date = False
|
|
# Exemption have not a start and end time
|
|
elif (bool(rec.temporary_exempt_start_date)
|
|
!= bool(rec.temporary_exempt_end_date)):
|
|
rec.future_alert_date = False
|
|
else:
|
|
date = rec.today
|
|
counter = rec.sr
|
|
# Simulate the countdown
|
|
while counter > 0:
|
|
date = self._next_countdown_date(
|
|
rec.irregular_start_date, date
|
|
)
|
|
# Check holidays
|
|
if (
|
|
rec.holiday_start_time and rec.holiday_end_time
|
|
and date >= rec.holiday_start_time
|
|
and date <= rec.holiday_end_time
|
|
):
|
|
date = add_days_delta(date, 1)
|
|
continue
|
|
# Check temporary exemption
|
|
if (
|
|
rec.temporary_exempt_start_date
|
|
and rec.temporary_exempt_end_date
|
|
and date >= rec.temporary_exempt_start_date
|
|
and date <= rec.temporary_exempt_end_date
|
|
):
|
|
date = add_days_delta(date, 1)
|
|
continue
|
|
# Otherwise
|
|
date = add_days_delta(date, 1)
|
|
counter -= 1
|
|
rec.future_alert_date = self._next_countdown_date(
|
|
rec.irregular_start_date, date
|
|
)
|
|
|
|
@api.depends('today', 'irregular_start_date', 'holiday_start_time',
|
|
'holiday_end_time', 'temporary_exempt_start_date',
|
|
'temporary_exempt_end_date')
|
|
def _compute_next_countdown_date(self):
|
|
"""
|
|
Compute the following countdown date. This date is the date when
|
|
the worker will see his counter changed du to the cron. This
|
|
date is like the birthday date of the worker that occurred each
|
|
PERIOD.
|
|
"""
|
|
for rec in self:
|
|
# Only for irregular worker
|
|
if rec.working_mode != 'irregular' and not rec.irregular_start_date:
|
|
rec.next_countdown_date = False
|
|
# Holidays are not set properly
|
|
elif bool(rec.holiday_start_time) != bool(rec.holiday_end_time):
|
|
rec.next_countdown_date = False
|
|
# Exemption have not a start and end time
|
|
elif (bool(rec.temporary_exempt_start_date)
|
|
!= bool(rec.temporary_exempt_end_date)):
|
|
rec.next_countdown_date = False
|
|
else:
|
|
date = rec.today
|
|
next_countdown_date = False
|
|
while not next_countdown_date:
|
|
date = self._next_countdown_date(
|
|
rec.irregular_start_date, date
|
|
)
|
|
# Check holidays
|
|
if (
|
|
rec.holiday_start_time and rec.holiday_end_time
|
|
and date >= rec.holiday_start_time
|
|
and date <= rec.holiday_end_time
|
|
):
|
|
date = add_days_delta(date, 1)
|
|
continue
|
|
# Check temporary exemption
|
|
if (
|
|
rec.temporary_exempt_start_date
|
|
and rec.temporary_exempt_end_date
|
|
and date >= rec.temporary_exempt_start_date
|
|
and date <= rec.temporary_exempt_end_date
|
|
):
|
|
date = add_days_delta(date, 1)
|
|
continue
|
|
# Otherwise
|
|
next_countdown_date = date
|
|
rec.next_countdown_date = next_countdown_date
|
|
|
|
#####################################
|
|
# Status Change implementation #
|
|
#####################################
|
|
def _get_regular_status(self):
|
|
self.ensure_one()
|
|
counter_unsubscribe = int(self.env['ir.config_parameter'].sudo().get_param('regular_counter_to_unsubscribe', -4))
|
|
alert_delay = int(self.env['ir.config_parameter'].sudo().get_param('alert_delay', 28))
|
|
grace_delay = int(self.env['ir.config_parameter'].sudo().get_param('default_grace_delay', 10))
|
|
ok = self.sr >= 0 and self.sc >= 0
|
|
grace_delay = grace_delay + self.time_extension
|
|
|
|
if (self.sr + self.sc) <= counter_unsubscribe or self.unsubscribed:
|
|
return 'unsubscribed'
|
|
# Check if exempted. Exempt end date is not required.
|
|
if self.temporary_exempt_start_date and self.today >= self.temporary_exempt_start_date:
|
|
if not self.temporary_exempt_end_date or self.today <= self.temporary_exempt_end_date:
|
|
return 'exempted'
|
|
|
|
# Transition to alert sr < 0 or stay in alert sr < 0 or sc < 0 and thus alert time is defined
|
|
if not ok and self.alert_start_time and self.extension_start_time and self.today <= add_days_delta(self.extension_start_time, grace_delay):
|
|
return 'extension'
|
|
if not ok and self.alert_start_time and self.extension_start_time and self.today > add_days_delta(self.extension_start_time, grace_delay):
|
|
return 'suspended'
|
|
if not ok and self.alert_start_time and self.today > add_days_delta(self.alert_start_time, alert_delay):
|
|
return 'suspended'
|
|
if (self.sr < 0) or (not ok and self.alert_start_time):
|
|
return 'alert'
|
|
|
|
if (
|
|
self.holiday_start_time
|
|
and self.holiday_end_time
|
|
and self.today >= self.holiday_start_time
|
|
and self.today <= self.holiday_end_time
|
|
):
|
|
|
|
return 'holiday'
|
|
elif ok or (not self.alert_start_time and self.sr >= 0):
|
|
return 'ok'
|
|
|
|
def _get_irregular_status(self):
|
|
self.ensure_one()
|
|
counter_unsubscribe = int(self.env['ir.config_parameter'].sudo().get_param('irregular_counter_to_unsubscribe', -3))
|
|
alert_delay = int(self.env['ir.config_parameter'].sudo().get_param('alert_delay', 28))
|
|
grace_delay = int(self.env['ir.config_parameter'].sudo().get_param('default_grace_delay', 10))
|
|
ok = self.sr >= 0
|
|
grace_delay = grace_delay + self.time_extension
|
|
if self.sr <= counter_unsubscribe or self.unsubscribed:
|
|
return 'unsubscribed'
|
|
# Check if exempted. Exempt end date is not required.
|
|
elif self.temporary_exempt_start_date and self.today >= self.temporary_exempt_start_date:
|
|
if not self.temporary_exempt_end_date or self.today <= self.temporary_exempt_end_date:
|
|
return 'exempted'
|
|
# Transition to alert sr < 0 or stay in alert sr < 0 or sc < 0 and thus alert time is defined
|
|
elif not ok and self.alert_start_time and self.extension_start_time and self.today <= add_days_delta(self.extension_start_time, grace_delay):
|
|
return 'extension'
|
|
elif not ok and self.alert_start_time and self.extension_start_time and self.today > add_days_delta(self.extension_start_time, grace_delay):
|
|
return 'suspended'
|
|
elif not ok and self.alert_start_time and self.today > add_days_delta(self.alert_start_time, alert_delay):
|
|
return 'suspended'
|
|
elif (self.sr < 0) or (not ok and self.alert_start_time):
|
|
return 'alert'
|
|
|
|
elif (
|
|
self.holiday_start_time
|
|
and self.holiday_end_time
|
|
and self.today >= self.holiday_start_time
|
|
and self.today <= self.holiday_end_time
|
|
):
|
|
return 'holiday'
|
|
elif ok or (not self.alert_start_time and self.sr >= 0):
|
|
return 'ok'
|
|
|
|
def _state_change(self, new_state):
|
|
self.ensure_one()
|
|
if new_state == 'alert':
|
|
self.write({'alert_start_time': self.today, 'extension_start_time': False, 'time_extension': 0})
|
|
if new_state == 'ok':
|
|
data = {'extension_start_time': False, 'time_extension': 0}
|
|
data['alert_start_time'] = False
|
|
self.write(data)
|
|
if new_state == 'unsubscribed' or new_state == 'resigning':
|
|
# Remove worker from task_templates
|
|
self.cooperator_id.sudo().write(
|
|
{'subscribed_shift_ids': [(5, 0, 0)]})
|
|
# Remove worker from supercoop in task_templates
|
|
task_tpls = self.env['beesdoo.shift.template'].search(
|
|
[('super_coop_id', 'in', self.cooperator_id.user_ids.ids)]
|
|
)
|
|
task_tpls.write({'super_coop_id': False})
|
|
# Remove worker for future tasks (remove also supercoop)
|
|
self.env['beesdoo.shift.shift'].sudo().unsubscribe_from_today(
|
|
[self.cooperator_id.id], now=fields.Datetime.now()
|
|
)
|
|
|
|
def _change_counter(self, data):
|
|
"""
|
|
Call when a shift state is changed
|
|
use data generated by _get_counter_date_state_change
|
|
"""
|
|
self.sc += data.get('sc', 0)
|
|
self.sr += data.get('sr', 0)
|
|
self.irregular_absence_counter += data.get('irregular_absence_counter', 0)
|
|
self.irregular_absence_date = data.get('irregular_absence_date', False)
|
|
|
|
###############################################
|
|
###### Irregular Cron implementation ##########
|
|
###############################################
|
|
|
|
def _get_irregular_worker_domain(self, **kwargs):
|
|
today = kwargs.get("today") or self.today
|
|
return ['&',
|
|
'&',
|
|
'&',
|
|
('status', 'not in', ['unsubscribed', 'exempted']),
|
|
('working_mode', '=', 'irregular'),
|
|
('irregular_start_date', '!=', False),
|
|
'|',
|
|
'|', ('holiday_start_time', '=', False), ('holiday_end_time', '=', False),
|
|
'|', ('holiday_start_time', '>', today), ('holiday_end_time', '<', today),
|
|
]
|
|
|
|
def _change_irregular_counter(self):
|
|
if self.sr > 0:
|
|
self.sr -= 1
|
|
elif self.alert_start_time:
|
|
self.sr -= 1
|
|
else:
|
|
self.sr -= 2
|
|
|
|
##################################
|
|
# Internal Implementation #
|
|
##################################
|
|
def _next_countdown_date(self, irregular_start_date, today=False):
|
|
"""
|
|
Return the next countdown date given irregular_start_date and
|
|
today dates.
|
|
This does not take holiday and other status into account.
|
|
"""
|
|
today = today or fields.Date.today()
|
|
|
|
delta = (today - irregular_start_date).days
|
|
if not delta % self._period:
|
|
return today
|
|
return add_days_delta(today, self._period - (delta % self._period))
|