twstats 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/twstats.rb +2 -2
- data/lib/twstats/csv_reader.rb +15 -1
- data/lib/twstats/extensions.rb +16 -0
- data/lib/twstats/runner.rb +50 -4
- data/lib/twstats/tw_log.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 27db2b5244ab293d6e6f955c7392b1473daeaf2832c0a5f9db342a10216a72df
|
4
|
+
data.tar.gz: 1a475fe0708379be56cfd4cf9329c84cf03b4c7b21a4572a4c1a45c8c6e39608
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09a95242b4c137c7cdc474be974ab3b1f9623daeb5caaf2af63a411a0556914d30ca77a1b18f687dafd99e848e85f25b2e7486afe88a9c7399e7f1671c7c32cf'
|
7
|
+
data.tar.gz: 0470c445f623518a781d4da31376c3161e1ead38f3df8b32aa7a60c3fa98507edcae85c2d5c986d7758e23b8196a4554dfe332e703db6b80d27da52b9eb439a9
|
data/Gemfile.lock
CHANGED
data/lib/twstats.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
+
require_relative 'twstats/extensions'
|
1
2
|
require_relative 'twstats/version'
|
3
|
+
require_relative 'twstats/tw_log'
|
2
4
|
require_relative 'twstats/csv_reader'
|
3
5
|
require_relative 'twstats/runner'
|
4
|
-
require_relative 'twstats/tw_log'
|
5
6
|
|
6
7
|
module Twstats
|
7
|
-
|
8
8
|
DEFAULT_OPTIONS = {encoding: 'ISO-8859-1:UTF-8', headers: true}
|
9
9
|
WELLCOME_MESSAGE = "\n***************************************************************************************
|
10
10
|
** TWStats helps you to get some stats from a CSV export of Time loggin gin Teamwork **
|
data/lib/twstats/csv_reader.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'csv'
|
2
|
-
require "twstats/tw_log"
|
3
2
|
|
4
3
|
module Twstats
|
5
4
|
class CSVReader
|
@@ -74,5 +73,20 @@ module Twstats
|
|
74
73
|
sorted_logs = logs.map{|l| l.date}.sort
|
75
74
|
(sorted_logs[-1] - sorted_logs[0]).to_i <= 7
|
76
75
|
end
|
76
|
+
|
77
|
+
def not_tagged_tasks
|
78
|
+
total_time = 0
|
79
|
+
list = []
|
80
|
+
logs.each do |log|
|
81
|
+
if log.tags.empty?
|
82
|
+
list << log
|
83
|
+
total_time += log.decimal_time
|
84
|
+
end
|
85
|
+
end
|
86
|
+
{
|
87
|
+
total_time: total_time,
|
88
|
+
list: list
|
89
|
+
}
|
90
|
+
end
|
77
91
|
end
|
78
92
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Extend the string core class to add the truncate method from Rails
|
2
|
+
class String
|
3
|
+
def truncate(truncate_at, options = {})
|
4
|
+
return dup unless length > truncate_at
|
5
|
+
|
6
|
+
options[:omission] ||= '...'
|
7
|
+
length_with_room_for_omission = truncate_at - options[:omission].length
|
8
|
+
stop = if options[:separator]
|
9
|
+
rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission
|
10
|
+
else
|
11
|
+
length_with_room_for_omission
|
12
|
+
end
|
13
|
+
|
14
|
+
"#{self[0...stop]}#{options[:omission]}"
|
15
|
+
end
|
16
|
+
end
|
data/lib/twstats/runner.rb
CHANGED
@@ -65,10 +65,38 @@ module Twstats
|
|
65
65
|
puts " - #{k.ljust(max,' ').bright.blue} | #{v.round(2)}" unless v.zero?
|
66
66
|
end
|
67
67
|
end
|
68
|
+
show_not_tagged_section false
|
68
69
|
end
|
69
70
|
|
70
|
-
def
|
71
|
+
def ranking_from_not_tagged(list)
|
72
|
+
result = {}
|
73
|
+
list[:list].each do |log|
|
74
|
+
result[log.who] ||= 0
|
75
|
+
result[log.who] += log.decimal_time
|
76
|
+
end
|
77
|
+
result.sort_by{|k,v| v}.reverse.to_h
|
78
|
+
end
|
79
|
+
|
80
|
+
def print_table(log_list)
|
81
|
+
167.times{print '-'}
|
82
|
+
puts "\n|"+'Date'.center(12,' ').bright+'|'+'Time'.center(6,' ').bright+'|'+'Who'.center(20, ' ').bright+
|
83
|
+
'|'+'Description'.center(78,' ').bright+'|'+'Tags'.center(24,' ').bright+'|'+'Task'.center(20, ' ').bright+'|'
|
84
|
+
167.times{print '-'}
|
85
|
+
puts ""
|
86
|
+
log_list.each do |log|
|
87
|
+
puts table_line(log)
|
88
|
+
end
|
89
|
+
167.times{print '-'}
|
90
|
+
puts ""
|
91
|
+
end
|
71
92
|
|
93
|
+
def table_line(log)
|
94
|
+
"|"+"#{log.date.strftime('%d/%m/%Y')}".truncate(10).center(12,' ')+
|
95
|
+
'|'+"#{log.decimal_time.round(2)}".truncate(4).center(6,' ')+
|
96
|
+
'|'+"#{log.who}".truncate(18).center(20, ' ')+
|
97
|
+
'|'+"#{log.description}".truncate(76).ljust(78,' ')+
|
98
|
+
'|'+"#{log.tags.join(', ')}".truncate(22).center(24,' ')+
|
99
|
+
'|'+"#{log.task}".truncate(18).center(20, ' ')+'|'
|
72
100
|
end
|
73
101
|
|
74
102
|
def show_full_stats
|
@@ -87,10 +115,28 @@ module Twstats
|
|
87
115
|
show_stats :people, true
|
88
116
|
section "Tags used"
|
89
117
|
show_stats :tags, true
|
118
|
+
show_not_tagged_section(true)
|
90
119
|
section "Usefull metrics"
|
91
120
|
show_metrics
|
92
121
|
end
|
93
122
|
|
123
|
+
def show_not_tagged_section(table)
|
124
|
+
not_tagged = @csv.not_tagged_tasks
|
125
|
+
unless not_tagged[:list].empty?
|
126
|
+
section("Tasks not tagged in this report")
|
127
|
+
puts "A total of #{not_tagged[:list].size} logs have not been tagged:"
|
128
|
+
puts " - A total time of #{not_tagged[:total_time]} is not tagged properly."
|
129
|
+
puts " - Impact by employee: "
|
130
|
+
ranking_from_not_tagged(not_tagged).each do |user, time|
|
131
|
+
puts "\t - #{user.ljust(30,' ').bright.blue} | #{time}"
|
132
|
+
end
|
133
|
+
table = @prompt.yes?('Do you want to see what tasks have not been tagged?', default: true) if table.nil?
|
134
|
+
if table
|
135
|
+
print_table not_tagged[:list]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
94
140
|
def section(text)
|
95
141
|
puts ""
|
96
142
|
puts (" "+text+" ").center(70,"*").bright
|
@@ -115,9 +161,9 @@ module Twstats
|
|
115
161
|
@csv.people.each do |person|
|
116
162
|
billable, non_billable = @csv.get_total_time(:people, person, true)
|
117
163
|
info[person] = {rate: billable * 100 / hours,
|
118
|
-
|
119
|
-
|
120
|
-
|
164
|
+
not_billed: hours - billable - non_billable,
|
165
|
+
billable: billable,
|
166
|
+
non_billable: non_billable
|
121
167
|
}
|
122
168
|
end
|
123
169
|
info.sort_by{|x,v| v[:rate] }.reverse.each do |person, data|
|
data/lib/twstats/tw_log.rb
CHANGED
@@ -19,7 +19,7 @@ module Twstats
|
|
19
19
|
@decimal_time = row["Decimal Hours"].to_f
|
20
20
|
@time = (DateTime.parse(row["End Date/Time"]) - DateTime.parse(row["Date/Time"]))*24
|
21
21
|
@description = row["Description"]
|
22
|
-
@tags = row["Tags"].split(',')
|
22
|
+
@tags = row['Tags'].nil? ? [] : row["Tags"].split(',')
|
23
23
|
@project = row["Project"]
|
24
24
|
@task = row["Task"]
|
25
25
|
@billable = !row["Is it Billable?"].to_i.zero?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twstats
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- J.P. Araque
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -104,6 +104,7 @@ files:
|
|
104
104
|
- exe/twstats
|
105
105
|
- lib/twstats.rb
|
106
106
|
- lib/twstats/csv_reader.rb
|
107
|
+
- lib/twstats/extensions.rb
|
107
108
|
- lib/twstats/runner.rb
|
108
109
|
- lib/twstats/tw_log.rb
|
109
110
|
- lib/twstats/version.rb
|