AGENT MULTI-CAMPAIGN DIALING DOC	Started: 2020-08-24	Updated: 2022-05-24

NOTE: Requires VICIdial svn/trunk code revision 3284 or higher to work properly!!!

NOTE: The new SHARED campaign dial methods require VICIdial svn/trunk code revision 3340 or higher to work properly!!!

NOTE: THIS FEATURE IS OPTIONAL, AND SHOULD ONLY BE CONFIGURED AFTER YOUR SYSTEM 
      HAS BEEN INSTALLED AND TESTED WITH A STANDARD OUTBOUND CAMPAIGN!



DESCRIPTION:

In cases where a company wants the same group of agents to be able to outbound auto-dial on more than one campaign, you can configure your system to be able to operate in this way. Although it will often lead to a higher total dropped call rate than using separated campaigns or using separate lists within the same campaign and the list override settings to achieve unique configurations per list.

First, a description of how to use List Overrides on multiple lists in a single campaign to achieve the goals of most of our clients that initially say they want to run multiple campaigns for the same group of agents. In the List Modification screen, you will see a series of settings that allow you to override campaign settings for calls placed from that list. For example, all of the following settings can be overriden at the list level:

- Agent Script Override	
- Inbound Script Override	
- Inbound Drop Voicemail Override	
- Inbound After Hours Voicemail Override	
- Campaign CID Override	
- Answering Machine Message Override	
- Drop Inbound Group Override	
- Status Group Override	
- Web Form	
- Web Form Two	
- Web Form Three	
- No Agent Call URL	
- Transfer-Conf Number 1 Override	
- Transfer-Conf Number 2 Override	
- Transfer-Conf Number 3 Override	
- Transfer-Conf Number 4 Override	
- Transfer-Conf Number 5 Override	
- Default Transfer Group	

The above settings will allow calls to go out and back in with unique settings, allowing for unique calls paths and agent screens for each list. So if you have a set of services to perform on a customer list, you can define one per list and have the same group of agents call on all of those separate lists all in one single campaign.


In some cases, like different agent spoken language skills, the above approach will not work, so you have to set up different campaigns(and lists) for each spoken language. In the example below we will detail each of the settings that need to be configured in Campaigns and In-Groups for this to work. We will use the example of an outbound appointment confirmation program that calls people who speak both English and Spanish and have agents who speak one or both of those languages. (There is also a newer and more efficient option for Shared Agent Multi-Campaign outbound dialing using the "SHARED_" Dial Methods that you can read about below this section.)

NOTE: The following instructions below assume that you already know how to set up and run an outbound auto-dialing campaign.

1. Set up three campaigns: 
	APPTENG(Appointments English)
	APPTSPA(Appointments Spanish)
	APPTAGNT(Appointments All Agents)

2. Set up two lists:
	1101(Appointments English List), assigned to the APPTENG campaign
	1102(Appointments Spanish List), assigned to the APPTSPA campaign

3. Set up two Inbound Groups to use as Drop In-Groups:
	DROP_APPT_ENG(Appointments English Drop InGroup)
	DROP_APPT_SPA(Appointments Spanish Drop InGroup)
     * RECOMMENDATIONS:
		- You may want to set the In-Group "Drop Call Seconds" to a lower number and send the call to a Call Menu if no agent is available

4. Set the following settings on both the APPTENG & APPTSPA campaigns (these are your two outbound dialing campaigns)
     * Start by setting these campaigns up as you would to be normal outbound auto-dialing campaigns
	Dial Method: ADAPT_AVERAGE or RATIO
	Available Only Tally: Y
	Drop Call Seconds: -1
	Drop Action: IN_GROUP
	Drop Transfer Group: DROP_APPT_ENG(for the APPTENG campaign) or DROP_APPT_SPA(for the APPTSPA campaign)
     * RECOMMENDATIONS:
		- You may want to enable "Available Only Tally" or "Available Only Tally Threshold" to reduce the drop levels on these campaigns
		- Depending on the number of agents, you may want to set "Dial Level Difference Target" to a negative number to reduce drops
		- For high-contact lists, you should use a RATIO dial method and a Dial Level of '1'

5. Set the following settings on the APPTAGNT campaign:
	Allow Inbound and Blended: Y
	Dial Method: RATIO
	Allow No-Hopper-Leads Logins: Y
	Allowed Inbound Groups: select both "DROP_APPT_ENG" & "DROP_APPT_SPA"
	* Do not assign any active lists to this campaign

6. Set the following settings on both the DROP_APPT_ENG & DROP_APPT_SPA inbound groups
	Welcome Message Filename: ---NONE---
	Play Welcome Message: NEVER
	No Delay Call Route: Y

7. Set up two Users(which will be used for Remote Agents)
	User Number: 900000 & 910000

8. Set up two Remote Agents
	User ID Start: 900000 & 910000
	Number of Lines: 1
	Server IP: <set to an active dialer with agents on your system>
		NOTE: On a multi-dialer cluster with multiple outbound campaigns, you will want to spread out Remote Agents across your active dialers
	External Extension: 8300
	Status: ACTIVE <You may want to leave this as INACTIVE until you are ready to dial>
	Campaign: assign one to the APPTENG campaign and the other to the APPTSPA campaign

9. All agents will log into the "APPTAGNT" campaign and will select the "DROP_APPT_ENG" and/or "DROP_APPT_SPA" in-groups to take calls from when they log in, or managers can select those in-groups for the agents in the User Modify screen for those agents if they don't want their agents to have the ability to choose.





HOW IT WORKS:

When an outbound dialing campaign has the "Drop Call Seconds" set to '-1' and the "Drop Action" set to 'IN_GROUP' then the predictive dialing system will look for active agents logged in to other campaigns that have selected that campaign's "Drop Transfer Group" and will count them as agents in the outbound campaign, for the purposes of calculating how many calls to place outbound. For this reason, we recommend enabling the campaign "Available Only Tally" settings, to ensure too many calls are not being placed for agents already in phone calls since any agent with more than one campaign "drop in-group" selected will appear as more than one agent to the dialing system. The Remote Agents are used as a way of telling the system that the outbound dialing campaigns should be active, and when the "Drop Call Seconds" set to '-1' and the "Drop Action" set to 'IN_GROUP' then the first remote agent entry will be ignored for a campaign when the system calculates how many calls to place outbound.

When "Drop Call Seconds" set to '-1' in a campaign, and a call is answered by a customer, the system will not even look for an agent in that campaign to send a call to, it will immediately drop the call to the selected drop in-group. With the In-Group "No Delay Call Route" set to 'Y', the system will attempt to send the call to an agent as fast as possible.




THE PROBLEM OF "OVER-DIALING":

When you allow a single agent to have multiple calls placed for them, there can always be a problem with "over-dialing", even when only using a single campaign. This issue is more complicated though when that same level of dialing is happening across multiple campaigns. At a minimum, the campaign "Available Only Tally" settings should be the first things you check to see if they are active. Beyond that, there really are not any simple solutions for it. Because of this, we added a new campaign feature, detailed below.

We have added a new campaign dialing method "SHARED_..." that is specifically for shared agent campaigns that will operate somewhat like a round-robin system for shared agent campaign dialing. For instance, if only one agent is logged-in with dialing happening for that agent across 3 campaigns, each of those 3 campaigns would take turns dialing for that one agent. The number of calls would be calculated based on the number of agents that could take calls from each campaign, and the number of campaigns each agent is set to take calls from. This was a very complex project to complete, but it is the most efficient option with the best possibility for a balance between keeping agents on the phone and not dropping calls under all conditions(even single-agent dialing).







***********************  The following are notes for how the new "SHARED_..." campaign Dial Methods work:

NOTE: to use the new SHARED campaign dial method, you must first enable the "Shared Agent Campaign Dialing" System Setting.


How a "SHARED_..." dial methods work:

1. New code added to the AST_VDadapt.pl and AST_VDauto_dial.pl scripts that will(for agents logged into shared-dialing campaigns, for dialing purposes only) rotate them among the campaigns that they are able to take calls from, while still allowing them to have calls from any of those campaigns sent to them any time they are available.
2. Change the dialing algorithm(for campaigns with a "SHARED_" dial method only) to prevent over-dialing as agents are rotated from dialing-campaign to dialing-campaign.
3. The agent-dialing-campaign-rotation process attempts to balance agents by time(round-robin-like) across the campaigns that they are assigned to take calls from.
4. New database fields/tables were added to store the temporary dialing campaign designations for each agent and what other campaigns they had just been assigned to
5. Added shared debug output to existing Admin Utilities "Campaign Debug Report" that will show everything that is going on for shared campaigns in the process of agent rotation and shared outbound dialing
6. Added optional debugging and a new "vicidial_shared_log" DB table as well as "Shared Debug Page" to help with troubleshooting of the SHARED dialing processes
	*NOTE: the optional extra debugging is enabled by changing the "Shared Agent Campaign Dialing" System Setting to '2' or higher.

Agent rotation steps, added to the AST_VDadapt.pl script: (see new database changes below for details on the DB storage of this data)
- runs once every 1 minute
- for each agent, gather all campaigns they can dial for, and their current dial_campaign
- delete from vicidial_agent_dial_campaigns any campaigns agent is no longer dialing for, update validate_time for others
- grab oldest vicidial_agent_dial_campaigns.dial_time campaign_id for each agent and update vicidial_live_agents.dial_campaign_id then update dial_time
- set dial_campaign to ''(blank) if no active campaigns or agent had removed all drop in-groups
- at Timeclock-end-of-day, wipe out everything in vicidial_agent_dial_campaigns table older than 5 minutes and optimize table

Shared campaigns outbound dialing steps:
- gather all campaigns that are using a SHARED_ dial method, use that list to count current calls and calculate how many new calls can be placed for each of the shared campaigns
- when counting for agents in the campaign to dial for, use the vicidial_live_agents.dial_campaign_id field
- when allocating dials for each campaign, sort by:
	- campaign shared agent dial ranking field(vicidial_campaigns.shared_dial_rank) *then*
	- oldest agent call handled(vicidial_live_agents.last_call_time)



The following are instructions for how to set up a "SHARED_" set of campaigns:

1. Set up three campaigns: 
	SHIPENG(Shipping English)
	SHIPFRE(Shipping French)
	SHIPAGNT(Shipping All Agents)

2. Set up two lists:
	1201(Shipping English List), assigned to the SHIPENG campaign
	1202(Shipping French List), assigned to the SHIPFRE campaign

3. Set up two Inbound Groups to use as Drop In-Groups:
	DROP_SHIP_ENG(Shipping English Drop InGroup)
	DROP_SHIP_FRE(Shipping French Drop InGroup)
     * RECOMMENDATIONS:
		- You may want to set the In-Group "Drop Call Seconds" to a lower number and send the call to a Call Menu if no agent is available

4. Set the following settings on both the SHIPENG & SHIPFRE campaigns (these are your two outbound dialing campaigns)
     * Start by setting these campaigns up as you would to be normal outbound auto-dialing campaigns
	Dial Method: SHARED_ADAPT_AVERAGE or SHARED_RATIO
	Available Only Tally: Y
	Drop Call Seconds: -1
	Drop Action: IN_GROUP
	Drop Transfer Group: DROP_SHIP_ENG(for the SHIPENG campaign) or DROP_SHIP_FRE(for the SHIPFRE campaign)

5. Set the following settings on the SHIPAGNT campaign:
	Allow Inbound and Blended: Y
	Dial Method: RATIO
	Allow No-Hopper-Leads Logins: Y
	Allowed Inbound Groups: select both "DROP_SHIP_ENG" & "DROP_SHIP_FRE"
	* Do not assign any active lists to this campaign

6. Set the following settings on both the DROP_SHIP_ENG & DROP_SHIP_FRE inbound groups
	Welcome Message Filename: ---NONE---
	Play Welcome Message: NEVER
	No Delay Call Route: Y

7. All agents will log into the "SHIPAGNT" campaign and will select the "DROP_SHIP_ENG" and/or "DROP_SHIP_FRE" in-groups to take calls from as well as selecting the "BLENDED CALLING" checkbox when they log in, or managers can select those in-groups and the "Closer Default Blended" for the agents in the User Modify screen for those agents if they don't want their agents to have the ability to choose.


* NOTES: 
- The "SHARED_..." campaign dial method does not require the use of Remote Agents at all, and the live agents do need to select to take blended (outbound) calls or no calls will be placed for them as they rotate through the shared agent campaigns.
- For SHARED agent campaigns, there is an additional campaign setting: "Shared Dial Rank", which will allow you to prioritize the dialing of your shared campaigns as calls are placed for them.
- For SHARED agent campaigns, the vicidial_log table will show In-Group transfer drops as 'SRDROP' status instead of 'DROP' status to differentiate them from standard dialing campaign drops. These are not considered dropped calls at all because they were never attempted to be routed to an agent by the outbound campaign before being sent to the In-Group.
- For SHARED agent campaigns, the predictive algorithm will not count In-Group transfer drops as dropped calls in its statistical calculations





DATABASE CHANGES: !!!!!! FOR DOCUMENTATION PURPOSES ONLY !!!!!

ALTER TABLE system_settings ADD allow_shared_dial ENUM('0','1','2','3','4','5','6') default '0';

ALTER TABLE vicidial_campaigns ADD shared_dial_rank TINYINT(3) default '99';
ALTER TABLE vicidial_campaigns MODIFY dial_method ENUM('MANUAL','RATIO','ADAPT_HARD_LIMIT','ADAPT_TAPERED','ADAPT_AVERAGE','INBOUND_MAN','SHARED_RATIO','SHARED_ADAPT_HARD_LIMIT','SHARED_ADAPT_TAPERED','SHARED_ADAPT_AVERAGE') default 'MANUAL';

ALTER TABLE vicidial_live_agents ADD dial_campaign_id VARCHAR(8) default '';

CREATE TABLE vicidial_agent_dial_campaigns (
campaign_id VARCHAR(8),
group_id VARCHAR(20),
user VARCHAR(20),
validate_time DATETIME,
dial_time DATETIME,
index (user),
index (campaign_id)
) ENGINE=MyISAM;

CREATE UNIQUE INDEX vadc_key on vicidial_agent_dial_campaigns(campaign_id, user);

CREATE TABLE vicidial_shared_log (
campaign_id VARCHAR(20) NOT NULL,
server_ip VARCHAR(15) NOT NULL,
log_time DATETIME,
total_agents SMALLINT(5) default '0',
total_calls SMALLINT(5) default '0',
debug_output TEXT,
adapt_output TEXT,
index (campaign_id),
index (log_time)
) ENGINE=MyISAM;

CREATE TABLE vicidial_shared_drops (
callerid VARCHAR(20),
server_ip VARCHAR(15) NOT NULL,
campaign_id VARCHAR(20),
status ENUM('SENT','RINGING','LIVE','XFER','PAUSED','CLOSER','BUSY','DISCONNECT','IVR') default 'PAUSED',
lead_id INT(9) UNSIGNED NOT NULL,
uniqueid VARCHAR(20),
channel VARCHAR(100),
phone_code VARCHAR(10),
phone_number VARCHAR(18),
call_time DATETIME,
call_type ENUM('IN','OUT','OUTBALANCE') default 'OUT',
stage VARCHAR(20) default 'START',
last_update_time DATETIME,
alt_dial VARCHAR(6) default 'NONE',
drop_time DATETIME,
index (callerid),
index (call_time),
index (drop_time)
) ENGINE=MyISAM;
