482 lines
22 KiB
Python
Executable File
482 lines
22 KiB
Python
Executable File
# -*- coding: utf-8 -*-
|
|
|
|
from odoo import models, fields, api
|
|
from datetime import datetime
|
|
from odoo.exceptions import UserError
|
|
|
|
class SOS_IR(models.Model):
|
|
_name = 'sos_ir'
|
|
_description = 'Inward Register'
|
|
_rec_name = 'ir_no'
|
|
_order = 'received_date desc, id desc'
|
|
|
|
ir_no=fields.Char(string="Inward Reference No",default=lambda self: self._generate_id())
|
|
supplier_name = fields.Many2one('sos_suppliers', string="Supplier Name")
|
|
supplier_address = fields.Text(related='supplier_name.address', string="Supplier Address")
|
|
service_provider_name = fields.Many2one('sos_service_providers', string="Service Provider Name")
|
|
service_provider_address = fields.Char(related='service_provider_name.address', string="Service Provider Address")
|
|
po_no = fields.Many2one(
|
|
'sos_po',
|
|
string="P.O No",
|
|
domain="[('po_status', '=', 'open'), ('supplier_name', '=', supplier_name)]"
|
|
)
|
|
wo_no = fields.Many2one(
|
|
'sos_wo',
|
|
string="W.O No",
|
|
domain="[('wo_status', '=', 'open'), ('supplier_name', '=', service_provider_name)]"
|
|
)
|
|
wo_no_inhouse = fields.Many2one(
|
|
'sos_wo',
|
|
string="W.O No",
|
|
domain="[('wo_status', '=', 'open'), ('wo_planned_at', '=', 'inhouse')]"
|
|
)
|
|
dc_no = fields.Many2one('sos_dc',string="DC No/Invoice No")
|
|
dc_date = fields.Datetime(string="DC Date/Invoice Date")
|
|
dc_no_char = fields.Char(string="DC No/Invoice No")
|
|
received_date = fields.Date(string="Received Date",default=fields.Date.today)
|
|
receiving_dept = fields.Many2one('sos_departments',string="Receiving Department")
|
|
receiving_by = fields.Many2one('res.users', string='Received By')
|
|
parcel_count = fields.Char(string="No of Bags/Barrels/Rolls/Boxes")
|
|
received_goods_type = fields.Selection([
|
|
('Materials', 'Materials'),
|
|
('SFG', 'SFG'),
|
|
('FG', 'FG')
|
|
], string='Goods Type',default="Materials",copy=True)
|
|
line_ids_material = fields.One2many('sos_ir_line_material', 'ir_id', string="Components for Materials",copy=True)
|
|
vehicle_type = fields.Selection([
|
|
('yes', 'Yes'),
|
|
('no', 'No'),
|
|
],string="Material Received in Top Closed Vehicle")
|
|
boxes_sealing = fields.Selection([
|
|
('yes', 'Yes'),
|
|
('no', 'No'),
|
|
], string="Boxes/Bag/Barrels/Rolls Sealing shall be in-tact")
|
|
line_ids_sfg = fields.One2many('sos_ir_line_sfg', 'ir_id', string="Components for SFG",copy=True)
|
|
line_ids_fg = fields.One2many('sos_ir_line_fg', 'ir_id', string="Components for FG",copy=True)
|
|
stores_approval_name = fields.Many2one('res.users', string='Stores Received By')
|
|
stores_approval_image = fields.Image(related="stores_approval_name.signature_image",string='Stores-RM/PM In Charge')
|
|
stores_approved_on = fields.Datetime(string="Approved On")
|
|
indent_no = fields.Many2one('sos_fg_plan',string="Indent No")
|
|
top_management_name = fields.Many2one('res.users', string='Top Management Approver')
|
|
top_management_approval_image = fields.Image(related="top_management_name.signature_image",string='Top Management Approval')
|
|
top_management_approved_on = fields.Datetime(string="Approved On")
|
|
wo_planned_at = fields.Selection([('inhouse', 'In-House'),('outsource', 'Out-Sourcing')],default="outsource",string="W.O Planned at")
|
|
dept_in_charge_name = fields.Many2one('res.users', string='Department In-Charge')
|
|
dept_in_charge_image = fields.Image(related="dept_in_charge_name.signature_image",string='Department In-Charge Sign',readonly=True)
|
|
dept_in_charge_approved_on = fields.Datetime(string="Approved On")
|
|
test_report = fields.Binary(string="DC/Invoice Document")
|
|
test_report_filename=fields.Char(string="DC DocumentFile Name")
|
|
#Rework
|
|
orr_no = fields.Many2one('sos_sfg_outsourcing_return_register',string="Ref No")
|
|
iqi_no = fields.Many2one('sos_iqi',string="IQI No",related="orr_no.iqi_no")
|
|
currency_id = fields.Many2one('res.currency', string='Currency')
|
|
service_charge = fields.Monetary(string="Service Charge",currency_field='currency_id')
|
|
_sql_constraints = [
|
|
('ir_no_unique', 'UNIQUE(ir_no)', 'The IR No must be unique!')
|
|
]
|
|
|
|
@api.onchange('orr_no')
|
|
def _onchange_orr_no(self):
|
|
if self.orr_no:
|
|
ir_ref_no = self.orr_no.iqi_no.ir_id_unique_id
|
|
matching_ir_records = self.env['sos_ir'].search([('ir_no', 'like', f"{ir_ref_no.ir_no}%")], limit=1)
|
|
variable = matching_ir_records.ir_no
|
|
if variable[-1].isdigit():
|
|
next_char = "(a)"
|
|
self.ir_no = variable + next_char
|
|
else:
|
|
last_char = variable[-2]
|
|
if 'a' <= last_char <= 'z':
|
|
next_char = f"({chr(ord(last_char) + 1)})" if last_char != 'z' else "(a)"
|
|
new_variable = variable[:-3]
|
|
self.ir_no = new_variable + next_char
|
|
|
|
|
|
self.received_goods_type = self.orr_no.goods_type
|
|
if self.orr_no.goods_type == "SFG":
|
|
self.service_provider_name = ir_ref_no.service_provider_name
|
|
self.wo_no = ir_ref_no.wo_no
|
|
sfg_lines = [(5, 0, 0)]
|
|
sfg_lines.append((0, 0, {
|
|
'component_id': self.iqi_no.sfg_name,
|
|
'qty': self.iqi_no.rejected_qty,
|
|
'order_qty': self.iqi_no.rejected_qty
|
|
}))
|
|
self.line_ids_sfg = sfg_lines
|
|
else:
|
|
self.supplier_name = ir_ref_no.supplier_name
|
|
#self.po_no = ir_ref_no.po_no
|
|
material_lines = [(5, 0, 0)]
|
|
material_lines.append((0, 0, {
|
|
'component_id': self.iqi_no.material_name,
|
|
'qty': self.iqi_no.rejected_qty,
|
|
'order_qty': self.iqi_no.rejected_qty
|
|
}))
|
|
self.line_ids_material = material_lines
|
|
self.parcel_count = ir_ref_no.parcel_count
|
|
self.vehicle_type = ir_ref_no.vehicle_type
|
|
self.boxes_sealing = ir_ref_no.boxes_sealing
|
|
self.test_report = ir_ref_no.test_report
|
|
self.test_report_filename = ir_ref_no.test_report_filename
|
|
|
|
|
|
def action_view_invoice(self):
|
|
"""Action to view the PDF of the test report."""
|
|
# Check if there is a test report
|
|
if not self.test_report:
|
|
raise UserError("No test report available for this record.")
|
|
|
|
# Use `ir.actions.act_url` to open the binary file as a PDF
|
|
return {
|
|
'type': 'ir.actions.act_url',
|
|
'url': '/web/content/{}/{}/{}?download=false'.format(
|
|
self._name, self.id, 'test_report'),
|
|
'target': 'new', # This opens the PDF in a new tab
|
|
}
|
|
@api.onchange('po_no')
|
|
def _onchange_po_no(self):
|
|
if self.po_no:
|
|
try:
|
|
lines = [(5, 0, 0)]
|
|
|
|
for param in self.po_no.line_ids:
|
|
if param.status in [0, 1]:
|
|
if param.prev_received_qty < param.quantity:
|
|
qty = param.quantity - param.prev_received_qty
|
|
else:
|
|
qty = param.quantity
|
|
lines.append((0, 0, {
|
|
'component_id': param.component_id.id,
|
|
'qty': qty,
|
|
'order_qty': param.quantity,
|
|
'unit_price': param.unit_price
|
|
}))
|
|
self.line_ids_material = lines
|
|
|
|
except Exception as e:
|
|
print("Error processing po_no: %s", str(e))
|
|
@api.onchange('wo_no')
|
|
def _onchange_wo_no(self):
|
|
if self.wo_no:
|
|
try:
|
|
lines = [(5, 0, 0)]
|
|
|
|
for param in self.wo_no.line_ids:
|
|
lines.append((0, 0, {
|
|
'component_id': param.component_id.id,
|
|
'qty': param.quantity,
|
|
'order_qty': param.quantity
|
|
}))
|
|
self.line_ids_sfg = lines
|
|
|
|
except Exception as e:
|
|
print("Error processing po_no: %s", str(e))
|
|
@api.onchange('wo_no_inhouse')
|
|
def _onchange_wo_no_inhouse(self):
|
|
if self.wo_no_inhouse:
|
|
try:
|
|
lines = [(5, 0, 0)]
|
|
|
|
for param in self.wo_no_inhouse.line_ids:
|
|
lines.append((0, 0, {
|
|
'component_id': param.component_id.id,
|
|
'qty': param.quantity,
|
|
'order_qty': param.quantity
|
|
}))
|
|
self.line_ids_sfg = lines
|
|
|
|
except Exception as e:
|
|
print("Error processing po_no: %s", str(e))
|
|
|
|
|
|
def action_report_ir_btn(self):
|
|
try:
|
|
action = self.env.ref("sos_inventory.action_report_ir").report_action(self)
|
|
return action
|
|
except ValueError as e:
|
|
print(f"Failed to find report action: {e}")
|
|
def _generate_id(self):
|
|
sequence_util = self.env['sos_common_scripts']
|
|
return sequence_util.generate_sequence('sos_ir','IR', 'ir_no')
|
|
|
|
def action_report_esign_btn(self):
|
|
|
|
iqi_model = self.env['sos_iqi']
|
|
grn_model = self.env['sos_grn']
|
|
grn_line_model = self.env['sos_grn_line']
|
|
sequence_util = self.env['sos_common_scripts']
|
|
material_model = self.env['sos_material']
|
|
iqi_no = sequence_util.generate_sequence('sos_iqi', 'iqi', 'iqi_no')
|
|
grn_no = sequence_util.generate_sequence('sos_grn', 'GRN', 'grn_no')
|
|
if self.received_goods_type == "Materials":
|
|
iqi_record = None
|
|
grn_record = None
|
|
iqi_lines_to_create = []
|
|
grn_line_values = []
|
|
|
|
for item in self.line_ids_material:
|
|
# Fetch the component related to the current item
|
|
component = self.env['sos_material'].browse(item.component_id.id)
|
|
#print(component)
|
|
#raise UserError("The PO Number already exists. Validation failed.")
|
|
if self.po_no:
|
|
for pos in self.po_no.line_ids:
|
|
if component.id == pos.component_id.id:
|
|
if item.qty >= pos.quantity:
|
|
pos.status = 2
|
|
pos.prev_received_qty = item.qty
|
|
self.po_no.received_qty += 1
|
|
elif item.qty > 0:
|
|
pos.prev_received_qty = pos.prev_received_qty + item.qty
|
|
pos.status = 1
|
|
if pos.prev_received_qty >= pos.quantity:
|
|
pos.status = 2
|
|
self.po_no.received_qty += 1
|
|
|
|
else:
|
|
pos.status = 0
|
|
|
|
|
|
if component.inspection_method == 10:
|
|
if not grn_record:
|
|
grn_record_values = {
|
|
'grn_no': grn_no,
|
|
'ir_no':self.id,
|
|
'supplier_name': self.supplier_name.id,
|
|
'received_goods_type': 'Materials',
|
|
'supplier_invoice_no':self.dc_no_char,
|
|
'po_no':self.po_no.id
|
|
}
|
|
if iqi_record:
|
|
grn_record_values['iqi_no'] = iqi_record.id
|
|
grn_record = grn_model.with_context(from_script=True).create(grn_record_values)
|
|
|
|
if item.qty > 0:
|
|
grn_line_values = {
|
|
'grn_id': grn_record.id, # Reference the created GRN
|
|
'component_id': item.component_id.id,
|
|
'received_qty': item.qty,
|
|
'approved_qty':item.qty,
|
|
'invoice_qty':item.order_qty,
|
|
'unit_price':item.unit_price
|
|
}
|
|
grn_line_model.with_context(from_script=True).create(grn_line_values)
|
|
|
|
|
|
else:
|
|
iqi_record = self.env['sos_iqi'].create({
|
|
'iqi_no': sequence_util.generate_sequence('sos_iqi', 'IQI', 'iqi_no'),
|
|
'material_option':True,
|
|
'sfg_option':False,
|
|
'supplier_name': self.supplier_name.id,
|
|
'batch_no':item.batch_no,
|
|
'received_qty':item.qty,
|
|
'uom': item.component_id.uom,
|
|
'material_name': item.component_id.id,
|
|
'material_code': item.component_id.material_code,
|
|
'in_tact':self.boxes_sealing,
|
|
'invoice_no':self.dc_no_char,
|
|
'invoice_date':self.dc_date,
|
|
'ir_id_unique_id':self.id,
|
|
'from_origin':"Vendor",
|
|
'unit_price':item.unit_price
|
|
|
|
|
|
})
|
|
# Email part
|
|
body_html = f"""
|
|
<p>Below <b>IQI</b> is waiting for your Approval</p>
|
|
"""
|
|
send_email = self.env['sos_common_scripts']
|
|
send_email.send_group_email(self.env,'sos_iqi',iqi_record.id,"deenalaura.m@sosaley.in","IQI Approval Request",body_html,'sos_inventory.sos_qc_user')
|
|
# Email part ends
|
|
elif self.received_goods_type == "SFG":
|
|
for item in self.line_ids_sfg:
|
|
# PO update part
|
|
sfg_component = self.env['sos_sfg'].browse(item.component_id.id)
|
|
if self.wo_planned_at == "outsource":
|
|
if self.wo_no:
|
|
if not self.orr_no:
|
|
for pos in self.wo_no.line_ids:
|
|
if sfg_component.id == pos.component_id.id:
|
|
pos.last_received_quantity += item.qty
|
|
else:
|
|
if self.wo_no_inhouse:
|
|
if not self.orr_no:
|
|
for pos in self.wo_no_inhouse.line_ids:
|
|
if sfg_component.id == pos.component_id.id:
|
|
pos.last_received_quantity = pos.last_received_quantity + item.qty
|
|
|
|
iqi_data = {
|
|
'iqi_no': sequence_util.generate_sequence('sos_iqi', 'IQI', 'iqi_no'),
|
|
'material_option':False,
|
|
'sfg_option':True,
|
|
'service_provider_name': self.service_provider_name.id,
|
|
'batch_no':item.batch_no,
|
|
'received_qty':item.qty,
|
|
'sfg_name': item.component_id.id,
|
|
'sfg_code': item.component_id.sfg_code,
|
|
'in_tact':self.boxes_sealing,
|
|
'invoice_no':self.dc_no_char,
|
|
'invoice_date':self.dc_date,
|
|
'ir_id_unique_id':self.id,
|
|
'from_origin':"Vendor"
|
|
|
|
}
|
|
if self.iqi_no.id:
|
|
iqi_data['iqi_no'] = sequence_util.generate_sequence('sos_iqi', 'R-IQI', 'iqi_no')
|
|
iqi_data['old_iqi_ref'] = self.iqi_no.id
|
|
iqi_data['iqi_type'] = 'rework'
|
|
# Rework Iteration starts
|
|
sos_record = self.env['sos_iqi'].search([('id', '=', self.iqi_no.id)], limit=1)
|
|
if sos_record:
|
|
rework_iteration = sos_record.reworked_count + 1
|
|
|
|
sos_record.write({
|
|
'reworked_count':rework_iteration
|
|
})
|
|
# Rework Iteration ends
|
|
iqi_record = self.env['sos_iqi'].create(iqi_data)
|
|
body_html = f"""
|
|
<p>Below <b>IQI</b> is waiting for your response</p>
|
|
"""
|
|
|
|
send_email = self.env['sos_common_scripts']
|
|
send_email.send_group_email(self.env,"sos_iqi",iqi_record.id,"deenalaura.m@sosaley.in","IQI Request",body_html,'sos_inventory.sos_qc_user')
|
|
|
|
sequence_util = self.env['sos_common_scripts']
|
|
sequence_util.action_assign_signature(
|
|
self,
|
|
'stores_approval_name',
|
|
'stores_approved_on',
|
|
'sos_inventory.sos_scg_group_user'
|
|
)
|
|
# Email part
|
|
body_html = f"""
|
|
<p>Below <b>Inward</b> is waiting for your Approval</p>
|
|
"""
|
|
|
|
send_email = self.env['sos_common_scripts']
|
|
send_email.send_group_email(self.env,"sos_ir",self.id,"deenalaura.m@sosaley.in","Incoming Material Received",body_html,'sos_inventory.sos_scg_group_manager')
|
|
# Email part ends
|
|
|
|
def action_deptincharge_esign_btn(self):
|
|
# Email part
|
|
body_html = f"""
|
|
<p>Below <b>Inward</b> is waiting for your Approval</p>
|
|
"""
|
|
subject = f"Inward Approval Request - {self.ir_no}"
|
|
send_email = self.env['sos_common_scripts']
|
|
send_email.send_direct_email(self.env,"sos_ir",self.id,"ramachandran.r@sosaley.in",subject,body_html)
|
|
# Email part ends
|
|
sequence_util = self.env['sos_common_scripts']
|
|
return sequence_util.action_assign_signature(
|
|
self,
|
|
'dept_in_charge_name',
|
|
'dept_in_charge_approved_on'
|
|
)
|
|
def action_topmanagement_esign_btn(self):
|
|
sequence_util = self.env['sos_common_scripts']
|
|
sequence_util.action_assign_signature(
|
|
self,
|
|
'top_management_name',
|
|
'top_management_approved_on',
|
|
'sos_inventory.sos_management_user'
|
|
)
|
|
body_html = f"""
|
|
<p>Below <b>Inward</b> was received</p>
|
|
"""
|
|
|
|
send_email = self.env['sos_common_scripts']
|
|
send_email.send_group_email(self.env,"sos_ir",self.id,"deenalaura.m@sosaley.in","Material Received",body_html,'sos_inventory.sos_finance_user')
|
|
|
|
|
|
class SOS_IR_Line_Material(models.Model):
|
|
_name = 'sos_ir_line_material'
|
|
_description = 'Inward Register Material Lines'
|
|
|
|
ir_id = fields.Many2one('sos_ir', string="IR", ondelete="cascade")
|
|
component_id = fields.Many2one('sos_material', string="Part No", required=True)
|
|
name = fields.Char(related="component_id.name")
|
|
uom = fields.Selection(related="component_id.uom")
|
|
inspection_method = fields.Integer(related="component_id.inspection_method")
|
|
material_code = fields.Char(related="component_id.material_code")
|
|
batch_no = fields.Char(string="Batch No / Lot No")
|
|
order_qty = fields.Integer(string="Order Quantity")
|
|
invoice_qty = fields.Integer(string="Invoice Quantity")
|
|
qty = fields.Integer(string="Received Quantity")
|
|
currency_id = fields.Many2one('res.currency', string='Currency')
|
|
unit_price = fields.Monetary(string="Unit Price", currency_field='currency_id')
|
|
test_report = fields.Binary(string="Test Report")
|
|
test_report_filename=fields.Char(string="Test Report File Name")
|
|
expiry_date = fields.Date(string="Expiry Date")
|
|
@api.onchange('component_id')
|
|
def _onchange_component_id(self):
|
|
if self.component_id:
|
|
self.unit_price = self.component_id.unit_price
|
|
|
|
def action_view_pdf(self):
|
|
"""Action to view the PDF of the test report."""
|
|
# Check if there is a test report
|
|
if not self.test_report:
|
|
raise UserError("No test report available for this record.")
|
|
|
|
# Use `ir.actions.act_url` to open the binary file as a PDF
|
|
return {
|
|
'type': 'ir.actions.act_url',
|
|
'url': '/web/content/{}/{}/{}?download=false'.format(
|
|
self._name, self.id, 'test_report'),
|
|
'target': 'new', # This opens the PDF in a new tab
|
|
}
|
|
class SOS_IR_Line_SFG(models.Model):
|
|
_name = 'sos_ir_line_sfg'
|
|
_description = 'Inward Register SFG Lines'
|
|
|
|
ir_id = fields.Many2one('sos_ir', string="IR", ondelete="cascade")
|
|
component_id = fields.Many2one('sos_sfg', string="Part No", required=True)
|
|
sfg_code = fields.Char(related="component_id.sfg_code")
|
|
batch_no = fields.Char(string="Batch No / Lot No")
|
|
invoice_qty = fields.Integer(string="Invoice Quantity")
|
|
order_qty = fields.Integer(string="Order Quantity")
|
|
qty = fields.Integer(string="Received Quantity")
|
|
test_report = fields.Binary(string="Test Report")
|
|
test_report_filename=fields.Char(string="Test Report File Name")
|
|
def action_view_pdf(self):
|
|
"""Action to view the PDF of the test report."""
|
|
# Check if there is a test report
|
|
if not self.test_report:
|
|
raise UserError("No test report available for this record.")
|
|
|
|
# Use `ir.actions.act_url` to open the binary file as a PDF
|
|
return {
|
|
'type': 'ir.actions.act_url',
|
|
'url': '/web/content/{}/{}/{}?download=false'.format(
|
|
self._name, self.id, 'test_report'),
|
|
'target': 'new', # This opens the PDF in a new tab
|
|
}
|
|
class SOS_IR_Line_FG(models.Model):
|
|
_name = 'sos_ir_line_fg'
|
|
_description = 'Inward Register FG Lines'
|
|
|
|
ir_id = fields.Many2one('sos_ir', string="IR", ondelete="cascade")
|
|
component_id = fields.Many2one('sos_fg', string="Part No", required=True)
|
|
fg_code = fields.Char(related="component_id.fg_code")
|
|
batch_no = fields.Char(string="Batch No / Lot No")
|
|
invoice_qty = fields.Integer(string="Invoice Quantity")
|
|
order_qty = fields.Integer(string="Order Quantity")
|
|
qty = fields.Integer(string="Received Quantity")
|
|
test_report = fields.Binary(string="Test Report")
|
|
test_report_filename=fields.Char(string="Test Report File Name")
|
|
def action_view_pdf(self):
|
|
"""Action to view the PDF of the test report."""
|
|
# Check if there is a test report
|
|
if not self.test_report:
|
|
raise UserError("No test report available for this record.")
|
|
|
|
# Use `ir.actions.act_url` to open the binary file as a PDF
|
|
return {
|
|
'type': 'ir.actions.act_url',
|
|
'url': '/web/content/{}/{}/{}?download=false'.format(
|
|
self._name, self.id, 'test_report'),
|
|
'target': 'new', # This opens the PDF in a new tab
|
|
} |