Skip to content
blak3r edited this page Jun 18, 2012 · 27 revisions

There are a lot of things that could be done to improve this project... Most of which don't really learning any of the domain specific Asterisk backend stuff. Would love to collaborate with people on this project and make it even better. So, any help would be greatly appreciated. Don't be shy about editing this page or any of the documentation for that matter. That's the part many of us like least!

I'll happily expand and give guidance on how to best implement features. Best way is to create an enhancement issue and i'll chime in with more details on it.

Table of Contents

Features

  • Have Button to create a new contact when inbound number isn't recognized... (Add to contact--> create new or add to existing) == basically done... probably should get an icon instead of using text.
  • Have ability to assign a call to a contact but not change add phone to the contact. For example, when you join a conference call... you need to be able to assign the call to the contact but can't do it automatically since conf. call number may be generic. -- I added code to make popup appear... but have no way of detecting the popup window was closed. You can't do an onchange on the form input fields it sets. onchange doesn't work when changed programatically...
  • Have ability to "Add to Existing Contact", allow user to click a button, select the contact and then select which phone to add it to. The UI for selecting the contact would be same as above. Prompting the user to select which phone field to add it to is less cookie cutter.
  • Add Icons for things like "Create Meeting"... etc. Internally at my company we use Sugar PRO which has quick select icons across the top so i'm not planning on adding these. But, it's been a highly requested feature.
  • Update language files for german and whatever the other language is.
  • Add Transfer Support (See Enhancements in Issues).

Minor Bugs

  • $sugar_config['asterisk_dialin_ext_match'] = 'Local\/(?:.*?)(\d\d\d?\d?\d?)@'; -- Make this take 3-11 digits. If longer then say 5 characters we need to implement a method to look at users's mobile phones.
  • See issues for bug on RingGroups

Other Cool New Features

  • Better handling for answering on mobile phone through a ring group. I forget if call window appears.
  • Would be cool if we displayed voicemail inside sugar. From what i've read this sounds doable given the options in AMI.
  • Make a "Call Controller" like window that would show the status of every current call in the system. It'd serve as a "presence" app as well. This would probably only be feasible for small implementations though.

Call Recording Support

  • Ability to record the call... I seems this is possible to do through AMI, so probably could hook it in to asteriskLogger and not need to create a custom dial command. http://www.voip-info.org/wiki/view/Asterisk+Manager+API+Action+Monitor.
  • Ideally I think we'd want to have a user setting for call recording preference... Ideally, we'd have AMI start the recording automatically when call starts and if by the end of the call the user presses the record button on the UI it'd retrieve it and add it to the call.
  • Where do we store the recordings? Do we leave them on the asterisk box or do we have to transfer them to sugar. (i'm guessing we'd have to transfer it to sugar or we'd have to expose files to the world.)

SugarCRM Architecture Improvements

Original plugin was developed in the sugar v4.5 days. A lot of effort has gone into modernizing it and making it upgrade safe but it's still has some rough edges. If you have any experience with developing for sugarcrm these would be a great way to help the project. These include:

Module Loader / Package

  • Fields are added to User, but user needs to go into studio to then add them to template. (This is fine in 6.4 since Users are now "Studioable". Users who are using older versions of Sugar have to manually merge the user fields. This is discussed in more detail in the installation steps.
  • Installer manually drop/creates a table in the mysql database.
    • At the very least we should detect and inform the user of this...
    • Long term solution would be to use the sugarcrm module builder to create the base package instead. Then let sugarcrm handle all the database creation. This would also make the asterisk_log table usable in reports/etc. I think I stopped because I wasn't sure how you ever. This fix should coincide with mysql refactorings.
  • Installer adds several entry points in an install script. Is there a way to do this in the manifest?
  • System Configuration settings update. The project uses a script called Configurator to create the admin panels. It's a hassle to add a new config option requires making changes in at least 3-4 places. I think since the package was originally written System settings were given a major facelift and their now more metadata driven. Not sure if we can switch over to the newer approach without converting entire project over to a module bean first...

Performance Improvements

I suspect as larger companies start using this plugin... Performance issues are going to crop up. If you're a DBA or have any experience with database query tuning. An hour of your time would be greatly appreciated.

Issue 1: Optimize callListener.php

The CallListener.php class is called by every active browser tab that each user has open about every 2-5 seconds (depending on the AJAX poll rate you configured). That means if you had 10 users logged into sugar, each with 3 browser tabs open, and a poll rate of 2000ms. That's 30 requests/2 minutes --> 15 requests per second. Each of those requests is going to require at least one DB query. Therefore, making callListener.php return as quickly as possible is important for scalability.

  1. Optimize the query that executes against the asterisk_log table. It selects any recent calls that have occurred in the last hour which haven't been closed by the user. I have very little experience with optimizing database queries.
    $lastHour = date('Y-m-d H:i:s',time() - 1*60*60);
    $query = " SELECT * FROM asterisk_log WHERE \"$lastHour\" < timestampCall AND (uistate IS NULL OR uistate != \"Closed\") AND (callstate != 'NeedID') AND (channel LIKE 'SIP/{$current_user->asterisk_ext_c}%' OR channel LIKE 'Local%{$current_user->asterisk_ext_c}%')";
    1. Perhaps indexing the timestampCall column would improve performance?
    2. Alternatively, perhaps we should move older calls to an archive table periodically to reduce the number of records in the asterisk_log table that have to be scanned through.
EDIT: Some ideas for improving performance are discussed here. Only psuedocode is provided thus far: https://github.com/blak3r/yaai/commit/6e24e2df62ade78c2135ff8756952761faa0c452#commitcomment-1472245

Issue 2: Looking for matching contact based on phone number requires a full table scan

The other area which could be a big problem for people with very large databases is the phone number lookup. The way this is implemented uses either REGEX (in asterisk logger) or Replace statements (callListener). As a result I'm told this requires a full table scan to find matching contacts for a phone number. In general this shouldn't happen too often (only once a call in most cases)... but if you have 100,000 contacts then this might be of greater concern.

The reason table scan is necessary is because phone numbers aren't stored in the database in a standard format. As a result when you write a query you need to remove punctuation from the values in the database before comparing. So, in order to fix this we either a) Need to enforce a particular database storage format of phone numbers. (I think i've seen a plugin for sugar that does this already) b) Need to create a custom field for each phone_work, phone_mobile, etc that stores a version of the phone number without anything punctuation in it and then rewrite the queries to go against it.

Other

Originally, this plugin continued to make AJAX calls even after the user session died (like when you login on a different computer)... I changed the code to only schedule subsequent ajax calls when the previous call returns successful. This will work from a performance standpoint but if there is ever a case where a single request fails for a legit reason... the call popup will not appear until user refreshes their page. I think this is an acceptable tradeoff. I'm just documenting it here in case the call popups seem to be sporatically failing.

Configuration Changes Needed

We need a better way to manage system configuration settings. It's such a chore to do so I put it off. See architecture section.

  • Add gravatar one,
  • Add opencnam enabled / apikey
  • In asteriskLogger these regular expressions are hardcoded
    $rgDetectRegex = "/^Local\/RG/i"; // TODO make this a configuration option
    $rgCellRingRegex = "/^Local\/\d{7,10}/i";// TODO make this a configuration option.... This detects in a RG when an outside line is called (usually for a cellphone)... for some reason the cell shows up as the Channel (aka the source)... We detect this by finding a number thats at least 7-10 characters long..
  • Add option for what to do with very short inbound calls (ie inbound calls that weren't answered). Set status to "Missed" (which shows up in activities as open task) or Held (shows up in history).
  • Need configurable Channel detection in order to assign calls to users when they answer on cell phones.
  • Add a configurable option for how long to display call popups before they hide automatically. (Default is 1 hour)
  • Add a config option to disable including jquery (workaround to jquery issue).
  • (DONE) Need to add dialin prefix (its in sugarListener)
  • (DONE) Need to make config option for the dialout. Currently hardcoded to /SIP (in my case i need to do the Local/##@sugarsip/n... see CreateCall... for some reason I don't need it in callListener (presumably b/c it's already SIP at that point).
  • (DONE) Parametize the channel --> assigned user id detection, search for Local/LC-52@from-internal-4bbbb in asteriskLogger.
  • (DONE) Add max subject length to controller.php (also variables for IBC, OBC);

MISC

  • Verify Asterisk Logger fix to relogin to AMI works if asterisk goes down.
  • (DONE) Currently language is hardcoded in sugarListener.php
  • (DONE) AsteriskLogger -> findUser method --> add to query something to detect that user is "Active" so you don't get past employees matchin.
  • Process the AMI response in CallCreate / controller and display errors when they fail in javascript.
  • If the database cannot be accessed, this is the error message you get
! FATAL: Cannot find login credentials for user admin which is a bit misleading... as it makes you think soap is the problem

Asterisk Logger Issues

Stability

Don't know what conditions occur which cause it to lock up... But, occassionally asterisk logger will lock up. So, for production systems it's good to restart the script daily. In my commit around 4/12 I added some code which makes it relogin to AMI after 30 consecutive timeouts or errors. I'm hoping this will keep it from locking up indefinitely. There seems to be no easy way to check the status of a socket. UPDATE 5/7/2012: Still hasn't locked up on me.

Run as a Service

Also, I did some cursory research on how to make it run as a windows service. Couple good solutions here: Please post back if you find one. http://stackoverflow.com/questions/5952500/setting-a-php-script-as-a-windows-service. Please post back with what works.

On linux this much easier. See the utils folder included in the module for a sample script.

JQUERY Include or Not To Include on Page Problem Notes =

In my production system, I have 6.4.1. I have an extension which uses JQUERY already (1.4 something)...

In AsteriskJS.php if I force include: echo '<script type="text/javascript" src="custom/include/javascript/jquery/jquery.pack.js"></script>'; Asterisk Plugin works fine... But, my Dispage plugins fail. If I remove it so that the asterisk plugin doesn't include jquery, everything is fine.

This then of course will not work for people who don't already have jquery loaded.

On my demo 6.4 instance (I don't have any other extensions so jquery isn't loaded).

My conditional include solution I found on stackoverflow adds the script tag to the end of head. But, the code that is adding the code is in the body. (Where the after_ui_frame javascript is loaded)

As a result, I get Uncaught ReferenceError: $ is not defined

Experimented with surrounding my jquery wth some YUI code... but didn't have too much luck. I tried: YAHOO.util.Event.onDomReady --> nothing happened YAHOO.util.Event.onContentReady --> Uncaught ReferenceError: jQuery is not defined

So, for now the workaround is... by default we include jquery and the user can go in and comment it out if they run into problems.

UPDATE: At sugarcon it was recommended that we replace the jquery ready method with Sugar.Util.doWhen("jquery != undefined", I haven't tried it yet to see if that works.

http://forums.sugarcrm.com/f6/conditionally-include-jquery-if-other-plugins-already-havent-79391/#post277003