timesheet 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest.txt CHANGED
@@ -6,6 +6,7 @@ bin/timesheet
6
6
  lib/timesheet.rb
7
7
  lib/timesheet/range_extensions.rb
8
8
  lib/timesheet/time_entry.rb
9
+ lib/timesheet/report_item.rb
9
10
  lib/timesheet/time_log.rb
10
11
  lib/timesheet/time_report.rb
11
12
  lib/timesheet/timesheet_parser.rb
data/lib/timesheet.rb CHANGED
@@ -9,6 +9,7 @@ require 'yaml'
9
9
  require 'yaml/store'
10
10
  require 'timesheet/range_extensions'
11
11
  require 'timesheet/time_entry'
12
+ require 'timesheet/report_item'
12
13
  require 'timesheet/time_log'
13
14
  require 'timesheet/time_report'
14
15
  require 'timesheet/trollop'
@@ -16,7 +17,7 @@ require 'timesheet/timesheet_parser'
16
17
 
17
18
  class Timesheet
18
19
 
19
- VERSION = '0.2.1'
20
+ VERSION = '0.2.2'
20
21
 
21
22
  def self.run(params)
22
23
  command_hash = {}
@@ -0,0 +1,53 @@
1
+ require 'delegate'
2
+
3
+ class ReportItem < DelegateClass(TimeEntry)
4
+
5
+ include Comparable
6
+
7
+ def initialize( report, time_entry)
8
+ @time_entry = time_entry
9
+ super(@time_entry)
10
+ @report = report
11
+ end
12
+
13
+ def start_time
14
+ if @time_entry.to_range.include?(@report.report_start)
15
+ @report.report_start
16
+ else
17
+ @time_entry.start_time
18
+ end
19
+ end
20
+
21
+ def end_time
22
+ if to_range.include?(@report.report_end)
23
+ @report.report_end
24
+ else
25
+ @time_entry.end_time
26
+ end
27
+ end
28
+
29
+ def formatted_record_number
30
+ sprintf("%5d", @time_entry.record_number)
31
+ end
32
+
33
+ def formatted_times
34
+ puts start_time
35
+ puts end_time
36
+ str = ""
37
+ str << start_time.strftime("%m/%d/%Y at %I:%M %p")
38
+ str << " to "
39
+ str << end_time.strftime("%m/%d/%Y at ") if ((start_time.year != end_time.year) || (start_time.yday != end_time.yday))
40
+ str << end_time.strftime("%I:%M %p")
41
+ end
42
+
43
+ def formatted_duration
44
+ str = ""
45
+ str << @time_entry.duration.strftime("%d Days ") if @time_entry.duration.days > 0
46
+ str << @time_entry.duration.strftime("%hh %mm")
47
+ end
48
+
49
+ def <=>(other_time_entry)
50
+ self.start_time <=> other_time_entry.start_time
51
+ end
52
+
53
+ end
@@ -46,5 +46,19 @@ class TimeEntry
46
46
  def to_range
47
47
  Range.new(@start_time, @end_time, true)
48
48
  end
49
+
50
+ def to_s
51
+ label_width = 10
52
+ str = ""
53
+ str << "#{"class:".ljust(label_width)}#{self.class}\n"
54
+ str << "#{"record:".ljust(label_width)}#{record_number}\n"
55
+ str << "#{"project:".ljust(label_width)}#{project}\n"
56
+ str << "#{"start:".ljust(label_width)}#{start_time.strftime("%m/%d/%Y at %I:%M %p")}\n"
57
+ str << "#{"end:".ljust(label_width)}#{end_time.strftime("%m/%d/%Y at %I:%M %p")}\n"
58
+ str << "#{"duration:".ljust(label_width)}#{duration}\n"
59
+ str << "#{"comment:".ljust(label_width)}#{comment}\n"
60
+
61
+ str
62
+ end
49
63
 
50
64
  end
@@ -4,17 +4,16 @@ require 'time'
4
4
  class TimeReport
5
5
 
6
6
  def initialize(entries)
7
- @entries = entries
7
+ @entries = (entries.nil?) ? [] : entries.map { |entry| ReportItem.new(self, entry)}
8
8
  end
9
9
 
10
10
  attr_accessor :entries
11
+ attr_reader :report_start
12
+ attr_reader :report_end
11
13
 
12
- def trim(start_time, end_time)
13
- @entries.map! do |e|
14
- e.start_time = start_time if e.to_range.include?(start_time)
15
- e.end_time = end_time if e.to_range.include?(end_time)
16
- e
17
- end
14
+ def constrain(start_time, end_time)
15
+ @report_start = start_time
16
+ @report_end = end_time
18
17
  end
19
18
 
20
19
  def report(command_options, outstream = STDOUT)
@@ -22,7 +21,7 @@ class TimeReport
22
21
  if (@entries.nil? || @entries.empty?)
23
22
  outstream.puts("No data available.")
24
23
  else
25
- trim(command_options[:start], command_options[:end])
24
+ constrain(command_options[:start], command_options[:end])
26
25
 
27
26
  detail_report(outstream) if command_options[:detail]
28
27
  summary_report(outstream) if command_options[:summary]
@@ -33,29 +32,25 @@ class TimeReport
33
32
  private
34
33
 
35
34
  def detail_report(outstream)
35
+
36
+ # field_names = ["Id", "Project", "Start - Stop", "Hours", "Comment"]
37
+ # field_methods = [:formatted_record_number, :project, :formatted_times, :formatted_duration, :comment]
38
+
36
39
  table = Ruport::Data::Table({ :column_names => ["Id", "Project", "Start - Stop", "Hours", "Comment"]}) do |table|
37
40
  @entries.sort.each do |entry|
38
41
  row = []
39
42
 
40
43
  # format record number
41
- row << sprintf("%5d", entry.record_number)
44
+ row << entry.formatted_record_number
42
45
 
43
46
  # format project
44
47
  row << entry.project
45
48
 
46
49
  # format start - stop
47
- str = ""
48
- str << entry.start_time.strftime("%m/%d/%Y at %I:%M %p")
49
- str << " to "
50
- str << entry.end_time.strftime("%m/%d/%Y at ") if ( (entry.start_time.year != entry.end_time.year) && (entry.start_time.yday != entry.end_time.yday))
51
- str << entry.end_time.strftime("%I:%M %p")
52
- row << str
50
+ row << entry.formatted_times
53
51
 
54
52
  # format duration
55
- str = ""
56
- str << entry.duration.strftime("%d Days ") if entry.duration.days > 0
57
- str << entry.duration.strftime("%hh %mm")
58
- row << str
53
+ row << entry.formatted_duration
59
54
 
60
55
  # format comment
61
56
  row << entry.comment
@@ -212,7 +212,7 @@ EOS
212
212
 
213
213
  when :current_week
214
214
  periods[:start] = Chronic.parse("this week #{WEEK_START} at 12 am")
215
- periods[:end] = periods[:start] + 7.days
215
+ periods[:end] = periods[:start] + 1.week
216
216
 
217
217
  when :current_month
218
218
  today = Date.today
@@ -225,8 +225,8 @@ EOS
225
225
  periods[:end] = periods[:start] + 1.day
226
226
 
227
227
  when :last_week
228
- periods[:start] = Chronic.parse("last week #{WEEK_START} at 12 am")
229
- periods[:end] = periods[:start] + 7.days
228
+ periods[:start] = Chronic.parse("this week #{WEEK_START} at 12 am") - 1.week
229
+ periods[:end] = periods[:start] + 1.week
230
230
 
231
231
  when :last_month
232
232
  today = Date.today
@@ -17,7 +17,8 @@ describe TimeEntry do
17
17
  context "Basic Features" do
18
18
 
19
19
  before :each do
20
- @time_entry = TimeEntry.new("Project", Time.local(2009, 12, 1, 9, 0, 0), Time.local(2009, 12, 1, 17, 0, 0))
20
+ @time_entry = TimeEntry.new("Project", Time.local(2009, 12, 1, 9, 0, 0), Time.local(2009, 12, 1, 17, 0, 0), "a comment")
21
+ @time_entry.record_number = 1
21
22
  end
22
23
 
23
24
 
@@ -34,7 +35,8 @@ describe TimeEntry do
34
35
  end
35
36
 
36
37
  it "should have an initial comment of nil" do
37
- @time_entry.comment.should == nil
38
+ time_entry = TimeEntry.new("Project", Time.local(2009, 12, 1, 9, 0, 0), Time.local(2009, 12, 1, 17, 0, 0))
39
+ time_entry.comment.should == nil
38
40
  end
39
41
 
40
42
  it "should calculate its duration from start and end times" do
@@ -74,6 +76,20 @@ describe TimeEntry do
74
76
  it "should not allow assignment to duration" do
75
77
  @time_entry.should_not respond_to :duration=
76
78
  end
79
+
80
+ it "should have a to_s method to display its contents" do
81
+ @time_entry.should respond_to :to_s
82
+ @time_entry.to_s.should eql( <<EOS
83
+ class: TimeEntry
84
+ record: 1
85
+ project: Project
86
+ start: 12/01/2009 at 09:00 AM
87
+ end: 12/01/2009 at 05:00 PM
88
+ duration: 0 seconds 0 minutes 8 hours 0 days
89
+ comment: a comment
90
+ EOS
91
+ )
92
+ end
77
93
 
78
94
  end
79
95
 
@@ -13,13 +13,13 @@ describe TimeReport do
13
13
  end
14
14
 
15
15
  it "should be able to trim its entries to a specific time span" do
16
- @time_report.trim(Time.local(2009, 12, 1, 11, 0, 0), Time.local(2009, 12, 5, 12, 0, 0))
16
+ @time_report.constrain(Time.local(2009, 12, 1, 11, 0, 0), Time.local(2009, 12, 5, 12, 0, 0))
17
17
  @time_report.entries[0].start_time.should eql(Time.local(2009, 12, 1, 11, 0, 0))
18
18
  @time_report.entries[-1].end_time.should eql(Time.local(2009, 12, 5, 12, 0, 0))
19
19
  end
20
20
 
21
21
  it "should leave entries alone when the trim span is outside the entry range" do
22
- @time_report.trim(Time.local(2009, 11, 1, 0, 0, 0), Time.local(2009, 12, 31, 0, 0, 0))
22
+ @time_report.constrain(Time.local(2009, 11, 1, 0, 0, 0), Time.local(2009, 12, 31, 0, 0, 0))
23
23
  @time_report.entries[0].start_time.should eql(Time.local(2009, 12, 1, 9, 0, 0))
24
24
  @time_report.entries[-1].end_time.should eql(Time.local(2009, 12, 5, 17, 0, 0))
25
25
  end
@@ -92,6 +92,7 @@ EOS
92
92
 
93
93
  it "should be able to produce a byday report" do
94
94
  @entries << TimeEntry.new("ProjectB", Time.local(2009, 12, 1, 17, 0, 0), Time.local(2009, 12, 1, 19, 0, 0), "another comment")
95
+ @time_report = TimeReport.new(@entries)
95
96
 
96
97
  command_options = {:byday => true, :start => Time.local(2009, 12, 1), :end => Time.local(2009, 12, 6)}
97
98
  stream = StringIO.new
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timesheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John F. Schank III
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-11 00:00:00 -05:00
12
+ date: 2010-02-07 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -225,6 +225,7 @@ files:
225
225
  - lib/timesheet.rb
226
226
  - lib/timesheet/range_extensions.rb
227
227
  - lib/timesheet/time_entry.rb
228
+ - lib/timesheet/report_item.rb
228
229
  - lib/timesheet/time_log.rb
229
230
  - lib/timesheet/time_report.rb
230
231
  - lib/timesheet/timesheet_parser.rb