749 lines
30 KiB
Python
749 lines
30 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2020-Today TechKhedut.
|
|
# Part of TechKhedut. See LICENSE file for full copyright and licensing details.
|
|
from odoo import fields, api, models, _
|
|
|
|
|
|
class JobOrder(models.Model):
|
|
_name = 'job.order'
|
|
_description = "Work Order"
|
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
|
|
|
name = fields.Char(string='Sequence', required=True,
|
|
readonly=True, default=lambda self: _('New'))
|
|
title = fields.Char(string="Title")
|
|
stage = fields.Selection([('draft', 'Draft'),
|
|
('waiting_approval', 'Waiting for approval'),
|
|
('approved', 'Approved'),
|
|
('complete', 'Complete'),
|
|
('cancel', 'Cancel')], default='draft', tracking=True)
|
|
is_user = fields.Boolean(compute="_compute_user_role")
|
|
is_material_requisition = fields.Boolean(compute="compute_material_req")
|
|
|
|
# Project Details
|
|
site_id = fields.Many2one('tk.construction.site', string="Project")
|
|
project_id = fields.Many2one(
|
|
'tk.construction.project', string="Sub Project")
|
|
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')
|
|
warehouse_id = fields.Many2one(
|
|
related="project_id.warehouse_id", string="Warehouse")
|
|
|
|
# Other Details
|
|
responsible_id = fields.Many2one('res.users', default=lambda self: self.env.user and self.env.user.id or False,
|
|
string="Created By")
|
|
start_date = fields.Date(string="Start Date")
|
|
end_date = fields.Date(string="End Date")
|
|
|
|
# Work Type
|
|
work_type_id = fields.Many2one('job.type', string="Work Type")
|
|
job_sheet_id = fields.Many2one(
|
|
'job.costing', string="Project Phase(WBS)", domain="[('project_id','=',project_id)]")
|
|
|
|
# Department
|
|
department_id = fields.Many2one(
|
|
'construction.department', string="Department")
|
|
manager_ids = fields.Many2many('res.users', string="Manager")
|
|
user_id = fields.Many2one('res.users', string="Responsible")
|
|
|
|
# Material
|
|
material_req_id = fields.Many2one(
|
|
'material.requisition', string="Material Request")
|
|
state = fields.Selection([('draft', 'Draft'),
|
|
('material_request', 'Material Request'),
|
|
('material_arrive', 'Material Arrived'),
|
|
('in_progress', 'In Progress'),
|
|
('complete', 'Complete'),
|
|
('cancel', 'Cancel')], default='draft')
|
|
|
|
# Task Details
|
|
project_project_id = fields.Many2one(
|
|
related="project_id.project_id", string="Project ")
|
|
task_name = fields.Char(string="Task Title")
|
|
task_desc = fields.Text(string="Description")
|
|
assignees_ids = fields.Many2many('res.users', 'construction_assign_dep_rel', 'assign_id', 'dep_id',
|
|
string="Assignees")
|
|
task_id = fields.Many2one('project.task', string="Task")
|
|
|
|
# One2 many
|
|
material_order_ids = fields.One2many('order.material.line', 'job_order_id')
|
|
equipment_order_ids = fields.One2many(
|
|
'order.equipment.line', 'job_order_id')
|
|
labour_order_ids = fields.One2many('order.labour.line', 'job_order_id')
|
|
overhead_order_ids = fields.One2many('order.overhead.line', 'job_order_id')
|
|
|
|
# Total
|
|
equipment_total_cost = fields.Monetary(
|
|
string="Equipment Cost", compute="_compute_total")
|
|
labour_total_cost = fields.Monetary(
|
|
string="Labour Cost", compute="_compute_total")
|
|
overhead_total_cost = fields.Monetary(
|
|
string="Overhead Cost", compute="_compute_total")
|
|
|
|
# Consume Order and Subcontract
|
|
consume_order_ids = fields.One2many('material.consume', 'job_order_id')
|
|
equipment_contract_ids = fields.One2many(
|
|
'equipment.subcontract', 'job_order_id')
|
|
labour_contract_ids = fields.One2many('labour.subcontract', 'job_order_id')
|
|
overhead_contract_ids = fields.One2many(
|
|
'overhead.subcontract', 'job_order_id')
|
|
|
|
# Count
|
|
po_count = fields.Integer(string="Purchase Count",
|
|
compute="_compute_count")
|
|
equip_po_count = fields.Integer(
|
|
string="Purchase Equip Count", compute="_compute_count")
|
|
labour_po_count = fields.Integer(
|
|
string="Purchase Labour Count", compute="_compute_count")
|
|
overhead_po_count = fields.Integer(
|
|
string="Purchase Overhead Count", compute="_compute_count")
|
|
bill_count = fields.Integer(string="Bill Count", compute="_compute_count")
|
|
delivery_count = fields.Integer(
|
|
string="Delivery Count", compute="_compute_count")
|
|
equip_contract_count = fields.Integer(
|
|
string="Equipment Contract Count", compute="_compute_count")
|
|
labour_contract_count = fields.Integer(
|
|
string="Labour Contract Count", compute="_compute_count")
|
|
overhead_contract_count = fields.Integer(
|
|
string="Overhead Contract Count", compute="_compute_count")
|
|
material_consume_count = fields.Integer(
|
|
string="Material Consume Count", compute="_compute_count")
|
|
|
|
# Create, Write, Unlink, Constrain
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
for vals in vals_list:
|
|
if vals.get('name', _('New')) == _('New') and vals.get('project_id'):
|
|
project_id = self.env['tk.construction.project'].browse(
|
|
vals.get('project_id'))
|
|
vals['name'] = str(project_id.code) + "/" + (
|
|
self.env['ir.sequence'].next_by_code('job.order') or _('New'))
|
|
res = super(JobOrder, self).create(vals_list)
|
|
for rec in res:
|
|
data = {
|
|
'name': rec.task_name,
|
|
'description': rec.task_desc,
|
|
'user_ids': rec.assignees_ids.ids,
|
|
'project_id': rec.project_project_id.id,
|
|
'job_order_id': rec.id,
|
|
'con_project_id': rec.project_id.id,
|
|
'date_deadline': rec.end_date
|
|
}
|
|
task_id = self.env['project.task'].create(data)
|
|
rec.task_id = task_id.id
|
|
return res
|
|
|
|
def name_get(self):
|
|
data = []
|
|
for rec in self:
|
|
data.append((rec.id, '%s - %s' % (rec.name, rec.title)))
|
|
return data
|
|
|
|
# Compute
|
|
def _compute_count(self):
|
|
for rec in self:
|
|
rec.po_count = self.env['purchase.order'].search_count(
|
|
[('job_order_id', '=', rec.id)])
|
|
rec.equip_po_count = self.env['purchase.order'].search_count(
|
|
[('job_order_id', '=', rec.id), ('purchase_order', '=', 'equipment')])
|
|
rec.labour_po_count = self.env['purchase.order'].search_count(
|
|
[('job_order_id', '=', rec.id), ('purchase_order', '=', 'labour')])
|
|
rec.overhead_po_count = self.env['purchase.order'].search_count(
|
|
[('job_order_id', '=', rec.id), ('purchase_order', '=', 'overhead')])
|
|
rec.bill_count = self.env['account.move'].search_count(
|
|
[('job_order_id', '=', rec.id)])
|
|
rec.delivery_count = self.env['stock.picking'].search_count(
|
|
[('consume_order_id', '=', rec.id)])
|
|
rec.equip_contract_count = self.env['equipment.subcontract'].search_count(
|
|
[('job_order_id', '=', rec.id)])
|
|
rec.labour_contract_count = self.env['labour.subcontract'].search_count(
|
|
[('job_order_id', '=', rec.id)])
|
|
rec.overhead_contract_count = self.env['overhead.subcontract'].search_count(
|
|
[('job_order_id', '=', rec.id)])
|
|
rec.material_consume_count = self.env['material.consume'].search_count(
|
|
[('job_order_id', '=', rec.id)])
|
|
|
|
def _compute_user_role(self):
|
|
if self.env.user.has_group('tk_construction_management.advance_construction_user'):
|
|
self.is_user = True
|
|
else:
|
|
self.is_user = False
|
|
|
|
@api.depends('material_order_ids')
|
|
def compute_material_req(self):
|
|
for rec in self:
|
|
material_req = False
|
|
for data in rec.material_order_ids:
|
|
if data.qty != 0:
|
|
material_req = True
|
|
break
|
|
rec.is_material_requisition = material_req
|
|
|
|
@api.depends('material_order_ids', 'equipment_order_ids', 'labour_order_ids', 'overhead_order_ids')
|
|
def _compute_total(self):
|
|
equipment, labour, overhead = 0, 0, 0
|
|
for rec in self:
|
|
for data in rec.equipment_order_ids:
|
|
equipment = equipment + data.total_cost
|
|
for data in rec.labour_order_ids:
|
|
labour = labour + data.sub_total
|
|
for data in rec.overhead_order_ids:
|
|
overhead = overhead + data.sub_total
|
|
rec.equipment_total_cost = equipment
|
|
rec.labour_total_cost = labour
|
|
rec.overhead_total_cost = overhead
|
|
|
|
# Smart Button
|
|
def action_view_purchase_order(self):
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': _('Purchase Order'),
|
|
'res_model': 'purchase.order',
|
|
'domain': [('job_order_id', '=', self.id)],
|
|
'context': {
|
|
'default_job_order_id': self.id,
|
|
'group_by': 'purchase_order'
|
|
},
|
|
'view_mode': 'list,form,kanban',
|
|
'target': 'current'
|
|
}
|
|
|
|
def action_view_bills(self):
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': _('Bills'),
|
|
'res_model': 'account.move',
|
|
'domain': [('job_order_id', '=', self.id)],
|
|
'context': {
|
|
'default_job_order_id': self.id
|
|
},
|
|
'view_mode': 'list,form,kanban',
|
|
'target': 'current'
|
|
}
|
|
|
|
def action_view_delivery_order(self):
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': _('Delivery Order'),
|
|
'res_model': 'stock.picking',
|
|
'domain': [('consume_order_id', '=', self.id)],
|
|
'context': {
|
|
'default_': self.id
|
|
},
|
|
'view_mode': 'list,form,kanban',
|
|
'target': 'current'
|
|
}
|
|
|
|
def action_view_purchase_order_equipment(self):
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': _('Equipment PO'),
|
|
'res_model': 'purchase.order',
|
|
'domain': [('job_order_id', '=', self.id), ('purchase_order', '=', 'equipment')],
|
|
'context': {
|
|
'default_job_order_id': self.id,
|
|
'purchase_order': 'equipment'
|
|
},
|
|
'view_mode': 'list,form,kanban',
|
|
'target': 'current'
|
|
}
|
|
|
|
def action_view_contract_equipment(self):
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': _('Equipment Contract'),
|
|
'res_model': 'equipment.subcontract',
|
|
'domain': [('job_order_id', '=', self.id)],
|
|
'context': {
|
|
'create': False,
|
|
},
|
|
'view_mode': 'list,form',
|
|
'target': 'current'
|
|
}
|
|
|
|
def action_view_contract_labour(self):
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': _('Labour Contract'),
|
|
'res_model': 'labour.subcontract',
|
|
'domain': [('job_order_id', '=', self.id)],
|
|
'context': {
|
|
'create': False,
|
|
},
|
|
'view_mode': 'list,form',
|
|
'target': 'current'
|
|
}
|
|
|
|
def action_view_contract_overhead(self):
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': _('Overhead Contract'),
|
|
'res_model': 'overhead.subcontract',
|
|
'domain': [('job_order_id', '=', self.id)],
|
|
'context': {
|
|
'create': False,
|
|
},
|
|
'view_mode': 'list,form',
|
|
'target': 'current'
|
|
}
|
|
|
|
def action_view_material_consume_order(self):
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': _('Consume Orders'),
|
|
'res_model': 'material.consume',
|
|
'domain': [('job_order_id', '=', self.id)],
|
|
'context': {
|
|
'create': False,
|
|
},
|
|
'view_mode': 'list,form',
|
|
'target': 'current'
|
|
}
|
|
|
|
# Button
|
|
def action_request_material(self):
|
|
if not self.material_order_ids:
|
|
message = {
|
|
'type': 'ir.actions.client',
|
|
'tag': 'display_notification',
|
|
'params': {
|
|
'type': 'info',
|
|
'title': _('Add Material'),
|
|
'message': "Add Material to Create Material Request",
|
|
'sticky': False,
|
|
}
|
|
}
|
|
return message
|
|
material_request_id = self.env['material.requisition'].create({
|
|
'title': self.title,
|
|
'company_id': self.company_id.id,
|
|
'desc': self.task_desc,
|
|
'project_id': self.project_id.id,
|
|
'department_id': self.department_id.id,
|
|
'manager_ids': self.manager_ids.ids,
|
|
'user_id': self.user_id.id,
|
|
'work_order_id': self.id,
|
|
'work_type_id': self.work_type_id.id,
|
|
'site_id': self.site_id.id
|
|
})
|
|
for data in self.material_order_ids:
|
|
if data.qty > 0:
|
|
record = {
|
|
'material_id': data.material_id.id,
|
|
'name': data.name,
|
|
'qty': data.qty,
|
|
'warehouse_id': self.warehouse_id.id,
|
|
'material_req_id': material_request_id.id,
|
|
'sub_category_id': data.sub_category_id.id,
|
|
'job_sheet_id': self.job_sheet_id.id,
|
|
}
|
|
req_line_id = self.env['material.requisition.line'].create(
|
|
record)
|
|
data.material_req_line_id = req_line_id.id
|
|
self.material_req_id = material_request_id.id
|
|
self.state = 'material_request'
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': _('Material Request'),
|
|
'res_model': 'material.requisition',
|
|
'res_id': material_request_id.id,
|
|
'view_mode': 'form',
|
|
'target': 'current'
|
|
}
|
|
|
|
def action_create_equipment_subcontract(self):
|
|
for rec in self.equipment_order_ids:
|
|
if not rec.equip_sub_contract_id:
|
|
data = {
|
|
'name': rec.desc,
|
|
'equipment_id': rec.equipment_id.id,
|
|
'cost_type': rec.cost_type,
|
|
'qty': rec.qty,
|
|
'remain_qty': rec.qty,
|
|
'cost': rec.cost,
|
|
'total_cost': rec.total_cost,
|
|
'vendor_id': rec.vendor_id.id,
|
|
'job_type_id': self.work_type_id.id,
|
|
'sub_category_id': rec.sub_category_id.id,
|
|
'job_order_id': self.id,
|
|
'remaining_amount': rec.total_cost,
|
|
'manager_ids': self.manager_ids.ids,
|
|
'tax_id': rec.tax_id.id
|
|
}
|
|
equip_line_id = self.env['equipment.subcontract'].create(data)
|
|
rec.equip_sub_contract_id = equip_line_id.id
|
|
|
|
def action_create_labour_subcontract(self):
|
|
for rec in self.labour_order_ids:
|
|
if not rec.labour_sub_contract_id:
|
|
data = {
|
|
'name': rec.name,
|
|
'product_id': rec.product_id.id,
|
|
'hours': rec.hours,
|
|
'remain_hours': rec.hours,
|
|
'cost': rec.cost,
|
|
'total_cost': rec.sub_total,
|
|
'vendor_id': rec.vendor_id.id,
|
|
'job_type_id': self.work_type_id.id,
|
|
'sub_category_id': rec.sub_category_id.id,
|
|
'job_order_id': self.id,
|
|
'remaining_amount': rec.sub_total,
|
|
'manager_ids': self.manager_ids.ids,
|
|
'tax_id': rec.tax_id.id
|
|
}
|
|
labour_line_id = self.env['labour.subcontract'].create(data)
|
|
rec.labour_sub_contract_id = labour_line_id.id
|
|
|
|
def action_create_overhead_subcontract(self):
|
|
for rec in self.overhead_order_ids:
|
|
if not rec.overhead_sub_contract_id:
|
|
data = {
|
|
'name': rec.name,
|
|
'product_id': rec.product_id.id,
|
|
'qty': rec.qty,
|
|
'remain_qty': rec.qty,
|
|
'cost': rec.cost,
|
|
'total_cost': rec.sub_total,
|
|
'vendor_id': rec.vendor_id.id,
|
|
'job_type_id': self.work_type_id.id,
|
|
'sub_category_id': rec.sub_category_id.id,
|
|
'job_order_id': self.id,
|
|
'remaining_amount': rec.sub_total,
|
|
'manager_ids': self.manager_ids.ids,
|
|
'tax_id': rec.tax_id.id
|
|
}
|
|
overhead_line_id = self.env['overhead.subcontract'].create(
|
|
data)
|
|
rec.overhead_sub_contract_id = overhead_line_id.id
|
|
|
|
def action_create_material_consume_order(self):
|
|
remain_qty = False
|
|
for rec in self.material_order_ids:
|
|
if not rec.remain_qty == 0:
|
|
remain_qty = True
|
|
break
|
|
if remain_qty:
|
|
consume_order_id = self.env['material.consume'].create({
|
|
'job_order_id': self.id,
|
|
'manager_ids': self.manager_ids.ids,
|
|
'warehouse_id': self.warehouse_id.id
|
|
})
|
|
for rec in self.material_order_ids:
|
|
if rec.remain_qty > 0:
|
|
self.env['material.consume.line'].create({
|
|
'material_id': rec.material_id.id,
|
|
'name': rec.name,
|
|
'qty': rec.remain_qty,
|
|
'material_consume_id': consume_order_id.id,
|
|
'material_line_id': rec.id
|
|
})
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': _('Material Consume Order'),
|
|
'res_model': 'material.consume',
|
|
'res_id': consume_order_id.id,
|
|
'view_mode': 'form',
|
|
'target': 'new'
|
|
}
|
|
if not remain_qty:
|
|
message = {
|
|
'type': 'ir.actions.client',
|
|
'tag': 'display_notification',
|
|
'params': {
|
|
'type': 'info',
|
|
'message': "No Material consumption orders found !",
|
|
'sticky': False,
|
|
}
|
|
}
|
|
return message
|
|
|
|
def action_department_approval(self):
|
|
self.stage = 'waiting_approval'
|
|
|
|
def action_department_approval_approved(self):
|
|
self.stage = 'approved'
|
|
|
|
def action_department_approval_reject(self):
|
|
self.stage = 'cancel'
|
|
|
|
def action_draft_order(self):
|
|
self.stage = 'draft'
|
|
|
|
def action_cancel_order(self):
|
|
self.stage = 'cancel'
|
|
|
|
def action_in_progress(self):
|
|
self.state = 'in_progress'
|
|
|
|
def action_reset_draft(self):
|
|
self.state = 'draft'
|
|
|
|
def action_complete_work_order(self):
|
|
material = True
|
|
equipment = True
|
|
labour = True
|
|
overhead = True
|
|
for data in self.equipment_contract_ids:
|
|
if data.stage != 'done':
|
|
equipment = False
|
|
break
|
|
for data in self.labour_contract_ids:
|
|
if data.stage != 'done':
|
|
labour = False
|
|
break
|
|
for data in self.overhead_contract_ids:
|
|
if data.stage != 'done':
|
|
overhead = False
|
|
break
|
|
for data in self.consume_order_ids:
|
|
if data.qc_status != 'approve':
|
|
material = False
|
|
break
|
|
if not material or not equipment or not labour or not overhead:
|
|
message = {
|
|
'type': 'ir.actions.client',
|
|
'tag': 'display_notification',
|
|
'params': {
|
|
'type': 'info',
|
|
'message': _(
|
|
"Please Complete Consume Order / Equipment Subcontract / Labour Subcontract / Overhead Subcontract to complete work order"),
|
|
'sticky': False,
|
|
}
|
|
}
|
|
return message
|
|
self.state = 'complete'
|
|
|
|
|
|
class OrderMaterialLine(models.Model):
|
|
_name = 'order.material.line'
|
|
_description = "Job order material line"
|
|
|
|
material_id = fields.Many2one(
|
|
'product.product', string="Material", domain="[('is_material','=',True)]")
|
|
name = fields.Char(string="Description")
|
|
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')
|
|
qty = fields.Integer(string="Qty.", default=1)
|
|
remain_qty = fields.Integer(string="Remain Qty.", default=1)
|
|
usage_qty = fields.Integer(string="Used Qty.")
|
|
uom_id = fields.Many2one(related="material_id.uom_po_id", string="UOM")
|
|
job_order_id = fields.Many2one('job.order', string="Work Order")
|
|
sub_category_id = fields.Many2one(
|
|
'job.sub.category', string="Work Sub Type")
|
|
price = fields.Monetary(string="Price")
|
|
total_price = fields.Monetary(
|
|
string="Total Price", compute="_compute_total_price")
|
|
material_req_line_id = fields.Many2one('material.requisition.line')
|
|
phase_forcast_qty = fields.Float()
|
|
tax_id = fields.Many2one('account.tax', string="Taxes")
|
|
|
|
# Budget Field
|
|
job_sheet_id = fields.Many2one(
|
|
related="job_order_id.job_sheet_id", store=True)
|
|
project_id = fields.Many2one(related="job_order_id.project_id", store=True)
|
|
work_type_id = fields.Many2one(
|
|
related="job_order_id.work_type_id", store=True)
|
|
state = fields.Selection(related="job_order_id.state", store=True)
|
|
|
|
@api.onchange('material_id')
|
|
def _onchange_product_desc(self):
|
|
for rec in self:
|
|
rec.name = rec.material_id.name
|
|
rec.price = rec.material_id.standard_price
|
|
|
|
@api.depends('qty', 'price', 'tax_id')
|
|
def _compute_total_price(self):
|
|
for rec in self:
|
|
total = 0.0
|
|
if rec.qty and rec.price:
|
|
total = rec.qty * rec.price
|
|
if rec.tax_id:
|
|
tax_amount = rec.tax_id.amount * total / 100
|
|
total = tax_amount + total
|
|
rec.total_price = total
|
|
|
|
@api.onchange('qty')
|
|
def _onchange_remain_qty(self):
|
|
for rec in self:
|
|
rec.remain_qty = rec.qty
|
|
|
|
@api.depends('warehouse_id', 'material_id')
|
|
def _compute_forcast_qty(self):
|
|
for rec in self:
|
|
qty = 0.0
|
|
if rec.material_id:
|
|
qty = rec.material_id.with_context(
|
|
warehouse=rec.warehouse_id.id).virtual_available
|
|
rec.forcast_qty = qty
|
|
|
|
|
|
class OrderEquipmentLine(models.Model):
|
|
_name = 'order.equipment.line'
|
|
_description = 'Construction Work Order Equipment Line'
|
|
|
|
equipment_id = fields.Many2one(
|
|
'product.product', string="Equipment", domain="[('is_equipment','=',True)]")
|
|
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')
|
|
cost_type = fields.Selection(
|
|
[('depreciation_cost', 'Depreciation Cost'), ('investment_cost', 'Investment/Interest Cost'),
|
|
('tax', 'Tax'), ('rent', 'Rent'), ('other', 'Other')], string="Type", default='rent')
|
|
desc = fields.Text(string='Description')
|
|
qty = fields.Integer(string="Qty.", default=1)
|
|
cost = fields.Monetary(string="Estimation Cost")
|
|
total_cost = fields.Monetary(
|
|
string="Total Cost", compute="_compute_total_cost", store=True)
|
|
vendor_id = fields.Many2one('res.partner', string="Vendor")
|
|
job_order_id = fields.Many2one('job.order', string="Work Order")
|
|
purchase_order_id = fields.Many2one(
|
|
'purchase.order', string="Purchase Order")
|
|
is_po_create = fields.Boolean()
|
|
sub_category_id = fields.Many2one(
|
|
'job.sub.category', string="Work Sub Type")
|
|
|
|
equip_sub_contract_id = fields.Many2one(
|
|
'equipment.subcontract', string="Equip Subcontract")
|
|
phase_forcast_qty = fields.Float()
|
|
tax_id = fields.Many2one('account.tax', string="Taxes")
|
|
|
|
# Budget Field
|
|
job_sheet_id = fields.Many2one(
|
|
related="job_order_id.job_sheet_id", store=True)
|
|
project_id = fields.Many2one(related="job_order_id.project_id", store=True)
|
|
work_type_id = fields.Many2one(
|
|
related="job_order_id.work_type_id", store=True)
|
|
state = fields.Selection(related="job_order_id.state", store=True)
|
|
|
|
@api.depends('qty', 'cost', 'tax_id')
|
|
def _compute_total_cost(self):
|
|
for rec in self:
|
|
total = 0.0
|
|
if rec.cost and rec.qty:
|
|
total = rec.cost * rec.qty
|
|
if rec.tax_id:
|
|
tax_amount = rec.tax_id.amount * total / 100
|
|
total = tax_amount + total
|
|
rec.total_cost = total
|
|
|
|
@api.onchange('equipment_id')
|
|
def _onchange_product_desc(self):
|
|
for rec in self:
|
|
rec.desc = rec.equipment_id.name
|
|
rec.cost = rec.equipment_id.standard_price
|
|
|
|
|
|
class OrderLabourLine(models.Model):
|
|
_name = 'order.labour.line'
|
|
_description = "Work Order Labour Line"
|
|
|
|
job_order_id = fields.Many2one('job.order', string="Work Order")
|
|
product_id = fields.Many2one(
|
|
'product.product', string="Product", domain="[('is_labour','=',True)]")
|
|
name = fields.Char(string="Description")
|
|
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')
|
|
hours = fields.Float(string="Hours")
|
|
remain_hours = fields.Float(
|
|
related='labour_sub_contract_id.remain_hours', string="Remain Hours")
|
|
cost = fields.Monetary(string="Cost / Hour")
|
|
sub_total = fields.Monetary(
|
|
string="Sub Total", compute="_compute_sub_total", store=True)
|
|
vendor_id = fields.Many2one('res.partner', string="Vendor")
|
|
is_bill_created = fields.Boolean()
|
|
purchase_order_id = fields.Many2one(
|
|
'purchase.order', string="Purchase Order")
|
|
sub_category_id = fields.Many2one(
|
|
'job.sub.category', string="Work Sub Type")
|
|
labour_sub_contract_id = fields.Many2one(
|
|
'labour.subcontract', string="Subcontract")
|
|
phase_forcast_qty = fields.Float()
|
|
tax_id = fields.Many2one('account.tax', string="Taxes")
|
|
|
|
# Budget Field
|
|
job_sheet_id = fields.Many2one(
|
|
related="job_order_id.job_sheet_id", store=True)
|
|
project_id = fields.Many2one(related="job_order_id.project_id", store=True)
|
|
work_type_id = fields.Many2one(
|
|
related="job_order_id.work_type_id", store=True)
|
|
state = fields.Selection(related="job_order_id.state", store=True)
|
|
|
|
@api.onchange('product_id')
|
|
def _onchange_product_desc(self):
|
|
for rec in self:
|
|
rec.name = rec.product_id.name
|
|
rec.cost = rec.product_id.standard_price
|
|
|
|
@api.depends('cost', 'hours', 'tax_id')
|
|
def _compute_sub_total(self):
|
|
for rec in self:
|
|
total = 0.0
|
|
if rec.cost and rec.hours:
|
|
total = rec.cost * rec.hours
|
|
if rec.tax_id:
|
|
tax_amount = rec.tax_id.amount * total / 100
|
|
total = tax_amount + total
|
|
rec.sub_total = total
|
|
|
|
|
|
class OrderOverheadLine(models.Model):
|
|
_name = 'order.overhead.line'
|
|
_description = "Work Order Overhead Line"
|
|
|
|
job_order_id = fields.Many2one('job.order', string="Work Order")
|
|
product_id = fields.Many2one(
|
|
'product.product', string="Product", domain="[('is_overhead','=',True)]")
|
|
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')
|
|
name = fields.Char(string="Description")
|
|
qty = fields.Integer(string="Qty.", default=1)
|
|
uom_id = fields.Many2one(
|
|
related="product_id.uom_po_id", string="Unit of Measure")
|
|
cost = fields.Monetary(string="Cost / Unit")
|
|
sub_total = fields.Monetary(
|
|
string="Sub Total", compute="_compute_sub_total", store=True)
|
|
vendor_id = fields.Many2one('res.partner', string="Vendor")
|
|
is_bill_created = fields.Boolean()
|
|
purchase_order_id = fields.Many2one(
|
|
'purchase.order', string="Purchase Order")
|
|
sub_category_id = fields.Many2one(
|
|
'job.sub.category', string="Work Sub Type")
|
|
overhead_sub_contract_id = fields.Many2one(
|
|
'overhead.subcontract', string="Subcontract")
|
|
phase_forcast_qty = fields.Float()
|
|
tax_id = fields.Many2one('account.tax', string="Taxes")
|
|
|
|
# Budget Field
|
|
job_sheet_id = fields.Many2one(
|
|
related="job_order_id.job_sheet_id", store=True)
|
|
project_id = fields.Many2one(related="job_order_id.project_id", store=True)
|
|
work_type_id = fields.Many2one(
|
|
related="job_order_id.work_type_id", store=True)
|
|
state = fields.Selection(related="job_order_id.state", store=True)
|
|
|
|
@api.depends('cost', 'qty', 'tax_id')
|
|
def _compute_sub_total(self):
|
|
for rec in self:
|
|
total = 0.0
|
|
if rec.cost and rec.qty:
|
|
total = rec.cost * rec.qty
|
|
if rec.tax_id:
|
|
tax_amount = rec.tax_id.amount * total / 100
|
|
total = tax_amount + total
|
|
rec.sub_total = total
|
|
|
|
@api.onchange('product_id')
|
|
def _onchange_product_desc(self):
|
|
for rec in self:
|
|
rec.name = rec.product_id.name
|
|
rec.cost = rec.product_id.standard_price
|