beggar 0.0.5.alpha → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -1
- data/Gemfile.lock +14 -36
- data/LICENSE +2 -2
- data/README.md +33 -6
- data/beggar.gemspec +2 -2
- data/bin/beggar +3 -2
- data/lib/beggar/base.rb +25 -8
- data/lib/beggar/basecamp.rb +47 -0
- data/lib/beggar/cli.rb +35 -9
- data/lib/beggar/current_month.rb +32 -7
- data/lib/beggar/version.rb +2 -1
- data/lib/beggar.rb +5 -5
- data/spec/base_spec.rb +63 -12
- data/spec/basecamp_spec.rb +69 -0
- data/spec/cli_spec.rb +48 -0
- data/spec/current_month_spec.rb +12 -11
- data/spec/fixtures/beggar +4 -0
- metadata +18 -19
- data/lib/beggar/hours.rb +0 -26
- data/lib/beggar/salary.rb +0 -25
- data/spec/hours_spec.rb +0 -21
- data/spec/salary_spec.rb +0 -19
- data/spec/spec_helper.rb +0 -1
data/.rspec
CHANGED
@@ -1 +1 @@
|
|
1
|
-
--color
|
1
|
+
--color -f d
|
data/Gemfile.lock
CHANGED
@@ -1,52 +1,30 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
beggar (0.0.
|
5
|
-
|
4
|
+
beggar (0.0.5.alpha)
|
5
|
+
httparty
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activemodel (3.1.3)
|
11
|
-
activesupport (= 3.1.3)
|
12
|
-
builder (~> 3.0.0)
|
13
|
-
i18n (~> 0.6)
|
14
|
-
activeresource (3.1.3)
|
15
|
-
activemodel (= 3.1.3)
|
16
|
-
activesupport (= 3.1.3)
|
17
|
-
activesupport (3.1.3)
|
18
|
-
multi_json (~> 1.0)
|
19
|
-
addressable (2.2.6)
|
20
|
-
basecamp (0.0.7)
|
21
|
-
activeresource (>= 2.3.0)
|
22
|
-
oauth2
|
23
|
-
xml-simple
|
24
|
-
builder (3.0.0)
|
25
10
|
diff-lcs (1.1.3)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
rack (>= 1.1.0, < 2)
|
30
|
-
i18n (0.6.0)
|
11
|
+
httparty (0.8.1)
|
12
|
+
multi_json
|
13
|
+
multi_xml
|
31
14
|
multi_json (1.0.4)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
rspec (2.
|
38
|
-
|
39
|
-
rspec-expectations (~> 2.7.0)
|
40
|
-
rspec-mocks (~> 2.7.0)
|
41
|
-
rspec-core (2.7.1)
|
42
|
-
rspec-expectations (2.7.0)
|
15
|
+
multi_xml (0.4.1)
|
16
|
+
rspec (2.8.0)
|
17
|
+
rspec-core (~> 2.8.0)
|
18
|
+
rspec-expectations (~> 2.8.0)
|
19
|
+
rspec-mocks (~> 2.8.0)
|
20
|
+
rspec-core (2.8.0)
|
21
|
+
rspec-expectations (2.8.0)
|
43
22
|
diff-lcs (~> 1.1.2)
|
44
|
-
rspec-mocks (2.
|
45
|
-
xml-simple (1.1.1)
|
23
|
+
rspec-mocks (2.8.0)
|
46
24
|
|
47
25
|
PLATFORMS
|
48
26
|
ruby
|
49
27
|
|
50
28
|
DEPENDENCIES
|
51
29
|
beggar!
|
52
|
-
rspec
|
30
|
+
rspec (>= 2.7.0)
|
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2012 Bartłomiej Kozal
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
a copy of this software and associated documentation files (the
|
@@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
17
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
18
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
19
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,12 +1,39 @@
|
|
1
1
|
# Beggar [![Build Status](https://secure.travis-ci.org/bkzl/beggar.png)](http://travis-ci.org/bkzl/beggar)
|
2
2
|
|
3
|
-
|
3
|
+
## Description
|
4
4
|
|
5
|
-
|
6
|
-
TODO
|
5
|
+
Beggar is a tool for generating time reports from your Basecamp account
|
7
6
|
|
8
|
-
|
9
|
-
|
7
|
+
Example output:
|
8
|
+
|
9
|
+
78% || 140.0h, -12.0h || 5320.0 zł, -456.0 zł
|
10
|
+
|
11
|
+
where
|
12
|
+
|
13
|
+
78% - working days progress in current month
|
14
|
+
140.0h, -12.0h - worked hours ratio
|
15
|
+
5320.0 zł, -456.0 zł - salary ratio
|
16
|
+
|
17
|
+
### Installation
|
18
|
+
|
19
|
+
Install it like any ruby gem
|
20
|
+
|
21
|
+
gem install beggar
|
22
|
+
|
23
|
+
and run by
|
24
|
+
|
25
|
+
beggar
|
26
|
+
|
27
|
+
### Configuration
|
28
|
+
|
29
|
+
Before first use, beggar will try to create configuration file in your home directory (~/.beggar)
|
30
|
+
|
31
|
+
Example config:
|
32
|
+
|
33
|
+
company: pear
|
34
|
+
token: abc123
|
35
|
+
rate: 50.0
|
10
36
|
|
11
37
|
## Changelog
|
12
|
-
|
38
|
+
v1.0.0 - first stable release
|
39
|
+
|
data/beggar.gemspec
CHANGED
@@ -20,6 +20,6 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
22
|
# specify any dependencies here; for example:
|
23
|
-
s.add_development_dependency "rspec"
|
24
|
-
s.
|
23
|
+
s.add_development_dependency "rspec", ">= 2.7.0"
|
24
|
+
s.add_dependency "httparty"
|
25
25
|
end
|
data/bin/beggar
CHANGED
data/lib/beggar/base.rb
CHANGED
@@ -1,20 +1,37 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
-
|
3
2
|
module Beggar
|
4
3
|
class Base
|
5
|
-
|
6
|
-
|
4
|
+
attr_accessor :basecamp
|
5
|
+
|
6
|
+
def initialize(basecamp)
|
7
|
+
@basecamp = basecamp
|
8
|
+
end
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
+
def progress
|
11
|
+
"#{CurrentMonth.days_progression}%"
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
13
|
-
|
14
|
+
def worked_hours
|
15
|
+
"#{basecamp.worked_hours}h, #{ratio(basecamp.hours_ratio)}h"
|
16
|
+
end
|
17
|
+
|
18
|
+
def salary
|
19
|
+
"#{as_money(basecamp.worked_hours)} zł, #{ratio(as_money(basecamp.hours_ratio))} zł"
|
14
20
|
end
|
15
21
|
|
16
22
|
def summary
|
17
|
-
[
|
23
|
+
[progress, worked_hours, salary].join(' || ')
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def as_money(hours)
|
29
|
+
hours * basecamp.config['rate']
|
30
|
+
end
|
31
|
+
|
32
|
+
def ratio(number)
|
33
|
+
(number > 0) ? "-#{number}" : "+#{number.abs}"
|
18
34
|
end
|
19
35
|
end
|
20
36
|
end
|
37
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Beggar
|
2
|
+
class Basecamp
|
3
|
+
include HTTParty
|
4
|
+
|
5
|
+
attr_accessor :config
|
6
|
+
|
7
|
+
def initialize(config)
|
8
|
+
@config = config
|
9
|
+
|
10
|
+
self.class.base_uri("https://#{config['company']}.basecamphq.com")
|
11
|
+
self.class.basic_auth(config['token'], 'X')
|
12
|
+
end
|
13
|
+
|
14
|
+
def time_report(options = {})
|
15
|
+
options.merge!( subject_id: current_user )
|
16
|
+
get(%(/time_entries/report.xml#{params(options)}))
|
17
|
+
end
|
18
|
+
|
19
|
+
def current_user
|
20
|
+
@current_user ||= get('/me.xml')['person']['id']
|
21
|
+
end
|
22
|
+
|
23
|
+
def current_month
|
24
|
+
@current_month ||= time_report(from: CurrentMonth.first_day, to: CurrentMonth.today)
|
25
|
+
end
|
26
|
+
|
27
|
+
def worked_hours
|
28
|
+
current_month['time_entries'].map do |entry|
|
29
|
+
entry['hours']
|
30
|
+
end.inject(:+)
|
31
|
+
end
|
32
|
+
|
33
|
+
def hours_ratio
|
34
|
+
CurrentMonth.weekday_hours_until_today - worked_hours
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def get(path)
|
40
|
+
self.class.get(path)
|
41
|
+
end
|
42
|
+
|
43
|
+
def params(options)
|
44
|
+
'?' + options.map { |name, value| "#{name}=#{value}" }.join('&')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/beggar/cli.rb
CHANGED
@@ -1,17 +1,43 @@
|
|
1
1
|
module Beggar
|
2
2
|
class CLI
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
class << self
|
4
|
+
def run
|
5
|
+
begin
|
6
|
+
$stdout.puts Base.new(Basecamp.new(load_config)).summary
|
7
|
+
rescue Errno::ENOENT
|
8
|
+
create_config
|
9
|
+
$stdout.puts "New config has been created in ~/.beggar"
|
10
|
+
$stdout.puts "Please fill it with proper data."
|
11
|
+
rescue URI::InvalidURIError
|
12
|
+
$stdout.puts "Ensure that your config file is proper formatted!"
|
13
|
+
end
|
14
|
+
exit 0
|
15
|
+
end
|
6
16
|
|
7
|
-
|
8
|
-
|
9
|
-
|
17
|
+
private
|
18
|
+
|
19
|
+
def load_config
|
20
|
+
YAML.load_file(config)
|
21
|
+
end
|
10
22
|
|
11
|
-
|
23
|
+
def create_config
|
24
|
+
File.open(config, "w") do |output|
|
25
|
+
YAML.dump(defaults, output)
|
26
|
+
end
|
27
|
+
end
|
12
28
|
|
13
|
-
|
14
|
-
|
29
|
+
def defaults
|
30
|
+
{
|
31
|
+
"company" => "___",
|
32
|
+
"token" => "___",
|
33
|
+
"rate" => "___"
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def config
|
38
|
+
"#{Dir.home}/.beggar"
|
39
|
+
end
|
15
40
|
end
|
16
41
|
end
|
17
42
|
end
|
43
|
+
|
data/lib/beggar/current_month.rb
CHANGED
@@ -1,25 +1,50 @@
|
|
1
1
|
module Beggar
|
2
2
|
class CurrentMonth
|
3
3
|
class << self
|
4
|
+
def weekdays
|
5
|
+
weekdays_until(last_day)
|
6
|
+
end
|
7
|
+
|
8
|
+
def weekdays_until_today
|
9
|
+
weekdays_until(today)
|
10
|
+
end
|
11
|
+
|
12
|
+
def weekday_hours
|
13
|
+
weekdays * 8.0
|
14
|
+
end
|
15
|
+
|
16
|
+
def weekday_hours_until_today
|
17
|
+
weekdays_until_today * 8.0
|
18
|
+
end
|
19
|
+
|
20
|
+
def days_progression
|
21
|
+
(weekdays_until_today * 100.0 / weekdays).round
|
22
|
+
end
|
23
|
+
|
24
|
+
def weekdays_until(date)
|
25
|
+
(first_day..date).reject { |d| [0, 6].include? d.wday }.length
|
26
|
+
end
|
27
|
+
|
4
28
|
def first_day
|
5
|
-
Date.new(
|
29
|
+
Date.new(year, month, 1)
|
6
30
|
end
|
7
31
|
|
8
32
|
def last_day
|
9
33
|
first_day.next_month - 1
|
10
34
|
end
|
11
35
|
|
12
|
-
def
|
13
|
-
|
36
|
+
def year
|
37
|
+
today.year
|
14
38
|
end
|
15
39
|
|
16
|
-
def
|
17
|
-
|
40
|
+
def month
|
41
|
+
today.month
|
18
42
|
end
|
19
43
|
|
20
|
-
def
|
21
|
-
|
44
|
+
def today
|
45
|
+
Date.today
|
22
46
|
end
|
23
47
|
end
|
24
48
|
end
|
25
49
|
end
|
50
|
+
|
data/lib/beggar/version.rb
CHANGED
data/lib/beggar.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require 'basecamp'
|
2
1
|
require 'yaml'
|
3
|
-
require '
|
4
|
-
|
2
|
+
require 'httparty'
|
3
|
+
|
5
4
|
require 'beggar/base'
|
5
|
+
require 'beggar/basecamp'
|
6
|
+
require 'beggar/cli'
|
6
7
|
require 'beggar/current_month'
|
7
|
-
|
8
|
-
require 'beggar/salary'
|
8
|
+
|
data/spec/base_spec.rb
CHANGED
@@ -1,19 +1,70 @@
|
|
1
|
-
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'beggar'
|
2
3
|
|
3
4
|
describe Beggar::Base do
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
let(:basecamp) { double('Basecamp', config: { 'rate' => 50.0 }) }
|
6
|
+
let(:base) { Beggar::Base.new(basecamp) }
|
7
|
+
|
8
|
+
describe 'displaying weekdays progression as a percents' do
|
9
|
+
it 'returns 62% on 17th February 2012' do
|
10
|
+
Date.stub(today: Date.new(2012, 2, 17))
|
11
|
+
base.progress.should == "62%"
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'returns 9% on 2nd December 2011' do
|
15
|
+
Date.stub(today: Date.new(2011, 12, 2))
|
16
|
+
base.progress.should == "9%"
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'returns 100% on 30th November 1988' do
|
20
|
+
Date.stub(today: Date.new(1988, 11, 30))
|
21
|
+
base.progress.should == "100%"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when 4 days have been free in February 2012 and rate is equal $50' do
|
26
|
+
before do
|
27
|
+
basecamp.stub(worked_hours: 136.0, hours_ratio: 32.0)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'returns "136.0h, -32.0h"' do
|
31
|
+
base.worked_hours.should == "136.0h, -32.0h"
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns "6800.0 zł, -1600.0 zł"' do
|
35
|
+
base.salary.should == "6800.0 zł, -1600.0 zł"
|
36
|
+
end
|
10
37
|
end
|
11
38
|
|
12
|
-
|
13
|
-
|
14
|
-
|
39
|
+
context 'when 1 day has been worked extra in February 2012 and rate is equal $50' do
|
40
|
+
before do
|
41
|
+
basecamp.stub(worked_hours: 176.0, hours_ratio: -8.0)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns "176.0h, +8.0h"' do
|
45
|
+
base.worked_hours.should == "176.0h, +8.0h"
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'returns "8800.0 zł, +$400.0 zł"' do
|
49
|
+
base.salary.should == "8800.0 zł, +400.0 zł"
|
50
|
+
end
|
15
51
|
end
|
16
52
|
|
17
|
-
|
18
|
-
|
53
|
+
describe 'private methods' do
|
54
|
+
it 'returns formatted ratio' do
|
55
|
+
base.send(:ratio, 1.0).should == "-1.0"
|
56
|
+
base.send(:ratio, -3.0).should == "+3.0"
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'returns hours multiplied by rate' do
|
60
|
+
basecamp.stub(:config).and_return({ 'rate' => 50.0 })
|
61
|
+
base.send(:as_money, 5.0).should == 250.0
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'returns summary' do
|
66
|
+
base.stub(progress: "78%", worked_hours: "140.0h, -12.0h", salary: "5320.0 zł, -456.0 zł")
|
67
|
+
base.summary.should == "78% || 140.0h, -12.0h || 5320.0 zł, -456.0 zł"
|
68
|
+
end
|
19
69
|
end
|
70
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'beggar'
|
2
|
+
|
3
|
+
describe Beggar::Basecamp do
|
4
|
+
let(:config) { YAML.load_file(File.expand_path('../fixtures/beggar', __FILE__)) }
|
5
|
+
let(:basecamp) { Beggar::Basecamp.new(config) }
|
6
|
+
|
7
|
+
before do
|
8
|
+
Date.stub(today: Date.new(2012, 02, 17))
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'constructor' do
|
12
|
+
after do
|
13
|
+
Beggar::Basecamp.new(config)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'set base uri' do
|
17
|
+
Beggar::Basecamp.should_receive(:base_uri).with('https://pear.basecamphq.com')
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'set basic auth credentials' do
|
21
|
+
Beggar::Basecamp.should_receive(:basic_auth).with('abc123', 'X')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'returns user id' do
|
26
|
+
response = { 'person' => { 'id' => 1 }}
|
27
|
+
basecamp.class.should_receive(:get).with('/me.xml').and_return(response)
|
28
|
+
basecamp.current_user.should == 1
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'returns time report for current user' do
|
32
|
+
basecamp.stub(current_user: 1)
|
33
|
+
basecamp.class.should_receive(:get).with('/time_entries/report.xml?subject_id=1')
|
34
|
+
basecamp.time_report
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns time report for current month' do
|
38
|
+
Date.stub(today: Date.new(2012, 02, 17))
|
39
|
+
basecamp.stub(current_user: 1)
|
40
|
+
basecamp.class.should_receive(:get).with('/time_entries/report.xml?from=2012-02-01&to=2012-02-17&subject_id=1')
|
41
|
+
basecamp.current_month
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'returns worked hours' do
|
45
|
+
response = { "time_entries" =>
|
46
|
+
[{ "hours" => 8.0 }, { "hours" => 6.0 }, { "hours" => 8.0 }]
|
47
|
+
}
|
48
|
+
basecamp.stub(current_month: response)
|
49
|
+
basecamp.worked_hours.should == 22.0
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'returns hours ratio with minus when working hours > weekdays hours' do
|
53
|
+
basecamp.stub(worked_hours: 106.0)
|
54
|
+
basecamp.hours_ratio.should == -2.0
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'returns hours ratio with plus when worked hours < weekdays hours' do
|
58
|
+
basecamp.stub(worked_hours: 96.0)
|
59
|
+
basecamp.hours_ratio.should == 8.0
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'private methods' do
|
63
|
+
it 'parses options to path params' do
|
64
|
+
basecamp.send(:params, { name: 'bob'}).should == '?name=bob'
|
65
|
+
basecamp.send(:params, { name: 'bob', surname: 'example'}).should == '?name=bob&surname=example'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'beggar'
|
2
|
+
|
3
|
+
describe Beggar::CLI do
|
4
|
+
let(:config) { "#{Dir.home}/.beggar" }
|
5
|
+
|
6
|
+
before do
|
7
|
+
$stdout.stub(:puts)
|
8
|
+
Beggar::Basecamp.stub(new: double('Basecamp'))
|
9
|
+
Beggar::Base.stub_chain(:new, :summary)
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
-> { Beggar::CLI.run }.should raise_error { SystemExit }
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when config file exists' do
|
17
|
+
it "loads it before running" do
|
18
|
+
YAML.should_receive(:load_file).with(config).and_return(double('configuration'))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when config file not exists' do
|
23
|
+
let(:default_config) {
|
24
|
+
{
|
25
|
+
"company" => "___",
|
26
|
+
"token" => "___",
|
27
|
+
"rate" => "___"
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
before do
|
32
|
+
YAML.should_receive(:load_file).with(config) { raise Errno::ENOENT }
|
33
|
+
end
|
34
|
+
it "creates config with default settings" do
|
35
|
+
output = double('output')
|
36
|
+
File.should_receive(:open).with(config, "w").and_yield(output)
|
37
|
+
YAML.should_receive(:dump).with(default_config, output)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'displays notification' do
|
41
|
+
$stdout.unstub(:puts)
|
42
|
+
Beggar::CLI.stub(:create_config)
|
43
|
+
$stdout.should_receive(:puts).with("New config has been created in ~/.beggar")
|
44
|
+
$stdout.should_receive(:puts).with("Please fill it with proper data.")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
data/spec/current_month_spec.rb
CHANGED
@@ -1,18 +1,19 @@
|
|
1
|
-
require '
|
1
|
+
require 'beggar'
|
2
2
|
|
3
|
+
# FIXME add missing specs
|
3
4
|
describe Beggar::CurrentMonth do
|
4
|
-
|
5
|
-
before { Date.stub(today: Date.new(2011, 12, 24)) }
|
5
|
+
let(:current_month) { Beggar::CurrentMonth }
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
before do
|
8
|
+
Date.stub(today: Date.new(2012, 2, 17))
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
+
it 'returns weekdays in hours' do
|
12
|
+
current_month.weekday_hours.should == 168.0
|
13
|
+
end
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
it { subject.working_days(first_day..last_day).should == 22 }
|
15
|
-
its(:working_days_up_today) { should == 17 }
|
16
|
-
its(:to_s) { should == '77%' }
|
15
|
+
it 'returns weekdays in hours until today' do
|
16
|
+
current_month.weekday_hours_until_today.should == 104.0
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
metadata
CHANGED
@@ -1,30 +1,30 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beggar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Bartlomiej Kozal
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-02-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70213892896680 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 2.7.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70213892896680
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
27
|
-
requirement: &
|
26
|
+
name: httparty
|
27
|
+
requirement: &70213892895980 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70213892895980
|
36
36
|
description: Tool for generating time reports from Basecamp. You can specify rate
|
37
37
|
for each project and get value of your month salary.
|
38
38
|
email:
|
@@ -54,16 +54,15 @@ files:
|
|
54
54
|
- bin/beggar
|
55
55
|
- lib/beggar.rb
|
56
56
|
- lib/beggar/base.rb
|
57
|
+
- lib/beggar/basecamp.rb
|
57
58
|
- lib/beggar/cli.rb
|
58
59
|
- lib/beggar/current_month.rb
|
59
|
-
- lib/beggar/hours.rb
|
60
|
-
- lib/beggar/salary.rb
|
61
60
|
- lib/beggar/version.rb
|
62
61
|
- spec/base_spec.rb
|
62
|
+
- spec/basecamp_spec.rb
|
63
|
+
- spec/cli_spec.rb
|
63
64
|
- spec/current_month_spec.rb
|
64
|
-
- spec/
|
65
|
-
- spec/salary_spec.rb
|
66
|
-
- spec/spec_helper.rb
|
65
|
+
- spec/fixtures/beggar
|
67
66
|
homepage: https://github.com/bkzl/beggar
|
68
67
|
licenses: []
|
69
68
|
post_install_message:
|
@@ -79,9 +78,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
79
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
79
|
none: false
|
81
80
|
requirements:
|
82
|
-
- - ! '
|
81
|
+
- - ! '>='
|
83
82
|
- !ruby/object:Gem::Version
|
84
|
-
version:
|
83
|
+
version: '0'
|
85
84
|
requirements: []
|
86
85
|
rubyforge_project: beggar
|
87
86
|
rubygems_version: 1.8.11
|
@@ -90,7 +89,7 @@ specification_version: 3
|
|
90
89
|
summary: Tool for generating time reports from Basecamp
|
91
90
|
test_files:
|
92
91
|
- spec/base_spec.rb
|
92
|
+
- spec/basecamp_spec.rb
|
93
|
+
- spec/cli_spec.rb
|
93
94
|
- spec/current_month_spec.rb
|
94
|
-
- spec/
|
95
|
-
- spec/salary_spec.rb
|
96
|
-
- spec/spec_helper.rb
|
95
|
+
- spec/fixtures/beggar
|
data/lib/beggar/hours.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Beggar
|
4
|
-
class Hours
|
5
|
-
class << self
|
6
|
-
attr_accessor :project_id
|
7
|
-
|
8
|
-
def worked
|
9
|
-
params = { project_id: project_id, from: CurrentMonth.first_day, to: Date.today }
|
10
|
-
@@worked ||= Basecamp::TimeEntry.report(params).select { |te| te.person_id == Base.me.id }.map(&:hours).inject(&:+)
|
11
|
-
end
|
12
|
-
|
13
|
-
def max_up_today
|
14
|
-
CurrentMonth.working_days_up_today * 8
|
15
|
-
end
|
16
|
-
|
17
|
-
def difference
|
18
|
-
max_up_today - worked
|
19
|
-
end
|
20
|
-
|
21
|
-
def to_s
|
22
|
-
%[#{worked}h ± #{difference}h]
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
data/lib/beggar/salary.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Beggar
|
4
|
-
class Salary
|
5
|
-
class << self
|
6
|
-
attr_accessor :rate
|
7
|
-
|
8
|
-
def today
|
9
|
-
Hours.worked * rate
|
10
|
-
end
|
11
|
-
|
12
|
-
def max_up_today
|
13
|
-
Hours.max_up_today * rate
|
14
|
-
end
|
15
|
-
|
16
|
-
def difference
|
17
|
-
max_up_today - today
|
18
|
-
end
|
19
|
-
|
20
|
-
def to_s
|
21
|
-
%[#{today} PLN ± #{difference} PLN]
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/spec/hours_spec.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
describe 'Beggar::Hours' do
|
6
|
-
context 'user was working in current month 2 days (8h and 6h)' do
|
7
|
-
before do
|
8
|
-
time_entries = double(map: [8.0, 6.0])
|
9
|
-
api_response = double(select: time_entries)
|
10
|
-
Basecamp::TimeEntry.stub(report: api_response)
|
11
|
-
Beggar::CurrentMonth.stub(working_days_up_today: 2)
|
12
|
-
end
|
13
|
-
|
14
|
-
subject { Beggar::Hours }
|
15
|
-
|
16
|
-
its(:worked) { should == 14.0 }
|
17
|
-
its(:max_up_today) { should == 16.0 }
|
18
|
-
its(:difference) { should == 2.0 }
|
19
|
-
its(:to_s) { should == '14.0h ± 2.0h' }
|
20
|
-
end
|
21
|
-
end
|
data/spec/salary_spec.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
describe 'Beggar::Salary' do
|
6
|
-
context 'user was working 10h (max: 40h) in current month and his rate per h amount 100.0 PLN' do
|
7
|
-
before do
|
8
|
-
Beggar::Hours.stub(worked: 10, max_up_today: 40)
|
9
|
-
Beggar::Salary.stub(rate: 100.0)
|
10
|
-
end
|
11
|
-
|
12
|
-
subject { Beggar::Salary }
|
13
|
-
|
14
|
-
its(:today) { should == 1000.0 }
|
15
|
-
its(:max_up_today) { should == 4000.0 }
|
16
|
-
its(:difference) { should == 3000.0 }
|
17
|
-
its(:to_s) { should == '1000.0 PLN ± 3000.0 PLN' }
|
18
|
-
end
|
19
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'beggar'
|