Files
odoo_source/addons/hr_timesheet/models/project.py
T
Adrian Torres 3f4f77fd9d [REF] *: adapt code to new related default behaviour
This commit adapts the business code to changes introduced by
the parent commit in order to keep the same behaviour as before.

All readonly=False fields will have to be checked afterwards to confirm
that the business case requires write access to the source field.
2018-09-27 12:10:23 +02:00

156 lines
7.7 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError
class Project(models.Model):
_inherit = "project.project"
allow_timesheets = fields.Boolean("Allow timesheets", default=True)
analytic_account_id = fields.Many2one('account.analytic.account', string="Analytic Account", copy=False, ondelete='set null',
help="Link this project to an analytic account if you need financial management on projects. "
"It enables you to connect projects with budgets, planning, cost and revenue analysis, timesheets on projects, etc.")
@api.onchange('partner_id')
def _onchange_partner_id(self):
domain = []
if self.partner_id:
domain = [('partner_id', '=', self.partner_id.id)]
return {'domain': {'analytic_account_id': domain}}
@api.onchange('analytic_account_id')
def _onchange_analytic_account(self):
if not self.analytic_account_id and self._origin:
self.allow_timesheets = False
@api.constrains('allow_timesheets', 'analytic_account_id')
def _check_allow_timesheet(self):
for project in self:
if project.allow_timesheets and not project.analytic_account_id:
raise ValidationError(_('To allow timesheet, your project %s should have an analytic account set.' % (project.name,)))
@api.model
def name_create(self, name):
""" Create a project with name_create should generate analytic account creation """
values = {
'name': name,
'allow_timesheets': True,
}
return self.create(values).name_get()[0]
@api.model
def create(self, values):
""" Create an analytic account if project allow timesheet and don't provide one
Note: create it before calling super() to avoid raising the ValidationError from _check_allow_timesheet
"""
allow_timesheets = values['allow_timesheets'] if 'allow_timesheets' in values else self.default_get(['allow_timesheets'])['allow_timesheets']
if allow_timesheets and not values.get('analytic_account_id'):
analytic_account = self.env['account.analytic.account'].create({
'name': values.get('name', _('Unknown Analytic Account')),
'company_id': values.get('company_id', self.env.user.company_id.id),
'partner_id': values.get('partner_id'),
'active': True,
})
values['analytic_account_id'] = analytic_account.id
return super(Project, self).create(values)
@api.multi
def write(self, values):
# create the AA for project still allowing timesheet
if values.get('allow_timesheets'):
for project in self:
if not project.analytic_account_id and not values.get('analytic_account_id'):
project._create_analytic_account()
result = super(Project, self).write(values)
return result
@api.multi
def unlink(self):
""" Delete the empty related analytic account """
analytic_accounts_to_delete = self.env['account.analytic.account']
for project in self:
if project.analytic_account_id and not project.analytic_account_id.line_ids:
analytic_accounts_to_delete |= project.analytic_account_id
result = super(Project, self).unlink()
analytic_accounts_to_delete.unlink()
return result
@api.model
def _init_data_analytic_account(self):
self.search([('analytic_account_id', '=', False), ('allow_timesheets', '=', True)])._create_analytic_account()
def _create_analytic_account(self):
for project in self:
analytic_account = self.env['account.analytic.account'].create({
'name': project.name,
'company_id': project.company_id.id,
'partner_id': project.partner_id.id,
'active': True,
})
project.write({'analytic_account_id': analytic_account.id})
class Task(models.Model):
_inherit = "project.task"
analytic_account_active = fields.Boolean("Analytic Account", related='project_id.analytic_account_id.active', readonly=True)
allow_timesheets = fields.Boolean("Allow timesheets", related='project_id.allow_timesheets', help="Timesheets can be logged on this task.", readonly=False)
remaining_hours = fields.Float("Remaining Hours", compute='_compute_remaining_hours', store=True, readonly=True, help="Total remaining time, can be re-estimated periodically by the assignee of the task.")
effective_hours = fields.Float("Hours Spent", compute='_compute_effective_hours', compute_sudo=True, store=True, help="Computed using the sum of the task work done.")
total_hours_spent = fields.Float("Total Hours", compute='_compute_total_hours_spent', store=True, help="Computed as: Time Spent + Sub-tasks Hours.")
progress = fields.Float("Progress", compute='_compute_progress_hours', store=True, group_operator="avg", help="Display progress of current task.")
subtask_effective_hours = fields.Float("Sub-tasks Hours Spent", compute='_compute_subtask_effective_hours', store=True, help="Sum of actually spent hours on the subtask(s)", oldname='children_hours')
timesheet_ids = fields.One2many('account.analytic.line', 'task_id', 'Timesheets')
@api.depends('timesheet_ids.unit_amount')
def _compute_effective_hours(self):
for task in self:
task.effective_hours = round(sum(task.timesheet_ids.mapped('unit_amount')), 2)
@api.depends('effective_hours', 'subtask_effective_hours', 'planned_hours')
def _compute_progress_hours(self):
for task in self:
if (task.planned_hours > 0.0):
task_total_hours = task.effective_hours + task.subtask_effective_hours
if task_total_hours > task.planned_hours:
task.progress = 100
else:
task.progress = round(100.0 * task_total_hours / task.planned_hours, 2)
else:
task.progress = 0.0
@api.depends('effective_hours', 'subtask_effective_hours', 'planned_hours')
def _compute_remaining_hours(self):
for task in self:
task.remaining_hours = task.planned_hours - task.effective_hours - task.subtask_effective_hours
@api.depends('effective_hours', 'subtask_effective_hours')
def _compute_total_hours_spent(self):
for task in self:
task.total_hours_spent = task.effective_hours + task.subtask_effective_hours
@api.depends('child_ids.effective_hours', 'child_ids.subtask_effective_hours')
def _compute_subtask_effective_hours(self):
for task in self:
task.subtask_effective_hours = sum(child_task.effective_hours + child_task.subtask_effective_hours for child_task in task.child_ids)
# ---------------------------------------------------------
# ORM
# ---------------------------------------------------------
@api.multi
def write(self, values):
# a timesheet must have an analytic account (and a project)
if 'project_id' in values and self and not values.get('project_id'):
raise UserError(_('This task must be part of a project because they some timesheets are linked to it.'))
return super(Task, self).write(values)
@api.model
def _fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
""" Set the correct label for `unit_amount`, depending on company UoM """
result = super(Task, self)._fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
result['arch'] = self.env['account.analytic.line']._apply_timesheet_label(result['arch'])
return result