Slink/sos_inventory/models/sos_ir.py

492 lines
23 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="Materials Lines",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)
if component.shelf_life == "yes":
shelflife_line_values = {
'ir_ref_no':self.id,
'name': item.component_id.id, # Reference the created GRN
'quantity': item.qty,
'expiry_date':item.expiry_date
}
shellife_record = self.env['sos_shelflife_register'].create(shelflife_line_values)
#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")
shelf_life = fields.Selection([('yes', 'Yes'), ('no', 'No')],related="component_id.shelf_life", string="Shelf Life")
@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
}