tracco 0.0.14 → 0.0.15
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/CHANGELOG +16 -0
- data/Gemfile.lock +1 -1
- data/README.md +4 -4
- data/lib/patches/trello/card.rb +3 -2
- data/lib/patches/trello/member.rb +4 -2
- data/lib/tasks/tasks.rake +2 -2
- data/lib/tracco/google_docs_exporter.rb +50 -47
- data/lib/tracco/models/effort.rb +40 -0
- data/lib/tracco/models/estimate.rb +29 -0
- data/lib/tracco/models/member.rb +64 -0
- data/lib/tracco/models/tracked_card.rb +148 -0
- data/lib/tracco/tracking/base.rb +68 -65
- data/lib/tracco/tracking/card_done_tracking.rb +9 -6
- data/lib/tracco/tracking/effort_tracking.rb +32 -29
- data/lib/tracco/tracking/estimate_tracking.rb +16 -13
- data/lib/tracco/tracking/factory.rb +18 -16
- data/lib/tracco/tracking/invalid_tracking.rb +15 -13
- data/lib/tracco/trello_tracker.rb +34 -30
- data/lib/tracco/version.rb +2 -2
- data/lib/tracco.rb +4 -4
- data/spec/factories/effort_factory.rb +2 -2
- data/spec/factories/estimate_factory.rb +1 -1
- data/spec/factories/tracked_card_factory.rb +1 -1
- data/spec/integration/trello_tracker_spec.rb +49 -47
- data/spec/models/effort_spec.rb +61 -0
- data/spec/models/estimate_spec.rb +40 -0
- data/spec/models/member_spec.rb +83 -0
- data/spec/models/tracked_card_spec.rb +467 -0
- data/spec/support/spec_helper_methods.rb +7 -1
- data/spec/tracking/card_done_tracking_spec.rb +11 -9
- data/spec/tracking/effort_tracking_spec.rb +77 -75
- data/spec/tracking/estimate_tracking_spec.rb +30 -28
- data/spec/tracking/factory_spec.rb +39 -0
- data/spec/trello_tracker_spec.rb +20 -18
- data/tracco.gemspec +1 -1
- metadata +12 -12
- data/lib/tracco/effort.rb +0 -37
- data/lib/tracco/estimate.rb +0 -26
- data/lib/tracco/member.rb +0 -61
- data/lib/tracco/tracked_card.rb +0 -145
- data/spec/effort_spec.rb +0 -59
- data/spec/estimate_spec.rb +0 -38
- data/spec/member_spec.rb +0 -81
- data/spec/tracked_card_spec.rb +0 -465
- data/spec/tracking_factory_spec.rb +0 -42
data/lib/tracco/tracked_card.rb
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
class TrackedCard
|
2
|
-
include Mongoid::Document
|
3
|
-
include Mongoid::Timestamps
|
4
|
-
extend MongoidHelper
|
5
|
-
|
6
|
-
field :name
|
7
|
-
field :description
|
8
|
-
field :short_id, type: Integer
|
9
|
-
field :trello_id
|
10
|
-
field :done, type: Boolean
|
11
|
-
field :due, type: Date
|
12
|
-
field :closed, type: Boolean
|
13
|
-
field :url
|
14
|
-
field :pos
|
15
|
-
|
16
|
-
embeds_many :estimates
|
17
|
-
embeds_many :efforts
|
18
|
-
|
19
|
-
validates_presence_of :name, :short_id, :trello_id
|
20
|
-
validates_numericality_of :short_id
|
21
|
-
|
22
|
-
scope :with_effort_spent_by, ->(username){ where("efforts.members.username" => username) }
|
23
|
-
|
24
|
-
def self.find_by_trello_id(trello_id)
|
25
|
-
without_mongo_raising_errors do
|
26
|
-
find_by(trello_id: trello_id)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.update_or_create_with(trello_card)
|
31
|
-
tracked_card = find_or_create_by(trello_id: trello_card.id)
|
32
|
-
trello_card.attributes.delete(:id)
|
33
|
-
tracked_card_attributes = trello_card.attributes.merge(done: trello_card.in_done_column?)
|
34
|
-
updated_successfully = tracked_card.update_attributes(tracked_card_attributes)
|
35
|
-
return tracked_card if updated_successfully
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.all_tracked_cards(sorting_options = {})
|
39
|
-
cards = all.reject(&:no_tracking?)
|
40
|
-
cards.sort_by!(&sorting_options[:sort_by].to_sym) if sorting_options[:sort_by]
|
41
|
-
cards.reverse! if sorting_options[:order] == :desc
|
42
|
-
return cards
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.build_from(trello_card)
|
46
|
-
trello_card_id = trello_card.id
|
47
|
-
trello_card.attributes.delete(:id)
|
48
|
-
new(trello_card.attributes.merge(trello_id: trello_card_id))
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.efforts_between(search_options)
|
52
|
-
condition = {}
|
53
|
-
{'$gte' => :from_date, '$lte' => :to_date}.each do |selection, option_key|
|
54
|
-
condition[selection] = search_options[option_key] if search_options[option_key]
|
55
|
-
end
|
56
|
-
|
57
|
-
where("efforts.date" => condition)
|
58
|
-
end
|
59
|
-
|
60
|
-
def status
|
61
|
-
if done?
|
62
|
-
:done
|
63
|
-
elsif efforts.empty?
|
64
|
-
:todo
|
65
|
-
else
|
66
|
-
:in_progress
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def add(tracking)
|
71
|
-
tracking.add_to(self)
|
72
|
-
end
|
73
|
-
|
74
|
-
def add!(tracking)
|
75
|
-
add(tracking) && save!
|
76
|
-
end
|
77
|
-
|
78
|
-
def contains_effort?(effort)
|
79
|
-
efforts.unscoped.any? { |e| e.tracking_notification_id == effort.tracking_notification_id }
|
80
|
-
end
|
81
|
-
|
82
|
-
def contains_estimate?(estimate)
|
83
|
-
estimates.any? { |e| e.tracking_notification_id == estimate.tracking_notification_id }
|
84
|
-
end
|
85
|
-
|
86
|
-
def no_tracking?
|
87
|
-
first_activity_date.nil?
|
88
|
-
end
|
89
|
-
|
90
|
-
def first_activity_date
|
91
|
-
[working_start_date, first_estimate_date].compact.min
|
92
|
-
end
|
93
|
-
|
94
|
-
def working_start_date
|
95
|
-
efforts.sort_by(&:date).first.date if efforts.present?
|
96
|
-
end
|
97
|
-
|
98
|
-
def first_estimate_date
|
99
|
-
estimates.sort_by(&:date).first.date if estimates.present?
|
100
|
-
end
|
101
|
-
|
102
|
-
def last_estimate_date
|
103
|
-
estimates.sort_by(&:date).last.date if estimates.present?
|
104
|
-
end
|
105
|
-
|
106
|
-
def total_effort
|
107
|
-
efforts.map(&:amount).inject(0, &:+)
|
108
|
-
end
|
109
|
-
|
110
|
-
def members
|
111
|
-
efforts.map(&:members).flatten.uniq
|
112
|
-
end
|
113
|
-
|
114
|
-
def last_estimate_error
|
115
|
-
estimate_errors.last
|
116
|
-
end
|
117
|
-
|
118
|
-
def estimate_errors
|
119
|
-
return [] if estimates.empty? || efforts.empty?
|
120
|
-
|
121
|
-
estimate_errors = []
|
122
|
-
estimates.each do |each|
|
123
|
-
estimate_errors << (100 * ((total_effort - each.amount) / each.amount * 1.0)).round(2)
|
124
|
-
end
|
125
|
-
|
126
|
-
estimate_errors
|
127
|
-
end
|
128
|
-
|
129
|
-
def trello_notifications
|
130
|
-
# TODO select all efforts, even the muted ones?
|
131
|
-
notification_ids = efforts.map(&:tracking_notification_id) | estimates.map(&:tracking_notification_id)
|
132
|
-
notification_ids.map { |id| Trello::Notification.find(id) rescue nil }.compact.sort_by(&:date)
|
133
|
-
end
|
134
|
-
|
135
|
-
def to_s
|
136
|
-
"[#{name}]. Total effort: #{total_effort}h. Estimates #{estimates.map(&:to_s)}. Efforts: #{efforts.map(&:to_s)}"
|
137
|
-
end
|
138
|
-
|
139
|
-
def ==(other)
|
140
|
-
return true if other.equal?(self)
|
141
|
-
return false unless other.kind_of?(self.class)
|
142
|
-
trello_id == other.trello_id
|
143
|
-
end
|
144
|
-
|
145
|
-
end
|
data/spec/effort_spec.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'mongoid-rspec'
|
3
|
-
|
4
|
-
describe Effort do
|
5
|
-
|
6
|
-
it { should have_fields(:amount, :date, :muted, :tracking_notification_id) }
|
7
|
-
it { should be_embedded_in(:tracked_card) }
|
8
|
-
it { should embed_many(:members) }
|
9
|
-
|
10
|
-
describe "validation" do
|
11
|
-
it { should validate_presence_of(:amount) }
|
12
|
-
it { should validate_presence_of(:date) }
|
13
|
-
it { should validate_presence_of(:members) }
|
14
|
-
end
|
15
|
-
|
16
|
-
%w{piero tommaso tom ugo}.each do |username|
|
17
|
-
let(username.to_sym) { Member.new(username: username) }
|
18
|
-
end
|
19
|
-
|
20
|
-
describe "#amount_per_member" do
|
21
|
-
it "counts the amount spent per single member" do
|
22
|
-
effort = Effort.new(amount: 6, members: [piero, tommaso], date: Date.parse("2012-11-09"), )
|
23
|
-
effort.amount_per_member.should == 3
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe "equality" do
|
28
|
-
it "is equal to another effort with same amount, date and members" do
|
29
|
-
effort = Effort.new(amount: 3, date: Date.parse("2012-11-09"), members: [piero, tommaso])
|
30
|
-
same_effort = Effort.new(amount: 3, date: Date.parse("2012-11-09"), members: [piero, tommaso])
|
31
|
-
yet_same_effort = Effort.new(amount: 3, date: Date.parse("2012-11-09"), members: [tommaso, piero])
|
32
|
-
|
33
|
-
effort.should == same_effort
|
34
|
-
effort.should == yet_same_effort
|
35
|
-
end
|
36
|
-
|
37
|
-
it "is not equal when amount differs" do
|
38
|
-
effort = Effort.new(amount: 3, date: Date.today, members: [tom, ugo])
|
39
|
-
another_effort = Effort.new(amount: 1, date: Date.today, members: [tom, ugo])
|
40
|
-
|
41
|
-
effort.should_not == another_effort
|
42
|
-
end
|
43
|
-
|
44
|
-
it "is not equal when date differs" do
|
45
|
-
effort = Effort.new(amount: 3, date: Date.parse("2012-11-09"), members: [tom, ugo])
|
46
|
-
another_effort = Effort.new(amount: 3, date: Date.parse("2011-10-08"), members: [tom, ugo])
|
47
|
-
|
48
|
-
effort.should_not == another_effort
|
49
|
-
end
|
50
|
-
|
51
|
-
it "is not equal when members differ" do
|
52
|
-
effort = Effort.new(amount: 3, date: Date.today, members: [tom, ugo])
|
53
|
-
another_effort = Effort.new(amount: 3, date: Date.today, members: [piero, ugo])
|
54
|
-
|
55
|
-
effort.should_not == another_effort
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
end
|
data/spec/estimate_spec.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'mongoid-rspec'
|
3
|
-
|
4
|
-
describe Estimate do
|
5
|
-
|
6
|
-
it { should have_fields(:amount, :date) }
|
7
|
-
it { should be_embedded_in(:tracked_card) }
|
8
|
-
|
9
|
-
describe "validation" do
|
10
|
-
it { should validate_presence_of(:amount) }
|
11
|
-
it { should validate_presence_of(:date) }
|
12
|
-
end
|
13
|
-
|
14
|
-
describe "equality" do
|
15
|
-
|
16
|
-
it "is equal to another estimate with same amount and date" do
|
17
|
-
estimate = Estimate.new(amount: 3, date: Date.parse("2012-11-09"))
|
18
|
-
same_estimate = Estimate.new(amount: 3, date: Date.parse("2012-11-09"))
|
19
|
-
|
20
|
-
estimate.should == same_estimate
|
21
|
-
end
|
22
|
-
|
23
|
-
it "is not equal when amount differs" do
|
24
|
-
estimate = Estimate.new(amount: 3, date: Date.today)
|
25
|
-
another_estimate = Estimate.new(amount: 1, date: Date.today)
|
26
|
-
|
27
|
-
estimate.should_not == another_estimate
|
28
|
-
end
|
29
|
-
|
30
|
-
it "is not equal when date differs" do
|
31
|
-
estimate = Estimate.new(amount: 3, date: Date.parse("2012-11-09"))
|
32
|
-
another_estimate = Estimate.new(amount: 3, date: Date.parse("2011-10-08"))
|
33
|
-
|
34
|
-
estimate.should_not == another_estimate
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
data/spec/member_spec.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'mongoid-rspec'
|
3
|
-
|
4
|
-
describe Member do
|
5
|
-
|
6
|
-
it { should have_fields(:trello_id, :username, :full_name, :avatar_id, :bio, :url) }
|
7
|
-
it { should be_embedded_in(:effort) }
|
8
|
-
|
9
|
-
describe "validation" do
|
10
|
-
it { should validate_presence_of(:username) }
|
11
|
-
end
|
12
|
-
|
13
|
-
describe "equality" do
|
14
|
-
it "is equal to another member with the same username" do
|
15
|
-
member = Member.new(username: "piero")
|
16
|
-
same_member = Member.new(username: "piero")
|
17
|
-
different_member = Member.new(username: "tommaso")
|
18
|
-
|
19
|
-
member.should == same_member
|
20
|
-
member.should_not == different_member
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe ".build_from" do
|
25
|
-
it "builds a Member from a Trello Member" do
|
26
|
-
member = Member.build_from(Trello::Member.new("username" => "piero"))
|
27
|
-
|
28
|
-
member.username.should == "piero"
|
29
|
-
end
|
30
|
-
|
31
|
-
it "takes the Trello Member id and set it as trello_id" do
|
32
|
-
member = Member.build_from(Trello::Member.new("username" => "piero", "id" => "1234567abc"))
|
33
|
-
|
34
|
-
member.id.should_not == "1234567abc"
|
35
|
-
member.trello_id.should == "1234567abc"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
describe "#effort_spent" do
|
40
|
-
%w{piero tommaso}.each do |username|
|
41
|
-
let(username.to_sym) { Member.new(username: username) }
|
42
|
-
end
|
43
|
-
|
44
|
-
let(:card) { TrackedCard.create(name: "any", short_id: 1234, trello_id: "123123") }
|
45
|
-
let(:another_card) { TrackedCard.create(name: "any_other", short_id: 1235, trello_id: "123125") }
|
46
|
-
|
47
|
-
it "is zero when the member did not spent effort at all" do
|
48
|
-
piero.effort_spent.should == 0
|
49
|
-
end
|
50
|
-
|
51
|
-
it "counts the effort spent on a card" do
|
52
|
-
card.efforts << Effort.new(amount: 4, date: Date.today, members: [piero, tommaso])
|
53
|
-
card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
|
54
|
-
|
55
|
-
piero.effort_spent.should == 4 / 2
|
56
|
-
end
|
57
|
-
|
58
|
-
it "counts the effort spent on several cards" do
|
59
|
-
card.efforts << Effort.new(amount: 4, date: Date.today, members: [piero, tommaso])
|
60
|
-
another_card.efforts << Effort.new(amount: 5, date: Date.today, members: [piero])
|
61
|
-
|
62
|
-
piero.effort_spent.should == 2 + 5
|
63
|
-
end
|
64
|
-
|
65
|
-
it "counts the effort spent on a card from a given date" do
|
66
|
-
card.efforts << Effort.new(amount: 4, date: Date.yesterday, members: [piero])
|
67
|
-
card.efforts << Effort.new(amount: 5, date: Date.today, members: [piero])
|
68
|
-
|
69
|
-
piero.effort_spent(Date.today).should == 5
|
70
|
-
piero.effort_spent_since(Date.today).should == 5
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
describe "#avatar_url" do
|
76
|
-
it "points to the avatar thumbnail image" do
|
77
|
-
member = Member.new(avatar_id: "123xyz")
|
78
|
-
member.avatar_url.should == "https://trello-avatars.s3.amazonaws.com/123xyz/30.png"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|