Skip to content

[19.0][ADD] crm_lead_escalation: notify a manager about stalled leads - #764

Open
JasminSForgeFlow wants to merge 1 commit into
OCA:19.0from
ForgeFlow:19.0-add-crm_lead_escalation
Open

JasminSForgeFlow wants to merge 1 commit into
OCA:19.0from
ForgeFlow:19.0-add-crm_lead_escalation

Conversation

@JasminSForgeFlow

Copy link
Copy Markdown

Escalate leads that got no follow-up for a configurable delay, or that are still neither won nor lost since their creation. Each rule defines the delay, the sales teams and lead types it covers, and who is warned: the sales team leader or a specific user. The recipient gets a to-do activity and an email, and can optionally be made the salesperson of the lead.

Any message, activity or stage change on the lead resets the escalation clock, so a lead stops being reported as soon as somebody works on it again.

@ForgeFlow

@MarinaAForgeFlow MarinaAForgeFlow left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codre review, LGTM

@AaronHForgeFlow AaronHForgeFlow left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code review, minor remarks

# One unrenderable template or one unreadable lead must not
# roll back the escalations of every other recipient.
with self.env.cr.savepoint():
self._escalate_batch(batch, recipient)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not big issue, but if _escalate_batch raises the leads are not marked as escalated

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks.

@api.model_create_multi
def create(self, vals_list):
activities = super().create(vals_list)
# Planning a call or a meeting is working on the lead too.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't understand this, can you explain?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a salesperson plans a call or meeting on a lead from the chatter, they are working on it, so the "no follow-up" clock restarts and the lead won't be escalated as stalled. Automated activities (planned by other modules, or the escalation's own activity) are excluded. I reworded the comment in the code to make this clearer.

<field name="user_id" ref="base.user_root" />
<field name="interval_number">5</field>
<field name="interval_type">minutes</field>
<field name="active" eval="True" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this needed?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks.


_logger = logging.getLogger(__name__)

ESCALATION_BATCH_SIZE = 1000

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps we can use a system parameter to avoid hardcoding?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks.

"""Warn ``recipient`` about ``leads``, in their own language."""
self.ensure_one()
rule = self.with_context(lang=recipient.lang)
note = Markup("<p>%s</p>") % rule.env._(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we move the note message to separate method?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks.

class MailActivity(models.Model):
_inherit = "mail.activity"

def _get_escalation_leads(self):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find more natural a code where the activity calls a method on the related lead

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks.

Escalate leads that got no follow-up for a configurable delay, or that are
still neither won nor lost since their creation. Each rule defines the delay,
the sales teams and lead types it covers, and who is warned: the sales team
leader or a specific user. The recipient gets a to-do activity and an email,
and can optionally be made the salesperson of the lead.

Any message, activity or stage change on the lead resets the escalation clock,
so a lead stops being reported as soon as somebody works on it again.
@JasminSForgeFlow
JasminSForgeFlow force-pushed the 19.0-add-crm_lead_escalation branch from 46ed1e3 to 94cfac3 Compare October 28, 2026 07:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mod:crm_lead_escalation Module crm_lead_escalation series:19.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants