File Coverage

blib/lib/App/TimeClock/Weekly/Report.pm
Criterion Covered Total %
statement 25 40 62.5
branch 8 20 40.0
condition 7 9 77.7
subroutine 7 10 70.0
pod 2 2 100.0
total 49 81 60.4


line stmt bran cond sub pod time code
1             package App::TimeClock::Weekly::Report;
2              
3 2     2   31720 use POSIX qw(difftime strftime);
  2         3958  
  2         8  
4 2     2   1676 use Time::Local;
  2         2098  
  2         1095  
5              
6             =head1 NAME
7              
8             App::TimeClock::Weekly::Report
9              
10             =head1 DESCRIPTION
11              
12             Can parse the timelog and generate a report using an instance of a
13             L.
14              
15             =head2 METHODS
16              
17             =over
18              
19             =item new($timelog, $printer)
20              
21             Initializes a new L object.
22              
23             Two parameters are required:
24              
25             =over
26              
27             =item B<$timelog>
28              
29             Must point to a timelog file. Will die if not.
30              
31             =item B<$printer>
32              
33             An object derived from L. Will die if not.
34              
35             =back
36              
37             =cut
38             sub new {
39 9 100   9 1 1009 die "must supply (timelog, printer) arguments to constructor" if $#_ != 2;
40 7         8 my $class = shift;
41 7         17 my $self = {
42             timelog => shift,
43             printer => shift,
44             };
45 7 100 66     159 die "timelog ($self->{timelog}) does not exist" unless -f $self->{timelog} and -r $self->{timelog};
46             die "printer is not a PrinterInterface" unless ref $self->{printer} and
47 6 100 100     67 UNIVERSAL::can($self->{printer},'isa') and $self->{printer}->isa("App::TimeClock::Weekly::PrinterInterface");
      66        
48 4         19 bless $self, $class;
49             };
50              
51              
52             =item _timelocal()
53              
54             Returns a time (seconds since epoch) from a date and time.
55              
56             =cut
57             sub _timelocal {
58 1     1   2 my ($self, $date, $time) = @_;
59 1         4 my ($year, $mon, $mday) = split(/\//, $date);
60 1         3 my ($hours, $min, $sec ) = split(/:/, $time);
61              
62 1         6 return timelocal($sec, $min, $hours, $mday, $mon-1, $year);
63             };
64              
65              
66             =item _get_report_time()
67              
68             Returns the time when the report was executed.
69              
70             =cut
71 0 0   0   0 sub _get_report_time { $_[0]->{_report_time} || time }
72              
73              
74             =item _set_report_time()
75              
76             Sets the time when the report is executed.
77              
78             =cut
79 1     1   7 sub _set_report_time { $_[0]->{_report_time} = $_[0]->_timelocal($_[1], $_[2]) }
80              
81              
82             =item _read_lines()
83              
84             Reads a set of check in and check out lines.
85              
86             If end of file is reached after reading the check in line, then
87             reading of the check out line is skipped.
88              
89             =cut
90             sub _read_lines {
91              
92 0     0   0 my ($self, $file) = (@_);
93 0         0 my ($iline, $oline) = (undef, undef);
94              
95 0 0       0 die "Prematurely end of file." if eof($file);
96              
97 0         0 ($iline = <$file>) =~ s/\R//g;
98              
99 0 0       0 die "Expected check in in line $." unless $iline =~ /^i /;
100            
101 0 0       0 if (not eof($file)) {
102 0         0 ($oline = <$file>) =~ s/\R//g;
103 0 0       0 die "Excepted check out in line $." unless $oline =~ /^o /;
104             }
105              
106 0         0 return ($iline, $oline);
107             }
108              
109              
110             =item _parse_lines()
111              
112             Parses a set of check in and check out lines.
113              
114             The lines are split on space and should contain the following four
115             fields:
116              
117             =over
118              
119             =item state
120              
121             is either 'i' - check in or 'o' - check out.
122              
123             =cut
124              
125             =item date
126              
127             is formatted as YYYY/MM//DD
128              
129             =cut
130              
131             =item time
132              
133             is formatted as HH:MM:SS
134              
135             =cut
136              
137             =item project
138              
139             is then name of the project/task and is only required when checking in.
140              
141             =cut
142              
143             =back
144              
145             =cut
146             sub _parse_lines {
147 0     0   0 my ($self, $file) = (@_);
148 0         0 my ($iline, $oline) = $self->_read_lines($file);
149              
150 0         0 my ($idate, $itime, $iproject) = (split(/ /, $iline, 4))[1..3];
151 0 0       0 my ($odate, $otime, $oproject) = (defined $oline) ? (split(/ /, $oline, 4))[1..3] :
152             (strftime("%Y/%m/%d", localtime($self->_get_report_time)),
153             strftime("%H:%M:%S", localtime($self->_get_report_time)), "DANGLING");
154            
155 0         0 return ($idate, $itime, $iproject, $odate, $otime, $oproject);
156             }
157              
158              
159             =item execute()
160              
161             Opens the timelog file starts parsing it, looping over each day and
162             calling print_day() for each.
163              
164             =cut
165             sub execute {
166 2     2 1 130 my $self = shift;
167              
168 2 100   2   11 open (my $file, "<:encoding(UTF-8)", $self->{timelog}) or die "$!\n";
  2         2  
  2         9  
  2         53  
169              
170 1         7688 $self->{printer}->print_header;
171              
172 1         3 $self->{printer}->print_week();
173              
174 1         3 $self->{printer}->print_footer();
175             };
176             1;
177              
178             =back
179              
180             =for text
181             =encoding utf-8
182             =end
183              
184             =head1 AUTHOR
185              
186             Søren Lund, C<< >>
187              
188             =head1 SEE ALSO
189              
190             L
191              
192             =head1 COPYRIGHT
193              
194             Copyright (C) 2012-2014 Søren Lund
195              
196             This file is part of App::TimeClock.
197              
198             App::TimeClock is free software: you can redistribute it and/or modify
199             it under the terms of the GNU General Public License as published by
200             the Free Software Foundation, either version 3 of the License, or
201             (at your option) any later version.
202              
203             App::TimeClock is distributed in the hope that it will be useful,
204             but WITHOUT ANY WARRANTY; without even the implied warranty of
205             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
206             GNU General Public License for more details.
207              
208             You should have received a copy of the GNU General Public License
209             along with App::TimeClock. If not, see .