151 lines
5.3 KiB
Python
151 lines
5.3 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import models, fields, api, _
|
|
|
|
|
|
|
|
class TimerMixin(models.AbstractModel):
|
|
_name = 'timer.mixin'
|
|
_description = 'Timer Mixin'
|
|
|
|
timer_start = fields.Datetime(related='user_timer_id.timer_start', export_string_translation=False)
|
|
timer_pause = fields.Datetime(related='user_timer_id.timer_pause', export_string_translation=False)
|
|
is_timer_running = fields.Boolean(related='user_timer_id.is_timer_running', search="_search_is_timer_running", export_string_translation=False)
|
|
user_timer_id = fields.One2many('timer.timer', compute='_compute_user_timer_id', search='_search_user_timer_id', export_string_translation=False)
|
|
|
|
def _search_is_timer_running(self, operator, value):
|
|
if operator != 'in':
|
|
return NotImplemented
|
|
|
|
running_timer_query = self.env['timer.timer']._search([
|
|
('timer_start', '!=', False),
|
|
('timer_pause', '=', False),
|
|
('res_model', '=', self._name),
|
|
])
|
|
|
|
return [('id', 'in', running_timer_query.subselect('res_id'))]
|
|
|
|
def _search_user_timer_id(self, operator, value):
|
|
timer_query = self.env['timer.timer']._search([
|
|
('id', operator, value),
|
|
('user_id', '=', self.env.user.id),
|
|
('res_model', '=', self._name),
|
|
])
|
|
return [('id', 'in', timer_query.subselect('res_id'))]
|
|
|
|
@api.depends_context('uid')
|
|
def _compute_user_timer_id(self):
|
|
""" Get the timers according these conditions
|
|
:user_id is is the current user
|
|
:res_id is the current record
|
|
:res_model is the current model
|
|
limit=1 by security but the search should never have more than one record
|
|
"""
|
|
timer_read_group = self.env['timer.timer']._read_group(
|
|
domain=[
|
|
('user_id', '=', self.env.user.id),
|
|
('res_id', 'in', self.ids),
|
|
('res_model', '=', self._name),
|
|
],
|
|
groupby=['res_id'],
|
|
aggregates=['id:array_agg'])
|
|
timer_by_model = dict(timer_read_group)
|
|
for record in self:
|
|
record.user_timer_id = timer_by_model.get(record.id, False)
|
|
|
|
@api.model
|
|
def _get_user_timers(self):
|
|
# Return user's timers. Can have multiple timers if some are in pause
|
|
return self.env['timer.timer'].search([('user_id', '=', self.env.user.id)])
|
|
|
|
def unlink(self):
|
|
if not self:
|
|
return True
|
|
timers = self._get_timers_from_other_users()
|
|
if timers:
|
|
self.check_access('unlink')
|
|
timers.sudo().unlink()
|
|
return super().unlink()
|
|
|
|
def _get_timer_vals(self):
|
|
return {
|
|
'timer_start': False,
|
|
'timer_pause': False,
|
|
'is_timer_running': False,
|
|
'res_model': self._name,
|
|
'res_id': self.id,
|
|
'user_id': self.env.user.id,
|
|
}
|
|
|
|
def _create_timer(self, vals=None):
|
|
if not vals:
|
|
vals = {}
|
|
return self.env['timer.timer'].create({
|
|
**self._get_timer_vals(),
|
|
**vals,
|
|
})
|
|
|
|
def action_timer_start(self):
|
|
""" Start the timer of the current record
|
|
First, if a timer is running, stop or pause it
|
|
If there isn't a timer for the current record, create one then start it
|
|
Otherwise, resume or start it
|
|
"""
|
|
self.ensure_one()
|
|
self.sudo()._stop_timer_in_progress()
|
|
timer = self.user_timer_id
|
|
if not timer:
|
|
timer = self._create_timer()
|
|
timer.action_timer_start()
|
|
else:
|
|
# Check if it is in pause then resume it or start it
|
|
if timer.timer_pause:
|
|
timer.action_timer_resume()
|
|
else:
|
|
timer.action_timer_start()
|
|
|
|
def action_timer_stop(self):
|
|
""" Stop the timer of the current record
|
|
Unlink the timer, it's useless to keep the stopped timer.
|
|
A new timer can be create if needed
|
|
Return the amount of minutes spent
|
|
"""
|
|
self.ensure_one()
|
|
timer = self.user_timer_id
|
|
minutes_spent = timer.action_timer_stop()
|
|
timer.unlink()
|
|
return minutes_spent
|
|
|
|
def action_timer_pause(self):
|
|
self.ensure_one()
|
|
timer = self.user_timer_id
|
|
timer.action_timer_pause()
|
|
|
|
def action_timer_resume(self):
|
|
self.ensure_one()
|
|
self._stop_timer_in_progress()
|
|
timer = self.user_timer_id
|
|
timer.action_timer_resume()
|
|
|
|
def _get_timers_from_other_users(self):
|
|
return self.env['timer.timer'].search([
|
|
('res_model', '=', self._name),
|
|
('res_id', 'in', self.ids),
|
|
('user_id', '!=', self.env.user.id),
|
|
])
|
|
|
|
def _action_interrupt_user_timers(self):
|
|
# Interruption is the action called when the timer is stoped by the start of another one
|
|
self.action_timer_pause()
|
|
|
|
def _stop_timer_in_progress(self):
|
|
"""
|
|
Cancel the timer in progress if there is one
|
|
Each model can interrupt the running timer in a specific way
|
|
By setting it in pause or stop by example
|
|
"""
|
|
timers = self._get_user_timers().filtered(lambda t: t.is_timer_running)
|
|
for timer in timers:
|
|
model = self.env[timer.res_model].browse(timer.res_id)
|
|
model._action_interrupt_user_timers()
|