view lib/Benzin/Bugzilla/Bug.pm @ 9:cc7244ab1b9f

implemented time reports on bugs
author cin
date Sat, 05 Sep 2015 22:01:12 +0300
parents 29309bc8d932
children 14a966369278
line wrap: on
line source

package Benzin::Bugzilla::Bug;
use strict;
use POSIX;
use Scalar::Util qw(looks_like_number);
use DateTime;

my @fields;

BEGIN {
	@fields = qw(
	  id
	  summary
	  creation_time
	  last_change_time
	  creator
	  assigned_to
	  qa_contact
	  cc

	  is_open
	  status
	  resolution

	  priority
	  severity
	  url

	  blocks
	  depends_on

	  component
	  product
	  classification
	  version

	  actual_time
	  estimated_time
	  remaining_time
	  deadline

	  comments
	  history
	);
}

use constant { BUG_FIELDS => \@fields };

use IMPL::declare {
	require => {
		Strptime => 'DateTime::Format::Strptime'
	},
	base => [
		'IMPL::Object::Fields' => undef
	]
};

use fields @fields;

my $dtparser = Strptime->new(
	pattern => '%Y%m%dT%H:%M:%S',
	time_zone => 'UTC',
	on_error => 'croak'
);

sub CTOR {
	my SELF $this = shift;
	my $data = shift;
	$this->{$_} = $data->{$_}
	  foreach grep exists $data->{$_}, @{ SELF->BUG_FIELDS };
}

# returns {
#	reports => [
#		{ who => email:string, when => report-date-time:DateTime, work_time => hours:double }
#	],
#   actual => hours
#	remaining => hours
# }
sub GetTimeReports {
	my SELF $this = shift;
	my $resolution = shift || 0.25;
	
	warn "Processing: $this->{id}";

	my @bookings;
	my $actual = 0;

	for my $history ( @{ $this->{history} || [] } ) {
		my $who     = $history->{who};
		warn $history->{when};
		my $when    = $dtparser->parse_datetime( $history->{when} );
		my $changes = $history->{changes};

		for my $change ( @{ $changes || [] } ) {
			if ( $change->{field_name} eq 'work_time' ) {
				my $prev  = $change->{removed} || 0;
				my $value = $change->{added}   || 0;
				if ( looks_like_number($prev) and looks_like_number($value) ) {
					my $dt = coarsen( $value - $prev, $resolution );

					if ($dt) {
						push @bookings,
						  {
							who       => $who,
							when      => $when->iso8601(),
							work_time => $dt,
							start     => $when->clone()->subtract( hours => $dt )->iso8601()
						  };
						$actual += $dt;
					}
				}
			}
		}
	}

	return {
		reports   => \@bookings,
		actual    => $actual,
		remaining => coarsen( $this->{remaining_time}, $resolution )
	};
}

sub coarsen {
	my ( $value, $resolution ) = @_;
	return $resolution ? ceil( $value / $resolution ) * $resolution : $value;
}

1;