Slink/sos_inventory/models/sos_fg.py

352 lines
15 KiB
Python
Executable File

# -*- coding: utf-8 -*-
from odoo import models, fields, api
class SOS_FG(models.Model):
_name = 'sos_fg'
_description = 'Finished Goods Master'
_order = 'fg_code asc'
fg_code = fields.Char(string="Part No", required= True)
code_no = fields.Char(string="Code")
name = fields.Char(string="Product Name", required= True)
display_name = fields.Char(string="Display Name", required= True)
qp_no = fields.Char(string="QP No")
hsn_code = fields.Char(string="HSN Code")
opening_bal_qty = fields.Float(string="Opening Balance Qty")
uom = fields.Selection([ ("Nos", "Nos"),('set', 'set'), ('Packs', 'Packs')], default="Nos" , string="UOM")
currency_id = fields.Many2one('res.currency', string='Currency')
minimum_stock_qty = fields.Integer(string="Minimum Stock Qty")
minimum_order_qty = fields.Integer(string="Minimum Order Qty")
inhand_stock_qty = fields.Integer(string="In-Hand Stock Qty")
inhand_stock_val = fields.Monetary(string="In-Hand Stock Value", currency_field='currency_id',compute='_compute_stock_val', store=True)
in_transit_stock_qty = fields.Integer(string="In-Transit Qty")
in_transit_stock_val = fields.Monetary(string="In-Transit Stock Value", currency_field='currency_id')
received_qty = fields.Integer(string="Last Received Qty")
received_stock_val = fields.Monetary(string="Last Received Stock Value", currency_field='currency_id')
cancelled_qty = fields.Integer(string="Canceled Qty")
issued_qty = fields.Integer(string="Issue to Dispatch Qty")
issued_val = fields.Monetary(string="Issue to Dispatch Value", currency_field='currency_id')
defect_qty = fields.Integer(string="Defect Qty")
defect_val = fields.Monetary(string="Defect Value", currency_field='currency_id')
blocked_qty = fields.Integer(string="Blocked Qty")
order_qty = fields.Integer(string="Required/Order Qty")
unit_price = fields.Monetary(string="Unit Price", currency_field='currency_id')
msp = fields.Monetary(string="Max Selling Price", currency_field='currency_id')
location = fields.Char(string="Location in Stores")
image = fields.Image(string="Upload Image",max_height=100,max_width=100)
description = fields.Text(string="Remarks")
line_ids_in = fields.One2many(
'sos_fg_transaction_history', 'ref_id',
string="FG History - In",
domain=[('action', '=', 'in')]
)
line_ids_out = fields.One2many(
'sos_fg_transaction_history', 'ref_id',
string="FG History - Out",
domain=[('action', '=', 'out')]
)
fg_type = fields.Selection(
[
('BHMS', 'BHMS'),
('LV-BMS', 'BMS-LV'),
('HV-BMS', 'BMS-HV'),
('SBMS', 'SBMS'),
('Motor Controller', 'Motor Controller'),
('Health Care', 'Health Care')
],
default='BHMS',
string="Type",
required=True
)
sub_type = fields.Many2one(
'sos.fg.subtype',
string="Sub Type",
domain="[('fg_type', '=', fg_type)]"
)
sub_type = fields.Selection(
[
('1.2V', 'BHMS 1.2V'),
('2V', 'BHMS 2V'),
('12V', 'BHMS 12V'),
('48V', 'BHMS 48V'),
('100A', 'BMS-LV 100A'),
('40A', 'BMS-LV 40A'),
('100A-HV', 'BMS-HV 100A'),
('250A-HV', 'BMS-HV 250A'),
('15S Slave-HV', 'BMS-HV 15S Slave'),
('SBMS55A', 'SBMS 55A'),
('250W', 'MC 250W'),
('HeartTarang', 'HeartTarang')
],
string="Sub Type",
required=True
)
_sql_constraints = [
('fg_code_unique', 'UNIQUE(fg_code)', 'The Product Code No must be unique!')
]
@api.onchange('fg_type')
def _onchange_fg_type(self):
self.sub_type = False
if self.fg_type == 'BHMS':
return {'domain': {'sub_type': [('1.2V', 'BHMS 1.2V'),('2V', 'BHMS 2V'),('12V', 'BHMS 12V'),('48V', 'BHMS 48V')]}}
elif self.fg_type == 'LV-BMS':
return {'domain': {'sub_type': [('100A', 'BMS-LV 100A'),('40A', 'BMS-LV 40A')]}}
elif self.fg_type == 'HV-BMS':
return {'domain': {'sub_type': [('100A-HV', 'BMS-HV 100A'),('250A-HV', 'BMS-HV 250A')]}}
elif self.fg_type == 'Motor Controller':
return {'domain': {'sub_type': [('250W', 'MC 250W')]}}
elif self.fg_type == 'SBMS':
return {'domain': {'sub_type': [('SBMS55A', 'SBMS 55A')]}}
elif self.fg_type == 'Health Care':
return {'domain': {'sub_type': [('HeartTarang', 'HeartTarang') ]}}
else:
return {'domain': {'sub_type': []}}
@api.onchange('sub_type')
def onchange_sub_type(self):
if self.sub_type:
prefix_map = {
"12V": "H1",
"1.2V": "H2",
"2V": "H3",
"48V": "H4",
"100A": "M1",
"40A": "M2",
"250W": "C1",
"HeartTarang": "T1"
}
prefix = prefix_map.get(self.sub_type, "")
self.code_no = prefix if prefix else False
def action_naming_culture(self):
print("Test")
@api.depends('unit_price','inhand_stock_qty')
def _compute_stock_val(self):
for val in self:
val.inhand_stock_val = val.unit_price * val.inhand_stock_qty
def action_calculate_msp(self):
part_no_quantities = {}
sfg_stores_model = self.env['sos_sfg']
sfg_line_model = self.env['sos_sfg_plan_msp']
material_line_model = self.env['sos_material_plan_msp']
product_bom = self.env['sos_fg_bom'].search([
('fg_name', '=', self.id),
('is_primary', '=', True)
], limit=1)
if product_bom:
existing_sfg_lines = sfg_line_model.search([('fg_name', '=', self.id)])
if existing_sfg_lines:
existing_sfg_lines.unlink()
existing_material_lines = material_line_model.search([('fg_name', '=', self.id)])
if existing_material_lines:
existing_material_lines.unlink()
lines = self.env['sos_fg_bom_line'].search([('bom_id', '=', product_bom.id)])
for sfg_line in lines:
sfg_name = sfg_line.sfg_bom_id.name.id # Use the ID for Many2one relationship
req_sfg_qty = sfg_line.quantity
sfg_line_model.create({
'fg_name':self.id,
'sfg_name': sfg_name,
'required_qty': req_sfg_qty,
'unit_price':sfg_line.sfg_bom_id.name.unit_price
})
# sfg_bom = self.env['sos_sfg_bom'].search([
# ('name', '=', sfg_line.sfg_bom_id.name.id)
# ])
# sfg_lines = self.env['sos_sfg_bom_line'].search([('bom_id', '=', sfg_bom.id)])
# for sfg_line in sfg_lines:
# for component_id in sfg_line.primary_component_id:
# req_qty = sfg_line.quantity
# # If part_no is already in the dictionary, increase the req_qty
# if component_id.part_no in part_no_quantities:
# part_no_quantities[component_id.part_no]['req_qty'] += req_qty
# else:
# part_no_quantities[component_id.part_no] = {
# 'req_qty': req_qty,
# 'part_no_id':component_id.id,
# 'approx_price':component_id.unit_price
# }
# for part_no, data in part_no_quantities.items():
# req_qty = data['req_qty']
# pick_line = self.env['sos_material_plan_msp'].search([
# ('fg_name', '=', self.id),
# ('material_name', '=', data['part_no_id'])
# ],limit=1)
# if pick_line:
# pick_line.write({
# 'required_qty': pick_line.required_qty + req_qty,
# })
# else:
# material_line_model.create({
# 'material_name': data['part_no_id'],
# 'fg_name': self.id,
# 'required_qty': req_qty,
# 'approx_price':data['approx_price']
# })
material_lines = self.env['sos_sfg_bom_line'].search([('fg_bom_id', '=', product_bom.id)])
for material_line in material_lines:
req_qty = material_line.quantity
material_line_model.create({
'fg_name':self.id,
'material_name': material_line.primary_component_id.id,
'required_qty': req_qty,
'approx_price':material_line.primary_component_id.unit_price
})
return {
'type': 'ir.actions.act_window',
'name': 'Calculate MSP',
'res_model': 'sos_msp_wizard',
'view_mode': 'form',
'target': 'new',
'context': {
'fg_name': self.id,
'old_msp':self.msp
},
}
class SOS_FG_Line(models.Model):
_name = 'sos_fg_transaction_history'
_description = 'FG Lines'
_order = 'date desc'
ref_id = fields.Many2one('sos_fg', string="FG", ondelete="cascade")
component_id = fields.Many2one('sos_fg', string="Part No")
action = fields.Selection([('in', 'IN'),('out', 'OUT')], string="Action", default='in')
quantity = fields.Integer(string="Quantity")
currency_id = fields.Many2one('res.currency', string='Currency')
unit_price = fields.Monetary(string="Unit Price", currency_field='currency_id')
date = fields.Datetime(string="Date", default=fields.Datetime.now)
min_no = fields.Many2one('sos_min', string="Issue Ref No")
fir_no = fields.Many2one('sos_fir_brr', string="BRR No")
return_fir_no = fields.Many2one('sos_return_fir', string="Return - BRR No")
mrn_no = fields.Many2one('sos_mrn', string="Material Return Ref No")
class SOS_Material_Plan_MSP(models.Model):
_name = 'sos_material_plan_msp'
_description = 'Material Plan Lines For MSP'
material_name = fields.Many2one('sos_material',string="Material Name")
fg_name = fields.Many2one('sos_fg',string="FG Name")
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)
required_qty = fields.Integer(string='Required Qty')
approx_price = fields.Monetary(currency_field='currency_id', string='Unit Price')
total_cost = fields.Monetary(
currency_field='currency_id',
string="Total Cost",
compute="_compute_total_cost",
store=True
)
margin = fields.Float(string='Margin (%)', default="10", store=True)
final_cost = fields.Monetary(
currency_field='currency_id',
string="Final Cost",
compute="_compute_final_cost",
inverse="_set_final_cost",
store=True
)
@api.depends('required_qty', 'approx_price')
def _compute_total_cost(self):
for record in self:
record.total_cost = record.required_qty * record.approx_price
@api.depends('total_cost', 'margin')
def _compute_final_cost(self):
for record in self:
record.final_cost = record.total_cost + (record.total_cost * (record.margin / 100))
def _set_final_cost(self):
for record in self:
if record.total_cost > 0:
record.margin = (record.final_cost / record.total_cost) * 100
@api.onchange('material_name')
def _onchange_material_name(self):
if self.material_name:
self.approx_price = self.material_name.unit_price
else:
self.approx_price = 0.0
class SOS_SFG_Plan_MSP(models.Model):
_name = 'sos_sfg_plan_msp'
_description = 'SFG Plan Lines For MSP'
sfg_name = fields.Many2one('sos_sfg',string="SFG Name")
category = fields.Selection([ ('pcba', 'PCB Board'),('cables', 'Cables & Connectors'),('others', 'Others')], default='pcba' , string="Category", related="sfg_name.category" )
fg_name = fields.Many2one('sos_fg',string="FG Name")
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)
required_qty = fields.Integer(string='Required Qty')
unit_price = fields.Monetary(currency_field='currency_id',string="Unit Price")
total_cost = fields.Monetary(
currency_field='currency_id',
string="Total Cost",
compute="_compute_total_cost",
store=True
)
margin = fields.Float(string='Margin (%)', compute="_compute_margin", store=True)
final_cost = fields.Monetary(
currency_field='currency_id',
string="Final Cost",
compute="_compute_final_cost",
inverse="_set_final_cost",
store=True
)
@api.depends('required_qty', 'unit_price')
def _compute_total_cost(self):
for record in self:
record.total_cost = record.required_qty * record.unit_price
@api.depends('total_cost', 'margin')
def _compute_final_cost(self):
for record in self:
record.final_cost = record.total_cost + (record.total_cost * (record.margin / 100))
def _set_final_cost(self):
for record in self:
if record.total_cost > 0:
record.margin = (record.final_cost / record.total_cost) * 100
@api.depends('category')
def _compute_margin(self):
for record in self:
if record.category == 'pcba':
record.margin = 42.85 # Default value for PCBA
else:
record.margin = 15 # Default value for Other categories
class SosFgSubType(models.Model):
_name = 'sos_fg_subtype'
_description = 'FG Sub Type Master'
name = fields.Char(required=True, string="Sub Type Name") # E.g., BHMS 1.2V
code = fields.Char(string="Code") # Optional
fg_type = fields.Selection([
('BHMS', 'BHMS'),
('LV-BMS', 'BMS-LV'),
('HV-BMS', 'BMS-HV'),
('SBMS', 'SBMS'),
('Motor Controller', 'Motor Controller'),
('Health Care', 'Health Care')
], required=True, string="Main FG Type")