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

PropertyReturnsDescription
allStagesMap<String,String>The stages of every one of the current tenant's funnels, merged into a single map of stage name to stage description.
allTaskTypesList<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.
funnelsMap<String,Funnel>The current tenant's configured funnels (sales/lead pipelines), keyed by funnel name.
leadsGroupGroupThe group configured to hold profiles who are leads/customers rather than sales team members.
leadsOrgTypeOrgTypeThe organisation type configured for lead-side organisations (eg customer companies).
salesGroupGroupThe group configured to hold the sales team's members.
salesOrgTypeOrgTypeThe organisation type configured for sales-side organisations (eg the tenant's own reseller or partner hierarchy).
searchV1LeadManSearchHelperV1The older (V1) helper for lead and organisation search, kept for backwards compatibility.
searchV2LeadManSearchHelperV2The 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.

ParameterDescription
leadthe lead to add the note to
newNotethe note text
actionTypea short code describing the kind of activity the note records, eg a call or email
inboundtrue if the note records contact initiated by the customer, false if initiated by the sales side
nowthe date and time the note was made
curUserthe 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.

ParameterDescription
funnelNamethe name of the funnel the lead is created in
sourcea short code describing where the lead came from
custthe customer profile the lead is for
notesan optional initial note to attach to the lead, may be null
assignedTothe profile the lead is assigned to, may be null
assignedToOrgthe 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.

ParameterDescription
sourceLeadthe lead to copy
leadNumthe 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.

ParameterDescription
leadthe 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.

ParameterDescription
pa 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.

ParameterDescription
pa 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).

ParameterDescription
pthe 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.

ParameterDescription
pthe profile whose closed deals are summarised
lastDayshow 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.

ParameterDescription
pthe 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.

ParameterDescription
pthe profile whose tasks are searched
numDaysthe number of days ahead of today to include

countActiveLeads(Profile p)

Returns: long

Counts the current tenant's leads assigned to the given profile.

ParameterDescription
pthe profile whose assigned leads are counted

findTaskById(long id)

Returns: Task

Finds a task belonging to the current tenant by its id.

ParameterDescription
idthe task's id

countClosedLeads(FunnelRepository funnel)

Returns: long

Counts leads in the given funnel that have been closed (won or lost, but not cancelled).

ParameterDescription
funnelthe funnel to count leads in

countCancelledLeads(FunnelRepository funnel)

Returns: long

Counts leads in the given funnel that have been cancelled.

ParameterDescription
funnelthe 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).

ParameterDescription
funnelthe 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.

ParameterDescription
funnelthe funnel whose leads should be checked
roleKeythe 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.

ParameterDescription
funnelthe funnel whose leads are searched
stageNamethe name of the stage to match
maxthe 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.

ParameterDescription
idthe 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.

ParameterDescription
numthe 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.

ParameterDescription
pthe profile whose leads are searched

findForProfile(Profile p)

Returns: List<Lead>

Finds all leads assigned to the given profile in the current tenant.

ParameterDescription
pthe 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.

ParameterDescription
pthe profile whose leads are searched
maxthe 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.

ParameterDescription
pthe profile whose leads are searched
maxthe maximum number of leads to return, may be null for no limit
fromthe start of the date range, may be null for no lower bound
tothe 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.

ParameterDescription
pthe profile whose leads are searched
funnelNamethe 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.

ParameterDescription
pthe 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.

ParameterDescription
leadthe 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.

ParameterDescription
journeyNamesthe 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.

ParameterDescription
journeysthe 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.

ParameterDescription
taskthe task to complete
outcomethe outcome code the task was completed with
followUpDatean optional follow-up date, passed through to the funnel event
newTaskTitlean optional title for a follow-up task, passed through to the funnel event
taskDescriptionan 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.

ParameterDescription
namethe name of the derived field, as configured on the funnel
leadthe 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.

ParameterDescription
fthe derived field definition to evaluate
funnelthe funnel the field belongs to
leadthe 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.

ParameterDescription
leadthe lead to delete
deletedBythe 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.

ParameterDescription
profilethe profile to check
leadthe 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.

ParameterDescription
leadthe lead to add the product to
productthe product to add
quantitythe 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.

ParameterDescription
leadthe lead the line item belongs to
idthe id of the line item to update
productthe product to set on the line item
quantitythe new quantity

removeLeadProduct(Lead lead, long id)

Returns: void

Removes a product line item from a lead's deal.

ParameterDescription
leadthe lead the line item belongs to
idthe 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.

ParameterDescription
fcthe 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.

ParameterDescription
fromthe zero-based offset of the first result to return
sizethe maximum number of results to return
paramsthe 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.

ParameterDescription
paramsthe 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.

ParameterDescription
leadthe lead to attach the file to
namethe file name
hashthe file's content hash, used to locate its stored content
contentTypethe file's MIME type
geoLocationan optional geographic location the file was captured at, may be null
createdBythe profile attaching the file
nowthe 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.

ParameterDescription
leadthe lead to attach the file to
namethe file name
hashthe file's content hash, used to locate its stored content
contentTypethe file's MIME type

deleteLeadFile(Lead lead, LeadFile leadFile)

Returns: void

Deletes a file attached to a lead.

ParameterDescription
leadthe lead the file is attached to
leadFilethe file to delete

updateLeadFile(LeadFile leadFile)

Returns: void

Saves changes to a lead file and marks its parent lead as updated.

ParameterDescription
leadFilethe 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.

ParameterDescription
leadthe lead to assign the participant to
roleKeythe role key - one of Lead's ROLE_* constants, or a custom role configured on the lead's funnel
targetthe 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.

ParameterDescription
leadthe lead to remove the participant from
roleKeythe role key to remove target from
targetthe 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.

ParameterDescription
defthe role definition to check eligibility against, may be null (treated as unconstrained)
targetthe 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.

ParameterDescription
leadthe lead to close
nowthe 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.

ParameterDescription
leadthe lead to cancel
nowthe date and time the lead is cancelled
reasona 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.

ParameterDescription
profilethe profile whose sales team organisations are found
To get full access to the Kademi Hub existing customers can login here, or new customers can register here.