diff --git a/connector_voicent/README.rst b/connector_voicent/README.rst new file mode 100644 index 0000000..36f2beb --- /dev/null +++ b/connector_voicent/README.rst @@ -0,0 +1,93 @@ +================= +Voicent Connector +================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fconnector--telephony-lightgray.png?logo=github + :target: https://github.com/OCA/connector-telephony/tree/12.0/connector_voicent + :alt: OCA/connector-telephony +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/connector-telephony-12-0/connector-telephony-12-0-connector_voicent + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/228/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows you to connect Odoo with Voicent and is meant to be extended to integrate Odoo records and processes with phone calls made by Voicent. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use this module, you need to: + +#. 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 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Open Source Integrators + +Contributors +~~~~~~~~~~~~ + +* Maxime Chambreuil +* Youness MAAFI +* Murtuza Saleh + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-max3903| image:: https://github.com/max3903.png?size=40px + :target: https://github.com/max3903 + :alt: max3903 + +Current `maintainer `__: + +|maintainer-max3903| + +This module is part of the `OCA/connector-telephony `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/connector_voicent/__init__.py b/connector_voicent/__init__.py new file mode 100644 index 0000000..69f7bab --- /dev/null +++ b/connector_voicent/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models diff --git a/connector_voicent/__manifest__.py b/connector_voicent/__manifest__.py new file mode 100644 index 0000000..0a710a2 --- /dev/null +++ b/connector_voicent/__manifest__.py @@ -0,0 +1,29 @@ +# Copyright (C) 2019 Open Source Integrators +# +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Voicent Connector', + 'version': '12.0.1.0.0', + 'category': 'Connector', + 'license': 'AGPL-3', + 'summary': """Connect Odoo with Voicent""", + "author": "Open Source Integrators, " + "Odoo Community Association (OCA)", + "website": "https://github.com/OCA/connector-telephony", + 'depends': [ + 'connector', + ], + 'data': [ + 'security/ir.model.access.csv', + 'data/ir_cron.xml', + 'views/res_partner.xml', + 'views/backend_voicent_call_line.xml', + 'views/backend_voicent.xml', + ], + 'installable': True, + 'maintainers': [ + 'max3903', + ], + 'development_status': 'Beta', +} diff --git a/connector_voicent/data/ir_cron.xml b/connector_voicent/data/ir_cron.xml new file mode 100644 index 0000000..6786f88 --- /dev/null +++ b/connector_voicent/data/ir_cron.xml @@ -0,0 +1,17 @@ + + + + + Voicent: Update the next call + + + + 15 + minutes + -1 + + code + model._run_update_next_call() + + + diff --git a/connector_voicent/examples/voicent.py b/connector_voicent/examples/voicent.py new file mode 100644 index 0000000..a6cf4b6 --- /dev/null +++ b/connector_voicent/examples/voicent.py @@ -0,0 +1,205 @@ +# 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 ast +import csv +import ntpath +import os +import requests + + +class Voicent(): + + def __init__(self, host="localhost", port="8155", callerid="000000000", + line="1"): + self.host_ = host + self.port_ = port + self.callerid_ = callerid + self.line_ = line + + 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': self.line_, + 'calldisps': '', + 'callerid': self.callerid_, + } + 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, + 'mergeopt': 'skip', + # 'profile': 'Test', + 'mod': 'cus', + 'row1': 1, + 'leadsrcname': 'Odoo Voicent Connector', + # Parameters for running the campaign + 'CAMP_NAME': 'Odoo Voicent Connector', + 'phonecols': 'Phone', + 'lines': self.line_, + 'calldisps': '', + 'callerid': self.callerid_, + # 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, camp_id): + urlstr = "/ocall/campapi" + params = { + 'action': 'campstats', + 'camp_id': camp_id + } + res = self.postToGateway(urlstr, params) + return ast.literal_eval(res) + + def exportResult(self, camp_id, filename, extracols=None): + urlstr = "/ocall/campapi" + params = { + 'action': 'exportcamp', + 'camp_id': camp_id, + 'f': 'webapps/ROOT/assets/global/' + filename, + 'extracols': extracols + } + res = ast.literal_eval(self.postToGateway(urlstr, params)) + if res.get('status') == 'OK': + url = 'http://' + self.host_ + ':' + self.port_ + \ + '/assets/global/' + filename + res2 = requests.get(url) + with open(filename, 'wb') as local_file: + local_file.write(res2.content) + local_file.close() + reader = csv.DictReader(open(filename, 'r')) + os.remove(filename) + for row in reader: + return row + else: + return res diff --git a/connector_voicent/models/__init__.py b/connector_voicent/models/__init__.py new file mode 100644 index 0000000..f6f7d9f --- /dev/null +++ b/connector_voicent/models/__init__.py @@ -0,0 +1,6 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import res_partner +from . import backend_voicent_call_line +from . import backend_voicent_time_line +from . import backend_voicent diff --git a/connector_voicent/models/backend_voicent.py b/connector_voicent/models/backend_voicent.py new file mode 100644 index 0000000..c00777b --- /dev/null +++ b/connector_voicent/models/backend_voicent.py @@ -0,0 +1,79 @@ +# Copyright (C) 2019 Open Source Integrators +# +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +from odoo import api, fields, models +from datetime import datetime, timedelta +from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT +from pytz import timezone + + +class BackendVoicent(models.Model): + _name = 'backend.voicent' + _description = 'Voicent Backend' + _inherit = ['connector.backend'] + + name = fields.Char(string='Name', required=True) + host = fields.Char(string='Host', default='localhost', required=True) + port = fields.Integer(string='Port', default='8155', required=True) + callerid = fields.Char(string='Caller ID', required=True) + line = fields.Integer(string='Number of lines', required=True) + next_call = fields.Datetime(string='Next Call', copy=False) + call_line_ids = fields.One2many( + string='Call Lines', + comodel_name='backend.voicent.call.line', + inverse_name='backend_id') + time_line_ids = fields.One2many( + string='Call Times', + comodel_name='backend.voicent.time.line', + inverse_name='backend_id') + active = fields.Boolean('Active', default=True) + + @api.model + def _run_update_next_call(self): + """ This method is called from a cron job. """ + + cr_time_list = [] + backends = self.search([('active', '=', True)]) + for backend in backends: + current_dt = datetime.now(timezone('UTC')) + user_tz = timezone( + self.env.context.get('tz') or self.env.user.tz or 'UTC') + dt_value = current_dt.astimezone(user_tz) + convt_dt_strf = dt_value.strftime(DEFAULT_SERVER_DATETIME_FORMAT) + convt_dt = datetime.strptime( + convt_dt_strf, + DEFAULT_SERVER_DATETIME_FORMAT) + current_time = convt_dt.strftime("%H:%M") + for time_line_rec in backend.time_line_ids: + hours, minutes = divmod(abs(time_line_rec.time) * 60, 60) + minutes = round(minutes) + if minutes == 60: + minutes = 0 + hours += 1 + line_time = '%02d:%02d' % (hours, minutes) + cr_time_list.append(line_time) + cr_time_list = sorted(cr_time_list) + next_call = False + for time_entry in cr_time_list: + if time_entry > current_time: + next_call = datetime.now().replace( + hour=int(time_entry.split(':')[0]), + minute=int(time_entry.split(':')[1]), + second=0) + break + if not next_call: + next_call = datetime.now().replace( + hour=int(cr_time_list[0].split(':')[0]), + minute=int(cr_time_list[0].split(':')[1]), + second=0) + timedelta( + days=0) + next_call_tz = timezone(self.env.context.get('tz') or + self.env.user.tz).localize(next_call, + is_dst=False) + next_call_utc = next_call_tz.astimezone(timezone('UTC')) + next_call_utc = datetime.strptime( + fields.Datetime.to_string(next_call_utc), + DEFAULT_SERVER_DATETIME_FORMAT) + backend.next_call = fields.Datetime.to_string(next_call_utc) diff --git a/connector_voicent/models/backend_voicent_call_line.py b/connector_voicent/models/backend_voicent_call_line.py new file mode 100644 index 0000000..3da9664 --- /dev/null +++ b/connector_voicent/models/backend_voicent_call_line.py @@ -0,0 +1,109 @@ +# Copyright (C) 2019 Open Source Integrators +# +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + +VOICENT_CONTACT_COLUMNS = [('Assigned To', 'Assigned To'), + ('Business', 'Business'), + ('Category', 'Category'), + ('Contact Status', 'Contact Status'), + ('Email', 'Email'), + ('First Name', 'First Name (Required)'), + ('Last Name', 'Last Name'), + ('Lead Source', 'Lead Source'), + ('Other', 'Other'), + ('Phone', 'Phone (Required)')] + +VOICENT_REPLY = [('availableagents', 'Available Agents'), + ('callback', 'Callback'), + ('campid', 'Campaign ID'), + ('campname', 'Campaign Name'), + ('campsize', 'Campaign Size'), + ('connected', 'Connected'), + ('dnc', 'Contact DNC'), + ('nophone', 'Contact No Phone'), + ('disc', 'Disc. Number'), + ('dropped', 'Dropped'), + ('failed', 'Failed'), + ('fax', 'Fax'), + ('info', 'Info'), + ('in', 'Interested'), + ('lines', 'Lines'), + ('linebusy', 'Line Busy'), + ('live', 'Live Answer'), + ('machine', 'Machine Answer'), + ('made', 'Made'), + ('maxlines', 'Max Lines'), + ('noact', 'No Activity'), + ('noanswer', 'No Answer'), + ('notin', 'Not Interested'), + ('notes', 'Notes'), + ('optout', 'Opt Out'), + ('serverr', 'Service Error'), + ('status', 'Status'), + ('totalagents', 'Total Agents'), + ('wit', 'Wit')] + +MSGTYPE = [('audio', 'Audio'), + ('ivr', 'IVR'), + ('survey', 'Survey'), + ('template', 'Template'), + ('tts', 'Text-To-Speech')] + + +class BackendVoicentCallLine(models.Model): + _name = 'backend.voicent.call.line' + _description = 'Voicent Backend Call Line' + + name = fields.Char(string='Name', required=True) + sequence = fields.Integer(string='Sequence', default=0) + applies_on = fields.Selection(string='Applies on', selection=[]) + msgtype = fields.Selection(MSGTYPE, string='Message Type', required=True) + msginfo = fields.Char(string='Message Info') + backend_id = fields.Many2one( + string='Backend', + comodel_name='backend.voicent', + ondelete='set null') + reply_ids = fields.One2many('backend.voicent.call.line.reply', 'line_id', + string="Replies") + contact_ids = fields.One2many('backend.voicent.call.line.contact', + 'line_id', + string="Contact Info") + + +class BackendVoicentCallLineContact(models.Model): + _name = 'backend.voicent.call.line.contact' + _description = 'Columns of the CSV file to provide the contact list' + _order = 'sequence' + + name = fields.Selection(VOICENT_CONTACT_COLUMNS, string='Voicent Field', + required=True) + other = fields.Char(string='Other') + sequence = fields.Integer(string='Sequence', default=0) + field_domain = fields.Char(string='Odoo Field', + required=True) + default_value = fields.Char(string='Default Value', required=True) + line_id = fields.Many2one( + string='Call Line', + comodel_name='backend.voicent.call.line', + ondelete='set null') + + +class BackendVoicentCallLineReply(models.Model): + _name = 'backend.voicent.call.line.reply' + _description = 'Reply to a Voicent Call' + + name = fields.Char(string='Name', required=True) + line_id = fields.Many2one( + string='Call Line', + comodel_name='backend.voicent.call.line', + ondelete='set null') + reply_field = fields.Selection(VOICENT_REPLY, string="Voicent Reply Field", + required=True) + reply_value = fields.Char(string="Voicent Reply Value", required=True) + action_id = fields.Many2one('ir.actions.server', string="Server Action", + required=True, + help="""If the Voicent reply field is equal to + the Voicent reply value, the server action is + executed.""") diff --git a/connector_voicent/models/backend_voicent_time_line.py b/connector_voicent/models/backend_voicent_time_line.py new file mode 100644 index 0000000..7d0760f --- /dev/null +++ b/connector_voicent/models/backend_voicent_time_line.py @@ -0,0 +1,18 @@ +# Copyright (C) 2019 Open Source Integrators +# +# 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' + _order = 'time' + + name = fields.Char(string='Name', required=True) + time = fields.Float(string='Time', copy=False) + backend_id = fields.Many2one( + string='Backend', + comodel_name='backend.voicent', + ondelete='set null') diff --git a/connector_voicent/models/res_partner.py b/connector_voicent/models/res_partner.py new file mode 100644 index 0000000..d3e8e5f --- /dev/null +++ b/connector_voicent/models/res_partner.py @@ -0,0 +1,11 @@ +# Copyright (C) 2019 Open Source Integrators +# +# 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='Accepts Voicent Calls', default=True) diff --git a/connector_voicent/readme/CONFIGURATION.rst b/connector_voicent/readme/CONFIGURATION.rst new file mode 100644 index 0000000..8fa1155 --- /dev/null +++ b/connector_voicent/readme/CONFIGURATION.rst @@ -0,0 +1,6 @@ +#. Go to Settings > Users & Companies > Users +#. Select the filter "Inactive Users" only +#. Select the user "OdooBot" +#. Click on "Edit" +#. Go to the tab "Preferences" +#. Set the timezone diff --git a/connector_voicent/readme/CONTRIBUTORS.rst b/connector_voicent/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000..b56fc23 --- /dev/null +++ b/connector_voicent/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* Maxime Chambreuil +* Youness MAAFI +* Murtuza Saleh diff --git a/connector_voicent/readme/DESCRIPTION.rst b/connector_voicent/readme/DESCRIPTION.rst new file mode 100644 index 0000000..4a2ce3e --- /dev/null +++ b/connector_voicent/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module allows you to connect Odoo with Voicent and is meant to be extended to integrate Odoo records and processes with phone calls made by Voicent. diff --git a/connector_voicent/readme/ROADMAP.rst b/connector_voicent/readme/ROADMAP.rst new file mode 100644 index 0000000..c793651 --- /dev/null +++ b/connector_voicent/readme/ROADMAP.rst @@ -0,0 +1,3 @@ +* On the backend, replace the 'Applies On' selection list with a Many2one to ir.model.fields +* On the backend call line contact, use the domain widget to select the field +* Update the voicent library on Pypi with examples/voicent.py diff --git a/connector_voicent/readme/USAGE.rst b/connector_voicent/readme/USAGE.rst new file mode 100644 index 0000000..f6907cc --- /dev/null +++ b/connector_voicent/readme/USAGE.rst @@ -0,0 +1,6 @@ +#. Go to Connectors > Backends > Voicent Backends +#. Create a new Voicent Backend with the host, port, the caller ID and the number of lines +#. Create Call Lines to determine when (which stage in the process) calls are added to the queue +#. Create Contact Info to create the structure of the CSV file to send to Voicent +#. Create Replies to determine what to do based on the replies (see example below) +#. Create Time Line to determine when (what time) calls are made diff --git a/connector_voicent/security/ir.model.access.csv b/connector_voicent/security/ir.model.access.csv new file mode 100644 index 0000000..00ecd4e --- /dev/null +++ b/connector_voicent/security/ir.model.access.csv @@ -0,0 +1,6 @@ +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,connector.group_connector_manager,1,1,1,1 +access_backend_voicent_call_line,access_backend_voicent_call_line,model_backend_voicent_call_line,connector.group_connector_manager,1,1,1,1 +access_backend_voicent_call_line_reply,access_backend_voicent_call_line_reply,model_backend_voicent_call_line_reply,connector.group_connector_manager,1,1,1,1 +access_backend_voicent_call_line_contact,access_backend_voicent_call_line_contact,model_backend_voicent_call_line_contact,connector.group_connector_manager,1,1,1,1 +access_backend_voicent_time_line,access_backend_voicent_time_line,model_backend_voicent_time_line,connector.group_connector_manager,1,1,1,1 diff --git a/connector_voicent/static/description/icon.png b/connector_voicent/static/description/icon.png new file mode 100644 index 0000000..40429d1 Binary files /dev/null and b/connector_voicent/static/description/icon.png differ diff --git a/connector_voicent/static/description/index.html b/connector_voicent/static/description/index.html new file mode 100644 index 0000000..9439998 --- /dev/null +++ b/connector_voicent/static/description/index.html @@ -0,0 +1,433 @@ + + + + + + +Voicent Connector + + + +
+

Voicent Connector

+ + +

Beta License: AGPL-3 OCA/connector-telephony Translate me on Weblate Try me on Runbot

+

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.

+

Table of contents

+ +
+

Usage

+
    +
  1. Go to Connectors > Backends > Voicent Backends
  2. +
  3. Create a new Voicent Backend with the host and port
  4. +
  5. Create Call Lines to determine when (which stage in the process) calls are added to the queue
  6. +
  7. Create Time Line to determine when (what time) calls are made
  8. +
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Open Source Integrators
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

max3903

+

This module is part of the OCA/connector-telephony project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/connector_voicent/tests/__init__.py b/connector_voicent/tests/__init__.py new file mode 100644 index 0000000..e1cc30d --- /dev/null +++ b/connector_voicent/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_backend_voicent diff --git a/connector_voicent/tests/test_backend_voicent.py b/connector_voicent/tests/test_backend_voicent.py new file mode 100644 index 0000000..35bf588 --- /dev/null +++ b/connector_voicent/tests/test_backend_voicent.py @@ -0,0 +1,37 @@ +# Copyright (C) 2019 Open Source Integrators +# +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + + +class TestBackendVoicent(TransactionCase): + + def setUp(self): + super(TestBackendVoicent, self).setUp() + self.backend_voicent_model = self.env['backend.voicent'] + self.backend_voicent_id = self.backend_voicent_model.create( + {'name': 'Test', + 'host': 'localhost', + 'port': '8155', + 'callerid': '0000000000', + 'line': '1', + 'active': True, + 'call_line_ids': [(0, 0, + {'name': 'call 1', + 'applies_on': False, + 'msgtype': 'tts', + 'msginfo': 'Hello World!'})], + 'time_line_ids': [(0, 0, {'name': 'Call Time 1', + 'time': 10.0}), + (0, 0, {'name': 'Call Time 2', + 'time': 11.0}), + (0, 0, {'name': 'Call Time 3', + 'time': 12.0}), + (0, 0, {'name': 'Call Time 4', + 'time': 13.0})] + }) + + def test_run_check_the_voicent_status(self): + """To call the scheduler method.""" + self.backend_voicent_id._run_update_next_call() diff --git a/connector_voicent/views/backend_voicent.xml b/connector_voicent/views/backend_voicent.xml new file mode 100644 index 0000000..c9a3269 --- /dev/null +++ b/connector_voicent/views/backend_voicent.xml @@ -0,0 +1,118 @@ + + + + backend.voicent.tree.view + backend.voicent + + + + + + + + + + + + + + + backend.voicent.form.view + backend.voicent + +
+ +
+ +
+
+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + backend.voicent.search.view + backend.voicent + + + + + + + + + + + + ir.actions.act_window + Voicent Backend + backend.voicent + tree,form + form + + +

+ Click to add new Voicent Backend +

+
+
+ + + + + +
diff --git a/connector_voicent/views/backend_voicent_call_line.xml b/connector_voicent/views/backend_voicent_call_line.xml new file mode 100644 index 0000000..98b41de --- /dev/null +++ b/connector_voicent/views/backend_voicent_call_line.xml @@ -0,0 +1,76 @@ + + + + backend.voicent.call.line.tree.view + backend.voicent.call.line + + + + + + + + + + + + backend.voicent.call.line.form.view + backend.voicent.call.line + +
+ +
+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
diff --git a/connector_voicent/views/res_partner.xml b/connector_voicent/views/res_partner.xml new file mode 100644 index 0000000..805002f --- /dev/null +++ b/connector_voicent/views/res_partner.xml @@ -0,0 +1,15 @@ + + + + view.res.partner.form + res.partner + + + + + + + + + diff --git a/oca_dependencies.txt b/oca_dependencies.txt index f3ae436..4e478c8 100644 --- a/oca_dependencies.txt +++ b/oca_dependencies.txt @@ -1,2 +1,4 @@ +connector +queue server-tools web