harvest-ruby-v2 0.3.3 → 0.5.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: 657bfe3e49665ad68a2d7498b8b775b6d7704701a807cbce5739d52e677e405b
4
- data.tar.gz: 9ced52a03ca53b10967c20e87ad156259c457d957a134196f89c403b6e97fc01
3
+ metadata.gz: cffdd572f038a6df6e90e8f2380d03c0b035dc687bd7ad49748a5e93c936095c
4
+ data.tar.gz: 60e6607a331fd3d6a892d803f7663050ccd61456bec9b84089d279f9c9b7a9fd
5
5
  SHA512:
6
- metadata.gz: 257341d20fd30a3e582784368020e32a903d9a87e9b6487aa6f6d1e85a57d170ccaf8082b9818da285d93c079bfad65925780e779430039e194fc85ffde426da
7
- data.tar.gz: 40a10bf4c46b6d48db61e4a4a8eeef8afd1db7e5a37c1018279967a1e02b6ace9314e12759d72080ba55fce393f8271a8b5874c83d8724d39de7f97f85a8146d
6
+ metadata.gz: 516bd47d51be828209b10d602c67bf2845a619bbbbacaa51b10ca2aeda4ad639a761455b6e6ff83f87854c06943ab6743eb42878b746e6276d624f90cd96bbe2
7
+ data.tar.gz: d42421df510e3d08e7a9e1ff8d9410911c3897a069e2270cabc966da8cc4c564afffd804b03b331d45791b7fa9e4a2dc1c6bbed4e66c8213447abaa681079244
data/CHANGELOG.rst CHANGED
@@ -0,0 +1,13 @@
1
+ ##########################
2
+ Changelog for harvest-ruby
3
+ ##########################
4
+
5
+ 0.5.1
6
+ ^^^^^
7
+
8
+ * Harvest API external_reference on time entries now contains account_id, updated Struct
9
+
10
+ 0.5.0
11
+ ^^^^^
12
+
13
+ * Fixed bug with ApiCall which caused query params to not be passed to the underlying call.
data/Gemfile CHANGED
@@ -8,6 +8,7 @@ gemspec
8
8
  gem 'activesupport', '~> 6.0'
9
9
  gem 'configparser', '~> 0.1.7', group: :development
10
10
  gem 'pry', '~> 0.13.1', group: :development
11
+ gem 'pry-stack_explorer', '~> 0.5.1', group: :development
11
12
  gem 'rake', '~> 12.0', group: :development
12
13
  gem 'redcarpet', '~> 3.5', group: :development
13
14
  gem 'reek', '~> 6.0', group: :development
data/Rakefile CHANGED
@@ -9,6 +9,8 @@ RSpec::Core::RakeTask.new(:spec)
9
9
  RuboCop::RakeTask.new(:spec) do |rubocop|
10
10
  rubocop.options << '--auto-correct'
11
11
  rubocop.options << '--display-cop-names'
12
+ rubocop.options << '--extra-details'
13
+ rubocop.options << '--display-style-guide'
12
14
  end
13
15
 
14
16
  YARD::Rake::YardocTask.new do |t|
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pry'
4
+ require 'pry-stack_explorer'
5
5
  require 'configparser'
6
6
  require 'date'
7
7
  require "bundler/setup"
data/lib/harvest.rb CHANGED
@@ -11,9 +11,11 @@ require 'harvest/exceptions'
11
11
  require 'harvest/finders'
12
12
  require 'harvest/discovers'
13
13
  require 'harvest/creates'
14
+ require 'harvest/changers'
14
15
 
15
16
  # Conform to naming pattern of Finder, Discover, Creators.
16
17
  # @param key [Symbol] symbol of state
18
+ # @return [Symbol] Symbol to use in class lookups
17
19
  def to_class_name(key)
18
20
  key.to_s.split('_').map(&:capitalize).join.to_sym
19
21
  end
@@ -38,14 +40,17 @@ module Harvest
38
40
  @client = Harvest::HTTP::Api.new(**@config)
39
41
  @factory = Harvest::ResourceFactory.new
40
42
  @state = state
41
- @active_user = @factory.user(@client.api_call(@client.api_caller('/users/me')))
42
- @admin_api = if @active_user.is_admin
43
+ @admin_api = if active_user.is_admin
43
44
  config.admin_api
44
45
  else
45
46
  false
46
47
  end
47
48
  end
48
49
 
50
+ def active_user
51
+ @state[:active_user] ||= @factory.user(@client.api_call(@client.api_caller('/users/me')))
52
+ end
53
+
49
54
  def allowed?(meth)
50
55
  %i[
51
56
  projects
@@ -90,6 +95,16 @@ module Harvest
90
95
  self
91
96
  end
92
97
 
98
+ # Find single instance of resource
99
+ def change(**kwargs)
100
+ @state[@state[:active]].map do |_obj|
101
+ Harvest::Changers.const_get(to_class_name(@state[:active])).new.change(
102
+ @factory, @client, active_user, @state, kwargs
103
+ )
104
+ end
105
+ self
106
+ end
107
+
93
108
  # Discover resources
94
109
  def discover(**params)
95
110
  @state[@state[:active]] = Harvest::Discovers
@@ -101,6 +116,16 @@ module Harvest
101
116
  self
102
117
  end
103
118
 
119
+ # Create an instance of object based on state
120
+ def create(**kwargs)
121
+ @state[@state[:active]] = Harvest::Create.const_get(
122
+ to_class_name(@state[:active])
123
+ ).new.create(
124
+ @factory, @client, active_user, @state, kwargs
125
+ )
126
+ self
127
+ end
128
+
104
129
  # Select a subset of all items depending on state
105
130
  def select(&block)
106
131
  @state[@state[:active]] = @state[@state[:active]].select(&block)
@@ -116,15 +141,5 @@ module Harvest
116
141
  def data
117
142
  @state[@state[:active]]
118
143
  end
119
-
120
- # Create an instance of object based on state
121
- def create(**kwargs)
122
- @state[@state[:active]] = Harvest::Create.const_get(
123
- to_class_name(@state[:active])
124
- ).new.create(
125
- @factory, @client, active_user, @state, kwargs
126
- )
127
- self
128
- end
129
144
  end
130
145
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Harvest
4
+ module Changers
5
+ class TimeEntry
6
+ def change(factory, client, _active_user, state, kwargs)
7
+ # binding.pry
8
+ state[state[:active]].map do |te|
9
+ send(kwargs[:action].to_sym, factory, client, te)
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def restart(factory, client, te)
16
+ # PATCH /v2/time_entries/{TIME_ENTRY_ID}/restart
17
+ # binding.pry
18
+ [factory.time_entry(client.api_call(client.api_caller("time_entries/#{te.id}/restart", http_method: 'patch')))]
19
+ end
20
+
21
+ def stop(factory, client, te)
22
+ # PATCH /v2/time_entries/{TIME_ENTRY_ID}/stop
23
+ [factory.time_entry(client.api_call(client.api_caller("time_entries/#{te.id}/stop", http_method: 'patch')))]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -34,8 +34,8 @@ module Harvest
34
34
 
35
35
  # @api private
36
36
  def time_entry_payload(kwargs)
37
- possible_keys = %i[spent_date notes external_reference user_id]
38
- payload = kwargs.map { |k, v| [k, v] if possible_keys.include?(k) }.to_h
37
+ possible_keys = %i[spent_date notes external_reference user_id project_id task_id]
38
+ payload = kwargs.each { |k, v| [k, v] if possible_keys.include?(k) }.to_h
39
39
  payload[:user_id] ||= @active_user.id
40
40
  payload[:task_id] = @state[:project_tasks][0].task.id
41
41
  payload[:project_id] = true_project(@state[:projects][0]).id
@@ -43,6 +43,9 @@ module Harvest
43
43
  paginator.path = 'time_entries'
44
44
  paginator.data_key = 'time_entries'
45
45
  paginator.param = params
46
+
47
+ # require 'pry'; binding.pry
48
+
46
49
  client.pagination(paginator).map do |time_entry|
47
50
  factory.time_entry(time_entry)
48
51
  end
@@ -10,7 +10,7 @@ module Harvest
10
10
 
11
11
  class TimeEntry
12
12
  def find(factory, client, id)
13
- [factory.time_entry(client.api_call(client.api_caller("time_entry/#{id}")))]
13
+ [factory.time_entry(client.api_call(client.api_caller("time_entries/#{id}")))]
14
14
  end
15
15
  end
16
16
  end
@@ -71,7 +71,7 @@ module Harvest
71
71
 
72
72
  # Make a api call to an endpoint.
73
73
  # @api public
74
- # @param struct [Struct::ApiCall]
74
+ # @param struct [ApiCall]
75
75
  def api_call(struct)
76
76
  JSON.parse(
77
77
  send(struct.http_method.to_sym, struct).tap do
@@ -85,7 +85,9 @@ module Harvest
85
85
  # @param struct [Struct::Pagination]
86
86
  def pagination(struct)
87
87
  struct.param[:page] = struct.page_count
88
- page = api_call(struct.to_api_call)
88
+ page = api_call(struct.to_api_call).tap do
89
+ # require 'pry'; binding.pry
90
+ end
89
91
  struct.rows.concat(page[struct.data_key])
90
92
 
91
93
  return struct.rows if struct.page_count >= page['total_pages']
@@ -108,11 +110,11 @@ module Harvest
108
110
  end
109
111
 
110
112
  def api_caller(path, http_method: 'get', param: {}, payload: nil, headers: {})
111
- Struct::ApiCall.new(
113
+ ApiCall.new(
112
114
  {
113
115
  path: path,
114
116
  http_method: http_method.to_sym,
115
- param: param,
117
+ params: param,
116
118
  payload: payload,
117
119
  headers: headers
118
120
  }
@@ -125,22 +127,43 @@ module Harvest
125
127
  client[struct.path].get(struct.headers)
126
128
  end
127
129
 
130
+ def delete(struct)
131
+ client[struct.path].delete(struct.headers)
132
+ end
133
+
128
134
  def post(struct)
129
135
  client[struct.path].post(struct.payload, struct.headers)
130
136
  end
137
+
138
+ def patch(struct)
139
+ client[struct.path].patch(struct.payload, struct.headers)
140
+ end
131
141
  end
132
142
 
133
- Struct.new(
134
- 'ApiCall',
135
- :path,
136
- :http_method,
137
- :param,
138
- :payload,
139
- :headers,
140
- keyword_init: true
141
- ) do
142
- def param(params)
143
- headers['params'] = params
143
+ class NoOptionProvided; end
144
+
145
+ class ApiCall
146
+ attr_accessor :path, :http_method, :payload, :headers
147
+
148
+ def initialize(path:, payload: {}, http_method: 'get', headers: {}, params: {})
149
+ @path = path
150
+ @http_method = http_method
151
+ @payload = payload
152
+ @headers = headers
153
+ param(params)
154
+ end
155
+
156
+ def param(params = NoOptionProvided)
157
+ if params == NoOptionProvided
158
+ @headers['params']
159
+ else
160
+ @headers['params'] = params
161
+ end
162
+ end
163
+
164
+ def param=(params)
165
+ param(params)
166
+ self
144
167
  end
145
168
  end
146
169
 
@@ -157,11 +180,11 @@ module Harvest
157
180
  keyword_init: true
158
181
  ) do
159
182
  def to_api_call
160
- Struct::ApiCall.new(
161
- {
183
+ ApiCall.new(
184
+ **{
162
185
  path: path,
163
186
  http_method: http_method,
164
- param: param,
187
+ params: param,
165
188
  payload: payload,
166
189
  headers: headers
167
190
  }
@@ -26,6 +26,8 @@ module Harvest
26
26
  # associated invoice's id and number.
27
27
  # @param hours [decimal]
28
28
  # Number of (decimal time) hours tracked in this time entry.
29
+ # @param hours_without_timer [decimal]
30
+ # Number of (decimal time) hours already tracked in this time entry, before the timer was last started.
29
31
  # @param rounded_hours [decimal]
30
32
  # Number of (decimal time) hours tracked in this time entry used in summary
31
33
  # reports and invoices. This value is rounded according to the Time Rounding
@@ -73,6 +75,7 @@ module Harvest
73
75
  :external_reference,
74
76
  :invoice,
75
77
  :hours,
78
+ :hours_without_timer,
76
79
  :rounded_hours,
77
80
  :notes,
78
81
  :is_locked,
@@ -95,6 +98,7 @@ module Harvest
95
98
  TimeEntryExternalReference = Struct.new(
96
99
  'TimeEntryExternalReference',
97
100
  :id,
101
+ :account_id,
98
102
  :group_id,
99
103
  :permalink,
100
104
  :service,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Harvest
4
- VERSION = '0.3.3'
4
+ VERSION = '0.5.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: harvest-ruby-v2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Craig Davis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-22 00:00:00.000000000 Z
11
+ date: 2021-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -61,6 +61,7 @@ files:
61
61
  - bin/setup
62
62
  - harvest-ruby-v2.gemspec
63
63
  - lib/harvest.rb
64
+ - lib/harvest/changers.rb
64
65
  - lib/harvest/client.rb
65
66
  - lib/harvest/config.rb
66
67
  - lib/harvest/creates.rb