Pratt 1.6.5 → 1.6.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Pratt.gemspec +16 -4
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/config.rb +0 -1
- data/lib/pratt.rb +1 -1
- data/lib/pratt/core_ext/array.rb +5 -1
- data/lib/pratt/core_ext/float.rb +1 -0
- data/lib/pratt/dialogs.rb +2 -1
- data/lib/pratt/formatting.rb +1 -1
- data/lib/pratt/reports.rb +16 -9
- data/models/customer.rb +5 -1
- data/models/pratt.rb +5 -0
- data/models/project.rb +8 -7
- data/models/whence.rb +1 -3
- data/spec/array_spec.rb +24 -0
- data/spec/fixtures/empty_graph.expectation +8 -0
- data/spec/fixtures/graph.expectation +8 -8
- data/spec/fixtures/proportions.expectation +4 -4
- data/spec/formatting_spec.rb +7 -0
- data/spec/money_spec.rb +9 -0
- data/spec/nil_class_spec.rb +8 -0
- data/spec/pratt_spec.rb +12 -61
- data/spec/project_spec.rb +6 -3
- data/spec/report_action_spec.rb +83 -0
- data/spec/report_spec.rb +205 -0
- data/spec/spec_helper.rb +34 -28
- data/views/general-invoice.eruby +3 -3
- data/views/invoice.eruby +1 -1
- metadata +16 -4
- data/Session.vim +0 -1010
data/Pratt.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{Pratt}
|
8
|
-
s.version = "1.6.
|
8
|
+
s.version = "1.6.8"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Scott Noel-Hemming"]
|
12
|
-
s.date = %q{2010-05-
|
12
|
+
s.date = %q{2010-05-31}
|
13
13
|
s.default_executable = %q{pratt.rb}
|
14
14
|
s.description = %q{
|
15
15
|
Need a way to keep track of your time, but get caught up in work? Or constant interruptions?
|
@@ -40,7 +40,6 @@ Gem::Specification.new do |s|
|
|
40
40
|
"README.html",
|
41
41
|
"README.txt",
|
42
42
|
"Rakefile",
|
43
|
-
"Session.vim",
|
44
43
|
"TODO",
|
45
44
|
"VERSION",
|
46
45
|
"bin/pratt.rb",
|
@@ -315,15 +314,22 @@ Gem::Specification.new do |s|
|
|
315
314
|
"reports/travel.log",
|
316
315
|
"reports/travel.log.2009",
|
317
316
|
"spec/app_spec.rb",
|
317
|
+
"spec/array_spec.rb",
|
318
318
|
"spec/customer_spec.rb",
|
319
|
+
"spec/fixtures/empty_graph.expectation",
|
319
320
|
"spec/fixtures/graph.expectation",
|
320
321
|
"spec/fixtures/proportions.expectation",
|
321
322
|
"spec/float_spec.rb",
|
323
|
+
"spec/formatting_spec.rb",
|
324
|
+
"spec/money_spec.rb",
|
325
|
+
"spec/nil_class_spec.rb",
|
322
326
|
"spec/numeric_spec.rb",
|
323
327
|
"spec/payment_spec.rb",
|
324
328
|
"spec/pratt_spec.rb",
|
325
329
|
"spec/project_spec.rb",
|
326
330
|
"spec/rcov.opts",
|
331
|
+
"spec/report_action_spec.rb",
|
332
|
+
"spec/report_spec.rb",
|
327
333
|
"spec/spec.opts",
|
328
334
|
"spec/spec_helper.rb",
|
329
335
|
"spec/string_ext_spec.rb",
|
@@ -348,15 +354,21 @@ Gem::Specification.new do |s|
|
|
348
354
|
s.rubygems_version = %q{1.3.6}
|
349
355
|
s.summary = %q{Pro/Re-Active Time Tracker. Track time based on what you expect to be working on, with frequent prompts to ensure accuracy.}
|
350
356
|
s.test_files = [
|
351
|
-
"spec/
|
357
|
+
"spec/nil_class_spec.rb",
|
358
|
+
"spec/whence_spec.rb",
|
359
|
+
"spec/array_spec.rb",
|
352
360
|
"spec/spec_helper.rb",
|
353
361
|
"spec/float_spec.rb",
|
354
362
|
"spec/pratt_spec.rb",
|
355
363
|
"spec/project_spec.rb",
|
356
364
|
"spec/numeric_spec.rb",
|
357
365
|
"spec/app_spec.rb",
|
366
|
+
"spec/formatting_spec.rb",
|
358
367
|
"spec/string_ext_spec.rb",
|
359
368
|
"spec/customer_spec.rb",
|
369
|
+
"spec/report_spec.rb",
|
370
|
+
"spec/money_spec.rb",
|
371
|
+
"spec/report_action_spec.rb",
|
360
372
|
"spec/payment_spec.rb"
|
361
373
|
]
|
362
374
|
|
data/Rakefile
CHANGED
@@ -42,6 +42,7 @@ Spec::Rake::SpecTask.new(:rcov) do |spec|
|
|
42
42
|
spec.libs << 'lib' << 'spec'
|
43
43
|
spec.pattern = 'spec/**/*_spec.rb'
|
44
44
|
spec.rcov = true
|
45
|
+
spec.rcov_opts = %w(--text-report --exclude=activerecord,ruby-debug,shifty_week,sqlite3-ruby,rspec,mocha,erubis,chronic,colored,columnize,builder,activesupport,i18n,linecache,json_pure,rcov,abstract,spec_helper.rb,config.rb,spec)
|
45
46
|
end
|
46
47
|
|
47
48
|
task :spec => :check_dependencies
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.6.
|
1
|
+
1.6.8
|
data/config.rb
CHANGED
data/lib/pratt.rb
CHANGED
data/lib/pratt/core_ext/array.rb
CHANGED
@@ -7,7 +7,11 @@ class Pratt
|
|
7
7
|
# @param [String] conjunction
|
8
8
|
# @return [String]
|
9
9
|
def to_sentence conjunction = 'and'
|
10
|
-
|
10
|
+
if self.size >= 2
|
11
|
+
self[0..-2].join(", ") << (self.size > 2 ? ',' : '') << " #{conjunction} #{self.last}"
|
12
|
+
elsif self.size <= 1
|
13
|
+
self.first.to_s
|
14
|
+
end
|
11
15
|
end
|
12
16
|
end
|
13
17
|
end
|
data/lib/pratt/core_ext/float.rb
CHANGED
data/lib/pratt/dialogs.rb
CHANGED
@@ -61,8 +61,9 @@ class Pratt
|
|
61
61
|
def pop
|
62
62
|
reload_and_detect_lock 'pop'
|
63
63
|
self.project = Whence.last_unended.project
|
64
|
+
project_time = project.formatted_time_spent_totals( project.time_spent(scale, when_to) )
|
64
65
|
defork do
|
65
|
-
command = "ruby views/pop.rb --project '#{project.name}' --start '#{project.whences.last_unended.start_at}' --project_time '#{
|
66
|
+
command = "ruby views/pop.rb --project '#{project.name}' --start '#{project.whences.last_unended.start_at}' --project_time '#{project_time}'"
|
66
67
|
system command
|
67
68
|
end
|
68
69
|
end
|
data/lib/pratt/formatting.rb
CHANGED
@@ -17,7 +17,7 @@ class Pratt
|
|
17
17
|
end
|
18
18
|
|
19
19
|
# Calculate totals. I think this should be an instance method on Projects/?/Whences
|
20
|
-
def totals hr
|
20
|
+
def totals hr
|
21
21
|
"#{(hr / 24).format_integer.cyan} day #{(hr % 24).format_integer.yellow} hour #{(60*(hr -= hr.to_i)).format_integer.green} min"
|
22
22
|
end
|
23
23
|
end
|
data/lib/pratt/reports.rb
CHANGED
@@ -5,7 +5,7 @@ class Pratt
|
|
5
5
|
self.template = 'graph'
|
6
6
|
|
7
7
|
if project?
|
8
|
-
@projects = [project]
|
8
|
+
@projects = [ project ]
|
9
9
|
else
|
10
10
|
@projects = Project.all
|
11
11
|
end
|
@@ -21,7 +21,7 @@ class Pratt
|
|
21
21
|
@projects = [project]
|
22
22
|
|
23
23
|
@primary = project.time_spent(scale, when_to)
|
24
|
-
@scaled_total = project.
|
24
|
+
@scaled_total = project.time_spent(scale, when_to)
|
25
25
|
else
|
26
26
|
@projects = Project.all
|
27
27
|
|
@@ -30,13 +30,13 @@ class Pratt
|
|
30
30
|
@off_total = proj.time_spent(scale, when_to) if proj.name == Project.off.name
|
31
31
|
@rest_total += proj.time_spent(scale, when_to) if Project.rest.collect(&:name).include?(proj.name)
|
32
32
|
end
|
33
|
-
@scaled_total = Whence.time_spent(scale, when_to)
|
33
|
+
@scaled_total = Whence.time_spent(scale, when_to) - @off_total
|
34
34
|
end
|
35
35
|
|
36
36
|
if @primary + @off_total + @rest_total > 0.0
|
37
37
|
process_template!
|
38
38
|
else
|
39
|
-
"No data to report"
|
39
|
+
$stdout.puts "No data to report"
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -47,13 +47,13 @@ class Pratt
|
|
47
47
|
if project?
|
48
48
|
@projects = [project]
|
49
49
|
|
50
|
-
@total = project.amount(scale, when_to)
|
50
|
+
@total = project.amount( project.time_spent(scale, when_to) )
|
51
51
|
else
|
52
52
|
@projects = (Project.all - [Project.primary, Project.off])
|
53
|
-
@projects.select
|
53
|
+
@projects = @projects.select {|proj| show_all or ( !show_all and proj.time_spent(scale, when_to) != 0.0 ) }
|
54
54
|
|
55
55
|
@total = @projects.inject 0.0 do |total, proj|
|
56
|
-
total += proj.amount(scale, when_to)
|
56
|
+
total += proj.amount( proj.time_spent(scale, when_to) )
|
57
57
|
total
|
58
58
|
end
|
59
59
|
end
|
@@ -64,7 +64,7 @@ class Pratt
|
|
64
64
|
if @total > 0.0
|
65
65
|
process_template!
|
66
66
|
else
|
67
|
-
puts "No data to report"
|
67
|
+
$stdout.puts "No data to report in Pratt#invoice"
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
@@ -118,10 +118,17 @@ class Pratt
|
|
118
118
|
end
|
119
119
|
|
120
120
|
private
|
121
|
+
def output
|
122
|
+
# for testing
|
123
|
+
@__output
|
124
|
+
end
|
125
|
+
|
121
126
|
def process_template!
|
122
127
|
input = File.open(Pratt.root("views", "#{template}.eruby").first).read
|
123
128
|
erubis = Erubis::Eruby.new(input)
|
124
|
-
|
129
|
+
@__output = erubis.evaluate(self)
|
130
|
+
$stdout.puts @__output
|
131
|
+
nil
|
125
132
|
end
|
126
133
|
|
127
134
|
end
|
data/models/customer.rb
CHANGED
@@ -13,7 +13,11 @@ class Customer < ActiveRecord::Base
|
|
13
13
|
phone = read_attribute(:phone)
|
14
14
|
class << phone
|
15
15
|
def pretty_print sep = '.'
|
16
|
-
self.
|
16
|
+
if self.blank?
|
17
|
+
""
|
18
|
+
else
|
19
|
+
self.split(/(\d{3})(\d{3})(\d{4})/)[1,3] * sep
|
20
|
+
end
|
17
21
|
end
|
18
22
|
end
|
19
23
|
phone
|
data/models/pratt.rb
CHANGED
@@ -6,5 +6,10 @@ class Pratt
|
|
6
6
|
cond = [(cond << "start_at BETWEEN ? AND ?").join(' AND ')] | [when_to.send("beginning_of_#{scale}"), when_to.send("end_of_#{scale}")] unless scale.nil?
|
7
7
|
cond
|
8
8
|
end
|
9
|
+
|
10
|
+
def total_whences whences_since
|
11
|
+
seconds = whences_since.inject(0.0) {|total, whence| total += ( whence.end_at - whence.start_at ) }
|
12
|
+
hour = seconds / 3600
|
13
|
+
end
|
9
14
|
end
|
10
15
|
end
|
data/models/project.rb
CHANGED
@@ -25,19 +25,20 @@ class Project < ActiveRecord::Base
|
|
25
25
|
self.start! at
|
26
26
|
end
|
27
27
|
|
28
|
-
def time_spent scale = nil, when_to = DateTime.now
|
28
|
+
def time_spent scale = nil, when_to = DateTime.now, &block
|
29
29
|
whences_since = self.whences.find :all, :conditions => conditions_for_time_spent(scale, when_to)
|
30
|
-
whences_since
|
31
|
-
total += ( whence.end_at - whence.start_at )
|
32
|
-
} / 3600
|
30
|
+
total_whences whences_since
|
33
31
|
end
|
34
32
|
|
35
|
-
def amount
|
36
|
-
amount =
|
37
|
-
amount *= payment.rate / 100.0
|
33
|
+
def amount hour
|
34
|
+
amount = hour * ( payment.rate / 100.0 )
|
38
35
|
amount.to_money
|
39
36
|
end
|
40
37
|
|
38
|
+
def formatted_time_spent_totals hour
|
39
|
+
"#{(hour / 24).format_integer.cyan} day #{(hour % 24).format_integer.yellow} hour #{(60*(hour -= hour.to_i)).format_integer.green} min"
|
40
|
+
end
|
41
|
+
|
41
42
|
class << self
|
42
43
|
def named name
|
43
44
|
first :conditions => { :name => name }
|
data/models/whence.rb
CHANGED
@@ -45,9 +45,7 @@ class Whence < ActiveRecord::Base
|
|
45
45
|
|
46
46
|
def time_spent scale = nil, when_to = Time.now
|
47
47
|
whences_since = Whence.find :all, :conditions => conditions_for_time_spent(scale, when_to)
|
48
|
-
whences_since
|
49
|
-
total += ( whence.end_at - whence.start_at )
|
50
|
-
} / 3600
|
48
|
+
total_whences whences_since
|
51
49
|
end
|
52
50
|
|
53
51
|
def last_unended
|
data/spec/array_spec.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pratt'
|
3
|
+
|
4
|
+
describe Array do
|
5
|
+
it "to_sentence concatenates each element correctly with no elements" do
|
6
|
+
[].to_sentence.should eql('')
|
7
|
+
end
|
8
|
+
|
9
|
+
it "to_sentence concatenates each element correctly with one element" do
|
10
|
+
%w(a).to_sentence.should eql('a')
|
11
|
+
end
|
12
|
+
|
13
|
+
it "to_sentence concatenates each element correctly with two elements" do
|
14
|
+
%w(a b).to_sentence.should eql('a and b')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "to_sentence concatenates each element correctly with >= three elements" do
|
18
|
+
%w(a b c d).to_sentence.should eql('a, b, c, and d')
|
19
|
+
end
|
20
|
+
|
21
|
+
it "to_sentence concatenates each element correctly with >= three elements and a different conjunction" do
|
22
|
+
%w(a b c d).to_sentence('&').should eql('a, b, c, & d')
|
23
|
+
end
|
24
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
Project detail
|
2
2
|
by week from
|
3
3
|
Mon 00:00:00 Sep 28 2009 to Sun 23:59:59 Oct 04 2009
|
4
|
-
|
5
|
-
|
4
|
+
dys hrs min total
|
5
|
+
-------------------------------------------------------------------
|
6
6
|
|
7
|
-
Lunch/Break| 00 day 01 hour 21 min
|
8
|
-
Task1| 00 day 01 hour
|
9
|
-
Task2| 00 day 00 hour 58 min
|
10
|
-
Another Task| 00 day 00 hour 05 min
|
11
|
-
Task3| 01 day 17 hour
|
7
|
+
Lunch/Break | 00 day 01 hour 21 min 1.35
|
8
|
+
Task1 | 00 day 01 hour 03 min 1.07
|
9
|
+
Task2 | 00 day 00 hour 58 min 0.97
|
10
|
+
Another Task | 00 day 00 hour 05 min 0.08
|
11
|
+
Task3 | 01 day 17 hour 31 min 41.53
|
12
12
|
|
13
|
-
|
13
|
+
-------------------------------------------------------------------
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
Total 43.65 hrs
|
2
|
+
Refactor 0.00%
|
3
|
+
Lunch/Break 3.09%
|
4
|
+
Other 100.00%
|
data/spec/money_spec.rb
ADDED
data/spec/pratt_spec.rb
CHANGED
@@ -81,59 +81,7 @@ describe Pratt do
|
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
-
describe "graph" do
|
85
|
-
before :each do
|
86
|
-
@when_to = Chronic.parse('last week').beginning_of_week
|
87
|
-
@pratt.scale = 'week'
|
88
|
-
@pratt.when_to = @when_to
|
89
|
-
@customer = Customer.create :name => 'Bob Hope', :address => '123 Where St', :zip => '22222'
|
90
|
-
@tasks = []
|
91
|
-
end
|
92
|
-
|
93
|
-
after :each do
|
94
|
-
Whence.delete_all
|
95
|
-
@customer.destroy
|
96
|
-
@tasks.each(&:destroy)
|
97
|
-
end
|
98
|
-
|
99
|
-
def task name, time_spent
|
100
|
-
task = Project.find_or_create_by_name :name => name, :customer => @customer
|
101
|
-
task.start! @when_to
|
102
|
-
task.stop! @when_to+time_spent
|
103
|
-
@tasks << task
|
104
|
-
end
|
105
|
-
|
106
|
-
def populate_with_data
|
107
|
-
@tasks << Project.find_or_create_by_name( :name => '**** ********', :weight => 1, :customer => @customer )
|
108
|
-
task 'Lunch/Break', 1.hour+21.minutes
|
109
|
-
task 'Task1', 1.hour+4.minutes
|
110
|
-
task 'Task2', 58.minutes
|
111
|
-
task 'Another Task', 5.minutes
|
112
|
-
task 'Task3', 1.day+17.hours+32.minutes
|
113
|
-
end
|
114
|
-
|
115
|
-
def get_expected_display
|
116
|
-
e = ''
|
117
|
-
Pratt.root('spec', 'fixtures', 'graph.expectation') {|file| e = File.open(file).read }
|
118
|
-
e
|
119
|
-
end
|
120
|
-
|
121
|
-
it "report no data" do
|
122
|
-
Project.expects(:all).returns([])
|
123
|
-
@pratt.expects(:process_template!).never
|
124
|
-
@pratt.graph.should == "No data to report"
|
125
|
-
end
|
126
|
-
|
127
|
-
it "should look right with data" do
|
128
|
-
populate_with_data
|
129
|
-
@pratt.expects(:process_template!)
|
130
|
-
|
131
|
-
@pratt.graph.should == get_expected_display
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
84
|
describe "parse" do
|
136
|
-
it "handles cli arg -n setting appropriate environment config"
|
137
85
|
# do
|
138
86
|
## Pratt.expects(:connect).with('staging')
|
139
87
|
## lambda {
|
@@ -142,14 +90,17 @@ describe Pratt do
|
|
142
90
|
# ENV['PRATT_ENV'].should == 'staging'
|
143
91
|
# end
|
144
92
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
93
|
+
it "inits an irb console when given console argument" do
|
94
|
+
Pratt.any_instance.stubs(:i_should?).returns false
|
95
|
+
# ^ to bypass actually calling the code
|
96
|
+
Pratt.any_instance.expects(:<<).with(:console)
|
97
|
+
Pratt.parse %w(console)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should start IRB when console method is called" do
|
102
|
+
ARGV.expects(:clear)
|
103
|
+
IRB.expects(:start)
|
104
|
+
@pratt.console
|
154
105
|
end
|
155
106
|
end
|