Fix for Issue #2

This commit is contained in:
Deena 2025-07-24 18:23:58 +05:30
parent b3641d3c63
commit 590d716eec
65 changed files with 1816 additions and 331 deletions

View File

@ -23,6 +23,7 @@
# always loaded
'data': [
'security/ir.model.access.csv',
'security/record_rules.xml',
'views/menu.xml',
'views/sos_travel_plan_view.xml',
'views/sos_travel_reimbursement_bills_view.xml',

View File

@ -44,6 +44,7 @@ class sos_travel_plan(models.Model):
]
)
prepared_by_name = fields.Many2one('res.users', string='Prepared by')
reporting_to = fields.Many2one('res.users',related="prepared_by_name.reporting_to", string='Prepared by')
prepared_by_image = fields.Image(related="prepared_by_name.signature_image",string='Prepared by Sign',readonly=True)
prepared_on = fields.Datetime(string="Approved On")
dept_in_charge_name = fields.Many2one('res.users', string='Department In-Charge')

View File

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- Travel Plan RECORD RULE-->
<record id="sos_travel_plan_own_records_rule" model="ir.rule">
<field name="name">Travel Plan: Own Records - Read Access</field>
<field name="model_id" ref="model_sos_travel_plan"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[
(4, ref('sos_inventory.sos_management_user')),
(4, ref('sos_inventory.sos_finance_user')),
(4, ref('sos_inventory.sos_hr_user')),
(4, ref('sos_inventory.sos_ce_user'))
]"/>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="1"/>
<field name="perm_unlink" eval="0"/>
</record>
<record id="sos_travel_plan_all_records_rule" model="ir.rule">
<field name="name">Travel Plan: All Records - Read Access</field>
<field name="model_id" ref="model_sos_travel_plan"/>
<field name="domain_force">[
'|',
('create_uid', '=', user.id),
('reporting_to', '=', user.id)
]</field>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="0"/>
<field name="perm_unlink" eval="0"/>
</record>
</odoo>

View File

@ -1,14 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<menuitem id="sos_installation_commision_menu_root" name="Installation &amp; Commissioning" groups="sos_inventory.sos_ce_user,sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user,sos_inventory.sos_hr_user"/>
<menuitem id="travel_root_menu" parent="sos_installation_commision_menu_root" name="TRAVEL" groups="sos_inventory.sos_ce_user,sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user,sos_inventory.sos_hr_user"/>
<menuitem id="customers_root_menu" action="sos_sales.action_sos_customers" parent="sos_installation_commision_menu_root" name="CUSTOMERS" groups="sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user"/>
<menuitem id="casediary_root_menu" action="sos_sales.action_sos_case_diary" parent="sos_installation_commision_menu_root" name="CASE DIARY" groups="sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user"/>
<menuitem id="sos_target_vs_actual_ce_menu" name="TARGET vs ACTUAL" parent="sos_installation_commision_menu_root" groups="sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user"/>
<menuitem id="menu_sos_sales_plan_target_ce" name="Sales Target" sequence="1" parent="sos_target_vs_actual_ce_menu" action="sos_sales.action_sos_sales_plan_target"/>
<menuitem id="menu_sos_sales_action_plan_ce" name="Sales Action Plan" sequence="2" parent="sos_target_vs_actual_ce_menu" action="sos_sales.action_sos_sales_action_plan"/>
<menuitem id="sos_sales_achievement_report_ce" name="Sales Achievements Report"
parent="sos_target_vs_actual_ce_menu" sequence="3"
action="sos_sales.action_sos_sales_achievement_report"/>
<menuitem id="sos_installation_commision_menu_root" name="Installation &amp; Commissioning" groups="sos_inventory.sos_ce_user,sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user,sos_inventory.sos_hr_user,sos_inventory.sos_sales_user,sos_inventory.sos_qc_user,sos_inventory.sos_production_user,sos_inventory.sos_qc_user,sos_inventory.sos_qa_user,sos_inventory.sos_rd_user"/>
<menuitem id="travel_root_menu" parent="sos_installation_commision_menu_root" name="TRAVEL" groups="sos_inventory.sos_ce_user,sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user,sos_inventory.sos_hr_user,sos_inventory.sos_sales_user,sos_inventory.sos_qc_user,sos_inventory.sos_production_user,sos_inventory.sos_qc_user,sos_inventory.sos_qa_user,sos_inventory.sos_rd_user"/>
<!-- <menuitem id="customers_root_menu" action="sos_sales.action_sos_customers" parent="sos_installation_commision_menu_root" name="CUSTOMERS" groups="sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user"/>
<menuitem id="casediary_root_menu" action="sos_sales.action_sos_case_diary" parent="sos_installation_commision_menu_root" name="CASE DIARY" groups="sos_inventory.sos_ce_user,sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user"/>
<menuitem id="actionplan_root_menu" action="sos_sales.action_sos_sales_action_plan" parent="sos_installation_commision_menu_root" name="ACTION PLAN" groups="sos_inventory.sos_ce_user,sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user"/> -->
</odoo>

View File

@ -230,6 +230,6 @@ name="action_report_travel_plan"><i class="fa fa-print"></i> Print</button>
<menuitem id="travel_plan_menu"
name="Travel Plan"
parent="travel_root_menu"
action="action_travel_plan_list" groups="sos_inventory.sos_ce_user,sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user,sos_inventory.sos_hr_user"/>
action="action_travel_plan_list" groups="sos_inventory.sos_ce_user,sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user,sos_inventory.sos_hr_user,sos_inventory.sos_sales_user,sos_inventory.sos_qc_user,sos_inventory.sos_production_user,sos_inventory.sos_qc_user,sos_inventory.sos_qa_user,sos_inventory.sos_rd_user"/>
</odoo>

View File

@ -80,6 +80,7 @@
'views/sos_serviceprovider_report.xml',
'views/sos_master_customer_property.xml',
'views/sos_service_call_log_report.xml',
'views/sos_transfer_challan_return_from_customer_view.xml',
'wizard/sfg_bom_bulk_upload_view.xml',
'wizard/mon_bulk_upload_view.xml',
'wizard/missing_component_wizard.xml',

View File

@ -57,3 +57,4 @@ from . import sos_inventory_customers
from . import sos_master_customer_property
from . import sos_service_call_log_report
from . import sos_inhouse_validation_reports_files
from . import sos_transfer_challan_return_from_customer

View File

@ -306,7 +306,8 @@ class Sequence_Generator(models.AbstractModel):
record.write({field_name: current_value + value_to_add})
return True
return False
def extract_value(self, input_string):
@staticmethod
def extract_value(input_string):
total = 0
items = input_string.split(",") # handles both single and comma-separated values

View File

@ -417,36 +417,36 @@ class sos_dock_audit_Line_Material(models.Model):
@api.model
def create(self, vals):
#print(f" First line in create ")
component_id = vals.get('component_id')
#component_id = vals.get('component_id')
ref_id = vals.get('ref_id')
sequence_util = self.env['sos_common_scripts']
#sequence_util = self.env['sos_common_scripts']
if component_id and ref_id:
# Search for an existing line with the same component_id and ref_id
existing = self.search([
('component_id', '=', component_id),
('ref_id', '=', ref_id)
], limit=1)
# if component_id and ref_id:
# # Search for an existing line with the same component_id and ref_id
# existing = self.search([
# ('component_id', '=', component_id),
# ('ref_id', '=', ref_id)
# ], limit=1)
if existing:
# Merge logic: add quantities
existing.singet_set_qty += vals.get('singet_set_qty', 1)
#existing.total_set += vals.get('total_set', 1)
# if existing:
# # Merge logic: add quantities
# existing.singet_set_qty += vals.get('singet_set_qty', 1)
# #existing.total_set += vals.get('total_set', 1)
previousval = 0
if vals.get('ref_id'):
parent = self.env['sos_dock_audit'].browse(vals['ref_id'])
existing.phase = str(existing.phase) + "," + str(parent.phase_version + 1)
previousval = sequence_util.extract_value(existing.total_phase_count)
# previousval = 0
# if vals.get('ref_id'):
# parent = self.env['sos_dock_audit'].browse(vals['ref_id'])
# existing.phase = str(existing.phase) + "," + str(parent.phase_version + 1)
# previousval = sequence_util.extract_value(existing.total_phase_count)
if existing.total_phase_count:
#existing.total_phase_count = str(existing.total_phase_count)+","+str(existing.singet_set_qty * existing.total_set)
existing.total_phase_count = str(existing.total_phase_count)+","+"P"+str(parent.phase_version + 1 or '') +"-"+str((existing.singet_set_qty * existing.total_set)- int(previousval))
else:
existing.total_phase_count = str(existing.singet_set_qty * existing.total_set)
# if existing.total_phase_count:
# #existing.total_phase_count = str(existing.total_phase_count)+","+str(existing.singet_set_qty * existing.total_set)
# existing.total_phase_count = str(existing.total_phase_count)+","+"P"+str(parent.phase_version + 1 or '') +"-"+str((existing.singet_set_qty * existing.total_set)- int(previousval))
# else:
# existing.total_phase_count = str(existing.singet_set_qty * existing.total_set)
# quantity and total_price are computed, so they'll auto update
return existing
# # quantity and total_price are computed, so they'll auto update
# return existing
#print(f"Initial : singet {vals.get('singet_set_qty', 1)}")
#print(f"Initial : total {vals.get('total_set', 1)}")
@ -508,37 +508,37 @@ class sos_dock_audit_Line_sfg(models.Model):
@api.model
def create(self, vals):
#print(f" First line in create ")
component_id = vals.get('component_id')
#component_id = vals.get('component_id')
ref_id = vals.get('ref_id')
sequence_util = self.env['sos_common_scripts']
#sequence_util = self.env['sos_common_scripts']
if component_id and ref_id:
# Search for an existing line with the same component_id and ref_id
existing = self.search([
('component_id', '=', component_id),
('ref_id', '=', ref_id)
], limit=1)
# if component_id and ref_id:
# # Search for an existing line with the same component_id and ref_id
# existing = self.search([
# ('component_id', '=', component_id),
# ('ref_id', '=', ref_id)
# ], limit=1)
if existing:
# Merge logic: add quantities
existing.singet_set_qty += vals.get('singet_set_qty', 1)
#existing.total_set += vals.get('total_set', 1)
# if existing:
# # Merge logic: add quantities
# existing.singet_set_qty += vals.get('singet_set_qty', 1)
# #existing.total_set += vals.get('total_set', 1)
previousval = 0
if vals.get('ref_id'):
# previousval = 0
# if vals.get('ref_id'):
parent = self.env['sos_dock_audit'].browse(vals['ref_id'])
existing.phase = str(existing.phase) + "," + str(parent.phase_version + 1)
previousval = sequence_util.extract_value(existing.total_phase_count)
# parent = self.env['sos_dock_audit'].browse(vals['ref_id'])
# existing.phase = str(existing.phase) + "," + str(parent.phase_version + 1)
# previousval = sequence_util.extract_value(existing.total_phase_count)
if existing.total_phase_count:
#existing.total_phase_count = str(existing.total_phase_count)+","+str(existing.singet_set_qty * existing.total_set)
existing.total_phase_count = str(existing.total_phase_count)+","+"P"+str(parent.phase_version + 1 or '') +"-"+str((existing.singet_set_qty * existing.total_set)- int(previousval))
else:
existing.total_phase_count = str(existing.singet_set_qty * existing.total_set)
# if existing.total_phase_count:
# #existing.total_phase_count = str(existing.total_phase_count)+","+str(existing.singet_set_qty * existing.total_set)
# existing.total_phase_count = str(existing.total_phase_count)+","+"P"+str(parent.phase_version + 1 or '') +"-"+str((existing.singet_set_qty * existing.total_set)- int(previousval))
# else:
# existing.total_phase_count = str(existing.singet_set_qty * existing.total_set)
# quantity and total_price are computed, so they'll auto update
return existing
# # quantity and total_price are computed, so they'll auto update
# return existing
singleset = vals.get('singet_set_qty', 1)
total_set = vals.get('total_set', 1)
@ -603,34 +603,34 @@ class sos_dock_audit_Line_fg(models.Model):
@api.model
def create(self, vals):
component_id = vals.get('component_id')
#component_id = vals.get('component_id')
ref_id = vals.get('ref_id')
sequence_util = self.env['sos_common_scripts']
#sequence_util = self.env['sos_common_scripts']
if component_id and ref_id:
# Search for an existing line with the same component_id and ref_id
existing = self.search([
('component_id', '=', component_id),
('ref_id', '=', ref_id)
], limit=1)
# if component_id and ref_id:
# # Search for an existing line with the same component_id and ref_id
# existing = self.search([
# ('component_id', '=', component_id),
# ('ref_id', '=', ref_id)
# ], limit=1)
if existing:
# Merge logic: add quantities
existing.singet_set_qty += vals.get('singet_set_qty', 1)
#existing.total_set += vals.get('total_set', 1)
previousval = 0
if vals.get('ref_id'):
parent = self.env['sos_dock_audit'].browse(vals['ref_id'])
existing.phase = str(existing.phase) + "," + str(parent.phase_version + 1)
previousval = sequence_util.extract_value(existing.total_phase_count)
if existing.total_phase_count:
#print(f" TT :: {existing.total_phase_count} ")
existing.total_phase_count = str(existing.total_phase_count)+","+"P"+str(parent.phase_version + 1 or '') +"-"+str((existing.singet_set_qty * existing.total_set)- int(previousval))
else:
existing.total_phase_count = "P"+str(existing.phase)+"-"+str(existing.singet_set_qty * existing.total_set)
##if existing:
# # Merge logic: add quantities
# existing.singet_set_qty += vals.get('singet_set_qty', 1)
# #existing.total_set += vals.get('total_set', 1)
## previousval = 0
## if vals.get('ref_id'):
## parent = self.env['sos_dock_audit'].browse(vals['ref_id'])
# existing.phase = str(existing.phase) + "," + str(parent.phase_version + 1)
## previousval = sequence_util.extract_value(existing.total_phase_count)
## if existing.total_phase_count:
# #print(f" TT :: {existing.total_phase_count} ")
## existing.total_phase_count = str(existing.total_phase_count)+","+"P"+str(parent.phase_version + 1 or '') +"-"+str((existing.singet_set_qty * existing.total_set)- int(previousval))
# else:
# existing.total_phase_count = "P"+str(existing.phase)+"-"+str(existing.singet_set_qty * existing.total_set)
# quantity and total_price are computed, so they'll auto update
return existing
# # quantity and total_price are computed, so they'll auto update
#return existing
singleset = vals.get('singet_set_qty', 1)
total_set = vals.get('total_set', 1)
@ -670,7 +670,8 @@ class sos_dock_audit_MiscellaneousCost(models.Model):
@api.model
def create(self, vals):
if vals.get('ref_id'):
ref_id = vals.get('ref_id')
if ref_id:
parent = self.env['sos_dock_audit'].browse(vals['ref_id'])
vals['phase'] = (parent.phase_version+1) or 0
return super().create(vals)
@ -718,39 +719,39 @@ class sos_dock_audit_Material_installationkit(models.Model):
@api.model
def create(self, vals):
component_id = vals.get('component_id')
#component_id = vals.get('component_id')
ref_id = vals.get('ref_id')
sequence_util = self.env['sos_common_scripts']
#sequence_util = self.env['sos_common_scripts']
if component_id and ref_id:
# Search for an existing line with the same component_id and ref_id
existing = self.search([
('component_id', '=', component_id),
('ref_id', '=', ref_id)
], limit=1)
# if component_id and ref_id:
# # Search for an existing line with the same component_id and ref_id
# existing = self.search([
# ('component_id', '=', component_id),
# ('ref_id', '=', ref_id)
# ], limit=1)
if existing:
# Merge logic: add quantities
existing.singet_set_qty += vals.get('singet_set_qty', 1)
#existing.total_set += vals.get('total_set', 1)
# if existing:
# # Merge logic: add quantities
# existing.singet_set_qty += vals.get('singet_set_qty', 1)
# #existing.total_set += vals.get('total_set', 1)
previousval = 0
if vals.get('ref_id'):
parent = self.env['sos_dock_audit'].browse(vals['ref_id'])
existing.phase = str(existing.phase) + "," + str(parent.phase_version + 1)
#print(f" Total_phase_count :{existing.total_phase_count}")
#print(f" Extract Value :{self.extract_value(existing.total_phase_count)}")
previousval = sequence_util.extract_value(existing.total_phase_count)
#print(f" : previousval : {previousval}")
if existing.total_phase_count:
#existing.total_phase_count = str(existing.total_phase_count)+","+str(existing.singet_set_qty * existing.total_set)
#print(f" Total Count : {existing.singet_set_qty * existing.total_set}")
existing.total_phase_count = str(existing.total_phase_count)+","+"P"+str(parent.phase_version + 1 or '') +"-"+str((existing.singet_set_qty * existing.total_set)- int(previousval))
else:
existing.total_phase_count = str(existing.singet_set_qty * existing.total_set)
# previousval = 0
# if vals.get('ref_id'):
# parent = self.env['sos_dock_audit'].browse(vals['ref_id'])
# existing.phase = str(existing.phase) + "," + str(parent.phase_version + 1)
# #print(f" Total_phase_count :{existing.total_phase_count}")
# #print(f" Extract Value :{self.extract_value(existing.total_phase_count)}")
# previousval = sequence_util.extract_value(existing.total_phase_count)
# #print(f" : previousval : {previousval}")
# if existing.total_phase_count:
# #existing.total_phase_count = str(existing.total_phase_count)+","+str(existing.singet_set_qty * existing.total_set)
# #print(f" Total Count : {existing.singet_set_qty * existing.total_set}")
# existing.total_phase_count = str(existing.total_phase_count)+","+"P"+str(parent.phase_version + 1 or '') +"-"+str((existing.singet_set_qty * existing.total_set)- int(previousval))
# else:
# existing.total_phase_count = str(existing.singet_set_qty * existing.total_set)
# quantity and total_price are computed, so they'll auto update
return existing
# # quantity and total_price are computed, so they'll auto update
# return existing
singleset = vals.get('singet_set_qty', 1)
total_set = vals.get('total_set', 1)

View File

@ -73,6 +73,7 @@ class SOS_Fg_Bom(models.Model):
def _compute_overall_total(self):
for record in self:
record.overall_total = record.sfg_cost + record.component_cost + record.miscellaneous_cost
record._sync_unit_price_with_fg()
@api.depends('sfg_bom_line_ids.unit_price')
def _compute_component_cost(self):

View File

@ -66,6 +66,18 @@ class SOS_Material(models.Model):
record.name or record.part_no
)
)
def write(self, vals):
unit_price_changed = 'unit_price' in vals
res = super().write(vals)
if unit_price_changed:
bom_lines = self.env['sos_sfg_bom_line'].search([
('primary_component_id', 'in', self.ids)
])
bom_ids = bom_lines.mapped('bom_id')
for bom in bom_ids:
bom._sync_unit_price_with_sfg()
return res
@api.depends('unit_price','inhand_stock_qty')
def _compute_stock_val(self):
for val in self:

View File

@ -13,7 +13,7 @@ class sos__min(models.Model):
min_no = fields.Char(string="MIN/SIN/FIN No", readonly= True, required= True, default=lambda self: self._generate_id())
min_date = fields.Date(string="MIN/SIN/FIN Date",required=True)
mon_no = fields.Many2one('sos_mon',string="MON/SON/FON No")
mon_no = fields.Many2one('sos_mon',string="MON/SON/FON No",readonly= True)
mon_date = fields.Date(string="MON/SON/FON Date")
ref_no = fields.Char(string="Purpose")
indent_ref_no = fields.Many2one('sos_fg_plan',string="Indent Reference No")
@ -31,7 +31,7 @@ class sos__min(models.Model):
line_ids_material = fields.One2many('sos_min_line_material', 'min_id', string="Materials",copy=True)
line_ids_sfg = fields.One2many('sos_min_line_sfg', 'min_id', string="Semi-Finished Goods",copy=True)
line_ids_fg = fields.One2many('sos_min_line_fg', 'min_id', string="Finished Goods",copy=True)
mon_created_by = fields.Many2one('res.users', string='Requested By')
mon_created_by = fields.Many2one('res.users', string='Requested By',readonly= True)
reporting_to = fields.Many2one('res.users', string='Reporting To')
issued_to = fields.Many2one('res.users', string='Issued To')
status = fields.Selection([ ('open', 'Open'),('close', 'Closed')], default='open' , string="Status")

View File

@ -115,10 +115,18 @@ class sos__mrn(models.Model):
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
@ -137,6 +145,16 @@ class sos__mrn(models.Model):
'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>
@ -147,6 +165,7 @@ class sos__mrn(models.Model):
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
@ -174,9 +193,19 @@ class sos__mrn(models.Model):
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
@ -213,6 +242,14 @@ class sos__mrn(models.Model):
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,

View File

@ -75,6 +75,8 @@ class Return_FIR_BRR(models.Model):
'return_fg_incoming_doc_ref':self.id,
'department':'Quality Control'
})
if ncmr_record:
self.ncmr_ref = ncmr_record.id
ncmr_body_html = f"""
<p>Below <b>NCMR</b> is waiting for your Inspection</p>
"""

View File

@ -53,6 +53,17 @@ class SOS_SFG(models.Model):
)
last_batch_no = fields.Char(string="Batch No")
last_serial_no = fields.Integer(string="Last Serial No")
def write(self, vals):
assembling_changed = 'assembling_charges' in vals
res = super().write(vals)
if assembling_changed:
for sfg in self:
bom_records = self.env['sos_sfg_bom'].search([('name', '=', sfg.id)])
for bom in bom_records:
bom._compute_overall_total() # If you want to force recompute manually
bom._sync_unit_price_with_sfg()
return res
@api.onchange('category')
def onchange_category(self):
if self.category:
@ -62,7 +73,6 @@ class SOS_SFG(models.Model):
}
prefix = prefix_map.get(self.category, "SO")
# Search all records starting with this prefix
matching_records = self.env['sos_sfg'].search([
('code_no', 'like', prefix + '%')
])

View File

@ -38,8 +38,10 @@ class SOS_Sfg_Bom(models.Model):
'material_code' : 'Material Code',
'primary_component_id': 'Material Name',
'quantity': 'Quantity',
'location':'Location',
'inhand_stock_qty':'Inhand Qty'
'inhand_stock_qty':'Inhand Qty',
'uom':'UOM',
'unit_price':'Unit Price',
'total_cost':'Total'
}
self._write_sheet(workbook, 'Materials', self.sfg_bom_line_ids, headers)
@ -62,12 +64,26 @@ class SOS_Sfg_Bom(models.Model):
}
def _write_sheet(self, workbook, sheet_name, line_records, headers):
"""Write data to each sheet based on specified fields and custom headers."""
worksheet = workbook.add_worksheet(sheet_name)
for col, header in enumerate(headers.values()):
worksheet.write(0, col, header)
for row, record in enumerate(line_records, start=1):
number_format = workbook.add_format({'num_format': '#,##0.00'})
bold_format = workbook.add_format({'bold': True})
name_value = getattr(self, 'name', False)
worksheet.write(0, 0, 'Name',bold_format) # Label for the first value
worksheet.write(0, 1, name_value.display_name if name_value else '') # Handle Many2one field
assembling_charges = getattr(self, 'assembling_charges', 0.0)
worksheet.write(1, 0, 'Assembly Charges',bold_format) # Label for the second value
worksheet.write(1, 1, assembling_charges, number_format) # Assume numeric (float)
overall_total = getattr(self, 'overall_total', 0.0)
worksheet.write(2, 0, 'Overall Cost (Including assembling charges)',bold_format) # Label for the third value
worksheet.write(2, 1, overall_total, number_format) # Assume numeric (float)
for col, header in enumerate(headers.values()):
worksheet.write(4, col, header,bold_format)
for row, record in enumerate(line_records, start=5):
for col, field in enumerate(headers.keys()):
value = getattr(record, field, '')
if isinstance(value, models.Model):
@ -123,7 +139,7 @@ class SOS_Sfg_Bom_Line(models.Model):
_description = 'BOM Lines of Semi-Finished Goods'
bom_id = fields.Many2one('sos_sfg_bom', string="SFG BOM Reference")
fg_bom_id = fields.Many2one('sos_fg_bom', string="SFG BOM Reference")
fg_bom_id = fields.Many2one('sos_fg_bom', string="FG BOM Reference")
primary_component_id = fields.Many2one('sos_material', string='Part No', required=True)
location = fields.Char(related="primary_component_id.location")
inhand_stock_qty = fields.Float(related="primary_component_id.inhand_stock_qty")

View File

@ -162,6 +162,13 @@ class SOS_SFG_Quote_Generation_Line(models.Model):
# final_supplier3_qty = fields.Integer(string='Qty')
best_supplier = fields.Many2one('sos_service_providers', string="Best Deal", compute='_compute_best_supplier', store=True)
available_suppliers = fields.Many2many('sos_service_providers', compute='_compute_available_suppliers')
remarks = fields.Char(string="Remarks")
@api.onchange('required_qty', 'inprogress_qty', 'status')
def _onchange_check_inprogress_qty(self):
for rec in self:
if (rec.inprogress_qty >= rec.required_qty and rec.required_qty != 0) or rec.status == 'close':
rec.inprogress_qty = 0
@api.depends('required_qty', 'inprogress_qty')
def _compute_from_ir(self):
for record in self:

View File

@ -180,7 +180,7 @@ class TC_Model_Line(models.Model):
'fir_date':self.production_to_qc_transfer_on,
'batch_size':self.production_to_qc_transfer_qty,
'sampling_size':self.production_to_qc_transfer_qty,
'plan_ref_no':plan_ref_no.id,
'plan_ref_no':plan_ref_no.id if plan_ref_no else '',
'batch_No':self.batch_no,
'fir_no': sequence_util.generate_sequence('sos_fir_brr','BRR', 'fir_no'),
@ -204,7 +204,7 @@ class TC_Model_Line(models.Model):
# Email part ends
self.production_to_qc_transfer_by = self.env.user.id
sequence_util = self.env['sos_common_scripts']
if self.tc_id.fg_option:
if self.tc_id.fg_option and self.tc_id.plan_ref_no:
week_number = sequence_util.calculate_week_number(
self.tc_id.indent_start_date,
self.tc_id.indent_target_date,

View File

@ -0,0 +1,81 @@
from odoo import models, fields, api
from datetime import date,datetime
from odoo.exceptions import ValidationError,UserError
import re
class SOS_TC_Return_Customer(models.Model):
_name = 'sos_transfer_challan_return_from_customer'
_description = 'Transfer Challan'
_rec_name="tc_no"
_order = 'tc_no desc'
tc_no = fields.Char(string="TC No",default=lambda self: self._generate_id(),readonly= True, required= True)
line_ids = fields.One2many('sos_transfer_challan_return_from_customer_lines', 'tc_id', string="Finished Goods",copy=True, ondelete='cascade')
mrn_ref_no = fields.Many2one('sos_mrn',string="Return Note Reference",readonly= True)
def _generate_id(self):
sequence_util = self.env['sos_common_scripts']
return sequence_util.generate_sequence('sos_transfer_challan_return_from_customer','TC', 'tc_no')
class SOS_TC_Return_CustomerLines(models.Model):
_name = 'sos_transfer_challan_return_from_customer_lines'
_description = 'tc Lines'
tc_id = fields.Many2one('sos_transfer_challan_return_from_customer')
item_name = fields.Char(string="Item Name")
item_type = fields.Selection([ ('FG', 'FG'),('SFG', 'SFG'),('Material', 'Material')],
default='FG' , string="Type")
return_incoming_doc_ref = fields.Many2one('sos_return_iqi',string="IQI Ref No",readonly=True)
return_fg_incoming_doc_ref = fields.Many2one('sos_return_fir',string="Return FIR ref",readonly=True)
combined_incoming_doc_ref = fields.Reference(
selection=[
('sos_return_iqi', 'Return IQI Ref No'),
('sos_return_fir', 'FIR Ref')
],
string="Incoming Document Reference",
compute="_compute_combined_incoming_doc_ref",
store=False
)
stores_handovered_by = fields.Many2one('res.users', string='Stores Handovered By',related="tc_id.mrn_ref_no.stores_approved_by")
stores_handovered_on = fields.Datetime(string="Stores Handovered On",related="tc_id.mrn_ref_no.stores_approved_on")
qc_tested_by = fields.Many2one('res.users', string='QC Tested By',compute="_compute_qc_tested_by")
qc_tested_on = fields.Datetime(string="QC Tested On")
received_qty = fields.Integer(string="Received Quantity")
approved_qty = fields.Integer(string="Approved Quantity")
rejected_qty = fields.Integer(string="Rejected Quantity")
ncmr_ref = fields.Many2one('sos_ncmr',string="NCMR Ref(If any)")
stores_received_by = fields.Many2one('res.users', string='Stores Received By')
stores_received_on = fields.Datetime(string="Stores Received On")
@api.depends('item_type','return_incoming_doc_ref','return_fg_incoming_doc_ref')
def _compute_qc_tested_by(self):
for record in self:
if record.item_type == "FG":
record.qc_tested_by = record.return_fg_incoming_doc_ref.qc_by_name
record.qc_tested_on = record.return_fg_incoming_doc_ref.qc_tested_on
record.qc_tested_on = record.return_fg_incoming_doc_ref.qc_tested_on
record.received_qty = record.return_fg_incoming_doc_ref.batch_size
record.approved_qty = record.return_fg_incoming_doc_ref.approved_qty
record.rejected_qty = record.return_fg_incoming_doc_ref.rejected_qty
record.ncmr_ref = record.return_fg_incoming_doc_ref.ncmr_ref
record.stores_received_by = record.return_fg_incoming_doc_ref.stores_received_by
record.stores_received_on = record.return_fg_incoming_doc_ref.stores_received_on
else:
record.qc_tested_by = record.return_incoming_doc_ref.qc_by_name
record.qc_tested_on = record.return_incoming_doc_ref.qc_tested_on
record.received_qty = record.return_incoming_doc_ref.received_qty
record.approved_qty = record.return_incoming_doc_ref.approved_qty
record.rejected_qty = record.return_incoming_doc_ref.rejected_qty
record.ncmr_ref = record.return_incoming_doc_ref.ncmr_ref
record.stores_received_by = record.return_incoming_doc_ref.stores_received_by
record.stores_received_on = record.return_incoming_doc_ref.stores_received_on
@api.depends('return_incoming_doc_ref','return_fg_incoming_doc_ref')
def _compute_combined_incoming_doc_ref(self):
for record in self:
if record.return_incoming_doc_ref:
record.combined_incoming_doc_ref = f'sos_return_iqi,{record.return_incoming_doc_ref.id}'
elif record.return_fg_incoming_doc_ref:
record.combined_incoming_doc_ref = f'sos_return_fir,{record.return_fg_incoming_doc_ref.id}'
else:
record.combined_incoming_doc_ref = False

View File

@ -61,7 +61,7 @@ class sos__wo(models.Model):
total_qty = fields.Integer(string='Total Line Items Count', compute='_compute_total_qty', store=True)
received_qty = fields.Integer(string='Received Line Items Count', store=True)
payment_method=fields.Selection([('neft', 'NEFT'),('credit', 'Credit'),('credit_card', 'Credit Card')],string="Payment Method")
wo_status = fields.Selection([ ('open', 'Open'),('close', 'Closed')], default='open' , string="Status")
wo_status = fields.Selection([ ('amend', 'Amended'),('open', 'Open'),('close', 'Closed')], default='open' , string="Status")
progress = fields.Float(string="Completion Percentage", compute='_compute_progress', store=True)
dc_no = fields.Many2one('sos_dc',string="DC Reference No", readonly= True)
stores_approved_by = fields.Many2one('res.users', string='Manager Approval By')
@ -82,7 +82,20 @@ class sos__wo(models.Model):
# record = super(sos__wo, self).create(vals)
# record.action_esign_btn()
# return record
def action_amend(self):
active_ids = self.env.context.get('active_ids', [])
records = self.browse(active_ids)
for record in records:
record.wo_status = 'amend'
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': 'Amended',
'message': 'The selected record(s) have been amended.',
'sticky': False,
}
}
def action_esign_btn(self):
sequence_util = self.env['sos_common_scripts']
sequence_util.action_assign_signature(
@ -143,7 +156,13 @@ class sos__wo(models.Model):
record.progress = (progress_sum / line_count) * 100
record.wo_status = 'close' if record.progress == 100 else 'open'
@api.onchange('progress')
def _onchange_progress_status(self):
for record in self:
if record.progress == 100:
record.wo_status = 'close'
else:
record.wo_status = 'open'
# @api.depends('total_qty', 'received_qty')
# def _compute_progress(self):
# print(self.received_qty,self.total_qty)

View File

@ -193,4 +193,7 @@ access_sos_transfer_challan_summary_lines,sos_transfer_challan_summary_lines acc
access_material_backup_export,material_backup_export access,model_material_backup_export,base.group_user,1,1,1,1
access_ncmr_report_wizard,ncmr_report_wizard access,model_ncmr_report_wizard,base.group_user,1,1,1,1
access_sos_parameter_fir,sos_parameter_fir access,model_sos_parameter_fir,base.group_user,1,1,1,1
access_sos_transfer_challan_return_from_customer_lines,sos_transfer_challan_return_from_customer_lines access,model_sos_transfer_challan_return_from_customer_lines,base.group_user,1,1,1,1
access_sos_transfer_challan_return_from_customer,sos_transfer_challan_return_from_customer access,model_sos_transfer_challan_return_from_customer,base.group_user,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
193 access_material_backup_export material_backup_export access model_material_backup_export base.group_user 1 1 1 1
194 access_ncmr_report_wizard ncmr_report_wizard access model_ncmr_report_wizard base.group_user 1 1 1 1
195 access_sos_parameter_fir sos_parameter_fir access model_sos_parameter_fir base.group_user 1 1 1 1
196 access_sos_transfer_challan_return_from_customer_lines sos_transfer_challan_return_from_customer_lines access model_sos_transfer_challan_return_from_customer_lines base.group_user 1 1 1 1
197 access_sos_transfer_challan_return_from_customer sos_transfer_challan_return_from_customer access model_sos_transfer_challan_return_from_customer base.group_user 1 1 1 1
198
199

View File

@ -46,7 +46,7 @@
<i class="fa fa-print"></i> Print</button> -->
<button class="btn btn-primary" type="object" name="action_clear_approval"
invisible="not top_management_name">Make Revision</button>
confirm="Are you sure to make revision for next phase?" invisible="not top_management_name">Make Revision</button>
</header>
<sheet>
<h2 style="text-align: center;text-transform: uppercase;text-shadow: 1px 1p 1px #140718;color: #65407c;padding:5px;">Dock Audit</h2><hr></hr><br></br>

View File

@ -27,7 +27,7 @@
<field name="inprogress_qty"/>
<field name="status" widget="badge" decoration-success="status == 'close'" decoration-danger="status == 'open'"/>
<field name="status" string="Change Status" groups="sos_inventory.sos_scg_group_manager"/>
<field name="remarks"/>
</tree>
</field>
</page>

View File

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="action_tc_return" model="ir.actions.act_window">
<field name="name">Transfer Challan</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sos_transfer_challan_return_from_customer</field>
<field name="view_mode">tree,form</field>
</record>
<record id="sos_transfer_challan_return_from_customer_view_tree" model="ir.ui.view">
<field name="name">sos_transfer_challan_return_from_customer.view.tree</field>
<field name="model">sos_transfer_challan_return_from_customer</field>
<field name="arch" type="xml">
<tree>
<field name="tc_no"/>
<field name="mrn_ref_no"/>
</tree>
</field>
</record>
<record id="sos_transfer_challan_return_from_customer_form_view" model="ir.ui.view">
<field name="name">Form</field>
<field name="model">sos_transfer_challan_return_from_customer</field>
<field name="arch" type="xml">
<form string="Model Form">
<sheet>
<!-- First Column -->
<group>
<group>
<field name="tc_no"/>
</group>
<group>
<field name="mrn_ref_no"/>
</group>
</group>
<notebook>
<page string="Summary">
<field name="line_ids">
<tree editable="bottom">
<field name="item_name"/>
<field name="item_type"/>
<field name="combined_incoming_doc_ref"/>
</tree>
</field>
</page>
<page string="Transaction Details">
<!-- <field name="line_ids">
<tree editable="bottom">
<field name="stores_handovered_by"/>
<field name="stores_handovered_on"/>
<field name="qc_tested_by"/>
<field name="qc_tested_on"/>
</tree>
</field> -->
<notebook>
<page string="From Stores to QC">
<field name="line_ids">
<tree editable="bottom">
<field name="item_name"/>
<field name="stores_handovered_by"/>
<field name="stores_handovered_on"/>
<field name="received_qty" string="Quantity Moved"/>
</tree>
</field>
</page>
<page string="Quality Inspection">
<field name="line_ids">
<tree editable="bottom">
<field name="item_name"/>
<field name="combined_incoming_doc_ref"/>
<field name="received_qty"/>
<field name="approved_qty"/>
<field name="rejected_qty"/>
<field name="qc_tested_by"/>
<field name="qc_tested_on"/>
<field name="ncmr_ref"/>
</tree>
</field>
</page>
<page string="From QC to Stores">
<field name="line_ids">
<tree editable="bottom">
<field name="item_name"/>
<field name="stores_received_by"/>
<field name="stores_received_on"/>
</tree>
</field>
</page>
</notebook>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<menuitem id="tc_return_from_customer_menu"
name="Transfer Challan (Return From Customer)"
parent="cnp_forms_menu_root" action="action_tc_return" groups="sos_inventory.sos_scg_group_manager,sos_inventory.sos_scg_group_user,sos_inventory.sos_production_user,sos_inventory.sos_qc_user,sos_inventory.sos_management_user,sos_inventory.sos_qa_user"/>
</odoo>

View File

@ -5,7 +5,7 @@
<field name="type">ir.actions.act_window</field>
<field name="res_model">sos_transfer_challan</field>
<field name="view_mode">tree,form,kanban</field>
<field name="context">{'group_by': 'plan_ref_no'}</field>
<field name="context"></field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No Data
@ -245,7 +245,7 @@ If no 'to' is used, values will be stored as entered."/>
</field>
</record>
<menuitem id="tc_menu"
name="Transfer Challan (Indent)"
name="Transfer Challan"
parent="production_forms_menu_root" action="action_tc_form_list" groups="sos_inventory.sos_scg_group_manager,sos_inventory.sos_scg_group_user,sos_inventory.sos_production_user,sos_inventory.sos_qc_user,sos_inventory.sos_management_user"/>

View File

@ -6,6 +6,15 @@
<field name="res_model">sos_wo</field>
<field name="view_mode">tree,form,kanban</field>
</record>
<record id="action_amend_server_action" model="ir.actions.server">
<field name="name">📝 Amend</field>
<field name="model_id" ref="model_sos_wo"/>
<field name="binding_model_id" ref="model_sos_wo"/>
<field name="state">code</field>
<field name="code">
action = model.action_amend()
</field>
</record>
<record id="sos_wo_view_panel" model="ir.ui.view">
<field name="name">sos_wo.search</field>
<field name="model">sos_wo</field>
@ -38,7 +47,8 @@
<field name="top_management_approved_by" string="Top Management Approved By" widget="many2one_avatar_user"/>
<field name="rounded_total_value" string="WO Value"/>
<field name="wo_status" widget="badge" decoration-success="wo_status == 'close'" decoration-danger="wo_status == 'open'"/>
<field name="wo_status" widget="badge" decoration-warning="wo_status == 'amend'" decoration-success="wo_status == 'close'" decoration-danger="wo_status == 'open'"/>
<field name="progress" widget="progressbar"/>
<field name="write_uid" string="Last Edited By" optional="hide"/>
<field name="write_date" string="Last Edited On" optional="hide"/>
@ -58,8 +68,10 @@
</header>
<sheet>
<widget name="web_ribbon" text="Open" bg_color="bg-danger" invisible="wo_status == 'close'"/>
<widget name="web_ribbon" text="Open" bg_color="bg-danger" invisible="wo_status == 'close' or wo_status == 'amend'"/>
<widget name="web_ribbon" text="Closed" bg_color="bg-success" invisible="wo_status == 'open'"/>
<widget name="web_ribbon" text="Amended" bg_color="bg-warning" invisible="wo_status != 'amend'"/>
<h2 style="text-align: center;text-transform: uppercase;text-shadow: 1px 1p 1px #140718;color: #65407c;padding:5px;">Work Order</h2><hr></hr><br></br>

View File

@ -67,7 +67,6 @@ class sos_case_diary(models.Model):
],
string="Service Type")
line_ids = fields.One2many('sos_case_diary_line', 'ref_id', string="Action")
accounts_line_ids = fields.One2many('sos_billing_collection', 'ref_id', string="Billed & Collected")
status = fields.Selection([('open', 'Open'),
('close', 'Closed without Order'),
('close_order', 'Closed with Order') ],default='open',string='Status')
@ -81,15 +80,7 @@ class sos_case_diary(models.Model):
po_copy = fields.Binary(string="PO Copy")
po_copy_filename=fields.Char(string="PO DocumentFile Name")
order_expected_on = fields.Date(string="Order Expected On")
line_ids_billed= fields.One2many(
'sos_billing_collection', 'ref_id',
domain=[('action_status', '=', 'Billed')]
)
line_ids_collected = fields.One2many(
'sos_billing_collection', 'ref_id',
domain=[('action_status', '=', 'Collected')]
)
@api.depends('end_customer_name', 'quote_no')
def _compute_display_name(self):
for rec in self:
@ -704,68 +695,3 @@ class SosCaseTransferHistory(models.Model):
)
return {'type': 'ir.actions.act_window_close'}
class SosBillingCollection(models.Model):
_name = 'sos_billing_collection'
_description = 'Billing & Collection Details'
ref_id = fields.Many2one('sos_case_diary', ondelete="cascade")
customer_name = fields.Many2one(
'sos_customers',
string="Customer Name",
related='ref_id.customer_name',
store=True,
readonly=True
)
sales_person = fields.Many2one(
'res.users',
string='Sales Executive', related="ref_id.sales_person",store=True)
action_status = fields.Selection([
('Billed', 'Billed'),
('Collected', 'Collected')
], string='Action')
date_of_action = fields.Date(string="Date")
currency_id = fields.Many2one(
'res.currency',
string='Currency',
default=lambda self: self.env['res.currency'].search([('name', '=', 'INR')], limit=1).id or False
)
value = fields.Monetary(currency_field='currency_id',string="Value(In Lakhs)")
def _get_financial_year(self, ref_date=None):
ref_date = ref_date or date.today()
start_year = ref_date.year if ref_date.month >= 4 else ref_date.year - 1
end_year = start_year + 1
return f"FY {start_year}-{end_year}"
@api.model
def create(self, vals):
# Get date and convert to datetime if it's a string
date_of_action = vals.get('date_of_action')
if isinstance(date_of_action, str):
date_of_action = datetime.strptime(date_of_action, '%Y-%m-%d').date()
fy = self._get_financial_year(date_of_action)
month_name = date_of_action.strftime('%B').lower()
action_status = vals.get('action_status', '').lower()
value = vals.get('value', 0.0)
# Compose the dynamic field
actual_field = f"{action_status}_target_{month_name}"
# Get sales person from related ref_id
ref_id = vals.get('ref_id')
sales_person = None
if ref_id:
ref = self.env['sos_case_diary'].browse(ref_id)
sales_person = ref.sales_person
if sales_person:
report = self.env['sos_sales_achievement_report'].search([
('financial_year', '=', fy),
('sales_person', '=', sales_person.id)
], limit=1)
if report and hasattr(report, actual_field):
current_value = getattr(report, actual_field, 0.0) or 0.0
report.write({actual_field: current_value + value})
return super(SosBillingCollection, self).create(vals)

View File

@ -5,6 +5,7 @@ class Battery_Installation_Requirement(models.Model):
_name = 'sos_proposal_boq'
_description = 'Battery Installation Details'
_rec_name="proposal_id"
_order = 'proposal_id asc'
_sql_constraints = [
('unique_proposal_id', 'unique(proposal_id)', 'Proposal ID must be unique!')
]
@ -56,7 +57,7 @@ class Battery_Installation_Requirement(models.Model):
warranty_cost = fields.Monetary(string="Warranty Cost", compute='_compute_warranty', store=True, currency_field='currency_id')
margin = fields.Monetary(string="Opreational Cost",compute='_compute_margin', currency_field='currency_id')
margin_per_battery = fields.Monetary(string="Opreational Cost per Battery", currency_field='currency_id')
warranty_percentage = fields.Integer(string="Warranty(%)")
warranty_percentage = fields.Float(string="Warranty(%)")
final_cost = fields.Monetary(string="Final Cost", compute='_compute_final_cost', store=True, currency_field='currency_id')
final_cost_per_battery = fields.Monetary(string="Final Cost", compute='_compute_final_cost_per_battery', store=True, currency_field='currency_id')
communication_type = fields.Selection([
@ -87,6 +88,11 @@ class Battery_Installation_Requirement(models.Model):
line_ids_fg_ups8 = fields.One2many('sos_proposal_boq_fg', 'ref_id', string="FG UPS 8",compute='_compute_line_ids_by_ups',store=False)
line_ids_fg_ups9 = fields.One2many('sos_proposal_boq_fg', 'ref_id', string="FG UPS 9",compute='_compute_line_ids_by_ups',store=False)
line_ids_fg_ups10 = fields.One2many('sos_proposal_boq_fg', 'ref_id', string="FG UPS 10",compute='_compute_line_ids_by_ups',store=False)
line_ids_fg_ups11 = fields.One2many('sos_proposal_boq_fg', 'ref_id', string="FG UPS 11",compute='_compute_line_ids_by_ups',store=False)
line_ids_fg_ups12 = fields.One2many('sos_proposal_boq_fg', 'ref_id', string="FG UPS 12",compute='_compute_line_ids_by_ups',store=False)
line_ids_fg_ups13 = fields.One2many('sos_proposal_boq_fg', 'ref_id', string="FG UPS 13",compute='_compute_line_ids_by_ups',store=False)
line_ids_fg_ups14 = fields.One2many('sos_proposal_boq_fg', 'ref_id', string="FG UPS 14",compute='_compute_line_ids_by_ups',store=False)
line_ids_fg_ups15 = fields.One2many('sos_proposal_boq_fg', 'ref_id', string="FG UPS 15",compute='_compute_line_ids_by_ups',store=False)
#SFG Fields
line_ids_sfg_ups1 = fields.One2many('sos_proposal_boq_sfg', 'ref_id', string="SFG UPS 1",compute='_compute_line_ids_by_ups',store=False)
@ -99,6 +105,12 @@ class Battery_Installation_Requirement(models.Model):
line_ids_sfg_ups8 = fields.One2many('sos_proposal_boq_sfg', 'ref_id', string="SFG UPS 8",compute='_compute_line_ids_by_ups',store=False)
line_ids_sfg_ups9 = fields.One2many('sos_proposal_boq_sfg', 'ref_id', string="SFG UPS 9",compute='_compute_line_ids_by_ups',store=False)
line_ids_sfg_ups10 = fields.One2many('sos_proposal_boq_sfg', 'ref_id', string="SFG UPS 10",compute='_compute_line_ids_by_ups',store=False)
line_ids_sfg_ups11 = fields.One2many('sos_proposal_boq_sfg', 'ref_id', string="SFG UPS 11",compute='_compute_line_ids_by_ups',store=False)
line_ids_sfg_ups12 = fields.One2many('sos_proposal_boq_sfg', 'ref_id', string="SFG UPS 12",compute='_compute_line_ids_by_ups',store=False)
line_ids_sfg_ups13 = fields.One2many('sos_proposal_boq_sfg', 'ref_id', string="SFG UPS 13",compute='_compute_line_ids_by_ups',store=False)
line_ids_sfg_ups14 = fields.One2many('sos_proposal_boq_sfg', 'ref_id', string="SFG UPS 14",compute='_compute_line_ids_by_ups',store=False)
line_ids_sfg_ups15 = fields.One2many('sos_proposal_boq_sfg', 'ref_id', string="SFG UPS 15",compute='_compute_line_ids_by_ups',store=False)
#Material Fields
line_ids_material_ups1 = fields.One2many('sos_proposal_boq_material', 'ref_id', string="Material UPS 1",compute='_compute_line_ids_by_ups',store=False)
@ -111,6 +123,12 @@ class Battery_Installation_Requirement(models.Model):
line_ids_material_ups8 = fields.One2many('sos_proposal_boq_material', 'ref_id', string="Material UPS 8",compute='_compute_line_ids_by_ups',store=False)
line_ids_material_ups9 = fields.One2many('sos_proposal_boq_material', 'ref_id', string="Material UPS 9",compute='_compute_line_ids_by_ups',store=False)
line_ids_material_ups10 = fields.One2many('sos_proposal_boq_material', 'ref_id', string="Material UPS 10",compute='_compute_line_ids_by_ups',store=False)
line_ids_material_ups11 = fields.One2many('sos_proposal_boq_material', 'ref_id', string="Material UPS 11",compute='_compute_line_ids_by_ups',store=False)
line_ids_material_ups12 = fields.One2many('sos_proposal_boq_material', 'ref_id', string="Material UPS 12",compute='_compute_line_ids_by_ups',store=False)
line_ids_material_ups13 = fields.One2many('sos_proposal_boq_material', 'ref_id', string="Material UPS 13",compute='_compute_line_ids_by_ups',store=False)
line_ids_material_ups14 = fields.One2many('sos_proposal_boq_material', 'ref_id', string="Material UPS 14",compute='_compute_line_ids_by_ups',store=False)
line_ids_material_ups15 = fields.One2many('sos_proposal_boq_material', 'ref_id', string="Material UPS 15",compute='_compute_line_ids_by_ups',store=False)
#Installation Kit Fields
line_ids_installation_kit_ups1 = fields.One2many('sos_proposal_line_material_installation', 'ref_id', string="Installation Kit UPS 1",compute='_compute_line_ids_by_ups',store=False)
@ -123,6 +141,11 @@ class Battery_Installation_Requirement(models.Model):
line_ids_installation_kit_ups8 = fields.One2many('sos_proposal_line_material_installation', 'ref_id', string="Installation Kit UPS 8",compute='_compute_line_ids_by_ups',store=False)
line_ids_installation_kit_ups9 = fields.One2many('sos_proposal_line_material_installation', 'ref_id', string="Installation Kit UPS 9",compute='_compute_line_ids_by_ups',store=False)
line_ids_installation_kit_ups10 = fields.One2many('sos_proposal_line_material_installation', 'ref_id', string="Installation Kit UPS 10",compute='_compute_line_ids_by_ups',store=False)
line_ids_installation_kit_ups11 = fields.One2many('sos_proposal_line_material_installation', 'ref_id', string="Installation Kit UPS 11",compute='_compute_line_ids_by_ups',store=False)
line_ids_installation_kit_ups12 = fields.One2many('sos_proposal_line_material_installation', 'ref_id', string="Installation Kit UPS 12",compute='_compute_line_ids_by_ups',store=False)
line_ids_installation_kit_ups13 = fields.One2many('sos_proposal_line_material_installation', 'ref_id', string="Installation Kit UPS 13",compute='_compute_line_ids_by_ups',store=False)
line_ids_installation_kit_ups14 = fields.One2many('sos_proposal_line_material_installation', 'ref_id', string="Installation Kit UPS 14",compute='_compute_line_ids_by_ups',store=False)
line_ids_installation_kit_ups15 = fields.One2many('sos_proposal_line_material_installation', 'ref_id', string="Installation Kit UPS 15",compute='_compute_line_ids_by_ups',store=False)
#Miscellaneous Kit Fields
line_ids_miscellaneous_ups1 = fields.One2many('sos_proposal_miscellaneous_items', 'ref_id', string="Miscellaneous UPS 1",compute='_compute_line_ids_by_ups',store=False)
@ -135,6 +158,11 @@ class Battery_Installation_Requirement(models.Model):
line_ids_miscellaneous_ups8 = fields.One2many('sos_proposal_miscellaneous_items', 'ref_id', string="Miscellaneous UPS 8",compute='_compute_line_ids_by_ups',store=False)
line_ids_miscellaneous_ups9 = fields.One2many('sos_proposal_miscellaneous_items', 'ref_id', string="Miscellaneous UPS 9",compute='_compute_line_ids_by_ups',store=False)
line_ids_miscellaneous_ups10 = fields.One2many('sos_proposal_miscellaneous_items', 'ref_id', string="Miscellaneous UPS 10",compute='_compute_line_ids_by_ups',store=False)
line_ids_miscellaneous_ups11 = fields.One2many('sos_proposal_miscellaneous_items', 'ref_id', string="Miscellaneous UPS 11",compute='_compute_line_ids_by_ups',store=False)
line_ids_miscellaneous_ups12 = fields.One2many('sos_proposal_miscellaneous_items', 'ref_id', string="Miscellaneous UPS 12",compute='_compute_line_ids_by_ups',store=False)
line_ids_miscellaneous_ups13 = fields.One2many('sos_proposal_miscellaneous_items', 'ref_id', string="Miscellaneous UPS 13",compute='_compute_line_ids_by_ups',store=False)
line_ids_miscellaneous_ups14 = fields.One2many('sos_proposal_miscellaneous_items', 'ref_id', string="Miscellaneous UPS 14",compute='_compute_line_ids_by_ups',store=False)
line_ids_miscellaneous_ups15 = fields.One2many('sos_proposal_miscellaneous_items', 'ref_id', string="Miscellaneous UPS 15",compute='_compute_line_ids_by_ups',store=False)
#ups totals
ups1_total = fields.Float(string="UPS 1 Total Cost",compute='_compute_ups_total',store=True)
@ -147,6 +175,11 @@ class Battery_Installation_Requirement(models.Model):
ups8_total = fields.Float(string="UPS 8 Total Cost", compute='_compute_ups_total', store=True)
ups9_total = fields.Float(string="UPS 9 Total Cost", compute='_compute_ups_total', store=True)
ups10_total = fields.Float(string="UPS 10 Total Cost", compute='_compute_ups_total', store=True)
ups11_total = fields.Float(string="UPS 11 Total Cost", compute='_compute_ups_total', store=True)
ups12_total = fields.Float(string="UPS 12 Total Cost", compute='_compute_ups_total', store=True)
ups13_total = fields.Float(string="UPS 13 Total Cost", compute='_compute_ups_total', store=True)
ups14_total = fields.Float(string="UPS 14 Total Cost", compute='_compute_ups_total', store=True)
ups15_total = fields.Float(string="UPS 15 Total Cost", compute='_compute_ups_total', store=True)
extra_lines_cost = fields.Monetary(string="Cost", compute='_compute_extra_lines_cost', store=True, currency_field='currency_id')
packing_and_forwarding = fields.Monetary(string="Packing & Forwarding", currency_field='currency_id',store=True)
@ -161,6 +194,11 @@ class Battery_Installation_Requirement(models.Model):
line_ids_spare_ups8 = fields.One2many('sos_proposal_line_spare_ups8','ref_id', string="Spare UPS 8")
line_ids_spare_ups9 = fields.One2many('sos_proposal_line_spare_ups9','ref_id', string="Spare UPS 9")
line_ids_spare_ups10 = fields.One2many('sos_proposal_line_spare_ups10','ref_id', string="Spare UPS 10")
line_ids_spare_ups11 = fields.One2many('sos_proposal_line_spare_ups11','ref_id', string="Spare UPS 11")
line_ids_spare_ups12 = fields.One2many('sos_proposal_line_spare_ups12','ref_id', string="Spare UPS 12")
line_ids_spare_ups13 = fields.One2many('sos_proposal_line_spare_ups13','ref_id', string="Spare UPS 13")
line_ids_spare_ups14 = fields.One2many('sos_proposal_line_spare_ups14','ref_id', string="Spare UPS 14")
line_ids_spare_ups15 = fields.One2many('sos_proposal_line_spare_ups15','ref_id', string="Spare UPS 15")
@api.model
def create(self, vals):
res = super().create(vals)
@ -254,11 +292,16 @@ class Battery_Installation_Requirement(models.Model):
'line_ids_spare_ups7.total_price', 'line_ids_spare_ups7.production_cost',
'line_ids_spare_ups8.total_price', 'line_ids_spare_ups8.production_cost',
'line_ids_spare_ups9.total_price', 'line_ids_spare_ups9.production_cost',
'line_ids_spare_ups10.total_price', 'line_ids_spare_ups10.production_cost'
'line_ids_spare_ups10.total_price', 'line_ids_spare_ups10.production_cost',
'line_ids_spare_ups11.total_price', 'line_ids_spare_ups11.production_cost',
'line_ids_spare_ups12.total_price', 'line_ids_spare_ups12.production_cost',
'line_ids_spare_ups13.total_price', 'line_ids_spare_ups13.production_cost',
'line_ids_spare_ups14.total_price', 'line_ids_spare_ups14.production_cost',
'line_ids_spare_ups15.total_price', 'line_ids_spare_ups15.production_cost'
)
def _compute_ups_total(self):
for rec in self:
for i in range(1, 11):
for i in range(1, 16):
total = 0
for field_name in [
'line_ids_fg',
@ -293,6 +336,11 @@ class Battery_Installation_Requirement(models.Model):
rec.line_ids_fg_ups8 = rec.line_ids_fg.filtered(lambda l: l.ups_index == 8)
rec.line_ids_fg_ups9 = rec.line_ids_fg.filtered(lambda l: l.ups_index == 9)
rec.line_ids_fg_ups10 = rec.line_ids_fg.filtered(lambda l: l.ups_index == 10)
rec.line_ids_fg_ups11 = rec.line_ids_fg.filtered(lambda l: l.ups_index == 11)
rec.line_ids_fg_ups12 = rec.line_ids_fg.filtered(lambda l: l.ups_index == 12)
rec.line_ids_fg_ups13 = rec.line_ids_fg.filtered(lambda l: l.ups_index == 13)
rec.line_ids_fg_ups14 = rec.line_ids_fg.filtered(lambda l: l.ups_index == 14)
rec.line_ids_fg_ups15 = rec.line_ids_fg.filtered(lambda l: l.ups_index == 15)
rec.line_ids_sfg_ups1 = rec.line_ids_sfg.filtered(lambda l: l.ups_index == 1)
rec.line_ids_sfg_ups2 = rec.line_ids_sfg.filtered(lambda l: l.ups_index == 2)
@ -304,6 +352,11 @@ class Battery_Installation_Requirement(models.Model):
rec.line_ids_sfg_ups8 = rec.line_ids_sfg.filtered(lambda l: l.ups_index == 8)
rec.line_ids_sfg_ups9 = rec.line_ids_sfg.filtered(lambda l: l.ups_index == 9)
rec.line_ids_sfg_ups10 = rec.line_ids_sfg.filtered(lambda l: l.ups_index == 10)
rec.line_ids_sfg_ups11 = rec.line_ids_sfg.filtered(lambda l: l.ups_index == 11)
rec.line_ids_sfg_ups12 = rec.line_ids_sfg.filtered(lambda l: l.ups_index == 12)
rec.line_ids_sfg_ups13 = rec.line_ids_sfg.filtered(lambda l: l.ups_index == 13)
rec.line_ids_sfg_ups14 = rec.line_ids_sfg.filtered(lambda l: l.ups_index == 14)
rec.line_ids_sfg_ups15 = rec.line_ids_sfg.filtered(lambda l: l.ups_index == 15)
rec.line_ids_material_ups1 = rec.line_ids_material.filtered(lambda l: l.ups_index == 1)
rec.line_ids_material_ups2 = rec.line_ids_material.filtered(lambda l: l.ups_index == 2)
@ -315,6 +368,12 @@ class Battery_Installation_Requirement(models.Model):
rec.line_ids_material_ups8 = rec.line_ids_material.filtered(lambda l: l.ups_index == 8)
rec.line_ids_material_ups9 = rec.line_ids_material.filtered(lambda l: l.ups_index == 9)
rec.line_ids_material_ups10 = rec.line_ids_material.filtered(lambda l: l.ups_index == 10)
rec.line_ids_material_ups11 = rec.line_ids_material.filtered(lambda l: l.ups_index == 11)
rec.line_ids_material_ups12 = rec.line_ids_material.filtered(lambda l: l.ups_index == 12)
rec.line_ids_material_ups13 = rec.line_ids_material.filtered(lambda l: l.ups_index == 13)
rec.line_ids_material_ups14 = rec.line_ids_material.filtered(lambda l: l.ups_index == 14)
rec.line_ids_material_ups15 = rec.line_ids_material.filtered(lambda l: l.ups_index == 15)
rec.line_ids_installation_kit_ups1 = rec.line_ids_installation_kit.filtered(lambda l: l.ups_index == 1)
rec.line_ids_installation_kit_ups2 = rec.line_ids_installation_kit.filtered(lambda l: l.ups_index == 2)
@ -326,6 +385,11 @@ class Battery_Installation_Requirement(models.Model):
rec.line_ids_installation_kit_ups8 = rec.line_ids_installation_kit.filtered(lambda l: l.ups_index == 8)
rec.line_ids_installation_kit_ups9 = rec.line_ids_installation_kit.filtered(lambda l: l.ups_index == 9)
rec.line_ids_installation_kit_ups10 = rec.line_ids_installation_kit.filtered(lambda l: l.ups_index == 10)
rec.line_ids_installation_kit_ups11 = rec.line_ids_installation_kit.filtered(lambda l: l.ups_index == 11)
rec.line_ids_installation_kit_ups12 = rec.line_ids_installation_kit.filtered(lambda l: l.ups_index == 12)
rec.line_ids_installation_kit_ups13 = rec.line_ids_installation_kit.filtered(lambda l: l.ups_index == 13)
rec.line_ids_installation_kit_ups14 = rec.line_ids_installation_kit.filtered(lambda l: l.ups_index == 14)
rec.line_ids_installation_kit_ups15 = rec.line_ids_installation_kit.filtered(lambda l: l.ups_index == 15)
rec.line_ids_miscellaneous_ups1 = rec.line_ids_miscellaneous.filtered(lambda l: l.ups_index == 1)
rec.line_ids_miscellaneous_ups2 = rec.line_ids_miscellaneous.filtered(lambda l: l.ups_index == 2)
@ -337,6 +401,11 @@ class Battery_Installation_Requirement(models.Model):
rec.line_ids_miscellaneous_ups8 = rec.line_ids_miscellaneous.filtered(lambda l: l.ups_index == 8)
rec.line_ids_miscellaneous_ups9 = rec.line_ids_miscellaneous.filtered(lambda l: l.ups_index == 9)
rec.line_ids_miscellaneous_ups10 = rec.line_ids_miscellaneous.filtered(lambda l: l.ups_index == 10)
rec.line_ids_miscellaneous_ups11 = rec.line_ids_miscellaneous.filtered(lambda l: l.ups_index == 11)
rec.line_ids_miscellaneous_ups12 = rec.line_ids_miscellaneous.filtered(lambda l: l.ups_index == 12)
rec.line_ids_miscellaneous_ups13 = rec.line_ids_miscellaneous.filtered(lambda l: l.ups_index == 13)
rec.line_ids_miscellaneous_ups14 = rec.line_ids_miscellaneous.filtered(lambda l: l.ups_index == 14)
rec.line_ids_miscellaneous_ups15 = rec.line_ids_miscellaneous.filtered(lambda l: l.ups_index == 15)
@api.model
@ -362,10 +431,14 @@ class Battery_Installation_Requirement(models.Model):
self.communication_type = self.proposal_id.communication_type
self.specific_requirements = self.proposal_id.specific_requirements
multiplier = max(1, math.ceil(self.proposal_id.number_of_batteries / 20))
if self.proposal_id.number_of_batteries < 100:
self.engineers_nos = 1
self.no_of_days = multiplier
else:
self.engineers_nos = 2
self.no_of_days = multiplier / 2
packing_calculation = 1200
packing_kg_12V=100
packing_kg_12V = 100 * self.proposal_id.number_of_ups
direction = self.proposal_id.direction
if direction == "North":
forwarding_calculation = 20 * packing_kg_12V
@ -375,8 +448,9 @@ class Battery_Installation_Requirement(models.Model):
forwarding_calculation = 23 * packing_kg_12V
else:
forwarding_calculation = 13 * packing_kg_12V
base_amount = 0.20 * (packing_calculation + forwarding_calculation)
self.packing_and_forwarding = base_amount * 0.18
base_amount = 1.20 * (packing_calculation + forwarding_calculation)
self.packing_and_forwarding = base_amount * 1.18
# Clear all lines
self.line_ids_fg = [(5, 0, 0)]
self.line_ids_sfg = [(5, 0, 0)]
@ -424,6 +498,7 @@ class Battery_Installation_Requirement(models.Model):
material_lines.append((0, 0, {
'component_id': material_record.id,
'uom': material_record.uom,
'singet_set_qty':single_set_qty,
'unit_price': material_record.unit_price,
'description': material_record.description,
'ups_index': ups_index,
@ -778,7 +853,7 @@ class sos_proposal_Material_installationkit(models.Model):
def _compute_set_wise(self):
for record in self:
record.quantity = record.singet_set_qty * record.total_set
@api.depends('unit_price','quantity')
@api.depends('unit_price','quantity','production_cost')
def _compute_total_price(self):
for record in self:
if record.production_cost:
@ -1153,6 +1228,176 @@ class sos_spare_material10(models.Model):
_name = 'sos_proposal_line_spare_ups10'
_description = 'Spare Material 10'
ref_id = fields.Many2one('sos_proposal_boq', ondelete="cascade")
component_id = fields.Many2one('sos_material', string="Material Name", required=True)
uom = fields.Selection([('meters', 'Meters'),('Nos', 'Nos'),('coils', 'Coils'), ('litre', 'litre'), ('kg', 'Kilogram'), ('Packs', 'Packs')], default="Nos",string="Uom")
currency_id = fields.Many2one('res.currency', string='Currency')
material_code = fields.Char(related="component_id.material_code",string="Material Code")
material_name = fields.Char(related="component_id.part_no",string="Material Name")
singet_set_qty = fields.Integer(string="Single Set Quantity",default=1)
total_set = fields.Integer(string="Total Set",default=1)
quantity = fields.Integer(string="Quantity",compute="_compute_set_wise",readonly=False)
unit_price = fields.Monetary(store=True,currency_field='currency_id',string="Unit Price",related="component_id.unit_price")
total_price = fields.Monetary(string="Total",compute="_compute_total_price")
description = fields.Char(string="Description")
production_cost = fields.Boolean(string="Include in Costing",default=True)
ups_index = fields.Integer(string="UPS Index",store=True)
@api.onchange('component_id')
def _onchange_component_id(self):
for record in self:
if record.component_id:
record.unit_price = record.component_id.unit_price
@api.depends('singet_set_qty','total_set')
def _compute_set_wise(self):
for record in self:
record.quantity = record.singet_set_qty * record.total_set
@api.depends('unit_price', 'quantity', 'production_cost')
def _compute_total_price(self):
for record in self:
if record.production_cost:
record.total_price = record.unit_price * record.quantity
else:
record.total_price = 0.00
class sos_spare_material11(models.Model):
_name = 'sos_proposal_line_spare_ups11'
_description = 'Spare Material 11'
ref_id = fields.Many2one('sos_proposal_boq', ondelete="cascade")
component_id = fields.Many2one('sos_material', string="Material Name", required=True)
uom = fields.Selection([('meters', 'Meters'),('Nos', 'Nos'),('coils', 'Coils'), ('litre', 'litre'), ('kg', 'Kilogram'), ('Packs', 'Packs')], default="Nos",string="Uom")
currency_id = fields.Many2one('res.currency', string='Currency')
material_code = fields.Char(related="component_id.material_code",string="Material Code")
material_name = fields.Char(related="component_id.part_no",string="Material Name")
singet_set_qty = fields.Integer(string="Single Set Quantity",default=1)
total_set = fields.Integer(string="Total Set",default=1)
quantity = fields.Integer(string="Quantity",compute="_compute_set_wise",readonly=False)
unit_price = fields.Monetary(store=True,currency_field='currency_id',string="Unit Price",related="component_id.unit_price")
total_price = fields.Monetary(string="Total",compute="_compute_total_price")
description = fields.Char(string="Description")
production_cost = fields.Boolean(string="Include in Costing",default=True)
ups_index = fields.Integer(string="UPS Index",store=True)
@api.onchange('component_id')
def _onchange_component_id(self):
for record in self:
if record.component_id:
record.unit_price = record.component_id.unit_price
@api.depends('singet_set_qty','total_set')
def _compute_set_wise(self):
for record in self:
record.quantity = record.singet_set_qty * record.total_set
@api.depends('unit_price', 'quantity', 'production_cost')
def _compute_total_price(self):
for record in self:
if record.production_cost:
record.total_price = record.unit_price * record.quantity
else:
record.total_price = 0.00
class sos_spare_material12(models.Model):
_name = 'sos_proposal_line_spare_ups12'
_description = 'Spare Material 12'
ref_id = fields.Many2one('sos_proposal_boq', ondelete="cascade")
component_id = fields.Many2one('sos_material', string="Material Name", required=True)
uom = fields.Selection([('meters', 'Meters'),('Nos', 'Nos'),('coils', 'Coils'), ('litre', 'litre'), ('kg', 'Kilogram'), ('Packs', 'Packs')], default="Nos",string="Uom")
currency_id = fields.Many2one('res.currency', string='Currency')
material_code = fields.Char(related="component_id.material_code",string="Material Code")
material_name = fields.Char(related="component_id.part_no",string="Material Name")
singet_set_qty = fields.Integer(string="Single Set Quantity",default=1)
total_set = fields.Integer(string="Total Set",default=1)
quantity = fields.Integer(string="Quantity",compute="_compute_set_wise",readonly=False)
unit_price = fields.Monetary(store=True,currency_field='currency_id',string="Unit Price",related="component_id.unit_price")
total_price = fields.Monetary(string="Total",compute="_compute_total_price")
description = fields.Char(string="Description")
production_cost = fields.Boolean(string="Include in Costing",default=True)
ups_index = fields.Integer(string="UPS Index",store=True)
@api.onchange('component_id')
def _onchange_component_id(self):
for record in self:
if record.component_id:
record.unit_price = record.component_id.unit_price
@api.depends('singet_set_qty','total_set')
def _compute_set_wise(self):
for record in self:
record.quantity = record.singet_set_qty * record.total_set
@api.depends('unit_price', 'quantity', 'production_cost')
def _compute_total_price(self):
for record in self:
if record.production_cost:
record.total_price = record.unit_price * record.quantity
else:
record.total_price = 0.00
class sos_spare_material13(models.Model):
_name = 'sos_proposal_line_spare_ups13'
_description = 'Spare Material 13'
ref_id = fields.Many2one('sos_proposal_boq', ondelete="cascade")
component_id = fields.Many2one('sos_material', string="Material Name", required=True)
uom = fields.Selection([('meters', 'Meters'),('Nos', 'Nos'),('coils', 'Coils'), ('litre', 'litre'), ('kg', 'Kilogram'), ('Packs', 'Packs')], default="Nos",string="Uom")
currency_id = fields.Many2one('res.currency', string='Currency')
material_code = fields.Char(related="component_id.material_code",string="Material Code")
material_name = fields.Char(related="component_id.part_no",string="Material Name")
singet_set_qty = fields.Integer(string="Single Set Quantity",default=1)
total_set = fields.Integer(string="Total Set",default=1)
quantity = fields.Integer(string="Quantity",compute="_compute_set_wise",readonly=False)
unit_price = fields.Monetary(store=True,currency_field='currency_id',string="Unit Price",related="component_id.unit_price")
total_price = fields.Monetary(string="Total",compute="_compute_total_price")
description = fields.Char(string="Description")
production_cost = fields.Boolean(string="Include in Costing",default=True)
ups_index = fields.Integer(string="UPS Index",store=True)
@api.onchange('component_id')
def _onchange_component_id(self):
for record in self:
if record.component_id:
record.unit_price = record.component_id.unit_price
@api.depends('singet_set_qty','total_set')
def _compute_set_wise(self):
for record in self:
record.quantity = record.singet_set_qty * record.total_set
@api.depends('unit_price', 'quantity', 'production_cost')
def _compute_total_price(self):
for record in self:
if record.production_cost:
record.total_price = record.unit_price * record.quantity
else:
record.total_price = 0.00
class sos_spare_material14(models.Model):
_name = 'sos_proposal_line_spare_ups14'
_description = 'Spare Material 14'
ref_id = fields.Many2one('sos_proposal_boq', ondelete="cascade")
component_id = fields.Many2one('sos_material', string="Material Name", required=True)
uom = fields.Selection([('meters', 'Meters'),('Nos', 'Nos'),('coils', 'Coils'), ('litre', 'litre'), ('kg', 'Kilogram'), ('Packs', 'Packs')], default="Nos",string="Uom")
currency_id = fields.Many2one('res.currency', string='Currency')
material_code = fields.Char(related="component_id.material_code",string="Material Code")
material_name = fields.Char(related="component_id.part_no",string="Material Name")
singet_set_qty = fields.Integer(string="Single Set Quantity",default=1)
total_set = fields.Integer(string="Total Set",default=1)
quantity = fields.Integer(string="Quantity",compute="_compute_set_wise",readonly=False)
unit_price = fields.Monetary(store=True,currency_field='currency_id',string="Unit Price",related="component_id.unit_price")
total_price = fields.Monetary(string="Total",compute="_compute_total_price")
description = fields.Char(string="Description")
production_cost = fields.Boolean(string="Include in Costing",default=True)
ups_index = fields.Integer(string="UPS Index",store=True)
@api.onchange('component_id')
def _onchange_component_id(self):
for record in self:
if record.component_id:
record.unit_price = record.component_id.unit_price
@api.depends('singet_set_qty','total_set')
def _compute_set_wise(self):
for record in self:
record.quantity = record.singet_set_qty * record.total_set
@api.depends('unit_price', 'quantity', 'production_cost')
def _compute_total_price(self):
for record in self:
if record.production_cost:
record.total_price = record.unit_price * record.quantity
else:
record.total_price = 0.00
class sos_spare_material15(models.Model):
_name = 'sos_proposal_line_spare_ups15'
_description = 'Spare Material 15'
ref_id = fields.Many2one('sos_proposal_boq', ondelete="cascade")
component_id = fields.Many2one('sos_material', string="Material Name", required=True)
uom = fields.Selection([('meters', 'Meters'),('Nos', 'Nos'),('coils', 'Coils'), ('litre', 'litre'), ('kg', 'Kilogram'), ('Packs', 'Packs')], default="Nos",string="Uom")

View File

@ -18,7 +18,7 @@ class SOS_Proposal_Builder(models.Model):
string='Currency',
default=lambda self: self.env['res.currency'].search([('name', '=', 'INR')], limit=1).id or False
)
total_cost = fields.Monetary(string="Total Cost", currency_field='currency_id')
total_cost = fields.Float(string="Total Cost", compute='_compute_total_cost', store=True)
buffer_in_percentage = fields.Integer(string="Buffer(%)",default=0,store=True)
total_with_buffer = fields.Monetary(string="Total with Buffer", compute='_compute_total_with_buffer', currency_field='currency_id', store=True)
#Proposal builder
@ -197,6 +197,32 @@ class SOS_Proposal_Builder(models.Model):
for rec in self:
buffer_percent = rec.buffer_in_percentage or 0.0
rec.total_with_buffer = rec.total_cost * (1 + buffer_percent / 100.0)
@api.depends('proposal_id')
def _compute_total_cost(self):
for rec in self:
boq = self.env['sos_proposal_boq'].search(
[('proposal_id', '=', rec.proposal_id.id)],
limit=1, order='id desc'
)
rec.total_cost = boq.final_cost if boq else 0.0
@api.model
def create(self, vals):
if vals.get('proposal_id') and not vals.get('total_cost'):
boq = self.env['sos_proposal_boq'].search(
[('proposal_id', '=', vals['proposal_id'])], limit=1, order='id desc'
)
if boq:
vals['total_cost'] = boq.final_cost
return super().create(vals)
def write(self, vals):
if vals.get('proposal_id') and not vals.get('total_cost'):
boq = self.env['sos_proposal_boq'].search(
[('proposal_id', '=', vals['proposal_id'])], limit=1, order='id desc'
)
if boq:
vals['total_cost'] = boq.final_cost
return super().write(vals)
class SOS_Technical_Diagrams(models.Model):
_name = 'sos_proposal_diagrams'

View File

@ -147,8 +147,8 @@ class Battery_Installation_Requirement(models.Model):
@api.onchange('number_of_ups')
def _onchange_number_of_ups(self):
if self.number_of_ups is not None:
if self.number_of_ups > 10:
raise ValidationError("Number of UPS cannot be more than 10.")
if self.number_of_ups > 15:
raise ValidationError("Number of UPS cannot be more than 15.")
lines = [(5, 0, 0)] # clear all
for i in range(self.number_of_ups):

View File

@ -1,8 +1,9 @@
from odoo import models, fields, api
from datetime import date
from datetime import date, timedelta,datetime
import re
import calendar
from odoo.exceptions import UserError
class SOS_Sales_Achievement_Report(models.Model):
@ -20,13 +21,13 @@ class SOS_Sales_Achievement_Report(models.Model):
planned_target_april = fields.Float(string="Planned For April")
actual_target_april = fields.Float(string="Actual For April")
billed_target_april = fields.Float(string="Billed For April")
yet_to_billed_target_april = fields.Float(string="Yet to Billed For April")
yet_to_billed_target_april = fields.Float(string="Yet to Billed For April",compute="_compute_yet_to_billed_april")
collected_target_april = fields.Float(string="Collected For April")
achievement_percentage_april = fields.Char(string="Achievement Percentage For April", compute="_compute_achievement_percentage", store=True)
planned_target_may = fields.Float(string="Planned For May")
actual_target_may = fields.Float(string="Actual For May")
billed_target_may = fields.Float(string="Billed For May")
yet_to_billed_target_may = fields.Float(string="Yet to Billed For May")
yet_to_billed_target_may = fields.Float(string="Yet to Billed For May",compute="_compute_yet_to_billed_targets")
collected_target_may = fields.Float(string="Collected For May")
achievement_percentage_may = fields.Char(string="Achievement Percentage For May", compute="_compute_achievement_percentage", store=True)
planned_target_june = fields.Float(string="Planned For June")
@ -108,6 +109,49 @@ class SOS_Sales_Achievement_Report(models.Model):
ytd_billed = fields.Float(string="YTD Billed", store=True,compute="_compute_ytd_billed")
ytd_collected = fields.Float(string="YTD Collected", store=True,compute="_compute_ytd_collected")
line_ids = fields.One2many('sos_sales_achievement_report_brief', 'ref_id',copy=True)
billing_collection_line_ids = fields.One2many(
'sos_billing_collection',
'ref_id',
string="Billing Collection Lines"
)
@api.depends('opening_balance', 'actual_target_april', 'billed_target_april')
def _compute_yet_to_billed_april(self):
for rec in self:
rec.yet_to_billed_target_april = (rec.opening_balance or 0.0) + \
(rec.actual_target_april or 0.0) - \
(rec.billed_target_april or 0.0)
@api.depends(
'yet_to_billed_target_april', # link to April
'actual_target_may', 'billed_target_may',
'actual_target_june', 'billed_target_june',
'actual_target_july', 'billed_target_july',
'actual_target_august', 'billed_target_august',
'actual_target_september', 'billed_target_september',
'actual_target_october', 'billed_target_october',
'actual_target_november', 'billed_target_november',
'actual_target_december', 'billed_target_december',
'actual_target_january', 'billed_target_january',
'actual_target_february', 'billed_target_february',
'actual_target_march', 'billed_target_march',
)
def _compute_yet_to_billed_targets(self):
month_order = [
'may', 'june', 'july', 'august', 'september',
'october', 'november', 'december',
'january', 'february', 'march'
]
for rec in self:
prev_yet_to_bill = rec.yet_to_billed_target_april or 0.0
for month in month_order:
actual = getattr(rec, f'actual_target_{month}', 0.0) or 0.0
billed = getattr(rec, f'billed_target_{month}', 0.0) or 0.0
result = prev_yet_to_bill + actual - billed
setattr(rec, f'yet_to_billed_target_{month}', result)
prev_yet_to_bill = result
@api.depends(
'yet_to_billed_target_april', 'yet_to_billed_target_may', 'yet_to_billed_target_june',
@ -137,41 +181,52 @@ class SOS_Sales_Achievement_Report(models.Model):
def action_view_billed_lines(self):
self.ensure_one()
# Extract the month from context
month = int(self.env.context.get('month', 0))
if not month:
month = 4 # fallback to April
# You must extract year (hardcoded or dynamic based on financial year logic)
# Assuming your main model has `financial_year = 'FY 2025-2026'`
match = re.search(r'FY\s*(\d{4})', self.financial_year or '')
if match:
year = int(match.group(1))
month = int(self.env.context.get('month', 4)) # default April
action = self.env.context.get('action', 'Collected')
if action == 'Billed':
view_id = self.env.ref('sos_sales.view_sos_billed_collection_wizard_form_billed').id
else:
year = date.today().year # fallback
view_id = self.env.ref('sos_sales.view_sos_billed_collection_wizard_form_collected').id
# Get month boundaries
# Extract year from financial_year string like 'FY 2025-2026'
match = re.search(r'FY\s*(\d{4})', self.financial_year or '')
year = int(match.group(1)) if match else date.today().year
# Get month date range
last_day = calendar.monthrange(year, month)[1]
from_date = f'{year}-{month:02d}-01'
to_date = f'{year}-{month:02d}-{last_day:02d}'
# Fetch Billed lines
from_date = date(year, month, 1)
to_date = date(year, month, last_day)
# Use the actual related record's value (not the related field)
sales_person_id = self.sales_person.id or self.ref('sales_person').id
# If sales_person is still None, raise a warning
if not sales_person_id:
raise UserError("Sales person is missing in this record.")
# Search filtered billing lines
billed_lines = self.env['sos_billing_collection'].search([
('sales_person', '=', self.sales_person.id),
('action_status', '=', self.env.context.get('action')),
('sales_person', '=', sales_person_id),
('action_status', '=', action),
('date_of_action', '>=', from_date),
('date_of_action', '<=', to_date),
])
wizard = self.env['sos_billed_collection_wizard'].create({
'main_parent_id': self.id,
'billed_line_ids': [(6, 0, billed_lines.ids)],
'action_status': action,
})
return {
'name': f"{self.env.context.get('action')} Items",
'type': 'ir.actions.act_window',
'res_model': 'sos_billed_collection_wizard',
'view_mode': 'form',
'view_id': view_id,
'target': 'new',
'context': {
'default_billed_line_ids': [(6, 0, billed_lines.ids)],
'default_parent_id': self.id,
}
'res_id': wizard.id,
}
def action_view_brief_lines(self):
self.ensure_one()
domain = [('ref_id', '=', self.id)]
@ -204,6 +259,7 @@ class SOS_Sales_Achievement_Report(models.Model):
}
}
@api.depends(
'collected_target_april', 'collected_target_may', 'collected_target_june',
'collected_target_july', 'collected_target_august', 'collected_target_september',
@ -500,13 +556,107 @@ class SOS_Sales_Achievement_Report_Brief(models.Model):
_order = 'action_date desc'
ref_id = fields.Many2one('sos_sales_achievement_report', string="Financial Year", ondelete="cascade")
customer_name = fields.Many2one('sos_customers',string="Customer Name", required=True)
action_date = fields.Date(string="QP No")
action_date = fields.Date(string="Date")
currency_id = fields.Many2one(
'res.currency',
string='Currency',
default=lambda self: self.env['res.currency'].search([('name', '=', 'INR')], limit=1).id or False
)
proposal_value = fields.Monetary(currency_field='currency_id',string="Proposal Value(In Lakhs)")
proposal_value = fields.Monetary(currency_field='currency_id',string="PO Received(In Lakhs)")
billed_date = fields.Date(string="Billed Date")
billed_amount = fields.Monetary(currency_field='currency_id',string="Billed Value(In Lakhs)")
def open_line_form(self):
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': 'Edit Line',
'res_model': self._name,
'res_id': self.id,
'view_mode': 'form',
'target': 'new', # Opens as a popup
}
def _get_financial_year(self,current_date):
start_year = current_date.year if current_date.month >= 4 else current_date.year - 1
end_year = start_year + 1
return f"FY {start_year}-{end_year}"
def write(self, vals):
for rec in self:
# Previous values
old_billed_date = rec.billed_date
old_billed_amount = rec.billed_amount
report = rec.ref_id
# New values
new_billed_date = vals.get('billed_date', old_billed_date)
new_billed_amount = vals.get('billed_amount', old_billed_amount)
if isinstance(new_billed_date, str):
new_billed_date = datetime.strptime(new_billed_date, '%Y-%m-%d').date()
# Adjust billed target
if report and old_billed_date and new_billed_date:
old_month_billed = old_billed_date.strftime('%B').lower()
new_month_billed = new_billed_date.strftime('%B').lower()
if old_month_billed != new_month_billed or old_billed_amount != new_billed_amount:
old_field_billed = f"billed_target_{old_month_billed}"
new_field_billed = f"billed_target_{new_month_billed}"
if hasattr(report, old_field_billed):
report.write({
old_field_billed: max((getattr(report, old_field_billed, 0.0) or 0.0) - old_billed_amount, 0.0)
})
if hasattr(report, new_field_billed):
report.write({
new_field_billed: (getattr(report, new_field_billed, 0.0) or 0.0) + new_billed_amount
})
# Optionally create billing collection entry (if needed)
if new_billed_amount > 0:
self.env['sos_billing_collection'].create({
'ref_id': report.id,
'customer_name': vals.get('customer_name', rec.customer_name.id),
'sales_person': report.sales_person.id,
'action_status': 'Billed',
'date_of_action': new_billed_date,
'value': new_billed_amount
})
return super(SOS_Sales_Achievement_Report_Brief, self).write(vals)
@api.model
def create(self, vals):
action_date = vals.get('action_date')
billed_date = vals.get('billed_date')
customer_name = vals.get('customer_name')
if isinstance(action_date, str):
action_date = datetime.strptime(action_date, '%Y-%m-%d').date()
if isinstance(billed_date, str):
billed_date = datetime.strptime(billed_date, '%Y-%m-%d').date()
month_name = action_date.strftime('%B').lower()
value = vals.get('proposal_value', 0.0)
actual_field = f"actual_target_{month_name}"
ref_id = vals.get('ref_id')
if ref_id:
report = self.env['sos_sales_achievement_report'].browse(ref_id)
sales_person = report.sales_person
if sales_person and hasattr(report, actual_field):
current_value = getattr(report, actual_field, 0.0) or 0.0
report.write({actual_field: current_value + value})
# Instead of also summing billed_value here, just create billing line
if billed_date:
self.env['sos_billing_collection'].create({
'ref_id': report.id,
'customer_name': customer_name,
'sales_person': report.sales_person.id,
'action_status': 'Billed',
'date_of_action': billed_date,
'value': vals.get('billed_amount', 0.0)
})
return super(SOS_Sales_Achievement_Report_Brief, self).create(vals)
class SOS_Sales_Achievement_Report_Brief_Wizard(models.TransientModel):
_name = 'sos_sales_achievement_report_brief_wizard'
@ -520,13 +670,144 @@ class SOS_Sales_Achievement_Report_Brief_Wizard(models.TransientModel):
string="Brief Lines",
readonly=True
)
def action_add_new_brief_line(self):
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': 'Add Brief Line',
'res_model': 'sos_sales_achievement_report_brief',
'view_mode': 'form',
'target': 'new',
'context': {
'default_ref_id': self.parent_id.id,
'default_currency_id': self.env.ref('base.INR').id,
}
}
class SosBilledCollectionWizard(models.TransientModel):
_name = 'sos_billed_collection_wizard'
_description = 'Billed Collection Lines Wizard'
parent_id = fields.Many2one('sos_billing_collection') # adjust accordingly
main_parent_id = fields.Many2one('sos_sales_achievement_report', string="Sales Achievement Report")
billed_line_ids = fields.Many2many(
'sos_billing_collection',
string="Billed Lines",
readonly=True,
domain="[('ref_id', '=', main_parent_id)]"
)
action_status = fields.Selection([
('Billed', 'Billed'),
('Collected', 'Collected')
], string='Action Status', readonly=True)
@api.model
def default_get(self, fields_list):
res = super(SosBilledCollectionWizard, self).default_get(fields_list)
main_parent_id = self.env.context.get('active_id')
if main_parent_id and self.env.context.get('active_model') == 'sos_sales_achievement_report':
res['main_parent_id'] = main_parent_id
# Populate billed_line_ids with related sos_billing_collection records
billing_lines = self.env['sos_billing_collection'].search([('ref_id', '=', main_parent_id)])
res['billed_line_ids'] = [(6, 0, billing_lines.ids)]
return res
def action_add_new_collection_line(self):
self.ensure_one()
if not self.main_parent_id:
raise UserError("No Sales Achievement Report found.")
if self.action_status == "Collected":
form_title="Collection"
view_xml_id="view_sos_billing_collection_minimal_form_collection"
else:
form_title="Billed"
view_xml_id="view_sos_billing_collection_minimal_form_billed"
return {
'type': 'ir.actions.act_window',
'name': f'Add {form_title}',
'res_model': 'sos_billing_collection',
'view_mode': 'form',
'view_id': self.env.ref(f'sos_sales.{view_xml_id}').id,
'target': 'new',
'context': {
'default_ref_id': self.main_parent_id.id,
'default_action_status': self.action_status,
'default_sales_person': self.main_parent_id.sales_person.id if self.main_parent_id.sales_person else False,
}
}
class SosBillingCollection(models.Model):
_name = 'sos_billing_collection'
_description = 'Billing & Collection Details'
ref_id = fields.Many2one('sos_sales_achievement_report', ondelete="cascade", required=True)
customer_name = fields.Many2one('sos_customers', string="Customer Name")
sales_person = fields.Many2one(
'res.users',
string='Sales Executive',
related="ref_id.sales_person",
store=True
)
action_status = fields.Selection([
('Billed', 'Billed'),
('Collected', 'Collected')
], string='Action')
date_of_action = fields.Date(string="Date")
currency_id = fields.Many2one(
'res.currency',
string='Currency',
default=lambda self: self.env['res.currency'].search([('name', '=', 'INR')], limit=1).id or False
)
value = fields.Monetary(currency_field='currency_id', string="Value (In Lakhs)")
customer_name = fields.Many2one('sos_customers',string="Customer Name")
po_no = fields.Char(string="PO No")
invoice_no = fields.Char(string="Invoice No")
products = fields.Selection(
[
('BHMS 1.2V', 'BHMS 1.2V'),
('BHMS 2V', 'BHMS 2V'),
('BHMS 12V', 'BHMS 12V'),
('BHMS 48V', 'BHMS 48V'),
('BMS-HV', 'BMS-HV'),
('BMS-LV 100A', 'BMS-LV 100A'),
('BMS-LV 40A', 'BMS-LV 40A'),
('SBMS 55A', 'SBMS 55A'),
('MC 250W', 'MC 250W'),
('HeartTarang', 'HeartTarang')
],
string="Products")
quantity = fields.Integer(string="Quantity")
def _get_financial_year(self, current_date):
start_year = current_date.year if current_date.month >= 4 else current_date.year - 1
end_year = start_year + 1
return f"FY {start_year}-{end_year}"
@api.model
def create(self, vals):
if not vals.get('ref_id'):
raise UserError("Cannot create record without a valid Sales Achievement Report.")
action_date = vals.get('date_of_action')
action_status = vals.get('action_status').lower()
if isinstance(action_date, str):
action_date = datetime.strptime(action_date, '%Y-%m-%d').date()
fy = self._get_financial_year(action_date) if action_date else False
month_name = action_date.strftime('%B').lower() if action_date else False
final_value = vals.get('value', 0.0)
actual_field = f"{action_status}_target_{month_name}" if month_name else False
record = super(SosBillingCollection, self).create(vals)
# Update the related sos_sales_achievement_report by adding value
if vals.get('ref_id') and month_name:
report = self.env['sos_sales_achievement_report'].search([
('id', '=', vals.get('ref_id')),
('financial_year', '=', fy),
])
if report and hasattr(report, actual_field):
current_value = getattr(report, actual_field, 0.0) or 0.0
new_value = current_value + final_value
report.write({actual_field: new_value})
return record

View File

@ -24,6 +24,14 @@ class sos_sales_action_plan(models.Model):
string="End Customer/Quote No",
domain="[('customer_name', '=', customer_name), ('quote_no', '!=', False)]"
)
ce_product_type = fields.Selection(
[
('Sales', 'Sales'),
('Service', 'Service'),
('Spare', 'Spare'),
('Cloud', 'Cloud')
],
string="Service Type")
product = fields.Selection(
[
('BHMS 1.2V', 'BHMS 1.2V'),
@ -80,7 +88,7 @@ class sos_sales_action_plan(models.Model):
('Engaged to Negotiation', 'Engaged to Negotiation'),
('Negotiation to Order', 'Negotiation to Order')
],
string="Action Category",requierd=True)
string="Action Category",required=True)
action_plan = fields.Text(string="Action Plan")
result = fields.Text(string="Result")
status = fields.Selection(
@ -101,9 +109,15 @@ class sos_sales_action_plan(models.Model):
], string='State', default='draft', readonly=True)
def _get_customer_domain(self):
if self.env.user.has_group('sos_inventory.sos_management_user'):
if (
self.env.user.has_group('sos_inventory.sos_management_user') or
self.env.user.has_group('sos_inventory.sos_ce_head') or
self.env.user.has_group('sos_inventory.sos_ce_user')
):
return [] # no filter, show all
return [('responsible', '=', self.env.uid)]
@api.onchange('quote_no_selector')
def _onchange_quote_no_selector(self):
if self.quote_no_selector:
@ -436,21 +450,23 @@ class sos_sales_action_plan(models.Model):
}
}
else:
casediary_record = self.env['sos_case_diary'].create({
vals = {
'customer_name': self.customer_name.id,
'end_customer_name':self.end_customer_name,
'end_customer_name': self.end_customer_name,
'customer_city': self.location,
'sales_person': self.sales_executive.id,
'products': self.product,
'proposal_value': self.value,
'status': self.status,
'quote_no':self.quote_no,
'quantity':self.quantity,
'po_no':self.po_no,
'po_copy':self.po_copy,
'po_copy_filename':self.po_copy_filename
})
'quote_no': self.quote_no,
'quantity': self.quantity,
'po_no': self.po_no,
'po_copy': self.po_copy,
'po_copy_filename': self.po_copy_filename
}
if self.ce_product_type:
vals['ce_product_type'] = self.ce_product_type
casediary_record = self.env['sos_case_diary'].create(vals)
self.env['sos_case_diary_line'].create({
'ref_id': casediary_record.id,
'action_plan_date': self.date,

View File

@ -35,24 +35,24 @@
</t>
<div style="page-break-after: always;"></div>
<h3 style="text-align: center;text-transform: uppercase;text-shadow: 1px 1p 1px #140718;color: #65407c;padding:5px;"><t t-esc="o.proposal_heading"/></h3><br></br>
<h3>1. INTRODUCTION</h3>
<h4>ABOUT SOSALEY</h4>
<h4 style="text-align: center;text-transform: uppercase;text-shadow: 1px 1p 1px #140718;color: #65407c;padding:5px;"><t t-esc="o.proposal_heading"/></h4><br></br>
<h4>1. INTRODUCTION</h4>
<h5>ABOUT SOSALEY</h5>
<p><t t-esc="o.about_sosaley"/></p>
<h3>2. PROPOSAL OBJECTIVE</h3>
<h4>2. PROPOSAL OBJECTIVE</h4>
<t t-esc="o.proposal_objective"/>
<h3>3. PROPOSAL OVERVIEW</h3>
<h4>3. PROPOSAL OVERVIEW</h4>
<t t-esc="o.proposal_overview"/>
<h3>4. ARCHITECTURE</h3>
<h4>4. ARCHITECTURE</h4>
<t t-foreach="o.technical_diagrams" t-as="line_items" t-index="index">
<p style="text-transform:uppercase;text-decoration:underline;font-weight:bold"><t t-esc="line_items.image_name"/></p>
<img style="height:400px;width:600px" t-if="line_items.image" t-att-src="'data:image/png;base64,%s' % (line_items.image.decode())"/>
<br></br>
</t>
<h4>PARAMETERS MONITORED</h4>
<h5>PARAMETERS MONITORED</h5>
<t t-esc="o.parameters_monitored"/>
<br></br>
<h3>5. QUOTATION</h3>
<h4>5. QUOTATION</h4>
<table class="table_custom">
<tr style="background-color:#ddd"><td colspan="2">Customer Details</td></tr>
<tr><td>Billing Address</td><td><t t-esc="o.billing_address"/></td></tr>
@ -74,9 +74,9 @@
</tr>
</table>
<h3>6. PAYMENT TERMS</h3>
<h4>6. PAYMENT TERMS</h4>
<t t-esc="o.payment_terms"/>
<h3>7. TERMS AND CONDITIONS</h3>
<h4>7. TERMS AND CONDITIONS</h4>
<t t-esc="o.terms_and_conditions"/>
</div>

View File

@ -51,9 +51,15 @@ access_sos_proposal_line_spare_ups7,sos_proposal_line_spare_ups7 access,model_so
access_sos_proposal_line_spare_ups8,sos_proposal_line_spare_ups8 access,model_sos_proposal_line_spare_ups8,base.group_user,1,1,1,1
access_sos_proposal_line_spare_ups9,sos_proposal_line_spare_ups9 access,model_sos_proposal_line_spare_ups9,base.group_user,1,1,1,1
access_sos_proposal_line_spare_ups10,sos_proposal_line_spare_ups10 access,model_sos_proposal_line_spare_ups10,base.group_user,1,1,1,1
access_sos_proposal_line_spare_ups11,sos_proposal_line_spare_ups11 access,model_sos_proposal_line_spare_ups11,base.group_user,1,1,1,1
access_sos_proposal_line_spare_ups12,sos_proposal_line_spare_ups12 access,model_sos_proposal_line_spare_ups12,base.group_user,1,1,1,1
access_sos_proposal_line_spare_ups13,sos_proposal_line_spare_ups13 access,model_sos_proposal_line_spare_ups13,base.group_user,1,1,1,1
access_sos_proposal_line_spare_ups14,sos_proposal_line_spare_ups14 access,model_sos_proposal_line_spare_ups14,base.group_user,1,1,1,1
access_sos_proposal_line_spare_ups15,sos_proposal_line_spare_ups15 access,model_sos_proposal_line_spare_ups15,base.group_user,1,1,1,1
access_sos_sales_achievement_report_brief,sos_sales_achievement_report_brief access,model_sos_sales_achievement_report_brief,base.group_user,1,1,1,1
access_sos_sales_achievement_report_brief_wizard,sos_sales_achievement_report_brief_wizard access,model_sos_sales_achievement_report_brief_wizard,base.group_user,1,1,1,1
access_sos_billing_collection,sos_billing_collection access,model_sos_billing_collection,base.group_user,1,1,1,1
access_sos_billed_collection_wizard,sos_billed_collection_wizard access,model_sos_billed_collection_wizard,base.group_user,1,1,1,1
access_sos_business_performance_wizard,sos_business_performance_wizard access,model_sos_business_performance_wizard,base.group_user,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
51 access_sos_proposal_line_spare_ups8 sos_proposal_line_spare_ups8 access model_sos_proposal_line_spare_ups8 base.group_user 1 1 1 1
52 access_sos_proposal_line_spare_ups9 sos_proposal_line_spare_ups9 access model_sos_proposal_line_spare_ups9 base.group_user 1 1 1 1
53 access_sos_proposal_line_spare_ups10 sos_proposal_line_spare_ups10 access model_sos_proposal_line_spare_ups10 base.group_user 1 1 1 1
54 access_sos_proposal_line_spare_ups11 sos_proposal_line_spare_ups11 access model_sos_proposal_line_spare_ups11 base.group_user 1 1 1 1
55 access_sos_proposal_line_spare_ups12 sos_proposal_line_spare_ups12 access model_sos_proposal_line_spare_ups12 base.group_user 1 1 1 1
56 access_sos_proposal_line_spare_ups13 sos_proposal_line_spare_ups13 access model_sos_proposal_line_spare_ups13 base.group_user 1 1 1 1
57 access_sos_proposal_line_spare_ups14 sos_proposal_line_spare_ups14 access model_sos_proposal_line_spare_ups14 base.group_user 1 1 1 1
58 access_sos_proposal_line_spare_ups15 sos_proposal_line_spare_ups15 access model_sos_proposal_line_spare_ups15 base.group_user 1 1 1 1
59 access_sos_sales_achievement_report_brief sos_sales_achievement_report_brief access model_sos_sales_achievement_report_brief base.group_user 1 1 1 1
60 access_sos_sales_achievement_report_brief_wizard sos_sales_achievement_report_brief_wizard access model_sos_sales_achievement_report_brief_wizard base.group_user 1 1 1 1
61 access_sos_billing_collection sos_billing_collection access model_sos_billing_collection base.group_user 1 1 1 1
62 access_sos_billed_collection_wizard sos_billed_collection_wizard access model_sos_billed_collection_wizard base.group_user 1 1 1 1
63 access_sos_business_performance_wizard sos_business_performance_wizard access model_sos_business_performance_wizard base.group_user 1 1 1 1
64
65

View File

@ -68,6 +68,17 @@
<field name="perm_create" eval="1"/>
<field name="perm_unlink" eval="0"/>
</record>
<record id="sos_sales_action_plan_ce_head_read_ce_user_rule" model="ir.rule">
<field name="name">Sales Action Plan: CE Head Reads CE User Records</field>
<field name="model_id" ref="model_sos_sales_action_plan"/>
<field name="domain_force" eval="[('create_uid.groups_id', 'in', [ref('sos_inventory.sos_ce_user')])]"/>
<field name="groups" eval="[(4, ref('sos_inventory.sos_ce_head'))]"/>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="0"/>
<field name="perm_create" eval="0"/>
<field name="perm_unlink" eval="0"/>
</record>
<record id="sos_sales_action_plan_all_records_rule" model="ir.rule">
<field name="name">Sos sales action plan: All Records - Read Access</field>
<field name="model_id" ref="model_sos_sales_action_plan"/>
@ -89,7 +100,8 @@
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[
(4, ref('sos_inventory.sos_management_user')),
(4, ref('sos_inventory.sos_finance_user'))
(4, ref('sos_inventory.sos_finance_user')),
(4, ref('sos_inventory.sos_ce_head'))
]"/>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
@ -127,7 +139,16 @@
<field name="perm_create" eval="1"/>
<field name="perm_unlink" eval="0"/>
</record>
<record id="sos_case_diary_ce_head_read_ce_user_rule" model="ir.rule">
<field name="name">Case Diary: CE Head Reads CE User Records</field>
<field name="model_id" ref="model_sos_case_diary"/>
<field name="domain_force" eval="[('create_uid.groups_id', 'in', [ref('sos_inventory.sos_ce_user')])]"/>
<field name="groups" eval="[(4, ref('sos_inventory.sos_ce_head'))]"/>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="0"/>
<field name="perm_create" eval="0"/>
<field name="perm_unlink" eval="0"/>
</record>
<record id="sos_case_diary_all_records_rule" model="ir.rule">
<field name="name">Sos Case Diary: All Records - Read Access</field>
<field name="model_id" ref="model_sos_case_diary"/>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<menuitem id="sos_sales_menu_root" name="Sales" groups="sos_inventory.sos_sales_user,sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_ce_user"/>
<menuitem id="sos_sales_report" name="REPORTS" parent="sos_sales_menu_root"/>
<menuitem id="sos_sales_report" name="REPORTS" parent="sos_sales_menu_root" groups="sos_inventory.sos_finance_user,sos_inventory.sos_sales_user,sos_inventory.sos_management_user,sos_inventory.sos_ce_head"/>
<menuitem id="sos_top_sales_report" name="MANAGEMENT REPORTS" parent="sos_sales_menu_root" groups="sos_inventory.sos_management_user"/>
<menuitem id="sos_proposal_system" name="PROPOSAL SYSTEM" parent="sos_sales_menu_root" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_sales_user,sos_inventory.sos_ce_head,sos_inventory.sos_ce_user,sos_inventory.sos_inside_sales_user"/>
</odoo>

View File

@ -164,36 +164,7 @@
</field>
</page>
<page string="Billing &amp; Collection" groups="sos_inventory.sos_finance_user,sos_inventory.sos_management_user">
<div class="row">
<div class="col-md-5">
<h3 style="text-transform: uppercase;
text-decoration: underline;">Billed</h3>
<br></br>
<field name="line_ids_billed" context="{'default_action_status': 'Billed'}">
<tree editable="bottom">
<field name="action_status" column_invisible="1"/>
<field name="date_of_action"/>
<field name="value"/>
</tree>
</field>
</div>
<div class="col-md-2"></div>
<div class="col-md-5">
<h3 style="text-transform: uppercase;
text-decoration: underline;">Collected</h3>
<br></br>
<field name="line_ids_collected" context="{'default_action_status': 'Collected'}">
<tree editable="bottom">
<field name="action_status" column_invisible="1"/>
<field name="date_of_action"/>
<field name="value"/>
</tree>
</field>
</div>
</div>
</page>
</notebook>
</sheet>
</form>
@ -310,7 +281,7 @@
<!-- Menu -->
<menuitem id="menu_sos_case_diary" name="CASE DIARY" parent="sos_sales_menu_root" action="action_sos_case_diary" sequence="6"/>
<menuitem id="menu_sos_case_diary" name="CASE DIARY" parent="sos_sales_menu_root" action="action_sos_case_diary" sequence="6" groups="sos_inventory.sos_finance_user,sos_inventory.sos_sales_user,sos_inventory.sos_management_user,sos_inventory.sos_ce_head,sos_inventory.sos_ce_user"/>
<menuitem id="menu_sos_spenco_report"
name=" SPENCO Report"
parent="sos_sales_report"

View File

@ -89,5 +89,5 @@
</field>
</record>
<!-- Menu -->
<menuitem id="menu_sos_customers" name="CUSTOMERS" parent="sos_sales_menu_root" action="action_sos_customers" sequence="2"/>
<menuitem id="menu_sos_customers" name="CUSTOMERS" parent="sos_sales_menu_root" action="action_sos_customers" sequence="2" groups="sos_inventory.sos_finance_user,sos_inventory.sos_sales_user,sos_inventory.sos_management_user,sos_inventory.sos_ce_head,sos_inventory.sos_ce_user"/>
</odoo>

View File

@ -1117,6 +1117,541 @@
<label for="ups10_total" style="font-weight: bold; margin-right: 10px;">Total Cost of UPS10</label>
<field name="ups10_total" class="oe_inline"/>
</div>
</div>
</page>
<page string="UPS 11" invisible="number_of_ups &lt; 11">
<h3 style="text-transform: uppercase;
text-decoration: underline;">Finished Goods</h3>
<field name="line_ids_fg_ups11">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Semi-Finished Goods</h3>
<field name="line_ids_sfg_ups11">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Materials</h3>
<field name="line_ids_material_ups11">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Installation Kit</h3>
<field name="line_ids_installation_kit_ups11">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Spare/Additional Materials</h3>
<field name="line_ids_spare_ups11" context="{'default_ups_index': 11}">
<tree editable="bottom">
<field name="ups_index" column_invisible="1"/>
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Miscellaneous</h3>
<field name="line_ids_miscellaneous_ups11">
<tree editable="bottom">
<field name="name"/>
<field name="cost"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<div groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user" class="oe_subtotal_footer" style="float: right;
padding: 20px;
border: solid 1px #ccc;
font-weight: bold;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;">
<div style="margin-bottom: 5px;">
<label for="ups11_total" style="font-weight: bold; margin-right: 10px;">Total Cost of UPS11</label>
<field name="ups11_total" class="oe_inline"/>
</div>
</div>
</page>
<page string="UPS 12" invisible="number_of_ups &lt; 12">
<h3 style="text-transform: uppercase;
text-decoration: underline;">Finished Goods</h3>
<field name="line_ids_fg_ups12">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Semi-Finished Goods</h3>
<field name="line_ids_sfg_ups12">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Materials</h3>
<field name="line_ids_material_ups12">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Installation Kit</h3>
<field name="line_ids_installation_kit_ups12">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Spare/Additional Materials</h3>
<field name="line_ids_spare_ups12" context="{'default_ups_index': 12}">
<tree editable="bottom">
<field name="ups_index" column_invisible="1"/>
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Miscellaneous</h3>
<field name="line_ids_miscellaneous_ups12">
<tree editable="bottom">
<field name="name"/>
<field name="cost"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<div groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user" class="oe_subtotal_footer" style="float: right;
padding: 20px;
border: solid 1px #ccc;
font-weight: bold;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;">
<div style="margin-bottom: 5px;">
<label for="ups12_total" style="font-weight: bold; margin-right: 10px;">Total Cost of UPS12</label>
<field name="ups12_total" class="oe_inline"/>
</div>
</div>
</page>
<page string="UPS 13" invisible="number_of_ups &lt; 13">
<h3 style="text-transform: uppercase;
text-decoration: underline;">Finished Goods</h3>
<field name="line_ids_fg_ups13">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Semi-Finished Goods</h3>
<field name="line_ids_sfg_ups13">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Materials</h3>
<field name="line_ids_material_ups13">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Installation Kit</h3>
<field name="line_ids_installation_kit_ups13">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Spare/Additional Materials</h3>
<field name="line_ids_spare_ups13" context="{'default_ups_index': 13}">
<tree editable="bottom">
<field name="ups_index" column_invisible="1"/>
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Miscellaneous</h3>
<field name="line_ids_miscellaneous_ups13">
<tree editable="bottom">
<field name="name"/>
<field name="cost"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<div groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user" class="oe_subtotal_footer" style="float: right;
padding: 20px;
border: solid 1px #ccc;
font-weight: bold;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;">
<div style="margin-bottom: 5px;">
<label for="ups13_total" style="font-weight: bold; margin-right: 10px;">Total Cost of UPS13</label>
<field name="ups13_total" class="oe_inline"/>
</div>
</div>
</page>
<page string="UPS 14" invisible="number_of_ups &lt; 14">
<h3 style="text-transform: uppercase;
text-decoration: underline;">Finished Goods</h3>
<field name="line_ids_fg_ups14">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Semi-Finished Goods</h3>
<field name="line_ids_sfg_ups14">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Materials</h3>
<field name="line_ids_material_ups14">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Installation Kit</h3>
<field name="line_ids_installation_kit_ups14">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Spare/Additional Materials</h3>
<field name="line_ids_spare_ups14" context="{'default_ups_index': 14}">
<tree editable="bottom">
<field name="ups_index" column_invisible="1"/>
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Miscellaneous</h3>
<field name="line_ids_miscellaneous_ups14">
<tree editable="bottom">
<field name="name"/>
<field name="cost"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<div groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user" class="oe_subtotal_footer" style="float: right;
padding: 20px;
border: solid 1px #ccc;
font-weight: bold;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;">
<div style="margin-bottom: 5px;">
<label for="ups14_total" style="font-weight: bold; margin-right: 10px;">Total Cost of UPS14</label>
<field name="ups14_total" class="oe_inline"/>
</div>
</div>
</page>
<page string="UPS 15" invisible="number_of_ups &lt; 15">
<h3 style="text-transform: uppercase;
text-decoration: underline;">Finished Goods</h3>
<field name="line_ids_fg_ups15">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Semi-Finished Goods</h3>
<field name="line_ids_sfg_ups15">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Materials</h3>
<field name="line_ids_material_ups15">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Installation Kit</h3>
<field name="line_ids_installation_kit_ups15">
<tree editable="bottom">
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="item_type"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Spare/Additional Materials</h3>
<field name="line_ids_spare_ups15" context="{'default_ups_index': 15}">
<tree editable="bottom">
<field name="ups_index" column_invisible="1"/>
<field name="production_cost" widget="boolean_toggle"/>
<field name="component_id"/>
<field name="description"/>
<field name="uom"/>
<field name="unit_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
<field name="singet_set_qty"/>
<field name="total_set"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<h3 style="text-transform: uppercase;
text-decoration: underline;">Miscellaneous</h3>
<field name="line_ids_miscellaneous_ups15">
<tree editable="bottom">
<field name="name"/>
<field name="cost"/>
<field name="quantity"/>
<field name="total_price" groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user"/>
</tree>
</field>
<div groups="sos_inventory.sos_management_user,sos_inventory.sos_finance_user,sos_inventory.sos_scg_group_user" class="oe_subtotal_footer" style="float: right;
padding: 20px;
border: solid 1px #ccc;
font-weight: bold;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;">
<div style="margin-bottom: 5px;">
<label for="ups15_total" style="font-weight: bold; margin-right: 10px;">Total Cost of UPS15</label>
<field name="ups15_total" class="oe_inline"/>
</div>
</div>
</page>
<!-- <page string="Finished Goods">
@ -1248,6 +1783,12 @@
<tr invisible="number_of_ups &lt; 8"><td class="column">UPS 8</td><td><field name="ups8_total"/></td></tr>
<tr invisible="number_of_ups &lt; 9"><td class="column">UPS 9</td><td><field name="ups9_total"/></td></tr>
<tr invisible="number_of_ups &lt; 10"><td class="column">UPS 10</td><td><field name="ups10_total"/></td></tr>
<tr invisible="number_of_ups &lt; 11"><td class="column">UPS 11</td><td><field name="ups11_total"/></td></tr>
<tr invisible="number_of_ups &lt; 12"><td class="column">UPS 12</td><td><field name="ups12_total"/></td></tr>
<tr invisible="number_of_ups &lt; 13"><td class="column">UPS 13</td><td><field name="ups13_total"/></td></tr>
<tr invisible="number_of_ups &lt; 14"><td class="column">UPS 14</td><td><field name="ups14_total"/></td></tr>
<tr invisible="number_of_ups &lt; 15"><td class="column">UPS 15</td><td><field name="ups15_total"/></td></tr>
<tr style="background-color: aliceblue;"><td class="column">Total</td><td><field style="font-weight: bold;font-size: 18px;" name="total_cost"/></td></tr>

View File

@ -17,7 +17,7 @@ name="action_report_achievement_btn"><i class="fa fa-print"></i> Print Report</b
<field name="sales_person" />
<field name="overall_target" />
<field name="opening_balance" groups="sos_inventory.sos_finance_user"/>
<field name="opening_balance" groups="sos_inventory.sos_finance_user,sos_inventory.sos_management_user"/>
</group>
<br></br>
@ -60,7 +60,7 @@ name="action_report_achievement_btn"><i class="fa fa-print"></i> Print Report</b
<td><field name="ytd_target" /></td>
</tr>
<tr>
<td class="column" style="background-color: lavender;">Sales</td>
<td class="column" style="background-color: lavender;">PO Received</td>
<td>
<div style="display: flex; align-items: center;">
<field name="actual_target_april" readonly="1" widget="monetary"/>

View File

@ -73,6 +73,8 @@
</group>
<group>
<field name="product" readonly="state == 'confirmed'"/>
<field name="ce_product_type" groups="sos_inventory.sos_ce_user,sos_inventory.sos_ce_head,sos_inventory.sos_finance_user,sos_inventory.sos_management_user"/>
<field name="location" readonly="state == 'confirmed'"/>
<field name="quantity" readonly="state == 'confirmed'"/>
<field name="sales_head" readonly="state == 'confirmed'"/>
@ -128,5 +130,5 @@
</record>
<!-- Menu -->
<menuitem id="menu_sos_sales_action_plan" name="ACTION PLAN" sequence="6" parent="sos_sales_menu_root" action="action_sos_sales_action_plan"/>
<menuitem id="menu_sos_sales_action_plan" name="ACTION PLAN" sequence="6" parent="sos_sales_menu_root" action="action_sos_sales_action_plan" groups="sos_inventory.sos_finance_user,sos_inventory.sos_sales_user,sos_inventory.sos_management_user,sos_inventory.sos_ce_head,sos_inventory.sos_ce_user"/>
</odoo>

View File

@ -99,5 +99,5 @@
</record>
<!-- Menu -->
<menuitem id="menu_sos_sales_leads" name="LEADS" parent="sos_sales_menu_root" action="action_sos_sales_leads" sequence="1"/>
<menuitem id="menu_sos_sales_leads" name="LEADS" parent="sos_sales_menu_root" action="action_sos_sales_leads" sequence="1" groups="sos_inventory.sos_finance_user,sos_inventory.sos_sales_user,sos_inventory.sos_management_user,sos_inventory.sos_ce_head"/>
</odoo>

View File

@ -257,5 +257,5 @@ name="action_report_sales_plan_btn"><i class="fa fa-print"></i> Print Report</bu
</record>
<!-- Menu -->
<menuitem id="menu_sos_sales_plan_target" name="SALES TARGET" sequence="7" parent="sos_sales_menu_root" action="action_sos_sales_plan_target"/>
<menuitem id="menu_sos_sales_plan_target" name="SALES TARGET" sequence="7" parent="sos_sales_menu_root" action="action_sos_sales_plan_target" groups="sos_inventory.sos_finance_user,sos_inventory.sos_sales_user,sos_inventory.sos_management_user,sos_inventory.sos_ce_head"/>
</odoo>

View File

@ -39,5 +39,5 @@
</record>
<!-- Menu -->
<menuitem id="menu_sos_vertical_domain" name="CONFIGURATION" parent="sos_sales_menu_root" action="action_sos_vertical_domain" sequence="4"/>
<menuitem id="menu_sos_vertical_domain" name="CONFIGURATION" parent="sos_sales_menu_root" action="action_sos_vertical_domain" sequence="4" groups="sos_inventory.sos_finance_user,sos_inventory.sos_sales_user,sos_inventory.sos_management_user,sos_inventory.sos_ce_head"/>
</odoo>

View File

@ -1,19 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_sos_sales_achievement_brief_wizard_form" model="ir.ui.view">
<field name="name">sos_sales_achievement_report_brief_wizard.form</field>
<field name="model">sos_sales_achievement_report_brief_wizard</field>
<field name="arch" type="xml">
<form string="Achievement Brief Lines">
<sheet>
<header> <button name="action_add_new_brief_line"
type="object"
string="Add New Line"
class="btn-primary"/></header>
<group>
<field name="parent_id" readonly="1"/>
</group>
<field name="brief_line_ids" nolabel="1">
<tree>
<field name="customer_name"/>
<field name="action_date" string="Date"/>
<field name="customer_name"/>
<field name="proposal_value"/>
<field name="billed_date"/>
<field name="billed_amount"/>
<button name="open_line_form" string="Edit"
type="object" icon="fa-pencil" invisible="billed_date != False and billed_amount != False"/>
</tree>
</field>
<footer>
@ -30,23 +43,109 @@
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<record id="view_sos_billed_collection_wizard_form" model="ir.ui.view">
<field name="name">sos.billed.collection.wizard.form</field>
<record id="action_sos_billed_collection_wizard" model="ir.actions.act_window">
<field name="name">Add Collection Line</field>
<field name="res_model">sos_billed_collection_wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<record id="view_sos_billing_collection_minimal_form_billed" model="ir.ui.view">
<field name="name">sos.billing.collection.minimal.billed.form</field>
<field name="model">sos_billing_collection</field>
<field name="arch" type="xml">
<form string="Add Billed Line">
<sheet>
<group>
<field name="ref_id" invisible="1"/>
<field name="action_status" invisible="1"/>
<field name="date_of_action"/>
<field name="customer_name"/>
<field name="value"/>
<field name="products"/>
<field name="po_no"/>
<field name="quantity"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_sos_billing_collection_minimal_form_collection" model="ir.ui.view">
<field name="name">sos.billing.collection.minimal.collection.form</field>
<field name="model">sos_billing_collection</field>
<field name="arch" type="xml">
<form string="Add Collection Line">
<sheet>
<group>
<field name="ref_id" invisible="1"/>
<field name="action_status" invisible="1"/>
<field name="date_of_action"/>
<field name="customer_name"/>
<field name="value"/>
<field name="invoice_no"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_sos_billed_collection_wizard_form_billed" model="ir.ui.view">
<field name="name">sos.billed.collection.wizard.form.billed</field>
<field name="model">sos_billed_collection_wizard</field>
<field name="arch" type="xml">
<form>
<sheet>
<header>
<button name="action_add_new_collection_line"
type="object"
string="Add New Billed Line"
class="btn-primary"/>
</header>
<field name="main_parent_id" invisible="1"/>
<field name="billed_line_ids">
<tree>
<field name="date_of_action"/>
<field name="value"/>
<field name="customer_name"/>
<field name="value"/>
<field name="products"/>
<field name="po_no"/>
<field name="quantity"/>
</tree>
</field>
<footer>
<button string="Close" special="cancel" class="btn-secondary"/>
</footer>
</sheet>
</form>
</field>
</record>
<record id="view_sos_billed_collection_wizard_form_collected" model="ir.ui.view">
<field name="name">sos.billed.collection.wizard.form.collected</field>
<field name="model">sos_billed_collection_wizard</field>
<field name="arch" type="xml">
<form>
<sheet>
<header>
<button name="action_add_new_collection_line"
type="object"
string="Add New Collected Line"
class="btn-primary"/>
</header>
<field name="main_parent_id" invisible="1"/>
<field name="billed_line_ids">
<tree>
<field name="date_of_action"/>
<field name="customer_name"/>
<field name="value"/>
<field name="invoice_no"/>
</tree>
</field>
<footer>
<button string="Close" special="cancel" class="btn-secondary"/>
</footer>
</sheet>
</form>
</field>
</record>
</odoo>