Tower: upload tk_construction_management 18.0.2.0.8 (was 18.0.2.0.8, via marketplace)
This commit is contained in:
230
addons/tk_construction_management/models/budget.py
Normal file
230
addons/tk_construction_management/models/budget.py
Normal file
@@ -0,0 +1,230 @@
|
||||
from odoo import api, fields, models, _
|
||||
|
||||
|
||||
class SubProjectBudget(models.Model):
|
||||
_name = 'sub.project.budget'
|
||||
_description = "Sub Project Budget"
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
|
||||
name = fields.Char(string="Title")
|
||||
progress = fields.Float(string="Budget Utilization(%)", compute="compute_used_budget")
|
||||
total_budget_amount = fields.Monetary(string="Total Budget Amount", compute="compute_used_budget")
|
||||
utilization_amount = fields.Monetary(string="Budget Utilization", compute="compute_used_budget")
|
||||
start_date = fields.Date(string="Start Date")
|
||||
end_date = fields.Date(string="End Date")
|
||||
site_id = fields.Many2one('tk.construction.site', string="Project")
|
||||
sub_project_id = fields.Many2one('tk.construction.project', string="Sub Project")
|
||||
responsible_id = fields.Many2one('res.users', default=lambda self: self.env.user and self.env.user.id or False,
|
||||
string="Responsible")
|
||||
company_id = fields.Many2one('res.company', string="Company", default=lambda self: self.env.company)
|
||||
currency_id = fields.Many2one('res.currency', related='company_id.currency_id', string='Currency')
|
||||
status = fields.Selection([('draft', 'Draft'), ('waiting_approval', 'Waiting Approval'), ('approved', 'Approved'),
|
||||
('in_progress', 'In Progress'), ('complete', 'Complete'), ('cancel', 'Cancel'),
|
||||
('reject', 'Reject')], default='draft')
|
||||
budget_count = fields.Integer(string="Budget Line Count", compute="compute_count")
|
||||
reject_reason = fields.Text(string="Reject Reason")
|
||||
budget_line_ids = fields.One2many('project.budget', 'sub_project_budget_id')
|
||||
|
||||
def compute_count(self):
|
||||
for rec in self:
|
||||
rec.budget_count = self.env['project.budget'].search_count([('sub_project_budget_id', '=', rec.id)])
|
||||
|
||||
def action_view_budget_line(self):
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': _('Budget'),
|
||||
'res_model': 'project.budget',
|
||||
'domain': [('sub_project_budget_id', '=', self.id)],
|
||||
'context': {'default_sub_project_budget_id': self.id},
|
||||
'view_mode': 'list,kanban,form',
|
||||
'target': 'current'
|
||||
}
|
||||
|
||||
def action_department_approval(self):
|
||||
self.status = 'waiting_approval'
|
||||
|
||||
def action_approve_budget(self):
|
||||
self.status = 'approved'
|
||||
|
||||
def action_reject_budget(self):
|
||||
self.status = 'reject'
|
||||
|
||||
def action_complete_budget(self):
|
||||
self.status = 'complete'
|
||||
|
||||
def action_cancel_budget(self):
|
||||
self.status = 'cancel'
|
||||
|
||||
def action_reset_draft_budget(self):
|
||||
self.status = 'draft'
|
||||
|
||||
@api.depends('budget_line_ids', 'budget_line_ids.budget', 'budget_line_ids.remaining_budget')
|
||||
def compute_used_budget(self):
|
||||
for rec in self:
|
||||
utilize_budget = 0.0
|
||||
total_budget_amount = 0.0
|
||||
remaining_budget_amount = 0.0
|
||||
for data in rec.budget_line_ids:
|
||||
total_budget_amount = total_budget_amount + data.budget
|
||||
remaining_budget_amount = remaining_budget_amount + data.remaining_budget
|
||||
utilize_budget = 100 - (
|
||||
(remaining_budget_amount * 100 / total_budget_amount) if total_budget_amount > 0 else 100)
|
||||
rec.progress = round(utilize_budget, 1)
|
||||
rec.total_budget_amount = total_budget_amount
|
||||
rec.utilization_amount = total_budget_amount - remaining_budget_amount
|
||||
|
||||
|
||||
class ProjectBudget(models.Model):
|
||||
_name = 'project.budget'
|
||||
_description = "Project Budget"
|
||||
_rec_name = 'job_type_id'
|
||||
|
||||
company_id = fields.Many2one('res.company', string="Company", default=lambda self: self.env.company)
|
||||
currency_id = fields.Many2one('res.currency', related='company_id.currency_id', string='Currency')
|
||||
sub_project_budget_id = fields.Many2one('sub.project.budget', string="Sub Project Budget")
|
||||
project_id = fields.Many2one(related="sub_project_budget_id.sub_project_id", string="Project")
|
||||
site_id = fields.Many2one(related="project_id.construction_site_id", string="Site")
|
||||
job_type_id = fields.Many2one('job.type', string="Work Type")
|
||||
sub_category_id = fields.Many2one('job.sub.category', string="Work Sub Type")
|
||||
boq_qty = fields.Float(string="BOQ Qty")
|
||||
additional_qty = fields.Float(string="Add. Qty", help="Additional Qty")
|
||||
total_qty = fields.Float(string="Total Qty.", compute="compute_total_qty")
|
||||
rate_analysis_id = fields.Many2one('rate.analysis', string="Rate Analysis")
|
||||
price_per_qty = fields.Monetary(string="Price / Qty", compute="compute_rate_analysis_info", store=True)
|
||||
untaxed_amount = fields.Monetary(string="Untaxed Amount", compute="compute_rate_analysis_info", store=True)
|
||||
tax_amount = fields.Monetary(string="Tax Amount", compute="compute_rate_analysis_info", store=True)
|
||||
budget = fields.Monetary(string="Total Budget Amount", compute="compute_rate_analysis_info", store=True)
|
||||
# Spent
|
||||
material_spent = fields.Monetary(string="Material Spent", compute="_compute_budget_calculation")
|
||||
equipment_spent = fields.Monetary(string="Equipment Spent", compute="_compute_budget_calculation")
|
||||
labour_spent = fields.Monetary(string="Labour Spent", compute="_compute_budget_calculation")
|
||||
overhead_spent = fields.Monetary(string="Overhead Spent", compute="_compute_budget_calculation")
|
||||
remaining_budget = fields.Monetary(string="Remaining Budget", compute="_compute_budget_calculation")
|
||||
|
||||
# Spent in Percentage
|
||||
total_spent = fields.Float(string="Utilization(%)", compute="_compute_budget_calculation")
|
||||
boq_used_qty = fields.Float(string="Used Qty", compute="_compute_budget_calculation")
|
||||
|
||||
@api.depends('boq_qty', 'additional_qty')
|
||||
def compute_total_qty(self):
|
||||
for rec in self:
|
||||
rec.total_qty = rec.boq_qty + rec.additional_qty
|
||||
|
||||
@api.depends('rate_analysis_id', 'rate_analysis_id.total_amount', 'rate_analysis_id.untaxed_amount',
|
||||
'rate_analysis_id.tax_amount', 'total_qty')
|
||||
def compute_rate_analysis_info(self):
|
||||
for rec in self:
|
||||
untaxed_amount = 0.0
|
||||
tax_amount = 0.0
|
||||
price_per_qty = 0.0
|
||||
budget = 0.0
|
||||
if rec.rate_analysis_id:
|
||||
price_per_qty = rec.rate_analysis_id.total_amount
|
||||
untaxed_amount = rec.rate_analysis_id.untaxed_amount
|
||||
tax_amount = rec.rate_analysis_id.tax_amount
|
||||
budget = rec.total_qty * price_per_qty
|
||||
rec.untaxed_amount = untaxed_amount
|
||||
rec.tax_amount = tax_amount
|
||||
rec.price_per_qty = price_per_qty
|
||||
rec.budget = budget
|
||||
|
||||
@api.depends('project_id', 'sub_category_id', 'job_type_id', 'budget', 'total_qty')
|
||||
def _compute_budget_calculation(self):
|
||||
for rec in self:
|
||||
budget_phase_ids = self.env['job.costing'].search(
|
||||
[('project_id', '=', rec.project_id.id), ('activity_id', '=', rec.job_type_id.id)]).mapped('id')
|
||||
domain = [('project_id', '=', rec.project_id.id), ('work_type_id', '=', rec.job_type_id.id),
|
||||
('sub_category_id', '=', rec.sub_category_id.id), ('state', '=', 'complete'),
|
||||
('job_sheet_id', 'in', budget_phase_ids)]
|
||||
material_spent = sum(self.env['order.material.line'].search(domain).mapped('total_price'))
|
||||
equipment_spent = sum(self.env['order.equipment.line'].search(domain).mapped('total_cost'))
|
||||
labour_spent = sum(self.env['order.labour.line'].search(domain).mapped('sub_total'))
|
||||
overhead_spent = sum(self.env['order.overhead.line'].search(domain).mapped('sub_total'))
|
||||
remaining_budget = rec.budget - (material_spent + equipment_spent + labour_spent + overhead_spent)
|
||||
total_spent = 100 - ((remaining_budget * 100 / rec.budget) if rec.budget > 0 else 100)
|
||||
boq_used_qty = rec.total_qty - (
|
||||
(remaining_budget * rec.total_qty / rec.budget) if rec.budget > 0 else rec.total_qty)
|
||||
rec.equipment_spent = equipment_spent
|
||||
rec.labour_spent = labour_spent
|
||||
rec.overhead_spent = overhead_spent
|
||||
rec.material_spent = material_spent
|
||||
rec.remaining_budget = remaining_budget
|
||||
rec.total_spent = round(total_spent, 1)
|
||||
rec.boq_used_qty = boq_used_qty
|
||||
|
||||
@api.onchange('sub_category_id', 'job_type_id')
|
||||
def _onchange_sub_category(self):
|
||||
ids = []
|
||||
for rec in self:
|
||||
if not rec.job_type_id:
|
||||
return
|
||||
ids = rec.job_type_id.sub_category_ids.ids
|
||||
return {'domain': {'sub_category_id': [('id', 'in', ids)]}}
|
||||
|
||||
def action_view_material_budget(self):
|
||||
budget_phase_ids = self.env['job.costing'].search(
|
||||
[('project_id', '=', self.project_id.id), ('activity_id', '=', self.job_type_id.id)]).mapped('id')
|
||||
domain = [('project_id', '=', self.project_id.id), ('work_type_id', '=', self.job_type_id.id),
|
||||
('sub_category_id', '=', self.sub_category_id.id), ('state', '=', 'complete'),
|
||||
('job_sheet_id', 'in', budget_phase_ids)]
|
||||
ids = self.env['order.material.line'].search(domain).mapped('id')
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': _('Material'),
|
||||
'res_model': 'order.material.line',
|
||||
'domain': [('id', 'in', ids)],
|
||||
'context': {'create': False},
|
||||
'view_mode': 'list',
|
||||
'target': 'current'
|
||||
}
|
||||
|
||||
def action_view_equipment_budget(self):
|
||||
budget_phase_ids = self.env['job.costing'].search(
|
||||
[('project_id', '=', self.project_id.id), ('activity_id', '=', self.job_type_id.id)]).mapped('id')
|
||||
domain = [('project_id', '=', self.project_id.id), ('work_type_id', '=', self.job_type_id.id),
|
||||
('sub_category_id', '=', self.sub_category_id.id), ('state', '=', 'complete'),
|
||||
('job_sheet_id', 'in', budget_phase_ids)]
|
||||
ids = self.env['order.equipment.line'].search(domain).mapped('id')
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': _('Equipment'),
|
||||
'res_model': 'order.equipment.line',
|
||||
'domain': [('id', 'in', ids)],
|
||||
'context': {'create': False},
|
||||
'view_mode': 'list',
|
||||
'target': 'current'
|
||||
}
|
||||
|
||||
def action_view_labour_budget(self):
|
||||
budget_phase_ids = self.env['job.costing'].search(
|
||||
[('project_id', '=', self.project_id.id), ('activity_id', '=', self.job_type_id.id)]).mapped('id')
|
||||
domain = [('project_id', '=', self.project_id.id), ('work_type_id', '=', self.job_type_id.id),
|
||||
('sub_category_id', '=', self.sub_category_id.id), ('state', '=', 'complete'),
|
||||
('job_sheet_id', 'in', budget_phase_ids)]
|
||||
ids = self.env['order.labour.line'].search(domain).mapped('id')
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': _('Labour'),
|
||||
'res_model': 'order.labour.line',
|
||||
'domain': [('id', 'in', ids)],
|
||||
'context': {'create': False},
|
||||
'view_mode': 'list',
|
||||
'target': 'current'
|
||||
}
|
||||
|
||||
def action_view_overhead_budget(self):
|
||||
budget_phase_ids = self.env['job.costing'].search(
|
||||
[('project_id', '=', self.project_id.id), ('activity_id', '=', self.job_type_id.id)]).mapped('id')
|
||||
domain = [('project_id', '=', self.project_id.id), ('work_type_id', '=', self.job_type_id.id),
|
||||
('sub_category_id', '=', self.sub_category_id.id), ('state', '=', 'complete'),
|
||||
('job_sheet_id', 'in', budget_phase_ids)]
|
||||
ids = self.env['order.overhead.line'].search(domain).mapped('id')
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': _('Overhead'),
|
||||
'res_model': 'order.overhead.line',
|
||||
'domain': [('id', 'in', ids)],
|
||||
'context': {'create': False},
|
||||
'view_mode': 'list',
|
||||
'target': 'current'
|
||||
}
|
||||
Reference in New Issue
Block a user