}
if (Param('timetrackinggroup')) {
- push @fields, qw(estimated_time remaining_time actual_time);
+ push @fields, qw(estimated_time remaining_time actual_time deadline);
}
return @fields;
DATE_FORMAT(creation_ts,'%Y.%m.%d %H:%i'),
delta_ts, COALESCE(SUM(votes.vote_count), 0),
reporter_accessible, cclist_accessible,
- estimated_time, remaining_time
+ estimated_time, remaining_time, DATE_FORMAT(deadline,'%Y-%m-%d')
from bugs left join votes using(bug_id),
classifications, products, components
where bugs.bug_id = $bug_id
"target_milestone", "qa_contact", "status_whiteboard",
"creation_ts", "delta_ts", "votes",
"reporter_accessible", "cclist_accessible",
- "estimated_time", "remaining_time")
+ "estimated_time", "remaining_time", "deadline")
{
$fields{$field} = shift @row;
if (defined $fields{$field}) {
}
$values{'estimated_time'} = format_time_decimal($values{'estimated_time'});
+ $values{'deadline'} = time2str("%Y-%m-%d", str2time($values{'deadline'}));
+
my @dependslist;
SendSQL("SELECT dependson FROM dependencies WHERE
blocked = $id ORDER BY dependson");
WHERE attach_id = $attachid");
$diffpart->{'isprivate'} = FetchOneColumn();
}
+ if( $fieldname eq 'deadline' ) {
+ $old = time2str("%Y-%m-%d", str2time($old));
+ $new = time2str("%Y-%m-%d", str2time($new));
+ }
$difftext = FormatTriple($what, $old, $new);
$diffpart->{'header'} = $diffheader;
$diffpart->{'fieldname'} = $fieldname;
next;
}
# Only send estimated_time if it is enabled and the user is in the group
- if ($f ne 'estimated_time' ||
- $user->groups->{Param('timetrackinggroup')}) {
+ if (($f ne 'estimated_time' && $f ne 'deadline') ||
+ $user->groups->{Param('timetrackinggroup')}) {
my $desc = $fielddescription{$f};
$head .= FormatDouble($desc, $value);
if (exists($diff->{'fieldname'}) &&
($diff->{'fieldname'} eq 'estimated_time' ||
$diff->{'fieldname'} eq 'remaining_time' ||
- $diff->{'fieldname'} eq 'work_time')) {
+ $diff->{'fieldname'} eq 'work_time' ||
+ $diff->{'fieldname'} eq 'deadline')){
if ($user->groups->{Param("timetrackinggroup")}) {
$add_diff = 1;
}
}
}
+ my $sql_deadlinefrom;
+ my $sql_deadlineto;
+ if (Bugzilla->user->in_group(Param('timetrackinggroup'))){
+ my $deadlinefrom;
+ my $deadlineto;
+
+ if ($params->param('deadlinefrom')){
+ $deadlinefrom = $params->param('deadlinefrom');
+ Bugzilla::Util::ValidateDate($deadlinefrom, 'deadlinefrom');
+ $sql_deadlinefrom = &::SqlQuote($deadlinefrom);
+ push(@wherepart, "bugs.deadline >= $sql_deadlinefrom");
+ }
+
+ if ($params->param('deadlineto')){
+ $deadlineto = $params->param('deadlineto');
+ Bugzilla::Util::ValidateDate($deadlineto, 'deadlineto');
+ $sql_deadlineto = &::SqlQuote($deadlineto);
+ push(@wherepart, "bugs.deadline <= $sql_deadlineto");
+ }
+ }
+
foreach my $f ("short_desc", "long_desc", "bug_file_loc",
"status_whiteboard") {
if (defined $params->param($f)) {
"^content," => sub {
ThrowUserError("search_content_without_matches");
},
+ "^deadline,(?:lessthan|greaterthan|equals|notequals),(-|\\+)?(\\d+)([dDwWmMyY])\$" => sub {
+ $v = SqlifyDate($v);
+ $q = &::SqlQuote($v);
+ },
"^commenter,(?:equals|anyexact),(%\\w+%)" => sub {
my $match = pronoun($1, $user);
my $chartseq = $chartid;
my ($sec, $min, $hour, $mday, $month, $year, $wday) = localtime(time());
return sprintf("%4d-%02d-%02d 00:00:00", $year+1900, $month+1, $mday);
}
- if ($str =~ /^-?(\d+)([dDwWmMyY])$/) { # relative date
- my ($amount, $unit, $date) = ($1, lc $2, time);
+
+
+ if ($str =~ /^(-|\+)?(\d+)([dDwWmMyY])$/) { # relative date
+ my ($sign, $amount, $unit, $date) = ($1, $2, lc $3, time);
my ($sec, $min, $hour, $mday, $month, $year, $wday) = localtime($date);
+ if ($sign eq '+') { $amount = -$amount; }
if ($unit eq 'w') { # convert weeks to days
$amount = 7*$amount + $wday;
$unit = 'd';
format_time format_time_decimal);
use Bugzilla::Config;
+use Bugzilla::Error;
+use Date::Parse;
+use Date::Format;
# This is from the perlsec page, slightly modifed to remove a warning
# From that page:
return $newtime;
}
+sub ValidateDate {
+ my ($date, $format) = @_;
+
+ my $ts = str2time($date);
+ my $date2 = time2str("%Y-%m-%d", $ts);
+
+ $date =~ s/(\d+)-0*(\d+?)-0*(\d+?)/$1-$2-$3/;
+ $date2 =~ s/(\d+)-0*(\d+?)-0*(\d+?)/$1-$2-$3/;
+
+ if ($date ne $date2) {
+ ThrowUserError('illegal_date', {date => $date, format => $format});
+ }
+}
+
1;
__END__
# check if the user should see this field's activity
if ($fieldname eq 'remaining_time' ||
$fieldname eq 'estimated_time' ||
- $fieldname eq 'work_time') {
+ $fieldname eq 'work_time' ||
+ $fieldname eq 'deadline') {
if (!UserInGroup(Param('timetrackinggroup'))) {
$activity_visible = 0;
$operation = {};
$changes = [];
}
+
+ if ($fieldname eq 'deadline') {
+ $removed = time2str("%Y-%m-%d", str2time($removed));
+ $added = time2str("%Y-%m-%d", str2time($added));
+ }
$operation->{'who'} = $who;
$operation->{'when'} = $when;
DefineColumn("actual_time" , "(SUM(ldtime.work_time)*COUNT(DISTINCT ldtime.bug_when)/COUNT(bugs.bug_id)) AS actual_time", "Actual Hours");
DefineColumn("percentage_complete","(100*((SUM(ldtime.work_time)*COUNT(DISTINCT ldtime.bug_when)/COUNT(bugs.bug_id))/((SUM(ldtime.work_time)*COUNT(DISTINCT ldtime.bug_when)/COUNT(bugs.bug_id))+bugs.remaining_time))) AS percentage_complete", "% Complete");
DefineColumn("relevance" , "relevance" , "Relevance" );
-
+DefineColumn("deadline" , "DATE_FORMAT(bugs.deadline, '%Y-%m-%d')", "Deadline");
################################################################################
# Display Column Determination
@displaycolumns = grep($_ ne 'remaining_time', @displaycolumns);
@displaycolumns = grep($_ ne 'actual_time', @displaycolumns);
@displaycolumns = grep($_ ne 'percentage_complete', @displaycolumns);
+ @displaycolumns = grep($_ ne 'deadline', @displaycolumns);
}
# Remove the relevance column if the user is not doing a fulltext search.
cclist_accessible tinyint not null default 1,
estimated_time decimal(5,2) not null default 0,
remaining_time decimal(5,2) not null default 0,
+ deadline datetime,
alias varchar(20),
index (assigned_to),
AddFDef("bug_group", "Group", 0);
AddFDef("estimated_time", "Estimated Hours", 1);
AddFDef("remaining_time", "Remaining Hours", 0);
+AddFDef("deadline", "Deadline", 1);
# Oops. Bug 163299
$dbh->do("DELETE FROM fielddefs WHERE name='cc_accessible'");
AddField("longdescs", "work_time", "decimal(5,2) not null default 0");
AddField("bugs", "estimated_time", "decimal(5,2) not null default 0");
AddField("bugs", "remaining_time", "decimal(5,2) not null default 0");
+AddField("bugs", "deadline", "datetime");
# 2002-03-15 bbaetz@student.usyd.edu.au - bug 129466
# 2002-05-13 preed@sigkill.com - bug 129446 patch backported to the
if (UserInGroup(Param("timetrackinggroup"))) {
push(@masterlist, ("estimated_time", "remaining_time", "actual_time",
- "percentage_complete"));
+ "percentage_complete", "deadline"));
}
push(@masterlist, ("short_desc", "short_short_desc"));
my $extra = "";
if (!UserInGroup(Param('timetrackinggroup'))) {
$extra = "WHERE name NOT IN ('estimated time', 'remaining_time', " .
- "'work_time', 'percentage_complete')";
+ "'work_time', 'percentage_complete', 'deadline')";
}
my @fields;
bugs.keywords,
bugs.estimated_time,
bugs.remaining_time,
- date_format(creation_ts,'%Y.%m.%d %H:%i')
+ date_format(creation_ts,'%Y.%m.%d %H:%i'),
+ date_format(bugs.deadline, '%Y-%m-%d')
FROM bugs,profiles assign,profiles report, classifications, products, components
WHERE assign.userid = bugs.assigned_to AND report.userid = bugs.reporter
AND bugs.product_id=products.id AND bugs.component_id=components.id
"bug_severity", "component", "assigned_to", "reporter",
"bug_file_loc", "short_desc", "target_milestone",
"qa_contact", "status_whiteboard", "keywords",
- "estimated_time", "remaining_time", "creation_ts")
+ "estimated_time", "remaining_time", "creation_ts",
+ "deadline")
{
$bug{$field} = shift @row;
}
# Build up SQL string to add bug.
my $sql = "INSERT INTO bugs " .
"(" . join(",", @used_fields) . ", reporter, creation_ts, " .
- "estimated_time, remaining_time) " .
+ "estimated_time, remaining_time, deadline) " .
"VALUES (";
foreach my $field (@used_fields) {
my $est_time = $::FORM{'estimated_time'};
Bugzilla::Bug::ValidateTime($est_time, 'estimated_time');
- $sql .= SqlQuote($est_time) . "," . SqlQuote($est_time);
+ $sql .= SqlQuote($est_time) . "," . SqlQuote($est_time) . ",";
} else {
- $sql .= "0, 0";
+ $sql .= "0, 0, ";
}
+
+if ((UserInGroup(Param("timetrackinggroup"))) && ($::FORM{'deadline'})) {
+ Bugzilla::Util::ValidateDate($::FORM{'deadline'}, 'YYYY-MM-DD');
+ my $str = $::FORM{'deadline'};
+ $sql .= SqlQuote($::FORM{'deadline'});
+} else {
+ $sql .= "NULL";
+}
+
$sql .= ")";
# Groups
}
}
}
+
+ if (defined $::FORM{'deadline'}) {
+ DoComma();
+ $::query .= "deadline = ";
+ if ($::FORM{'deadline'}) {
+ Bugzilla::Util::ValidateDate($::FORM{'deadline'}, 'YYYY-MM-DD');
+ $::query .= SqlQuote($::FORM{'deadline'});
+ } else {
+ $::query .= "NULL" ;
+ }
+ }
}
# If the user is submitting changes from show_bug.cgi for a single bug,
<input name="estimated_time" size="6" maxlength="6" value="0.0">
</td>
</tr>
+ <tr>
+ <td align="right"><strong>Deadline:</strong></td>
+ <td colspan="3">
+ <input name="deadline" size="10" maxlength="10">
+ <small>(YYYY-MM-DD)</small>
+ </td>
+ </tr>
<tr>
<td> </td>
<th align="center" bgcolor="#cccccc">
Gain
</th>
+ <th align="center" bgcolor="#cccccc">
+ Deadline
+ </th>
</tr>
<tr>
<td align="center">
<td align="center">
[% PROCESS formattimeunit time_unit=bug.estimated_time - (bug.actual_time + bug.remaining_time) %]
</td>
+ <td align="center">
+ <input name="deadline" value="[% bug.deadline %]"
+ size="10" maxlength="10">
+ </td>
</tr>
</table>
[% END %]
[% PROCESS formattimeunit
time_unit=bug.estimated_time - (bug.actual_time + bug.remaining_time) %]
+ <b>Deadline:</b>
+ [% bug.deadline %]
</td>
</tr>
[% END %]
],
'bug/edit.html.tmpl' => [
+ 'bug.deadline',
'bug.remaining_time',
'bug.delta_ts',
'bug.bug_id',
'bug/show-multiple.html.tmpl' => [
'bug.bug_id',
+ 'bug.deadline',
],
'bug/show.xml.tmpl' => [
"component_id" => "Component ID",
"component" => "Component",
"creation_ts" => "$terms.Bug Creation time",
+ "deadline" => "Deadline",
"delta_ts" => "Last Changed time",
"dependson" => "Depends on",
"dup_id" => "Duplicate",
[% ELSIF error == "illegal_date" %]
[% title = "Illegal Date" %]
'<tt>[% date FILTER html %]</tt>' is not a legal date.
+ [% IF format %]
+ Please use the format '<tt>[% format FILTER html %]</tt>'.
+ [% END %]
[% ELSIF error == "illegal_email_address" %]
[% title = "Invalid Email Address" %]
</td>
</tr>
[% END %]
+
+ [%# Deadline %]
+ [% IF UserInGroup(Param("timetrackinggroup")) %]
+ <tr>
+ <th align="right">
+ Dead<u>l</u>ine:
+ </th>
+ <td>
+ from
+ <input name="deadlinefrom" size="10" maxlength="10" accesskey="l">
+ to
+ <input name="deadlineto" size="10" maxlength="10">
+ </td>
+ <td>
+ <small>(YYYY-MM-DD)</small>
+ </td>
+ </tr>
+ [% END %]
+
</table>
<hr>