Skip to main content

Auto Dialer Lists and Sessions

Distribution lists, their destinations, and the call sessions the dialer creates. Campaign settings are on AutoDialerCampaign.

AutoDialerList​

A distribution list of phone numbers. Uploading a new file over a list's numbers keeps the list row and increases version_number; the replaced numbers are kept as an AutoDialerListVersion. parent_list_id links a "(Part N)" list to the list a large upload was split from.

Table: auto_dialer_lists
Model: App\Models\AutoDialerList
Tenant scoped: yes (OrganizationScope)

ColumnTypeNullableDefaultDescription
idbigint unsignedNoautoPrimary key
organization_idbigint unsignedNo-Tenant. Foreign key to organizations, on delete cascade
campaign_idbigint unsignedYesnullCampaign the list is assigned to; several lists can share a campaign. Foreign key to auto_dialer_campaigns, on delete set null
namevarchar(255)No-List name
descriptiontextYesnullDescription
version_numberint unsignedNo1Version number, starting at 1
parent_list_idbigint unsignedYesnullList this "(Part N)" list was split from (rows of a retired versioning flow also use it). Foreign key to auto_dialer_lists, on delete set null
is_latest_versionbooleanNotrueTrue on the newest version of a list
statusenumYesdraftList state. Values: draft, pending, processing, ready, failed, in_use, used, archived (cast to ListStatus)
used_by_campaign_idbigint unsignedYesnullCampaign that used the list. Foreign key to auto_dialer_campaigns, on delete set null
used_attimestampYesnullWhen the list was marked used
original_filenamevarchar(255)YesnullUploaded CSV file name
uploaded_bybigint unsignedYesnullUser who uploaded the current file. Foreign key to users, on delete set null
uploaded_attimestampYesnullWhen the current file was uploaded
processed_attimestampYesnullWhen CSV processing finished
total_rowsint unsignedNo0Rows in the uploaded CSV
valid_rowsint unsignedNo0Rows imported as destinations
invalid_rowsint unsignedNo0Rows rejected by validation
validation_errorsjsonYesnullPer-row validation errors
created_attimestampYesnull
updated_attimestampYesnull
archived_attimestampYesnullWhen the list was archived

Indexes

  • auto_dialer_lists_campaign_id_foreign: campaign_id
  • auto_dialer_lists_used_by_campaign_id_foreign: used_by_campaign_id
  • idx_latest: organization_id, is_latest_version
  • idx_org_status: organization_id, status
  • idx_version: parent_list_id, version_number

Casts: validation_errors (array), uploaded_at (datetime)

Relationships

$autoDialerList->campaign() → AutoDialerCampaign (campaign_id) [BelongsTo]
$autoDialerList->destinations() → AutoDialerDestination (list_id) [HasMany]
$autoDialerList->organization() → Organization (organization_id) [BelongsTo]
$autoDialerList->parentList() → AutoDialerList (parent_list_id) [BelongsTo]
$autoDialerList->versions() → AutoDialerListVersion (list_id) [HasMany]
$autoDialerList->parts() → AutoDialerList (parent_list_id, name like '% (Part %)') [HasMany]
$autoDialerList->usedByCampaign() → AutoDialerCampaign (used_by_campaign_id) [BelongsTo]

Scopes: ready(), processing(), archived(), latestVersion(), assignable()
Methods: canBeArchived(), isReady(), allDestinationsArePendingAndFresh(), canDelete(), isAssigned(), canUnassign(), isLocked(), allParts(), markAsInUse(), markAsUsed(), archive(), copy()

canUnassign() is true while the list is assigned and every destination is still pending with zero dial_attempts (allDestinationsArePendingAndFresh()); once the campaign has started processing the list's entries, the list can no longer be unassigned.

ready(), processing() and archived() filter by status, latestVersion() by is_latest_version, and assignable() returns ready lists. The ListStatus rules (which states can be assigned, uploaded to, archived, copied or versioned) are listed in Enumerations.

AutoDialerListVersion​

A previous version of a distribution list: the numbers one re-upload replaced, kept until expires_at. Written by ListManagementService::updateListWithBackup() in the same transaction that deletes the replaced destinations.

Table: auto_dialer_list_versions
Model: App\Models\AutoDialerListVersion
Tenant scoped: yes (OrganizationScope)

ColumnTypeNullableDefaultDescription
idbigint unsignedNoautoPrimary key
organization_idbigint unsignedNo-Tenant. Foreign key to organizations, on delete cascade
list_idbigint unsignedNo-The list. Foreign key to auto_dialer_lists, on delete cascade
version_numberint unsignedNo-The list's version_number while these numbers were current
original_filenamevarchar(255)YesnullFile the version came from, when known
uploaded_bybigint unsignedYesnullUser who uploaded that file, when known. Foreign key to users, on delete set null
uploaded_attimestampYesnullWhen that file was uploaded (for lists uploaded before uploads were recorded, when processing finished)
replaced_attimestampNo-When a new upload replaced the version
expires_attimestampYesnullWhen the version is deleted: replaced_at plus RETENTION_AUTO_DIALER_LIST_VERSIONS_DAYS (default 30); null when that setting is empty (kept until the list is deleted)
entries_countint unsignedNo0Numbers kept
total_rowsint unsignedYesnullRows in that version's CSV
valid_rowsint unsignedYesnullRows imported from it
invalid_rowsint unsignedYesnullRows rejected from it
created_attimestampYesnull
updated_attimestampYesnull

Indexes

  • auto_dialer_list_versions_list_id_version_number_unique: list_id, version_number (unique)
  • auto_dialer_list_versions_expires_at_index: expires_at

Casts: uploaded_at, replaced_at, expires_at (datetime)

Relationships

$autoDialerListVersion->list() → AutoDialerList (list_id) [BelongsTo]
$autoDialerListVersion->uploader() → User (uploaded_by) [BelongsTo]
$autoDialerListVersion->destinations() → AutoDialerListVersionDestination (version_id) [HasMany]

distribution-lists:prune-versions (daily at 03:15) deletes versions whose expires_at has passed; their entries go by cascade. It also deletes files on the list_backups disk (storage/app/backups/lists, JSON backups written by older releases) older than the retention period.

AutoDialerListVersionDestination​

One number of a previous list version, copied from auto_dialer_destinations when the version was replaced. Rows are only inserted (chunked INSERT ... SELECT), never updated.

Table: auto_dialer_list_version_destinations
Model: App\Models\AutoDialerListVersionDestination
Tenant scoped: yes (OrganizationScope)

ColumnTypeNullableDefaultDescription
idbigint unsignedNoautoPrimary key; ascending in the order of the original list
version_idbigint unsignedNo-The version. Foreign key to auto_dialer_list_versions, on delete cascade
organization_idbigint unsignedNo-Tenant. Foreign key to organizations, on delete cascade
phone_numbervarchar(50)No-Number
namevarchar(255)YesnullContact name
batch_identifiervarchar(255)YesnullBatch label from the CSV
metadatajsonYesnullExtra CSV columns
statusvarchar(20)No-Dialing state at the time (cast to DestinationStatus)
dial_attemptsint unsignedNo0Dial attempts made
last_dialed_attimestampYesnullWhen the last attempt started
last_dispositionvarchar(50)YesnullDisposition of the last attempt
durationint unsignedNo0Duration of the last call, seconds
created_attimestampYesnullCopied from the destination
updated_attimestampYesnullCopied from the destination

Indexes

  • adlvd_version_phone_idx: version_id, phone_number

Casts: status (DestinationStatus), metadata (array), last_dialed_at (datetime)

AutoDialerDestination​

One phone number in a distribution list, with its dialing state.

Table: auto_dialer_destinations
Model: App\Models\AutoDialerDestination
Tenant scoped: yes (OrganizationScope)

ColumnTypeNullableDefaultDescription
idbigint unsignedNoautoPrimary key
organization_idbigint unsignedNo-Tenant. Foreign key to organizations, on delete cascade
list_idbigint unsignedNo-Distribution list. Foreign key to auto_dialer_lists, on delete cascade
phone_numbervarchar(50)No-Number to dial
namevarchar(255)YesnullContact name
batch_identifiervarchar(255)YesnullOptional batch label from the CSV
metadatajsonYesnullExtra CSV columns
statusenumNopendingDialing state. Values: pending, dialing, connected, failed, completed, invalid (cast to DestinationStatus)
dial_attemptstinyint unsignedNo0Dial attempts made
consecutive_initiate_failuressmallint unsignedNo0Consecutive failures to start a call. Reset to 0 after a successful start; at 3 the destination is marked failed, otherwise it is retried after 2^(failures-1) minutes
priorityint unsignedNo1Dial priority
last_session_tokenvarchar(255)YesnullCloudonix session token of the last attempt
last_call_idvarchar(255)YesnullCall ID of the last attempt
last_dialed_attimestampYesnullWhen the last attempt started
next_retry_attimestampYesnullEarliest time of the next attempt
last_dispositionvarchar(50)YesnullDisposition of the last attempt
durationint unsignedNo0Duration of the last call, seconds
billsecint unsignedNo0Billed seconds of the last call
last_cdr_idbigint unsignedYesnullLast call detail record
last_errorvarchar(500)YesnullLast error message
created_attimestampYesnull
updated_attimestampYesnull

Indexes

  • add_list_status_idx: list_id, status
  • add_org_phone_idx: organization_id, phone_number
  • add_retry_at_idx: status, next_retry_at
  • add_session_token_idx: last_session_token

Casts: metadata (array)

Relationships

$autoDialerDestination->list() → AutoDialerList (list_id) [BelongsTo]
$autoDialerDestination->campaign() → ? [BelongsTo]
$autoDialerDestination->organization() → Organization (organization_id) [BelongsTo]

Scopes: pending(), completed(), failed(), invalid()
Methods: canDial(), incrementDialAttempts(), markAsInvalid(), markAsFailed(), markAsCompleted()

campaign() is resolved through the list ($destination->list->belongsTo(AutoDialerCampaign::class)), so it needs the list loaded. Scopes pending(), completed(), failed() and invalid() filter by status.

AutoDialerCallSession​

One call attempt placed by the dialer worker for a campaign destination.

Table: auto_dialer_call_sessions
Model: App\Models\AutoDialerCallSession
Tenant scoped: yes (OrganizationScope)
Traits: PrunesByRetention

ColumnTypeNullableDefaultDescription
idbigint unsignedNoautoPrimary key
organization_idbigint unsignedNo-Tenant. Foreign key to organizations, on delete cascade
campaign_idbigint unsignedNo-Campaign. Foreign key to auto_dialer_campaigns, on delete cascade
destination_idbigint unsignedNo-Destination dialed. Foreign key to auto_dialer_destinations, on delete cascade
caller_idvarchar(50)YesnullCaller ID used
caller_did_idbigint unsignedYesnullPool DID used as Caller ID. Foreign key to did_numbers, on delete set null
phone_numbervarchar(50)YesnullNumber dialed
worker_idvarchar(255)YesnullDialer worker that placed the call
session_tokenvarchar(255)No-Cloudonix session token
call_idvarchar(255)YesnullCloudonix call ID
statusenumNoinitiatedCall state. Values: initiated, ringing, answered, completed, failed
dispositionvarchar(50)YesnullFinal disposition
durationint unsignedNo0Duration, seconds
billsecint unsignedNo0Billed seconds
recording_urltextYesnullRecording URL
initiated_attimestampNoCURRENT_TIMESTAMPWhen the call was placed
answered_attimestampYesnullWhen it was answered
completed_attimestampYesnullWhen it ended
amd_resultenumYesnullVoicemail detection result. Values: human, voicemail, unknown
amd_confidencedecimal(5,2)YesnullVoicemail detection confidence
created_attimestampYesnull
updated_attimestampYesnull

Indexes

  • adcs_campaign_status_idx: campaign_id, status
  • adcs_destination_idx: destination_id
  • adcs_session_token_idx: session_token
  • adcs_worker_id_idx: worker_id
  • auto_dialer_call_sessions_caller_did_id_foreign: caller_did_id
  • auto_dialer_call_sessions_organization_id_foreign: organization_id

Casts: amd_confidence (decimal:2)
Not mass assignable: caller_id, caller_did_id

Relationships

$autoDialerCallSession->campaign() → AutoDialerCampaign (campaign_id) [BelongsTo]
$autoDialerCallSession->destination() → AutoDialerDestination (destination_id) [BelongsTo]
$autoDialerCallSession->organization() → Organization (organization_id) [BelongsTo]

Scopes: active()
Methods: markAsAnswered(), markAsCompleted(), markAsFailed(), setAmdResult(), getDuration()

active() returns sessions in initiated, ringing or answered. Rows whose created_at is older than RETENTION_AUTO_DIALER_CALL_SESSIONS_DAYS (default 183) are deleted daily by model:prune.