Tower: upload tk_construction_management 18.0.2.0.8 (was 18.0.2.0.8, via marketplace)
This commit is contained in:
813
addons/tk_construction_management/models/sub_contract.py
Normal file
813
addons/tk_construction_management/models/sub_contract.py
Normal file
@@ -0,0 +1,813 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2020-Today TechKhedut.
|
||||
# Part of TechKhedut. See LICENSE file for full copyright and licensing details.
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class EquipmentSubcontract(models.Model):
|
||||
_name = 'equipment.subcontract'
|
||||
_description = "Equipment Subcontract"
|
||||
_rec_name = 'seq'
|
||||
|
||||
seq = fields.Char(string='Sequence', required=True, readonly=True, default=lambda self: _('New'))
|
||||
name = fields.Char(string="Title")
|
||||
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')
|
||||
cost = fields.Monetary(string="Estimation Cost")
|
||||
vendor_id = fields.Many2one('res.partner', string="Vendor")
|
||||
purchase_order_id = fields.Many2one('purchase.order', string="Purchase Order")
|
||||
job_type_id = fields.Many2one('job.type', string="Work Type")
|
||||
sub_category_id = fields.Many2one('job.sub.category', string="Work Sub Type")
|
||||
stage = fields.Selection([('draft', 'Draft'), ('in_progress', 'In Progress'), ('done', 'Done')], default='draft')
|
||||
po_bill = fields.Selection([('bill', 'Bill'), ('purchase_order', 'Purchase Order')], string="Type", default='bill')
|
||||
ra_bill_ids = fields.One2many('equip.contract.line', 'contract_id', string="Ra Bills")
|
||||
completion_date = fields.Date(string="Completion Date", compute="compute_completion_date")
|
||||
|
||||
# Calculation
|
||||
qty = fields.Integer(string="Qty.", default=1)
|
||||
remain_qty = fields.Integer(string="Remaining Qty")
|
||||
total_cost = fields.Monetary(string="Total Cost")
|
||||
remaining_amount = fields.Monetary(string="Remaining Amount")
|
||||
progress = fields.Float(string="Complete Billing", compute="_compute_payment_progress")
|
||||
tax_id = fields.Many2one('account.tax', string='Tax')
|
||||
|
||||
# Project Details
|
||||
job_order_id = fields.Many2one('job.order', string="Work Order")
|
||||
phase_id = fields.Many2one(related="job_order_id.job_sheet_id", string="Project Phase(WBS)", store=True)
|
||||
project_id = fields.Many2one(related='job_order_id.project_id', string="Sub Project", store=True)
|
||||
task_id = fields.Many2one(related="job_order_id.task_id", string="Task", store=True)
|
||||
|
||||
# Department
|
||||
department_id = fields.Many2one(related="job_order_id.department_id", string="Department", store=True)
|
||||
manager_ids = fields.Many2many('res.users', store=True, string="Manager")
|
||||
user_id = fields.Many2one(related="job_order_id.user_id", string="Responsible")
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('seq', _('New')) == _('New'):
|
||||
vals['seq'] = self.env['ir.sequence'].next_by_code('equip.sub') or _('New')
|
||||
res = super(EquipmentSubcontract, self).create(vals_list)
|
||||
return res
|
||||
|
||||
def action_in_progress(self):
|
||||
self.stage = 'in_progress'
|
||||
|
||||
def action_state_done(self):
|
||||
self.stage = 'done'
|
||||
|
||||
@api.constrains('ra_bill_ids', 'qty')
|
||||
def _check_ra_bill_qty(self):
|
||||
qty = 0
|
||||
for record in self.ra_bill_ids:
|
||||
if record.qc_status != 'reject':
|
||||
qty = qty + record.qty
|
||||
if qty > self.qty:
|
||||
raise ValidationError(_("Quantity should be less than total qty."))
|
||||
|
||||
@api.depends('total_cost', 'remaining_amount')
|
||||
def _compute_payment_progress(self):
|
||||
for rec in self:
|
||||
progress = 0.0
|
||||
if rec.total_cost and rec.remaining_amount:
|
||||
progress = (rec.remaining_amount * 100) / rec.total_cost
|
||||
rec.progress = 100 - progress
|
||||
|
||||
@api.depends('stage', 'ra_bill_ids')
|
||||
def compute_completion_date(self):
|
||||
for rec in self:
|
||||
date = None
|
||||
if rec.stage == "done":
|
||||
dates = rec.ra_bill_ids.mapped('date')
|
||||
if dates:
|
||||
date = dates[-1]
|
||||
rec.completion_date = date
|
||||
|
||||
|
||||
class EquipContractLine(models.Model):
|
||||
_name = 'equip.contract.line'
|
||||
_description = "Equip Contract Line"
|
||||
_rec_name = 'remark'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
|
||||
contract_id = fields.Many2one('equipment.subcontract', string="Subcontract", ondelete='cascade')
|
||||
percentage = fields.Float(string="Percentage", tracking=True, compute="_compute_percentage")
|
||||
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')
|
||||
amount = fields.Monetary(tracking=True, string="Amount", compute="_compute_percentage_amount")
|
||||
date = fields.Date(string="Date", default=fields.Date.today(), tracking=True)
|
||||
remark = fields.Char(string="Remark", tracking=True)
|
||||
purchase_order_id = fields.Many2one('purchase.order', string="Purchase Order")
|
||||
bill_id = fields.Many2one('account.move', string="Bill")
|
||||
payment_state = fields.Selection(related="bill_id.payment_state", string="Payment State", tracking=True)
|
||||
state = fields.Selection(related="purchase_order_id.state", string="State", tracking=True)
|
||||
po_bill = fields.Selection(related="contract_id.po_bill")
|
||||
qty = fields.Integer(string="Qty")
|
||||
retention_percentage = fields.Float(string="Retention(%)")
|
||||
retention_amount = fields.Monetary(string="Retention Amount", compute="compute_retention_amount")
|
||||
final_amount = fields.Monetary(string="Total Amount", compute="_compute_final_amount")
|
||||
|
||||
# QC Check
|
||||
qc_user_id = fields.Many2one('res.users', string="QC Responsible", tracking=True)
|
||||
qc_status = fields.Selection(
|
||||
[('draft', 'Draft'),
|
||||
('request', 'Department Approval'),
|
||||
('approve', 'Approve'),
|
||||
('reject', 'Reject')], default='draft', string="Quality Check Status", tracking=True)
|
||||
reject_reason = fields.Text(string="Reject Reason", tracking=True)
|
||||
|
||||
def unlink(self):
|
||||
for rec in self:
|
||||
if rec.qc_status != 'draft':
|
||||
raise ValidationError(_("You can't delete until Quality Check status is in Draft"))
|
||||
else:
|
||||
return super(EquipContractLine, self).unlink()
|
||||
|
||||
@api.constrains('qty')
|
||||
def _check_ra_bill_qty(self):
|
||||
ra_bill_ids = self.env['equip.contract.line'].search([('contract_id', '=', self.contract_id.id)])
|
||||
qty = 0
|
||||
for record in ra_bill_ids:
|
||||
if record.qc_status != 'reject':
|
||||
qty = qty + record.qty
|
||||
if qty > self.contract_id.qty:
|
||||
raise ValidationError(_("Quantity should be less than total qty."))
|
||||
|
||||
@api.depends('contract_id', 'qty', 'contract_id.tax_id')
|
||||
def _compute_percentage_amount(self):
|
||||
for rec in self:
|
||||
amount = 0.0
|
||||
if rec.qty and rec.contract_id:
|
||||
amount = (rec.contract_id.cost + (rec.contract_id.tax_id.amount * rec.contract_id.cost / 100)) * rec.qty
|
||||
rec.amount = amount
|
||||
|
||||
@api.depends('qty', 'retention_amount')
|
||||
def _compute_final_amount(self):
|
||||
for rec in self:
|
||||
total = 0.0
|
||||
if rec.amount:
|
||||
total = rec.amount - rec.retention_amount
|
||||
rec.final_amount = total
|
||||
|
||||
@api.depends('amount', 'retention_percentage')
|
||||
def compute_retention_amount(self):
|
||||
for rec in self:
|
||||
retention_amount = 0.0
|
||||
if rec.retention_percentage:
|
||||
retention_amount = rec.amount * rec.retention_percentage / 100
|
||||
rec.retention_amount = retention_amount
|
||||
|
||||
@api.depends('contract_id', 'amount')
|
||||
def _compute_percentage(self):
|
||||
for rec in self:
|
||||
percentage = 0.0
|
||||
if rec.contract_id and rec.amount > 0:
|
||||
percentage = (100 * rec.amount) / rec.contract_id.total_cost
|
||||
rec.percentage = percentage
|
||||
|
||||
def action_quality_check(self):
|
||||
self.qc_status = 'request'
|
||||
|
||||
def action_quality_check_approve(self):
|
||||
self.qc_status = 'approve'
|
||||
self.qc_user_id = self.env.user.id
|
||||
|
||||
def action_quality_check_reject(self):
|
||||
self.qc_status = 'reject'
|
||||
self.qc_user_id = self.env.user.id
|
||||
|
||||
def action_reset_to_draft(self):
|
||||
self.qc_status = 'draft'
|
||||
|
||||
def action_create_ra_bill(self):
|
||||
if self.po_bill == 'bill':
|
||||
record = {
|
||||
'product_id': self.contract_id.equipment_id.id,
|
||||
'name': self.contract_id.name,
|
||||
'quantity': 1,
|
||||
'price_unit': self.final_amount,
|
||||
'tax_ids': False
|
||||
}
|
||||
invoice_lines = [(0, 0, record)]
|
||||
data = {
|
||||
'partner_id': self.contract_id.vendor_id.id,
|
||||
'invoice_date': self.date,
|
||||
'invoice_line_ids': invoice_lines,
|
||||
'move_type': 'in_invoice',
|
||||
'equipment_subcontract_id': self.contract_id.id,
|
||||
'job_order_id': self.contract_id.job_order_id.id,
|
||||
'purchase_order': 'equipment'
|
||||
}
|
||||
invoice_id = self.env['account.move'].sudo().create(data)
|
||||
self.bill_id = invoice_id.id
|
||||
remaining_amount = self.contract_id.remaining_amount
|
||||
self.contract_id.remaining_amount = remaining_amount - self.amount
|
||||
qty = self.contract_id.remain_qty
|
||||
self.contract_id.remain_qty = qty - self.qty
|
||||
elif self.po_bill == 'purchase_order':
|
||||
purchase_record = {
|
||||
'product_id': self.contract_id.equipment_id.id,
|
||||
'name': self.contract_id.name,
|
||||
'product_qty': 1,
|
||||
'price_unit': self.final_amount,
|
||||
}
|
||||
purchase_lines = [(0, 0, purchase_record)]
|
||||
purchase_data = {
|
||||
'partner_id': self.contract_id.vendor_id.id,
|
||||
'order_line': purchase_lines,
|
||||
'job_order_id': self.contract_id.job_order_id.id,
|
||||
'equipment_subcontract_id': self.contract_id.id,
|
||||
'purchase_order': 'equipment'
|
||||
}
|
||||
purchase_order_id = self.env['purchase.order'].create(purchase_data)
|
||||
self.purchase_order_id = purchase_order_id.id
|
||||
remaining_amount = self.contract_id.remaining_amount
|
||||
self.contract_id.remaining_amount = remaining_amount - self.amount
|
||||
qty = self.contract_id.remain_qty
|
||||
self.contract_id.remain_qty = qty - self.qty
|
||||
|
||||
|
||||
class LabourSubcontract(models.Model):
|
||||
_name = 'labour.subcontract'
|
||||
_description = "Labour Sub Contract"
|
||||
_rec_name = 'seq'
|
||||
|
||||
seq = fields.Char(string='Sequence', required=True, readonly=True, default=lambda self: _('New'))
|
||||
name = fields.Char(string="Title")
|
||||
product_id = fields.Many2one('product.product', string="Product", domain="[('is_labour','=',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 = fields.Monetary(string="Cost / Hour")
|
||||
po_bill = fields.Selection([('bill', 'Bill'), ('purchase_order', 'Purchase Order')], string="Type",
|
||||
default='bill')
|
||||
stage = fields.Selection([('draft', 'Draft'), ('in_progress', 'In Progress'), ('done', 'Done')],
|
||||
default='draft')
|
||||
vendor_id = fields.Many2one('res.partner', string="Contractor")
|
||||
job_type_id = fields.Many2one('job.type', string="Work Type")
|
||||
sub_category_id = fields.Many2one('job.sub.category', string="Work Sub Type")
|
||||
ra_bill_ids = fields.One2many('labour.contract.line', 'contract_id', string="Ra Bills")
|
||||
|
||||
# Project Details
|
||||
job_order_id = fields.Many2one('job.order', string="Work Order")
|
||||
phase_id = fields.Many2one(related="job_order_id.job_sheet_id", string="Project Phase(WBS)", store=True)
|
||||
project_id = fields.Many2one(related='job_order_id.project_id', string="Sub Project", store=True)
|
||||
task_id = fields.Many2one(related="job_order_id.task_id", string="Task", store=True)
|
||||
|
||||
# Department
|
||||
department_id = fields.Many2one(related="job_order_id.department_id", string="Department", store=True)
|
||||
manager_ids = fields.Many2many('res.users', store=True, string="Manager")
|
||||
user_id = fields.Many2one(related="job_order_id.user_id", string="Responsible")
|
||||
|
||||
# Calculation
|
||||
hours = fields.Float(string="Hours")
|
||||
remain_hours = fields.Float(string="Remaining Hours")
|
||||
total_cost = fields.Monetary(string="Total Cost")
|
||||
remaining_amount = fields.Monetary(string="Remaining Amount")
|
||||
progress = fields.Float(string="Completed Billing", compute="_compute_payment_progress")
|
||||
tax_id = fields.Many2one('account.tax', string='Tax')
|
||||
completion_date = fields.Date(string="Completion Date", compute="compute_completion_date")
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('seq', _('New')) == _('New'):
|
||||
vals['seq'] = self.env['ir.sequence'].next_by_code('labour.sub') or _('New')
|
||||
res = super(LabourSubcontract, self).create(vals_list)
|
||||
return res
|
||||
|
||||
def action_in_progress(self):
|
||||
self.stage = 'in_progress'
|
||||
|
||||
def action_state_done(self):
|
||||
self.stage = 'done'
|
||||
|
||||
@api.constrains('ra_bill_ids', 'hours')
|
||||
def _check_ra_bill_hours(self):
|
||||
hours = 0
|
||||
for record in self.ra_bill_ids:
|
||||
if record.qc_status != 'reject':
|
||||
hours = hours + record.hours
|
||||
if hours > self.hours:
|
||||
raise ValidationError(_("Hours should be less than total hours"))
|
||||
|
||||
@api.depends('total_cost', 'remaining_amount')
|
||||
def _compute_payment_progress(self):
|
||||
for rec in self:
|
||||
progress = 0.0
|
||||
if rec.total_cost and rec.remaining_amount:
|
||||
progress = (rec.remaining_amount * 100) / rec.total_cost
|
||||
rec.progress = 100 - progress
|
||||
|
||||
@api.depends('stage', 'ra_bill_ids')
|
||||
def compute_completion_date(self):
|
||||
for rec in self:
|
||||
date = None
|
||||
if rec.stage == "done":
|
||||
dates = rec.ra_bill_ids.mapped('date')
|
||||
if dates:
|
||||
date = dates[-1]
|
||||
rec.completion_date = date
|
||||
|
||||
|
||||
class LabourContractLine(models.Model):
|
||||
_name = 'labour.contract.line'
|
||||
_description = "Labour Contract Line"
|
||||
_rec_name = 'remark'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
|
||||
contract_id = fields.Many2one('labour.subcontract', string="Labour Subcontract", ondelete='cascade')
|
||||
percentage = fields.Float(string="Percentage", tracking=True, compute="_compute_percentage")
|
||||
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')
|
||||
amount = fields.Monetary(tracking=True, string="Amount", compute="_compute_percentage_amount")
|
||||
date = fields.Date(string="Date", default=fields.Date.today(), tracking=True)
|
||||
remark = fields.Char(string="Remark", tracking=True)
|
||||
purchase_order_id = fields.Many2one('purchase.order', string="Purchase Order")
|
||||
bill_id = fields.Many2one('account.move', string="Bill")
|
||||
payment_state = fields.Selection(related="bill_id.payment_state", string="Payment State", tracking=True)
|
||||
state = fields.Selection(related="purchase_order_id.state", string="State", tracking=True)
|
||||
po_bill = fields.Selection(related="contract_id.po_bill")
|
||||
hours = fields.Float(string="Hours")
|
||||
retention_percentage = fields.Float(string="Retention(%)")
|
||||
retention_amount = fields.Monetary(string="Retention Amount", compute="compute_retention_amount")
|
||||
final_amount = fields.Monetary(string="Total Amount", compute="_compute_final_amount")
|
||||
|
||||
# QC Check
|
||||
qc_user_id = fields.Many2one('res.users', string="QC Responsible", tracking=True)
|
||||
qc_status = fields.Selection([('draft', 'Draft'),
|
||||
('request', 'Department Approval'),
|
||||
('approve', 'Approve'),
|
||||
('reject', 'Reject')],
|
||||
default='draft', string="Quality Check Status", tracking=True)
|
||||
reject_reason = fields.Text(string="Reject Reason", tracking=True)
|
||||
|
||||
def unlink(self):
|
||||
for rec in self:
|
||||
if rec.qc_status != 'draft':
|
||||
raise ValidationError(_("You can't delete until Quality Check status is in Draft"))
|
||||
else:
|
||||
return super(LabourContractLine, self).unlink()
|
||||
|
||||
@api.constrains('hours')
|
||||
def _check_ra_bill_hours(self):
|
||||
ra_bill_ids = self.env['labour.contract.line'].search([('contract_id', '=', self.contract_id.id)])
|
||||
hours = 0
|
||||
for record in ra_bill_ids:
|
||||
if record.qc_status != 'reject':
|
||||
hours = hours + record.hours
|
||||
if hours > self.contract_id.hours:
|
||||
raise ValidationError(_("Hours should be less than total hours"))
|
||||
|
||||
@api.depends('contract_id', 'hours', 'contract_id.tax_id')
|
||||
def _compute_percentage_amount(self):
|
||||
for rec in self:
|
||||
amount = 0.0
|
||||
if rec.hours and rec.contract_id:
|
||||
amount = (rec.contract_id.cost + (
|
||||
rec.contract_id.tax_id.amount * rec.contract_id.cost / 100)) * rec.hours
|
||||
rec.amount = amount
|
||||
|
||||
@api.depends('hours', 'retention_amount')
|
||||
def _compute_final_amount(self):
|
||||
for rec in self:
|
||||
total = 0.0
|
||||
if rec.amount:
|
||||
total = rec.amount - rec.retention_amount
|
||||
rec.final_amount = total
|
||||
|
||||
@api.depends('amount', 'retention_percentage')
|
||||
def compute_retention_amount(self):
|
||||
for rec in self:
|
||||
retention_amount = 0.0
|
||||
retention_amount = rec.amount * rec.retention_percentage / 100
|
||||
rec.retention_amount = retention_amount
|
||||
|
||||
@api.depends('contract_id', 'amount')
|
||||
def _compute_percentage(self):
|
||||
for rec in self:
|
||||
percentage = 0.0
|
||||
if rec.contract_id and rec.amount > 0:
|
||||
percentage = (100 * rec.amount) / rec.contract_id.total_cost
|
||||
rec.percentage = percentage
|
||||
|
||||
def action_quality_check(self):
|
||||
self.qc_status = 'request'
|
||||
|
||||
def action_quality_check_approve(self):
|
||||
self.qc_status = 'approve'
|
||||
self.qc_user_id = self.env.user.id
|
||||
|
||||
def action_quality_check_reject(self):
|
||||
self.qc_status = 'reject'
|
||||
self.qc_user_id = self.env.user.id
|
||||
|
||||
def action_reset_to_draft(self):
|
||||
self.qc_status = 'draft'
|
||||
|
||||
def action_create_ra_bill(self):
|
||||
if self.po_bill == 'bill':
|
||||
record = {
|
||||
'product_id': self.contract_id.product_id.id,
|
||||
'name': self.contract_id.name,
|
||||
'quantity': 1,
|
||||
'price_unit': self.final_amount,
|
||||
'tax_ids': False
|
||||
}
|
||||
invoice_lines = [(0, 0, record)]
|
||||
data = {
|
||||
'partner_id': self.contract_id.vendor_id.id,
|
||||
'invoice_date': self.date,
|
||||
'invoice_line_ids': invoice_lines,
|
||||
'move_type': 'in_invoice',
|
||||
'labour_subcontract_id': self.contract_id.id,
|
||||
'job_order_id': self.contract_id.job_order_id.id,
|
||||
'purchase_order': 'equipment'
|
||||
}
|
||||
invoice_id = self.env['account.move'].sudo().create(data)
|
||||
remaining_amount = self.contract_id.remaining_amount
|
||||
self.contract_id.remaining_amount = remaining_amount - self.amount
|
||||
self.bill_id = invoice_id.id
|
||||
qty = self.contract_id.remain_hours
|
||||
self.contract_id.remain_hours = qty - self.hours
|
||||
elif self.po_bill == 'purchase_order':
|
||||
purchase_record = {
|
||||
'product_id': self.contract_id.product_id.id,
|
||||
'name': self.contract_id.name
|
||||
,
|
||||
'product_qty': 1,
|
||||
'price_unit': self.final_amount,
|
||||
}
|
||||
purchase_lines = [(0, 0, purchase_record)]
|
||||
purchase_data = {
|
||||
'partner_id': self.contract_id.vendor_id.id,
|
||||
'order_line': purchase_lines,
|
||||
'job_order_id': self.contract_id.job_order_id.id,
|
||||
'labour_subcontract_id': self.contract_id.id,
|
||||
'purchase_order': 'equipment'
|
||||
}
|
||||
purchase_order_id = self.env['purchase.order'].create(purchase_data)
|
||||
self.purchase_order_id = purchase_order_id.id
|
||||
remaining_amount = self.contract_id.remaining_amount
|
||||
self.contract_id.remaining_amount = remaining_amount - self.amount
|
||||
qty = self.contract_id.remain_hours
|
||||
self.contract_id.remain_hours = qty - self.hours
|
||||
|
||||
|
||||
class OverheadSubcontract(models.Model):
|
||||
_name = 'overhead.subcontract'
|
||||
_description = "Overhead Subcontract"
|
||||
_rec_name = 'seq'
|
||||
|
||||
seq = fields.Char(string='Sequence', required=True, readonly=True, default=lambda self: _('New'))
|
||||
name = fields.Char(string="Title")
|
||||
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')
|
||||
uom_id = fields.Many2one(related="product_id.uom_po_id", string="Unit of Measure")
|
||||
cost = fields.Monetary(string="Cost / Unit")
|
||||
po_bill = fields.Selection([('bill', 'Bill'), ('purchase_order', 'Purchase Order')], string="Type", default='bill')
|
||||
stage = fields.Selection([('draft', 'Draft'), ('in_progress', 'In Progress'), ('done', 'Done')], default='draft')
|
||||
vendor_id = fields.Many2one('res.partner', string="Vendor")
|
||||
job_type_id = fields.Many2one('job.type', string="Work Type")
|
||||
sub_category_id = fields.Many2one('job.sub.category', string="Work Sub Type")
|
||||
ra_bill_ids = fields.One2many('overhead.contract.line', 'contract_id', string="Ra Bills")
|
||||
|
||||
# Project Details
|
||||
job_order_id = fields.Many2one('job.order', string="Work Order")
|
||||
phase_id = fields.Many2one(related="job_order_id.job_sheet_id", string="Project Phase(WBS)", store=True)
|
||||
project_id = fields.Many2one(related='job_order_id.project_id', string="Sub Project", store=True)
|
||||
task_id = fields.Many2one(related="job_order_id.task_id", string="Task", store=True)
|
||||
# Department
|
||||
department_id = fields.Many2one(related="job_order_id.department_id", string="Department", store=True)
|
||||
manager_ids = fields.Many2many('res.users', store=True, string="Manager")
|
||||
user_id = fields.Many2one(related="job_order_id.user_id", string="Responsible")
|
||||
|
||||
# Calculation
|
||||
qty = fields.Integer(string="Qty.", default=1)
|
||||
remain_qty = fields.Integer(string="Remaining Qty")
|
||||
total_cost = fields.Monetary(string="Total Cost")
|
||||
remaining_amount = fields.Monetary(string="Remaining Amount")
|
||||
progress = fields.Float(string="Completed Billing", compute="_compute_payment_progress")
|
||||
tax_id = fields.Many2one('account.tax', string='Tax')
|
||||
completion_date = fields.Date(string="Completion Date", compute="compute_completion_date")
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('seq', _('New')) == _('New'):
|
||||
vals['seq'] = self.env['ir.sequence'].next_by_code('overhead.sub') or _('New')
|
||||
res = super(OverheadSubcontract, self).create(vals_list)
|
||||
return res
|
||||
|
||||
def action_in_progress(self):
|
||||
self.stage = 'in_progress'
|
||||
|
||||
def action_state_done(self):
|
||||
self.stage = 'done'
|
||||
|
||||
@api.constrains('ra_bill_ids', 'qty')
|
||||
def _check_ra_bill_qty(self):
|
||||
qty = 0
|
||||
for record in self.ra_bill_ids:
|
||||
if record.qc_status != 'reject':
|
||||
qty = qty + record.qty
|
||||
if qty > self.qty:
|
||||
raise ValidationError(_("Quantity should be less than total qty."))
|
||||
|
||||
@api.depends('total_cost', 'remaining_amount')
|
||||
def _compute_payment_progress(self):
|
||||
for rec in self:
|
||||
progress = 0.0
|
||||
if rec.total_cost and rec.remaining_amount:
|
||||
progress = (rec.remaining_amount * 100) / rec.total_cost
|
||||
rec.progress = 100 - progress
|
||||
|
||||
@api.depends('stage', 'ra_bill_ids')
|
||||
def compute_completion_date(self):
|
||||
for rec in self:
|
||||
date = None
|
||||
if rec.stage == "done":
|
||||
dates = rec.ra_bill_ids.mapped('date')
|
||||
if dates:
|
||||
date = dates[-1]
|
||||
rec.completion_date = date
|
||||
|
||||
|
||||
class OverheadContractLine(models.Model):
|
||||
_name = 'overhead.contract.line'
|
||||
_description = "Overhead Contract Line"
|
||||
_rec_name = 'remark'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
|
||||
contract_id = fields.Many2one('overhead.subcontract', string="Overhead Subcontract", ondelete='cascade')
|
||||
percentage = fields.Float(string="Percentage", tracking=True, compute="_compute_percentage")
|
||||
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')
|
||||
amount = fields.Monetary(tracking=True, string="Amount", compute="_compute_percentage_amount")
|
||||
date = fields.Date(string="Date", default=fields.Date.today(), tracking=True)
|
||||
remark = fields.Char(string="Remark", tracking=True)
|
||||
purchase_order_id = fields.Many2one('purchase.order', string="Purchase Order")
|
||||
bill_id = fields.Many2one('account.move', string="Bill")
|
||||
payment_state = fields.Selection(related="bill_id.payment_state", string="Payment State", tracking=True)
|
||||
state = fields.Selection(related="purchase_order_id.state", string="State", tracking=True)
|
||||
po_bill = fields.Selection(related="contract_id.po_bill")
|
||||
qty = fields.Integer(string="Qty")
|
||||
retention_percentage = fields.Float(string="Retention(%)")
|
||||
retention_amount = fields.Monetary(string="Retention Amount", compute="compute_retention_amount")
|
||||
final_amount = fields.Monetary(string="Total Amount", compute="_compute_final_amount")
|
||||
|
||||
# QC Check
|
||||
qc_user_id = fields.Many2one('res.users', string="QC Responsible", tracking=True)
|
||||
qc_status = fields.Selection([('draft', 'Draft'),
|
||||
('request', 'Department Approval'),
|
||||
('approve', 'Approve'),
|
||||
('reject', 'Reject')], default='draft', string="Quality Check Status", tracking=True)
|
||||
reject_reason = fields.Text(string="Reject Reason", tracking=True)
|
||||
|
||||
def unlink(self):
|
||||
for rec in self:
|
||||
if rec.qc_status != 'draft':
|
||||
raise ValidationError(_("You can't delete until Quality Check status is in Draft"))
|
||||
else:
|
||||
return super(OverheadContractLine, self).unlink()
|
||||
|
||||
@api.constrains('qty')
|
||||
def _check_ra_bill_qty(self):
|
||||
ra_bill_ids = self.env['overhead.contract.line'].search([('contract_id', '=', self.contract_id.id)])
|
||||
qty = 0
|
||||
for record in ra_bill_ids:
|
||||
if record.qc_status != 'reject':
|
||||
qty = qty + record.qty
|
||||
if qty > self.contract_id.qty:
|
||||
raise ValidationError(_("Quantity should be less than total qty."))
|
||||
|
||||
@api.depends('contract_id', 'qty', 'contract_id.tax_id')
|
||||
def _compute_percentage_amount(self):
|
||||
for rec in self:
|
||||
amount = 0.0
|
||||
if rec.qty and rec.contract_id:
|
||||
amount = (rec.contract_id.cost + (rec.contract_id.tax_id.amount * rec.contract_id.cost / 100)) * rec.qty
|
||||
rec.amount = amount
|
||||
|
||||
@api.depends('qty', 'retention_amount')
|
||||
def _compute_final_amount(self):
|
||||
for rec in self:
|
||||
total = 0.0
|
||||
if rec.amount:
|
||||
total = rec.amount - rec.retention_amount
|
||||
rec.final_amount = total
|
||||
|
||||
@api.depends('amount', 'retention_percentage')
|
||||
def compute_retention_amount(self):
|
||||
for rec in self:
|
||||
retention_amount = 0.0
|
||||
if rec.retention_percentage:
|
||||
retention_amount = rec.amount * rec.retention_percentage / 100
|
||||
rec.retention_amount = retention_amount
|
||||
|
||||
@api.depends('contract_id', 'amount')
|
||||
def _compute_percentage(self):
|
||||
for rec in self:
|
||||
percentage = 0.0
|
||||
if rec.contract_id and rec.amount > 0:
|
||||
percentage = (100 * rec.amount) / rec.contract_id.total_cost
|
||||
rec.percentage = percentage
|
||||
|
||||
def action_quality_check(self):
|
||||
self.qc_status = 'request'
|
||||
|
||||
def action_quality_check_approve(self):
|
||||
self.qc_status = 'approve'
|
||||
self.qc_user_id = self.env.user.id
|
||||
|
||||
def action_quality_check_reject(self):
|
||||
self.qc_status = 'reject'
|
||||
self.qc_user_id = self.env.user.id
|
||||
|
||||
def action_reset_to_draft(self):
|
||||
self.qc_status = 'draft'
|
||||
|
||||
def action_create_ra_bill(self):
|
||||
if self.po_bill == 'bill':
|
||||
record = {
|
||||
'product_id': self.contract_id.product_id.id,
|
||||
'name': self.contract_id.name,
|
||||
'quantity': 1,
|
||||
'price_unit': self.final_amount,
|
||||
'tax_ids': False
|
||||
}
|
||||
invoice_lines = [(0, 0, record)]
|
||||
data = {
|
||||
'partner_id': self.contract_id.vendor_id.id,
|
||||
'invoice_date': self.date,
|
||||
'invoice_line_ids': invoice_lines,
|
||||
'move_type': 'in_invoice',
|
||||
'overhead_subcontract_id': self.contract_id.id,
|
||||
'job_order_id': self.contract_id.job_order_id.id,
|
||||
'purchase_order': 'overhead'
|
||||
}
|
||||
invoice_id = self.env['account.move'].sudo().create(data)
|
||||
remaining_amount = self.contract_id.remaining_amount
|
||||
self.contract_id.remaining_amount = remaining_amount - self.amount
|
||||
self.bill_id = invoice_id.id
|
||||
qty = self.contract_id.remain_qty
|
||||
self.contract_id.remain_qty = qty - self.qty
|
||||
elif self.po_bill == 'purchase_order':
|
||||
purchase_record = {
|
||||
'product_id': self.contract_id.product_id.id,
|
||||
'name': self.contract_id.name
|
||||
,
|
||||
'product_qty': 1,
|
||||
'price_unit': self.final_amount,
|
||||
}
|
||||
purchase_lines = [(0, 0, purchase_record)]
|
||||
purchase_data = {
|
||||
'partner_id': self.contract_id.vendor_id.id,
|
||||
'order_line': purchase_lines,
|
||||
'job_order_id': self.contract_id.job_order_id.id,
|
||||
'overhead_subcontract_id': self.contract_id.id,
|
||||
'purchase_order': 'overhead'
|
||||
}
|
||||
purchase_order_id = self.env['purchase.order'].create(
|
||||
purchase_data)
|
||||
self.purchase_order_id = purchase_order_id.id
|
||||
remaining_amount = self.contract_id.remaining_amount
|
||||
self.contract_id.remaining_amount = remaining_amount - self.amount
|
||||
qty = self.contract_id.remain_qty
|
||||
self.contract_id.remain_qty = qty - self.qty
|
||||
|
||||
|
||||
class MaterialConsume(models.Model):
|
||||
_name = 'material.consume'
|
||||
_description = "Material Consume Order"
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_rec_name = 'seq'
|
||||
|
||||
seq = fields.Char(string='Sequence', required=True, readonly=True, default=lambda self: _('New'))
|
||||
date = fields.Date(string="Date", default=fields.Date.today())
|
||||
remark = fields.Char(string="Remark")
|
||||
|
||||
warehouse_id = fields.Many2one('stock.warehouse')
|
||||
consume_order_id = fields.Many2one('stock.picking', string="Consume Order")
|
||||
state = fields.Selection(related="consume_order_id.state", string="Status")
|
||||
consume_order_ids = fields.One2many('material.consume.line', 'material_consume_id', string="Material Consume")
|
||||
|
||||
# Project Details
|
||||
job_order_id = fields.Many2one('job.order', string="Work Order")
|
||||
phase_id = fields.Many2one(related="job_order_id.job_sheet_id", string="Project Phase(WBS)", store=True)
|
||||
project_id = fields.Many2one(related='job_order_id.project_id', string="Sub Project", store=True)
|
||||
task_id = fields.Many2one(related="job_order_id.task_id", string="Task", store=True)
|
||||
# Department
|
||||
department_id = fields.Many2one(related="job_order_id.department_id", string="Department", store=True)
|
||||
manager_ids = fields.Many2many('res.users', store=True, string="Manager")
|
||||
user_id = fields.Many2one(related="job_order_id.user_id", string="Responsible", store=True)
|
||||
|
||||
# Quality Check
|
||||
qc_user_id = fields.Many2one('res.users', string="QC Responsible", tracking=True)
|
||||
qc_status = fields.Selection([('draft', 'Draft'), ('request', 'Department Approval'), ('approve', 'Approve'),
|
||||
('reject', 'Reject'), ('cancel', 'Cancel')], default='draft',
|
||||
string="Quality Check Status", tracking=True)
|
||||
reject_reason = fields.Text(string="Reject Reason", tracking=True)
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
for vals in vals_list:
|
||||
if vals.get('seq', _('New')) == _('New'):
|
||||
vals['seq'] = self.env['ir.sequence'].next_by_code('material.consume') or _('New')
|
||||
res = super(MaterialConsume, self).create(vals_list)
|
||||
return res
|
||||
|
||||
def unlink(self):
|
||||
if self.qc_status != 'draft':
|
||||
raise ValidationError(_("You can't delete until Quality Check status is in Draft"))
|
||||
else:
|
||||
return super(MaterialConsume, self).unlink()
|
||||
|
||||
@api.constrains('consume_order_ids')
|
||||
def _check_material_line_qty(self):
|
||||
for rec in self.consume_order_ids:
|
||||
if rec.qty > rec.material_line_id.remain_qty:
|
||||
raise ValidationError(_("Qty should be less than remain Qty."))
|
||||
|
||||
def action_quality_check(self):
|
||||
self.qc_status = 'request'
|
||||
|
||||
def action_quality_check_approve(self):
|
||||
self.qc_status = 'approve'
|
||||
self.qc_user_id = self.env.user.id
|
||||
|
||||
def action_quality_check_reject(self):
|
||||
self.qc_status = 'reject'
|
||||
self.qc_user_id = self.env.user.id
|
||||
|
||||
def action_reset_to_draft(self):
|
||||
self.qc_status = 'draft'
|
||||
|
||||
def action_cancel_consume_order(self):
|
||||
self.qc_status = 'cancel'
|
||||
|
||||
def action_create_consume_order(self):
|
||||
dest_location_id = False
|
||||
if self.warehouse_id.consume_stock_location_id:
|
||||
dest_location_id = self.warehouse_id.consume_stock_location_id
|
||||
else:
|
||||
dest_location_id = self.env['stock.location'].create(
|
||||
{'name': "Consume Location/" + str(self.warehouse_id.name), 'usage': 'production'})
|
||||
self.warehouse_id.consume_stock_location_id = dest_location_id.id
|
||||
lines = []
|
||||
for rec in self.consume_order_ids:
|
||||
lines.append((0, 0, {
|
||||
'product_id': rec.material_id.id,
|
||||
'product_uom_qty': rec.qty,
|
||||
'product_uom': rec.uom_id.id,
|
||||
'location_id': self.warehouse_id.lot_stock_id.id,
|
||||
'location_dest_id': dest_location_id.id,
|
||||
'name': rec.name
|
||||
}))
|
||||
source_id = self.warehouse_id.lot_stock_id
|
||||
stock_picking_type_id = self.env['stock.picking.type'].search(
|
||||
[('code', '=', 'outgoing'), ('warehouse_id', '=', self.warehouse_id.id)], limit=1)
|
||||
delivery_record = {
|
||||
'picking_type_id': stock_picking_type_id.id,
|
||||
'location_id': source_id.id,
|
||||
'location_dest_id': dest_location_id.id,
|
||||
'move_ids_without_package': lines,
|
||||
'consume_order_id': self.job_order_id.id,
|
||||
'material_consume_id': self.id,
|
||||
'move_type': 'one'
|
||||
}
|
||||
delivery_id = self.env['stock.picking'].create(delivery_record)
|
||||
self.consume_order_id = delivery_id.id
|
||||
for rec in self.consume_order_ids:
|
||||
remain_qty = rec.material_line_id.remain_qty
|
||||
usage_qty = rec.material_line_id.usage_qty
|
||||
rec.material_line_id.remain_qty = remain_qty - rec.qty
|
||||
rec.material_line_id.usage_qty = usage_qty + rec.qty
|
||||
return {
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': _('Consume Order'),
|
||||
'res_model': 'stock.picking',
|
||||
'res_id': delivery_id.id,
|
||||
'view_mode': 'form',
|
||||
'target': 'current'
|
||||
}
|
||||
|
||||
|
||||
class MaterialConsumeLine(models.Model):
|
||||
_name = 'material.consume.line'
|
||||
_description = "Material Consume Line"
|
||||
|
||||
material_id = fields.Many2one('product.product', string="Material", domain="[('is_material','=',True)]")
|
||||
uom_id = fields.Many2one(related="material_id.uom_id", string="UOM")
|
||||
name = fields.Char(string="Description")
|
||||
qty = fields.Integer(string="Qty")
|
||||
material_consume_id = fields.Many2one('material.consume', string="Material Consume")
|
||||
qc_status = fields.Selection(related="material_consume_id.qc_status")
|
||||
material_line_id = fields.Many2one('order.material.line')
|
||||
Reference in New Issue
Block a user