forecasting 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: edb8ec26fd106cae648d103e0d55a3eac43a84950932903c964263597641dae1
4
- data.tar.gz: cc0ff4974048deca834309b5c652bd776ba6ef78454f7cf5cbe1afeeb85dc4cf
3
+ metadata.gz: 28606e4981727f588e0ab9a027bcea84cd3f25563d2ab031b2eeb075455d42be
4
+ data.tar.gz: e68359ad5b0452f3c60f5d5d4c00a7cf9f03311da0d277b7832c88a3115dfc68
5
5
  SHA512:
6
- metadata.gz: bf01d135878f0a0fe617787f0b4f73404b5cbc71b0fe6ea7c460b47bb8e097f25265925d9a50e78dc5bd17386d32773d8e86428ed2ad414e293d2b1975296f5a
7
- data.tar.gz: f58e4883da565c2388e6baa5b6b09498574e5e214cbc21d1e0cff0b9d696462db230c07b3406500ee6583faa5f680960bc78670a66570805d688fb4fd3b080f1
6
+ metadata.gz: 37dccf7bdca14315ec3810be2bc6de1123827b5388a903dee7b5f2f9501a064c3772a10afc0cb5fa5dee12c7da0335b9f7e82a80927052c8f20376f4fdb233d9
7
+ data.tar.gz: da4002bc71187fe2084fee8c377de963805f93a7ba79e0a7489cd6f275ff8985b688ca805823282da145334cdd0684eb113ffb8e9e0c1f553e6bb40cdfae937e
data/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@
4
4
 
5
5
  **Bug Fixes**
6
6
 
7
+ ## Version 0.2.0 - Jan 30, 2023
8
+
9
+ **Notes**
10
+
11
+ - Refactored Forecasting::Models::Base and Forecasting::Models::ForecastRecord
12
+
7
13
  ## Version 0.1.0 - Jan 29, 2023
8
14
 
9
15
  **Notes**
data/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/forecasting.svg)](https://badge.fury.io/rb/forecasting)
4
4
  [![Tests](https://github.com/NeomindLabs/forecasting/actions/workflows/ruby.yml/badge.svg)](https://github.com/NeomindLabs/forecasting/actions/workflows/ruby.yml)
5
- [![Code Climate](https://codeclimate.com/github/NeomindLabs/forecasting/badges/gpa.svg)](https://codeclimate.com/github/NeomindLabs/forecasting)
6
5
 
7
6
  A Ruby gem to interact with the Harvest Forecast API. Please note that there is currently [no official public API](https://help.getharvest.com/forecast/faqs/faq-list/api). This API client has been made by inspecting network requests using the Forecast website. This library is based on the excellent [Harvesting](https://github.com/fastruby/harvesting) gem.
8
7
 
@@ -17,12 +17,12 @@ class Forecasting::Client
17
17
 
18
18
  # @return [Forecasting::Models::Account]
19
19
  def account(id:)
20
- Forecasting::Models::Account.new(get("accounts/#{id}")["account"])
20
+ Forecasting::Models::Account.new(get("accounts/#{id}")["account"], forecast_client: self)
21
21
  end
22
22
 
23
23
  # @return [Forecasting::Models::Assignment]
24
24
  def assignment(id:)
25
- Forecasting::Models::Assignment.new(get("assignments/#{id}")["assignment"], forecast_client: self)
25
+ Forecasting::Models::Assignment.get(id, forecast_client: self)
26
26
  end
27
27
 
28
28
  # @return [Array<Forecasting::Models::Assignment>]
@@ -34,7 +34,7 @@ class Forecasting::Client
34
34
 
35
35
  # @return [Forecasting::Models::Client]
36
36
  def client(id:)
37
- Forecasting::Models::Client.new(get("clients/#{id}")["client"], forecast_client: self)
37
+ Forecasting::Models::Client.get(id, forecast_client: self)
38
38
  end
39
39
 
40
40
  # @return [Array<Forecasting::Models::Client>]
@@ -46,7 +46,7 @@ class Forecasting::Client
46
46
 
47
47
  # @return [Forecasting::Models::FtuxState]
48
48
  def ftux_state
49
- Forecasting::Models::FtuxState.new(get("ftux_state")["ftux_state"])
49
+ Forecasting::Models::FtuxState.new(get("ftux_state")["ftux_state"], forecast_client: self)
50
50
  end
51
51
 
52
52
  # @return [Array<Forecasting::Models::FutureScheduledHours>]
@@ -59,7 +59,7 @@ class Forecasting::Client
59
59
 
60
60
  # @return [Forecasting::Models::Milestone]
61
61
  def milestone(id:)
62
- Forecasting::Models::Milestone.new(get("milestones/#{id}")["milestone"], forecast_client: self)
62
+ Forecasting::Models::Milestone.get(id, forecast_client: self)
63
63
  end
64
64
 
65
65
  # @return [Array<Forecasting::Models::Milestone>]
@@ -71,7 +71,7 @@ class Forecasting::Client
71
71
 
72
72
  # @return [Forecasting::Models::Person]
73
73
  def person(id:)
74
- Forecasting::Models::Person.new(get("people/#{id}")["person"], forecast_client: self)
74
+ Forecasting::Models::Person.get(id, forecast_client: self)
75
75
  end
76
76
 
77
77
  # @return [Array<Forecasting::Models::Person>]
@@ -83,7 +83,7 @@ class Forecasting::Client
83
83
 
84
84
  # @return [Forecasting::Models::Placeholder]
85
85
  def placeholder(id:)
86
- Forecasting::Models::Placeholder.new(get("placeholders/#{id}")["placeholder"], forecast_client: self)
86
+ Forecasting::Models::Placeholder.get(id, forecast_client: self)
87
87
  end
88
88
 
89
89
  # @return [Array<Forecasting::Models::Placeholder>]
@@ -95,7 +95,7 @@ class Forecasting::Client
95
95
 
96
96
  # @return [Forecasting::Models::Projects]
97
97
  def project(id:)
98
- Forecasting::Models::Project.new(get("projects/#{id}")["project"], forecast_client: self)
98
+ Forecasting::Models::Project.get(id, forecast_client: self)
99
99
  end
100
100
 
101
101
  # @return [Array<Forecasting::Models::Project>]
@@ -114,7 +114,7 @@ class Forecasting::Client
114
114
 
115
115
  # @return [Forecasting::Models::RepeatedAssignmentSet]
116
116
  def repeated_assignment_set(id:)
117
- Forecasting::Models::RepeatedAssignmentSet.new(get("repeated_assignment_sets/#{id}")["repeated_assignment_set"], forecast_client: self)
117
+ Forecasting::Models::RepeatedAssignmentSet.get(id, forecast_client: self)
118
118
  end
119
119
 
120
120
  # @return [Array<Forecasting::Models::RepeatedAssignmentSet>]
@@ -126,7 +126,7 @@ class Forecasting::Client
126
126
 
127
127
  # @return [Forecasting::Models::Role]
128
128
  def role(id:)
129
- Forecasting::Models::Role.new(get("roles/#{id}")["role"], forecast_client: self)
129
+ Forecasting::Models::Role.get(id, forecast_client: self)
130
130
  end
131
131
 
132
132
  # @return [Array<Forecasting::Models::Role>]
@@ -138,19 +138,19 @@ class Forecasting::Client
138
138
 
139
139
  # @return [Forecasting::Models::Subscription]
140
140
  def subscription
141
- Forecasting::Models::Subscription.new(get("billing/subscription")["subscription"])
141
+ Forecasting::Models::Subscription.new(get("billing/subscription")["subscription"], forecast_client: self)
142
142
  end
143
143
 
144
144
  # @return [Forecasting::Models::UserConnection]
145
145
  def user_connections(opts = {})
146
146
  get("user_connections", opts)["user_connections"].map do |entry|
147
- Forecasting::Models::UserConnection.new(entry)
147
+ Forecasting::Models::UserConnection.new(entry, forecast_client: self)
148
148
  end
149
149
  end
150
150
 
151
151
  # @return [Forecasting::Models::User]
152
152
  def whoami
153
- Forecasting::Models::User.new(get("whoami")["current_user"])
153
+ Forecasting::Models::User.new(get("whoami")["current_user"], forecast_client: self)
154
154
  end
155
155
 
156
156
  # Creates an `entity` in your Harvest account.
@@ -13,4 +13,7 @@ module Forecasting
13
13
 
14
14
  class RateLimitExceeded < StandardError
15
15
  end
16
+
17
+ class MethodNotImplemented < StandardError
18
+ end
16
19
  end
@@ -15,7 +15,7 @@ module Forecasting
15
15
  :updated_by_id
16
16
 
17
17
  def path
18
- @attributes['id'].nil? ? "milestones" : "milestones/#{@attributes['id']}"
18
+ @attributes['id'].nil? ? "assignments" : "assignments/#{@attributes['id']}"
19
19
  end
20
20
 
21
21
  def project
@@ -1,10 +1,14 @@
1
1
  module Forecasting
2
2
  module Models
3
3
  class Base
4
+ # @return [Forecasting::Client]
5
+ attr_reader :forecast_client
6
+
4
7
  # @return [Hash]
5
8
  attr_accessor :attributes
6
9
 
7
- def initialize(attrs)
10
+ def initialize(attrs, opts = {})
11
+ @forecast_client = opts[:forecast_client] || Forecasting::Client.new(**opts)
8
12
  @attributes = attrs.dup
9
13
  @models = {}
10
14
  end
@@ -16,7 +20,6 @@ module Forecasting
16
20
  @attributes
17
21
  end
18
22
 
19
-
20
23
  # Class method to define attribute methods for accessing attributes for
21
24
  # a record
22
25
  #
@@ -55,7 +58,7 @@ module Forecasting
55
58
  opts.each do |attribute_name, model|
56
59
  attribute_name_string = attribute_name.to_s
57
60
  define_method(attribute_name_string) do
58
- @models[attribute_name_string] ||= model.new(@attributes[attribute_name_string] || {})
61
+ @models[attribute_name_string] ||= model.new(@attributes[attribute_name_string] || {}, forecast_client: forecast_client)
59
62
  end
60
63
  end
61
64
  end
@@ -1,13 +1,6 @@
1
1
  module Forecasting
2
2
  module Models
3
3
  class ForecastRecord < Base
4
- # @return [Forecasting::Model::Client]
5
- attr_reader :forecast_client
6
-
7
- def initialize(attrs, opts = {})
8
- @forecast_client = opts[:forecast_client] || Forecasting::Client.new(**opts)
9
- super(attrs)
10
- end
11
4
 
12
5
  def save
13
6
  id.nil? ? create : update
@@ -25,11 +18,10 @@ module Forecasting
25
18
  forecast_client.delete(self)
26
19
  end
27
20
 
28
- # It loads a new record from your Harvest account.
29
- #
30
- # @return [Forecasting::Models::Base]
21
+ # It loads a new record from your Harvest account. #
22
+ # @return [Forecasting::Models::ForecastRecord]
31
23
  def fetch
32
- self.class.new(@forecast_client.get(path), forecast_client: @forecast_client)
24
+ self.class.new(forecast_client.get(path), forecast_client: forecast_client)
33
25
  end
34
26
 
35
27
  # It returns the model type
@@ -39,6 +31,10 @@ module Forecasting
39
31
  self.class.name.split("::").last.downcase
40
32
  end
41
33
 
34
+ def path
35
+ raise Forecasting::MethodNotImplemented
36
+ end
37
+
42
38
  # Retrieves an instance of the object by ID
43
39
  #
44
40
  # @param id [Integer] the id of the object to retrieve
@@ -46,27 +42,8 @@ module Forecasting
46
42
  # instance
47
43
  def self.get(id, opts = {})
48
44
  client = opts[:forecast_client] || Forecasting::Client.new(**opts)
49
- self.new({ 'id' => id }, opts).fetch
50
- end
51
-
52
- protected
53
-
54
- # Class method to define nested resources for a record.
55
- #
56
- # It needs to be used like this:
57
- #
58
- # class Project < ForecastRecord
59
- # modeled client: Client
60
- # ...
61
- # end
62
- #
63
- # @param opts [Hash] key = symbol that needs to be the same as the one returned by the Harvest API. value = model class for the nested resource.
64
- def self.modeled(opts = {})
65
- opts.each do |attribute_name, model|
66
- attribute_name_string = attribute_name.to_s
67
- define_method(attribute_name_string) do
68
- @models[attribute_name_string] ||= model.new(@attributes[attribute_name_string] || {}, forecast_client: forecast_client)
69
- end
45
+ self.new({ 'id' => id }, opts).tap do |record|
46
+ record.attributes = client.get(record.path)
70
47
  end
71
48
  end
72
49
  end
@@ -1,19 +1,11 @@
1
1
  module Forecasting
2
2
  module Models
3
3
  class FutureScheduledHours < Base
4
- # @return [Forecasting::Model::Client]
5
- attr_reader :forecast_client
6
-
7
4
  attributed :project_id,
8
5
  :person_id,
9
6
  :placeholder_id,
10
7
  :allocation
11
8
 
12
- def initialize(attrs, opts = {})
13
- @forecast_client = opts[:forecast_client] || Forecasting::Client.new(**opts)
14
- super(attrs)
15
- end
16
-
17
9
  def project
18
10
  forecast_client.project(id: project_id)
19
11
  end
@@ -1,20 +1,12 @@
1
1
  module Forecasting
2
2
  module Models
3
3
  class RemainingBudgetedHours < Base
4
- # @return [Forecasting::Model::Client]
5
- attr_reader :forecast_client
6
-
7
4
  attributed :project_id,
8
5
  :budget_by,
9
6
  :budget_is_monthly,
10
7
  :hours,
11
8
  :response_code
12
9
 
13
- def initialize(attrs, opts = {})
14
- @forecast_client = opts[:forecast_client] || Forecasting::Client.new(**opts)
15
- super(attrs)
16
- end
17
-
18
10
  def project
19
11
  forecast_client.project(id: project_id)
20
12
  end
@@ -1,3 +1,3 @@
1
1
  module Forecasting
2
- VERSION = "0.1.0".freeze
2
+ VERSION = "0.2.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forecasting
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordan Owens
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-29 00:00:00.000000000 Z
11
+ date: 2023-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http
@@ -52,7 +52,7 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
- description: Interact with the Forecast API from your Ruby application
55
+ description: Interact with the Harvest Forecast API from your Ruby application
56
56
  email:
57
57
  - jordan@neomindlabs.com
58
58
  executables: []
@@ -109,5 +109,5 @@ requirements: []
109
109
  rubygems_version: 3.3.20
110
110
  signing_key:
111
111
  specification_version: 4
112
- summary: Ruby wrapper for the Forecast API
112
+ summary: Ruby wrapper for the Harvest Forecast API
113
113
  test_files: []