Owns the lifecycle of leads (Kademi's CRM/sales-pipeline records) and their related tasks, files, notes, products and participant role assignments. Application code reaches it via RequestContext.C(LeadManager.class); findSalesTeamOrgs is also exported to GraalJS for admin scripts. It delegates persistence and business rules to LeadmanService and FunnelManager, and delegates lead and organisation search to its LeadManSearchHelperV1 and LeadManSearchHelperV2 helpers.
Group: Managers
Properties
| Property | Returns | Description |
|---|---|---|
| allStages | Map<String,String> | The stages of every one of the current tenant's funnels, merged into a single map of stage name to stage description. |
| allTaskTypes | List<Pair<String,Long>> | The distinct task type names used across the current tenant's tasks, each paired with the number of tasks of that type. |
| funnels | Map<String,Funnel> | The current tenant's configured funnels (sales/lead pipelines), keyed by funnel name. |
| leadsGroup | Group | The group configured to hold profiles who are leads/customers rather than sales team members. |
| leadsOrgType | OrgType | The organisation type configured for lead-side organisations (eg customer companies). |
| salesGroup | Group | The group configured to hold the sales team's members. |
| salesOrgType | OrgType | The organisation type configured for sales-side organisations (eg the tenant's own reseller or partner hierarchy). |
| searchV1 | LeadManSearchHelperV1 | The older (V1) helper for lead and organisation search, kept for backwards compatibility. |
| searchV2 | LeadManSearchHelperV2 | The current (V2) helper for lead and organisation search, used for lead omni-search, profile search and organisation search. |
Methods
createNote(Lead lead, String newNote, String actionType, boolean inbound, Date now, Profile curUser) · createLead(String funnelName, String source, Profile cust, String notes, Profile assignedTo, Organisation assignedToOrg) · duplicateLead(Lead sourceLead, String leadNum) · updateLead(Lead lead) · teamTaskStatus(Profile p) · teamStats(Profile p) · taskStats(Profile p) · dealsInfo(Profile p, int lastDays) · leadsEstimatedValue(Profile p) · dueTasks(Profile p, int numDays) · countActiveLeads(Profile p) · findTaskById(long id) · countClosedLeads(FunnelRepository funnel) · countCancelledLeads(FunnelRepository funnel) · countActiveLeads(FunnelRepository funnel) · countParticipantsInRole(FunnelRepository funnel, String roleKey) · findLeadsByStage(Funnel funnel, String stageName, Integer max) · get(long id) · findByLeadNumber(String num) · findWonForProfile(Profile p) · findForProfile(Profile p) · findForProfile(Profile p, Integer max) · findForProfile(Profile p, Integer max, Date from, Date to) · findForProfileAndFunnel(Profile p, String funnelName) · calcEmailConversionPerc(Profile p) · engagementScore(Lead lead) · getFunnels() · getAllStages() · getStagesByJourneys(String journeyNames) · getStagesByJourneys(List<String> journeys) · getAllTaskTypes() · completeTask(Task task, String outcome, Date followUpDate, String newTaskTitle, String taskDescription) · evaluateDerivedField(String name, Lead lead) · evaluateDerivedField(DerivedFunnelField f, Funnel funnel, Lead lead) · delete(Lead lead, Profile deletedBy) · isReleventToLead(Profile profile, Lead lead) · getSearchV1() · getSearchV2() · addProduct(Lead lead, Product product, BigDecimal quantity) · updateLeadProduct(Lead lead, long id, Product product, BigDecimal quantity) · removeLeadProduct(Lead lead, long id) · getOrCreateCompany(FormContext fc) · doLeadSearch(Integer from, Integer size, Map<String,String> params) · doLeadAggregation(Map<String,String> params) · addNewFile(Lead lead, String name, String hash, String contentType, String geoLocation, Profile createdBy, Date now) · addNewFile(Lead lead, String name, String hash, String contentType) · deleteLeadFile(Lead lead, LeadFile leadFile) · updateLeadFile(LeadFile leadFile) · assignParticipant(Lead lead, String roleKey, BaseEntity target) · removeParticipant(Lead lead, String roleKey, BaseEntity target) · describeParticipantIneligibility(LeadRoleDef def, BaseEntity target) · getLeadsOrgType() · getSalesOrgType() · getSalesGroup() · getLeadsGroup() · close(Lead lead, Date now) · cancel(Lead lead, Date now, String reason) · findSalesTeamOrgs(Profile profile)
createNote(Lead lead, String newNote, String actionType, boolean inbound, Date now, Profile curUser)
Returns: LeadNote
Adds a note (a timestamped comment) to a lead's activity history, recording who made it and whether it represents inbound or outbound contact.
| Parameter | Description |
|---|---|
lead | the lead to add the note to |
newNote | the note text |
actionType | a short code describing the kind of activity the note records, eg a call or email |
inbound | true if the note records contact initiated by the customer, false if initiated by the sales side |
now | the date and time the note was made |
curUser | the profile the note is attributed to |
createLead(String funnelName, String source, Profile cust, String notes, Profile assignedTo, Organisation assignedToOrg)
Returns: Lead
Creates a new lead in the named funnel (pipeline) for the given customer profile, recording the source of the lead and an optional initial note and assignment.
| Parameter | Description |
|---|---|
funnelName | the name of the funnel the lead is created in |
source | a short code describing where the lead came from |
cust | the customer profile the lead is for |
notes | an optional initial note to attach to the lead, may be null |
assignedTo | the profile the lead is assigned to, may be null |
assignedToOrg | the organisation the lead is assigned to, may be null |
duplicateLead(Lead sourceLead, String leadNum)
Returns: Lead
Creates a copy of an existing lead in the same funnel and stage, copying its field values, organisation, assignment, deal amount, contact details and files, and appending " (Copy)" to the title.
| Parameter | Description |
|---|---|
sourceLead | the lead to copy |
leadNum | the lead number to use for the copy; if blank, one is derived from the source lead's number and the new lead's id |
updateLead(Lead lead)
Returns: Lead
Saves a lead, sets its modified date, fires change events and recalculates its scores.
| Parameter | Description |
|---|---|
lead | the lead to save |
teamTaskStatus(Profile p)
Returns: TaskStats
Counts of the current tenant's tasks by due-date status (overdue, due today, upcoming) for the team the given profile is part of.
| Parameter | Description |
|---|---|
p | a profile belonging to the sales team to report on |
teamStats(Profile p)
Returns: TeamStats
Summary statistics (eg lead and deal counts) for the current tenant's sales team that the given profile belongs to.
| Parameter | Description |
|---|---|
p | a profile belonging to the sales team to report on |
taskStats(Profile p)
Returns: TaskStats
Counts of the given profile's own tasks by due-date status (overdue, due today, upcoming).
| Parameter | Description |
|---|---|
p | the profile whose tasks are counted |
dealsInfo(Profile p, int lastDays)
Returns: DealsInfo
Summary of the deals a profile closed in the last lastDays days, for the current tenant.
| Parameter | Description |
|---|---|
p | the profile whose closed deals are summarised |
lastDays | how many days back from today to include |
leadsEstimatedValue(Profile p)
Returns: long
Sum of the estimated deal amounts of the current tenant's open leads assigned to the given profile.
| Parameter | Description |
|---|---|
p | the profile whose assigned leads are summed |
dueTasks(Profile p, int numDays)
Returns: List<Task>
Finds the given profile's tasks due within the next numDays days.
| Parameter | Description |
|---|---|
p | the profile whose tasks are searched |
numDays | the number of days ahead of today to include |
countActiveLeads(Profile p)
Returns: long
Counts the current tenant's leads assigned to the given profile.
| Parameter | Description |
|---|---|
p | the profile whose assigned leads are counted |
findTaskById(long id)
Returns: Task
Finds a task belonging to the current tenant by its id.
| Parameter | Description |
|---|---|
id | the task's id |
countClosedLeads(FunnelRepository funnel)
Returns: long
Counts leads in the given funnel that have been closed (won or lost, but not cancelled).
| Parameter | Description |
|---|---|
funnel | the funnel to count leads in |
countCancelledLeads(FunnelRepository funnel)
Returns: long
Counts leads in the given funnel that have been cancelled.
| Parameter | Description |
|---|---|
funnel | the funnel to count leads in |
countActiveLeads(FunnelRepository funnel)
Returns: long
Counts leads in the given funnel that are still open (not closed and not cancelled).
| Parameter | Description |
|---|---|
funnel | the funnel to count leads in |
countParticipantsInRole(FunnelRepository funnel, String roleKey)
Returns: long
Counts existing lead participant assignments for a custom role, used by the funnel admin roles screen to prevent deleting or renaming a role key that leads are still relying on.
| Parameter | Description |
|---|---|
funnel | the funnel whose leads should be checked |
roleKey | the custom LeadRoleDef.roleKey to check |
findLeadsByStage(Funnel funnel, String stageName, Integer max)
Returns: List<Lead>
Finds leads currently at the given stage of the given funnel, for the current tenant.
| Parameter | Description |
|---|---|
funnel | the funnel whose leads are searched |
stageName | the name of the stage to match |
max | the maximum number of leads to return, may be null for no limit |
get(long id)
Returns: Lead
Finds a lead belonging to the current tenant by its internal id.
| Parameter | Description |
|---|---|
id | the lead's internal id |
findByLeadNumber(String num)
Returns: Lead
Finds a lead belonging to the current tenant by its lead number, the user-defined identifier rather than the internal id.
| Parameter | Description |
|---|---|
num | the lead number to search for |
findWonForProfile(Profile p)
Returns: List<Lead>
Finds the given profile's leads that have a closed date set, ie leads that have been won or lost.
| Parameter | Description |
|---|---|
p | the profile whose leads are searched |
findForProfile(Profile p)
Returns: List<Lead>
Finds all leads assigned to the given profile in the current tenant.
| Parameter | Description |
|---|---|
p | the profile whose leads are searched |
findForProfile(Profile p, Integer max)
Returns: List<Lead>
Finds leads assigned to the given profile in the current tenant, up to a maximum count.
| Parameter | Description |
|---|---|
p | the profile whose leads are searched |
max | the maximum number of leads to return, may be null for no limit |
findForProfile(Profile p, Integer max, Date from, Date to)
Returns: List<Lead>
Finds leads assigned to the given profile in the current tenant, created within the given date range, up to a maximum count.
| Parameter | Description |
|---|---|
p | the profile whose leads are searched |
max | the maximum number of leads to return, may be null for no limit |
from | the start of the date range, may be null for no lower bound |
to | the end of the date range, may be null for no upper bound |
findForProfileAndFunnel(Profile p, String funnelName)
Returns: List<Lead>
Finds leads assigned to the given profile within a specific named funnel.
| Parameter | Description |
|---|---|
p | the profile whose leads are searched |
funnelName | the name of the funnel to restrict the search to |
calcEmailConversionPerc(Profile p)
Returns: Double
Calculates the percentage of emails sent to the given profile that were marked as converted, based on the profile's sent-and-clicked email history.
| Parameter | Description |
|---|---|
p | the profile whose email history is analysed |
engagementScore(Lead lead)
Returns: Float
Calculates the given lead's engagement score, as determined by the funnel's engagement scoring rules.
| Parameter | Description |
|---|---|
lead | the lead to score |
getFunnels()
Returns: Map<String,Funnel>
The current tenant's configured funnels (sales/lead pipelines), keyed by funnel name.
getAllStages()
Returns: Map<String,String>
The stages of every one of the current tenant's funnels, merged into a single map of stage name to stage description.
getStagesByJourneys(String journeyNames)
Returns: Map<String,String>
Finds the stages belonging to the named funnels, or every stage if no funnel names are given.
| Parameter | Description |
|---|---|
journeyNames | the names of the funnels to restrict the result to, may be empty for all funnels |
getStagesByJourneys(List<String> journeys)
Returns: Map<String,String>
Finds the stages belonging to the named funnels, or every stage if the journeys list is empty.
| Parameter | Description |
|---|---|
journeys | the names of the funnels to restrict the result to, may be empty for all funnels |
getAllTaskTypes()
Returns: List<Pair<String,Long>>
The distinct task type names used across the current tenant's tasks, each paired with the number of tasks of that type.
completeTask(Task task, String outcome, Date followUpDate, String newTaskTitle, String taskDescription)
Returns: void
Marks a task as completed, assigning it to the current user if it has no assignee yet, and fires the task-complete funnel event so any goal actions configured for the outcome can run.
| Parameter | Description |
|---|---|
task | the task to complete |
outcome | the outcome code the task was completed with |
followUpDate | an optional follow-up date, passed through to the funnel event |
newTaskTitle | an optional title for a follow-up task, passed through to the funnel event |
taskDescription | an optional description for a follow-up task, passed through to the funnel event |
evaluateDerivedField(String name, Lead lead)
Returns: Object
Evaluates a named derived field (a funnel-configured JS calculation) against a lead, looking up the field definition on the lead's funnel.
| Parameter | Description |
|---|---|
name | the name of the derived field, as configured on the funnel |
lead | the lead to evaluate the field against |
evaluateDerivedField(DerivedFunnelField f, Funnel funnel, Lead lead)
Returns: Object
Evaluates a derived field's JS function against a lead. Errors thrown by the field's script are logged and swallowed, returning null rather than propagating.
| Parameter | Description |
|---|---|
f | the derived field definition to evaluate |
funnel | the funnel the field belongs to |
lead | the lead to evaluate the field against |
delete(Lead lead, Profile deletedBy)
Returns: void
Soft-deletes a lead, marking it as removed without deleting its database row.
| Parameter | Description |
|---|---|
lead | the lead to delete |
deletedBy | the profile performing the deletion |
isReleventToLead(Profile profile, Lead lead)
Returns: boolean
Returns true if the profile is associated with the lead in a meaningful way. This includes if the profile is the lead's customer or assigned salesperson, or is a member of the lead's organisation.
| Parameter | Description |
|---|---|
profile | the profile to check |
lead | the lead to check the profile's association with |
getSearchV1()
Returns: LeadManSearchHelperV1
The older (V1) helper for lead and organisation search, kept for backwards compatibility.
getSearchV2()
Returns: LeadManSearchHelperV2
The current (V2) helper for lead and organisation search, used for lead omni-search, profile search and organisation search.
addProduct(Lead lead, Product product, BigDecimal quantity)
Returns: LeadProduct
Adds a product line item to a lead's deal, with the given quantity.
| Parameter | Description |
|---|---|
lead | the lead to add the product to |
product | the product to add |
quantity | the quantity of the product |
updateLeadProduct(Lead lead, long id, Product product, BigDecimal quantity)
Returns: LeadProduct
Updates an existing product line item on a lead's deal with a new product and quantity.
| Parameter | Description |
|---|---|
lead | the lead the line item belongs to |
id | the id of the line item to update |
product | the product to set on the line item |
quantity | the new quantity |
removeLeadProduct(Lead lead, long id)
Returns: void
Removes a product line item from a lead's deal.
| Parameter | Description |
|---|---|
lead | the lead the line item belongs to |
id | the id of the line item to remove |
getOrCreateCompany(FormContext fc)
Returns: Organisation
Finds an existing organisation by the newOrgId form parameter, or creates a new one with that id and the newOrgTitle form parameter as its title.
| Parameter | Description |
|---|---|
fc | the form context to read the newOrgId and newOrgTitle parameters from |
doLeadSearch(Integer from, Integer size, Map<String,String> params)
Returns: KSearchResponse
Searches leads using the V1 search helper, returning a page of results.
| Parameter | Description |
|---|---|
from | the zero-based offset of the first result to return |
size | the maximum number of results to return |
params | the search parameters, eg query text and filters |
doLeadAggregation(Map<String,String> params)
Returns: KSearchResponse
Runs a lead search restricted to zero results and aggregates the matches by status, for the current tenant's lead index. Used to drive lead status counts in the admin UI.
| Parameter | Description |
|---|---|
params | the search filter parameters: query, team, tags, sources, assignedTo, journeys and stages |
addNewFile(Lead lead, String name, String hash, String contentType, String geoLocation, Profile createdBy, Date now)
Returns: LeadFile
Attaches a file to a lead, recording who added it, when, and where.
| Parameter | Description |
|---|---|
lead | the lead to attach the file to |
name | the file name |
hash | the file's content hash, used to locate its stored content |
contentType | the file's MIME type |
geoLocation | an optional geographic location the file was captured at, may be null |
createdBy | the profile attaching the file |
now | the date and time the file was attached |
addNewFile(Lead lead, String name, String hash, String contentType)
Returns: LeadFile
Attaches a file to a lead, attributing it to the current user at the current time.
| Parameter | Description |
|---|---|
lead | the lead to attach the file to |
name | the file name |
hash | the file's content hash, used to locate its stored content |
contentType | the file's MIME type |
deleteLeadFile(Lead lead, LeadFile leadFile)
Returns: void
Deletes a file attached to a lead.
| Parameter | Description |
|---|---|
lead | the lead the file is attached to |
leadFile | the file to delete |
updateLeadFile(LeadFile leadFile)
Returns: void
Saves changes to a lead file and marks its parent lead as updated.
| Parameter | Description |
|---|---|
leadFile | the file record to save |
assignParticipant(Lead lead, String roleKey, BaseEntity target)
Returns: void
Assigns a participant using the current thread's session, for callers (eg JS admin controllers) that don't have direct access to a Hibernate Session. See the four-argument assignParticipant overload for the full behaviour.
| Parameter | Description |
|---|---|
lead | the lead to assign the participant to |
roleKey | the role key - one of Lead's ROLE_* constants, or a custom role configured on the lead's funnel |
target | the Profile or Organisation filling the role |
removeParticipant(Lead lead, String roleKey, BaseEntity target)
Returns: void
Removes a participant from a role on a lead, using the current thread's session.
| Parameter | Description |
|---|---|
lead | the lead to remove the participant from |
roleKey | the role key to remove target from |
target | the Profile or Organisation to remove |
describeParticipantIneligibility(LeadRoleDef def, BaseEntity target)
Returns: String
Describes why target is not eligible to fill def's role, or returns null if it is eligible - system roles and custom roles with no configured constraints are always eligible. Used by the admin UI to explain ineligible search candidates before a user attempts to assign them, so assignParticipant's IllegalArgumentException is only ever a race-condition backstop, never the primary way a user discovers a candidate can't fill a role.
| Parameter | Description |
|---|---|
def | the role definition to check eligibility against, may be null (treated as unconstrained) |
target | the candidate Profile or Organisation |
getLeadsOrgType()
Returns: OrgType
The organisation type configured for lead-side organisations (eg customer companies).
getSalesOrgType()
Returns: OrgType
The organisation type configured for sales-side organisations (eg the tenant's own reseller or partner hierarchy).
getSalesGroup()
Returns: Group
The group configured to hold the sales team's members.
getLeadsGroup()
Returns: Group
The group configured to hold profiles who are leads/customers rather than sales team members.
close(Lead lead, Date now)
Returns: void
Closes a lead as won, setting its closed date to now.
| Parameter | Description |
|---|---|
lead | the lead to close |
now | the date and time the lead is closed |
cancel(Lead lead, Date now, String reason)
Returns: void
Cancels a lead, recording the date and a reason.
| Parameter | Description |
|---|---|
lead | the lead to cancel |
now | the date and time the lead is cancelled |
reason | a description of why the lead was cancelled |
findSalesTeamOrgs(Profile profile)
Returns: List<Organisation>
Finds the organisations that make up a profile's sales team: the organisations it belongs to via membership of the configured sales group, plus any organisations where it holds the SalesManager role. Results are deduplicated by organisation id.
| Parameter | Description |
|---|---|
profile | the profile whose sales team organisations are found |