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 +4 -4
- data/CHANGELOG.rst +13 -0
- data/Gemfile +1 -0
- data/Rakefile +2 -0
- data/bin/console +1 -1
- data/lib/harvest.rb +27 -12
- data/lib/harvest/changers.rb +27 -0
- data/lib/harvest/creates.rb +2 -2
- data/lib/harvest/discovers.rb +3 -0
- data/lib/harvest/finders.rb +1 -1
- data/lib/harvest/httpclient.rb +41 -18
- data/lib/harvest/resources/timeentry.rb +4 -0
- data/lib/harvest/version.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: cffdd572f038a6df6e90e8f2380d03c0b035dc687bd7ad49748a5e93c936095c
|
4
|
+
data.tar.gz: 60e6607a331fd3d6a892d803f7663050ccd61456bec9b84089d279f9c9b7a9fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
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
|
-
@
|
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
|
data/lib/harvest/creates.rb
CHANGED
@@ -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.
|
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
|
data/lib/harvest/discovers.rb
CHANGED
data/lib/harvest/finders.rb
CHANGED
data/lib/harvest/httpclient.rb
CHANGED
@@ -71,7 +71,7 @@ module Harvest
|
|
71
71
|
|
72
72
|
# Make a api call to an endpoint.
|
73
73
|
# @api public
|
74
|
-
# @param struct [
|
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
|
-
|
113
|
+
ApiCall.new(
|
112
114
|
{
|
113
115
|
path: path,
|
114
116
|
http_method: http_method.to_sym,
|
115
|
-
|
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
|
-
|
134
|
-
|
135
|
-
|
136
|
-
:http_method,
|
137
|
-
|
138
|
-
:
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
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
|
-
|
161
|
-
{
|
183
|
+
ApiCall.new(
|
184
|
+
**{
|
162
185
|
path: path,
|
163
186
|
http_method: http_method,
|
164
|
-
|
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,
|
data/lib/harvest/version.rb
CHANGED
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.
|
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:
|
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
|