Browse Source

Jun 20 : [FIX] Bug Fixed 'project_task_timer'

pull/257/head
AjmalCybro 2 years ago
parent
commit
c6a4f572a5
  1. 3
      project_task_timer/__manifest__.py
  2. 40
      project_task_timer/models/project_task_timer.py
  3. 146
      project_task_timer/static/src/js/timer.js
  4. 7
      project_task_timer/static/src/xml/timer.xml
  5. 3
      project_task_timer/views/project_task_timer_view.xml

3
project_task_timer/__manifest__.py

@ -26,13 +26,14 @@
'author': 'Cybrosys Techno Solutions',
'company': 'Cybrosys Techno Solutions',
'website': "http://www.cybrosys.com",
'depends': ['base', 'project', 'hr_timesheet','web'],
'depends': ['base', 'project', 'hr_timesheet'],
'data': [
'views/project_task_timer_view.xml',
],
'assets': {
'web.assets_backend': [
'project_task_timer/static/src/js/timer.js',
'project_task_timer/static/src/xml/timer.xml',
]},
'images': ['static/description/banner.png'],
'license': 'AGPL-3',

40
project_task_timer/models/project_task_timer.py

@ -26,8 +26,7 @@ class ProjectTaskTimeSheet(models.Model):
date_start = fields.Datetime(string='Start Date')
date_end = fields.Datetime(string='End Date', readonly=1)
timer_duration = fields.Float(invisible=1,
string='Time Duration (Minutes)=')
timer_duration = fields.Float(invisible=1, string='Time Duration (Minutes)=')
class ProjectTaskTimer(models.Model):
@ -41,15 +40,12 @@ class ProjectTaskTimer(models.Model):
'Real Duration', compute='_compute_duration', store=True)
def _compute_duration(self):
"""Compute Duration"""
self
def _compute_is_user_working(self):
""" Checks whether the current user is working """
for order in self:
if order.timesheet_ids.filtered(
lambda x: (x.user_id.id == self.env.user.id) and (
not x.date_end)):
if order.timesheet_ids.filtered(lambda x: (x.user_id.id == self.env.user.id) and (not x.date_end)):
order.is_user_working = True
else:
order.is_user_working = False
@ -73,15 +69,23 @@ class ProjectTaskTimer(models.Model):
time_line_obj = self.env['account.analytic.line']
domain = [('task_id', 'in', self.ids), ('date_end', '=', False)]
for time_line in time_line_obj.search(domain):
time_line.write({'date_end': fields.Datetime.now()})
if time_line.date_start and time_line.date_end:
diff = fields.Datetime.from_string(
time_line.date_end) - fields.Datetime.from_string(
time_line.date_start).replace(microsecond=0)
time_line.timer_duration = round(
diff.total_seconds() / 60.0, 2)
time_line.unit_amount = round(
diff.total_seconds() / (60.0 * 60.0), 2)
else:
time_line.unit_amount = 0.0
time_line.timer_duration = 0.0
if time_line.date_start:
time_line.write({'date_end': fields.Datetime.now()})
diff = fields.Datetime.from_string(time_line.date_end) - fields.Datetime.from_string(time_line.date_start)
time_line.timer_duration = round(diff.total_seconds() / 60.0, 2)
time_line.unit_amount = round(diff.total_seconds() / (60.0 * 60.0), 2)
def get_working_duration(self):
"""Get the additional duration for 'open times'
i.e. productivity lines with no date_end."""
self.ensure_one()
duration = 0
for time in \
self.timesheet_ids.filtered(lambda time: not time.date_end):
if type(time.date_start) != datetime:
time.date_start = datetime.now()
duration = 0
else:
duration += \
(datetime.now() - time.date_start).total_seconds() / 60
return duration

146
project_task_timer/static/src/js/timer.js

@ -1,82 +1,86 @@
odoo.define('project_task_timer.timer', function (require) {
"use strict";
var AbstractField = require('web.AbstractField');
var core = require('web.core');
var field_registry = require('web.field_registry');
var time = require('web.time');
var FieldManagerMixin = require('web.FieldManagerMixin');
/** @odoo-module **/
var _t = core._t;
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
import { parseFloatTime } from "@web/views/fields/parsers";
import { useInputField } from "@web/views/fields/input_field_hook";
// $(document).on('click','#timer', function(){
// if ($(this).hasClass('btn-secondary'))
// { $(this).removeClass('btn-secondary');
// $(this).addClass('btn-primary');
// }
// });
const { Component, useState, onWillUpdateProps, onWillStart, onWillDestroy } = owl;
/**
* Custom field type for displaying a time counter based on data from the account.analytic.line model.
* Inherits from the AbstractField class.
*/
function formatMinutes(value) {
if (value === false) {
return "";
}
const isNegative = value < 0;
if (isNegative) {
value = Math.abs(value);
}
let min = Math.floor(value);
let sec = Math.floor((value % 1) * 60);
sec = `${sec}`.padStart(2, "0");
min = `${min}`.padStart(2, "0");
return `${isNegative ? "-" : ""}${min}:${sec}`;
}
var TimeCounter = AbstractField.extend({
export class TaskTimer extends Component {
setup() {
this.orm = useService('orm');
this.state = useState({
// duration is expected to be given in minutes
duration:
this.props.value !== undefined ? this.props.value : this.props.record.data.duration,
});
useInputField({
getValue: () => this.durationFormatted,
refName: "numpadDecimal",
parse: (v) => parseFloatTime(v),
});
willStart: function () {
var self = this;
var def = this._rpc({
model: 'account.analytic.line',
method: 'search_read',
domain: [['task_id', '=', this.res_id],
['user_id', '=', self.record.context['uid']]],
}).then(function (result) {
if (self.mode === 'readonly') {
var currentDate = new Date();
self.duration = 0;
_.each(result, function (data) {
self.duration += data.date_end ?
self._getDateDifference(data.date_start, data.date_end):
self._getDateDifference(time.auto_str_to_date(data.date_start), currentDate);
});
this.ongoing =
this.props.ongoing !== undefined
? this.props.ongoing
: this.props.record.data.is_user_working;
onWillStart(async () => {
if(this.props.ongoing === undefined && !this.props.record.model.useSampleModel && this.props.record.data.task_timer) {
const additionalDuration = await this.orm.call('project.task', 'get_working_duration', [this.props.record.resId]);
this.state.duration += additionalDuration;
}
if (this.ongoing) {
this._runTimer();
}
});
return $.when(this._super.apply(this, arguments), def);
},
destroy: function () {
this._super.apply(this, arguments);
clearTimeout(this.timer);
},
isSet: function () {
return true;
},
_getDateDifference: function (dateStart, dateEnd) {
return moment(dateEnd).diff(moment(dateStart));
},
onWillUpdateProps((nextProps) => {
const newOngoing =
"ongoing" in nextProps
? nextProps.ongoing
: "record" in nextProps && nextProps.record.data.is_user_working;
const rerun = !this.ongoing && newOngoing;
this.ongoing = newOngoing;
if (rerun) {
this.state.duration = nextProps.value;
this._runTimer();
}
});
onWillDestroy(() => clearTimeout(this.timer));
}
_render: function () {
this._startTimeCounter();
},
get durationFormatted() {
return formatMinutes(this.state.duration);
}
/**
* Starts a timer to update the field every second if the user is working.
* Increments the duration by one second each time the timer runs.
* Updates the field with the new duration in HH:mm:ss format.
*/
_startTimeCounter: function () {
var self = this;
clearTimeout(this.timer);
if (this.record.data.is_user_working) {
this.timer = setTimeout(function () {
self.duration += 1000;
self._startTimeCounter();
}, 1000);
} else {
clearTimeout(this.timer);
}
this.$el.html($('<span>' + moment.utc(this.duration).format("HH:mm:ss") + '</span>'));
},
});
field_registry.add('timesheet_uoms', TimeCounter);
});
_runTimer() {
this.timer = setTimeout(() => {
if (this.ongoing) {
this.state.duration += 1 / 60;
this._runTimer();
}
}, 1000);
}
}
TaskTimer.supportedTypes = ["float"];
TaskTimer.template = "TaskTimerTemplate";
registry.category("fields").add("task_timer", TaskTimer);
registry.category("formatters").add("task_timer", formatMinutes);

7
project_task_timer/static/src/xml/timer.xml

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="TaskTimerTemplate" owl="1">
<span t-if="props.readonly" t-esc="durationFormatted"/>
<input t-else="" t-att-id="props.id" t-ref="numpadDecimal" t-att-placeholder="props.placeholder" inputmode="numeric" class="o_input" />
</t>
</templates>

3
project_task_timer/views/project_task_timer_view.xml

@ -26,7 +26,6 @@
<field name="model">project.task</field>
<field name="inherit_id" ref="project_task_timer.project_task_timer_inherit_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='timesheet_ids']/tree/field[@name='unit_amount']" position="before">
<field name="date_start" required="1"/>
<field name="date_end"/>
@ -37,7 +36,7 @@
<label for="duration"/>
<div>
<button style="pointer-events: none;" class="oe_inline label label-default">
<field name="duration" id="duration" widget="timesheet_uoms" style="color: red;" />
<field name="duration" id="duration" widget="task_timer" style="color: red;" />
</button>
</div>
</xpath>

Loading…
Cancel
Save