Browse Source

[ADD] connector_voicent

pull/191/head
Youness MAAFI 5 years ago
committed by Maxime Chambreuil
parent
commit
f27163f1f9
  1. 13
      connector_voicent/README.rst
  2. 1
      connector_voicent/__init__.py
  3. 30
      connector_voicent/__manifest__.py
  4. 32
      connector_voicent/examples/prototype.py
  5. 2
      connector_voicent/examples/voicent.csv
  6. 187
      connector_voicent/examples/voicent.py
  7. 4
      connector_voicent/models/__init__.py
  8. 33
      connector_voicent/models/backend_voicent.py
  9. 25
      connector_voicent/models/backend_voicent_call_line.py
  10. 23
      connector_voicent/models/backend_voicent_time_line.py
  11. 11
      connector_voicent/models/res_partner.py
  12. 1
      connector_voicent/readme/CONFIGURE.rst
  13. 2
      connector_voicent/readme/CONTRIBUTORS.rst
  14. 0
      connector_voicent/readme/CREDITS.rst
  15. 2
      connector_voicent/readme/DESCRIPTION.rst
  16. 0
      connector_voicent/readme/HISTORY.rst
  17. 1
      connector_voicent/readme/INSTALL.rst
  18. 0
      connector_voicent/readme/ROADMAP.rst
  19. 4
      connector_voicent/readme/USAGE.rst
  20. 4
      connector_voicent/security/ir.model.access.csv
  21. BIN
      connector_voicent/static/description/icon.png
  22. 94
      connector_voicent/view/backend_voicent.xml
  23. 15
      connector_voicent/view/res_partner.xml

13
connector_voicent/README.rst

@ -0,0 +1,13 @@
**Connector Voicent**
*This module allows you to connect Odoo with Voicent (https://www.voicent.com).*
* **DESCRIPTION.rst**
* **USAGE.rst**
* **CONTRIBUTORS.rst**
* INSTALL.rst
* CONFIGURE.rst
* DEVELOP.rst
* ROADMAP.rst
* HISTORY.rst
* CREDITS.rst

1
connector_voicent/__init__.py

@ -0,0 +1 @@
from . import models

30
connector_voicent/__manifest__.py

@ -0,0 +1,30 @@
# @TODO: To use the right License.
# @TODO: Description, Website, Contributros..etc.
{
'name': 'Voicent Connector',
'version': '12.0.1.0.0',
'category': 'Phone',
'license': 'AGPL-3',
'summary': 'Automate phone calls based on stage changes',
'development_status': 'Stable',
'maintainers': [
'younessmaafi',
'max3903',
],
'author': 'Maxime Chambreuil, Youness MAAFI,'
' Odoo Community Association (OCA)',
'website': 'http://opensourceintegrators.com',
'depends': [
'base',
],
'data': [
# Security
'security/ir.model.access.csv',
# Views
'view/res_partner.xml',
'view/backend_voicent.xml',
],
'demo': [],
'installable': True,
'auto_install': False,
}

32
connector_voicent/examples/prototype.py

@ -0,0 +1,32 @@
# Copyright (C) 2019 Open Source Integrators
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# Simple message
import voicent
v = voicent.Voicent()
phoneno = "6024275632"
reqid = v.callText(phoneno, "Hello, This is a test of the autodialer.", "1")
status = v.callStatus(reqid)
# Using Campaign in 2 steps
v = voicent.Voicent()
filepath = "/home/mchambreuil/odoo/pvm/voicent.csv"
listname = "Test"
leadsrc_id = v.importCampaign(listname, filepath)
res = v.runCampaign(listname)
v.checkStatus(res['leadsrc_id'])
# Using Campaign in 1 step with TTS
v = voicent.Voicent()
filepath = "/home/mchambreuil/odoo/pvm/voicent.csv"
res = v.importAndRunCampaign(filepath, "tts", "Hello, This is a test. Bye")
status = v.checkStatus(res['camp_id'])
# Using Campaign in 1 step with Template
v = voicent.Voicent()
filepath = "/home/mchambreuil/odoo/pvm/voicent.csv"
res = v.importAndRunCampaign(filepath, "template", "Test")
status = v.checkStatus(res['camp_id'])

2
connector_voicent/examples/voicent.csv

@ -0,0 +1,2 @@
Name,Phone
Maxime Chambreuil,6024275632

187
connector_voicent/examples/voicent.py

@ -0,0 +1,187 @@
# Copyright (C) 2018 Voicent
# Copyright (C) 2019 Open Source Integrators
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
#
# Documentation available at https://voicent.com/developer/docs/camp-api/
import ntpath
import requests
import ast
class Voicent():
def __init__(self, host="localhost", port="8155"):
self.host_ = host
self.port_ = port
def postToGateway(self, urlstr, params, files=None):
url = "http://" + self.host_ + ":" + self.port_ + urlstr
res = requests.post(url, params, files=files)
return res.text
def getReqId(self, rcstr):
index1 = rcstr.find("[ReqId=")
if (index1 == -1):
return ""
index1 += 7
index2 = rcstr.find("]", index1)
if (index2 == -1):
return ""
return rcstr[index1:index2]
def callText(self, phoneno, text, selfdelete):
urlstr = "/ocall/callreqHandler.jsp"
params = {
'info': 'simple text call',
'phoneno': phoneno,
'firstocc': 10,
'txt': text,
'selfdelete': selfdelete
}
res = self.postToGateway(urlstr, params)
return self.getReqId(res)
def callAudio(self, phoneno, filename, selfdelete):
urlstr = "/ocall/callreqHandler.jsp"
params = {
'info': 'simple audio call',
'phoneno': phoneno,
'firstocc': 10,
'audiofile': filename,
'selfdelete': selfdelete
}
res = self.postToGateway(urlstr, params)
return self.getReqId(res)
def callIvr(self, phoneno, appname, selfdelete):
urlstr = "/ocall/callreqHandler.jsp"
params = {
'info': 'simple text call',
'phoneno': phoneno,
'firstocc': 10,
'startapp': appname,
'selfdelete': selfdelete
}
res = self.postToGateway(urlstr, params)
return self.getReqId(res)
def callStatus(self, reqid):
urlstr = "/ocall/callstatusHandler.jsp"
params = {'reqid': reqid}
res = self.postToGateway(urlstr, params)
return self.getReqId(res)
def callRemove(self, reqId):
urlstr = "/ocall/callremoveHandler.jsp"
params = {'reqid': reqId}
res = self.postToGateway(urlstr, params)
return self.getReqId(res)
def callTillConfirm(self, vcastexe, vocfile, wavfile, ccode):
urlstr = "/ocall/callreqHandler.jsp"
cmdline = "\""
cmdline += vocfile
cmdline += "\""
cmdline += " -startnow"
cmdline += " -confirmcode "
cmdline += ccode
cmdline += " -wavfile "
cmdline += "\""
cmdline += wavfile
cmdline += "\""
params = {
'info': 'Simple Call till Confirm',
'phoneno': '1111111',
'firstocc': 10,
'selfdelete': 0,
'startexec': vcastexe,
'cmdline': cmdline
}
res = self.postToGateway(urlstr, params)
return self.getReqId(res)
################
# CAMPAIGN API #
################
def importCampaign(self, listname, filepath):
urlstr = "/ocall/campapi"
params = {
'action': 'import',
'importfile': ntpath.basename(filepath),
'importfilepath': filepath,
'profile': 'Test',
'mod': 'cus',
'fieldsep': ',',
'row1': 1,
'mergeopt': 'empty',
'leadsrcname': listname
}
files = {
'file': (ntpath.basename(filepath), open(filepath, 'rb'))
}
res = self.postToGateway(urlstr, params, files)
return ast.literal_eval(res)
def runCampaign(self, listname):
urlstr = "/ocall/campapi"
params = {
'action': 'bbp',
'CAMP_NAME': 'Test',
'listname': listname,
'phonecols': 'Phone',
'lines': '4',
'calldisps': '',
'callerid': '+18884728568',
}
res = self.postToGateway(urlstr, params)
return ast.literal_eval(res)
def importAndRunCampaign(self, filepath, msgtype, msginfo):
urlstr = "/ocall/campapi"
params = {
'action': 'bbp',
# Parameters for importing the campaign
'importfile': ntpath.basename(filepath),
'importfilepath': filepath,
# 'profile': 'Test',
'mod': 'cus',
'row1': 1,
'leadsrcname': 'Test',
# Parameters for running the campaign
'CAMP_NAME': 'Test',
'phonecols': 'Phone',
'lines': '4',
'calldisps': '',
'callerid': '+18884728568',
# Parameters for Autodialer
'msgtype': msgtype,
'msginfo': msginfo,
}
files = {
'file': (ntpath.basename(filepath), open(filepath, 'rb'))
}
res = self.postToGateway(urlstr, params, files)
return ast.literal_eval(res)
def checkStatus(self, leadsrc_id):
urlstr = "/ocall/campapi"
params = {
'action': 'campstats',
'leadsrc_id': leadsrc_id
}
res = self.postToGateway(urlstr, params)
return ast.literal_eval(res)
def exportResult(self, camp_id, filename, extracols):
urlstr = "/ocall/campapi"
params = {
'action': 'exportcamp',
'camp_id_id': camp_id,
'f': filename,
'extracols': extracols
}
res = self.postToGateway(urlstr, params)
return ast.literal_eval(res)

4
connector_voicent/models/__init__.py

@ -0,0 +1,4 @@
from . import res_partner
from . import backend_voicent
from . import backend_voicent_call_line
from . import backend_voicent_time_line

33
connector_voicent/models/backend_voicent.py

@ -0,0 +1,33 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class BackendVoicent(models.Model):
_name = 'backend.voicent'
_description = 'Voicent Backend'
_rec_name = 'host'
host = fields.Char(
string=u'Host',
required=True,
)
port = fields.Integer(
string=u'Port',
required=True,
)
next_call = fields.Datetime(
string=u'Next Call',
copy=False,
default=lambda self: fields.Datetime.now(),
)
call_line_ids = fields.One2many(
string=u'Call Lines',
comodel_name='backend.voicent.call.line',
inverse_name='backend_id',
)
time_line_ids = fields.One2many(
string=u'Call Times',
comodel_name='backend.voicent.time.line',
inverse_name='backend_id',
)

25
connector_voicent/models/backend_voicent_call_line.py

@ -0,0 +1,25 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class BackendVoicentCallLine(models.Model):
_name = 'backend.voicent.call.line'
_description = 'Voicent Backend Call Line'
name = fields.Char(
string=u'Name',
required=True,
)
applies_on = fields.Selection(
string=u'Applies on',
selection=[],
)
voicent_app = fields.Char(
string=u'Voicent App',
)
backend_id = fields.Many2one(
string=u'Backend',
comodel_name='backend.voicent',
ondelete='set null',
)

23
connector_voicent/models/backend_voicent_time_line.py

@ -0,0 +1,23 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class BackendVoicentTimeLine(models.Model):
_name = 'backend.voicent.time.line'
_description = 'Voicent Backend Time Line'
name = fields.Char(
string=u'Name',
required=True,
)
time = fields.Datetime(
string=u'Time',
copy=False,
default=lambda self: fields.Datetime.now(),
)
backend_id = fields.Many2one(
string=u'Backend',
comodel_name='backend.voicent',
ondelete='set null',
)

11
connector_voicent/models/res_partner.py

@ -0,0 +1,11 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
can_call = fields.Boolean(
string=u'Accepts Calls',
)

1
connector_voicent/readme/CONFIGURE.rst

@ -0,0 +1 @@
There is no specific configuration procedure for this module.

2
connector_voicent/readme/CONTRIBUTORS.rst

@ -0,0 +1,2 @@
* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
* Youness MAAFI <youness.maafi@gmail.com>

0
connector_voicent/readme/CREDITS.rst

2
connector_voicent/readme/DESCRIPTION.rst

@ -0,0 +1,2 @@
This module allows you to connect Odoo with Voicent (https://www.voicent.com),
and is meant to be extended to integrate Odoo records and processes with phone calls made by Voicent.

0
connector_voicent/readme/HISTORY.rst

1
connector_voicent/readme/INSTALL.rst

@ -0,0 +1 @@
There is no specific installation procedure for this module.

0
connector_voicent/readme/ROADMAP.rst

4
connector_voicent/readme/USAGE.rst

@ -0,0 +1,4 @@
#. Go to Connectors > Backends > Voicent Backends
#. Create a new Voicent Backend with the host and port
#. Create Call Lines to determine when (which stage in the process) calls are added to the queue
#. Create Time Line to determine when (what time) calls are made

4
connector_voicent/security/ir.model.access.csv

@ -0,0 +1,4 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_backend_voicent,access_backend_voicent,model_backend_voicent,base.group_user,1,1,1,0
access_backend_voicent_call_line,access_backend_voicent_call_line,model_backend_voicent_call_line,base.group_user,1,1,1,0
access_backend_voicent_time_line,access_backend_voicent_time_line,model_backend_voicent_time_line,base.group_user,1,0,1,0

BIN
connector_voicent/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

94
connector_voicent/view/backend_voicent.xml

@ -0,0 +1,94 @@
<odoo>
<record id="view_backend_voicent_tree" model="ir.ui.view">
<field name="name">view.backend.voicent.tree</field>
<field name="model">backend.voicent</field>
<field name="mode">primary</field>
<field name="arch" type="xml">
<tree string="Voicent Backend" create="1" delete="1" edit="1">
<field name="host"/>
<field name="port"/>
<field name="next_call"/>
</tree>
</field>
</record>
<record id="view_backend_voicent_form" model="ir.ui.view">
<field name="name">view.backend.voicent.form</field>
<field name="model">backend.voicent</field>
<field name="mode">primary</field>
<field name="arch" type="xml">
<form string="Voicent Backend" create="1" delete="1" edit="1">
<header>
</header>
<sheet>
<group>
<field name="host"/>
<field name="port"/>
</group>
<separator string="Call Lines"/>
<field name="call_line_ids">
<tree string="Call Lines" create="1" delete="1" edit="1" editable="top">
<field name="name"/>
<field name="applies_on"/>
<field name="voicent_app"/>
</tree>
</field>
<separator string="Call Times"/>
<field name="time_line_ids">
<tree string="Call Times" create="1" delete="1" edit="1" editable="top">
<field name="name"/>
<field name="time"/>
</tree>
</field>
</sheet>
</form>
</field>
</record>
<record id="view_backend_voicent_search" model="ir.ui.view">
<field name="name">view.backend.voicent.search</field>
<field name="model">backend.voicent</field>
<field name="mode">primary</field>
<field name="arch" type="xml">
<search string="Voicent Backend">
<field name="host"/>
<field name="port"/>
</search>
</field>
</record>
<record id="action_backend_voicent_act_window" model="ir.actions.act_window">
<field name="type">ir.actions.act_window</field>
<field name="name">Voicent Backend</field>
<field name="res_model">backend.voicent</field>
<field name="view_mode">tree,form</field>
<field name="view_type">form</field>
<field name="search_view_id" ref="view_backend_voicent_search"/>
<field name="help" type="html">
<p class="oe_view_nocontent_create">
Click to add new Voicent Backend
</p>
</field>
</record>
<record id="menu_connectors_root" model="ir.ui.menu" >
<field name="name">Connectors</field>
<field name="sequence" eval="10" />
</record>
<record id="menu_connectors_backends" model="ir.ui.menu" >
<field name="name">Backends</field>
<field name="sequence" eval="10" />
<field name="parent_id" ref="connector_voicent.menu_connectors_root" />
</record>
<record id="menu_backend_voicent" model="ir.ui.menu" >
<field name="name">Voicent Backends</field>
<field name="sequence" eval="10" />
<field name="action" ref="action_backend_voicent_act_window" />
<field name="parent_id" ref="connector_voicent.menu_connectors_backends" />
</record>
</odoo>

15
connector_voicent/view/res_partner.xml

@ -0,0 +1,15 @@
<odoo>
<record id="view_res_partner_form" model="ir.ui.view">
<field name="name">view.res.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//h1//field[@name='name']/.." position="after">
<group attrs="{'invisible': [('is_company', '=', True)]}">
<field name="can_call"/>
</group>
</xpath>
</field>
</record>
</odoo>
Loading…
Cancel
Save