viernes, 31 de marzo de 2017

IVR-Base de datos.

                                                       IVR-Base de datos.


En esta entrada vamos a probar el Elastix (RIP) en su versión 4, obviamente esta configuración es válida para Asterisk.

No explicare cómo funciona el dialplan, pero si tienen alguna duda o comentario estoy más que a la orden.

Podremos ver como recoger datos de una llamada activa, convertirlas en variables y consultar una base de datos.

Para la administración de base de datos, usaremos MysqlWorkbench.

Escenario

Supongamos que tenemos un cliente que nos solicita un sistema que pueda informar el saldo o balance de su cuenta con las siguientes condiciones, que el usuario debe ingresar su cédula, número de tarjeta y pin de la tarjeta.

Planificación

Necesitaremos una BD  y una tabla que incluya los siguientes campos.
Columns:
id
mediumint(8) UN AI PK
nombre
varchar(255)
pin
varchar(255)
cedula
mediumint(9)
saldo
mediumint(9)
tarjeta
varchar(255)

En la que:
Id = lo usaremos para identificar nuestros registros
Nombre = Nombre del “cliente”
Pin = pin de la tarjeta
Cedula = cedula del cliente
Saldo = al saldo o balance de la tarjeta

Tarjeta = número de la tarjeta


Crear base de datos

Se utilizó el programa MySQL Workbench 6.3 para administrar tablas y columnas, solamente se creó la base de datos directamente desde el servidor.
MariaDB [(none)]> CREATE DATABASE ivr;


















Crear tabla desde el workbench

use ivr ;

CREATE TABLE `consultasaldo` (
  `id` mediumint(8) unsigned NOT NULL auto_increment,
  `nombre` varchar(255) default NULL,
  `pin` varchar(255),
  `cedula` mediumint,
  `saldo` mediumint,
  `tarjeta` varchar(255),
  PRIMARY KEY (`id`)
) AUTO_INCREMENT=1;


Una vez creada podemos hacer un insert con estos datos ficticios

INSERT INTO `consultasaldo` (`nombre`,`pin`,`cedula`,`saldo`,`tarjeta`) VALUES ("Xenos Roberts","1952",1000000,80000,"5289189197495478"),("Guy Frank","8389",999999,81024,"5436838962304701"),("Emerson Holmes","4782",999998,82048,"5155538874222442"),("Yasir Weaver","9586",999997,83072,"5186691021189338"),("Melvin Cherry","4720",999996,84096,"5180135775111516"),("Barry English","9178",999995,85120,"5349546772192739"),("Hunter Richardson","9562",999994,86144,"5466555386389950"),("Axel Manning","6411",999993,87168,"5359126912999017"),("Theodore Hewitt","9652",999992,88192,"5595052758928809"),("Ryan Mathews","4238",999991,89216,"5397617379840847");
INSERT INTO `consultasaldo` (`nombre`,`pin`,`cedula`,`saldo`,`tarjeta`) VALUES ("Kadeem Wise","4424",999990,90240,"5262521203855678"),("Amir Moore","7425",999989,91264,"5515504504631274"),("Zachery Rush","4026",999988,92288,"5214467948709599"),("Owen Acosta","9237",999987,93312,"5394424055023837"),("Thomas Humphrey","1862",999986,94336,"5210261440457938"),("Brody Price","4204",999985,95360,"5179830329339471"),("Carlos Pate","8850",999984,96384,"5170245525180711"),("Hamish May","8665",999983,97408,"5592949789982981"),("Kelly Randolph","5642",999982,98432,"5246184054233767"),("Carson Sanford","3767",999981,99456,"5444155212685106");
INSERT INTO `consultasaldo` (`nombre`,`pin`,`cedula`,`saldo`,`tarjeta`) VALUES ("Gil Floyd","6166",999980,100480,"5376146073834331"),("Magee Blake","9055",999979,101504,"5598438636321506"),("Orlando English","1618",999978,102528,"5238654392494206"),("Fitzgerald Rowe","4091",999977,103552,"5248539462448588"),("Keane Acevedo","6316",999976,104576,"5552578747064257"),("Drake Marks","6416",999975,105600,"5138958716344026"),("Malik Hopper","3878",999974,106624,"5107597067455580"),("Bernard Guy","7858",999973,107648,"5261651118979486"),("Dustin Hansen","6362",999972,108672,"5158442295882149"),("Luke Lloyd","7472",999971,109696,"5498234418380278");
INSERT INTO `consultasaldo` (`nombre`,`pin`,`cedula`,`saldo`,`tarjeta`) VALUES ("Len Robles","3709",999970,110720,"5457028537674671"),("Jarrod Morrow","9042",999969,111744,"5385908990305110"),("Edward Clayton","2363",999968,112768,"5588240865228879"),("Gil Vinson","7445",999967,113792,"5113413916883810"),("Timothy Martinez","7872",999966,114816,"5298387836098591"),("Eagan Mcguire","4716",999965,115840,"5218231580055778"),("Neville Murphy","6624",999964,116864,"5293502129315628"),("Reese Beach","4057",999963,117888,"5213316124149586"),("Gregory Greer","1993",999962,118912,"5158806017106179"),("Luke Gibbs","8196",999961,119936,"5161291984172709");
INSERT INTO `consultasaldo` (`nombre`,`pin`,`cedula`,`saldo`,`tarjeta`) VALUES ("Beau Roberts","1788",999960,120960,"5547320719416324"),("Plato Holden","7419",999959,121984,"5148903468672206"),("Dolan Morton","6123",999958,123008,"5304883078566933"),("Harlan Chapman","4581",999957,124032,"5392890294932982"),("Arthur Hodges","4999",999956,125056,"5501126047856287"),("Neville Leach","5887",999955,126080,"5387833156909307"),("Arthur Ramos","4812",999954,127104,"5466988998779856"),("Eric Jennings","8802",999953,128128,"5317955419069796"),("Caleb Hicks","3165",999952,129152,"5539285538412640"),("Dante Glass","1240",999951,130176,"5137047782361246");
INSERT INTO `consultasaldo` (`nombre`,`pin`,`cedula`,`saldo`,`tarjeta`) VALUES ("Hilel Contreras","9898",999950,131200,"5321234985072723"),("Tate Nichols","1693",999949,132224,"5225869336507328"),("Orlando Charles","5089",999948,133248,"5472072920453484"),("Xanthus Greene","8858",999947,134272,"5120783054550939"),("Blaze Gallegos","2972",999946,135296,"5465844945581039"),("Preston Jennings","3220",999945,136320,"5381391602559560"),("Ahmed Finch","5834",999944,137344,"5295257867273780"),("Neville Barrera","5245",999943,138368,"5498456936002205"),("Tate Dodson","3479",999942,139392,"5104169348708402"),("Hedley Fleming","8154",999941,140416,"5130550582437287");
INSERT INTO `consultasaldo` (`nombre`,`pin`,`cedula`,`saldo`,`tarjeta`) VALUES ("Hu Kerr","8086",999940,141440,"5324878619549493"),("Lewis Donaldson","4945",999939,142464,"5531667004122332"),("Ferdinand Odonnell","8314",999938,143488,"5418431798967081"),("Brennan Spence","7270",999937,144512,"5208910056062648"),("Dean Ratliff","6697",999936,145536,"5386174646777413"),("Hashim Cunningham","7881",999935,146560,"5449221367896032"),("Louis Palmer","9554",999934,147584,"5252682399768901"),("Russell Sanders","1522",999933,148608,"5355587690683715"),("Coby Moore","5374",999932,149632,"5513153357346275"),("Richard Boyle","4631",999931,150656,"5584823801501097");
INSERT INTO `consultasaldo` (`nombre`,`pin`,`cedula`,`saldo`,`tarjeta`) VALUES ("Jermaine Norman","1492",999930,151680,"5250962061730419"),("Yasir Pratt","3976",999929,152704,"5367704467340934"),("Duncan Stevenson","9993",999928,153728,"5498576713215777"),("Alan Parker","8230",999927,154752,"5286357556032645"),("Prescott Santiago","6632",999926,155776,"5459145917092213"),("Theodore Barnett","7244",999925,156800,"5228170144771736"),("Baxter Lang","5922",999924,157824,"5213228067040567"),("Leroy Patrick","8563",999923,158848,"5569396807196260"),("Blake Padilla","5676",999922,159872,"5231912413239332"),("Arden Perkins","7222",999921,160896,"5355901137710942");
INSERT INTO `consultasaldo` (`nombre`,`pin`,`cedula`,`saldo`,`tarjeta`) VALUES ("Norman Logan","1746",999920,161920,"5254213730901049"),("Igor Gardner","2203",999919,162944,"5296290936831535"),("Logan Cummings","7446",999918,163968,"5598098073500085"),("Ryder Medina","8325",999917,164992,"5369581818531280"),("Coby Sosa","9946",999916,166016,"5310646970421479"),("Cadman Kirkland","9079",999915,167040,"5300397584369553"),("Ralph Griffin","9271",999914,168064,"5293441997383360"),("Gabriel George","4759",999913,169088,"5572479208274756"),("Upton Higgins","6203",999912,170112,"5467542634862417"),("Kadeem Heath","4309",999911,171136,"5402931362441106");
INSERT INTO `consultasaldo` (`nombre`,`pin`,`cedula`,`saldo`,`tarjeta`) VALUES ("Justin Ferguson","9363",999910,172160,"5517492761215734"),("Myles Dudley","4270",999909,173184,"5510323009983741"),("Josiah Humphrey","1292",999908,174208,"5104651344919638"),("Baxter Grant","7666",999907,175232,"5380601965859352"),("Ryder Hubbard","9050",999906,176256,"5582772516695755"),("Uriel Lambert","4167",999905,177280,"5198751516173969"),("Rogan Davidson","6776",999904,178304,"5477811976095813"),("Chaim Bradley","1135",999903,179328,"5119414154117295"),("Joel Figueroa","8721",999902,180352,"5320044477254684"),("Dustin Lang","6048",999901,181376,"5410490727387280");

Ahora comprobamos que los datos se hayan insertado en la tabla consulta de saldo

SELECT * FROM consultasaldo;

Deben ver datos similares a estos











Con esto tendremos preparada la base de datos para las consultas desde nuestro dialplan.


Extensions_custom.conf

Ahora editamos el archivo
vim /etc/asterisk/extensions_custom.conf

Revisamos y pegamos es siguiente contenido


[local2]
exten => _*10,1,Goto(consultadb,s,1)   ;cuando marquemos *10 saltara al contexto consultadb
[consultadb] ;contexto para la consulta
exten => _s,1,Answer
exten => _s,n,Set(loop=0)
exten => _s,n,Set(TIMEOUT(digit)=3)
exten => _s,n(start),agi(googletts.agi,"Gracias por llamar. Digite su numero de cedula despues del tono. Y presione el simbolo numeral",es,,1.25)
exten => _s,n,Set(loop=$[${loop}+1])
exten => _s,n(incrementoloop),NoOp(${loop})
exten => _s,n,Playback(beep)
exten => _s,n,Read(ceduladigitada,,20)
exten => _s,n,GotoIf($[${loop} > 2]?final)
exten => _s,n,Gotoif($["${ceduladigitada}" = ""]?start:ConfirmacionCed)
exten => _s,n(ConfirmacionCed),agi(googletts.agi,"Su numero de cedula es",es,,1.26)
exten => _s,n,SayDigits(${ceduladigitada},m)
exten => _s,n,agi(googletts.agi,"Digite 1, si es correcto, Digite 2 si es incorrecto",es,,1.26)
exten => _s,n,Background(silence/4)
exten => _s,n,WaitExten(4,)
exten => 2,1(ivrsel-2),Goto(consultadb,s,1)
exten => 1,1(ivrsel-1),Goto(Numerotarjeta,s,1)
exten => h,1(final),Hangup
[Numerotarjeta]
exten => _s,1,Answer
exten => _s,n,Set(loop=0)
exten => _s,n,Set(TIMEOUT(digit)=3)
exten => _s,n(start),agi(googletts.agi,"Digite su numero de tarjeta, despues del tono",es,,1.26)
exten => _s,n,Set(loop=$[${loop}+1])
exten => _s,n(incrementoloop),NoOp(${loop}
exten => _s,n,Playback(beep)
exten => _s,n,Read(numerodetarjeta,,30)
exten => _s,n,GotoIf($[${loop} > 2]?final)
exten => _s,n,Gotoif($["${numerodetarjeta}" = ""]?start:Confirmaciontarj)
exten => _s,n(Confirmaciontarj),agi(googletts.agi,"Su numero de tarjeta es",es,,1.26)
exten => _s,n,SayDigits(${numerodetarjeta},m)
exten => _s,n,agi(googletts.agi,"Digite 1, si es correcto, Digite 2 si es incorrecto",es,,1.26)
exten => _s,n,Background(silence/4)
exten => _s,n,WaitExten(4,)
exten => 2,1(ivrsel-2),Goto(Numerotarjeta,s,1)
exten => 1,1(ivrsel-1),Goto(pin,s,1)
exten => h,1(final),Hangup
[pin]
exten => _s,1,Answer
exten => _s,n,Set(loop=0)
exten => _s,n,Set(TIMEOUT(digit)=3)
exten => _s,n(start),agi(googletts.agi,"Digite el pin de su tarjeta despues del tono.",es,,1.26)
exten => _s,n,Set(loop=$[${loop}+1])
exten => _s,n(incrementoloop),NoOp(${loop}
exten => _s,n,Playback(beep)
exten => _s,n,Read(PIN,,4)
exten => _s,n,GotoIf($[${loop} > 2]?final)
exten => _s,n,Gotoif($["${numerodetarjeta}" = ""]?start:Confirmacionpin)
exten => _s,n(Confirmacionpin),agi(googletts.agi,"El pin de su tarjeta es:",es,,1.26)
exten => _s,n,SayDigits(${PIN},m)
exten => _s,n,agi(googletts.agi,"Digite 1, si es correcto, Digite 2 si es incorrecto",es,,1.26)
exten => _s,n,Background(silence/4)
exten => _s,n,WaitExten(4,)
exten => 2,1(ivrsel-2),Goto(pin,s,1)
exten => 1,1(ivrsel-1),Goto(conexionmysql,s,1)
exten => h,1(final),Hangup
[conexionmysql]
exten => _s,1,Answer
exten => _s,n,NoOp(Probando MySQL)
exten => _s,n,NoOp(Conectando con MySQL)
exten => _s,n,Mysql(connect conexion localhost root 123456 ivr)
exten => _s,n,NoOP(Resultado de conexion = ${conexion})
exten => _s,n,WaitExten(2,)
exten => _s,n,Mysql(query consulta ${conexion} SELECT * FROM consultasaldo WHERE cedula=${ceduladigitada} and pin=${PIN} and tarjeta = ${numerodetarjeta})
exten => _s,n,NoOP(Resultado de consulta = ${consulta})
exten => _s,n,NoOP(Asignando resultados a variables variable1 y variable2 )
exten => _s,n,Mysql(fetch asignacion ${consulta} variable1 variable2 variable3 variable4 variable5 variable6)
exten => _s,n,NoOP(Resultado de asignacion = ${asignacion})
exten => _s,n,NoOP(variable1 = ${variable1})
exten => _s,n,NoOP(variable2 = ${variable2})
exten => _s,n,NoOP(variable2 = ${variable3})
exten => _s,n,NoOP(variable2 = ${variable4})
exten => _s,n,NoOP(variable2 = ${variable5})
exten => _s,n,NoOP(Limpiando resultado de la consulta)
exten => _s,n,Mysql(clear ${consulta})
exten => _s,n,NoOP(Resultado de limpieza: consulta = ${consulta})
exten => _s,n,NoOP(Cerrando conexion)
exten => _s,n,Mysql(disconnect ${conexion})
exten => _s,n,GotoIf($["${variable1}" = ""]?nodataread,s,1:continuar)
exten => _s,n(continuar),agi(googletts.agi,"ID en base de datos es",es)
exten => _s,n,SayDigits(${variable1})
exten => _s,n,agi(googletts.agi,"Su nombre es ${variable2}",es,,1.26)
exten => _s,n,agi(googletts.agi,"su saldo es ${variable5}",es,,1.26)
exten => _s,n(final),Hangup()
[nodataread]
exten => _s,1,Answer
exten => _s,n(cedulanodigitada),agi(googletts.agi,"El valor no existe",es,,1.16)
exten => _s,n,Goto(consultadb,s,1)



Debemos hacer el include este mismo archivo

[from-internal-custom]
exten => 1234,1,Playback(demo-congrats) ; extensions can dial 1234
exten => 1234,2,Hangup()
exten => h,1,Hangup()
include => agentlogin
include => conferences
include => calendar-event
include => weather-wakeup
include => local2
include => consultadb
include => cedulainvalida
include => Numerotarjeta
include => pin
include => conexionmysql
include => nodataread

Guardamos el archivo y reiniciamos el dialplan

asterisk -rx "dialplan reload"


¡Y estamos listos (casi...)!

A falta de una voz glamurosa para las grabaciones, opte por usar el tts de google el cual obviamente se puede utilizar hasta que no pase lo contrario de forma gratuita, pueden seguir estos pasos para instalarlo;

http://zaf.github.io/asterisk-googletts/


¡Ahora si!

Solo nos queda probar  el flujo de la llamada

Marcamos

*10

Escuchamos y seguimos las opciones, para entender el el dialplan pueden ir leyendo literalmente cada paso, también pueden ir viendo la consola del Asterisk para "debuguear"

Los valores ingresados deben coincidir con los de la base de datos, de lo contrario vuelven a la opción anterior.

El resultado debe de ser:

Con un audio (googletts.agi), id en base de datos.
Con un audio (googletts.agi), Nombre en la base de datos.
Con un audio (googletts.agi), Saldo en la base de datos.

En esta esta entrada utlizamos varias aplicaciones, con esto nos damos cuenta de lo potente que puede ser este recurso para una empresa.

Si les intereso el articulo, recomiendo aprender /leer mas sobre:

Aplicacion   Goto
Aplicacion   GotoIF
Aplicacion   Mysql con mas de una opcion
Aplicacion   AGI
Aplicacion   NoOp

Espero les guste la entrada y los reto a tratar de simplificar este IVR.


Como siempre quedo atento a sus comentarios

gabofuentesm@gmail.com

Saludos,