parent
de6c275785
commit
e608da1fc9
|
|
@ -11,7 +11,7 @@
|
|||
id="main_menu_dms"
|
||||
name="Documents"
|
||||
web_icon="dms,static/description/icon.png"
|
||||
groups="group_dms_user"
|
||||
groups="group_dms_user,sos_inventory.sos_marketing_user"
|
||||
>
|
||||
<menuitem id="menu_dms_file" name="Files" sequence="20" action="action_dms_file" />
|
||||
<menuitem
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@
|
|||
'security/security.xml',
|
||||
'security/record_rules.xml',
|
||||
'security/ir.model.access.csv',
|
||||
# 'data/cron_jobs.xml',
|
||||
|
||||
'data/cron_jobs.xml',
|
||||
'views/sos_audit_log_view.xml',
|
||||
'views/menu.xml',
|
||||
'views/sos_quote_generation.xml',
|
||||
|
|
@ -81,6 +80,7 @@
|
|||
'views/sos_master_customer_property.xml',
|
||||
'views/sos_service_call_log_report.xml',
|
||||
'views/sos_transfer_challan_return_from_customer_view.xml',
|
||||
'views/sos_shelflife_register_view.xml',
|
||||
'wizard/sfg_bom_bulk_upload_view.xml',
|
||||
'wizard/mon_bulk_upload_view.xml',
|
||||
'wizard/missing_component_wizard.xml',
|
||||
|
|
@ -93,7 +93,6 @@
|
|||
'wizard/stock_movement_report_wizard.xml',
|
||||
'wizard/dock_audit_report.xml',
|
||||
'wizard/material_backup_export.xml',
|
||||
|
||||
'report/view_quote.xml',
|
||||
'report/sos_po_report.xml',
|
||||
'report/sos_iqi_report.xml',
|
||||
|
|
@ -114,6 +113,7 @@
|
|||
'report/sos_dock_audit_report.xml',
|
||||
'report/mme_history_card_report.xml',
|
||||
'report/sos_boq_labels.xml',
|
||||
'report/shelflife_report.xml',
|
||||
'data/send_indent_plan_email_template.xml',
|
||||
'data/selection_item.xml'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<record id="cron_test_material_backup" model="ir.cron">
|
||||
<field name="name">[TEST] Material Table Backup Every Minute</field>
|
||||
<field name="active" eval="True"/>
|
||||
<field name="priority">10</field>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">minutes</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field name="nextcall">2026-03-31 23:59:00</field>
|
||||
<field name="model_id" ref="model_sos_material"/>
|
||||
<record id="action_weekly_shelflife_report" model="ir.cron">
|
||||
<field name="name">Weekly Shelf Life Expiry Report</field>
|
||||
<field name="model_id" ref="model_sos_shelflife_register"/>
|
||||
<field name="state">code</field>
|
||||
<field name="code">model.cron_create_table_backup()</field>
|
||||
<field name="code">model.action_generate_expiry_report()</field>
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">weeks</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field name="nextcall">2025-08-11 08:00:00</field>
|
||||
<field name="doall">True</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -58,3 +58,4 @@ 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
|
||||
from . import sos_shelflife_register
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -42,7 +42,7 @@ class SOS_IR(models.Model):
|
|||
('SFG', 'SFG'),
|
||||
('FG', 'FG')
|
||||
], string='Goods Type',default="Materials",copy=True)
|
||||
line_ids_material = fields.One2many('sos_ir_line_material', 'ir_id', string="Components for Materials",copy=True)
|
||||
line_ids_material = fields.One2many('sos_ir_line_material', 'ir_id', string="Materials Lines",copy=True)
|
||||
vehicle_type = fields.Selection([
|
||||
('yes', 'Yes'),
|
||||
('no', 'No'),
|
||||
|
|
@ -217,7 +217,14 @@ class SOS_IR(models.Model):
|
|||
for item in self.line_ids_material:
|
||||
# Fetch the component related to the current item
|
||||
component = self.env['sos_material'].browse(item.component_id.id)
|
||||
#print(component)
|
||||
if component.shelf_life == "yes":
|
||||
shelflife_line_values = {
|
||||
'ir_ref_no':self.id,
|
||||
'name': item.component_id.id, # Reference the created GRN
|
||||
'quantity': item.qty,
|
||||
'expiry_date':item.expiry_date
|
||||
}
|
||||
shellife_record = self.env['sos_shelflife_register'].create(shelflife_line_values)
|
||||
#raise UserError("The PO Number already exists. Validation failed.")
|
||||
if self.po_no:
|
||||
for pos in self.po_no.line_ids:
|
||||
|
|
@ -410,11 +417,14 @@ class SOS_IR_Line_Material(models.Model):
|
|||
test_report = fields.Binary(string="Test Report")
|
||||
test_report_filename=fields.Char(string="Test Report File Name")
|
||||
expiry_date = fields.Date(string="Expiry Date")
|
||||
shelf_life = fields.Selection([('yes', 'Yes'), ('no', 'No')],related="component_id.shelf_life", string="Shelf Life")
|
||||
|
||||
@api.onchange('component_id')
|
||||
def _onchange_component_id(self):
|
||||
if self.component_id:
|
||||
self.unit_price = self.component_id.unit_price
|
||||
|
||||
|
||||
def action_view_pdf(self):
|
||||
"""Action to view the PDF of the test report."""
|
||||
# Check if there is a test report
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, fields, api
|
||||
from datetime import date
|
||||
import base64
|
||||
class SOS_Shelflife_Material_Register(models.Model):
|
||||
_name = 'sos_shelflife_register'
|
||||
_description = 'Shelf Life Register'
|
||||
|
||||
|
||||
name = fields.Many2one('sos_material',string="Material Name", required=True)
|
||||
quantity = fields.Float(string="Quantity")
|
||||
expiry_date = fields.Date(string="Expiry Date")
|
||||
ir_ref_no = fields.Many2one('sos_ir',string="Inward Ref No")
|
||||
remaining_days = fields.Integer(string="Remaining days to expire", compute="_compute_remaining_days", store=True)
|
||||
|
||||
@api.depends('expiry_date')
|
||||
def _compute_remaining_days(self):
|
||||
today = date.today()
|
||||
for record in self:
|
||||
if record.expiry_date:
|
||||
delta = (record.expiry_date - today).days
|
||||
record.remaining_days = max(0, delta) # don't show negative days
|
||||
else:
|
||||
record.remaining_days = 0
|
||||
def action_generate_expiry_report(self):
|
||||
expiring_materials = self.search([
|
||||
('remaining_days', '<', 7),
|
||||
('remaining_days', '>', 0)
|
||||
])
|
||||
if not expiring_materials:
|
||||
return
|
||||
|
||||
# Build HTML table
|
||||
table_rows = ''.join([
|
||||
f"""
|
||||
<tr>
|
||||
<td>{material.name.part_no or ''}</td>
|
||||
<td>{material.expiry_date or ''}</td>
|
||||
<td>{material.remaining_days or ''}</td>
|
||||
</tr>
|
||||
"""
|
||||
for material in expiring_materials
|
||||
])
|
||||
|
||||
html_body = f"""
|
||||
<p>Dear Team,</p>
|
||||
<p>Below is the weekly report of materials expiring within 7 days:</p>
|
||||
<table class="table" border="1" cellpadding="5" cellspacing="0" style="border-collapse: collapse;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Material Name</th>
|
||||
<th>Expiry Date</th>
|
||||
<th>Remaining Days to Expire</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{table_rows}
|
||||
</tbody>
|
||||
</table><br></br>
|
||||
<p>Regards,<br/>Slink Admin</p>
|
||||
"""
|
||||
|
||||
# Get users in the group
|
||||
group = self.env.ref('sos_inventory.sos_scg_group_user')
|
||||
users = self.env['res.users'].search([('groups_id', 'in', group.id)])
|
||||
recipient_emails = ','.join(filter(None, users.mapped('email')))
|
||||
|
||||
# Create and send the email directly
|
||||
mail_template = self.env['mail.template'].create({
|
||||
'name': 'HTML Shelf Life Expiry Report',
|
||||
'model_id': self.env['ir.model']._get(self._name).id,
|
||||
'subject': f'Shelf Life Expiry Report - {date.today().strftime("%Y-%m-%d")}',
|
||||
'email_from': self.env.user.email,
|
||||
'email_to': recipient_emails,
|
||||
'body_html': html_body,
|
||||
})
|
||||
|
||||
mail_template.send_mail(
|
||||
res_id=expiring_materials[0].id, # Just link to one of the records
|
||||
force_send=True
|
||||
)
|
||||
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<template id="report_shelflife_expiry">
|
||||
<t t-call="web.html_container">
|
||||
<t t-call="web.external_layout">
|
||||
<div class="page">
|
||||
<h2>Materials Expiring Within 7 Days</h2>
|
||||
<p>Report generated on: <span t-field="docs[0].write_date" t-options='{"format": "MM/dd/YYYY"}'/></p>
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Material Name</th>
|
||||
<th>Quantity</th>
|
||||
<th>Expiry Date</th>
|
||||
<th>Remaining Days</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="docs" t-as="record">
|
||||
<tr>
|
||||
<td><span t-field="record.name"/></td>
|
||||
<td><span t-field="record.quantity"/></td>
|
||||
<td><span t-field="record.expiry_date"/></td>
|
||||
<td><span t-field="record.remaining_days"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
|
||||
<record id="action_shelflife_expiry_report" model="ir.actions.report">
|
||||
<field name="name">Shelf Life Expiry Report</field>
|
||||
<field name="model">sos_shelflife_register</field>
|
||||
<field name="report_type">qweb-pdf</field>
|
||||
<field name="report_name">sos_inventory.report_shelflife_expiry</field>
|
||||
<field name="report_file">sos_shelflife_expiry_report</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -195,5 +195,6 @@ access_ncmr_report_wizard,ncmr_report_wizard access,model_ncmr_report_wizard,bas
|
|||
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
|
||||
access_sos_shelflife_register,sos_shelflife_register access,model_sos_shelflife_register,base.group_user,1,1,1,1
|
||||
|
||||
|
||||
|
|
|
|||
|
|
|
@ -99,7 +99,8 @@
|
|||
<field name="order_qty"/>
|
||||
<field name="qty"/>
|
||||
<field name="unit_price"/>
|
||||
<field name="expiry_date"/>
|
||||
<field name="shelf_life" column_invisible="1"/>
|
||||
<field name="expiry_date" required="shelf_life == 'yes'"/>
|
||||
<field name="test_report" widget="binary" filename="test_report_filename"/>
|
||||
<field name="test_report_filename" column_invisible="1"/>
|
||||
<button name="action_view_pdf" invisible="not test_report" type="object" string="View" class="btn-primary" icon="fa-eye"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<record id="view_sos_shelflife_register_tree" model="ir.ui.view">
|
||||
<field name="name">sos_shelflife_register.tree</field>
|
||||
<field name="model">sos_shelflife_register</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Register">
|
||||
<field name="name"/>
|
||||
<field name="quantity"/>
|
||||
<field name="expiry_date"/>
|
||||
<field name="ir_ref_no"/>
|
||||
<field name="remaining_days" decoration-danger="remaining_days < 7" decoration-success="remaining_days >= 7"/> <field name="write_uid" string="Last Edited By" optional="hide"/>
|
||||
<field name="write_date" string="Last Edited On" optional="hide"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<record id="view_sos_shelflife_register_form" model="ir.ui.view">
|
||||
<field name="name">sos_shelflife_register.form</field>
|
||||
<field name="model">sos_shelflife_register</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Calibration Device">
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="ir_ref_no" readonly="1"/>
|
||||
<field name="name"/>
|
||||
<field name="quantity"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="expiry_date"/>
|
||||
<field name="remaining_days" decoration-danger="remaining_days < 7" decoration-success="remaining_days >= 7"/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="action_sos_shelflife_register" model="ir.actions.act_window">
|
||||
<field name="name">Shelf Life Register</field>
|
||||
<field name="res_model">sos_shelflife_register</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="view_id" ref="view_sos_shelflife_register_tree"/>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_sos_shelflife_register" name="Material Shelf Life Register"
|
||||
parent="scg_forms_menu_root" action="action_sos_shelflife_register" groups="sos_inventory.sos_qc_user,sos_inventory.sos_qa_user,sos_inventory.sos_management_user,sos_inventory.sos_scg_group_user"/>
|
||||
</odoo>
|
||||
Binary file not shown.
|
|
@ -96,7 +96,7 @@ class SOS_Sales_Achievement_Report(models.Model):
|
|||
achievement_percentage_total = fields.Char(string="Achievement Percentage For Total", compute="_compute_achievement_percentage_total", store=True)
|
||||
billed_target_total = fields.Char(string="Billed For Total", compute="_compute_billed_total_target", store=True)
|
||||
yet_to_billed_target_total = fields.Char(string="Billed For Total", compute="_compute_yet_to_billed_total_target", store=True)
|
||||
collected_target_total = fields.Char(string="collected For Total", compute="_compute_collected_total_target", store=True)
|
||||
collected_target_total = fields.Float(string="collected For Total", compute="_compute_collected_total_target", store=True)
|
||||
can_edit_billed_target = fields.Boolean(
|
||||
string="Can Edit Billed Target",
|
||||
compute="_compute_can_edit_billed_target",
|
||||
|
|
@ -451,7 +451,7 @@ class SOS_Sales_Achievement_Report(models.Model):
|
|||
)
|
||||
def _compute_collected_total_target(self):
|
||||
for record in self:
|
||||
record.collected_target_total = sum([
|
||||
record.collected_target_total = round(sum([
|
||||
record.collected_target_april or 0,
|
||||
record.collected_target_may or 0,
|
||||
record.collected_target_june or 0,
|
||||
|
|
@ -464,7 +464,8 @@ class SOS_Sales_Achievement_Report(models.Model):
|
|||
record.collected_target_january or 0,
|
||||
record.collected_target_february or 0,
|
||||
record.collected_target_march or 0
|
||||
])
|
||||
]), 2)
|
||||
|
||||
@api.depends(
|
||||
'billed_target_april','billed_target_may','billed_target_june',
|
||||
'billed_target_july','billed_target_august','billed_target_september',
|
||||
|
|
@ -473,7 +474,7 @@ class SOS_Sales_Achievement_Report(models.Model):
|
|||
)
|
||||
def _compute_billed_total_target(self):
|
||||
for record in self:
|
||||
record.billed_target_total = sum([
|
||||
record.billed_target_total = round(sum([
|
||||
record.billed_target_april or 0,
|
||||
record.billed_target_may or 0,
|
||||
record.billed_target_june or 0,
|
||||
|
|
@ -486,7 +487,7 @@ class SOS_Sales_Achievement_Report(models.Model):
|
|||
record.billed_target_january or 0,
|
||||
record.billed_target_february or 0,
|
||||
record.billed_target_march or 0
|
||||
])
|
||||
]), 2)
|
||||
@api.depends('actual_target_total', 'planned_target_total')
|
||||
def _compute_achievement_percentage_total(self):
|
||||
for record in self:
|
||||
|
|
@ -503,7 +504,7 @@ class SOS_Sales_Achievement_Report(models.Model):
|
|||
)
|
||||
def _compute_yet_to_billed_total_target(self):
|
||||
for record in self:
|
||||
record.yet_to_billed_target_total = sum([
|
||||
record.yet_to_billed_target_total = round(sum([
|
||||
record.yet_to_billed_target_april or 0,
|
||||
record.yet_to_billed_target_may or 0,
|
||||
record.yet_to_billed_target_june or 0,
|
||||
|
|
@ -516,7 +517,7 @@ class SOS_Sales_Achievement_Report(models.Model):
|
|||
record.yet_to_billed_target_january or 0,
|
||||
record.yet_to_billed_target_february or 0,
|
||||
record.yet_to_billed_target_march or 0
|
||||
])
|
||||
]), 2)
|
||||
@api.depends(
|
||||
'planned_target_april','planned_target_may','planned_target_june',
|
||||
'planned_target_july','planned_target_august','planned_target_september',
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@
|
|||
<field name="value"/>
|
||||
<field name="products"/>
|
||||
<field name="po_no"/>
|
||||
<field name="quantity"/>
|
||||
<!-- <field name="quantity"/> -->
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
|
|
@ -139,7 +139,7 @@
|
|||
<field name="value"/>
|
||||
<field name="products"/>
|
||||
<field name="po_no"/>
|
||||
<field name="quantity"/>
|
||||
<!-- <field name="quantity"/> -->
|
||||
</tree>
|
||||
</field>
|
||||
<footer>
|
||||
|
|
|
|||
Loading…
Reference in New Issue