time-sheet 0.9.0 → 0.11.2

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
  SHA256:
3
- metadata.gz: 0bacee0db8abe56f89e78df5cfef966da22efcc24e5fff2db291714727815cd4
4
- data.tar.gz: 91e6034615db1c7d56ff9e91ba47200c41ac83338ae8049c22c6bf4ea93f67e1
3
+ metadata.gz: 34d0ef63890eeae177443276610e4537d5dc2cfd138497132e6eb351ef5aa869
4
+ data.tar.gz: e40b4fc84073bfc67a358e54c72107bd5a2a988969a75a3a5b04261b2574255c
5
5
  SHA512:
6
- metadata.gz: f3aff4885cc228ce208263dd4f3f2a9c93465b2e819d863595222060ae5c1902ee35c40a93b631bcc9ea6ca38192b8c5e5214712cbb7592145880d3ff33080db
7
- data.tar.gz: f01226ee033c0f451d367ad2616601294d3a6a6e2db414a5f3d728cd7f2fa3805bfde8ebc4241fdf2dc1bf8fdde80c15dc9ceee1614708c87bf559cf6fb14628
6
+ metadata.gz: 1bc92043a7bd4085427ade8981d7e7e014bc6704cec744174b53ec3ce9f6bd5e274d58d740371f08356fc1968207bc8b2c487d01b82fef1c2bbdd294b603cc75
7
+ data.tar.gz: 4ebf6508e2c23bb2ca6ba88f00c9ab945777f39ec76236a66362908787004c1d339bd6df7405f29f5fcde48f235853b611606e0c7b9d67d61dca8a7398265456
data/lib/time_sheet.rb CHANGED
@@ -1,5 +1,12 @@
1
1
  require 'time_sheet/version'
2
2
 
3
+ # silence HTTPClient
4
+ module Warning
5
+ def warn(mgs)
6
+ # drop
7
+ end
8
+ end
9
+
3
10
  if defined?(Bundler)
4
11
  begin
5
12
  require 'pry'
@@ -15,4 +22,12 @@ module TimeSheet
15
22
  def self.root
16
23
  @root ||= File.expand_path(File.dirname(__FILE__) + '/..')
17
24
  end
25
+
26
+ def self.options=(options)
27
+ @options = options
28
+ end
29
+
30
+ def self.options
31
+ @options
32
+ end
18
33
  end
@@ -3,6 +3,8 @@ require 'time'
3
3
 
4
4
  class TimeSheet::Time::Cmd
5
5
  def run
6
+ TimeSheet.options = options
7
+
6
8
  if d = options[:from]
7
9
  if d.match(/^\d\d?-\d\d?$/)
8
10
  d = "#{TimeSheet::Time::Util.now.year}-#{d}"
@@ -64,6 +66,10 @@ class TimeSheet::Time::Cmd
64
66
  options[:to] = TimeSheet::Time::Util.month_end(-1)
65
67
  options[:summary] = true
66
68
  report
69
+ when 'year-to-day', 'year'
70
+ options[:from] = TimeSheet::Time::Util.year_start(-1)
71
+ options[:summary] = true
72
+ report
67
73
  when 'overview'
68
74
  overview
69
75
  else
@@ -111,12 +117,14 @@ class TimeSheet::Time::Cmd
111
117
  o.string '-t', '--to', 'ignore entries more recent than the date given'
112
118
  o.string '-p', '--project', 'take only entries of this project into account'
113
119
  o.string '-a', '--activity', 'take only entries of this activity into account'
120
+ o.string '--tags', 'take only entries with these tags into account (comma separated, not case sensitive)'
114
121
  o.string '-d', '--description', 'consider only entries matching this description'
115
122
  o.string '-e', '--employee', 'consider only entries for this employee'
116
123
  o.float '-r', '--rate', 'use an alternative hourly rate (default: 80.0)', default: 80.00
117
124
  o.boolean '-s', '--summary', 'when reporting, add summary section'
118
125
  o.boolean '--trim', 'compact the output for processing as CSV', default: false
119
126
  o.boolean '-v', '--verbose', 'be more verbose'
127
+ o.boolean '--debug', 'drop into a REPL on errors'
120
128
  o.separator "\n invoice options:"
121
129
  o.integer '--package', 'for invoice output: build packages of this duration in hours', default: 0
122
130
  o.integer '--petty', 'fold records under a certain threshold into a "misc" activity', default: 0
@@ -148,7 +156,7 @@ class TimeSheet::Time::Cmd
148
156
  end
149
157
 
150
158
  if options[:package]
151
- package = data.last.map{|entry| entry[1]}.sum
159
+ package = (data.last.nil? ? 0 : data.last.map{|entry| entry[1]}.sum)
152
160
  total = options[:package] * 60
153
161
  percent = (package / total.to_f * 100)
154
162
 
@@ -78,7 +78,7 @@ class TimeSheet::Time::Entry
78
78
  end
79
79
 
80
80
  def tags
81
- (@data['tags'] || '').split(/\s*,\s*/)
81
+ self.class.parse_tags(@data['tags'])
82
82
  end
83
83
 
84
84
  def working_day?
@@ -90,7 +90,9 @@ class TimeSheet::Time::Entry
90
90
  from = from.to_time if from.is_a?(Date)
91
91
  to = (filters[:to] ? filters[:to] : nil)
92
92
  to = (to + 1).to_time if to.is_a?(Date)
93
+ tags = self.class.parse_tags(filters[:tags])
93
94
 
95
+ has_tags?(tags) &&
94
96
  self.class.attrib_matches_any?(employee, filters[:employee]) &&
95
97
  self.class.attrib_matches_any?(description, filters[:description]) &&
96
98
  self.class.attrib_matches_any?(project, filters[:project]) &&
@@ -99,12 +101,23 @@ class TimeSheet::Time::Entry
99
101
  (!to || to >= self.end)
100
102
  end
101
103
 
104
+ def has_tags?(tags)
105
+ return true if tags.empty?
106
+
107
+ tags.all? do |tag|
108
+ self.tags.include?(tag)
109
+ end
110
+ end
111
+
102
112
  def valid?
103
113
  valid!
104
114
  true
105
115
  rescue TimeSheet::Time::Exception => e
106
116
  self.exception = e
107
117
  false
118
+ rescue StandardError => e
119
+ binding.pry if Timesheet.options[:debug]
120
+ false
108
121
  end
109
122
 
110
123
  def valid!
@@ -154,7 +167,8 @@ class TimeSheet::Time::Entry
154
167
  'duration' => duration,
155
168
  'project' => project,
156
169
  'activity' => activity,
157
- 'description' => description
170
+ 'description' => description,
171
+ 'tags' => tags
158
172
  }
159
173
  end
160
174
 
@@ -170,4 +184,8 @@ class TimeSheet::Time::Entry
170
184
  end
171
185
  end
172
186
 
187
+ def self.parse_tags(string)
188
+ (string || '').to_s.downcase.split(/\s*,\s*/).map{|t| t.strip}
189
+ end
190
+
173
191
  end
@@ -68,10 +68,11 @@ class TimeSheet::Time::Parser
68
68
 
69
69
  Spreadsheet.open(filename).worksheets.each do |sheet|
70
70
  headers = sheet.rows.first.to_a
71
- sheet.rows[1..-1].each do |row|
71
+ sheet.rows[1..-1].each.with_index do |row, i|
72
72
  # TODO find a way to guard against xls sheets with 65535 (empty)
73
73
  # lines, perhaps:
74
74
  # break if row[1].nil?
75
+ next if row.all?{|cell| [nil, ''].include?(cell)}
75
76
 
76
77
  record = {}
77
78
  row.each_with_index do |value, i|
@@ -84,16 +85,16 @@ class TimeSheet::Time::Parser
84
85
  results
85
86
  end
86
87
 
87
- def parse_google_doc(share_url)
88
- id = share_url.match(/\/d\/([^\/]+)\//)[1]
89
- url = "https://docs.google.com/spreadsheets/d/#{id}/export?exportFormat=tsv"
88
+ def parse_google_doc(url)
89
+ # Chart Tools datasource protocol, see
90
+ # https://developers.google.com/chart/interactive/docs/querylanguage
90
91
  response = HTTPClient.get(url)
91
92
 
92
93
  if response.status == 200
93
- data = CSV.parse(response.body, col_sep: "\t")
94
+ data = CSV.parse(response.body, liberal_parsing: true)
94
95
  headers = data.shift
95
96
  data.map do |row|
96
- record = headers.zip(row).to_h
97
+ record = nullify_empties(headers.zip(row).to_h)
97
98
  parse_date_and_time(record)
98
99
  end
99
100
  else
@@ -108,9 +109,16 @@ class TimeSheet::Time::Parser
108
109
  'end' => (record['end'] ? DateTime.parse(record['end']) : nil)
109
110
  )
110
111
  rescue ArgumentError => e
112
+ binding.pry if TimeSheet.options[:debug]
111
113
  puts "current record: #{record.inspect}"
112
114
  return {}
113
115
  # raise e
114
116
  end
115
117
 
118
+ def nullify_empties(record)
119
+ record.transform_values do |v|
120
+ v == '' ? nil : v
121
+ end
122
+ end
123
+
116
124
  end
@@ -1,3 +1,3 @@
1
1
  module TimeSheet
2
- VERSION = "0.9.0"
2
+ VERSION = "0.11.2"
3
3
  end
data/time_sheet.gemspec CHANGED
@@ -28,8 +28,8 @@ Gem::Specification.new do |spec|
28
28
  spec.add_dependency 'slop'
29
29
  spec.add_dependency 'httpclient'
30
30
 
31
- spec.add_development_dependency "bundler", "~> 1.15"
32
- spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "bundler", "~> 2.2.16"
32
+ spec.add_development_dependency "rake", "~> 13.0"
33
33
  spec.add_development_dependency "rspec", "~> 3.0"
34
34
  spec.add_development_dependency 'pry'
35
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: time-sheet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.11.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moritz Schepp
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-25 00:00:00.000000000 Z
11
+ date: 2021-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: spreadsheet
@@ -58,28 +58,28 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.15'
61
+ version: 2.2.16
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '1.15'
68
+ version: 2.2.16
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '10.0'
75
+ version: '13.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '10.0'
82
+ version: '13.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -108,7 +108,7 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
- description:
111
+ description:
112
112
  email:
113
113
  - moritz.schepp@gmail.com
114
114
  executables:
@@ -134,13 +134,13 @@ files:
134
134
  - lib/time_sheet/time/util.rb
135
135
  - lib/time_sheet/version.rb
136
136
  - time_sheet.gemspec
137
- homepage:
137
+ homepage:
138
138
  licenses:
139
139
  - GPL-3.0-only
140
140
  metadata:
141
141
  bug_tracker_uri: https://github.com/moritzschepp/time-sheet/issues
142
142
  documentation_uri: https://github.com/moritzschepp/time-sheet
143
- post_install_message:
143
+ post_install_message:
144
144
  rdoc_options: []
145
145
  require_paths:
146
146
  - lib
@@ -155,9 +155,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
155
  - !ruby/object:Gem::Version
156
156
  version: '0'
157
157
  requirements: []
158
- rubyforge_project:
159
- rubygems_version: 2.7.6.2
160
- signing_key:
158
+ rubygems_version: 3.1.6
159
+ signing_key:
161
160
  specification_version: 4
162
161
  summary: a time tracking solution based on spreadsheets
163
162
  test_files: []