[hermes] [patch] Submitted time review screen

Jason M. Felice jfelice at cronosys.com
Thu Nov 6 17:14:47 PST 2003


Implements a time review screen where a "time administrator" can see, modify
and delete submitted timeslices.  You must set permissions before you
can see it or edit time on it, see docs/INFO included in this patch for
more info.

-- 
 Jason M. Felice
 Cronosys, LLC <http://www.cronosys.com/>
 216.221.4600 x302
-------------- next part --------------
epm diff hermes/templates/menu/menu.inc
--- hermes/templates/menu/menu.inc	2003-11-06 19:59:59.000000000 -0500
+++ hermes/templates/menu/menu.inc	2003-11-06 19:59:59.000000000 -0500
@@ -16,9 +16,11 @@
 /* Hermes menu items */
 $time = Horde::applicationUrl('time.php');
 $submit = Horde::applicationUrl('submit.php');
+$review = Horde::applicationUrl('review.php');
 if (isset($timestamp)) {
     $time = Util::addParameter($time, 'timestamp=' . $timestamp);
     $submit = Util::addParameter($submit, 'timestamp=' . $timestamp);
+    $review = Util::addParameter($review, 'timestamp=' . $timestamp);
 }
 
 Menu::printItem($time, _("Enter Time"), 'hermes.gif');
@@ -28,6 +30,11 @@
     Menu::printItem('#', _("Other Weeks"), 'goto.gif', null, '', 'openGoto(\'' . $timestamp . '\'); return false;');
 }
 
+$perms = Perms::singleton();
+if ($perms->hasPermission('hermes:review', Auth::getAuth(), _PERMS_SHOW)) {
+    Menu::printItem($review, _("Review"), 'hermes.gif');
+}
+
 /* Print */
 if ($conf['menu']['print'] && isset($print_link) && $browser->hasFeature('javascript')) {
     Menu::printItem('#', _("Print"), 'print.gif', $registry->getParam('graphics', 'horde'), '', "open_print_win('$print_link'); return false;");
epm diff hermes/lib/api.php
--- hermes/lib/api.php	1969-12-31 19:00:00.000000000 -0500
+++ hermes/lib/api.php	2003-11-06 19:59:59.000000000 -0500
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Hermes external API interface.
+ *
+ * $Horde: $
+ *
+ * This file defines Nag's external API interface. Other applications
+ * can interact with Nag through this API.
+ *
+ * @package Hermes
+ */
+
+$_services['perms'] = array(
+    'args' => array(),
+    'type' => 'array');
+
+function _hermes_perms()
+{
+    $perms = array();
+    $perms['tree']['hermes']['review'] = array();
+    $perms['title']['hermes:review'] = _("Time Review Screen");
+
+    return $perms;
+}
+
epm diff config/registry.php.dist
--- config/registry.php.dist	2003-11-06 19:59:59.000000000 -0500
+++ config/registry.php.dist	2003-11-06 19:59:59.000000000 -0500
@@ -380,7 +380,8 @@
     'name' => _("Time Tracking"),
     'allow_guests' => false,
     'status' => 'active',
-    'menu_parent' => 'office'
+    'menu_parent' => 'office',
+    'provides' => 'time'
 );
 
 $this->applications['juno'] = array(
epm diff hermes/lib/base.php
--- hermes/lib/base.php	2003-11-06 19:59:59.000000000 -0500
+++ hermes/lib/base.php	2003-11-06 19:59:59.000000000 -0500
@@ -58,3 +58,6 @@
 // Forms libraries.
 require_once HORDE_BASE . '/lib/Form.php';
 require_once HORDE_BASE . '/lib/Form/Renderer.php';
+
+// Perms
+require_once HORDE_BASE . '/lib/Perms.php';
epm diff hermes/review.php
--- hermes/review.php	1969-12-31 19:00:00.000000000 -0500
+++ hermes/review.php	2003-11-06 19:59:59.000000000 -0500
@@ -0,0 +1,97 @@
+<?php
+/*
+ * $Horde: $
+ *
+ * Copyright 2003 Jay 'Eraserhead' Felice <jfelice at cronosys.com>
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://www.horde.org/licenses/bsdl.php.
+ */
+
+ at define('HERMES_BASE', dirname(__FILE__));
+require_once HERMES_BASE . '/lib/base.php';
+require_once HERMES_BASE . '/lib/TimeForm.php';
+require_once HORDE_BASE . '/lib/Identity.php';
+
+$vars = &Horde_Form::getDefaultVars();
+$timestamp = Hermes::getCurrentTimestamp();
+
+$delete = $vars->getVar('delete');
+if (!empty($delete)) {
+    $result = $hermes->updateTime(array(array('id' => $delete, 'delete' => true)));
+    if (is_a($result, 'PEAR_Error')) {
+        Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+        $notification->push(sprintf(_("There was an error deleting the time: %s"), $result->getMessage()), 'horde.error');
+    } else {
+        $notification->push(_("The time entry was successfully deleted."), 'horde.success');
+        $vars->unsetVar('delete');
+    }
+}
+
+$formname = $vars->getVar('formname');
+if ($formname) {
+    $form = &Horde_Form::singleton('TimeReviewForm', $vars, Hermes::getCurrentTimestamp());
+    $form->validate($vars);
+    if ($form->isValid()) {
+        $form->getInfo($vars, $info);
+        $result = $hermes->updateTime(array($info));
+        if (is_a($result, 'PEAR_Error')) {
+            Horde::logMessage($result, __FILE__, __LINE__, PEAR_LOG_ERR);
+            $notification->push(sprintf(_("There was an error storing your timesheet: %s"), $result->getMessage()), 'horde.error');
+        } else {
+            $notification->push(_("The timeslice was successfully updated."), 'horde.success');
+            $vars = &new Horde_Form_Vars();
+        }
+    }
+}
+
+$title = _("Review Submitted Time");
+require HERMES_TEMPLATES . '/common-header.inc';
+
+Hermes::menu();
+
+$hours = $hermes->getHours(array('submitted' => 1,
+                                 'exported' => 0));
+if ($vars->isVarSet('id')) {
+    // Editing a record.
+    $id = $vars->getVar('id'); 
+    foreach ($hours as $item) {
+        if (isset($item['id']) && $item['id'] == $id) {
+            foreach ($item as $key => $value) {
+                $vars->setVar($key, $value);
+            }
+        }
+    }
+
+    $r = &new Horde_Form_Renderer();
+    $form = &Horde_Form::singleton('TimeReviewForm', $vars, Hermes::getCurrentTimestamp());
+    $form->renderActive($r, $vars, 'review.php', 'post');
+
+} else {
+    if (count($hours) > 0) {
+        $total_hours = 0.0;
+        $total_billable_hours = 0.0;
+        foreach ($hours as $vals) {
+            $total_hours += (double)$vals['hours'];
+            if ($vals['billable']) {
+                $total_billable_hours += (double)$vals['hours'];
+            }
+        }
+        $billable_pct = round($total_billable_hours / $total_hours * 100.0);
+        $clients = Hermes::listClients();
+
+        require HERMES_TEMPLATES . '/review/table-header.inc';
+        foreach ($hours as $item) {
+            $item_link = Util::addParameter(Horde::applicationUrl('review.php'),
+                                            'timestamp', $timestamp);
+            $delete_link = Util::addParameter($item_link, 'delete',
+                                              $item['id']);
+            $item_link = Util::addParameter($item_link, 'id', $item['id']);
+
+            require HERMES_TEMPLATES . '/review/table-item.inc';
+        }
+        require HERMES_TEMPLATES . '/review/table-footer.inc';
+    }
+}
+
+require HERMES_TEMPLATES . '/common-footer.inc';
epm diff hermes/templates/review/table-header.inc
--- hermes/templates/review/table-header.inc	1969-12-31 19:00:00.000000000 -0500
+++ hermes/templates/review/table-header.inc	2003-11-06 19:59:59.000000000 -0500
@@ -0,0 +1,15 @@
+<table width="100%" cellspacing="1" cellpadding="0" border="0" class="item">
+  <tr>
+    <td align="left" class="header" colspan="9">Submitted Time to Review</td>
+  </tr>
+  <tr class="item">
+    <td>&nbsp;</td>
+    <td><b><?php echo _("Date") ?></b></td>
+    <td><b><?php echo _("Employee") ?></b></td>
+    <td><b><?php echo _("Client") ?></b></td>
+    <td><b><?php echo _("Job Type") ?></b></td>
+    <td><b><?php echo _("Hours") ?></b></td>
+    <td><b><?php echo _("Bill?") ?></b></td>
+    <td><b><?php echo _("Description") ?></b></td>
+    <td><b><?php echo _("Additional Notes") ?></b></td>
+  </tr>
epm diff hermes/templates/review/table-footer.inc
--- hermes/templates/review/table-footer.inc	1969-12-31 19:00:00.000000000 -0500
+++ hermes/templates/review/table-footer.inc	2003-11-06 19:59:59.000000000 -0500
@@ -0,0 +1,35 @@
+<tr class="text" onmouseover="className='text-hi';" onmouseout="className='text';">
+  <td>&nbsp;</td>
+  <td colspan="4"><b>Total Billable Hours (<?php
+    echo sprintf('%.0f%%', $billable_pct);
+  ?>)</b></td>
+  <td align="right"><b><?php
+    echo number_format($total_billable_hours,2);
+  ?></b>&nbsp;</td>
+  <td>&nbsp;</td>
+  <td>&nbsp;</td>
+  <td>&nbsp;</td>
+</tr>
+<tr class="text" onmouseover="className='text-hi';" onmouseout="className='text';">
+  <td>&nbsp;</td>
+  <td colspan="4"><b>Total Non-billable Hours (<?php
+    echo sprintf('%.0f%%', 100.0 - $billable_pct);
+  ?>)</b></td>
+  <td align="right"><b><?php
+    echo number_format($total_hours - $total_billable_hours,2);
+  ?></b>&nbsp;</td>
+  <td>&nbsp;</td>
+  <td>&nbsp;</td>
+  <td>&nbsp;</td>
+</tr>
+<tr class="text" onmouseover="className='text-hi';" onmouseout="className='text';">
+  <td>&nbsp;</td>
+  <td colspan="4"><b>Total Hours</b></td>
+  <td align="right"><b><?php
+    echo number_format($total_hours, 2);
+  ?></b>&nbsp;</td>
+  <td>&nbsp;</td>
+  <td>&nbsp;</td>
+  <td>&nbsp;</td>
+</tr>
+</table><br />
epm diff hermes/templates/review/table-item.inc
--- hermes/templates/review/table-item.inc	1969-12-31 19:00:00.000000000 -0500
+++ hermes/templates/review/table-item.inc	2003-11-06 19:59:59.000000000 -0500
@@ -0,0 +1,48 @@
+<tr class="text" onmouseover="className='text-hi';" onmouseout="className='text';">
+  <td><nobr><?php
+    if (isset($item['id']) && Hermes::canEditTimeslice($item['id'])) {
+        echo Horde::link($item_link, _("Edit Entry"), 'widget'),
+            Horde::img('edit.gif', _("Edit Entry")), "</a>",
+            Horde::link($delete_link, _("Delete Entry"), 'widget'),
+            Horde::img('delete.gif', _("Delete Entry")), "</a>";
+    }
+  ?></nobr></td><td><?php
+    if (isset($item['date'])) {
+        echo strftime("%a (%x)", $item['date']);
+    }
+  ?></td><td><?php
+    if (!empty($item['employee'])) {
+        $identity = &new Identity($item['employee']);
+        echo htmlspecialchars($identity->getValue('fullname'));
+    }
+
+  ?></td><td><?php
+    if (isset($item['client']) && isset($clients[$item['client']])) {
+        echo htmlspecialchars($clients[$item['client']]);
+    }
+  ?></td><td><?php 
+    if (isset($item['_type_name'])) {
+        echo htmlspecialchars($item['_type_name']);
+    }
+  ?></td><td align="right"><?php
+    if (isset($item['hours'])) {
+        echo number_format($item['hours'],2);
+    }
+  ?>&nbsp;</td><td><?php
+    if (isset($item['billable'])) {
+        if ((int) $item['billable']) {
+            echo _("Yes");
+        } else {
+            echo _("No");
+        }
+    }
+  ?></td><td><?php
+    if (isset($item['description'])) {
+        echo htmlspecialchars($item['description']);
+    }
+  ?></td><td><?php
+    if (isset($item['note'])) {
+        echo htmlspecialchars($item['note']);
+    }
+  ?></td>
+</tr>
epm diff hermes/lib/Hermes.php
--- hermes/lib/Hermes.php	2003-11-06 19:59:59.000000000 -0500
+++ hermes/lib/Hermes.php	2003-11-06 19:59:59.000000000 -0500
@@ -119,6 +119,14 @@
         if ($slice['employee'] == Auth::getAuth() && !$slice['submitted']) {
             return true;
         }
+
+        require_once HORDE_BASE . '/lib/Perms.php';
+
+        $perms = &Perms::singleton();
+        if ($perms->hasPermission('hermes:review', Auth::getAuth(), _PERMS_EDIT)) {
+            return true;
+        }
+
         return false;
     }
 
epm diff hermes/templates/time/table-header.inc
--- hermes/templates/time/table-header.inc	2003-11-06 19:59:59.000000000 -0500
+++ hermes/templates/time/table-header.inc	2003-11-06 19:59:59.000000000 -0500
@@ -10,7 +10,7 @@
     <td><b><?php echo _("Client") ?></b></td>
     <td><b><?php echo _("Job Type") ?></b></td>
     <td><b><?php echo _("Hours") ?></b></td>
-    <td><b><?php echo _("Billable?") ?></b></td>
+    <td><b><?php echo _("Bill?") ?></b></td>
     <td><b><?php echo _("Description") ?></b></td>
     <td><b><?php echo _("Additional Notes") ?></b></td>
   </tr>
epm diff hermes/lib/TimeForm.php
--- hermes/lib/TimeForm.php	2003-11-06 19:59:59.000000000 -0500
+++ hermes/lib/TimeForm.php	2003-11-06 19:59:59.000000000 -0500
@@ -139,8 +139,91 @@
             $this->addVariable(_("Billable?"), 'billable', 'enum', true, false, null, array($yesno));
         }
 
-        $this->addVariable(_("Description"), 'description', 'longtext', true, false, null, array(1, 20));
-        $this->addVariable(_("Additional Notes"), 'note', 'longtext', false, false, null, array(1, 20));
+        $this->addVariable(_("Description"), 'description', 'longtext', true, false, null, array(4, 60));
+        $this->addVariable(_("Additional Notes"), 'note', 'longtext', false, false, null, array(4, 60));
+    }
+
+}
+
+/**
+ * TimeReviewForm Class.
+ *
+ * $Horde: hermes/lib/TimeForm.php,v 1.21 2003/11/05 18:28:45 chuck Exp $
+ *
+ * Copyright 2003 Jay 'Eraserhaed' Felice <jfelice at cronosys.com>
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you
+ * did not receive this file, see http://www.horde.org/licenses/bsdl.php.
+ *
+ * @author Jay 'Eraserhead' Felice <jfelice at cronosys.com>
+ * @version $Revision: 1.21 $
+ * @package hermes
+ */
+class TimeReviewForm extends TimeForm {
+
+    function TimeReviewForm(&$vars, $dowstamp = null)
+    {
+        global $hermes, $conf;
+
+        parent::TimeForm($vars, $dowstamp, _("Update Submitted Time"));
+        $this->setButtons(_("Update time"));
+
+        list($clienttype, $clientparams) = $this->getClientType();
+        if ($clienttype == 'enum') {
+            $map = array();
+            $clients = Hermes::listClients();
+            foreach ($clients as $id => $name) {
+                $info = $hermes->getClientSettings($id);
+                if (!is_a($info, 'PEAR_Error')) {
+                    $map[$id] = $info['enterdescription'] ? '' : _("See Attached Timesheet");
+                } else {
+                    $map[$id] = '';
+                }
+            }
+
+            require_once HORDE_BASE . '/lib/Form/Action.php';
+            $action = &Horde_Form_Action::factory('conditional_setvalue',
+                                                  array('map' => $map,
+                                                        'target' => 'description'));
+        }
+
+        $date_values = $this->getDOWValues();
+        list($typetype, $typeparams) = $this->getJobTypeType();
+
+        $this->addHidden('', 'id', 'int', true);
+        $this->addHidden('', 'timestamp', 'int', true);
+
+        $employees = array();
+
+        require_once HORDE_BASE . '/lib/Identity.php';
+        $auth = &Auth::singleton($conf['auth']['driver']);
+        $users = $auth->listUsers();
+        if (!is_a($users, 'PEAR_Error')) {
+            foreach ($users as $user) {
+                $identity = &new Identity($user);
+                $employees[$user] = $identity->getValue('fullname');
+            }
+        }
+
+        $this->addVariable(_("Employee"), 'employee', 'enum', true, false, null, array($employees));
+
+        $this->addVariable(_("Date"), 'date', 'enum', true, false, null, array($date_values));
+
+        $cli = &$this->addVariable(_("Client"), 'client', $clienttype, true, false, null, $clientparams);
+        if (isset($action)) {
+            $cli->setAction($action);
+        }
+
+        $this->addVariable(_("Job Type"), 'type', $typetype, true, false, null, $typeparams);
+        $this->addVariable(_("Hours"), 'hours', 'number', true);
+
+        if ($conf['time']['choose_ifbillable']) {
+            $yesno = array(1 => _("Yes"), 0 => _("No"));
+            $this->addVariable(_("Billable?"), 'billable', 'enum', true, false, null, array($yesno));
+        }
+
+        $this->addVariable(_("Description"), 'description', 'longtext', true, false, null, array(4, 60));
+        $this->addVariable(_("Additional Notes"), 'note', 'longtext', false, false, null, array(4, 60));
     }
 
 }
epm diff hermes/lib/Driver/sql.php
--- hermes/lib/Driver/sql.php	2003-11-06 19:59:59.000000000 -0500
+++ hermes/lib/Driver/sql.php	2003-11-06 19:59:59.000000000 -0500
@@ -129,7 +129,14 @@
                                ' WHERE timeslice_id = %d',
                                (int)$info['id']);
             } else {
+                if (isset($info['employee'])) {
+                    $employee_cl = sprintf(' employee_id = %s,',
+                                           $this->_db->quote($info['employee']));
+                } else {
+                    $employee_cl = '';
+                }
                 $sql = sprintf('UPDATE hermes_timeslices SET' .
+                               $employee_cl .
                                ' clientjob_id = %s, jobtype_id = %s,' .
                                ' timeslice_hours = %s, timeslice_isbillable = %d,' .
                                ' timeslice_date = %d, timeslice_description = %s, timeslice_note = %s' .
epm diff hermes/docs/INFO
--- hermes/docs/INFO	1969-12-31 19:00:00.000000000 -0500
+++ hermes/docs/INFO	2003-11-06 20:06:53.000000000 -0500
@@ -0,0 +1,19 @@
+Hermes INFO
+===========
+
+Review Screen
+-------------
+
+  A user won't see this menu icon unless he or she has "show" permission for
+  hermes / review (see "Permissions" from the Administration menu for
+  more info).
+
+  A user won't be able to edit submitted time unless he or she has the "edit"
+  permission for hermes / review.  If a user has this permission, he or she
+  will be able to edit submitted time from anywhere he or she can see it
+  (including their own time screen).
+
+  The review screen shows all submitted, unexported time.  The administrator
+  should export the time after reviewing so that they don't collect it all
+  next time around.  This should probably be polished up some, it's on my
+  task list.


More information about the hermes mailing list