Whups as Helpdesk CVS Diff
| Newsgroups | gmane.comp.horde.whups |
|---|---|
| Message-ID | <[email protected]> |
All: I have to say that what everyone has done to Whups has been great! A while ago, back in June/July, I had brought up how I modified Whups a little to make it more of a Tech. Support Helpdesk, like for a company, campus, etc. rather than a Project Ticket System. This week, I needed to add a lot of features and decided to update. So, I cvs'd and applied my changes (which is actually 1/4 of the total code due to the improvements made) and have a CVS Diff ready to go (as of 5 mins ago). First let me say my goals for the system as it will explain a lot of what I have done. 1) Keep track of ticket creator information. Since we have to comply to the Sarbanes-Oxley system, we *have* to keep track of who created a ticket, and who commented on that ticket, etc., so the guest system wouldn't work. 2) Not have users login to create a ticket. We have a ton of people and getting them to login just would not work. If I could, then #1 would have already been solved. 3) Have User information in a single location. I didn't really want 2 versions of user information floating around, so I decided to use Turba to house that info (since I can integrate into our current system via. Ldap). There are some processes that I have changed, so let me go over them now. * Turba is integrated to keep track of user information. What I did was store the Turba ID as the ticket's user_id_requester. Each time it was referenced, I just did a getContact (actually a Whups function) to get their information to display. * When a ticket is created from a guest point of view, I have them just type in their userid (which happens to also be their e-mail '[email protected]'). This goes back to the lazy factor and people would be up in arms if they had to type in their entire e-mail address. * The block layout (along with mybugs) has an "Unassigned Tickets" listing so you can see all the tickets that haven't been picked up yet only from the queues which you are responsible for. I also modified it to display extra information about the ticket specifically relating to the user. * Added a "Take Ticket" link to make it easier to actually grab a ticket from the queue. * Added Whups_Ticket::ticketNumberFormat() to make the tickets a little easier to read as I created a custom numbering system (BranchID - year - ticketID). * The update tab was changed to allow a ticket to go back into the queue if the person wasn't able to handle it, accidentally grabbed it, etc. * The update tab actually makes you an owner if you choose "Assigned" - but it's hardcoded which at the moment I don't like, but it works. * A purely custom addition was that of using the turba field ['branchid'] throughout random parts of the code. This is because we have a lot of branches so this helps us sort out tickets. Of course this should be removed for general usage. A lot of the things I've done may seem silly, or pointless, but in reality this system has worked beautifully for us for the past several months. Additionally, it's saved the company thousands as other products like HEAT, etc. are extremely expensive. Take it for what you will, and let me know if you have any questions on why I did something the way I did. Regards, Mike Bydalek -- Whups mailing list - Join the hunt: http://horde.org/bounties/#whups Frequently Asked Questions: http://horde.org/faq/ To unsubscribe, mail: [email protected]
cvs.diff
(application/octet-stream, 17.6 KB)
Index: whups/mybugs.php
===================================================================
RCS file: /repository/whups/mybugs.php,v
retrieving revision 1.22
diff -r1.22 mybugs.php
31a32,57
> /* MMI: Add a unassigned tickets list to the mybugs page
> Get only the tickets from the queues you are responsible for
> */
> $queues = Whups::permissionsFilter($whups->getQueues(), 'queue', PERMS_EDIT);
>
> $utickets = array();
>
> foreach ($queues as $queue => $queueName) {
> $users = $whups->getQueueUsers($queue);
>
> if (in_array(Auth::getAuth(), $users)) {
> $info = array('uc' => true,
> 'queueid' => $queue);
> $queue_tickets = $whups->getTicketsByProperties($info);
> if (is_a($queue_tickets, 'PEAR_Error')) {
> $notification->push(sprintf(_("There was an error listing your open requests: %s"), $utickets->getMessage()), 'horde.error');
> }
> $utickets = array_merge($utickets, $queue_tickets);
> }
> }
>
> if (count($utickets)) {
> Whups::sortTickets($utickets, 'timestamp');
> }
> $unassigned_results = &new SearchResults(_("Unassigned Ticket Requests"));
>
75a102,105
> if (!empty($unassigned_results)) {
> $unassigned_results->results($utickets, $values);
> }
>
Index: whups/config/conf.xml
===================================================================
RCS file: /repository/whups/config/conf.xml,v
retrieving revision 1.22
diff -r1.22 conf.xml
30a31
> <configstring name="domain" required="true" desc="What domain name will be used for doing Windows Login lookups when creating new tickets? This will be appended to the username to do a lookup in the Address Book to get the user's information."></configstring>
Index: whups/lib/Create.php
===================================================================
RCS file: /repository/whups/lib/Create.php,v
retrieving revision 1.53
diff -r1.53 Create.php
30c30,31
< $this->addVariable(_("Your Email Address"), 'user_email', 'email', true);
---
> //MMI: Change the variable to allow for windows username
> $this->addVariable(_("Windows Login Name of Person to Help"), 'user_login', 'text', true, false, _("Enter the login name of the person who is having a problem."));
73a75,109
>
> /* MMI: Tack on default domain to the username they provide in Step 1
> and create a hidden variable 'requester' to allow use in later parts
> of the code */
> $login = Auth::getAuth()?Auth::getAuth():$vars->get('user_login');
> $email = $login . "@" . $conf['mail']['domain'];
>
> if ($vars->get('user_login') || Auth::getAuth()) {
> global $registry;
> /* MMI: Search Turba for an email matching $email */
> $args = array('names' => array($email),
> 'fields' => array('email'));
> $results = $registry->call('clients/searchClients', $args);
> $clientdetails = array_pop(array_pop($results));
>
> /* MMI: TODO: Figure out good way to present an error message here
> with a possible redirect */
> if (empty($clientdetails)) {
> /* Throw an invalid login and take back to step 1 */
> $url = 'ticket/create.php';
> header('Location: ' . Horde::applicationUrl(Util::addParameter($url, 'invalidlogin', $login), true));
> } else {
> /* MMI: $clientlist should be an arry with 1 value in form ['id' => 'name']
> which is the person we are submitting a ticket for
> so get the 'id' and 'name' into vars */
> $client_display = &$this->addVariable(_("User's Name"), 'user_display_name', 'text', true, true);
> $client = &$this->addHidden('', 'requester', 'text', false);
> $branch = &$this->addHidden('', 'branch', 'text', false);
> $email = &$this->addHidden('', 'user_email', 'text', false);
> $client_display->setDefault($clientdetails['name']);
> $client->setDefault($clientdetails['__key']);
> $branch->setDefault($clientdetails['branchid']);
> $email->setDefault($clientdetails['email']);
> }
> }
106a143,158
> /* MMI: Add IP information for guests only */
> $ipaddr_params = array('regex' => '/^(0?0?\d|[01]?\d\d|2[0-4]\d|25[0-5])\.(0?0?\d|[01]?\d\d|2[0-4]\d|25[0-5])\.(0?0?\d|[01]?\d\d|2[0-4]\d|25[0-5])\.(0?0?\d|[01]?\d\d|2[0-4]\d|25[0-5])$/',
> 'size' => 16,
> 'maxlength' => 15);
> $ipaddr = &$this->addVariable(_("IP Address of Problem Computer"), 'ipaddress', 'text', true, null, _("<b>Be sure this is the IP of the computer we will need to connect to!</b><br> If you are entering this ticket for someone else, please be sure to get their IP address."), $ipaddr_params);
>
> if (!Auth::getAuth()) {
> if (preg_match("/172.20/i", $_SERVER['REMOTE_ADDR'])) {
> $ipaddr->setDefault($_SERVER['REMOTE_ADDR']);
> } else {
> $ipaddr->setDefault('192.168.');
> }
> } else {
> $ipaddr->setDefault($_SERVER['REMOTE_ADDR']);
> }
>
Index: whups/lib/Driver.php
===================================================================
RCS file: /repository/whups/lib/Driver.php,v
retrieving revision 1.128
diff -r1.128 Driver.php
55c55,59
< $history[$transaction]['user_id'] = $row['user_id'];
---
>
> /* Check if 'user_id' is a Turba ID, if so, use that information
> to populate the comment's creators name */
> $user = Whups::getUserInfo($row['user_id']);
> $history[$transaction]['user_id'] = isset($user['name'])?$user['name']:$row['user_id'];
182a187,192
>
> /* MMI: Fudge to set ['email'] to $user if it's an e-mail address */
> if (eregi("@", $user) && empty($details['email'])) {
> $details['email'] = $user;
> }
>
188c198,206
< $mails[$key][] = $email;
---
>
> /* MMI: If the recipient has an @ symbol in it, then we know we want
> * to send it to this person, which usually is the person taking the ticket */
> if (eregi("@", $user)) {
> $mails[$key][] = $user;
> $headers['To'] = MIME::encodeAddress($user);
> } else {
> $mails[$key][] = $email;
> }
Index: whups/lib/Ticket.php
===================================================================
RCS file: /repository/whups/lib/Ticket.php,v
retrieving revision 1.25
diff -r1.25 Ticket.php
362a363,367
>
> /* MMI: Add custom fields to be displayed */
> $user = Whups::getUserInfo($this->get('user_id_requester'));
> $vars->set('employee', $user['name']);
> $vars->set('branch', $user['company']);
411c416
< $message .= ' ' . String::pad(_("Ticket"), $length) . ' | ' . $this->_id . "\n";
---
> $message .= ' ' . String::pad(_("Ticket"), $length) . ' | #' . $this->formatTicketNumber($this->_id) . "\n";
475a481,492
> /**
> * Format ticket to ###-##-####
> */
> function formatTicketNumber($tid)
> {
> if (strlen($tid) != 9) {
> return $tid;
> }
>
> return substr($tid, 0, 3) . "-" . substr($tid, 3, 2) . "-" . substr($tid, 5, 4);
> }
>
488a506,517
> /* MMI: Create 'take ticket' link
> TODO: Only display if ticket isn't assigned or higher
> */
> if ($whups->getStateName($vars->get('type'), $vars->get('state')) == "Unassigned" && !$vars->get('taken') && Auth::getAuth()) {
> $url = Util::addParameter(Horde::applicationUrl('ticket/people.php?formname=assignticketform'), 'id', $vars->get('id'));
> $url = Util::addParameter($url, 'taken', true);
> $takelink = array('text' => _("Take Ticket"), 'url' => $url);
> $this->addVariable('', 'link', 'link', false, true, null, array($takelink));
> }
>
> $this->addVariable(_("Employee Name"), 'employee', 'text', true, true);
> $this->addVariable(_("Branch"), 'branch', 'text', true, true);
504c533
< $this->addVariable(_("Requester"), 'user_id_requester', 'email', true, true, null, array(false, true));
---
> //$this->addVariable(_("Requester"), 'user_id_requester', 'email', true, true, null, array(false, true));
Index: whups/lib/Whups.php
===================================================================
RCS file: /repository/whups/lib/Whups.php,v
retrieving revision 1.123
diff -r1.123 Whups.php
399a400,402
> _("User") => 'name',
> _("Branch") => 'branch',
> _("Number") => 'branchid',
566a570,575
> function getUserInfo($key) {
> global $registry;
> $args = array('key' => $key);
> return $registry->call('clients/getClient', $args);
> }
>
Index: whups/lib/Block/summary.php
===================================================================
RCS file: /repository/whups/lib/Block/summary.php,v
retrieving revision 1.20
diff -r1.20 summary.php
73a74,103
> /* MMI: Add a unassigned tickets list to the portal block
> Get only the tickets from the queues you are responsible for
> */
> $queues = Whups::permissionsFilter($whups->getQueues(), 'queue', PERMS_EDIT);
>
> $unassigned = array();
>
> foreach ($queues as $queue => $queueName) {
> $users = $whups->getQueueUsers($queue);
> if (in_array(Auth::getAuth(), $users)) {
> $info = array('uc' => true,
> 'queueid' => $queue);
> $queue_tickets = $whups->getTicketsByProperties($info);
> if (is_a($queue_tickets, 'PEAR_Error')) {
> return $queue_tickets;
> }
> $unassigned = array_merge($unassigned, $queue_tickets);
> }
> }
>
> $blank = false;
> $html .= '<tr><td colspan="7" class="text"><b>' . _("Unassigned Tickets") . '</b></td></tr>';
> if (count($unassigned)) {
> Whups::sortTickets($unassigned, 'timestamp');
> $this->_list($unassigned, $html);
> } else {
> $html .= sprintf('<tr><td><i>%s</i></td></tr>', _("There are no open tickets"));
> $blank = true;
> }
>
85c115,117
< global $prefs;
---
> /* MMI: Include for formatTicketNumber function */
> require_once dirname(__FILE__) . '/../Ticket.php';
> global $prefs, $whups;
87a120,122
> /* MMI: Get user information for this ticket */
> $user = Whups::getUserInfo($ticket['user_id_requester']);
>
92c127
< $ticket['summary'] = '[' . $ticket['id'] . '] ' . $ticket['summary'];
---
> $ticket['summary'] = '[#' . Whups_Ticket::formatTicketNumber($ticket['id']) . '] ' . $ticket['summary'];
94a130,133
> $html .= '<td valign="top" class="text" nowrap="nowrap">' . $user['name'] . '</td>';
> $html .= '<td valign="top" class="text" nowrap="nowrap">' . $user['company'] . '</td>';
> $html .= '<td valign="top" class="text" nowrap="nowrap">' . $user['branchid'] . '</td>';
> $html .= '<td valign="top" class="text" nowrap="nowrap">' . $ticket['queue_name'] . '</td>';
96c135,136
< $html .= '<td valign="top" class="text">' . $ticket['state_name'] . '</td></tr>';
---
> $html .= '<td valign="top" class="text" nowrap="nowrap">' . Horde_Form_Type_date::getFormattedTime($ticket['timestamp'], '%c', false) . '</td>';
> $html .= '</tr>';
100c140
< }
---
> }
\ No newline at end of file
Index: whups/lib/Driver/sql.php
===================================================================
RCS file: /repository/whups/lib/Driver/sql.php,v
retrieving revision 1.200
diff -r1.200 sql.php
180a181,183
> // MMI: Prepend initial comment with the IP Address
> $comment = "IP Address: " . $info['ipaddress'] . "\n" . $info['comment'];
>
183c186,192
< $ticketId = $this->_db->nextId('whups_tickets');
---
> // MMI: Unique numbering scheme for ticket ID's
> // Dynamically prepend Branch number to ticket ID
> if (!isset($info['branch']) || $info['branch'] < 100) {
> $info['branch'] = 999;
> }
> $ticketId = ($info['branch'] . date("y")) * 10000 + $this->_db->nextId('whups_tickets');
>
673a683,685
> /* MMI: Add filter for queueId */
> $qid = isset($info['queueid']) ? ' AND whups_tickets.queue_id = ' . $this->_db->quote($info['queueid']) : '';
>
676,677c688,689
< $uc || $res || $new || $ass || $cat) {
< $where = $this->_addWhere($where, 1, "(whups_tickets.type_id = whups_states.type_id AND whups_tickets.state_id = whups_states.state_id$nouc$nores$nonew$noass$uc$res$new$ass$cat)");
---
> $uc || $res || $new || $ass || $cat || $qid) {
> $where = $this->_addWhere($where, 1, "(whups_tickets.type_id = whups_states.type_id AND whups_tickets.state_id = whups_states.state_id$nouc$nores$nonew$noass$uc$res$new$ass$cat$qid)");
1694a1707,1714
> /* MMI: Go through array and change Turba ID's to real e-mails */
> foreach ($users as $user) {
> if ($detail = Whups::getUserInfo($user)) {
> unset($users[$user]);
> $users[$detail['email']] = $detail['email'];
> }
> }
>
Index: whups/templates/comment.inc
===================================================================
RCS file: /repository/whups/templates/comment.inc,v
retrieving revision 1.60
diff -r1.60 comment.inc
100a101,109
>
> /* MMI: Get User's name to display */
> $user = Whups::getUserInfo($vars->get('user_id'));
> if (empty($user)) {
> $name = Whups::formatUser($vars->get('user_id'), false, true, true);
> } else {
> $name = $user['name'];
> }
>
104c113
< <td width="20%" class="<?php echo $class ?>_m" valign="top"><?php echo Whups::formatUser($vars->get('user_id'), false, true, true) ?></td>
---
> <td width="20%" class="<?php echo $class ?>_m" valign="top"><?php echo $name ?></td>
Index: whups/templates/searchresults.inc
===================================================================
RCS file: /repository/whups/templates/searchresults.inc,v
retrieving revision 1.44
diff -r1.44 searchresults.inc
87a88,93
> /* MMI: Get the user information for this ticket to print */
> $user = Whups::getUserInfo($info['user_id_requester']);
> $info['name'] = $user['name'];
> $info['branch'] = $user['company'];
> $info['branchid'] = $user['branchid'];
>
Index: whups/ticket/create.php
===================================================================
RCS file: /repository/whups/ticket/create.php,v
retrieving revision 1.9
diff -r1.9 create.php
16a17,20
> /* MMI: Check to see if we had an invalid login */
> if (Util::getFormData('invalidlogin')) {
> $notification->push(sprintf(_("No User was found with a login of '%s'. Please enter a new name."), Util::getFormData('invalidlogin')), 'horde.error');
> }
151c155
< $ticket = &Whups_Ticket::newTicket($info, Auth::getAuth());
---
> $ticket = &Whups_Ticket::newTicket($info, $info['requester']);
157c161,162
< $notification->push(sprintf(_("Your ticket ID is %s. An appropriate person has been notified of this request."), $ticket->getId()), 'horde.success');
---
> /* MMI: Format Ticket */
> $notification->push(sprintf(_("Your ticket ID is %s. An appropriate person has been notified of this request."), Whups_Ticket::formatTicketNumber($ticket->getId())), 'horde.success');
Index: whups/ticket/index.php
===================================================================
RCS file: /repository/whups/ticket/index.php,v
retrieving revision 1.10
diff -r1.10 index.php
17c17
< require_once 'Horde/Text/Filter.php';
---
> require_once 'Horde/Text/Filter.php';
23c23,24
< $title = '[#' . $ticket->getId() . '] ' . $ticket->get('summary');
---
> /* MMI: Format Ticket Number */
> $title = '[#' . Whups_Ticket::formatTicketNumber($ticket->getId()) . '] ' . $ticket->get('summary');
Index: whups/ticket/people.php
===================================================================
RCS file: /repository/whups/ticket/people.php,v
retrieving revision 1.5
diff -r1.5 people.php
96a97,100
> /* MMI: Set the owner to the person who clicked the Take Ticket link if possible */
> if (empty($info['owners']) && empty($info['group_owners'])) {
> $info['owners'] = ("user:" . Auth::getAuth());
> }
Index: whups/ticket/update.php
===================================================================
RCS file: /repository/whups/ticket/update.php,v
retrieving revision 1.9
diff -r1.9 update.php
45c45
< $this->addVariable(_("State"), 'state', 'enum', true, false, null, array($whups->getStates($type, '', 'unconfirmed')));
---
> $this->addVariable(_("State"), 'state', 'enum', true, false, null, array($whups->getStates($type, '', '')));
53c53
< $var = &$this->addVariable($name, "a$id", 'text', false);
---
> $var = &$this->addVariable($name, "$id", 'text', false);
102a103,108
> if ($info['state'] == 56) {
> $ticket->change('owners', '');
> } else if($info['state'] == 58) {
> $ticket->change('owners', array("user:" . Auth::getAuth()));
> }
>