Added override for email campaign sending to send emails at 08:15AM instead of midnight
This commit is contained in:
BIN
rangeldigital/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
rangeldigital/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
rangeldigital/__pycache__/hooks.cpython-310.pyc
Normal file
BIN
rangeldigital/__pycache__/hooks.cpython-310.pyc
Normal file
Binary file not shown.
@ -11,8 +11,31 @@ override_doctype_class = {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Lead: Add javascript to add "Add to Email Campaign to Action Dropdown"
|
||||||
|
doctype_js = {
|
||||||
|
"Lead": "public/js/lead.js"
|
||||||
|
}
|
||||||
|
# Add cron scheduler for email campaign sending
|
||||||
|
# Send email at 08:15 AM every day
|
||||||
|
scheduler_events = {
|
||||||
|
"cron": {
|
||||||
|
"15 8 * * *": [
|
||||||
|
|
||||||
|
|
||||||
|
"rangeldigital.utilities.scheduler.scheduler.send_email_to_leads_or_contacts"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Disable default send_email_to_leads_or_contacts
|
||||||
|
after_install = "rangeldigital.utilities.install.after_install"
|
||||||
|
|
||||||
|
|
||||||
|
# Enable default send_email_to_leads_or_contacts
|
||||||
|
before_uninstall = "rangeldigital.utilities.uninstall.before_uninstall"
|
||||||
|
|
||||||
|
|
||||||
|
#app_include_js = "/assets/rangeldigital/js/lead.js"
|
||||||
|
|
||||||
web_include_js = [
|
web_include_js = [
|
||||||
|
|
||||||
|
|||||||
26
rangeldigital/install.py
Normal file
26
rangeldigital/install.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def after_install():
|
||||||
|
stop_erpnext_scheduled_send_email_job()
|
||||||
|
|
||||||
|
def stop_erpnext_scheduled_send_email_job():
|
||||||
|
# Get list of Scheduled Job Type docs with that method
|
||||||
|
job_docs = frappe.get_all(
|
||||||
|
"Scheduled Job Type",
|
||||||
|
filters={"method": "erpnext.crm.doctype.email_campaign.email_campaign.send_email_to_leads_or_contacts"},
|
||||||
|
limit_page_length=1
|
||||||
|
)
|
||||||
|
|
||||||
|
if not job_docs:
|
||||||
|
frappe.msgprint("Scheduled Job Type not found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
job_name = job_docs[0].name
|
||||||
|
job_doc = frappe.get_doc("Scheduled Job Type", job_name)
|
||||||
|
|
||||||
|
# Set stopped = 1
|
||||||
|
job_doc.stopped = 1
|
||||||
|
job_doc.save(ignore_permissions=True)
|
||||||
|
frappe.db.commit()
|
||||||
|
|
||||||
|
frappe.msgprint(f"Scheduled Job Type '{job_doc.method}' stopped successfully.")
|
||||||
65
rangeldigital/public/js/lead.js
Normal file
65
rangeldigital/public/js/lead.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
frappe.ui.form.on('Lead', {
|
||||||
|
refresh(frm) {
|
||||||
|
// Only show the button if the Lead has been saved and has an email
|
||||||
|
if (!frm.doc.__islocal && frm.doc.email_id) {
|
||||||
|
frm.add_custom_button(__('Add to Email Campaign'), () => {
|
||||||
|
open_email_campaign_dialog(frm);
|
||||||
|
}, __('Action'));
|
||||||
|
} else if (!frm.doc.email_id) {
|
||||||
|
// Optional: give user visual feedback
|
||||||
|
frm.dashboard.set_headline(__('This Lead has no email address — cannot add to Email Campaign.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function open_email_campaign_dialog(frm) {
|
||||||
|
frappe.prompt([
|
||||||
|
{
|
||||||
|
fieldname: 'campaign_name',
|
||||||
|
label: 'Campaign',
|
||||||
|
fieldtype: 'Link',
|
||||||
|
options: 'Campaign',
|
||||||
|
reqd: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname: 'start_date',
|
||||||
|
label: 'Start Date',
|
||||||
|
fieldtype: 'Date',
|
||||||
|
default: frappe.datetime.get_today(),
|
||||||
|
reqd: 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
(values) => {
|
||||||
|
frappe.call({
|
||||||
|
method: 'rangeldigital.utilities.lead.lead_api.add_lead_to_campaign',
|
||||||
|
args: {
|
||||||
|
lead_name: frm.doc.name,
|
||||||
|
campaign_name: values.campaign_name,
|
||||||
|
start_date: values.start_date
|
||||||
|
},
|
||||||
|
freeze: true,
|
||||||
|
freeze_message: __('Creating Email Campaign...'),
|
||||||
|
callback: (r) => {
|
||||||
|
if (r.message && r.message.status === 'success') {
|
||||||
|
frappe.show_alert({
|
||||||
|
message: __('Email Campaign created successfully'),
|
||||||
|
indicator: 'green'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
frappe.msgprint(__('Something went wrong. Please try again.'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: (err) => {
|
||||||
|
if (err && err.message) {
|
||||||
|
frappe.msgprint(err.message);
|
||||||
|
} else {
|
||||||
|
frappe.msgprint(__('Unexpected error. Check the console.'));
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
__('New Email Campaign'),
|
||||||
|
__('Create')
|
||||||
|
);
|
||||||
|
}
|
||||||
Binary file not shown.
1
rangeldigital/utilities/__init__.py
Normal file
1
rangeldigital/utilities/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
__version__ = "0.0.1"
|
||||||
BIN
rangeldigital/utilities/__pycache__/__init__.cpython-310.pyc
Normal file
BIN
rangeldigital/utilities/__pycache__/__init__.cpython-310.pyc
Normal file
Binary file not shown.
BIN
rangeldigital/utilities/__pycache__/install.cpython-310.pyc
Normal file
BIN
rangeldigital/utilities/__pycache__/install.cpython-310.pyc
Normal file
Binary file not shown.
BIN
rangeldigital/utilities/__pycache__/uninstall.cpython-310.pyc
Normal file
BIN
rangeldigital/utilities/__pycache__/uninstall.cpython-310.pyc
Normal file
Binary file not shown.
26
rangeldigital/utilities/install.py
Normal file
26
rangeldigital/utilities/install.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def after_install():
|
||||||
|
stop_erpnext_scheduled_send_email_job()
|
||||||
|
|
||||||
|
def stop_erpnext_scheduled_send_email_job():
|
||||||
|
# Get list of Scheduled Job Type docs with that method
|
||||||
|
job_docs = frappe.get_all(
|
||||||
|
"Scheduled Job Type",
|
||||||
|
filters={"method": "erpnext.crm.doctype.email_campaign.email_campaign.send_email_to_leads_or_contacts"},
|
||||||
|
limit_page_length=1
|
||||||
|
)
|
||||||
|
|
||||||
|
if not job_docs:
|
||||||
|
frappe.msgprint("Scheduled Job Type not found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
job_name = job_docs[0].name
|
||||||
|
job_doc = frappe.get_doc("Scheduled Job Type", job_name)
|
||||||
|
|
||||||
|
# Set stopped = 1
|
||||||
|
job_doc.stopped = 1
|
||||||
|
job_doc.save(ignore_permissions=True)
|
||||||
|
frappe.db.commit()
|
||||||
|
|
||||||
|
frappe.msgprint(f"Scheduled Job Type '{job_doc.method}' stopped successfully.")
|
||||||
1
rangeldigital/utilities/lead/__init__.py
Normal file
1
rangeldigital/utilities/lead/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
__version__ = "0.0.1"
|
||||||
Binary file not shown.
Binary file not shown.
31
rangeldigital/utilities/lead/lead_api.py
Normal file
31
rangeldigital/utilities/lead/lead_api.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import frappe
|
||||||
|
from frappe.utils import today
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def add_lead_to_campaign(lead_name, campaign_name, start_date=None):
|
||||||
|
if not frappe.db.exists("Lead", lead_name):
|
||||||
|
frappe.throw("Lead does not exist")
|
||||||
|
|
||||||
|
# Check if there's already a scheduled/in-progress campaign for this Lead with same name
|
||||||
|
existing = frappe.db.exists("Email Campaign", {
|
||||||
|
"recipient": lead_name,
|
||||||
|
"campaign_name": campaign_name,
|
||||||
|
"email_campaign_for": "Lead",
|
||||||
|
"status": ["in", ["Scheduled", "In Progress"]]
|
||||||
|
})
|
||||||
|
|
||||||
|
if existing:
|
||||||
|
frappe.throw("This Lead is already part of an Email Campaign with this name.")
|
||||||
|
|
||||||
|
doc = frappe.new_doc("Email Campaign")
|
||||||
|
doc.update({
|
||||||
|
"campaign_name": campaign_name,
|
||||||
|
"email_campaign_for": "Lead",
|
||||||
|
"recipient": lead_name,
|
||||||
|
"start_date": start_date or today(),
|
||||||
|
"sender": frappe.session.user # or replace with a specific default sender
|
||||||
|
})
|
||||||
|
doc.insert(ignore_permissions=True)
|
||||||
|
frappe.db.commit()
|
||||||
|
|
||||||
|
return {"status": "success", "message": "Email Campaign created"}
|
||||||
1
rangeldigital/utilities/scheduler/__init__.py
Normal file
1
rangeldigital/utilities/scheduler/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
__version__ = "0.0.1"
|
||||||
Binary file not shown.
Binary file not shown.
4
rangeldigital/utilities/scheduler/scheduler.py
Normal file
4
rangeldigital/utilities/scheduler/scheduler.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from erpnext.crm.doctype.email_campaign.email_campaign import send_email_to_leads_or_contacts as erpnext_send_email
|
||||||
|
|
||||||
|
def send_email_to_leads_or_contacts():
|
||||||
|
erpnext_send_email()
|
||||||
26
rangeldigital/utilities/uninstall.py
Normal file
26
rangeldigital/utilities/uninstall.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import frappe
|
||||||
|
|
||||||
|
def before_uninstall():
|
||||||
|
start_erpnext_scheduled_send_email_job()
|
||||||
|
|
||||||
|
def start_erpnext_scheduled_send_email_job():
|
||||||
|
# Get list of Scheduled Job Type docs with that method
|
||||||
|
job_docs = frappe.get_all(
|
||||||
|
"Scheduled Job Type",
|
||||||
|
filters={"method": "erpnext.crm.doctype.email_campaign.email_campaign.send_email_to_leads_or_contacts"},
|
||||||
|
limit_page_length=1
|
||||||
|
)
|
||||||
|
|
||||||
|
if not job_docs:
|
||||||
|
frappe.msgprint("Scheduled Job Type not found.")
|
||||||
|
return
|
||||||
|
|
||||||
|
job_name = job_docs[0].name
|
||||||
|
job_doc = frappe.get_doc("Scheduled Job Type", job_name)
|
||||||
|
|
||||||
|
# Set stopped = 1
|
||||||
|
job_doc.stopped = 0
|
||||||
|
job_doc.save(ignore_permissions=True)
|
||||||
|
frappe.db.commit()
|
||||||
|
|
||||||
|
frappe.msgprint(f"Scheduled Job Type '{job_doc.method}' stopped successfully.")
|
||||||
Reference in New Issue
Block a user