MOD: Pending - Autoclose for osTicket 1.7ST

This mod is an update of the old 1.6ST Pending Status and Autoclose mod for osTicket version 1.7ST. It adds a new "Pending" status that can be used on tickets, it also adds an autoclose feature for tickets that are left in pending for more then 5 days. Here are instructions on what the steps are and how to do so:

version: 1.7.b

note: some of this might not cut and paste correctly.

Summary:

  • 1. Install the additional files
  • 2. Update the database
  • 3. Editing the files
  • 4. Customizing the Mod

Step 1 - Install the additional Files

Copy the two files [preLogin.pgp and autoClose.php from archive below] to /include/staff

In /scp/login.php
circa line 31 locate:

require_once('index.php'); //Just incase header is messed up.

below add the following:

define("OMEGAPVTLTD",TRUE); //Make includes happy        
// do tasks prior to redirecting
include_once(INCLUDE_DIR.'staff/preLogin.php');

Files: pending-mod-files.zip

Step 2 - Update the database

update the database [please edit this to fit your installation] with the following MySQL Queries:

ALTER TABLE ost_ticket CHANGE status status ENUM('open','closed','pending') DEFAULT 'open';
ALTER TABLE ost_ticket_event CHANGE state state ENUM('created','closed','reopened','assigned','transferred','overdue','pending')


Step 3 - Editing the files

open \scp\tickets.php
circa line 42 locate:

$statusKeys=array('open'=>'Open','Reopen'=>'Open','Close'=>'Closed');

replace it with

$statusKeys=array('open'=>'Open','Reopen'=>'Open','Close'=>'Closed','pending'=>'Pending');

circa line 506 locate:

if($stats['overdue']) {
    $nav->addSubMenu(array('desc'=>'Overdue ('.number_format($stats['overdue']).')',
                           'title'=>'Stale Tickets',
                           'href'=>'tickets.php?status=overdue',
                           'iconclass'=>'overdueTickets'),
                        ($_REQUEST['status']=='overdue'));
    if(!$sysnotice && $stats['overdue']>10)
        $sysnotice=$stats['overdue'] .' overdue tickets!';
}

below it add:

        $nav->addSubMenu(array('desc'=>'Pending Tickets ('.number_format($stats['pending']).')',
                               'title'=>'Pending Tickets',
                               'href'=>'tickets.php?status=pending',
                               'iconclass'=>'closedTickets'),
                            (!$_REQUEST['status'] || $_REQUEST['status']=='Pending'));

open \include\class.ticket.php
circa line 113 locate:

    function isReopened() {
        return ($this->getReopenDate());
    }

below it add:

    function isPending(){
        return (strcasecmp($this->getStatus(),'Pending')==0);
    }

circa line 631 locate:

    function setStatus($status) {
        if(strcasecmp($this->getStatus(), $status)==0)
            return true; //No changes needed.
        switch(strtolower($status)) {
            case 'open':
                return $this->reopen();
                break;
            case 'closed':
                return $this->close();
                break;
        }
        return false;
    }

replace with:

    function setStatus($status) {
        if(strcasecmp($this->getStatus(), $status)==0)
            return true; //No changes needed.
        switch(strtolower($status)) {
            case 'open':
                return $this->reopen();
                break;
            case 'pending':
                return $this->pending();
                break;
            case 'closed':
                return $this->close();
                break;
        }
        return false;
    }

circa line 648 locate:

    function setState($state, $alerts=false) {
        switch(strtolower($state)) {
            case 'open':
                return $this->setStatus('open');
                break;
            case 'closed':
                return $this->setStatus('closed');
                break;
            case 'answered':
                return $this->setAnsweredState(1);
                break;
            case 'unanswered':
                return $this->setAnsweredState(0);
                break;
            case 'overdue':
                return $this->markOverdue();
                break;
            case 'notdue':
                return $this->clearOverdue();
                break;
            case 'unassined':
                return $this->unassign();
        }
        return false;
    }

replace with:

    function setState($state, $alerts=false) {
        switch(strtolower($state)) {
            case 'open':
                return $this->setStatus('open');
                break;
            case 'pending':
                return $this->setStatus('pending');
                break;
            case 'closed':
                return $this->setStatus('closed');
                break;
            case 'answered':
                return $this->setAnsweredState(1);
                break;
            case 'unanswered':
                return $this->setAnsweredState(0);
                break;
            case 'overdue':
                return $this->markOverdue();
                break;
            case 'notdue':
                return $this->clearOverdue();
                break;
            case 'unassined':
                return $this->unassign();
        }
        return false;
    }

circa line 688 locate:

    //Close the ticket
    function close() {
        global $thisstaff;
        $sql='UPDATE '.TICKET_TABLE.' SET closed=NOW(),isoverdue=0, duedate=NULL, updated=NOW(), 

status='.db_input('closed');
        if($thisstaff) //Give the closing  staff credit.
            $sql.=', staff_id='.db_input($thisstaff->getId());
        $sql.=' WHERE ticket_id='.db_input($this->getId());
        if(!db_query($sql) || !db_affected_rows())
            return false;
        $this->reload();
        $this->logEvent('closed');
        return true;
    }

above it add:

    //Mark Ticket as Pending
    function pending() {
        global $thisstaff;
        $sql='UPDATE '.TICKET_TABLE.' SET isoverdue=0, duedate=NULL, updated=NOW(), status='.db_input

('pending');
        if($thisstaff) //Give the closing  staff credit.
            $sql.=', staff_id='.db_input($thisstaff->getId());
        $sql.=' WHERE ticket_id='.db_input($this->getId());
        if(!db_query($sql) || !db_affected_rows())
            return false;
        $this->reload();
        $this->logEvent('pending');
        return true;
    }

circa line 1763 locate:

        $sql='SELECT count(open.ticket_id) as open, count(answered.ticket_id) as answered '
            .' ,count(overdue.ticket_id) as overdue, count(assigned.ticket_id) as assigned, count(closed.ticket_id) as closed '
            .' FROM '.TICKET_TABLE.' ticket '
            .' LEFT JOIN '.TICKET_TABLE.' open ON (open.ticket_id=ticket.ticket_id AND open.status=\'open\' 
AND open.isanswered=0 '.((!($cfg->showAssignedTickets() || $staff->showAssignedTickets()))? ' AND 
open.staff_id=0 ':'').') '
            .' LEFT JOIN '.TICKET_TABLE.' answered ON (answered.ticket_id=ticket.ticket_id AND 
answered.status=\'open\' AND answered.isanswered=1) '
            .' LEFT JOIN '.TICKET_TABLE.' overdue ON (overdue.ticket_id=ticket.ticket_id AND 
overdue.status=\'open\' AND overdue.isoverdue=1) '
            .' LEFT JOIN '.TICKET_TABLE.' assigned ON (assigned.ticket_id=ticket.ticket_id AND 
assigned.status=\'open\' AND assigned.staff_id='.db_input($staff->getId()).')'
            .' LEFT JOIN '.TICKET_TABLE.' closed ON (closed.ticket_id=ticket.ticket_id AND closed.status=\'closed\' )'
            .' WHERE (ticket.staff_id='.db_input($staff->getId());

replace with:

            $sql='SELECT count(open.ticket_id) as open, count(answered.ticket_id) as answered '
            .' ,count(overdue.ticket_id) as overdue, count(assigned.ticket_id) as assigned, count(pending.ticket_id) as pending, count(closed.ticket_id) as closed '
            .' FROM '.TICKET_TABLE.' ticket '
            .' LEFT JOIN '.TICKET_TABLE.' open ON (open.ticket_id=ticket.ticket_id AND open.status=\'open\' AND open.isanswered=0 '.((!($cfg->showAssignedTickets() || $staff->showAssignedTickets()))? ' AND open.staff_id=0 ':'').') '
            .' LEFT JOIN '.TICKET_TABLE.' answered ON (answered.ticket_id=ticket.ticket_id AND answered.status=\'open\' AND answered.isanswered=1) '
            .' LEFT JOIN '.TICKET_TABLE.' pending ON (pending.ticket_id=ticket.ticket_id AND pending.status=\'pending\' )'
            .' LEFT JOIN '.TICKET_TABLE.' overdue ON (overdue.ticket_id=ticket.ticket_id AND overdue.status=\'open\' AND overdue.isoverdue=1) '
            .' LEFT JOIN '.TICKET_TABLE.' assigned ON (assigned.ticket_id=ticket.ticket_id AND assigned.status=\'open\' AND assigned.staff_id='.db_input($staff->getId()).')'
            .' LEFT JOIN '.TICKET_TABLE.' closed ON (closed.ticket_id=ticket.ticket_id AND closed.status=\'closed\' )'
            .' WHERE (ticket.staff_id='.db_input($staff->getId());

circa line 1796 locate:

        $sql='SELECT count(open.ticket_id) as open, count(closed.ticket_id) as closed '
            .' FROM '.TICKET_TABLE.' ticket '
            .' LEFT JOIN '.TICKET_TABLE.' open
                ON (open.ticket_id=ticket.ticket_id AND open.status=\'open\') '
            .' LEFT JOIN '.TICKET_TABLE.' closed
                ON (closed.ticket_id=ticket.ticket_id AND closed.status=\'closed\')'
            .' WHERE ticket.email='.db_input($email);

replace with:

        $sql='SELECT count(open.ticket_id) as open, count(pending.ticket_id) as pending, count(closed.ticket_id) as closed '
            .' FROM '.TICKET_TABLE.' ticket '
            .' LEFT JOIN '.TICKET_TABLE.' open ON (open.ticket_id=ticket.ticket_id AND open.status=\'open\') '
            .' LEFT JOIN '.TICKET_TABLE.' pending ON (pending.ticket_id=ticket.ticket_id AND pending.status=\'pending\') '
            .' LEFT JOIN '.TICKET_TABLE.' closed ON (closed.ticket_id=ticket.ticket_id AND closed.status=\'closed\')'
            .' WHERE ticket.email='.db_input($email);

open include\staff\tickets.inc.php
circa line 32 locate:

    case 'open':
        $status='open';
        break;

below add:

    case 'pending':
        $status='pending';
        break;

open include\staff\ticket-view.inc.php
circa line 485 locate:

            <?php
            if($ticket->isClosed() || $thisstaff->canCloseTickets()) { ?>
            <tr>
                <td width="160">
                    <label><strong>Ticket Status:</strong></label>
                </td>
                <td width="765">
                    <?php
                    $statusChecked=isset($info['reply_ticket_status'])?'checked="checked"':'';
                    if($ticket->isClosed()) { ?>
                        <label><input type="checkbox" name="reply_ticket_status" id="reply_ticket_status" value="Open"
                            <?php echo $statusChecked; ?>> Reopen on Reply
                   <?php
                    } elseif($thisstaff->canCloseTickets()) { ?>
                         <label><input type="checkbox" name="reply_ticket_status" id="reply_ticket_status" value="Closed"
                              <?php echo $statusChecked; ?>> Close on Reply</label>
                   <?php
                    } ?>
                </td>
            </tr>
            <?php
            } ?>

replace with:

            <?php
            if($ticket->isClosed() || $thisstaff->canCloseTickets()) { ?>
                        <tr>
                <td width="160">
                    <label><strong>Ticket Status:</strong></label>
                </td>
                <td width="765">
     						<?php
     						$statusChecked=isset($info['reply_ticket_status'])?'checked="checked"':'';
     						if($ticket->isOpen()) { ?>
                	  <label><input type="checkbox" name="reply_ticket_status" id="reply_ticket_status" value="Pending"
                    <?php echo $statusChecked; ?>> Mark as Pending</label>
                    <?php
                    } elseif($ticket->isPending()) { ?>
                    <label><input type="checkbox" name="reply_ticket_status" id="reply_ticket_status" value="Open"
                    <?php echo $statusChecked; ?>> Unmark as Pending</label>
                    <?php
                    } ?>
                    <?php
                    $statusChecked=isset($info['reply_ticket_status'])?'checked="checked"':'';
                    if($ticket->isClosed()) { ?>
                        <label><input type="checkbox" name="reply_ticket_status" id="reply_ticket_status" value="Open"
                            <?php echo $statusChecked; ?>> Reopen on Reply
                    <?php
                    } elseif($thisstaff->canCloseTickets()) { ?>
                    <label><input type="checkbox" name="reply_ticket_status" id="reply_ticket_status" value="Closed"
                    <?php echo $statusChecked; ?>> Close on Reply</label>
                    <?php
                    } ?>
								</td>   
            </tr>
            <?php
            } ?>

Step 4 - Customizing your mod to fit your installation more

You may want to close tickets sooner (or later than) the default 5 days. The number of days is handled in the autoClose.php by part of the sql statement:

Locate:

$sql .= " AND updated <= '" . date("Y-m-d", strtotime('-5 days')) . " 00:00:00'";

modifying the part of the statement that reads '-5 days' will change the number of days.