File Coverage

File:lib/App/TimeTracker/Data/Task.pm
Coverage:89.7%

linestmtbrancondsubpodtimecode
1package App::TimeTracker::Data::Task;
2
8
8
8
8
8
8
953424
389
132
41
23
97
use 5.010;
3
4# ABSTRACT: TimeTracker Task storage
5
6
8
8
8
2568
2001481
86
use Moose;
7
8
8
8
43179
35447
67
use namespace::autoclean;
8
8
8
8
1175
68
186
use App::TimeTracker;
9
8
8
8
2503
466651
396
use DateTime::Format::ISO8601;
10
8
8
8
2954
31137
351
use DateTime::Format::Duration;
11
8
8
8
1788
21061
64
use User::pwent;
12
13
8
8
8
2169
136662
71
use MooseX::Storage;
14with Storage(
15    format => [ JSONpm => { json_opts => { pretty => 1 } } ],
16    io => "File",
17    );
18
19MooseX::Storage::Engine->add_custom_type_handler(
20    'DateTime' => (
21        expand => sub { DateTime::Format::ISO8601->parse_datetime(shift) },
22        collapse => sub { (shift)->iso8601 }
23    )
24);
25my $dtf_dur = DateTime::Format::Duration->new(pattern => '%H:%M:%S', normalise=>1);
26my $dtf_sec = DateTime::Format::Duration->new(pattern => '%s');
27
28has 'start' => (
29    isa=>'DateTime',
30    is=>'ro',
31    required=>1,
32    default=>sub { DateTime->now(time_zone=>'local') }
33);
34has 'stop' => (
35    isa=>'DateTime',
36    is=>'rw',
37    trigger=>\&_calc_duration,
38);
39has 'seconds' => (
40    isa=>'Maybe[Int]',
41    is=>'rw',
42    lazy_build=>1,
43);
44sub _build_seconds {
45
1
3142
    my $self = shift;
46
1
9
    my $delta = DateTime->now(time_zone=>'local')->subtract_datetime($self->start);
47
1
16373
    my $s =$dtf_sec->format_duration($delta);
48
1
184
    return undef unless $s > 1;
49
1
10
    return $s;
50}
51has 'duration' => (
52    isa=>'Str',
53    is=>'rw',
54);
55has 'status' => (
56    isa=>'Str',
57    is=>'rw',
58);
59sub _build_user {
60
1
1
554
8
    return @{getpw( $< )}[0];
61}
62has 'user' => (
63    isa=>'Str',
64    is=>'ro',
65    required => 1,
66    lazy_build => 1,
67);
68has 'project' => (
69    isa=>'Str',
70    is=>'ro',
71    required=>1,
72);
73has 'tags' => (
74    isa=>'ArrayRef',
75    is=>'ro',
76    default=>sub { [] },
77    traits => ['Array'],
78);
79
80sub _filepath {
81
4
51
    my $self = shift;
82
4
31
    my $start = $self->start;
83
4
51
    my $name = $self->project;
84
4
34
    $name=~s/\W/_/g;
85
4
10
    $name=~s/_+/_/g;
86
4
11
    $name=~s/^_//;
87
4
10
    $name=~s/_$//;
88
4
30
    return ($start->year,sprintf('%02d',$start->month),$start->strftime("%Y%m%d-%H%M%S").'_'.$name.'.trc');
89}
90
91sub _calc_duration {
92
3
421
    my ( $self, $stop ) = @_;
93
3
22
    $stop ||= $self->stop;
94
3
93
    my $delta = $stop->subtract_datetime($self->start);
95
3
1046
    $self->seconds($dtf_sec->format_duration($delta));
96
3
716
    $self->duration($dtf_dur->format_duration($delta));
97}
98
99sub storage_location {
100
3
0
5036
    my ($self, $home) = @_;
101
3
13
    my $file = $home->file($self->_filepath);
102
3
1437
    $file->parent->mkpath;
103
3
479
    return $file;
104}
105
106sub save {
107
1
0
3
    my ($self, $home) = @_;
108
109
1
4
    my $file = $self->storage_location($home)->stringify;
110
1
64
    $self->store($file);
111
1
555
    return $file;
112}
113
114sub current {
115
1
0
303024
    my ($class, $home) = @_;
116
1
5
    $class->_load_from_link($home, 'current');
117}
118
119sub previous {
120
1
0
2128
    my ($class, $home) = @_;
121
1
5
    $class->_load_from_link($home, 'previous');
122}
123
124sub _load_from_link {
125
2
8
    my ($class, $home, $link) = @_;
126
2
14
    my $file = $home->file($link);
127
2
649
    return unless -e $file;
128
2
127
    return $class->load($file->slurp(chomp=>1));
129}
130
131sub say_project_tags {
132
1
0
3
    my $self = shift;
133
134
1
10
    my $tags = $self->tags;
135
1
14
    my $rv = $self->project;
136
1
10
    $rv .= ' ('.join(', ',@$tags).')' if @$tags;
137
1
30
    return $rv;
138}
139
140sub do_start {
141
1
0
160
    my ($self, $home) = @_;
142
143
1
4
    my $saved_to = $self->save($home);
144
145
1
72
    my $fh = $home->file('current')->openw;
146
1
493
    say $fh $saved_to;
147
1
15
    close $fh;
148
149
1
5
    say "Started working on ".$self->say_project_tags ." at ". $self->start->hms;
150}
151
152sub rounded_minutes {
153
2
0
3575
    my $self = shift;
154
2
17
    my $sec = $self->seconds;
155
2
23
    my $rest = 60 - $sec % 60;
156
2
8
    my $min = ( $sec + $rest ) /60;
157
2
15
    return $min;
158}
159
160__PACKAGE__->meta->make_immutable;
1611;
162