More tweaks to output.
[ical-summary.git] / bin / summary-ics.pl
1 #!/usr/bin/perl -w
2
3 use strict;
4 use Getopt::Long;
5 use Date::Manip;
6 use iCal::Parser;
7 use Text::Wrap;
8
9 my $start = undef;
10 my $end   = undef;
11
12 GetOptions(
13  'start' => \$start,
14  'end'   => \$end,
15 );
16
17 $start ||= UnixDate(ParseDate('last month'), '%Y-%m-01');
18 $end   ||= UnixDate(ParseDate('now'), '%Y-%m-01');
19
20 $start = ParseDate($start);
21 $end   = ParseDate($end);
22
23 my $filename = shift;
24
25 die "Please tell me a filename to work on!\n"
26   unless defined $filename;
27 die "I can't find the file: $filename\n"
28   unless -f $filename;
29
30 print "Processing date range: " . UnixDate($start, '%Y-%m-%d') . " - " . UnixDate($end, '%Y-%m-%d') . "\n\n";
31
32 my $parser = iCal::Parser->new(
33   'start' => UnixDate($start, '%Y%m%d'),
34   'end'   => UnixDate($end, '%Y%m%d'),
35   'no_todos' => 1,
36 );
37
38 my $cal = $parser->parse($filename);
39 my $events = $cal->{'events'};
40
41 my %clients;
42 my %days;
43 my $total_hours = 0;
44
45 use Data::Dumper;
46 for my $year (keys %{ $events }) {
47   for my $month (sort keys %{ $events->{$year} }) {
48     for my $day (sort keys %{ $events->{$year}{$month} }) {
49       for my $uid (keys %{ $events->{$year}{$month}{$day} }) {
50         my $summary = $events->{$year}{$month}{$day}{$uid}{'SUMMARY'}     || '';
51         my $desc    = $events->{$year}{$month}{$day}{$uid}{'DESCRIPTION'} || 'misc';
52         my $hours   = $events->{$year}{$month}{$day}{$uid}{'hours'}       || 0;
53         my $dtstart = $events->{$year}{$month}{$day}{$uid}{'DTSTART'}     || '';
54
55         $hours = 8
56           if defined $events->{$year}{$month}{$day}{$uid}{'allday'};
57
58         $dtstart =~ s/T/ /;
59         $desc =~ s/\\//g;
60
61         $total_hours += $hours;
62
63         # Days
64         my ($day) = split(/ /, $dtstart);
65         $days{$day}{lc($summary)}{'work'}{$desc} += $hours;
66         $days{$day}{lc($summary)}{'client'} ||= $summary;
67
68         # Clients
69         $clients{lc($summary)}{'work'}{$desc}{'hours'} += $hours;
70         $clients{lc($summary)}{'hours'} += $hours;
71         $clients{lc($summary)}{'client'} ||= $summary;
72         push @{ $clients{lc($summary)}{'work'}{$desc}{'times'} }, [ $hours, $dtstart ];
73         #print "event: $summary - $dtstart - $desc\n";
74       #print Dumper($entry);
75       }
76     }
77   }
78 }
79
80 print_clients_summary();
81 print "\n";
82 print_clients();
83 print "\n";
84 print_days();
85
86 print "Total Hours Worked: $total_hours\n\n";
87
88 exit;
89
90 sub detail_line {
91   my $indent = shift;
92   return sprintf((' ' x $indent) . "%2.2f - %s\n", @_);
93 }
94   
95 sub print_clients_summary {
96   $Text::Wrap::columns = 78;
97   for my $client (sort keys %clients) {
98     print detail_line(2, $clients{$client}{'hours'}, $clients{$client}{'client'});
99   }
100 }
101
102 sub print_clients {
103   $Text::Wrap::columns = 78;
104   for my $client (sort keys %clients) {
105     print "$clients{$client}{'client'}:\n";
106     print detail_line(2, $clients{$client}{'hours'}, 'Client Total');
107     print "\n";
108   
109     for my $desc (sort keys %{ $clients{$client}{'work'} }) {
110       print wrap('  ', '  ', $desc) . "\n";
111   
112       for my $time (sort { $a->[1] cmp $b->[1] } @{ $clients{$client}{'work'}{$desc}{'times'} }) {
113         print detail_line(4, $time->[0], $time->[1]);
114       }
115   
116       if (scalar(@{ $clients{$client}{'work'}{$desc}{'times'} }) > 1) {
117         print detail_line(4, $clients{$client}{'work'}{$desc}{'hours'}, 'Total');
118       }
119     }
120
121     print "\n";
122   }
123 }
124
125 sub print_days {
126   $Text::Wrap::columns = 70;
127   for my $day (sort keys %days) {
128     print "$day:\n";
129
130     for my $client (sort keys %{ $days{$day} }) {
131       for my $desc (sort keys %{ $days{$day}{$client}{'work'} }) {
132         print detail_line(2, $days{$day}{$client}{'work'}{$desc}, wrap('', '         ', "$days{$day}{$client}{'client'} - $desc"));
133       }
134     }
135
136     print "\n";
137   }
138 }
139