14 changed files with 377 additions and 0 deletions
@ -0,0 +1,23 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<http://www.cybrosys.com>). |
|||
# Author: Jesni Banu(<http://www.cybrosys.com>) |
|||
# you can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# It is forbidden to publish, distribute, sublicense, or sell copies |
|||
# of the Software or modified copies of the Software. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import models |
@ -0,0 +1,43 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<http://www.cybrosys.com>). |
|||
# Author: Jesni Banu(<http://www.cybrosys.com>) |
|||
# you can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# It is forbidden to publish, distribute, sublicense, or sell copies |
|||
# of the Software or modified copies of the Software. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
{ |
|||
'name': 'Project Task Timer', |
|||
'version': '10.0.1.0', |
|||
'summary': """Task Timer With Start & Stop""", |
|||
'description': """"This module helps you to track time sheet in project automatically.""", |
|||
'category': 'Project', |
|||
'author': 'Cybrosys Techno Solutions', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'website': "http://www.cybrosys.com", |
|||
'depends': ['base', 'project', 'hr_timesheet'], |
|||
'data': [ |
|||
'views/project_task_timer_view.xml', |
|||
'views/project_timer_static.xml', |
|||
], |
|||
'images': ['static/description/banner.jpg'], |
|||
'license': 'AGPL-3', |
|||
'demo': [], |
|||
'installable': True, |
|||
'auto_install': False, |
|||
'application': False, |
|||
} |
@ -0,0 +1,23 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<http://www.cybrosys.com>). |
|||
# Author: Jesni Banu(<http://www.cybrosys.com>) |
|||
# you can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# It is forbidden to publish, distribute, sublicense, or sell copies |
|||
# of the Software or modified copies of the Software. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import project_task_timer |
@ -0,0 +1,91 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<http://www.cybrosys.com>). |
|||
# Author: Jesni Banu(<http://www.cybrosys.com>) |
|||
# you can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# It is forbidden to publish, distribute, sublicense, or sell copies |
|||
# of the Software or modified copies of the Software. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
from datetime import datetime |
|||
from odoo import models, fields, api |
|||
|
|||
|
|||
class ProjectTaskTimeSheet(models.Model): |
|||
_inherit = 'account.analytic.line' |
|||
|
|||
date_start = fields.Datetime(string='Start Date') |
|||
date_end = fields.Datetime(string='End Date', readonly=1) |
|||
|
|||
|
|||
class ProjectTaskTimer(models.Model): |
|||
_inherit = 'project.task' |
|||
|
|||
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)): |
|||
order.is_user_working = True |
|||
else: |
|||
order.is_user_working = False |
|||
|
|||
@api.multi |
|||
@api.depends('timesheet_ids.unit_amount') |
|||
def _compute_duration(self): |
|||
self.duration = 0 |
|||
for each in self: |
|||
each.duration = sum(each.timesheet_ids.mapped('unit_amount')) |
|||
|
|||
@api.multi |
|||
def toggle_start(self): |
|||
for record in self: |
|||
record.task_timer = not record.task_timer |
|||
if self.task_timer: |
|||
self.write({'is_user_working': True}) |
|||
time_line = self.env['account.analytic.line'] |
|||
for time_sheet in self: |
|||
time_line.create({ |
|||
'name': self.env.user.name + ': ' + time_sheet.name, |
|||
'task_id': time_sheet.id, |
|||
'user_id': self.env.user.id, |
|||
'project_id': time_sheet.project_id.id, |
|||
'date_start': datetime.now(), |
|||
}) |
|||
else: |
|||
self.write({'is_user_working': False}) |
|||
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_end: |
|||
diff = fields.Datetime.from_string(time_line.date_end) - fields.Datetime.from_string( |
|||
time_line.date_start) |
|||
time_line.unit_amount = round(diff.total_seconds() / 60.0, 2) |
|||
else: |
|||
time_line.unit_amount = 0.0 |
|||
|
|||
task_timer = fields.Boolean() |
|||
is_user_working = fields.Boolean( |
|||
'Is Current User Working', compute='_compute_is_user_working', |
|||
help="Technical field indicating whether the current user is working. ") |
|||
duration = fields.Float( |
|||
'Real Duration', compute='_compute_duration', |
|||
readonly=True, store=True) |
|||
|
|||
|
|||
|
|||
|
|||
|
After Width: | Height: | Size: 108 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 34 KiB |
@ -0,0 +1,87 @@ |
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan">Project Task Timer</h2> |
|||
<h3 class="oe_slogan">Task Timer with Start & Stop</h3> |
|||
<h4 class="oe_slogan" style="font-size: 23px;">Author : Cybrosys Techno Solutions , www.cybrosys.com</h4> |
|||
<div> |
|||
<h4><p>Features:</p></h4> |
|||
<ul> |
|||
<li style="list-style:none !important;"><span style="color:green;"> ☑</span> Timer in Task.</li> |
|||
<li style="list-style:none !important;"><span style="color:green;"> ☑</span> Automatic Time sheet Calculation.</li> |
|||
</ul> |
|||
</div> |
|||
<p class="oe_mt32"> |
|||
You have a smart button to start & stop your task. When you start your task it will automatically makes |
|||
a time sheet entry for that task with starting time. When you toggle it to pause it's end date will be update |
|||
and duration will calculate automatically. |
|||
</p> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h3 class="oe_slogan">Timer in Task</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<p class="oe_mt32"> |
|||
Project -> Search -> Task <br> |
|||
Here you can a toggle button to start and stop your task. |
|||
</p> |
|||
</div> |
|||
<div class="oe_span12"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img style="border:10px solid white;" class="oe_picture oe_screenshot" src="timer1.png"> |
|||
</div> |
|||
</div> |
|||
<div class="oe_span12"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img style="border:10px solid white;" class="oe_picture oe_screenshot" src="timer2.png"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h3 class="oe_slogan">Automatic Time sheet Calculation</h3> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_span12"> |
|||
<p class="oe_mt32"> |
|||
Here you can see the Automatic time sheet entries. |
|||
</p> |
|||
</div> |
|||
<div class="oe_span12"> |
|||
<div class="oe_row_img oe_centered"> |
|||
<img style="border:10px solid white;" class="oe_picture oe_screenshot" src="timer3.png"> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<h2 class="oe_slogan" style="margin-top:20px;" >Need Any Help?</h2> |
|||
<div class="oe_slogan" style="margin-top:10px !important;"> |
|||
<div> |
|||
<a class="btn btn-primary btn-lg mt8" |
|||
style="color: #FFFFFF !important;border-radius: 0;" href="https://www.cybrosys.com"><i |
|||
class="fa fa-envelope"></i> Email </a> <a |
|||
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" |
|||
href="https://www.cybrosys.com/contact/"><i |
|||
class="fa fa-phone"></i> Contact Us </a> <a |
|||
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" |
|||
href="https://www.cybrosys.com/odoo-customization-and-installation/"><i |
|||
class="fa fa-check-square"></i> Request Customization </a> |
|||
</div> |
|||
<br> |
|||
<img src="cybro_logo.png" style="width: 190px; margin-bottom: 20px;" class="center-block"> |
|||
<div> |
|||
<a href="https://twitter.com/cybrosys" target="_blank"><i class="fa fa-2x fa-twitter" style="color:white;background: #00a0d1;width:35px;"></i></a></td> |
|||
<a href="https://www.linkedin.com/company/cybrosys-technologies-pvt-ltd" target="_blank"><i class="fa fa-2x fa-linkedin" style="color:white;background: #31a3d6;width:35px;padding-left: 3px;"></i></a></td> |
|||
<a href="https://www.facebook.com/cybrosystechnologies" target="_blank"><i class="fa fa-2x fa-facebook" style="color:white;background: #3b5998;width:35px;padding-left: 8px;"></i></a></td> |
|||
<a href="https://plus.google.com/106641282743045431892/about" target="_blank"><i class="fa fa-2x fa-google-plus" style="color:white;background: #c53c2c;width:35px;padding-left: 3px;"></i></a></td> |
|||
<a href="https://in.pinterest.com/cybrosys" target="_blank"><i class="fa fa-2x fa-pinterest" style="color:white;background: #ac0f18;width:35px;padding-left: 3px;"></i></a></td> |
|||
</div> |
|||
</div> |
|||
</section> |
After Width: | Height: | Size: 89 KiB |
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 96 KiB |
@ -0,0 +1,57 @@ |
|||
odoo.define('timer_widget.timer', function (require) { |
|||
"use strict"; |
|||
|
|||
var core = require('web.core'); |
|||
var common = require('web.form_common'); |
|||
var Model = require('web.Model'); |
|||
var time = require('web.time'); |
|||
var utils = require('web.utils'); |
|||
|
|||
var _t = core._t; |
|||
|
|||
var TimeCounter = common.AbstractField.extend(common.ReinitializeFieldMixin, { |
|||
start: function() { |
|||
this._super(); |
|||
var self = this; |
|||
this.field_manager.on("view_content_has_changed", this, function () { |
|||
self.render_value(); |
|||
}); |
|||
}, |
|||
start_time_counter: function(){ |
|||
var self = this; |
|||
clearTimeout(this.timer); |
|||
if (this.field_manager.datarecord.is_user_working) { |
|||
this.duration += 1000; |
|||
this.timer = setTimeout(function() { |
|||
self.start_time_counter(); |
|||
}, 1000); |
|||
} else { |
|||
clearTimeout(this.timer); |
|||
} |
|||
this.$el.html($('<span>' + moment.utc(this.duration).format("HH:mm:ss") + '</span>')); |
|||
}, |
|||
render_value: function() { |
|||
this._super.apply(this, arguments); |
|||
var self = this; |
|||
this.duration; |
|||
var productivity_domain = [['task_id', '=', this.field_manager.datarecord.id], ['user_id', '=', self.session.uid]]; |
|||
new Model('account.analytic.line').call('search_read', [productivity_domain, []]).then(function(result) { |
|||
if (self.get("effective_readonly")) { |
|||
self.$el.removeClass('o_form_field_empty'); |
|||
var current_date = new Date(); |
|||
self.duration = 0; |
|||
_.each(result, function(data) { |
|||
self.duration += data.date_end ? self.get_date_difference(data.date_start, data.date_end) : self.get_date_difference(time.auto_str_to_date(data.date_start), current_date); |
|||
}); |
|||
self.start_time_counter(); |
|||
} |
|||
}); |
|||
}, |
|||
get_date_difference: function(date_start, date_deadline) { |
|||
var difference = moment(date_deadline).diff(moment(date_start)); |
|||
return moment.duration(difference); |
|||
}, |
|||
}); |
|||
|
|||
core.form_widget_registry.add('time_counter', TimeCounter); |
|||
}); |
@ -0,0 +1,45 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data> |
|||
<record id="project_task_timer_inherit_view" model="ir.ui.view"> |
|||
<field name="name">project task timer</field> |
|||
<field name="model">project.task</field> |
|||
<field name="inherit_id" ref="project.view_task_form2"/> |
|||
<field name="arch" type="xml"> |
|||
<div name="button_box" position="inside"> |
|||
<button name="toggle_start" type="object" |
|||
class="oe_stat_button" icon="fa-clock-o"> |
|||
<field name="task_timer" widget="boolean_button" |
|||
options='{"terminology": { |
|||
"string_true": "Started", |
|||
"hover_true": "Pause", |
|||
"string_false": "Timer", |
|||
"hover_false": "Start" |
|||
}}'/> |
|||
</button> |
|||
</div> |
|||
<field name="progress" position="after"> |
|||
<field name="is_user_working" invisible="1"/> |
|||
<label for="duration"/> |
|||
<div> |
|||
<button style="pointer-events: none;" class="oe_inline label label-default"> |
|||
<field name="duration" widget="time_counter"/> |
|||
</button> |
|||
</div> |
|||
</field> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="project_task_timer_inherit_view1" model="ir.ui.view"> |
|||
<field name="name">project task timer1</field> |
|||
<field name="model">project.task</field> |
|||
<field name="inherit_id" ref="hr_timesheet.view_task_form2_inherited"/> |
|||
<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"/> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,8 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<odoo> |
|||
<template id="assets_backend1" name="web_widget_color assets1" inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<script type="text/javascript" src="/project_task_timer/static/src/js/timer.js"></script> |
|||
</xpath> |
|||
</template> |
|||
</odoo> |
Loading…
Reference in new issue