367 lines
19 KiB
Python
Executable File
367 lines
19 KiB
Python
Executable File
# -*- coding: utf-8 -*-
|
|
|
|
from odoo import models, fields, api
|
|
import time
|
|
from odoo.exceptions import UserError
|
|
|
|
class sos__mrn(models.Model):
|
|
_name = 'sos_mrn'
|
|
_description = 'Return Note'
|
|
_rec_name = 'mrn_no'
|
|
_order = 'id desc'
|
|
|
|
mrn_no = fields.Char(string="MRN/SRN/FRN No", readonly= True, required= True, default=lambda self: self._generate_id(),copy=False)
|
|
mrn_date = fields.Datetime(string="MRN/SRN/FRN Date", required=True, default=fields.Datetime.now,copy=False)
|
|
min_no = fields.Many2one('sos_min',string="MIN/SIN/FIN No",copy=False)
|
|
min_date = fields.Date(related="min_no.min_date",string="MIN/SIN/FIN Date",copy=False)
|
|
filled_by = fields.Many2one('res.users', string='Filled By', readonly=True,required=True,default=lambda self: self.env.user)
|
|
prepared_by_name = fields.Many2one('res.users', string='Prepared by',copy=False)
|
|
prepared_by_image = fields.Image(related="prepared_by_name.signature_image",string='Prepared by Sign',readonly=True,copy=False)
|
|
prepared_on = fields.Datetime(string="Approved On",copy=False)
|
|
reporting_to = fields.Many2one('res.users',related="prepared_by_name.reporting_to", string='Prepared by')
|
|
dept_in_charge_name = fields.Many2one('res.users', string='Department In-Charge',copy=False)
|
|
dept_in_charge_image = fields.Image(related="dept_in_charge_name.signature_image",string='Department In-Charge Sign',readonly=True,copy=False)
|
|
dept_in_charge_approved_on = fields.Datetime(string="Approved On",copy=False)
|
|
stores_approved_by = fields.Many2one('res.users', string='Stores Approved By',copy=False)
|
|
stores_approved_image = fields.Image(related="stores_approved_by.signature_image",string='Stores Approval Sign',readonly=True,copy=False)
|
|
stores_approved_on = fields.Datetime(string="Approved On",copy=False)
|
|
qa_approved_by = fields.Many2one('res.users', string='QA Approved By',copy=False)
|
|
qa_approved_image = fields.Image(related="qa_approved_by.signature_image",string='QA Approval Sign',readonly=True,copy=False)
|
|
qa_approved_on = fields.Datetime(string="Approved On",copy=False)
|
|
material_option = fields.Boolean('Materials', default=True)
|
|
sfg_option = fields.Boolean('Semi-Finished Goods')
|
|
fg_option = fields.Boolean('Finished Goods')
|
|
return_type = fields.Selection([('excess_qty', 'SFG Assembling, Excess Qty'),('customer', 'Customer Complaint'), ('spare', 'Spare'), ('service', 'Service'), ('expo', 'Expo'), ('demo', 'Demo'), ('others', 'Others')], string="Return Type")
|
|
customer_name=fields.Char(string="Customer Name")
|
|
order_type = fields.Char(string='order_type',copy=True)
|
|
line_ids_material = fields.One2many('sos_mrn_line_material', 'mrn_id', string="Materials",copy=True)
|
|
line_ids_sfg = fields.One2many('sos_mrn_line_sfg', 'mrn_id', string="Semi-Finished Goods",copy=True)
|
|
line_ids_fg = fields.One2many('sos_mrn_line_fg', 'mrn_id', string="Finished Goods",copy=True)
|
|
show_customer = fields.Boolean(compute="_compute_show_customer", store=False)
|
|
company_id = fields.Many2one('res.company', store=True, copy=False,
|
|
string="Company",
|
|
default=lambda self: self.env.user.company_id.id)
|
|
currency_id = fields.Many2one('res.currency', string="Currency",
|
|
related='company_id.currency_id',
|
|
default=lambda
|
|
self: self.env.user.company_id.currency_id.id)
|
|
approx_value = fields.Monetary(compute='_compute_approx_value', string="Approximate Value", currency_field='currency_id', readonly=True)
|
|
|
|
@api.depends('line_ids_material.total_cost')
|
|
def _compute_approx_value(self):
|
|
for record in self:
|
|
record.approx_value = sum(line.total_cost for line in record.line_ids_material)
|
|
@api.depends('return_type')
|
|
def _compute_show_customer(self):
|
|
for rec in self:
|
|
rec.show_customer = rec.return_type in ['spare', 'service', 'customer']
|
|
# @api.model
|
|
# def create(self, vals):
|
|
# record = super(sos__mrn, self).create(vals)
|
|
# record.action_report_esign_btn()
|
|
# return record
|
|
|
|
@api.onchange('material_option', 'sfg_option', 'fg_option')
|
|
def _onchange_material_option(self):
|
|
options = []
|
|
if self.material_option:
|
|
options.append("Material")
|
|
if self.sfg_option:
|
|
options.append("SFG")
|
|
if self.fg_option:
|
|
options.append("FG")
|
|
|
|
self.order_type = ",".join(options)
|
|
|
|
def _generate_id(self):
|
|
sequence_util = self.env['sos_common_scripts']
|
|
return sequence_util.generate_sequence('sos_mrn','MRN', 'mrn_no')
|
|
|
|
def action_report_mrn_btn(self):
|
|
try:
|
|
action = self.env.ref("sos_inventory.action_report_mrn").report_action(self)
|
|
return action
|
|
except ValueError as e:
|
|
print(f"Failed to find report action: {e}")
|
|
|
|
def action_report_esign_incharge(self):
|
|
# Email part
|
|
body_html = f"""
|
|
<p>Below <b>Return Note</b> is waiting for your Approval</p>
|
|
"""
|
|
send_email = self.env['sos_common_scripts']
|
|
send_email.send_group_email(self.env,'sos_mrn',self.id,"deenalaura.m@sosaley.in","Return Note Approval Request",body_html,'sos_inventory.sos_qa_user')
|
|
# Email part ends
|
|
send_email.action_assign_signature(
|
|
self,
|
|
'dept_in_charge_name',
|
|
'dept_in_charge_approved_on'
|
|
)
|
|
def action_qa_esign(self):
|
|
# Email part
|
|
body_html = f"""
|
|
<p>Below <b>Return Note</b> is waiting for your Approval</p>
|
|
"""
|
|
send_email = self.env['sos_common_scripts']
|
|
send_email.send_group_email(self.env,'sos_mrn',self.id,"deenalaura.m@sosaley.in","Return Note Approval Request",body_html,'sos_inventory.sos_scg_group_user')
|
|
# Email part ends
|
|
send_email.action_assign_signature(
|
|
self,
|
|
'qa_approved_by',
|
|
'qa_approved_on',
|
|
'sos_inventory.sos_qa_user'
|
|
)
|
|
|
|
def action_report_esign_btn1(self):
|
|
sequence_util = self.env['sos_common_scripts']
|
|
splitted=self.order_type.split(",")
|
|
if self.return_type == "customer":
|
|
sequence_util = self.env['sos_common_scripts']
|
|
tc_no = sequence_util.generate_sequence('sos_transfer_challan_return_from_customer','TC', 'tc_no')
|
|
customer_return_record = self.env['sos_transfer_challan_return_from_customer'].create({
|
|
'tc_no': tc_no,
|
|
'mrn_ref_no':self.id
|
|
})
|
|
for eachone in splitted:
|
|
if eachone == "Material":
|
|
for item in self.line_ids_material:
|
|
component = self.env['sos_material'].browse(item.component_id.id)
|
|
|
|
if item.qa_decision == "to_stores":
|
|
current_qty = getattr(component, 'inhand_stock_qty', 0)
|
|
new_qty = current_qty + item.quantity
|
|
component.write({'inhand_stock_qty': new_qty})
|
|
component.line_ids_in.create({'ref_id': component.id,'component_id': item.component_id.id,
|
|
'quantity' : item.quantity,'mrn_no':self.id,
|
|
'action' : 'in'})
|
|
else:
|
|
iqi_record = self.env['sos_return_iqi'].create({
|
|
'iqi_no': sequence_util.generate_sequence('sos_return_iqi', 'Return-IQI', 'iqi_no'),
|
|
'material_option':True,
|
|
'sfg_option':False,
|
|
'received_qty':item.quantity,
|
|
'material_name': item.component_id.id,
|
|
'material_code': item.component_id.material_code,
|
|
'mrn_id':self.id
|
|
|
|
})
|
|
if customer_return_record and self.return_type == "customer" and item.qa_decision != "to_stores":
|
|
create_vals = {
|
|
'tc_id': customer_return_record.id,
|
|
'item_name': component.name,
|
|
'item_type': 'Material',
|
|
'return_incoming_doc_ref':iqi_record.id if iqi_record else None
|
|
}
|
|
new_line = self.env['sos_transfer_challan_return_from_customer_lines'].create(create_vals)
|
|
|
|
|
|
# Email part
|
|
body_html = f"""
|
|
<p>Below <b>Return-IQI</b> is waiting for your Approval</p>
|
|
"""
|
|
send_email = self.env['sos_common_scripts']
|
|
send_email.send_group_email(self.env,'sos_return_iqi',iqi_record.id,"deenalaura.m@sosaley.in","Return-IQI Inspection Request",body_html,'sos_inventory.sos_qc_user')
|
|
# Email part ends
|
|
elif eachone == "SFG":
|
|
for item in self.line_ids_sfg:
|
|
component = self.env['sos_sfg'].browse(item.component_id.id)
|
|
|
|
if item.qa_decision == "to_stores":
|
|
current_qty = getattr(component, 'inhand_stock_qty', 0)
|
|
new_qty = current_qty + item.quantity
|
|
component.write({'inhand_stock_qty': new_qty})
|
|
component.line_ids_in.create({'ref_id': component.id,'component_id': item.component_id.id,
|
|
'quantity' : item.quantity,'mrn_no':self.id,
|
|
'action' : 'in'})
|
|
else:
|
|
if component:
|
|
iqi_record = self.env['sos_return_iqi'].create({
|
|
'iqi_no': sequence_util.generate_sequence('sos_return_iqi', 'Return-IQI', 'iqi_no'),
|
|
'material_option':False,
|
|
'sfg_option':True,
|
|
'received_qty':item.quantity,
|
|
'sfg_name': item.component_id.id,
|
|
'sfg_code': item.component_id.sfg_code,
|
|
'mrn_id':self.id,
|
|
'iqi_date':item.mrn_id.mrn_date
|
|
|
|
})
|
|
# Email part
|
|
body_html = f"""
|
|
<p>Below <b>Return-IQI</b> is waiting for your Approval</p>
|
|
"""
|
|
send_email = self.env['sos_common_scripts']
|
|
send_email.send_group_email(self.env,'sos_return_iqi',iqi_record.id,"deenalaura.m@sosaley.in","Return-IQI Inspection Request",body_html,'sos_inventory.sos_qc_user')
|
|
# Email part ends
|
|
if customer_return_record and self.return_type == "customer" and item.qa_decision != "to_stores":
|
|
create_vals = {
|
|
'tc_id': customer_return_record.id,
|
|
'item_name': component.name,
|
|
'item_type': 'SFG',
|
|
'return_incoming_doc_ref':iqi_record.id if iqi_record else None
|
|
}
|
|
new_line = self.env['sos_transfer_challan_return_from_customer_lines'].create(create_vals)
|
|
|
|
else:
|
|
for item in self.line_ids_fg:
|
|
component = self.env['sos_fg'].browse(item.component_id.id)
|
|
|
|
if item.qa_decision == "to_stores":
|
|
current_qty = getattr(component, 'inhand_stock_qty', 0)
|
|
new_qty = current_qty + item.quantity
|
|
component.write({'inhand_stock_qty': new_qty})
|
|
component.line_ids_in.create({'ref_id': component.id,'component_id': item.component_id.id,
|
|
'quantity' : item.quantity,'mrn_no':self.id,
|
|
'action' : 'in'})
|
|
else:
|
|
if self.return_type == "customer":
|
|
return_fg_record = self.env['sos_return_fg_register'].create({
|
|
'mrn_no': self.id,
|
|
'customer_name': self.customer_name,
|
|
'date':item.mrn_id.mrn_date,
|
|
'fg_name':item.component_id.id,
|
|
'lot_no':item.serial_no,
|
|
'reason_for_return':item.reject_reason,
|
|
'returned_quantity':item.quantity
|
|
|
|
})
|
|
if component:
|
|
return_fir_record = self.env['sos_return_fir'].create({
|
|
'fir_no': sequence_util.generate_sequence('sos_return_fir', 'Return-BRR', 'fir_no'),
|
|
'fg_name': item.component_id.id,
|
|
'batch_No': item.batch_No,
|
|
'serial_no':item.serial_no,
|
|
'fir_date':item.mrn_id.mrn_date,
|
|
'batch_size':item.quantity
|
|
|
|
})
|
|
# Email part
|
|
body_html = f"""
|
|
<p>Below <b>Return-BRR</b> is waiting for your Approval</p>
|
|
"""
|
|
send_email = self.env['sos_common_scripts']
|
|
send_email.send_group_email(self.env,'sos_return_fir',return_fir_record.id,"deenalaura.m@sosaley.in","Return-BRR Inspection Request",body_html,'sos_inventory.sos_qc_user')
|
|
# Email part ends
|
|
if customer_return_record and self.return_type == "customer" and item.qa_decision != "to_stores":
|
|
create_vals = {
|
|
'tc_id': customer_return_record.id,
|
|
'item_name': component.name,
|
|
'item_type': 'FG',
|
|
'return_fg_incoming_doc_ref':return_fir_record.id if return_fir_record else None
|
|
}
|
|
new_line = self.env['sos_transfer_challan_return_from_customer_lines'].create(create_vals)
|
|
|
|
return sequence_util.action_assign_signature(
|
|
self,
|
|
'stores_approved_by',
|
|
'stores_approved_on',
|
|
'sos_inventory.sos_scg_group_user'
|
|
)
|
|
def action_report_esign_btn(self):
|
|
# Email part
|
|
|
|
body_html = f"""
|
|
<p>Below <b>Return Note</b> is waiting for your Approval</p>
|
|
"""
|
|
|
|
send_email = self.env['sos_common_scripts']
|
|
send_email.send_mon_min_email(self.env,'sos_mrn',self.id,"deenalaura.m@sosaley.in","Return Note Approval Request",body_html,"user")
|
|
# Email part ends
|
|
sequence_util = self.env['sos_common_scripts']
|
|
return sequence_util.action_assign_signature(
|
|
self,
|
|
'prepared_by_name',
|
|
'prepared_on'
|
|
)
|
|
|
|
|
|
|
|
|
|
class Mrn_Line_Material(models.Model):
|
|
_name = 'sos_mrn_line_material'
|
|
_description = 'Material Order Lines'
|
|
|
|
mrn_id = fields.Many2one('sos_mrn', string="Materials", ondelete="cascade")
|
|
component_id = fields.Many2one('sos_material', string="Part No", required=True)
|
|
qp_no = fields.Char(string="QP No")
|
|
uom = fields.Selection([('meters', 'Meters'), ('Packs', 'Packs'),('Nos', 'Nos'),('coils', 'Coils'), ('litre', 'litre'), ('kg', 'Kilogram')], string="Uom",readonly="1")
|
|
reject_reason = fields.Text(string="Reason for return")
|
|
quantity = fields.Integer(string="Quantity",default=1)
|
|
condition = fields.Selection([ ('work', 'Working'),('nowork', 'Not Working')], default='work' , string="Condition")
|
|
image = fields.Binary(string='Image', attachment=True)
|
|
qa_decision = fields.Selection([('to_stores', 'Move to Stores'),('to_qc', 'Move to QC')], default="to_qc",string="QA Decision")
|
|
company_id = fields.Many2one('res.company', store=True, copy=False,
|
|
string="Company",
|
|
default=lambda self: self.env.user.company_id.id)
|
|
currency_id = fields.Many2one('res.currency', string="Currency",
|
|
related='company_id.currency_id',
|
|
default=lambda
|
|
self: self.env.user.company_id.currency_id.id)
|
|
approx_price = fields.Monetary(string="Unit Price", compute='_compute_unit_price', store=True, readonly=False)
|
|
total_cost = fields.Monetary(compute="_compute_total_cost", currency_field='currency_id')
|
|
@api.depends('approx_price', 'quantity')
|
|
def _compute_total_cost(self):
|
|
for record in self:
|
|
record.total_cost = record.approx_price * record.quantity
|
|
@api.depends('component_id.unit_price')
|
|
def _compute_unit_price(self):
|
|
for record in self:
|
|
record.approx_price = record.component_id.unit_price
|
|
@api.onchange('component_id')
|
|
def _onchange_component_id(self):
|
|
if self.component_id:
|
|
self.qp_no = self.component_id.qp_no
|
|
self.uom = self.component_id.uom
|
|
else:
|
|
self.qp_no = False
|
|
self.uom = False
|
|
|
|
class Mrn_Line_SFG(models.Model):
|
|
_name = 'sos_mrn_line_sfg'
|
|
_description = 'SFG Order Lines'
|
|
|
|
mrn_id = fields.Many2one('sos_mrn', string="Materials", ondelete="cascade")
|
|
component_id = fields.Many2one('sos_sfg', string="SFG Name", required=True)
|
|
qp_no = fields.Char(string="QP No")
|
|
uom = fields.Selection([('set', 'Set'),('Nos', 'Nos'), ('Packs', 'Packs')], string="Uom",default="Nos")
|
|
reject_reason = fields.Char(string="Reason for return")
|
|
quantity = fields.Integer(string="Quantity",default=1)
|
|
condition = fields.Selection([ ('work', 'Working'),('nowork', 'Not Working')], default='work' , string="Condition")
|
|
image = fields.Binary(string='Image', attachment=True)
|
|
qa_decision = fields.Selection([('to_stores', 'Move to Stores'),('to_qc', 'Move to QC')], default="to_qc",string="QA Decision")
|
|
|
|
@api.onchange('component_id')
|
|
def _onchange_component_id(self):
|
|
if self.component_id:
|
|
self.qp_no = self.component_id.qp_no
|
|
self.uom = self.component_id.uom
|
|
else:
|
|
self.qp_no = False
|
|
self.uom = False
|
|
class Mrn_Line_FG(models.Model):
|
|
_name = 'sos_mrn_line_fg'
|
|
_description = 'FG Order Lines'
|
|
|
|
mrn_id = fields.Many2one('sos_mrn', string="Materials", ondelete="cascade")
|
|
component_id = fields.Many2one('sos_fg',string="FG Name", required=True)
|
|
batch_No = fields.Char(string="Batch No")
|
|
serial_no = fields.Char(string="Serial No")
|
|
uom = fields.Selection([('set', 'Set'),('Nos', 'Nos'), ('Packs', 'Packs')], string="Uom",default="Nos")
|
|
reject_reason = fields.Char(string="Reason for return")
|
|
quantity = fields.Integer(string="Quantity",default=1)
|
|
condition = fields.Selection([ ('work', 'Working'),('nowork', 'Not Working')], default='work' , string="Condition")
|
|
image = fields.Binary(string='Image', attachment=True)
|
|
qa_decision = fields.Selection([('to_stores', 'Move to Stores'),('to_qc', 'Move to QC')], default="to_qc",string="QA Decision")
|
|
|
|
@api.onchange('component_id')
|
|
def _onchange_component_id(self):
|
|
if self.component_id:
|
|
self.uom = self.component_id.uom
|
|
else:
|
|
self.uom = False
|
|
|
|
|
|
|
|
|
|
|