Skip to content
Snippets Groups Projects
Commit 0d2a66f8 authored by Peter Rotich's avatar Peter Rotich
Browse files

Merge ticket edit and typeahead

parents 1775aba9 705893de
No related branches found
No related tags found
No related merge requests found
......@@ -238,6 +238,9 @@ class TicketsAjaxAPI extends AjaxController {
$options[]=array('action'=>'Post Note','url'=>"tickets.php?id=$tid#note");
if($thisstaff->canEditTickets())
$options[]=array('action'=>'Edit Ticket','url'=>"tickets.php?id=$tid&a=edit");
if($options) {
echo '<ul class="tip_menu">';
foreach($options as $option)
......
......@@ -19,91 +19,113 @@ class SLA {
var $info;
function SLA($id){
function SLA($id) {
$this->id=0;
$this->load($id);
}
function load($id) {
function load($id=0) {
if(!$id && !($id=$this->getId()))
return false;
$sql='SELECT * FROM '.SLA_TABLE.' WHERE id='.db_input($id);
if(($res=db_query($sql)) && db_num_rows($res)) {
$info=db_fetch_array($res);
$this->id=$info['id'];
$this->info=$info;
return true;
}
return false;
if(!($res=db_query($sql)) || !db_num_rows($res))
return false;
$this->ht=db_fetch_array($res);
$this->id=$this->ht['id'];
return true;
}
function reload() {
return $this->load($this->getId());
return $this->load();
}
function getId(){
function getId() {
return $this->id;
}
function getName(){
return $this->info['name'];
function getName() {
return $this->ht['name'];
}
function getGracePeriod(){
return $this->info['grace_period'];
function getGracePeriod() {
return $this->ht['grace_period'];
}
function getNotes(){
return $this->info['notes'];
function getNotes() {
return $this->ht['notes'];
}
function getInfo(){
return $this->info;
function getHashtable() {
return $this->ht;
}
function isActive(){
return ($this->info['isactive']);
function getInfo() {
return $this->getHashtable();
}
function sendAlerts(){
return (!$this->info['disable_overdue_alerts']);
function isActive() {
return ($this->ht['isactive']);
}
function priorityEscalation(){
return ($this->info['enable_priority_escalation']);
function sendAlerts() {
return (!$this->ht['disable_overdue_alerts']);
}
function update($vars,&$errors){
if(SLA::save($this->getId(),$vars,$errors)){
$this->reload();
return true;
}
function priorityEscalation() {
return ($this->ht['enable_priority_escalation']);
}
function update($vars,&$errors) {
return false;
if(!SLA::save($this->getId(),$vars,$errors))
return false;
$this->reload();
return true;
}
function delete(){
function delete() {
global $cfg;
if($cfg && $cfg->getDefaultSLAId()==$this->getId())
if(!$cfg || $cfg->getDefaultSLAId()==$this->getId())
return false;
$id=$this->getId();
$sql='DELETE FROM '.SLA_TABLE.' WHERE id='.db_input($id).' LIMIT 1';
if(db_query($sql) && ($num=db_affected_rows())){
if(db_query($sql) && ($num=db_affected_rows())) {
db_query('UPDATE '.DEPT_TABLE.' SET sla_id=0 WHERE sla_id='.db_input($id));
db_query('UPDATE '.TOPIC_TABLE.' SET sla_id=0 WHERE sla_id='.db_input($id));
db_query('UPDATE '.TICKET_TABLE.' SET sla_id=0 WHERE sla_id='.db_input($id));
db_query('UPDATE '.TICKET_TABLE.' SET sla_id='.db_input($cfg->getDefaultSLAId()).' WHERE sla_id='.db_input($id));
}
return $num;
}
/** static functions **/
function create($vars,&$errors){
function create($vars,&$errors) {
return SLA::save(0,$vars,$errors);
}
function getIdByName($name){
function getSLAs() {
$slas=array();
$sql='SELECT id, name FROM '.SLA_TABLE;
if(($res=db_query($sql)) && db_num_rows($res)) {
while(list($id, $name)=db_fetch_row($res))
$slas[$id]=$name;
}
return $slas;
}
function getIdByName($name) {
$sql='SELECT id FROM '.SLA_TABLE.' WHERE name='.db_input($name);
if(($res=db_query($sql)) && db_num_rows($res))
......@@ -112,11 +134,11 @@ class SLA {
return $id;
}
function lookup($id){
function lookup($id) {
return ($id && is_numeric($id) && ($sla= new SLA($id)) && $sla->getId()==$id)?$sla:null;
}
function save($id,$vars,&$errors){
function save($id,$vars,&$errors) {
if(!$vars['grace_period'])
......
......@@ -24,6 +24,7 @@ include_once(INCLUDE_DIR.'class.attachment.php');
include_once(INCLUDE_DIR.'class.banlist.php');
include_once(INCLUDE_DIR.'class.template.php');
include_once(INCLUDE_DIR.'class.priority.php');
include_once(INCLUDE_DIR.'class.sla.php');
class Ticket{
......@@ -285,6 +286,28 @@ class Ticket{
return $this->ht['ip_address'];
}
function getHashtable() {
return $this->ht;
}
function getUpdateInfo() {
$info=array('name' => $this->getName(),
'email' => $this->getEmail(),
'phone' => $this->getPhone(),
'phone_ext' => $this->getPhoneExt(),
'subject' => $this->getSubject(),
'source' => $this->getSource(),
'topicId' => $this->getTopicId(),
'priorityId' => $this->getPriorityId(),
'slaId' => $this->getSLAId(),
'duedate' => $this->getDueDate()?(Format::userdate('m/d/Y', Misc::db2gmtime($this->getDueDate()))):'',
'time' => $this->getDueDate()?(Format::userdate('G:i', Misc::db2gmtime($this->getDueDate()))):'',
);
return $info;
}
function getLockId() {
return $this->lock_id;
}
......@@ -362,6 +385,17 @@ class Ticket{
return '';
}
function getAssignees() {
$assignees='';
if($staff=$this->getStaff())
$assignees.=$staff->getName();
if($team=$this->getTeam())
$assignees.=$team->getName();
return $assignees;
}
function getTopicId(){
return $this->topic_id;
......@@ -1459,8 +1493,7 @@ class Ticket{
function deleteAttachments(){
global $cfg;
$deleted=0;
// Clear reference table
$res=db_query('DELETE FROM '.TICKET_ATTACHMENT_TABLE.' WHERE ticket_id='.db_input($this->getId()));
......@@ -1473,17 +1506,90 @@ class Ticket{
function delete(){
$sql='DELETE FROM '.TICKET_TABLE.' WHERE ticket_id='.$this->getId().' LIMIT 1';
if(!db_query($sql) || !db_affected_rows())
return false;
db_query('DELETE FROM '.TICKET_MESSAGE_TABLE.' WHERE ticket_id='.db_input($this->getId()));
db_query('DELETE FROM '.TICKET_RESPONSE_TABLE.' WHERE ticket_id='.db_input($this->getId()));
db_query('DELETE FROM '.TICKET_NOTE_TABLE.' WHERE ticket_id='.db_input($this->getId()));
$this->deleteAttachments();
return true;
}
function update($vars, &$errors) {
global $cfg, $thisstaff;
if(!$cfg || !$thisstaff || !$thisstaff->canEditTickets())
return false;
$fields=array();
$fields['name'] = array('type'=>'string', 'required'=>1, 'error'=>'Name required');
$fields['email'] = array('type'=>'email', 'required'=>1, 'error'=>'Valid email required');
$fields['subject'] = array('type'=>'string', 'required'=>1, 'error'=>'Subject required');
$fields['topicId'] = array('type'=>'int', 'required'=>1, 'error'=>'Help topic required');
$fields['slaId'] = array('type'=>'int', 'required'=>1, 'error'=>'SLA required');
$fields['priorityId'] = array('type'=>'int', 'required'=>1, 'error'=>'Priority required');
$fields['phone'] = array('type'=>'phone', 'required'=>0, 'error'=>'Valid phone # required');
$fields['duedate'] = array('type'=>'date', 'required'=>0, 'error'=>'Invalid date - must be MM/DD/YY');
$fields['note'] = array('type'=>'text', 'required'=>1, 'error'=>'Reason for the update required');
if(!Validator::process($fields, $vars, $errors) && !$errors['err'])
$errors['err'] ='Missing or invalid data - check the errors and try again';
if($vars['duedate']) {
if($this->isClosed())
$errors['duedate']='Duedate can NOT be set on a closed ticket';
elseif(!$vars['time'] || strpos($vars['time'],':')===false)
$errors['time']='Select time';
elseif(strtotime($vars['duedate'].' '.$vars['time'])===false)
$errors['duedate']='Invalid duedate';
elseif(strtotime($vars['duedate'].' '.$vars['time'])<=time())
$errors['duedate']='Due date must be in the future';
}
//Make sure phone extension is valid
if($vars['phone_ext'] ) {
if(!is_numeric($vars['phone_ext']) && !$errors['phone'])
$errors['phone']='Invalid phone ext.';
elseif(!$vars['phone']) //make sure they just didn't enter ext without phone #
$errors['phone']='Phone number required';
}
if($errors) return false;
$sql='UPDATE '.TICKET_TABLE.' SET updated=NOW() '
.' ,email='.db_input($vars['email'])
.' ,name='.db_input(Format::striptags($vars['name']))
.' ,subject='.db_input(Format::striptags($vars['subject']))
.' ,phone="'.db_input($vars['phone'],false).'"'
.' ,phone_ext='.db_input($vars['phone_ext']?$vars['phone_ext']:NULL)
.' ,priority_id='.db_input($vars['priorityId'])
.' ,topic_id='.db_input($vars['topicId'])
.' ,sla_id='.db_input($vars['slaId'])
.' ,duedate='.($vars['duedate']?db_input(date('Y-m-d G:i',Misc::dbtime($vars['duedate'].' '.$vars['time']))):'NULL');
if($vars['duedate']) { //We are setting new duedate...
$sql.=' ,isoverdue=0';
}
$sql.=' WHERE ticket_id='.db_input($this->getId());
if(!db_query($sql) || !db_affected_rows())
return false;
if(!$vars['note'])
$vars['note']=sprintf('Ticket Updated by %s', $thisstaff->getName());
$this->postNote('Ticket Updated', $vars['note']);
$this->reload();
if(db_query('DELETE FROM '.TICKET_TABLE.' WHERE ticket_id='.$this->getId().' LIMIT 1') && db_affected_rows()):
db_query('DELETE FROM '.TICKET_MESSAGE_TABLE.' WHERE ticket_id='.db_input($this->getId()));
db_query('DELETE FROM '.TICKET_RESPONSE_TABLE.' WHERE ticket_id='.db_input($this->getId()));
db_query('DELETE FROM '.TICKET_NOTE_TABLE.' WHERE ticket_id='.db_input($this->getId()));
$this->deleteAttachments();
return TRUE;
endif;
return FALSE;
return true;
}
/*============== Static functions. Use Ticket::function(params); ==================*/
function getIdByExtId($extid) {
......@@ -1599,84 +1705,6 @@ class Ticket{
return db_fetch_array(db_query($sql));
}
//FIXME: Refactor the code for version 1.7
function update($var,&$errors) {
global $cfg,$thisstaff;
$fields=array();
$fields['name'] = array('type'=>'string', 'required'=>1, 'error'=>'Name required');
$fields['email'] = array('type'=>'email', 'required'=>1, 'error'=>'Email is required');
$fields['note'] = array('type'=>'text', 'required'=>1, 'error'=>'Reason for the update required');
$fields['subject'] = array('type'=>'string', 'required'=>1, 'error'=>'Subject required');
$fields['topicId'] = array('type'=>'int', 'required'=>0, 'error'=>'Invalid Selection');
$fields['pri'] = array('type'=>'int', 'required'=>0, 'error'=>'Invalid Priority');
$fields['phone'] = array('type'=>'phone', 'required'=>0, 'error'=>'Valid phone # required');
$fields['duedate'] = array('type'=>'date', 'required'=>0, 'error'=>'Invalid date - must be MM/DD/YY');
$params = new Validator($fields);
if(!$params->validate($var)){
$errors=array_merge($errors,$params->errors());
}
if($var['duedate']){
if($this->isClosed())
$errors['duedate']='Duedate can NOT be set on a closed ticket';
elseif(!$var['time'] || strpos($var['time'],':')===false)
$errors['time']='Select time';
elseif(strtotime($var['duedate'].' '.$var['time'])===false)
$errors['duedate']='Invalid duedate';
elseif(strtotime($var['duedate'].' '.$var['time'])<=time())
$errors['duedate']='Due date must be in the future';
}
//Make sure phone extension is valid
if($var['phone_ext'] ) {
if(!is_numeric($var['phone_ext']) && !$errors['phone'])
$errors['phone']='Invalid phone ext.';
elseif(!$var['phone']) //make sure they just didn't enter ext without phone #
$errors['phone']='Phone number required';
}
$cleartopic=false;
$topicDesc='';
if($var['topicId'] && ($topic= new Topic($var['topicId'])) && $topic->getId()) {
$topicDesc=$topic->getName();
}elseif(!$var['topicId'] && $this->getTopicId()){
$topicDesc='';
$cleartopic=true;
}
if(!$errors){
$sql='UPDATE '.TICKET_TABLE.' SET updated=NOW() '.
',email='.db_input($var['email']).
',name='.db_input(Format::striptags($var['name'])).
',subject='.db_input(Format::striptags($var['subject'])).
',phone="'.db_input($var['phone'],false).'"'.
',phone_ext='.db_input($var['phone_ext']?$var['phone_ext']:NULL).
',priority_id='.db_input($var['pri']).
',topic_id='.db_input($var['topicId']).
',duedate='.($var['duedate']?db_input(date('Y-m-d G:i',Misc::dbtime($var['duedate'].' '.$var['time']))):'NULL');
if($var['duedate']) { //We are setting new duedate...
$sql.=',isoverdue=0';
}
if($topicDesc || $cleartopic) { //we're overwriting previous topic.
$sql.=',helptopic='.db_input($topicDesc);
}
$sql.=' WHERE ticket_id='.db_input($this->getId());
//echo $sql;
if(db_query($sql)){
$this->postNote('Ticket Updated',$var['note']);
$this->reload();
return true;
}
}
return false;
}
/*
* The mother of all functions...You break it you fix it!
*
......@@ -1805,7 +1833,7 @@ class Ticket{
// OK...just do it.
$deptId=$vars['deptId']; //pre-selected Dept if any.
$priorityId=$vars['pri'];
$priorityId=$vars['priorityId'];
$source=ucfirst($vars['source']);
$topic=NULL;
// Intenal mapping magic...see if we need to overwrite anything
......
<?php
if(!defined('OSTSCPINC') || !$thisstaff || !$thisstaff->canEditTickets() || !$ticket) die('Access Denied');
$info=Format::htmlchars(($errors && $_POST)?$_POST:$ticket->getUpdateInfo());
?>
<form action="tickets.php?id=<?php echo $ticket->getId(); ?>&a=edit" method="post" id="save" enctype="multipart/form-data">
<input type="hidden" name="do" value="update">
<input type="hidden" name="a" value="edit">
<input type="hidden" name="id" value="<?php echo $ticket->getId(); ?>">
<h2>Update Ticket# <?php echo $ticket->getExtId(); ?></h2>
<table class="form_table" width="940" border="0" cellspacing="0" cellpadding="2">
<thead>
<tr>
<th colspan="2">
<h4>Ticket Update</h4>
<em><strong>User Information</strong>: Make sure the email address is valid.</em>
</th>
</tr>
</thead>
<tbody>
<tr>
<td width="160" class="required">
Full Name:
</td>
<td>
<input type="text" size="45" name="name" value="<?php echo $info['name']; ?>">
&nbsp;<span class="error">*&nbsp;<?php echo $errors['name']; ?></span>
</td>
</tr>
<tr>
<td width="160" class="required">
Email Address:
</td>
<td>
<input type="text" size="45" name="email" value="<?php echo $info['email']; ?>">
&nbsp;<span class="error">*&nbsp;<?php echo $errors['email']; ?></span>
</td>
</tr>
<tr>
<td width="160">
Phone Number:
</td>
<td>
<input type="text" size="18" name="phone" value="<?php echo $info['phone']; ?>">
&nbsp;<span class="error">&nbsp;<?php echo $errors['phone']; ?></span>
Ext <input type="text" size="5" name="phone_ext" value="<?php echo $info['phone_ext']; ?>">
&nbsp;<span class="error">&nbsp;<?php echo $errors['phone_ext']; ?></span>
</td>
</tr>
<tr>
<th colspan="2">
<em><strong>Ticket Information</strong>: Due date overwrites SLA's grace period.</em>
</th>
</tr>
<tr>
<td width="160" class="required">
Ticket Source:
</td>
<td>
<select name="source">
<option value="" selected >&mdash; Select Source &mdash;</option>
<option value="Phone" <?php echo ($info['source']=='Phone')?'selected="selected"':''; ?>>Phone</option>
<option value="Email" <?php echo ($info['source']=='Email')?'selected="selected"':''; ?>>Email</option>
<option value="Web" <?php echo ($info['source']=='Web')?'selected="selected"':''; ?>>Web</option>
<option value="API" <?php echo ($info['source']=='API')?'selected="selected"':''; ?>>API</option>
<option value="Other" <?php echo ($info['source']=='Other')?'selected="selected"':''; ?>>Other</option>
</select>
&nbsp;<font class="error"><b>*</b>&nbsp;<?=$errors['source']?></font>
</td>
</tr>
<tr>
<td width="160" class="required">
Help Topic:
</td>
<td>
<select name="topicId">
<option value="" selected >&mdash; Select Help Topic &mdash;</option>
<?php
if($topics=Topic::getHelpTopics()) {
foreach($topics as $id =>$name) {
echo sprintf('<option value="%d" %s>%s</option>',
$id, ($info['topicId']==$id)?'selected="selected"':'',$name);
}
}
?>
</select>
&nbsp;<font class="error"><b>*</b>&nbsp;<?=$errors['topicId']?></font>
</td>
</tr>
<tr>
<td width="160" class="required">
Priority Level:
</td>
<td>
<select name="priorityId">
<option value="" selected >&mdash; Select Priority &mdash;</option>
<?php
if($priorities=Priority::getPriorities()) {
foreach($priorities as $id =>$name) {
echo sprintf('<option value="%d" %s>%s</option>',
$id, ($info['priorityId']==$id)?'selected="selected"':'',$name);
}
}
?>
</select>
&nbsp;<font class="error">*&nbsp;<?=$errors['priorityId']?></font>
</td>
</tr>
<tr>
<td width="160" class="required">
SLA:
</td>
<td>
<select name="slaId">
<option value="" selected >&mdash; Select SLA &mdash;</option>
<?php
if($slas=SLA::getSLAs()) {
foreach($slas as $id =>$name) {
echo sprintf('<option value="%d" %s>%s</option>',
$id, ($info['slaId']==$id)?'selected="selected"':'',$name);
}
}
?>
</select>
&nbsp;<font class="error">*&nbsp;<?=$errors['slaId']?></font>
</td>
</tr>
<tr>
<td width="160" class="required">
Subject:
</td>
<td>
<input type="text" name="subject" size="60" value="<?=$info['subject']?>">
&nbsp;<font class="error">*&nbsp;<?=$errors['subject']?></font>
</td>
</tr>
<tr>
<td width="160">
Due Date:
</td>
<td>
<input id="duedate" name="duedate" value="<?php echo Format::htmlchars($info['duedate']); ?>" size="10"
onclick="event.cancelBubble=true;calendar(this);" autocomplete=OFF>
<a href="#" onclick="event.cancelBubble=true;calendar(getObj('duedate')); return false;"><img src='images/cal.png'border=0 alt=""></a>
&nbsp;&nbsp;
<?php
$min=$hr=null;
if($info['time'])
list($hr,$min)=explode(':',$info['time']);
echo Misc::timeDropdown($hr,$min,'time');
?>
&nbsp;<font class="error">&nbsp;<?=$errors['duedate']?>&nbsp;<?php echo $errors['time']; ?></font>
<em>Time is based on your time zone (GM <?php echo $thisstaff->getTZoffset(); ?>)</em>
</td>
</tr>
<tr>
<th colspan="2">
<em><strong>Internal Note</strong>: Reason for editing the ticket (required) <font class="error">&nbsp;<?php echo $errors['note'];?></font></em>
</th>
</tr>
<tr>
<td colspan=2>
<textarea name="note" cols="21" rows="6" style="width:80%;"><?php echo $info['note']; ?></textarea>
</td>
</tr>
</tbody>
</table>
<p style="padding-left:250px;">
<input type="submit" name="submit" value="Save">
<input type="reset" name="reset" value="Reset">
<input type="button" name="cancel" value="Cancel" onclick='window.location.href="tickets.php?id=<?php echo $ticket->getId(); ?>"'>
</p>
</form>
......@@ -116,7 +116,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
Subject:
</td>
<td>
<input type="text" name="subject" size="35" value="<?=$info['subject']?>">
<input type="text" name="subject" size="55" value="<?=$info['subject']?>">
&nbsp;<font class="error">*&nbsp;<?=$errors['subject']?></font>
</td>
</tr>
......@@ -305,6 +305,6 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
<p style="padding-left:250px;">
<input type="submit" name="submit" value="Open">
<input type="reset" name="reset" value="Reset">
<input type="button" name="cancel" value="Cancel" onclick='window.location.href="departments.php"'>
<input type="button" name="cancel" value="Cancel" onclick='window.location.href="tickets.php"'>
</p>
</form>
......@@ -157,15 +157,15 @@ if($_POST && !$errors):
$errors['note']='Error(s) occurred. Unable to post the note.';
}
break;
case 'edit':
case 'update':
$page='editticket.inc.php';
if(!$ticket || !$thisstaff->canEditTickets())
$errors['err']='Perm. Denied. You are not allowed to edit tickets';
elseif($ticket->update($_POST,$errors)){
elseif($ticket->update($_POST,$errors)) {
$msg='Ticket updated successfully';
$page='ticket.inc.php';
}elseif(!$errors['err']) {
$errors['err']='Error(s) occured! Try again.';
$_REQUEST['a'] = null;
} elseif(!$errors['err']) {
$errors['err']='Unable to update the ticket. Correct the errors below and try again!';
}
break;
case 'process':
......@@ -454,8 +454,8 @@ $inc = 'tickets.inc.php';
if($ticket) {
$nav->setActiveSubMenu(-1);
$inc = 'ticket-view.inc.php';
if($_REQUEST['a']=='edit' && $thisstaff->canEditTickets())
$errors['err'] ='Work in progress... ';
if($_REQUEST['a']=='edit' && $thisstaff->canEditTickets())
$inc = 'ticket-edit.inc.php';
}else {
$inc = 'tickets.inc.php';
if($_REQUEST['a']=='open' && $thisstaff->canCreateTickets())
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment