Pratt 1.6.8-x86-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/.exrc +61 -0
  2. data/.gitignore +6 -0
  3. data/History.txt +6 -0
  4. data/Manifest.txt +46 -0
  5. data/Pratt.gemspec +173 -0
  6. data/Pratt.mm +1867 -0
  7. data/README.txt +67 -0
  8. data/Rakefile +96 -0
  9. data/TODO +56 -0
  10. data/VERSION +1 -0
  11. data/bin/pratt +13 -0
  12. data/config.rb +19 -0
  13. data/db/sqlite_databases_go_here +0 -0
  14. data/db/zips.csv.zip +0 -0
  15. data/lib/models.rb +8 -0
  16. data/lib/pratt.rb +308 -0
  17. data/lib/pratt/core_ext.rb +6 -0
  18. data/lib/pratt/core_ext/array.rb +20 -0
  19. data/lib/pratt/core_ext/float.rb +29 -0
  20. data/lib/pratt/core_ext/nil.rb +5 -0
  21. data/lib/pratt/core_ext/numeric.rb +9 -0
  22. data/lib/pratt/core_ext/string.rb +31 -0
  23. data/lib/pratt/core_ext/time.rb +20 -0
  24. data/lib/pratt/dialogs.rb +81 -0
  25. data/lib/pratt/formatting.rb +19 -0
  26. data/lib/pratt/project_actions.rb +25 -0
  27. data/lib/pratt/reports.rb +140 -0
  28. data/models/app.rb +39 -0
  29. data/models/customer.rb +50 -0
  30. data/models/invoice.rb +28 -0
  31. data/models/invoice_whence.rb +18 -0
  32. data/models/payment.rb +22 -0
  33. data/models/pratt.rb +15 -0
  34. data/models/project.rb +89 -0
  35. data/models/whence.rb +77 -0
  36. data/models/zip.rb +27 -0
  37. data/pratt.mm +1875 -0
  38. data/spec/app_spec.rb +48 -0
  39. data/spec/array_spec.rb +24 -0
  40. data/spec/customer_spec.rb +31 -0
  41. data/spec/fixtures/empty_graph.expectation +8 -0
  42. data/spec/fixtures/graph.expectation +13 -0
  43. data/spec/fixtures/proportions.expectation +4 -0
  44. data/spec/float_spec.rb +24 -0
  45. data/spec/formatting_spec.rb +7 -0
  46. data/spec/money_spec.rb +9 -0
  47. data/spec/nil_class_spec.rb +8 -0
  48. data/spec/numeric_spec.rb +30 -0
  49. data/spec/payment_spec.rb +19 -0
  50. data/spec/pratt_spec.rb +106 -0
  51. data/spec/project_spec.rb +182 -0
  52. data/spec/rcov.opts +0 -0
  53. data/spec/report_action_spec.rb +83 -0
  54. data/spec/report_spec.rb +205 -0
  55. data/spec/seed_data.rb +33 -0
  56. data/spec/spec.opts +1 -0
  57. data/spec/spec_helper.rb +24 -0
  58. data/spec/string_ext_spec.rb +33 -0
  59. data/spec/whence_spec.rb +54 -0
  60. data/tasks/pratt.rb +87 -0
  61. data/templates/model.eruby +12 -0
  62. data/templates/spec.eruby +8 -0
  63. data/views/current.eruby +5 -0
  64. data/views/general-invoice.eruby +538 -0
  65. data/views/graph.eruby +16 -0
  66. data/views/invoice.eruby +148 -0
  67. data/views/main.rb +90 -0
  68. data/views/pid.eruby +3 -0
  69. data/views/pop.rb +78 -0
  70. data/views/proportions.eruby +4 -0
  71. data/views/raw.eruby +11 -0
  72. metadata +275 -0
File without changes
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ require 'pratt'
3
+
4
+ describe "Pratt report actions" do
5
+ include SeedData
6
+
7
+ before :each do
8
+ @pratt = Pratt.new
9
+ @when_to = DateTime.now
10
+ load_seed_data
11
+ end
12
+
13
+ after :each do
14
+ Whence.delete_all
15
+ end
16
+
17
+ it "calls project#start! in begin method" do
18
+ @pratt.project = Project.primary
19
+ @pratt.when_to = @when_to
20
+ @pratt.project.expects(:start!).with @when_to
21
+ @pratt.begin
22
+ end
23
+
24
+ it "calls project#restart! in restart method with defined project" do
25
+ @next_when_to = @when_to + 7.minutes
26
+ primary = Project.primary
27
+ primary.start! @when_to
28
+ @pratt.project = primary
29
+ @pratt.when_to = @next_when_to
30
+ whence = primary.whences.last
31
+ Whence.expects(:last_unended).never
32
+ primary.expects(:restart!).with @next_when_to
33
+ @pratt.restart
34
+ end
35
+
36
+ it "calls last unended project in restart method without defined project" do
37
+ @next_when_to = @when_to + 7.minutes
38
+ primary = Project.primary
39
+ primary.start! @when_to
40
+ @pratt.when_to = @next_when_to
41
+ whence = primary.whences.last
42
+ Whence.expects(:last_unended).returns whence
43
+ whence.project.expects(:restart!).with @next_when_to
44
+ @pratt.restart
45
+ whence.project.should eql(primary)
46
+ end
47
+
48
+ it "stops! defined project in end method" do
49
+ @pratt.project = Project.primary
50
+ @pratt.when_to = @when_to
51
+ @pratt.project.expects(:stop!).with @when_to
52
+ @pratt.end
53
+ end
54
+
55
+ it "stops! the last unended project in end method without defined project" do
56
+ primary = Project.primary
57
+ primary.start! @when_to
58
+ whence = primary.whences.last
59
+ Whence.expects(:last_unended).returns whence
60
+ whence.expects(:stop!).with @when_to
61
+ @pratt.when_to = @when_to
62
+ @pratt.end
63
+ end
64
+
65
+ it "changes last project in change method" do
66
+ primary = Project.primary
67
+ primary.start! @when_to
68
+ primary.stop! @when_to+10.minutes
69
+ other = Project.rest.first
70
+ whence = primary.whences.last
71
+ Whence.expects(:last).returns whence
72
+ whence.expects(:change!).with other.name
73
+ @pratt.project = other
74
+ @pratt.change
75
+ end
76
+
77
+ it "destroys defined project in destroy method" do
78
+ @pratt.project = Project.create :name => "to be destroyed"
79
+ lambda {
80
+ @pratt.destroy
81
+ }.should change(Project, :count).by -1
82
+ end
83
+ end
@@ -0,0 +1,205 @@
1
+ require 'spec_helper'
2
+ require 'pratt'
3
+
4
+ describe "Pratt report method" do
5
+
6
+ describe "#pid" do
7
+ @pratt = Pratt.new
8
+ @pratt.expects(:template=).with("pid")
9
+ @pratt.expects(:process_template!)
10
+ @pratt.pid
11
+ end
12
+
13
+ # FIXME: Get this working
14
+ describe "#cpid" #do
15
+ # @pratt = Pratt.new
16
+ # ::Kernel.expects(:`)
17
+ # @pratt.cpid
18
+ # end
19
+
20
+ describe "#graph" do
21
+ before :each do
22
+ @pratt = Pratt.new
23
+ end
24
+
25
+ it "with no project uses Project.all to generate output" do
26
+ @pratt.expects(:template=).with("graph")
27
+ @pratt.expects(:project?).returns false
28
+ Project.expects(:all).returns([])
29
+ @pratt.expects(:process_template!)
30
+ @pratt.graph
31
+ end
32
+
33
+ it "with project uses defined project to generate output" do
34
+ @pratt.project = Project.new
35
+ @pratt.expects(:template=).with("graph")
36
+ @pratt.expects(:project?).returns true
37
+ @pratt.expects(:process_template!)
38
+ @pratt.graph
39
+ @pratt.instance_variable_get("@projects").should eql([@pratt.project])
40
+ end
41
+ end
42
+
43
+ describe "output" do
44
+ include SeedData
45
+
46
+ before :each do
47
+ @pratt = Pratt.new
48
+ end
49
+ before :each do
50
+ @when_to = Chronic.parse('September 29 2009').beginning_of_week
51
+ @pratt.scale = 'week'
52
+ @pratt.when_to = @when_to
53
+ @customer = Customer.create :name => 'Bob Hope', :address => '123 Where St', :zip => '22222'
54
+ @tasks = []
55
+ end
56
+
57
+ after :each do
58
+ Whence.delete_all
59
+ @customer.destroy
60
+ @tasks.each(&:destroy)
61
+ end
62
+
63
+ def get_expected_display fixture_name
64
+ Pratt.root('spec', 'fixtures', "#{fixture_name}.expectation").first.read
65
+ end
66
+
67
+ it "graphs output as expected with no data" do
68
+ Pratt.color = false
69
+ Project.stubs(:longest_project_name).returns 12
70
+ Project.stubs(:all).returns([])
71
+ $stdout.expects(:puts)
72
+ @pratt.graph
73
+ @pratt.send(:output).should eql( get_expected_display("empty_graph") )
74
+ end
75
+
76
+ it "graphs output as expected with data" do
77
+ populate_with_data
78
+ Pratt.color = false
79
+ Project.stubs(:longest_project_name).returns 12
80
+ $stdout.expects(:puts)
81
+
82
+ @pratt.graph
83
+ @pratt.send(:output).should eql( get_expected_display("graph") )
84
+ end
85
+
86
+ it "generates proportions graphs output as expected with data" do
87
+ populate_with_data
88
+ Pratt.color = false
89
+ Project.stubs(:longest_project_name).returns 12
90
+ $stdout.expects(:puts)
91
+
92
+ @pratt.proportions
93
+ @pratt.send(:output).should eql( get_expected_display("proportions") )
94
+ end
95
+
96
+ def task name, time_spent
97
+ task = Project.find_or_create_by_name :name => name, :customer => @customer
98
+ task.start! @when_to
99
+ task.stop! @when_to+time_spent
100
+ @tasks << task
101
+ end
102
+
103
+ def populate_with_data
104
+ load_seed_data
105
+ @tasks << Project.primary
106
+ task 'Lunch/Break', 1.hour+21.minutes+0.seconds
107
+ task 'Task1', 1.hour+4.minutes+0.seconds
108
+ task 'Task2', 58.minutes+0.seconds
109
+ task 'Another Task', 5.minutes+0.seconds
110
+ task 'Task3', 1.day+17.hours+32.minutes+0.seconds
111
+ end
112
+ end
113
+
114
+ describe "#proportions" do
115
+ include SeedData
116
+
117
+ before :each do
118
+ @pratt = Pratt.new
119
+ end
120
+ before :each do
121
+ @when_to = Chronic.parse('last week').beginning_of_week
122
+ @pratt.scale = 'week'
123
+ @pratt.when_to = @when_to
124
+ @customer = Customer.create :name => 'Bob Hope', :address => '123 Where St', :zip => '22222'
125
+ @tasks = []
126
+ end
127
+
128
+ after :each do
129
+ Whence.delete_all
130
+ @customer.destroy
131
+ @tasks.each(&:destroy)
132
+ end
133
+
134
+ def task name, time_spent
135
+ task = Project.find_or_create_by_name :name => name, :customer => @customer, :weight => -1
136
+ task.start! @when_to
137
+ task.stop! @when_to+time_spent
138
+ @tasks << task
139
+ end
140
+
141
+ def populate_with_data
142
+ load_seed_data
143
+ primary = Project.primary
144
+ primary.start! @when_to
145
+ primary.stop! @when_to+20.hours
146
+ @tasks << primary
147
+ task 'Lunch/Break', 1.hour+21.minutes
148
+ task 'Task1', 1.hour+4.minutes
149
+ task 'Task2', 58.minutes
150
+ task 'Another Task', 5.minutes
151
+ task 'Task3', 1.day+17.hours+32.minutes
152
+ end
153
+
154
+ it "uses Project.all with data to generate output" do
155
+ populate_with_data
156
+ @pratt.expects(:template=).with("proportions")
157
+ @pratt.expects(:project?).returns false
158
+ @pratt.expects(:process_template!)
159
+ @pratt.proportions
160
+ @pratt.instance_variable_get("@primary").should eql(20.0)
161
+ @pratt.instance_variable_get("@off_total").should eql(1.35)
162
+ @pratt.instance_variable_get("@rest_total").should eql(43.65)
163
+ @pratt.instance_variable_get("@projects").should eql(Project.all)
164
+ @pratt.instance_variable_get("@scaled_total").should eql(63.65)
165
+ end
166
+
167
+ it "uses defined project with data to generate output" do
168
+ populate_with_data
169
+ @pratt.expects(:template=).with("proportions")
170
+ @pratt.expects(:project?).returns true
171
+ @pratt.project = Project.named('Task1')
172
+ @pratt.expects(:process_template!)
173
+ @pratt.proportions
174
+ @pratt.instance_variable_get("@primary").should eql(64/60.0)
175
+ @pratt.instance_variable_get("@off_total").should eql(0.0)
176
+ @pratt.instance_variable_get("@rest_total").should eql(0.0)
177
+ @pratt.instance_variable_get("@projects").should eql([@pratt.project])
178
+ @pratt.instance_variable_get("@scaled_total").should eql(64/60.0)
179
+ end
180
+
181
+ it "uses Project.all with no data to generate output" do
182
+ @pratt.expects(:template=).with("proportions")
183
+ @pratt.expects(:project?).returns false
184
+ Project.expects(:all).returns []
185
+ @pratt.expects(:process_template!).never
186
+ $stdout.expects(:puts).with "No data to report"
187
+ @pratt.proportions
188
+ end
189
+
190
+ it "uses defined project with no with data to generate output" do
191
+ @pratt.expects(:template=).with("proportions")
192
+ @pratt.expects(:project?).returns true
193
+ @pratt.project = Project.new
194
+ @pratt.project.expects(:time_spent).twice.returns 0.0
195
+ @pratt.expects(:process_template!).never
196
+ $stdout.expects(:puts).with "No data to report"
197
+ @pratt.proportions
198
+ @pratt.instance_variable_get("@primary").should eql(0.0)
199
+ @pratt.instance_variable_get("@off_total").should eql(0.0)
200
+ @pratt.instance_variable_get("@rest_total").should eql(0.0)
201
+ @pratt.instance_variable_get("@projects").should eql([@pratt.project])
202
+ @pratt.instance_variable_get("@scaled_total").should eql(0.0)
203
+ end
204
+ end
205
+ end
@@ -0,0 +1,33 @@
1
+ module SeedData
2
+ def load_seed_data
3
+ Customer.delete_all
4
+ customer = Customer.create(
5
+ :name => 'Scott Noel-Hemming',
6
+ :company_name => 'Frogstarr78 Software',
7
+ :address => '312 NW 7th',
8
+ :phone => '509.730.5401',
9
+ :zip => '97862'
10
+ )
11
+
12
+ Project.delete_all
13
+ Project.create(
14
+ [
15
+ {
16
+ :name => 'Refactor',
17
+ :weight => 1,
18
+ :customer => customer
19
+ },
20
+ {
21
+ :name => 'Lunch/Break',
22
+ :weight => 0,
23
+ :customer => customer
24
+ },
25
+ {
26
+ :name => 'Other',
27
+ :weight => -1,
28
+ :customer => customer
29
+ }
30
+ ]
31
+ )
32
+ end
33
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,24 @@
1
+ # This file is copied to ~/spec when you run 'ruby script/generate rspec'
2
+ # from the project root directory.
3
+ require 'rubygems'
4
+ require 'spec'
5
+ require 'mocha'
6
+ require 'lib/pratt'
7
+ require 'ruby-debug'
8
+ require 'seed_data'
9
+
10
+ Spec::Runner.configure do |config|
11
+ # config.mock_with :rspec
12
+ config.mock_with :mocha
13
+
14
+ Pratt.connect! 'test'
15
+ end
16
+
17
+ shared_examples_for "Time spent on a project" do
18
+ end
19
+
20
+ shared_examples_for "being a billable item" do
21
+ it "responds to amount" do
22
+ subject.class.new.should respond_to(:amount)
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+ require 'pratt'
3
+
4
+ describe String do
5
+ it { subject.should respond_to(:colorize) }
6
+ it { subject.should respond_to(:or) }
7
+ it { subject.should respond_to(:with_label) }
8
+
9
+ it "doesn't process alternate format when Pratt.color? == false" do
10
+ Pratt.color = false
11
+ "abc".or("xyz").should eql("abc")
12
+ end
13
+
14
+ it "processes alternate format when Pratt.color? == true" do
15
+ Pratt.color = true
16
+ "abc".or("xyz").should eql("xyz")
17
+ end
18
+
19
+ it "doesn't colorize when Pratt.color? == false" do
20
+ Pratt.color = false
21
+ "abc".blue.should eql("abc")
22
+ end
23
+
24
+ it "colorizes when Pratt.color? == true" do
25
+ Pratt.color = true
26
+ "abc".blue.should eql("\e[34mabc\e[0m")
27
+ end
28
+
29
+ it "handles with_label as expected" do
30
+ Project.expects(:longest_project_name).returns 11
31
+ "abc".with_label("label").should eql(" label abc")
32
+ end
33
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ describe Whence do
4
+
5
+ context "scopes" do
6
+ it "last_unended should return nil if there aren't any unended" do
7
+ Whence.expects(:first).with(:conditions => "end_at IS NULL", :order => "start_at DESC")
8
+ Whence.last_unended
9
+ end
10
+ end
11
+
12
+ context "instances" do
13
+ before :each do
14
+ @whence = Whence.new
15
+ end
16
+
17
+ it "parse a string argument to stop!" do
18
+ when_to = 'yesterday'
19
+ when_to = '2009-10-06 13:48:58'
20
+ expectation = Chronic.parse when_to
21
+
22
+ @whence.expects(:save!)
23
+ @whence.expects(:reload)
24
+ # don't work I'm not sure why
25
+ # @whence.expects(:end_at).with expectation
26
+ # Chronic.expects(:parse).with when_to
27
+
28
+ @whence.stop! when_to
29
+ @whence.end_at.should == expectation
30
+ end
31
+
32
+ it "doesn't parse a non-string thing on stop!" do
33
+ when_to = Chronic.parse 'last week'
34
+ Chronic.expects(:parse).never
35
+ @whence.expects(:save!)
36
+ @whence.expects(:reload)
37
+ @whence.stop! when_to
38
+ @whence.end_at.should == when_to
39
+ end
40
+
41
+ it "should change! to project correctly" do
42
+ project_name = 'proj'
43
+ @whence.expects(:save!)
44
+ @whence.expects(:reload)
45
+ @whence.change! project_name
46
+ @whence.project.name.should == project_name
47
+ end
48
+
49
+ it "should have a special output for start_at.to_s" do
50
+ @whence.start_at = Time.parse('Wed Oct 7 10:57:21 PDT 2009')
51
+ @whence.start_at.to_s.should eql('Wed 07 Oct 2009 10:57:21')
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,87 @@
1
+ # -*- ruby -*-
2
+
3
+ namespace :pratt do
4
+
5
+ task :establish_connection do
6
+ Pratt.connect!( ENV['PRATT_ENV'] || 'development' )
7
+ Pratt.root 'models', '*.rb' do |model|
8
+ require model
9
+ end
10
+ end
11
+
12
+ desc "DB Quick access"
13
+ namespace :db do
14
+
15
+ desc "Show App detail."
16
+ task :app => :establish_connection do
17
+ puts App.last.inspect
18
+ end
19
+
20
+ namespace :schema do
21
+ desc "Run schema file"
22
+ task :run, :file, :needs => :establish_connection do |t, args|
23
+ puts args.inspect
24
+ puts args.file.nil?
25
+ puts args.file.empty?
26
+ raise "Missing required file argument" if args.file.nil? or ( not args.file.nil? and args.file.empty? )
27
+ schema_change = File.open( args.file ).read
28
+
29
+ ActiveRecord::Schema.define do
30
+ ActiveRecord::Base.transaction do
31
+ begin
32
+ eval schema_change
33
+ rescue Exception => e
34
+ puts "There was an error:
35
+ #{e.inspect}.
36
+ Rolling back!"
37
+ raise ActiveRecord::Rollback
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ namespace :generate do
46
+ desc "Genarate model"
47
+ task :model do
48
+ raise "Missing required klass parameter" unless ENV.include? 'klass'
49
+ klass = ENV['klass'].downcase.singularize
50
+ outfile = File.join(Pratt.root('models'), "#{klass}.rb")
51
+ template = ''
52
+ Pratt.root('templates', 'model.eruby') {|model_gen| template = File.read(model_gen) }
53
+
54
+ eruby = Erubis::Eruby.new(template)
55
+ unless File.exists? outfile
56
+ File.open(outfile, 'w') {|file| file.write eruby.result(:klass => klass) }
57
+ else
58
+ puts "Model '#{klass}' already exists"
59
+ end
60
+
61
+ Rake::Task["generate:spec"].execute
62
+ end
63
+
64
+ desc "Generate spec test"
65
+ task :spec do
66
+ klass = ENV['klass'].downcase.singularize
67
+ raise "Missing required klass parameter" unless ENV.include? 'klass'
68
+
69
+ outpath = File.join(Pratt.root('spec'), "#{klass}_spec.rb")
70
+ inpath = File.join(Pratt.root('templates'), "spec.eruby")
71
+
72
+ if File.exists? outpath
73
+ puts "Spec '#{klass}' already exists"
74
+ else
75
+ File.open outpath, 'w' do |outfile|
76
+ File.open inpath do |infile|
77
+ eruby = Erubis::Eruby.new( infile.read )
78
+ outfile.write eruby.result( :klass => klass )
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ end
86
+
87
+ # vim: syntax=Ruby