[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> </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> </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> </td>
+ <td> </td>
+ <td> </td>
+ <td> </td>
+</tr>
+<tr class="text" onmouseover="className='text-hi';" onmouseout="className='text';">
+ <td> </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> </td>
+ <td> </td>
+ <td> </td>
+ <td> </td>
+</tr>
+<tr class="text" onmouseover="className='text-hi';" onmouseout="className='text';">
+ <td> </td>
+ <td colspan="4"><b>Total Hours</b></td>
+ <td align="right"><b><?php
+ echo number_format($total_hours, 2);
+ ?></b> </td>
+ <td> </td>
+ <td> </td>
+ <td> </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);
+ }
+ ?> </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