92 lines
4.3 KiB
Python
92 lines
4.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
from odoo import api, models, fields, tools, _
|
|
from odoo.exceptions import UserError, ValidationError
|
|
|
|
|
|
class ProjectProject(models.Model):
|
|
_inherit = "project.project"
|
|
|
|
budget_id = fields.One2many('crossovered.budget', 'project_id', string="Project Budget")
|
|
project_cost = fields.Float('Cost',compute="_get_project_costs",help="Project Cost to date")
|
|
project_hours_cost = fields.Float('Man-Hours Cost',compute="_get_project_costs",help="Project Man Hours Cost to date")
|
|
project_total_cost = fields.Float('Total Cost',compute="_get_project_costs",help="Project Cost + Project Man Hours Cost")
|
|
gross_amount = fields.Float('Gross Margin',compute="_get_project_costs",help="Billed amount - Total Cost")
|
|
ready_budget = fields.Boolean('project budget is ready',compute="_get_budget_status")
|
|
estimated_hours = fields.Float("Budget Hours",compute="_get_project_hours",copy=False)
|
|
|
|
|
|
def _get_project_hours(self):
|
|
for rec in self:
|
|
estimated_hours = 0
|
|
for budget in rec.budget_id:
|
|
estimated_hours = sum(budget.hour_line_ids.mapped("qty"))
|
|
rec.estimated_hours = estimated_hours
|
|
|
|
# @api.depends('budget_id','budget_id.crossovered_budget_line','budget_id.crossovered_budget_line.practical_amount','total_invoiced_amount')
|
|
def _get_project_costs(self):
|
|
for rec in self:
|
|
project_cost = 0.0
|
|
project_hours_cost = 0.0
|
|
project_total_cost = 0.0
|
|
gross_amount = 0.0
|
|
for budget in rec.budget_id:
|
|
project_hours_cost = abs(sum(budget.mapped('crossovered_budget_line').filtered(lambda l:l.general_budget_id.is_timesheet_hours).mapped('practical_amount')))
|
|
project_cost = abs(sum(budget.mapped('crossovered_budget_line').filtered(lambda l:not l.general_budget_id.is_timesheet_hours).mapped('practical_amount')))
|
|
project_total_cost = project_hours_cost + project_cost
|
|
rec.project_cost = project_cost
|
|
rec.project_hours_cost = project_hours_cost
|
|
rec.project_total_cost = project_total_cost
|
|
rec.gross_amount = rec.total_invoiced_amount - rec.project_total_cost
|
|
|
|
def _get_budget_status(self):
|
|
for rec in self:
|
|
ready_budget = False
|
|
for budget in rec.budget_id:
|
|
if budget.state == 'done':
|
|
ready_budget = True
|
|
rec.ready_budget = ready_budget
|
|
|
|
|
|
def _check_hour_budget(self, to_add_hours):
|
|
for rec in self:
|
|
for budget in rec.budget_id:
|
|
for line in budget.hour_line_ids:
|
|
add_amount = to_add_hours * line.amount
|
|
if add_amount > line.project_remaining_amount:
|
|
raise ValidationError(
|
|
_("There is No enough Man-Hours in project budget %s , please contact your manager") % (
|
|
rec.display_name))
|
|
|
|
def _check_project_budget(self):
|
|
for rec in self:
|
|
if not rec.budget_id:
|
|
raise ValidationError(_("There is no budget created yet for this project."))
|
|
for budget in rec.budget_id:
|
|
if budget.state != 'done':
|
|
raise ValidationError(_("The Budget must approved from accounting first!"))
|
|
budget_hours = sum(budget.hour_line_ids.mapped("qty"))
|
|
project_hours = sum(rec.project_phase_ids.mapped("estimated_hours"))
|
|
if project_hours > budget_hours:
|
|
raise ValidationError(_("Project Allocated hours must not be more than Man-Hours in budget!"))
|
|
|
|
def action_done(self):
|
|
for record in self:
|
|
record._check_project_budget()
|
|
return super().action_done()
|
|
|
|
def action_view_budget(self):
|
|
self.ensure_one()
|
|
action_window = {
|
|
"type": "ir.actions.act_window",
|
|
"res_model": "crossovered.budget",
|
|
"name": "Budget",
|
|
'view_type': 'form',
|
|
'view_mode': 'tree,form',
|
|
"context": {"default_project_id": self.id,"create": False,"edit": False,
|
|
'form_view_ref': 'project_budget.project_budget_custom_form',
|
|
'tree_view_ref': 'project_budget.project_budget_view_tree'},
|
|
"domain": [('project_id', '=', self.id)]
|
|
}
|
|
return action_window
|
|
|