time_cop 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/time_cop/accountability.rb +24 -45
- data/lib/time_cop/runner.rb +63 -18
- data/lib/time_cop/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5386380ae098f3a9daa1a1e7861a44fb346db8e8
|
4
|
+
data.tar.gz: 6aa3386caa796aca933336607980e764aced49f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a4c4d9e71d174573580c90dc35f2f90f48de1059369d084d93411972a44b60c669af0cf9e59b807ccbc2128f3b015e48e01587d8e09a0f75570b4741010f6cd
|
7
|
+
data.tar.gz: 05f65255b494f94b81891a522a94e0635b17712cfbc60a3df8e49c8ed4ad18fdd4fa5e067c3df9715d31d3ed7c91c51eeeb5cbc663a1d1133299348387517f49
|
@@ -3,7 +3,7 @@ require 'date'
|
|
3
3
|
|
4
4
|
module TimeCop
|
5
5
|
class Accountability
|
6
|
-
attr_reader :report_builder, :client, :date, :hours_per_week
|
6
|
+
attr_reader :report_builder, :client, :date, :today, :hours_per_week
|
7
7
|
|
8
8
|
DAYS_PER_WEEK = 5.0
|
9
9
|
|
@@ -14,9 +14,10 @@ module TimeCop
|
|
14
14
|
q4: [{month: 10, day: 1}, {month: 12, day: 31}]
|
15
15
|
}
|
16
16
|
|
17
|
-
def initialize(username:, password:, subdomain: 'wildland', date: Date.today, report_builder: nil, email: nil, hours_per_week: 32)
|
17
|
+
def initialize(username:, password:, subdomain: 'wildland', date: Date.today, today: Date.today, report_builder: nil, email: nil, hours_per_week: 32)
|
18
18
|
@client = Harvest.client(username: username, password: password, subdomain: subdomain)
|
19
19
|
@date = date
|
20
|
+
@today = today
|
20
21
|
@hours_per_week = hours_per_week
|
21
22
|
@report_builder = report_builder ||
|
22
23
|
ReportBuilder.new(
|
@@ -83,49 +84,12 @@ module TimeCop
|
|
83
84
|
(end_of_quarter_date - start_of_quarter_date).to_i
|
84
85
|
end
|
85
86
|
|
86
|
-
def
|
87
|
-
|
88
|
-
return 0 unless days_between > 0
|
89
|
-
|
90
|
-
# Assuming we need to calculate days from 9th to 25th, 10-23 are covered
|
91
|
-
# by whole weeks, and 24-25 are extra days.
|
92
|
-
#
|
93
|
-
# Su Mo Tu We Th Fr Sa # Su Mo Tu We Th Fr Sa
|
94
|
-
# 1 2 3 4 5 # 1 2 3 4 5
|
95
|
-
# 6 7 8 9 10 11 12 # 6 7 8 9 ww ww ww
|
96
|
-
# 13 14 15 16 17 18 19 # ww ww ww ww ww ww ww
|
97
|
-
# 20 21 22 23 24 25 26 # ww ww ww ww ed ed 26
|
98
|
-
# 27 28 29 30 31 # 27 28 29 30 31
|
99
|
-
whole_weeks, extra_days = days_between.divmod(7)
|
100
|
-
|
101
|
-
unless extra_days.zero?
|
102
|
-
# Extra days start from the week day next to start_day,
|
103
|
-
# and end on end_date's week date. The position of the
|
104
|
-
# start date in a week can be either before (the left calendar)
|
105
|
-
# or after (the right one) the end date.
|
106
|
-
#
|
107
|
-
# Su Mo Tu We Th Fr Sa # Su Mo Tu We Th Fr Sa
|
108
|
-
# 1 2 3 4 5 # 1 2 3 4 5
|
109
|
-
# 6 7 8 9 10 11 12 # 6 7 8 9 10 11 12
|
110
|
-
# ## ## ## ## 17 18 19 # 13 14 15 16 ## ## ##
|
111
|
-
# 20 21 22 23 24 25 26 # ## 21 22 23 24 25 26
|
112
|
-
# 27 28 29 30 31 # 27 28 29 30 31
|
113
|
-
#
|
114
|
-
# If some of the extra_days fall on a weekend, they need to be subtracted.
|
115
|
-
# In the first case only corner days can be days off,
|
116
|
-
# and in the second case there are indeed two such days.
|
117
|
-
extra_days -= if start_date.next_day.wday <= end_date.wday
|
118
|
-
[start_date.next_day.sunday?, end_date.saturday?].count(true)
|
119
|
-
else
|
120
|
-
2
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
(whole_weeks * 5) + extra_days
|
87
|
+
def weekdays_between(start_date, end_date)
|
88
|
+
(start_date..end_date).select{|d| (1..5).include?(d.wday)}.size
|
125
89
|
end
|
126
90
|
|
127
91
|
def total_week_days
|
128
|
-
|
92
|
+
weekdays_between(start_of_quarter_date, end_of_quarter_date)
|
129
93
|
end
|
130
94
|
|
131
95
|
def expected_quarter_hours
|
@@ -133,7 +97,7 @@ module TimeCop
|
|
133
97
|
end
|
134
98
|
|
135
99
|
def expected_quarter_hours_to_today
|
136
|
-
|
100
|
+
weekdays_between(start_of_quarter_date, today < end_of_quarter_date ? Date.today : end_of_quarter_date) * hours_per_day
|
137
101
|
end
|
138
102
|
|
139
103
|
def current_hours_delta
|
@@ -145,13 +109,28 @@ module TimeCop
|
|
145
109
|
end
|
146
110
|
|
147
111
|
def quarterly_hours_per_business_day_needed
|
148
|
-
if
|
112
|
+
if weekdays_between(today, end_of_quarter_date) == 0
|
149
113
|
quarterly_hours_delta
|
150
114
|
else
|
151
|
-
quarterly_hours_delta /
|
115
|
+
quarterly_hours_delta / weekdays_between(today, end_of_quarter_date).to_f
|
152
116
|
end
|
153
117
|
end
|
154
118
|
|
119
|
+
def summary_hash
|
120
|
+
{
|
121
|
+
quarter: {
|
122
|
+
start: start_of_quarter_date,
|
123
|
+
end: end_of_quarter_date,
|
124
|
+
weekdays_in_quarter: weekdays_between(@report_builder.start_date, @report_builder.end_date)
|
125
|
+
},
|
126
|
+
hours_per_week: @hours_per_week,
|
127
|
+
hours: {
|
128
|
+
charged: total_quarter_time_tracked,
|
129
|
+
needed: expected_quarter_hours,
|
130
|
+
}
|
131
|
+
}
|
132
|
+
end
|
133
|
+
|
155
134
|
def print_report
|
156
135
|
puts "Quarter Period: #{start_of_quarter_date} #{end_of_quarter_date}"
|
157
136
|
puts "Hours Per Week: #{@hours_per_week}"
|
data/lib/time_cop/runner.rb
CHANGED
@@ -13,28 +13,73 @@ module TimeCop
|
|
13
13
|
cli = HighLine.new
|
14
14
|
username = cli.ask('Harvest Username: ')
|
15
15
|
password = cli.ask('Harvest Password: ') { |q| q.echo = false }
|
16
|
-
interactive_hash[:hours_per_week] = cli.ask('Hours per week? ') { |q| q.default =
|
16
|
+
interactive_hash[:hours_per_week] = cli.ask('Hours per week? (Full Time 34)') { |q| q.default = 34 }.to_f
|
17
|
+
accountability_options = {
|
18
|
+
username: (username.nil? ? options[:username] : username),
|
19
|
+
password: (password.nil? ? options[:password] : password),
|
20
|
+
email: options[:email]
|
21
|
+
}
|
22
|
+
q_dates = [
|
23
|
+
Date.new(Date.today.year, 1, 1),
|
24
|
+
Date.new(Date.today.year, 4, 1),
|
25
|
+
Date.new(Date.today.year, 7, 1),
|
26
|
+
Date.new(Date.today.year, 10, 1)
|
27
|
+
]
|
28
|
+
|
17
29
|
cli.choose do |menu|
|
18
30
|
menu.prompt = 'Which Quarter? '
|
19
|
-
menu.choice(:Q1)
|
20
|
-
|
21
|
-
|
22
|
-
|
31
|
+
menu.choice(:Q1) do
|
32
|
+
interactive_hash[:date] = q_dates[0]
|
33
|
+
Accountability.new(interactive_hash.merge(accountability_options)).print_report
|
34
|
+
end
|
35
|
+
menu.choice(:Q2) do
|
36
|
+
interactive_hash[:date] = q_dates[1]
|
37
|
+
Accountability.new(interactive_hash.merge(accountability_options)).print_report
|
38
|
+
end
|
39
|
+
menu.choice(:Q3) do
|
40
|
+
interactive_hash[:date] = q_dates[2]
|
41
|
+
Accountability.new(interactive_hash.merge(accountability_options)).print_report
|
42
|
+
end
|
43
|
+
menu.choice(:Q4) do
|
44
|
+
interactive_hash[:date] = q_dates[3]
|
45
|
+
Accountability.new(interactive_hash.merge(accountability_options)).print_report
|
46
|
+
end
|
47
|
+
menu.choice(:Year) do
|
48
|
+
summary = q_dates.map do |d|
|
49
|
+
interactive_hash[:date] = d
|
50
|
+
Accountability.new(interactive_hash.merge(accountability_options)).summary_hash
|
51
|
+
end
|
52
|
+
logged = summary.inject(0){|sum, s| sum + s[:hours][:charged]}
|
53
|
+
needed = summary.inject(0){|sum, s| sum + s[:hours][:needed]}.round(2 )
|
54
|
+
diff = (logged - needed).round(2)
|
55
|
+
weekdays = (Date.today..Date.new(Date.today.year, 12, 31)).select{|d| (1..5).include?(d.wday)}.size
|
56
|
+
weekdays_so_far = (Date.new(Date.today.year, 1, 1)..Date.today).select{|d| (1..5).include?(d.wday)}.size
|
57
|
+
average_needed = (-1 * diff / weekdays).round(2)
|
58
|
+
average_clocked = (logged / weekdays_so_far).round(2)
|
59
|
+
projected_diff = ((logged + (weekdays * average_clocked)) - needed).round(2)
|
60
|
+
|
61
|
+
puts "Business Days Left In Year: #{weekdays}"
|
62
|
+
puts "Current Year End Surplus(+)/Deficit(-): #{diff}"
|
63
|
+
puts "Projected Year End Surplus(+)/Deficit(-): #{projected_diff}"
|
64
|
+
puts ""
|
65
|
+
puts "Total Harvest Hours This Year: #{logged}"
|
66
|
+
puts "Average Harvest Hours Per Business Day: #{average_clocked}"
|
67
|
+
puts ""
|
68
|
+
puts "Total Hours Needed By End Of Year: #{needed}"
|
69
|
+
puts "Average Hours Per Business Day Needed To Reach Goal: #{average_needed}"
|
70
|
+
end
|
23
71
|
end
|
72
|
+
else
|
73
|
+
accountability_options = {
|
74
|
+
username: (options[:username]),
|
75
|
+
password: (options[:password]),
|
76
|
+
email: options[:email]
|
77
|
+
}
|
78
|
+
accountability = Accountability.new(
|
79
|
+
accountability_options
|
80
|
+
)
|
81
|
+
accountability.print_report
|
24
82
|
end
|
25
|
-
|
26
|
-
accountability_options = {
|
27
|
-
username: (username.nil? ? options[:username] : username),
|
28
|
-
password: (password.nil? ? options[:password] : password),
|
29
|
-
email: options[:email]
|
30
|
-
}
|
31
|
-
|
32
|
-
accountability_options = interactive_hash.merge(accountability_options)
|
33
|
-
|
34
|
-
accountability = Accountability.new(
|
35
|
-
accountability_options
|
36
|
-
)
|
37
|
-
accountability.print_report
|
38
83
|
rescue Harvest::AuthenticationFailed
|
39
84
|
puts 'Unable to authenticate to Harvest. Check username/password.'
|
40
85
|
rescue Harvest::HTTPError => e
|
data/lib/time_cop/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: time_cop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Clopton
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: harvested
|