add membership_expiry_reminder
This commit is contained in:
parent
de0520d5a8
commit
9376d03d9d
8 changed files with 256 additions and 0 deletions
3
membership_expiry_reminder/models/__init__.py
Normal file
3
membership_expiry_reminder/models/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import res_config_settings, res_partner
|
||||
15
membership_expiry_reminder/models/res_config_settings.py
Normal file
15
membership_expiry_reminder/models/res_config_settings.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = "res.config.settings"
|
||||
|
||||
membership_expiry_reminder_days = fields.Integer(
|
||||
string="Days before expiry to send reminder",
|
||||
default=30,
|
||||
config_parameter="membership_expiry_reminder.days_before_expiry",
|
||||
help="Number of days before the membership end date to send the renewal "
|
||||
"reminder email. Set to 0 to disable automatic reminders.",
|
||||
)
|
||||
88
membership_expiry_reminder/models/res_partner.py
Normal file
88
membership_expiry_reminder/models/res_partner.py
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = "res.partner"
|
||||
|
||||
membership_expiry_reminder_sent = fields.Boolean(
|
||||
string="Expiry Reminder Sent",
|
||||
default=False,
|
||||
copy=False,
|
||||
help="Checked when the membership renewal reminder email has been sent "
|
||||
"for the current membership period. Reset automatically when the "
|
||||
"membership is renewed.",
|
||||
)
|
||||
|
||||
def _cron_send_membership_expiry_reminders(self):
|
||||
"""Daily cron: find members whose membership expires within the next N days
|
||||
and who have not yet received a reminder. This catches up on any members
|
||||
that were missed on previous runs."""
|
||||
days = int(
|
||||
self.env["ir.config_parameter"]
|
||||
.sudo()
|
||||
.get_param("membership_expiry_reminder.days_before_expiry", 30)
|
||||
)
|
||||
if not days:
|
||||
_logger.info(
|
||||
"membership_expiry_reminder: disabled (days_before_expiry = 0)"
|
||||
)
|
||||
return
|
||||
|
||||
template = self.env.ref(
|
||||
"membership_expiry_reminder.email_template_membership_expiry",
|
||||
raise_if_not_found=False,
|
||||
)
|
||||
if not template:
|
||||
_logger.warning(
|
||||
"membership_expiry_reminder: email template not found, skipping."
|
||||
)
|
||||
return
|
||||
|
||||
today = fields.Date.today()
|
||||
deadline = today + timedelta(days=days)
|
||||
|
||||
partners = self.search(
|
||||
[
|
||||
("membership_state", "=", "paid"),
|
||||
("membership_stop", ">=", today),
|
||||
("membership_stop", "<=", deadline),
|
||||
("membership_expiry_reminder_sent", "=", False),
|
||||
("email", "!=", False),
|
||||
]
|
||||
)
|
||||
|
||||
_logger.info(
|
||||
"membership_expiry_reminder: sending reminders to %d partner(s) "
|
||||
"(expiry between today and %s, i.e. within %d days)",
|
||||
len(partners),
|
||||
deadline,
|
||||
days,
|
||||
)
|
||||
|
||||
for partner in partners:
|
||||
try:
|
||||
template.send_mail(partner.id, force_send=True)
|
||||
partner.membership_expiry_reminder_sent = True
|
||||
except Exception:
|
||||
_logger.exception(
|
||||
"membership_expiry_reminder: failed to send email to partner %d (%s)",
|
||||
partner.id,
|
||||
partner.email,
|
||||
)
|
||||
|
||||
def write(self, vals):
|
||||
# Reset the reminder flag when the membership is renewed
|
||||
# (i.e., when member_lines changes, which updates membership_stop)
|
||||
result = super().write(vals)
|
||||
if "membership_stop" in vals:
|
||||
self.filtered("membership_expiry_reminder_sent").write(
|
||||
{"membership_expiry_reminder_sent": False}
|
||||
)
|
||||
return result
|
||||
Loading…
Add table
Add a link
Reference in a new issue