changeset 11:4eb9fdf4efa9

refactoring, non-working bookings
author cin
date Mon, 07 Sep 2015 19:18:21 +0300
parents 14a966369278
children 52b34ea50eff
files bug-list.xsl lib/Benzin/Bugzilla/Bug.pm lib/Benzin/Bugzilla/XmlWriter.pm translate.pl
diffstat 4 files changed, 236 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- a/bug-list.xsl	Mon Sep 07 01:37:11 2015 +0300
+++ b/bug-list.xsl	Mon Sep 07 19:18:21 2015 +0300
@@ -1,7 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet version="1.0"
 	xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common"
-	extension-element-prefixes="exsl">
+	xmlns:date="http://exslt.org/dates-and-times"
+	extension-element-prefixes="exsl date">
 	<xsl:output method="text" indent="yes" />
 
 	<!-- PARAMETERS -->
@@ -113,6 +114,8 @@
 		<xsl:element name="bug">
 			<xsl:attribute name="id"><xsl:value-of select="$id" /></xsl:attribute>
 			<xsl:attribute name="desc"><xsl:value-of select="summary" /></xsl:attribute>
+			<xsl:attribute name="estimated"><xsl:value-of
+				select="number((time/estimated | estimated_time)[1])" /></xsl:attribute>
 
 			<xsl:if test="$children">
 				<xsl:attribute name="group"><xsl:value-of select="boolean($children)" /></xsl:attribute>
@@ -143,15 +146,12 @@
 		</xsl:apply-templates>
 	</xsl:template>
 
+	<!-- task -->
 	<xsl:template match="bug">
 		<xsl:param name="indent" select="0" />
 		<xsl:param name="chargeset" />
-		<xsl:variable name="id" select="@id" />
-		<xsl:variable name="details" select="$bugs[id = $id]" />
-		<xsl:variable name="hasTime"
-			select="number($details/estimated_time) or number($details/actual_time) or number($details/remaining_time)" />
 
-		<!-- task header -->
+		<!-- format the task header -->
 		<xsl:call-template name="start-task">
 			<xsl:with-param name="indent" select="$indent" />
 			<xsl:with-param name="id">
@@ -162,6 +162,7 @@
 			<xsl:with-param name="desc" select="@desc" />
 		</xsl:call-template>
 
+		<!-- specify chargeset if present -->
 		<xsl:if test="$chargeset">
 			<xsl:call-template name="println">
 				<xsl:with-param name="indent" select="$indent + 1" />
@@ -170,48 +171,12 @@
 			</xsl:call-template>
 		</xsl:if>
 
-		<!-- task details -->
-		<xsl:choose>
-			<xsl:when test="@group">
-				<!-- DEBUG -->
-				<xsl:call-template name="comment">
-					<xsl:with-param name="indent" select="$indent + 1" />
-					<xsl:with-param name="comment" select="'group'" />
-				</xsl:call-template>
-
-
-				<xsl:apply-templates select="$details/node()"
-					mode="group-details">
-					<xsl:with-param name="indent" select="$indent + 1" />
-				</xsl:apply-templates>
+		<!-- print task contents -->
+		<xsl:apply-templates select="." mode="task-content">
+			<xsl:with-param name="indent" select="$indent + 1" />
+		</xsl:apply-templates>
 
-				<xsl:if test="$hasTime">
-					<xsl:call-template name="start-task">
-						<xsl:with-param name="indent" select="$indent + 1" />
-						<xsl:with-param name="id" select="'manage'" />
-						<xsl:with-param name="desc" select="@desc" />
-					</xsl:call-template>
-					<xsl:apply-templates
-						select="$details/estimated_time | $details/actual_time | $details/remaining_time | $details/assigned_to"
-						mode="task-details">
-						<xsl:with-param name="indent" select="$indent + 2" />
-						<xsl:with-param name="hasTime" select="$hasTime" />
-					</xsl:apply-templates>
-					<xsl:call-template name="end-task">
-						<xsl:with-param name="indent" select="$indent + 1" />
-					</xsl:call-template>
-				</xsl:if>
-			</xsl:when>
-			<xsl:otherwise>
-				<xsl:apply-templates select="$details/node()"
-					mode="task-details">
-					<xsl:with-param name="indent" select="$indent + 1" />
-					<xsl:with-param name="hasTime" select="$hasTime" />
-				</xsl:apply-templates>
-			</xsl:otherwise>
-		</xsl:choose>
-
-		<!-- subtasks and dependencies -->
+		<!-- prints subtasks and dependencies -->
 		<xsl:apply-templates>
 			<xsl:with-param name="indent" select="$indent + 1" />
 			<xsl:with-param name="referer" select="." />
@@ -222,9 +187,11 @@
 		</xsl:call-template>
 	</xsl:template>
 
+	<!-- dependency -->
 	<xsl:template match="dependency">
-		<xsl:param name="indent" />
+		<xsl:param name="indent" select="0" />
 		<xsl:param name="referer" />
+
 		<xsl:call-template name="println">
 			<xsl:with-param name="indent" select="$indent" />
 			<xsl:with-param name="text">
@@ -237,40 +204,84 @@
 		</xsl:call-template>
 	</xsl:template>
 
+	<!-- an organizational task with spent/estimated time will contain a generated 
+		task which will contain the information about resource allocation and bookings -->
+	<xsl:template match="bug[@group][@estimated > 0]" mode="task-content"
+		priority="3">
+		<xsl:param name="indent" select="0" />
+		<xsl:variable name="id" select="@id" />
 
-	<xsl:template match="text()" />
+		<!-- DEBUG -->
+		<xsl:call-template name="comment">
+			<xsl:with-param name="indent" select="$indent" />
+			<xsl:with-param name="comment" select="'group'" />
+		</xsl:call-template>
 
-	<!-- TASK ATTRIBUTES -->
+		<!-- print group details -->
+		<xsl:apply-templates select="$bugs[id = $id]/node()"
+			mode="group-task">
+			<xsl:with-param name="indent" select="$indent" />
+		</xsl:apply-templates>
 
-	<xsl:template match="estimated_time" mode="task-details">
-		<xsl:param name="indent" />
-		<xsl:if test="number(.)">
-			<xsl:call-template name="println">
-				<xsl:with-param name="indent" select="$indent" />
-				<xsl:with-param name="text" select="concat('effort ', .,'h')" />
-			</xsl:call-template>
-		</xsl:if>
+		<xsl:variable name="metabug">
+			<bug id="{@id}" estimated="{@estimated}" desc="{@desc}" />
+		</xsl:variable>
+
+		<!-- write an administrative bug for this group-task -->
+		<xsl:apply-templates select="exsl:node-set($metabug)/bug[1]">
+			<xsl:with-param name="indent" select="$indent" />
+		</xsl:apply-templates>
+	</xsl:template>
+
+	<!-- an organizational task without resource allocations -->
+	<xsl:template match="bug[@group]" mode="task-content">
+		<xsl:param name="indent" select="0" />
+		<xsl:variable name="id" select="@id" />
+		<xsl:apply-templates select="$bugs[id = $id]/node()"
+			mode="group-task">
+			<xsl:with-param name="indent" select="$indent" />
+		</xsl:apply-templates>
 	</xsl:template>
 
-	<xsl:template match="assigned_to" mode="task-details">
-		<xsl:param name="indent" />
-		<xsl:param name="hasTime" />
-		<xsl:if test="$hasTime">
-			<xsl:variable name="email" select="string(.)" />
-			<xsl:variable name="resource" select="$resources[@email = $email]/@id" />
-			<xsl:if test="$resource">
-				<xsl:call-template name="println">
-					<xsl:with-param name="indent" select="$indent" />
-					<xsl:with-param name="text"
-						select="concat('allocate ', $resource)" />
-				</xsl:call-template>
-			</xsl:if>
-		</xsl:if>
-	</xsl:template>
-	<xsl:template match="text()" mode="task-details">
+	<!-- a work task -->
+	<xsl:template match="bug[@estimated > 0]" mode="task-content">
+		<xsl:param name="indent" select="0" />
+		<xsl:variable name="id" select="@id" />
+
+		<!-- DEBUG -->
+		<xsl:call-template name="comment">
+			<xsl:with-param name="indent" select="$indent" />
+			<xsl:with-param name="comment" select="'work'" />
+		</xsl:call-template>
+
+		<xsl:apply-templates select="$bugs[id = $id]/node()"
+			mode="work-task">
+			<xsl:with-param name="indent" select="$indent" />
+		</xsl:apply-templates>
 	</xsl:template>
 
-	<xsl:template match="assigned_to" mode="group-details">
+	<!-- a milestone task -->
+	<xsl:template match="bug" mode="task-content">
+		<xsl:param name="indent" select="0" />
+		<xsl:variable name="id" select="@id" />
+
+		<!-- DEBUG -->
+		<xsl:call-template name="comment">
+			<xsl:with-param name="indent" select="$indent" />
+			<xsl:with-param name="comment" select="'milestone'" />
+		</xsl:call-template>
+
+		<xsl:apply-templates select="$bugs[id = $id]/node()"
+			mode="milestone-task">
+			<xsl:with-param name="indent" select="$indent" />
+		</xsl:apply-templates>
+	</xsl:template>
+
+	<!-- each type of task processed in the corresponding mode MODES: * group-task 
+		* work-task * milestone-task -->
+
+	<!-- group-task -->
+	<xsl:template match="assigned_to" mode="group-task">
 		<xsl:param name="indent" />
 		<xsl:variable name="email" select="string(.)" />
 		<xsl:variable name="resource" select="$resources[@email = $email]/@id" />
@@ -282,13 +293,104 @@
 			</xsl:call-template>
 		</xsl:if>
 	</xsl:template>
-	<xsl:template match="text()" mode="group-details">
+
+	<xsl:template match="*" mode="group-task">
+		<xsl:param name="indent" select="0" />
+		<xsl:apply-templates mode="group-task">
+			<xsl:with-param name="indent" select="$indent" />
+		</xsl:apply-templates>
+	</xsl:template>
+
+	<xsl:template match="text()" mode="group-task">
+	</xsl:template>
+
+
+	<!-- work-task -->
+	<xsl:template match="assigned_to" mode="work-task">
+		<xsl:param name="indent" />
+		<xsl:variable name="email" select="string(.)" />
+		<xsl:variable name="resource" select="$resources[@email = $email]/@id" />
+		<xsl:if test="$resource">
+			<xsl:call-template name="println">
+				<xsl:with-param name="indent" select="$indent" />
+				<xsl:with-param name="text" select="concat('allocate ', $resource)" />
+			</xsl:call-template>
+		</xsl:if>
+	</xsl:template>
+
+	<!-- if we have a timereports -->
+	<xsl:template match="time/estimated[. > 0]" mode="work-task">
+		<xsl:param name="indent" />
+		<xsl:call-template name="println">
+			<xsl:with-param name="indent" select="$indent" />
+			<xsl:with-param name="text" select="concat('effort ', .,'h')" />
+		</xsl:call-template>
+	</xsl:template>
+
+	<!-- if we have an estimated_time -->
+	<xsl:template match="estimated_time[../time/estimated = 0]"
+		mode="work-task">
+		<xsl:param name="indent" />
+		<xsl:call-template name="comment">
+			<xsl:with-param name="indent" select="$indent" />
+			<xsl:with-param name="comment" select="'original estimated'" />
+		</xsl:call-template>
+		<xsl:call-template name="println">
+			<xsl:with-param name="indent" select="$indent" />
+			<xsl:with-param name="text" select="concat('effort ', .,'h')" />
+		</xsl:call-template>
+	</xsl:template>
+
+	<!-- time reports -->
+	<xsl:template match="time/report" mode="work-task">
+		<xsl:param name="indent" />
+		<xsl:variable name="email" select="string(who)" />
+		<xsl:variable name="start" select="start" />
+		<xsl:variable name="work_time" select="work_time" />
+		<xsl:variable name="resource" select="$resources[@email = $email]/@id" />
+		<xsl:call-template name="println">
+			<xsl:with-param name="indent" select="$indent" />
+			<xsl:with-param name="text"
+				select="concat('booking ', $resource, ' ', $start, ' +', $work_time,'h { overtime 2 }')" />
+		</xsl:call-template>
+	</xsl:template>
+
+	<xsl:template match="*" mode="work-task">
+		<xsl:param name="indent" select="0" />
+		<xsl:apply-templates mode="work-task">
+			<xsl:with-param name="indent" select="$indent" />
+		</xsl:apply-templates>
+	</xsl:template>
+
+	<xsl:template match="text()" mode="work-task">
+	</xsl:template>
+
+	<!-- milestone-task -->
+	<xsl:template match="assigned_to" mode="milestone-task">
+		<xsl:param name="indent" />
+		<xsl:variable name="email" select="string(.)" />
+		<xsl:variable name="resource" select="$resources[@email = $email]/@id" />
+		<xsl:if test="$resource">
+			<xsl:call-template name="println">
+				<xsl:with-param name="indent" select="$indent" />
+				<xsl:with-param name="text"
+					select="concat('responsible ', $resource)" />
+			</xsl:call-template>
+		</xsl:if>
+	</xsl:template>
+
+	<xsl:template match="*" mode="milestone-task">
+		<xsl:param name="indent" select="0" />
+		<xsl:apply-templates mode="milestone-task">
+			<xsl:with-param name="indent" select="$indent" />
+		</xsl:apply-templates>
+	</xsl:template>
+
+	<xsl:template match="text()" mode="milestone-task">
 	</xsl:template>
 
 	<!-- PRIMITIVES -->
 
-
-
 	<xsl:template name="bug-local-name">
 		<xsl:param name="id" />
 		<xsl:value-of select="concat('bug',$id)" />
--- a/lib/Benzin/Bugzilla/Bug.pm	Mon Sep 07 01:37:11 2015 +0300
+++ b/lib/Benzin/Bugzilla/Bug.pm	Mon Sep 07 19:18:21 2015 +0300
@@ -45,9 +45,7 @@
 
 use constant { BUG_FIELDS => \@fields };
 
-use IMPL::declare {
-	base    => [ 'IMPL::Object::Fields' => undef ]
-};
+use IMPL::declare { base => [ 'IMPL::Object::Fields' => undef ] };
 use fields @fields;
 
 sub CTOR {
@@ -67,14 +65,25 @@
 sub GetTimeReports {
 	my SELF $this = shift;
 	my $resolution = shift || 0.25;
+	my $span = $resolution * 60;
 
 	my @bookings;
 	my $actual = 0;
 
 	for my $history ( @{ $this->{history} || [] } ) {
-		my $who = $history->{who};
+		my $who     = $history->{who};
 		my $when    = $history->{when};
 		my $changes = $history->{changes};
+		
+		my $minutes = coarsen( $when->minute(), $span );
+		
+		if ($minutes >= 60 ) {
+			$when->add(hours => 1);
+			$minutes -= 60;
+		}
+		$when->set_second(0);
+		$when->set_minute($minutes);
+		
 
 		for my $change ( @{ $changes || [] } ) {
 			if ( $change->{field_name} eq 'work_time' ) {
@@ -86,11 +95,10 @@
 					if ($dt) {
 						push @bookings,
 						  {
-							end       => $who,
-							when      => $when->iso8601(),
+							who       => $who,
+							end      => $when,
 							work_time => $dt,
 							start => $when->clone()->subtract( hours => $dt )
-							  ->iso8601()
 						  };
 						$actual += $dt;
 					}
@@ -99,10 +107,12 @@
 		}
 	}
 
+	my $remaining = coarsen( $this->{remaining_time}, $resolution );
 	return {
-		reports   => \@bookings,
+		report    => \@bookings,
 		actual    => $actual,
-		remaining => coarsen( $this->{remaining_time}, $resolution )
+		remaining => $remaining,
+		estimated => $actual + $remaining
 	};
 }
 
--- a/lib/Benzin/Bugzilla/XmlWriter.pm	Mon Sep 07 01:37:11 2015 +0300
+++ b/lib/Benzin/Bugzilla/XmlWriter.pm	Mon Sep 07 19:18:21 2015 +0300
@@ -1,25 +1,28 @@
 package Benzin::Bugzilla::XmlWriter;
 
 our %Transform = (
-	'Benzin::Bugzilla::Bug' => 'WriteBug',
+	'Benzin::Bugzilla::Bug'        => 'WriteBug',
 	'Benzin::Bugzilla::BugComment' => 'WriteBugComment',
-	'HASH' => 'WriteHash',
-	-plain => 'WriteValue',
-	-default => 'WriteValue'
+	'HASH'                         => 'WriteHash',
+	'DateTime'                     => 'WriteTJ3DateTime',
+	-plain                         => 'WriteValue',
+	-default                       => 'WriteValue'
 );
 
 use IMPL::Const qw(:prop);
 use IMPL::declare {
 	require => {
-		XMLWriter => 'XML::Writer',
-		Bug => 'Benzin::Bugzilla::Bug',
-		BugComment => 'Benzin::Bugzilla::BugComment'
+		XMLWriter  => 'XML::Writer',
+		Bug        => 'Benzin::Bugzilla::Bug',
+		BugComment => 'Benzin::Bugzilla::BugComment',
 	},
 	base => [
 		'IMPL::Transform' => sub { %Transform }
 	],
 	props => [
-		_writer => PROP_RW
+		_writer        => PROP_RW,
+		timereports    => PROP_RW,
+		timeresolution => PROP_RW
 	]
 };
 
@@ -27,44 +30,45 @@
 
 sub CTOR {
 	my SELF $this = shift;
-	
-	$this->_writer(XMLWriter->new(@_));
+
+	$this->_writer( XMLWriter->new(@_) );
 }
 
 sub WriteBugList {
 	my SELF $this = shift;
 	my $bugs = shift || [];
 	my $writer = $this->_writer;
-	
-	
+
 	$writer->xmlDecl("UTF-8");
 	$writer->startTag("bugzilla");
-	
-	
+
 	foreach my $bug (@$bugs) {
 		$writer->startTag("bug");
 		$this->WriteBug($bug);
 		$writer->endTag();
 	}
-	
+
 	$writer->endTag();
-	
+
 }
 
 sub WriteBug {
 	my SELF $this = shift;
-	my $value       = shift;
+	my $value     = shift;
 	my $writer    = $this->_writer;
 
 	foreach my $field ( @{ Bug->BUG_FIELDS } ) {
 		next unless $value->{$field};
 		$this->WriteElement( $field, $value->{$field} );
 	}
+	$this->WriteElement( 'time',
+		$value->GetTimeReports( $this->timeresolution ) )
+	  if $this->timereports;
 }
 
 sub WriteBugComment {
 	my SELF $this = shift;
-	my $value       = shift;
+	my $value     = shift;
 	my $writer    = $this->_writer;
 
 	foreach my $field ( @{ BugComment->COMMENT_FIELDS } ) {
@@ -76,9 +80,9 @@
 sub WriteHash {
 	my SELF $this = shift;
 	my $value = shift;
-	
-	while(my ($k,$v) = each %$value) {
-		$this->WriteElement($k,$v);
+
+	while ( my ( $k, $v ) = each %$value ) {
+		$this->WriteElement( $k, $v );
 	}
 }
 
@@ -95,7 +99,7 @@
 
 	foreach my $v (@values) {
 		$writer->startTag($name);
-		$this->Transform( $v );
+		$this->Transform($v);
 		$writer->endTag;
 	}
 }
@@ -103,8 +107,15 @@
 sub WriteValue {
 	my SELF $this = shift;
 	my $value = shift;
-	
+
 	$this->_writer->characters($value) if defined $value;
 }
 
+sub WriteTJ3DateTime {
+	my SELF $this = shift;
+    my $value = shift;
+
+    $this->_writer->characters($value->strftime('%F-%T')) if defined $value;
+}
+
 1;
--- a/translate.pl	Mon Sep 07 01:37:11 2015 +0300
+++ b/translate.pl	Mon Sep 07 19:18:21 2015 +0300
@@ -26,6 +26,7 @@
 
 my $proc = start(
 	[ 'saxon8', '-novw', '-', 'bug-list.xsl' ],
+
 	#[ 'cat' ],
 	'<pipe', \*HIN, '>', \*STDOUT
 ) or die "failed to create pipe: $!";
@@ -33,6 +34,8 @@
 binmode *HIN, ":encoding(utf-8)";
 my $writer =
   BugWriter->new( OUTPUT => *HIN, DATA_INDENT => 2, DATA_MODE => 'on' );
+$writer->timereports('on');
+$writer->timeresolution(0.25);
 
 eval {
 	my %visited;