odex25_standard/odex25_project/project_budget/models/project.py

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