comparison 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
comparison
equal deleted inserted replaced
8:ff9c0c788382 9:cc7244ab1b9f
1 package Benzin::Bugzilla::Bug; 1 package Benzin::Bugzilla::Bug;
2 use strict; 2 use strict;
3 use POSIX;
4 use Scalar::Util qw(looks_like_number);
5 use DateTime;
3 6
4 my @bugFields; 7 my @fields;
5 8
6 BEGIN { 9 BEGIN {
7 @bugFields = qw( 10 @fields = qw(
8 id 11 id
9 summary 12 summary
10 creation_time 13 creation_time
11 last_change_time 14 last_change_time
12 creator 15 creator
13 assigned_to 16 assigned_to
14 qa_contact 17 qa_contact
15 cc 18 cc
16 19
20 is_open
17 status 21 status
18 resolution 22 resolution
19 23
20 priority 24 priority
21 severity 25 severity
22 url 26 url
23 27
24 blocks 28 blocks
25 depends_on 29 depends_on
26
27 30
28 component 31 component
29 product 32 product
30 classification 33 classification
31 version 34 version
32 35
33 actual_time 36 actual_time
34 estimated_time 37 estimated_time
35 remaining_time 38 remaining_time
36 deadline 39 deadline
37 40
38 comments 41 comments
42 history
39 ); 43 );
40 } 44 }
41 45
42 use constant { 46 use constant { BUG_FIELDS => \@fields };
43 BUG_FIELDS => \@bugFields
44 };
45 47
46 use IMPL::declare { 48 use IMPL::declare {
49 require => {
50 Strptime => 'DateTime::Format::Strptime'
51 },
47 base => [ 52 base => [
48 'IMPL::Object::Fields' => undef 53 'IMPL::Object::Fields' => undef
49 ] 54 ]
50 }; 55 };
51 56
52 use fields @bugFields; 57 use fields @fields;
58
59 my $dtparser = Strptime->new(
60 pattern => '%Y%m%dT%H:%M:%S',
61 time_zone => 'UTC',
62 on_error => 'croak'
63 );
53 64
54 sub CTOR { 65 sub CTOR {
55 my SELF $this = shift; 66 my SELF $this = shift;
56 my $data = shift; 67 my $data = shift;
57 68 $this->{$_} = $data->{$_}
58 $this->{$_} = $data->{$_} foreach grep exists $data->{$_}, SELF->BUG_FIELDS; 69 foreach grep exists $data->{$_}, @{ SELF->BUG_FIELDS };
59 } 70 }
60 71
61 sub GetEffort { 72 # returns {
73 # reports => [
74 # { who => email:string, when => report-date-time:DateTime, work_time => hours:double }
75 # ],
76 # actual => hours
77 # remaining => hours
78 # }
79 sub GetTimeReports {
62 my SELF $this = shift; 80 my SELF $this = shift;
81 my $resolution = shift || 0.25;
63 82
64 return $this->{actual_time} + $this->{remaining_time}; 83 warn "Processing: $this->{id}";
84
85 my @bookings;
86 my $actual = 0;
87
88 for my $history ( @{ $this->{history} || [] } ) {
89 my $who = $history->{who};
90 warn $history->{when};
91 my $when = $dtparser->parse_datetime( $history->{when} );
92 my $changes = $history->{changes};
93
94 for my $change ( @{ $changes || [] } ) {
95 if ( $change->{field_name} eq 'work_time' ) {
96 my $prev = $change->{removed} || 0;
97 my $value = $change->{added} || 0;
98 if ( looks_like_number($prev) and looks_like_number($value) ) {
99 my $dt = coarsen( $value - $prev, $resolution );
100
101 if ($dt) {
102 push @bookings,
103 {
104 who => $who,
105 when => $when->iso8601(),
106 work_time => $dt,
107 start => $when->clone()->subtract( hours => $dt )->iso8601()
108 };
109 $actual += $dt;
110 }
111 }
112 }
113 }
114 }
115
116 return {
117 reports => \@bookings,
118 actual => $actual,
119 remaining => coarsen( $this->{remaining_time}, $resolution )
120 };
121 }
122
123 sub coarsen {
124 my ( $value, $resolution ) = @_;
125 return $resolution ? ceil( $value / $resolution ) * $resolution : $value;
65 } 126 }
66 127
67 1; 128 1;