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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c21ee81a8b7fc0e59cc8a8e5f157c5d17cfd3214
4
- data.tar.gz: 8360109023c4c93f1f34808281b121f2a13eab73
3
+ metadata.gz: 5386380ae098f3a9daa1a1e7861a44fb346db8e8
4
+ data.tar.gz: 6aa3386caa796aca933336607980e764aced49f3
5
5
  SHA512:
6
- metadata.gz: 0dd03ba3806685a59503b8ab5d6c9cb1e1915d9f112986da4ad1b0e64754319149375aa376b47c1dbd8be78d13108e1847932ed23b51b1a950ab3a224fd7c573
7
- data.tar.gz: c4266afc1f13cdaeb481dc7e8fac50997fc79a3ac50df396ec4f9948282005de53bccf089e73c8f65499cb7c79937097d8d879fa0e234bb2e1666bf14b913dbc
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 business_days_between(start_date, end_date)
87
- days_between = (end_date - start_date).to_i
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
- business_days_between(start_of_quarter_date, end_of_quarter_date)
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
- business_days_between(start_of_quarter_date, date) * hours_per_day
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 business_days_between(date, end_of_quarter_date) == 0
112
+ if weekdays_between(today, end_of_quarter_date) == 0
149
113
  quarterly_hours_delta
150
114
  else
151
- quarterly_hours_delta / business_days_between(date, end_of_quarter_date).to_f
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}"
@@ -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 = 32 }.to_i
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) { interactive_hash[:date] = Date.new(Date.today.year, 1, 1)}
20
- menu.choice(:Q2) { interactive_hash[:date] = Date.new(Date.today.year, 4, 1)}
21
- menu.choice(:Q3) { interactive_hash[:date] = Date.new(Date.today.year, 7, 1)}
22
- menu.choice(:Q4) { interactive_hash[:date] = Date.new(Date.today.year, 10, 1)}
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
@@ -1,3 +1,3 @@
1
1
  module TimeCop
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
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.5.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-07-17 00:00:00.000000000 Z
11
+ date: 2017-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: harvested