time_cop 0.5.0 → 0.6.0

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.
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