GatherPhoneNumbersFromRecords

What It Does

After BuildCommunicationScopeForRecord determines which records are in scope, the package needs to extract the phone numbers from those records. It then queries PhoneCall__c records whose external phone numbers match, which is how calls appear in the timeline.

By default:

  • ContactPhone, MobilePhone, HomePhone, OtherPhone.
  • AccountPhone.
  • Any other SObject — no phone numbers extracted (calls will not appear).

Implement GatherPhoneNumbersFromRecords.IStrategy to override extraction for a specific object type — for example, to read from a custom phone field, add numbers from a related list, or support a custom object entirely.

Interface

global interface IStrategy {
    void gather(Context context);
}

Context

Input

Field Type Description
recordRefs callcoreio.RecordRefSet The set of records to extract phone numbers from. All records are the same SObject type.

Access the IDs to query via context.recordRefs.toIdSet().

Write Methods

Call these from your gather implementation to record phone numbers:

Method Description
add(callcoreio.RecordRef recordRef, String displayName, String phoneNumber) Adds a single phone number for a record.
add(callcoreio.RecordRef recordRef, String displayName, Set<String> phoneNumbers) Adds multiple phone numbers for a record.
add(Id recordId, String displayName, Set<String> phoneNumbers) Convenience overload accepting a raw Id.

Phone number normalisation is applied automatically inside add(). You do not need to normalise numbers before passing them — pass them as they appear on the record. Null and blank values in the set are silently ignored.

Discriminator

The discriminator is RecordType:<SObjectApiName> where <SObjectApiName> is the API name of the object the strategy handles (e.g., RecordType:Contact, RecordType:MyObject__c).

Use default to provide a fallback for all object types without a more specific record. Note that the packaged default returns no phone numbers — if you want numbers extracted from an object not supported by default, you must register a record for it.

Default Behaviour

Object Fields gathered
Contact Phone, MobilePhone, HomePhone, OtherPhone
Account Phone
Anything else None

Example: Custom Object with Multiple Phone Fields

A custom object Supplier__c has fields MainPhone__c, EmergencyPhone__c, and Mobile__c.

public class GatherPhoneNumbersFromSuppliers
    implements callcoreio.GatherPhoneNumbersFromRecords.IStrategy {

    public void gather(callcoreio.GatherPhoneNumbersFromRecords.Context context) {
        List<Supplier__c> suppliers = [
            SELECT Id, Name, MainPhone__c, EmergencyPhone__c, Mobile__c
            FROM Supplier__c
            WHERE Id IN :context.recordRefs.toIdSet()
        ];

        for (Supplier__c s : suppliers) {
            context.add(
                s.Id,
                s.Name,
                new Set<String>{ s.MainPhone__c, s.EmergencyPhone__c, s.Mobile__c }
            );
        }
    }
}

Register with:

  • Strategy Type: GatherPhoneNumbersFromRecords
  • Discriminator: RecordType:Supplier__c
  • Apex Class Name: GatherPhoneNumbersFromSuppliers

Example: Overriding Contact to Add a Custom Field

To extend the built-in Contact extraction with an additional custom field DirectLine__c:

public class GatherPhoneNumbersFromContactsExtended
    implements callcoreio.GatherPhoneNumbersFromRecords.IStrategy {

    public void gather(callcoreio.GatherPhoneNumbersFromRecords.Context context) {
        List<Contact> contacts = [
            SELECT Id, FirstName, LastName, Phone, MobilePhone,
                   HomePhone, OtherPhone, DirectLine__c
            FROM Contact
            WHERE Id IN :context.recordRefs.toIdSet()
        ];

        for (Contact c : contacts) {
            context.add(
                c.Id,
                buildName(c),
                new Set<String>{
                    c.Phone, c.MobilePhone, c.HomePhone,
                    c.OtherPhone, c.DirectLine__c
                }
            );
        }
    }

    private String buildName(Contact c) {
        List<String> parts = new List<String>();
        if (!String.isBlank(c.FirstName)) parts.add(c.FirstName.trim());
        if (!String.isBlank(c.LastName))  parts.add(c.LastName.trim());
        return String.join(parts, ' ');
    }
}

Register with:

  • Strategy Type: GatherPhoneNumbersFromRecords
  • Discriminator: RecordType:Contact
  • Apex Class Name: GatherPhoneNumbersFromContactsExtended

Notes

  • The strategy is called once per SObject type in the scope. If both Contacts and Accounts are in scope, the Contact strategy and the Account strategy are each called separately with their respective RecordRefSet.
  • Query WHERE Id IN :context.recordRefs.toIdSet() — never query in a loop. The framework may pass multiple records at once.
  • The displayName parameter is used in the call record display. It is typically the record's name field. Pass an empty string if no name is available.
  • Phone numbers must already exist in Salesforce field values. The strategy cannot call external APIs.