<!-- Module User's Guide -->

<chapter>
	
	<title>&adminguide;</title>
	
	<section id="overview" xreflabel="Overview">
	<title>Overview</title>
	<para>
	The Call Center module implements an inbound call center system with call 
	flows (for queuing the received calls) and agents (for answering the 
	calls).
	</para>
	<para>
	The module implements the queuing system, the call distribution 
	to agents, agents managements, CDRs for the calls, statistics on 
	call distribution and agent's activity - basically everything 
	except the media playback (for the queue). This part must be provided via 
	a third party media server (FreeSwitch, Asterisk or others).
	</para>
	<para>
	This is actually a Contact Center and it is able to handle both
	RTP/audio calls and (multiple) MSRP/chat calls, in the same time.
	</para>
	<para>
	The module provides an internal buit-in dispatching logic (for sending the
	calls/chats to the agents), but also offers the possibility to use an
	external logic to do the dispatching
	(see <xref linkend="mi_cc_dispatch_call_to_agent"/> MI command).
	</para>
	</section>

	<section>
	<title>How it works</title>
	<para>
	The main entities in the modules are the flows (queues) and agents.
	</para>
		<section>
		<title>DB tables</title>
		<para>
		Each entity has a corresponding table in the database, for 
		provisioning purposes - the <emphasis>cc_flows</emphasis> and 
		<emphasis>cc_agents</emphasis> tables, see
		<ulink url='https://opensips.org/Documentation/Install-DBSchema--3-3#AEN2656'>DB schema</ulink>.
		Data is loaded at startup and cached into memory ; runtime reload is 
		possible via the MI commands (see the <emphasis>cc_reload</emphasis> 
		command in <xref linkend="exported_mi_functions"/>).
		</para>
		<para>
		Additionally there is a table <emphasis>cc_cdrs</emphasis> for writing 
		the CDRs - this operation is done in realtime, after the call in 
		completed, covering all possible cases: call was dropped while in 
		queue, call was rejected by agent, call was accepted by agent, call 
		terminated with error - NOTE that a call may generate more than one 
		CDR (like call rejected by agent A, and redistributed and accepted by 
		agent B).
		</para>
		<para>
		The <emphasis>cc_calls</emphasis> table is used to store ongoing calls,
		regardless it's state (in queue, to the agent, ended). It is populated
		at runtime by the module and queried at startup. This table should not
		be manually provisioned.
		</para>
		</section>

		<section>
		<title>Call Flows</title>
		<para>
		A flow is defined by a unique alphanumerical ID - the main attribute 
		of a flow is the <emphasis>skill</emphasis> - the skill is a 
		capability required by the flow for an agent to be able to answer the 
		call ; the concept of <emphasis>skills</emphasis> is the link between 
		the flows and the agents - telling what agents are serving what flows 
		- the flows require a skill, while the agents provide a set of skills. 
		Agents matching the required skill of a flow will automatically 
		receive calls from that flow.
		</para>
		<para>
		Additional, the flow has a <emphasis>priority</emphasis> - as agents 
		may server multiple flows in the same time (based on skills), you can
		define priorities between the flows - if the flows has a higher 
		priority, its calls will be pushed (in deliver to agents and queuing) in
		front of the calls from flows with a lower priority.
		</para>
		<para>
		Configurable per flow, the module may do per-flow call dissuading; this
		means to redirect a call to another destination, if the queue/flow 
		is overloaded:
		</para>
		<itemizedlist>
			<listitem>
			<para>if the number of calls already in the queue exceeds the diss_qsize_th threshold</para>
			</listitem>
			<listitem>
			<para>if the estimated time to wait of the queue exceeds the diss_ewt_th threshold</para>
			</listitem>
			<listitem>
			<para>if the call was waiting in the queue for longer than diss_onhold_th threshold</para>
			</listitem>
		</itemizedlist>
		<para>
		Optionally, the flow may define a <emphasis>prependcid</emphasis> - a
		prefix to be added to the CLI (Caller ID) when the call is delivered to
		the agents - as an agent may receive call from multiple flows, it is 
		important for the user to see which was the queue a call was received.
		</para>
		<para>
		In terms of media announcements, the flow defines the 
		<emphasis>message_welcome</emphasis> (optional, to be played in the 
		call, before doing anything with the call) and 
		<emphasis>message_queue</emphasis> (mandatory, the looping message
		providing infinite on hold media IMPORTANT - this message must cycle 
		and media server must never hung up on it. Both announcements are 
		provided as SIP URIs (where the call has to be sent in order to get
		the playback).
		</para>
		<para>
		The flow also has an optional <emphasis>max_wrapup time</emphasis>,
		which acts as an upper limit for the per-agent/global value (the flow 
		forces a ceiling of the wrapup value for all its calls).
		</para>
		</section>

		<section>
		<title>Agents</title>
		<para>
		An agent is defined by a unique alphanumerical ID - the main attribute 
		of an agent is its the set of <emphasis>skills</emphasis>. This set of
		skills will tell what calls to be received (from which flows, based on
		the skill matching).
		</para>
		<para>
		The agent may provide support for different optional media types, like
		RTP/audio or MSRP/chat. Each supported media type comes with the 
		maximum supported number of sessions. Of course, for audio the `1` 
		value is hardocded. On the SIP side, each media type comes with a
		<emphasis>locations</emphasis>. The location is a SIP URI where to 
		calls must be sent in order to be answered by the agent. At least one 
		media type should be defined. To specify which media the agent
		support, just define the corresponding SIP location in his profile.
		</para>
		<para>
		So, at a certain time, an agent may handle either a single call,
		either several chat sessions.
		</para>
		<para>
		Additionally, the agent has a initial <emphasis>logstate</emphasis> - 
		if he is logged in or not (being logged in is a must in order to
		receive calls). The log state may be changed at runtime via a 
		dedicated MI command <emphasis>cc_agent_login</emphasis>, see 
		<xref linkend="exported_mi_functions"/>.
		</para>
		<para>
		There is an optional per-agent <emphasis>wrapup_time</emphasis>
		defined, saying the time interval for an agent before getting a new 
		call from the system (after he finished a call). If no value is defined
		for the agent, the global <emphasis>wrapup_time</emphasis> will be 
		used. Note that the resulting value may be upper limited by the
		per-flow <emphasis>max_wrapup_time</emphasis> if defined.
		</para>
		</section>
	</section>


	<section id="dependencies" xreflabel="Dependencies">
	<title>Dependencies</title>
	<section>
		<title>&osips; Modules</title>
		<para>
		The following modules must be loaded before this module:
			<itemizedlist>
			<listitem>
			<para>
				<emphasis>b2b_logic</emphasis> - B2bUA module
			</para>
			</listitem>
			<listitem>
			<para>
				<emphasis>database</emphasis> - one of the SQL DB modules
			</para>
			</listitem>
			</itemizedlist>
		</para>
	</section>


	<section>
		<title>External Libraries or Applications</title>
		<para>
		The following libraries or applications must be installed before 
		running &osips; with this module loaded:
			<itemizedlist>
			<listitem>
			<para>
				<emphasis>None</emphasis>.
			</para>
			</listitem>
			</itemizedlist>
		</para>
	</section>
	</section>


	<section id="exported_parameters" xreflabel="Exported Parameters">
	<title>Exported Parameters</title>

	<section id="param_db_url" xreflabel="db_url">
		<title><varname>db_url</varname> (string)</title>
		<para>
		SQL address to the DB server -- database specific. This must be
		the Database holding the provisioning tables (cc_flows, cc_agents
		and cc_calls tables).
		</para>
		If not explicitly set, the global OpenSIPS DB URL will be used.
		<para>
		</para>
		<example>
		<title>Set <varname>db_url</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "db_url", 
	"mysql://opensips:opensipsrw@localhost/opensips")
...
</programlisting>
		</example>
	</section>

	<section id="param_acc_db_url" xreflabel="acc_db_url">
		<title><varname>acc_db_url</varname> (string)</title>
		<para>
		SQL address to the DB server -- database specific. This must be
		the Database where the CDRs table (cc_cdrs) is located.
		</para>
		If not explicitly set, the global OpenSIPS DB URL will be used.
		<para>
		</para>
		<example>
		<title>Set <varname>acc_db_url</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "acc_db_url", 
	"mysql://opensips:opensipsrw@localhost/opensips_cdrs")
...
</programlisting>
		</example>
	</section>

	<section id="param_rt_db_url" xreflabel="rt_db_url">
		<title><varname>rt_db_url</varname> (string)</title>
		<para>
		SQL address/URL of the DB server (database specific) where the
		runtime tables (non provisioning tables) are located. The
		runtime tables are the tables populated by OpenSIPS with data
		learned during runtime. To be more specific, the only runtime
		table we have so far is the "cc_calls" table.
		</para>
		If not explicitly set, the global OpenSIPS DB URL will be used.
		<para>
		</para>
		<example>
		<title>Set <varname>rt_db_url</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "rt_db_url", 
	"mysql://opensips:opensipsrw@localhost/opensips_runtime")
...
</programlisting>
		</example>
	</section>

	<section id="param_wrapup_time" xreflabel="wrapup_time">
		<title><varname>wrapup_time</varname> (integer)</title>
		<para>
		Time for an agent between finishing a call and receiving the next
		call from the system. Even if there are queued calls, the module
		will not deliver call to agent during this wrapup interval.
		</para>
		<para>
		This value may be overwritten by the per-agent value (if defined)
		and furher more, by the per-flow value (if defined).
		</para>
		<para>
		<emphasis>Default value is <quote>30 seconds</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>wrapup_time</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "wrapup_time", 45)
...
</programlisting>
		</example>
	</section>

	<section id="param_queue_pos_param" xreflabel="queue_pos_param">
		<title><varname>queue_pos_param</varname> (string)</title>
		<para>
		The name of an SIP URI parameter to be used to report the position
		in the waiting queue when sending the call to media server for
		onwait/queue playback. The position 0 means it is the next call
		to be delivered to an agent.
		</para>
		<para>
		<emphasis>Default value is <quote>empty(none)</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>queue_pos_param</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "queue_pos_param", "cc_pos")
...
</programlisting>
		</example>
	</section>

	<section id="param_reject_on_no_agents" xreflabel="reject_on_no_agents">
		<title><varname>reject_on_no_agents</varname> (int)</title>
		<para>
		A parameter to tell if an incoming call should be rejected or
		quueued if there are no logged in agents. Basically this allows
		call queueing on flows with no agents yet.
		</para>
		<para>
		<emphasis>Default value is <quote>1 (true)</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>reject_on_no_agents</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "reject_on_no_agents", 0)
...
</programlisting>
		</example>
	</section>

	<section id="param_chat_dispatch_policy" xreflabel="chat_dispatch_policy">
		<title><varname>chat_dispatch_policy</varname> (int)</title>
		<para>
		A parameter to tell what should be the policy on dispatching the
		chat/MSRP sessions to the agents, considering that an agent may
		handle multiple such sessions/chats in the same time.
		</para>
		<para>
		Options are:
		</para>
		<itemizedlist>
		<listitem>
			<para>
			<emphasis role='bold'>balancing </emphasis> - the distribution
			will try to be even across the agents, but by doing this you may 
			end up waisting chat sessions on agents and call starvation -
			agents are partially used by chat sessions, so they cannot take
			calls (of course, if you have mixed agetns with audio/chat)
			</para>
		</listitem>
		<listitem>
			<para>
			<emphasis role='bold'>full-load</emphasis> - the distribution
			will try to make usage of an agent in the best possible way when
			comes to chat sessions - once the agent take a chat, all the
			following chats will be assigned ot him - the idea is to try to 
			be efficient in using the resource/sessions of an agents, to leave
			as much room as possible for calls. Of course, this may lead to an
			un-even loading of chat agents - some will be full, others empty.
			</para>
		</listitem>
		</itemizedlist>
		<para>
		<emphasis>Default value is <quote>balancing</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>chat_dispatch_policy</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "chat_dispatch_policy", "balancing")
...
</programlisting>
		</example>
	</section>

	<section id="param_internal_call_dispatching" xreflabel="chat_internal_call_dispatching">
		<title><varname>internal_call_dispatching</varname> (int)</title>
		<para>
		A parameter to tell if the internal/buit-in call dispatching to agent
		should be used or not. If enabled, the module will automatically
		dispatch (by itself) the queued/incoming calls to the available agents.
		If disabled, the module will not do such dispaching by itself and it
		is expected to use the  <xref linkend="mi_cc_dispatch_call_to_agent"/>
		MI command to dispatch the queued calls to agents. This allows the
		implementation of an external, custom dispatching logic. The value of
		this setting may be changed during runtime via the 
		<xref linkend="mi_cc_internal_call_dispatching"/> MI command.
		</para>
		<para>
		<emphasis>Default value is <quote>1</quote> (enabled).
		</emphasis>
		</para>
		<example>
		<title>Set <varname>internal_call_dispatching</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "internal_call_dispatching", 0)
...
</programlisting>
		</example>
	</section>

	<section id="param_cc_agents_table" xreflabel="cc_agents_table">
		<title><varname>cc_agents_table</varname> (string)</title>
		<para>
		Name to be used for the table holding the agents.
		</para>
		<para>
		<emphasis>Default value is <quote>cc_agents</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cc_agents_table</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "cc_agents_table", "my_agents")
...
</programlisting>
		</example>
	</section>

	<section id="param_cca_agentid_column" xreflabel="cca_agentid_column">
		<title><varname>cca_agentid_column</varname> (string)</title>
		<para>
		Name to be used for the "agent id" (unique DB id) column in the
		agents table.
		</para>
		<para>
		<emphasis>Default value is <quote>agentid</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cca_agentid_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "cca_agentid_column", "cid")
...
</programlisting>
		</example>
	</section>

	<section id="param_cca_location_column" xreflabel="cca_location_column">
		<title><varname>cca_location_column</varname> (string)</title>
		<para>
		Name to be used for the calling/audio "location" (SIP URI) column in 
		the agents table.
		</para>
		<para>
		<emphasis>Default value is <quote>location</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cca_location_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "cca_location_column", "sip_uri")
...
</programlisting>
		</example>
	</section>

	<section id="param_cca_msrp_location_column" xreflabel="cca_msrp_location_column">
		<title><varname>cca_msrp_location_column</varname> (string)</title>
		<para>
		Name to be used for the msrp/chat "location" (SIP URI) column in the
		agents table.
		</para>
		<para>
		<emphasis>Default value is <quote>msrp_location</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cca_msrp_location_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "cca_msrp_location_column", "sip_uri")
...
</programlisting>
		</example>
	</section>

	<section id="param_cca_msrp_max_sessions_column" xreflabel="cca_msrp_max_sessions_column">
		<title><varname>cca_msrp_max_sessions_column</varname> (string)</title>
		<para>
		Name to be used for the column (in the agents table) holding the 
		maximum number of chat sessions that can be handled by the agent.
		</para>
		<para>
		<emphasis>Default value is <quote>msrp_max_sessions</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cca_msrp_max_sessions_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "cca_msrp_max_sessions_column", "max_chats")
...
</programlisting>
		</example>
	</section>

	<section id="param_cca_skills_column" xreflabel="cca_skills_column">
		<title><varname>cca_skills_column</varname> (string)</title>
		<para>
		Name to be used for the "skills" (list of skills) column in the
		agents table.
		</para>
		<para>
		<emphasis>Default value is <quote>skills</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cca_skills_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "cca_skills_column", "skills")
...
</programlisting>
		</example>
	</section>

	<section id="param_cca_logstate_column" xreflabel="cca_logstate_column">
		<title><varname>cca_logstate_column</varname> (string)</title>
		<para>
		Name to be used for the "logstate" (original login state) column in the
		agents table.
		</para>
		<para>
		<emphasis>Default value is <quote>logstate</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cca_logstate_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "cca_logstate_column", "log_state")
...
</programlisting>
		</example>
	</section>

	<section id="param_cca_wrapuptime_column" xreflabel="cca_wrapuptime_column">
		<title><varname>cca_wrapuptime_column</varname> (string)</title>
		<para>
		Name to be used for the "wrapuptime" (per-agent wrapup time) column 
		in the agents table.
		</para>
		<para>
		<emphasis>Default value is <quote>wrapup_time</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cca_wrapuptime_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "cca_wrapuptime_column", "wtime")
...
</programlisting>
		</example>
	</section>

	<section id="param_cca_wrapupend_column" xreflabel="cca_wrapupend_column">
		<title><varname>cca_wrapupend_column</varname> (string)</title>
		<para>
		Name to be used for the "wrapupend" (timestamp when the wrapup ends) 
		column in the agents table.
		</para>
		<para>
		<emphasis>Default value is <quote>wrapup_end_time</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cca_wrapupend_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "cca_wrapupend_column", "wrapup_ends")
...
</programlisting>
		</example>
	</section>

	<section id="param_cc_flows_table" xreflabel="cc_flows_table">
		<title><varname>cc_flows_table</varname> (string)</title>
		<para>
		Name to be used for the table holding the definition of the
		flows/queues.
		</para>
		<para>
		<emphasis>Default value is <quote>cc_flows</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>cc_flows_table</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "cc_flows_table", "queues")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_flowid_column" xreflabel="ccf_flowid_column">
		<title><varname>ccf_flowid_column</varname> (string)</title>
		<para>
		Name to be used for the "flow id" (unique DB id) column in the
		flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>flowid</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_flowid_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_flowid_column", "queue_id")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_priority_column" xreflabel="ccf_priority_column">
		<title><varname>ccf_priority_column</varname> (string)</title>
		<para>
		Name to be used for the "priority" column in the
		flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>priority</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_priority_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_priority_column", "queue_prio")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_skill_column" xreflabel="ccf_skill_column">
		<title><varname>ccf_skill_column</varname> (string)</title>
		<para>
		Name to be used for the "skill" column in the
		flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>skill</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_skill_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_skill_column", "queue_skill")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_cid_column" xreflabel="ccf_cid_column">
		<title><varname>ccf_cid_column</varname> (string)</title>
		<para>
		Name to be used for the "caller ID prefix" column in the
		flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>prependcid</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_cid_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_cid_column", "queue_cli_prefix")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_max_wrapup_column" xreflabel="ccf_max_wrapup_column">
		<title><varname>ccf_max_wrapup_column</varname> (string)</title>
		<para>
		Name to be used for the "max limit for wrapup time" column in the
		flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>max_wrapup_time</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_max_wrapup_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_max_wrapup_column", "queue_wrapup")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_dissuading_hangup_column" xreflabel="ccf_dissuading_hangup_column">
		<title><varname>ccf_dissuading_hangup_column</varname> (string)</title>
		<para>
		Name to be used for the "hangup after dissuading" column in the
		flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>dissuading_hangup</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_dissuading_hangup_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_dissuading_hangup_column", "hangup_on_dissuading")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_dissuading_onhold_th_column" xreflabel="ccf_dissuading_onhold_th_column">
		<title><varname>ccf_dissuading_onhold_th_column</varname> (string)</title>
		<para>
		Name to be used for the "on-hold dissuading threshold" column in the
		flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>dissuading_onhold_th</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_dissuading_onhold_th_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_dissuading_onhold_th_column", "th_diss_onhold")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_dissuading_ewt_th_column" xreflabel="ccf_dissuading_ewt_th_column">
		<title><varname>ccf_dissuading_ewt_th_column</varname> (string)</title>
		<para>
		Name to be used for the "EWT dissuading threshold" column in the
		flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>dissuading_ewt_th</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_dissuading_ewt_th_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_dissuading_ewt_th_column", "th_diss_ewt")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_dissuading_qsize_th_column" xreflabel="ccf_dissuading_qsize_th_column">
		<title><varname>ccf_dissuading_qsize_th_column</varname> (string)</title>
		<para>
		Name to be used for the "queue size dissuading threshold" column in the
		flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>dissuading_qsize_th</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_dissuading_qsize_th_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_dissuading_qsize_th_column", "th_diss_qsize")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_m_welcome_column" xreflabel="ccf_m_welcome_column">
		<title><varname>ccf_m_welcome_column</varname> (string)</title>
		<para>
		Name to be used for the "audio message on welcome" column in the
		flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>message_welcome</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_m_welcome_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_m_welcome_column", "audio_welcome")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_m_queue_column" xreflabel="ccf_m_queue_column">
		<title><varname>ccf_m_queue_column</varname> (string)</title>
		<para>
		Name to be used for the "audio message on queueing" column in the
		flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>message_queue</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_m_queue_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_m_queue_column", "audio_queue")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_m_dissuading_column" xreflabel="ccf_m_dissuading_column">
		<title><varname>ccf_m_dissuading_column</varname> (string)</title>
		<para>
		Name to be used for the "audio message on dissuading" column in the
		flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>message_dissuading</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_m_dissuading_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_m_dissuading_column", "audio_dissuading")
...
</programlisting>
		</example>
	</section>

	<section id="param_ccf_m_flow_id_column" xreflabel="ccf_m_flow_id_column">
		<title><varname>ccf_m_flow_id_column</varname> (string)</title>
		<para>
		Name to be used for the "audio message on identifying the flow" column
		in the flows table.
		</para>
		<para>
		<emphasis>Default value is <quote>message_flow_id</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>ccf_m_flow_id_column</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "ccf_m_flow_id_column", "audio_flow_id")
...
</programlisting>
		</example>
	</section>

	<section id="param_b2b_logic_ctx_param" xreflabel="b2b_logic_ctx_param">
		<title><varname>b2b_logic_ctx_param</varname> (string)</title>
		<para>
		The name of the <emphasis>$b2b_logic.ctx</emphasis> variable that can be
		used to retrieve the value of the parameter passed to
		the <xref linkend="func_cc_handle_call"/> function.
		</para>
		<para>
		This parameter will be copied throughout all the B2B scenarios started
		by the call_center module. NOTE that you can change the value of the current
		scenario by writing into it, but the change will not be reflected in a
		different scenario.
		</para>
		<para>
		<emphasis>Default value is <quote>call_center</quote>.
		</emphasis>
		</para>
		<example>
		<title>Set <varname>b2b_logic_ctx_param</varname> parameter</title>
		<programlisting format="linespecific">
...
modparam("call_center", "b2b_logic_ctx_param", "b2b_callid")
...
route[handle_call_center] {
    ...
    cc_handle_call("flow", $ci);
    ...
}
...
route[b2b_handle_request] {
    ...
    xlog("Initial Callid is $b2b_logic.ctx(b2b_callid)\n");
    ...
}
</programlisting>
		</example>
	</section>

</section>


	<section id="exported_functions" xreflabel="exported_functions">
	<title>Exported Functions</title>
	<section id="func_cc_handle_call" xreflabel="cc_handle_call">
		<title>
		<function>cc_handle_call( flowID [,param])</function>
		</title>
		<para>
		This must be used only for initial INVITE requests - the function
		pushes the call to be handled by the call center module (via a certain
		flow/queue).
		</para>
		<para>
		This function can be used from REQUEST_ROUTE.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>flowID (string)</emphasis> - the ID of the flow to
				handle this call (push the call to that flow).
			</para></listitem>
			<listitem><para>
				<emphasis>param (string, optional)</emphasis> - an opaque
				string to be passed as parameter to the "callcenter" and 
				"agent" B2B scenarios. It is
				intended for custom integration of the call center module and 
				it is 100% up to the script writer about the value and purpose
				of this parameter, OpenSIPS will not touch or interpret it.
				You can retrieve the value of this parameter using the
				<emphasis>$b2b_logic.ctx</emphasis> variable with the name
				defined in the <xref linkend="param_b2b_logic_ctx_param"/>
				parameter.
			</para></listitem>
		</itemizedlist>
		<para>
		The function returns TRUE back to the script if the call was 
		successfully pushed and handled by the Call Center engine. IMPORTANT: 
		you must not do any signaling on the call (reply, relay) after this
		point.
		</para>
		<para>
		In case of error, FALSE is returned to the script with the following 
		return codes:
		</para>
		<itemizedlist>
			<listitem><para>
			<emphasis role='bold'>-1</emphasis> - unable to get the flow ID
			from the parameter;
			</para></listitem>
			<listitem><para>
			<emphasis role='bold'>-2</emphasis> - unable to parse the FROM URI;
			</para></listitem>
			<listitem><para>
			<emphasis role='bold'>-3</emphasis> - flow with FlowID not found;
			</para></listitem>
			<listitem><para>
			<emphasis role='bold'>-4</emphasis> - no agents logged in the flow;
			</para></listitem>
			<listitem><para>
			<emphasis role='bold'>-5</emphasis> - internal error;
			</para></listitem>
		</itemizedlist>
		<example>
		<title><function>cc_handle_call</function> usage</title>
		<programlisting format="linespecific">
...
if (is_method("INVITE") and !has_totag()) {
	if (!cc_handle_call("tech_support")) {
		send_reply(403,"Cannot handle call");
		exit;
	}
}
...
</programlisting>
		</example>
	</section>

	<section id="func_cc_agent_login" xreflabel="cc_agent_login">
		<title>
		<function>cc_agent_login(agentID, state)</function>
		</title>
		<para>
		This function sets the login (on or off) state for an agent.
		</para>
		<para>
		This function can be used from REQUEST_ROUTE.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>agentID (string)</emphasis> - the ID of the agent
			</para></listitem>
			<listitem><para>
				<emphasis>state (int)</emphasis> - an integer value giving
				the new state - 0 means logged off, anything else means logged in.
			</para></listitem>
		</itemizedlist>
		<example>
		<title><function>cc_agent_login</function> usage</title>
		<programlisting format="linespecific">
...
# log off the 'agentX' agent
cc_agent_login("agentX",0);
...
</programlisting>
		</example>
	</section>

	</section>


	<section>
	<title>Exported Statistics</title>

	<section>
	<title>Global statistics</title>
		<section id="stat_ccg_incalls" xreflabel="ccg_incalls">
		<title>ccg_incalls</title>
			<para>
			Total number of received calls. (counter type)
			</para>
		</section>

		<section id="stat_ccg_awt" xreflabel="ccg_awt">
		<title>ccg_awt</title>
			<para>
			Global avg. waiting time for calls. (realtime type)
			</para>
		</section>

		<section id="stat_ccg_load" xreflabel="ccg_load">
		<title>ccg_load</title>
			<para>
			Global load (across all flows). (realtime type)
			</para>
		</section>

		<section id="stat_ccg_distributed_incalls" xreflabel="ccg_distributed_incalls">
		<title>ccg_distributed_incalls</title>
			<para>
			Total number of distributed calls. (counter type)
			</para>
		</section>

		<section id="stat_ccg_answered_incalls" xreflabel="ccg_answered_incalls">
		<title>ccg_answered_incalls</title>
			<para>
			Total number of calls (audio/RTP and chat/MSRP) answered by agents. (counter type)
			</para>
		</section>

		<section id="stat_ccg_answered_inchats" xreflabel="ccg_answered_inchats">
		<title>ccg_answered_inchats</title>
			<para>
			Total number of chat/MSRP only calls answered by agents. (counter type)
			</para>
		</section>

		<section id="stat_ccg_abandonned_incalls" xreflabel="ccg_abandonned_incalls">
		<title>ccg_abandonned_incalls</title>
			<para>
			Total number of calls terminated by caller before being
			answered by agents. (counter type)
			</para>
		</section>

		<section id="stat_ccg_onhold_calls" xreflabel="ccg_onhold_calls">
		<title>ccg_onhold_calls</title>
			<para>
			Total number of calls (audio/RTP and chat/MSRP) in the queues (onhold). (realtime type)
			</para>
		</section>

		<section id="stat_ccg_onhold_chats" xreflabel="ccg_onhold_chats">
		<title>ccg_onhold_chats</title>
			<para>
			Total number of chat/MSRP only calls in the queues (onhold). (realtime type)
			</para>
		</section>

		<section id="stat_ccg_free_agents" xreflabel="ccg_free_agents">
		<title>ccg_free_agents</title>
			<para>
			Total number of free agents (across all flows). (realtime type)
			</para>
		</section>
	</section>

	<section>
	<title>Per-flow statistics (one set for each flow)</title>
		<section id="stat_ccf_incalls_flowID" xreflabel="ccf_incalls_flowID">
		<title>ccf_incalls_flowID</title>
			<para>
			Number of received calls for the flow. (counter type)
			</para>
		</section>

		<section id="stat_ccf_dist_incalls_flowID" xreflabel="ccf_dist_incalls_flowID">
		<title>ccf_dist_incalls_flowID</title>
			<para>
			Number of distributed calls in this flow. (counter type)
			</para>
		</section>

		<section id="stat_ccf_answ_incalls_flowID" xreflabel="ccf_answ_incalls_flowID">
		<title>ccf_answ_incalls_flowID</title>
			<para>
			Nnumber of calls (audio/RTP and chat/MSRP) from the flow answered by agents. (counter type)
			</para>
		</section>

		<section id="stat_ccf_answ_inchats_flowID" xreflabel="ccf_answ_incalls_flowID">
		<title>ccf_answ_incalls_flowID</title>
			<para>
			Nnumber of chat/MSRP only calls from the flow answered by agents. (counter type)
			</para>
		</section>

		<section id="stat_ccf_aban_incalls_flowID" xreflabel="ccf_aban_incalls_flowID">
		<title>ccf_aban_incalls_flowID</title>
			<para>
			Number of calls (from the flow) terminated by caller before being
			answered by agents. (counter type)
			</para>
		</section>

		<section id="stat_ccf_onhold_incalls_flowID" xreflabel="ccf_onhold_incalls_flowID">
		<title>ccf_onhold_incalls_flowID</title>
			<para>
			Number of calls (audio/RTP and chat/MSRP) -from the flow- which are onhold.
			 (realtime type)
			</para>
		</section>

		<section id="stat_ccf_onhold_inchats_flowID" xreflabel="ccf_onhold_inchats_flowID">
		<title>ccf_onhold_inchats_flowID</title>
			<para>
			Number of chat/MSRP only calls -from the flow- which are onhold.
			 (realtime type)
			</para>
		</section>

		<section id="stat_ccf_queued_calls_flowID" xreflabel="ccf_queued_calls_flowID">
		<title>ccf_queued_calls_flowID</title>
			<para>
			Number of calls which are queued for this flow. (realtime type)
			</para>
		</section>

		<section id="stat_ccf_free_agents_flowID" xreflabel="ccf_free_agents_flowID">
		<title>ccf_free_agents_flowID</title>
			<para>
			Number of free agents serving this flow. (realtime type)
			</para>
		</section>

		<section id="stat_ccf_etw_flowID" xreflabel="ccf_etw_flowID">
		<title>ccf_etw_flowID</title>
			<para>
			Estimated Time to Wait for this flow. (realtime type)
			</para>
		</section>

		<section id="stat_ccf_awt_flowID" xreflabel="ccf_awt_flowID">
		<title>ccf_awt_flowID</title>
			<para>
			Avg. Wating Time for this flow. (realtime type)
			</para>
		</section>

		<section id="stat_ccg_load_flowID" xreflabel="ccg_load_flowID">
		<title>ccg_load_flowID</title>
			<para>
			The load on the flow (number of queued calls versus number of
			logged agents). (realtime type)
			</para>
		</section>
	</section>

	<section>
	<title>Per-agent statistics (one set for each agent)</title>
		<section id="stat_cca_dist_incalls_agnetID" xreflabel="cca_dist_incalls_agnetID">
		<title>cca_dist_incalls_agnetID</title>
			<para>
			Number of distributed calls to this agent. (counter type)
			</para>
		</section>

		<section id="stat_cca_answ_incalls_agentID" xreflabel="cca_answ_incalls_agentID">
		<title>cca_answ_incalls_agentID</title>
			<para>
			Number of calls (audio/RTP and chat/MSRP) answered by the agent. (counter type)
			</para>
		</section>

		<section id="stat_cca_answ_inchats_agentID" xreflabel="cca_answ_inchats_agentID">
		<title>cca_answ_inchats_agentID</title>
			<para>
			Number of chat/MSRP only calls answered by the agent. (counter type)
			</para>
		</section>

		<section id="stat_cca_aban_incalls_agentID" xreflabel="cca_aban_incalls_agentID">
		<title>cca_aban_incalls_agentID</title>
			<para>
			Number of calls (sent to this agent) terminated by caller before 
			being answered by agents. (counter type)
			</para>
		</section>

		<section id="stat_cca_att_agentID" xreflabel="cca_att_agentID">
		<title>cca_att_agentID</title>
			<para>
			Avg. Talk Time for this agent (realtime type)
			</para>
		</section>
	</section>

	</section>


	<section id="exported_mi_functions" xreflabel="Exported MI Functions">
	<title>Exported MI Functions</title>

	<section id="mi_cc_reload" xreflabel="cc_reload">
		<title>
		<function moreinfo="none">cc_reload</function>
		</title>
		<para>
		Command to reload flows and agents definition from database.
		</para>
		<para>
			It takes no parameter.
		</para>
		<para>
		MI FIFO Command usage:
		</para>
		<programlisting  format="linespecific">
opensips-cli -x mi cc_reload
</programlisting>
	</section>

	<section id="mi_cc_agent_login" xreflabel="cc_agent_login">
		<title>
		<function moreinfo="none">cc_agent_login</function>
		</title>
		<para>
		Command to login an agent into the Call Center engine.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>agent_id</emphasis> - ID of the agent
			</para></listitem>
			<listitem><para>
				<emphasis>state</emphasis> - the new login state (0 - log off, 1 - log in)
			</para></listitem>
		</itemizedlist>
		<para>
		MI FIFO Command usage:
		</para>
		<programlisting  format="linespecific">
opensips-cli -x mi cc_agent_login agentX 0
</programlisting>
	</section>

	<section id="mi_cc_list_queue" xreflabel="cc_list_queue">
		<title>
		<function moreinfo="none">cc_list_queue</function>
		</title>
		<para>
		Command to list all the calls in queuing - for each call, the 
		following attributes will be printed: the call id, the calling
		user info, the flow of the call, for how
		long the call is in the queue, the ETW for the call, call priority 
		and the call skill (inherited from the flow).
		</para>
		<para>
		It takes no parameter.
		</para>
		<para>
		MI FIFO Command usage:
		</para>
		<programlisting  format="linespecific">
opensips-cli -x mi cc_list_queue
</programlisting>
	</section>

	<section id="mi_cc_list_flows" xreflabel="cc_list_flows">
		<title>
		<function moreinfo="none">cc_list_flows</function>
		</title>
		<para>
		Command to list all the flows - for each flow, the 
		following attributes will be printed: the flow ID, the avg. call 
		duration, how many calls were processed, how many agents are logged, 
		and how many onging calls are.
		</para>
		<para>
		It takes no parameter.
		</para>
		<para>
		MI FIFO Command usage:
		</para>
		<programlisting  format="linespecific">
opensips-cli -x mi cc_list_flows
</programlisting>
	</section>

	<section id="mi_cc_list_agents" xreflabel="cc_list_agents">
		<title>
		<function moreinfo="none">cc_list_agents</function>
		</title>
		<para>
		Command to list all the agents - for each agent, the 
		following attributes will be printed: agent ID, agent login state,
		agent state (free, wrapup, incall) and info on ongoing sessions.
		</para>
		<para>
		It takes no parameter.
		</para>
		<para>
		MI FIFO Command usage:
		</para>
		<programlisting  format="linespecific">
opensips-cli -x mi cc_list_agents
</programlisting>
	</section>

	<section id="mi_cc_list_calls" xreflabel="cc_list_calls">
		<title>
		<function moreinfo="none">cc_list_calls</function>
		</title>
		<para>
		Command to list all the ongoing calls - for each call, the 
		following attributes will be printed: call ID, call state 
		(welcome, queued, toagent, ended), call duration, flow it belongs to,
		agent serving the call (if any).
		</para>
		<para>
		It takes no parameter.
		</para>
		<para>
		MI FIFO Command usage:
		</para>
		<programlisting  format="linespecific">
opensips-cli -x mi cc_list_agents
</programlisting>
	</section>

	<section id="mi_cc_dispatch_call_to_agent" xreflabel="cc_dispatch_call_to_agent">
		<title>
		<function moreinfo="none">cc_dispatch_call_to_agent</function>
		</title>
		<para>
		This function sends a given call (from the queue) to a given agent. For
		the operation to succeed, several conditions must be met:
		</para>
		<itemizedlist>
			<listitem><para>
			the call must be in the queue
			</para></listitem>
			<listitem><para>
			the agent must be logged in
			</para></listitem>
			<listitem><para>
			the agent must support the skill required by the call
			</para></listitem>
			<listitem><para>
			the agent must support the media (RTP/MSRP) requiref by the call
			</para></listitem>
			<listitem><para>
			the agent must have available sessions for the requested media
			</para></listitem>
		</itemizedlist>
		<para>
		It takes two parameters.
		</para>
		<itemizedlist>
			<listitem><para>
			<emphasis>call_id</emphasis> - the ID of the call, as provided by
			the queue listing MI command <xref linkend="mi_cc_list_queue"/>
			</para></listitem>
			<listitem><para>
			<emphasis>agent_id</emphasis> - the ID of the call, as provided by
			the agents listing MI command <xref linkend="mi_cc_list_agents"/>
			</para></listitem>
		</itemizedlist>
		<para>
		IMPORTANT: in order to be used, you need to be sure that the internal
		call dispatching is DISABLED via the
		<xref linkend="param_internal_call_dispatching"/> module parameter
		or the <xref linkend="mi_cc_internal_call_dispatching"/> MI command.
		</para>
		<para>
		MI FIFO Command usage:
		</para>
		<programlisting  format="linespecific">
opensips-cli -x mi cc_dispatch_call_to_agent B2B452.dee2.33 agentX
</programlisting>
	</section>

	<section id="mi_cc_internal_call_dispatching" xreflabel="cc_internal_call_dispatching">
		<title>
		<function moreinfo="none">cc_internal_call_dispatching</function>
		</title>
		<para>
		Command to inspect and/or change the 
		<xref linkend="param_internal_call_dispatching"/> setting
		</para>
		<para>
		It takes one optional parameter <varname>dispatching</varname> if the
		value of the setting should be changed. A 0 value means disabling
		the internal dispatching, a non zero means to enable it.
		</para>
		<para>
		MI FIFO Command usage:
		</para>
		<programlisting  format="linespecific">
opensips-cli -x mi cc_internal_call_dispatching 0
</programlisting>
	</section>


	<section id="mi_cc_reset_stats" xreflabel="cc_reset_stats">
		<title>
		<function moreinfo="none">cc_reset_stats</function>
		</title>
		<para>
		Command to reset all counter-like statistics.
		</para>
		<para>
		It takes no parameter.
		</para>
		<para>
		MI FIFO Command usage:
		</para>
		<programlisting  format="linespecific">
opensips-cli -x mi cc_reset_stats
</programlisting>
	</section>

	</section>

	<section id="exported_events" xreflabel="Exported Events">
	<title>Exported Events</title>
	<section id="event_E_CALLCENTER_AGENT_REPORT" xreflabel="E_CALLCENTER_AGENT_REPORT">
		<title>
		<function moreinfo="none">E_CALLCENTER_AGENT_REPORT</function>
		</title>
		<para>
			This event is raised when the status of an agent changes.
		</para>
		<para>Parameters:</para>
		<itemizedlist>
			<listitem><para>
				<emphasis>agent_id</emphasis> - the id of the agent.
			</para></listitem>
			<listitem><para>
				<emphasis>state</emphasis> - the status of the agent:
				<itemizedlist>
					<listitem>offline</listitem>
					<listitem>free</listitem>
					<listitem>incall</listitem>
					<listitem>wrapup</listitem>
				</itemizedlist>
			</para></listitem>
			<listitem><para>
				<emphasis>wrapup_ends</emphasis> - the timestamp when the 
				wrapup state will end; published only if the state is 
				"wrapup"
			</para></listitem>
			<listitem><para>
				<emphasis>flow_id</emphasis> - the flow ID that delivered the
				call for this agent; published only if the state is "incall"
			</para></listitem>
		</itemizedlist>
	</section>
	</section>


	<section id="exported_pseudo_variables">
	<title>Exported Pseudo-Variables</title>
	<para>
		<section id="pv_cc_state" xreflabel="$cc_state">
			<title><function moreinfo="none">$cc_state</function></title>
			<para>
			Returns the state of a call.
			</para>
			<para>
				Possible values returned are:
				<para>
				<itemizedlist>
					<listitem><para>
					<emphasis>welcome</emphasis> - the welcome message is played.
					</para></listitem>
					<listitem><para>
					<emphasis>dissuading1</emphasis> - the first dissuading message is played.
					</para></listitem>
					<listitem><para>
					<emphasis>dissuading2</emphasis> - the second dissuading message is played.
					</para></listitem>
					<listitem><para>
					<emphasis>queue</emphasis> - the call is in queue.
					</para></listitem>
					<listitem><para>
					<emphasis>preagent</emphasis> - the agent is being called.
					</para></listitem>
					<listitem><para>
					<emphasis>toagent</emphasis> - the agent is in call.
					</para></listitem>
				</itemizedlist>
				</para>
			</para>

		<example>
		<title>$rtpquery Usage</title>
		<programlisting format="linespecific">
...
	$json(reply) := $rtpquery;
	xlog("Total RTP Stats: $json(reply/totals)\n");
...
		</programlisting>
		</example>
		</section>
	NONE
	</para>
	</section>



</chapter>

