diff --git a/dms/views/menu.xml b/dms/views/menu.xml index f74778f..e8071c5 100755 --- a/dms/views/menu.xml +++ b/dms/views/menu.xml @@ -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" > - - - [TEST] Material Table Backup Every Minute - - 10 - 1 - minutes - -1 - 2026-03-31 23:59:00 - - code - model.cron_create_table_backup() - - - + + Weekly Shelf Life Expiry Report + + code + model.action_generate_expiry_report() + 1 + weeks + -1 + 2025-08-11 08:00:00 + True + + \ No newline at end of file diff --git a/sos_inventory/models/__init__.py b/sos_inventory/models/__init__.py index fa11e2f..3537e14 100755 --- a/sos_inventory/models/__init__.py +++ b/sos_inventory/models/__init__.py @@ -57,4 +57,5 @@ 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 \ No newline at end of file +from . import sos_transfer_challan_return_from_customer +from . import sos_shelflife_register \ No newline at end of file diff --git a/sos_inventory/models/__pycache__/__init__.cpython-310.pyc b/sos_inventory/models/__pycache__/__init__.cpython-310.pyc index 95c81f2..e4b2598 100644 Binary files a/sos_inventory/models/__pycache__/__init__.cpython-310.pyc and b/sos_inventory/models/__pycache__/__init__.cpython-310.pyc differ diff --git a/sos_inventory/models/__pycache__/sos_ir.cpython-310.pyc b/sos_inventory/models/__pycache__/sos_ir.cpython-310.pyc index 58cde96..1310398 100644 Binary files a/sos_inventory/models/__pycache__/sos_ir.cpython-310.pyc and b/sos_inventory/models/__pycache__/sos_ir.cpython-310.pyc differ diff --git a/sos_inventory/models/sos_ir.py b/sos_inventory/models/sos_ir.py index 005e1aa..ed8d164 100755 --- a/sos_inventory/models/sos_ir.py +++ b/sos_inventory/models/sos_ir.py @@ -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,10 +417,13 @@ 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.""" diff --git a/sos_inventory/models/sos_shelflife_register.py b/sos_inventory/models/sos_shelflife_register.py new file mode 100755 index 0000000..849f546 --- /dev/null +++ b/sos_inventory/models/sos_shelflife_register.py @@ -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""" + + {material.name.part_no or ''} + {material.expiry_date or ''} + {material.remaining_days or ''} + + """ + for material in expiring_materials + ]) + + html_body = f""" +

Dear Team,

+

Below is the weekly report of materials expiring within 7 days:

+ + + + + + + + + + {table_rows} + +
Material NameExpiry DateRemaining Days to Expire


+

Regards,
Slink Admin

+ """ + + # 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 + ) + \ No newline at end of file diff --git a/sos_inventory/report/shelflife_report.xml b/sos_inventory/report/shelflife_report.xml new file mode 100644 index 0000000..ff41ca8 --- /dev/null +++ b/sos_inventory/report/shelflife_report.xml @@ -0,0 +1,41 @@ + + + + + + Shelf Life Expiry Report + sos_shelflife_register + qweb-pdf + sos_inventory.report_shelflife_expiry + sos_shelflife_expiry_report + + \ No newline at end of file diff --git a/sos_inventory/security/ir.model.access.csv b/sos_inventory/security/ir.model.access.csv index d6e7c17..f5dd6d4 100755 --- a/sos_inventory/security/ir.model.access.csv +++ b/sos_inventory/security/ir.model.access.csv @@ -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 diff --git a/sos_inventory/views/sos_ir_view.xml b/sos_inventory/views/sos_ir_view.xml index dd9cc2b..a6e0773 100755 --- a/sos_inventory/views/sos_ir_view.xml +++ b/sos_inventory/views/sos_ir_view.xml @@ -99,7 +99,8 @@ - + +