mirror of
https://gitlab.com/hibou-io/hibou-odoo/suite.git
synced 2025-01-20 12:37:31 +02:00
[WIP] sale_timesheet_manager:
Agile portal time-sheet manager. Allow users to create time lines for assigned tasks and add notes before confirming. Time lines must be confirmed before they are committed. To-do's made for users that have unconfirmed lines that get committed to time-sheets by EOD cron job. (optional)
This commit is contained in:
2
sale_timesheet_manager/__init__.py
Normal file
2
sale_timesheet_manager/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import controllers
|
||||
from . import models
|
||||
23
sale_timesheet_manager/__manifest__.py
Normal file
23
sale_timesheet_manager/__manifest__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# Part of Hibou Suite Professional. See LICENSE_PROFESSIONAL file for full copyright and licensing details.
|
||||
|
||||
{
|
||||
'name': 'Hibou Project Time Manager',
|
||||
'version': '13.0.1.3.0',
|
||||
'category': 'Warehouse',
|
||||
'author': 'Hibou Corp.',
|
||||
'license': 'OPL-1',
|
||||
'website': 'https://hibou.io/',
|
||||
'depends': [
|
||||
'sale_timesheet',
|
||||
'website',
|
||||
],
|
||||
'data': [
|
||||
'security/ir.model.access.csv',
|
||||
# 'views/project_views.xml',
|
||||
'views/time_manager_templates.xml',
|
||||
'views/web_assets.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'application': False,
|
||||
'auto_install': False,
|
||||
}
|
||||
1
sale_timesheet_manager/controllers/__init__.py
Normal file
1
sale_timesheet_manager/controllers/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import portal
|
||||
20
sale_timesheet_manager/controllers/portal.py
Normal file
20
sale_timesheet_manager/controllers/portal.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from odoo import _
|
||||
from odoo.http import Controller, request, route
|
||||
from odoo.addons.portal.controllers.portal import CustomerPortal, pager as portal_pager
|
||||
from odoo.exceptions import AccessError, MissingError
|
||||
from odoo.http import request
|
||||
|
||||
from logging import getLogger as Logs
|
||||
_logger = Logs(__name__)
|
||||
|
||||
|
||||
class SaleTimesheetManager(Controller):
|
||||
@route('/my/task/time/manager', type='http', auth='public', website=True)
|
||||
def portal_my_timesheet_manager(self, **kwargs):
|
||||
user = request.env.user
|
||||
vals = {
|
||||
'user': user,
|
||||
'projects': user._get_tasks_grouped_by_project(),
|
||||
}
|
||||
|
||||
return request.render('sale_timesheet_manager.dashboard', vals)
|
||||
3
sale_timesheet_manager/data/ir_cron.xml
Normal file
3
sale_timesheet_manager/data/ir_cron.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<!-- TODO: Create a daily cron that will force confirm lines daily if setting is enabled in res config -->
|
||||
2
sale_timesheet_manager/models/__init__.py
Normal file
2
sale_timesheet_manager/models/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import project
|
||||
from . import users
|
||||
45
sale_timesheet_manager/models/project.py
Normal file
45
sale_timesheet_manager/models/project.py
Normal file
@@ -0,0 +1,45 @@
|
||||
from odoo import api, fields, models
|
||||
|
||||
from logging import getLogger as Logs
|
||||
_logger = Logs(__name__)
|
||||
|
||||
|
||||
class ProjectTask(models.Model):
|
||||
_inherit = 'project.task'
|
||||
|
||||
time_manager_ids = fields.One2many('project.task.time.manager', 'task_id', string='Uncommitted time entries.')
|
||||
|
||||
|
||||
class ProjectTaskTimeManager(models.Model):
|
||||
_name = 'project.task.time.manager'
|
||||
_description = 'Used to hold arbitrary data as o2m lines until it is committed via user or server action at EOD'
|
||||
|
||||
# Relational Fields
|
||||
task_id = fields.Many2one('project.task', string='Parent Task')
|
||||
time_line_ids = fields.One2many('project.task.time.manager.line', 'time_manager_id')
|
||||
user_id = fields.Many2one('res.user', string='')
|
||||
|
||||
|
||||
class ProjectTaskTimeManagerLine(models.Model):
|
||||
_name = 'project.task.time.manager.line'
|
||||
_description = 'Informational time lines that hold data until committed'
|
||||
|
||||
# Relational Fields
|
||||
time_manager_id = fields.Many2one('project.task.time.manager')
|
||||
user_id = fields.Many2one('res.user', string='Timesheet User')
|
||||
|
||||
# Informational Fields
|
||||
user_confirmed = fields.Boolean('User Confirmed Time')
|
||||
cron_confirmed = fields.Boolean('Cron Confirmed Time')
|
||||
|
||||
date_start = fields.Date('Time Started')
|
||||
date_end = fields.Date('Time Finished')
|
||||
duration = fields.Float('Time Duration', compute='_compute_time_line_duration')
|
||||
|
||||
def _compute_time_line_duration(self):
|
||||
for line in self:
|
||||
if line.date_start and line.date_end:
|
||||
time = line.date_start + line.date_end
|
||||
line.duration = float(time.hours)
|
||||
else:
|
||||
line.duration = 0
|
||||
17
sale_timesheet_manager/models/users.py
Normal file
17
sale_timesheet_manager/models/users.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from odoo import api, fields, models
|
||||
|
||||
from logging import getLogger as Logs
|
||||
_logger = Logs(__name__)
|
||||
|
||||
class ResUsers(models.Model):
|
||||
_inherit = 'res.users'
|
||||
|
||||
@api.model
|
||||
def _get_tasks_grouped_by_project(self):
|
||||
self.ensure_one()
|
||||
res = {}
|
||||
for task in self.env['project.task'].search([('user_id', '=', self.id)]):
|
||||
res.setdefault(task.project_id, []).append(task)
|
||||
_logger.warn('-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-')
|
||||
_logger.warn(res)
|
||||
return res
|
||||
3
sale_timesheet_manager/security/ir.model.access.csv
Normal file
3
sale_timesheet_manager/security/ir.model.access.csv
Normal file
@@ -0,0 +1,3 @@
|
||||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
||||
"manage_project_task_time_manager","manage project time manager","model_project_task_time_manager","base.group_user",1,1,1,1
|
||||
"manage_project_task_time_manager_line","manage project time manager line","model_project_task_time_manager_line","base.group_user",1,1,1,1
|
||||
|
11
sale_timesheet_manager/src/js/sale_time_manager.js
Normal file
11
sale_timesheet_manager/src/js/sale_time_manager.js
Normal file
@@ -0,0 +1,11 @@
|
||||
odoo.define('sale_timesheet_manager.main', function (require) {
|
||||
"use strict";
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
console.log('Sale Time Manager Loaded');
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
6
sale_timesheet_manager/views/project_views.xml
Normal file
6
sale_timesheet_manager/views/project_views.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
|
||||
|
||||
|
||||
</odoo>
|
||||
115
sale_timesheet_manager/views/time_manager_templates.xml
Normal file
115
sale_timesheet_manager/views/time_manager_templates.xml
Normal file
@@ -0,0 +1,115 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
|
||||
<template id="dashboard">
|
||||
<t t-call="portal.portal_layout">
|
||||
|
||||
<div id="dashboard_container">
|
||||
<t t-call="sale_timesheet_manager.assigned_tasks"/>
|
||||
</div>
|
||||
|
||||
</t>
|
||||
|
||||
</template>
|
||||
|
||||
<!-- Main Dashboard -->
|
||||
<template id="assigned_tasks">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 mt-2 mb-4 mb-0">
|
||||
<div class="card">
|
||||
<h3 class="m-3">Assigned Tasks</h3>
|
||||
<!-- TODO: Add quick-search on-type filtering for list -->
|
||||
<div class="position-absolute mr-4" style="right: 0; top: 50%; transform: translateY(-50%);">
|
||||
<a href="#" class="btn float-right">
|
||||
<i class="fa fa-search text-muted"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="task_container" class="card-container d-inline-block w-100"
|
||||
style="overflow-x: scroll; white-space: nowrap;">
|
||||
<t t-foreach="projects" t-as="project">
|
||||
<t t-set="tasks" t-value="projects[project]"/>
|
||||
<span class="task-container"
|
||||
style="width: 320px; display: inline-block; position: relative; vertical-align: top;">
|
||||
<div>
|
||||
<div>
|
||||
<div class="ml-4">
|
||||
<strong class="card-title">
|
||||
<span t-esc="project.name"/>
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<t t-foreach="tasks" t-as="task">
|
||||
<div>
|
||||
<div>
|
||||
<div class="task-card card m-2 p-1" t-att-data-record-id="task.id">
|
||||
<!-- Task Title and ID -->
|
||||
<a href="#" t-att-title="task.name" class="card-header"
|
||||
style="overflow: hidden;">
|
||||
<strong class="card-title">
|
||||
<span t-esc="task.name"/>
|
||||
</strong>
|
||||
</a>
|
||||
<!-- Conditionally colored star system -->
|
||||
<t t-if="task.priority">
|
||||
<t t-set="priority" t-value="task.priority"/>
|
||||
<span class="task-priority-stars float-right"
|
||||
style="position: absolute; left: 50%; bottom: 5px; transform: translate(-50%, -50%);">
|
||||
<t t-foreach="range(int(priority))" t-as="star">
|
||||
<t t-if="star == 0">
|
||||
<i class="fa fa-star text-muted"></i>
|
||||
</t>
|
||||
<t t-if="star == 1">
|
||||
<i class="fa fa-star text-primary"></i>
|
||||
</t>
|
||||
<t t-if="star >= 2">
|
||||
<i class="fa fa-star text-warning"></i>
|
||||
</t>
|
||||
</t>
|
||||
</span>
|
||||
</t>
|
||||
|
||||
|
||||
<!-- Task Actions -->
|
||||
<div class="card-body text-center">
|
||||
<span>
|
||||
<a href="#" class="btn m-1">
|
||||
<i class="fa fa-2x fa-play-circle text-success"></i>
|
||||
</a>
|
||||
<a href="#" class="btn btn-warning m-1 d-none">
|
||||
<i class="fa fa-2x fa-pause-circle"></i>
|
||||
</a>
|
||||
<a href="#" class="btn btn-danger m-1 d-none">
|
||||
<i class="fa fa-2x fa-stop-circle"></i>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Task info -->
|
||||
<div class="card-footer">
|
||||
<a href="#" class="text-info">
|
||||
<i class="fa fa-list-ul mr-1"></i>
|
||||
Entries
|
||||
</a>
|
||||
<span class="float-right text-muted">
|
||||
H
|
||||
<t t-esc="task.id"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</span>
|
||||
</t>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
10
sale_timesheet_manager/views/web_assets.xml
Normal file
10
sale_timesheet_manager/views/web_assets.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<odoo>
|
||||
|
||||
<template id="web_assets_frontend" inherit_id="website.assets_frontend">
|
||||
<xpath expr="//script[last()]" position="after">
|
||||
<script type="text/javascript" src="/sale_timesheet_manager/static/src/js/sale_time_manager.js"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user