harvest-ruby-v2 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,220 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pry'
4
+ require 'harvest/resources'
5
+
6
+ module Harvest
7
+ # Conversion for hash to Struct including nested items.
8
+ # TODO: Refactor for figuring out what Struct should be used
9
+ class NoValidStruct < ArgumentError
10
+ end
11
+
12
+ class ResourceFactory
13
+ def resource(klass, data)
14
+ data ||= {}
15
+ send(klass.to_sym, data)
16
+ end
17
+
18
+ def message_recipient(data)
19
+ data ||= {}
20
+ Struct::MessageRecipient.new(data)
21
+ end
22
+
23
+ def company(data)
24
+ data ||= {}
25
+ Struct::Company.new(data)
26
+ end
27
+
28
+ def estimate(data)
29
+ data ||= {}
30
+ convert_estimate_line_items(convert_client(Struct::Estimate.new(data)))
31
+ end
32
+
33
+ def estimate_line_item(data)
34
+ data ||= {}
35
+ Struct::EstimateLineItem.new(data)
36
+ end
37
+
38
+ def estimate_message(data)
39
+ data ||= {}
40
+ Struct::EstimateMessage.new(data)
41
+ end
42
+
43
+ def estimate_item_category(data)
44
+ data ||= {}
45
+ Struct::EstimateItemCategory.new(data)
46
+ end
47
+
48
+ def expense_category(data)
49
+ data ||= {}
50
+ Struct::ExpenseCategory.new(data)
51
+ end
52
+
53
+ def expense(data)
54
+ data ||= {}
55
+ Struct::Expense.new(data)
56
+ end
57
+
58
+ def invoice(data)
59
+ data ||= {}
60
+ Struct::Invoice.new(data)
61
+ end
62
+
63
+ def invoice_line_item(data)
64
+ data ||= {}
65
+ Struct::InvoiceLineItem.new(data)
66
+ end
67
+
68
+ def invoice_message(data)
69
+ data ||= {}
70
+ Struct::InvoiceMessage.new(data)
71
+ end
72
+
73
+ def invoice_payment(data)
74
+ data ||= {}
75
+ Struct::InvoicePayment.new(data)
76
+ end
77
+
78
+ def invoice_item_category(data)
79
+ data ||= {}
80
+ Struct::InvoiceItemCategory.new(data)
81
+ end
82
+
83
+ def project_assignment(data)
84
+ data ||= {}
85
+ unless data.nil?
86
+ convert_dates(
87
+ convert_project_client(
88
+ convert_task_assignments(
89
+ Struct::ProjectAssignment.new(data)
90
+ )
91
+ )
92
+ )
93
+ end
94
+ end
95
+
96
+ def project(data)
97
+ data ||= {}
98
+ convert_dates(Struct::Project.new(data)) unless data.nil?
99
+ end
100
+
101
+ def client(data)
102
+ data ||= {}
103
+ convert_dates(Struct::ResourceClient.new(data)) unless data.nil?
104
+ end
105
+
106
+ def task_assignment(data)
107
+ data ||= {}
108
+ convert_dates(convert_task(Struct::TaskAssignment.new(data))) unless data.nil?
109
+ end
110
+
111
+ def task(data)
112
+ data ||= {}
113
+ convert_dates(Struct::Task.new(data)) unless data.nil?
114
+ end
115
+
116
+ def user(data)
117
+ data ||= {}
118
+ convert_dates(Struct::User.new(data)) unless data.nil?
119
+ end
120
+
121
+ def user_assignment(data)
122
+ data ||= {}
123
+ convert_dates(Struct::UserAssignment.new(data)) unless data.nil?
124
+ end
125
+
126
+ def time_entry_external_reference(data)
127
+ data ||= {}
128
+ Struct::TimeEntryExternalReference.new(data)
129
+ end
130
+
131
+ def time_entry(data)
132
+ data ||= {}
133
+ convert_dates(
134
+ convert_project_client(
135
+ convert_task_assignment(
136
+ convert_task(
137
+ convert_user_assignment(
138
+ convert_user(
139
+ convert_external_reference(
140
+ Struct::TimeEntry.new(data)
141
+ )
142
+ )
143
+ )
144
+ )
145
+ )
146
+ )
147
+ )
148
+ end
149
+
150
+ private
151
+
152
+ def convert_estimate_line_items(data)
153
+ unless data.line_items.nil?
154
+ data.line_items = data.line_items.map { |ta| estimate_line_item(ta) }
155
+ end
156
+ data
157
+ end
158
+
159
+ def convert_external_reference(data)
160
+ data.external_reference = time_entry_external_reference(data.external_reference)
161
+ data
162
+ end
163
+
164
+ def convert_user(data)
165
+ data.user ||= {}
166
+ data.user = user(data.user) unless data.nil?
167
+ data
168
+ end
169
+
170
+ def convert_user_assignment(data)
171
+ data.user_assignment ||= {}
172
+ data.user_assignment = user_assignment(data.user_assignment) unless data.nil?
173
+ data
174
+ end
175
+
176
+ def convert_task_assignment(data)
177
+ data.task_assignment ||= {}
178
+
179
+ data.task_assignment = task_assignment(data.task_assignment) unless data.task_assignment.nil?
180
+ data
181
+ end
182
+
183
+ def convert_task_assignments(data)
184
+ unless data.task_assignments.nil?
185
+ data.task_assignments = data.task_assignments.map { |ta| task_assignment(ta) }
186
+ end
187
+ data
188
+ end
189
+
190
+ def convert_task(data)
191
+ data.task ||= {}
192
+ data.task = task(data.task) unless data.task.nil?
193
+ data
194
+ end
195
+
196
+ # @param data [Struct] passed a struct which contains an attribute client
197
+ def convert_client(data)
198
+ data.client = client(data.client)
199
+ data
200
+ end
201
+
202
+ def convert_project(data)
203
+ data.project = project(data.project)
204
+ data
205
+ end
206
+
207
+ def convert_project_client(data)
208
+ convert_project(convert_client(data))
209
+ end
210
+
211
+ def convert_dates(data)
212
+ %i[created_at updated_at sent_at accepted_at declined_at].each do |key|
213
+ if data.members.include?(key) && !data.method(key).call.nil?
214
+ data.method("#{key}=").call(DateTime.strptime(data.method(key).call))
215
+ end
216
+ end
217
+ data
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'harvest/resources/message'
4
+ require 'harvest/resources/company'
5
+ require 'harvest/resources/user'
6
+ require 'harvest/resources/task_assignment'
7
+ require 'harvest/resources/user_assignment'
8
+ require 'harvest/resources/timeentry'
9
+ require 'harvest/resources/estimates'
10
+ require 'harvest/resources/client'
11
+ require 'harvest/resources/expenses'
12
+ require 'harvest/resources/task'
13
+ require 'harvest/resources/project'
14
+ require 'harvest/resources/project_assignment'
15
+ require 'harvest/resources/invoices'
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Harvest
4
+ module Resources
5
+ # @param id [Integer]
6
+ # Unique ID for the client.
7
+ # @param name [String]
8
+ # A textual description of the client.
9
+ # @param is_active [Boolean]
10
+ # Whether the client is active or archived.
11
+ # @param address [String]
12
+ # The physical address for the client.
13
+ # @param statement_key [String]
14
+ # Used to build a URL to your client's invoice dashboard:
15
+ # @param currency [String]
16
+ # The currency code associated with this client.
17
+ # @param created_at [DateTime]
18
+ # Date and time the client was created.
19
+ # @param updated_at [DateTime]
20
+ # Date and time the client was last updated.
21
+ ResourceClient = Struct.new(
22
+ 'ResourceClient',
23
+ :id,
24
+ :name,
25
+ :is_active,
26
+ :address,
27
+ :statement_key,
28
+ :currency,
29
+ :created_at,
30
+ :updated_at,
31
+ keyword_init: true
32
+ )
33
+ end
34
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Harvest
4
+ module Resources
5
+ # @param base_uri [String]
6
+ # The Harvest URL for the company.
7
+ # @param full_domain [String]
8
+ # The Harvest domain for the company.
9
+ # @param name [String]
10
+ # The name of the company.
11
+ # @param is_active [Boolean]
12
+ # Whether the company is active or archived.
13
+ # @param week_start_day [String]
14
+ # The week day used as the start of the week. Returns one of: Saturday, Sunday, or Monday.
15
+ # @param wants_timestamp_timers [Boolean]
16
+ # Whether time is tracked via duration or start and end times.
17
+ # @param time_format [String]
18
+ # The format used to display time in Harvest. Returns either decimal or hours_minutes.
19
+ # @param plan_type [String]
20
+ # The type of plan the company is on. Examples: trial, free, or simple-v4
21
+ # @param clock [String]
22
+ # Used to represent whether the company is using a 12-hour or 24-hour clock.
23
+ # Returns either 12h or 24h.
24
+ # @param decimal_symbol [String]
25
+ # Symbol used when formatting decimals.
26
+ # @param thousands_separator [String]
27
+ # Separator used when formatting numbers.
28
+ # @param color_scheme [String]
29
+ # The color scheme being used in the Harvest web client.
30
+ # @param weekly_capacity [Integer]
31
+ # The weekly capacity in seconds.
32
+ # @param expense_feature [Boolean]
33
+ # Whether the expense module is enabled.
34
+ # @param invoice_feature [Boolean]
35
+ # Whether the invoice module is enabled.
36
+ # @param estimate_feature [Boolean]
37
+ # Whether the estimate module is enabled.
38
+ # @param approval_feature [Boolean]
39
+ # Whether the approval module is enabled.
40
+ Company = Struct.new(
41
+ 'Company',
42
+ :base_uri,
43
+ :full_domain,
44
+ :name,
45
+ :is_active,
46
+ :week_start_day,
47
+ :wants_timestamp_timers,
48
+ :time_format,
49
+ :plan_type,
50
+ :clock,
51
+ :decimal_symbol,
52
+ :thousands_separator,
53
+ :color_scheme,
54
+ :weekly_capacity,
55
+ :expense_feature,
56
+ :invoice_feature,
57
+ :estimate_feature,
58
+ :approval_feature,
59
+ keyword_init: true
60
+ )
61
+ end
62
+ end
@@ -0,0 +1,173 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Harvest
4
+ module Resources
5
+ # @param id [Integer]
6
+ # Unique ID for the estimate.
7
+ # @param client [Struct]
8
+ # An object containing estimate's client id and name.
9
+ # @param line_items [List]
10
+ # Array of estimate line items.
11
+ # @param creator [Struct]
12
+ # An object containing the id and name of the person that created the estimate.
13
+ # @param client_key [String]
14
+ # Used to build a URL to the public web invoice for your client:
15
+ # @param number [String]
16
+ # If no value is set, the number will be automatically generated.
17
+ # @param purchase_order [String]
18
+ # The purchase order number.
19
+ # @param amount [decimal]
20
+ # The total amount for the estimate, including any discounts and taxes.
21
+ # @param tax [decimal]
22
+ # This percentage is applied to the subtotal, including line items and
23
+ # discounts.
24
+ # @param tax_amount [decimal]
25
+ # The first amount of tax included, calculated from tax. If no tax is
26
+ # defined, this value will be null.
27
+ # @param tax2 [decimal]
28
+ # This percentage is applied to the subtotal, including line items and
29
+ # discounts.
30
+ # @param tax2_amount [decimal]
31
+ # The amount calculated from tax2.
32
+ # @param discount [decimal]
33
+ # This percentage is subtracted from the subtotal.
34
+ # @param discount_amount [decimal]
35
+ # The amount calcuated from discount.
36
+ # @param subject [String]
37
+ # The estimate subject.
38
+ # @param notes [String]
39
+ # Any additional notes included on the estimate.
40
+ # @param currency [String]
41
+ # The currency code associated with this estimate.
42
+ # @param state [String]
43
+ # The current state of the estimate: draft, sent, accepted, or declined.
44
+ # @param issue_date [Date]
45
+ # Date the estimate was issued.
46
+ # @param sent_at [DateTime]
47
+ # Date and time the estimate was sent.
48
+ # @param accepted_at [DateTime]
49
+ # Date and time the estimate was accepted.
50
+ # @param declined_at [DateTime]
51
+ # Date and time the estimate was declined.
52
+ # @param created_at [DateTime]
53
+ # Date and time the estimate was created.
54
+ # @param updated_at [DateTime]
55
+ # Date and time the estimate was last updated.
56
+ Estimate = Struct.new(
57
+ 'Estimate',
58
+ :id,
59
+ :client,
60
+ :line_items,
61
+ :creator,
62
+ :client_key,
63
+ :number,
64
+ :purchase_order,
65
+ :amount,
66
+ :tax,
67
+ :tax_amount,
68
+ :tax2,
69
+ :tax2_amount,
70
+ :discount,
71
+ :discount_amount,
72
+ :subject,
73
+ :notes,
74
+ :currency,
75
+ :state,
76
+ :issue_date,
77
+ :sent_at,
78
+ :accepted_at,
79
+ :declined_at,
80
+ :created_at,
81
+ :updated_at,
82
+ keyword_init: true
83
+ )
84
+
85
+ # @param id [Integer]
86
+ # Unique ID for the line item.
87
+ # @param kind [String]
88
+ # The name of an estimate item category.
89
+ # @param description [String]
90
+ # Text description of the line item.
91
+ # @param quantity [Integer]
92
+ # The unit quantity of the item.
93
+ # @param unit_price [decimal]
94
+ # The individual price per unit.
95
+ # @param amount [decimal]
96
+ # The line item subtotal (quantity * unit_price).
97
+ # @param taxed [Boolean]
98
+ # Whether the estimate's tax percentage applies to this line item.
99
+ # @param taxed2 [Boolean]
100
+ # Whether the estimate's tax2 percentage applies to this line item.
101
+ EstimateLineItem = Struct.new(
102
+ 'EstimateLineItem',
103
+ :id,
104
+ :kind,
105
+ :description,
106
+ :quantity,
107
+ :unit_price,
108
+ :amount,
109
+ :taxed,
110
+ :taxed2,
111
+ keyword_init: true
112
+ )
113
+
114
+ # @param id [Integer]
115
+ # Unique ID for the message.
116
+ # @param sent_by [String]
117
+ # Name of the user that created the message.
118
+ # @param sent_by_email [String]
119
+ # Email of the user that created the message.
120
+ # @param sent_from [String]
121
+ # Name of the user that the message was sent from.
122
+ # @param sent_from_email [String]
123
+ # Email of the user that message was sent from.
124
+ # @param recipients [List]
125
+ # Array of estimate message recipients.
126
+ # @param subject [String]
127
+ # The message subject.
128
+ # @param body [String]
129
+ # The message body.
130
+ # @param send_me_a_copy [Boolean]
131
+ # Whether to email a copy of the message to the current user.
132
+ # @param event_type [String]
133
+ # The type of estimate event that occurred with the message: send, accept,
134
+ # decline, re-open, view, or invoice.
135
+ # @param created_at [DateTime]
136
+ # Date and time the message was created.
137
+ # @param updated_at [DateTime]
138
+ # Date and time the message was last updated.
139
+ EstimateMessage = Struct.new(
140
+ 'EstimateMessage',
141
+ :id,
142
+ :sent_by,
143
+ :sent_by_email,
144
+ :sent_from,
145
+ :sent_from_email,
146
+ :recipients,
147
+ :subject,
148
+ :body,
149
+ :send_me_a_copy,
150
+ :event_type,
151
+ :created_at,
152
+ :updated_at,
153
+ keyword_init: true
154
+ )
155
+
156
+ # @param id [Integer]
157
+ # Unique ID for the estimate item category.
158
+ # @param name [String]
159
+ # The name of the estimate item category.
160
+ # @param created_at [DateTime]
161
+ # Date and time the estimate item category was created.
162
+ # @param updated_at [DateTime]
163
+ # Date and time the estimate item category was last updated.
164
+ EstimateItemCategory = Struct.new(
165
+ 'EstimateItemCategory',
166
+ :id,
167
+ :name,
168
+ :created_at,
169
+ :updated_at,
170
+ keyword_init: true
171
+ )
172
+ end
173
+ end