avatax 14.4.4 → 17.5.0

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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +54 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +7 -0
  5. data/.yardopts +5 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE +201 -191
  8. data/README.md +63 -61
  9. data/Rakefile +9 -0
  10. data/avatax.gemspec +39 -0
  11. data/example/avatax.rb +14 -0
  12. data/example/credentials.example.yaml +5 -0
  13. data/lib/avatax.rb +19 -13
  14. data/lib/avatax/api.rb +27 -0
  15. data/lib/avatax/client.rb +32 -0
  16. data/lib/avatax/client/accounts.rb +110 -0
  17. data/lib/avatax/client/addresses.rb +52 -0
  18. data/lib/avatax/client/batches.rb +117 -0
  19. data/lib/avatax/client/companies.rb +218 -0
  20. data/lib/avatax/client/contacts.rb +115 -0
  21. data/lib/avatax/client/definitions.rb +569 -0
  22. data/lib/avatax/client/filingcalendars.rb +313 -0
  23. data/lib/avatax/client/filings.rb +417 -0
  24. data/lib/avatax/client/free.rb +104 -0
  25. data/lib/avatax/client/fundingrequests.rb +53 -0
  26. data/lib/avatax/client/items.rb +111 -0
  27. data/lib/avatax/client/jurisdictionoverrides.rb +125 -0
  28. data/lib/avatax/client/locations.rb +158 -0
  29. data/lib/avatax/client/nexus.rb +157 -0
  30. data/lib/avatax/client/notices.rb +297 -0
  31. data/lib/avatax/client/onboarding.rb +23 -0
  32. data/lib/avatax/client/pointofsale.rb +24 -0
  33. data/lib/avatax/client/registrar.rb +216 -0
  34. data/lib/avatax/client/settings.rb +137 -0
  35. data/lib/avatax/client/subscriptions.rb +66 -0
  36. data/lib/avatax/client/taxcodes.rb +127 -0
  37. data/lib/avatax/client/taxrules.rb +127 -0
  38. data/lib/avatax/client/transactions.rb +473 -0
  39. data/lib/avatax/client/upcs.rb +112 -0
  40. data/lib/avatax/client/users.rb +112 -0
  41. data/lib/avatax/client/utilities.rb +52 -0
  42. data/lib/avatax/configuration.rb +53 -18
  43. data/lib/avatax/connection.rb +28 -0
  44. data/lib/avatax/request.rb +38 -0
  45. data/lib/avatax/version.rb +3 -0
  46. data/spec/avatax/client/accounts_spec.rb +26 -0
  47. data/spec/avatax_spec.rb +59 -0
  48. data/spec/fixtures/accounts.json +16 -0
  49. data/spec/spec_helper.rb +47 -0
  50. metadata +143 -30
  51. data/lib/avatax/address_service.rb +0 -31
  52. data/lib/avatax/tax_service.rb +0 -61
@@ -0,0 +1,157 @@
1
+ module AvaTax
2
+ class Client
3
+ module Nexus
4
+
5
+
6
+ # Create a new nexus
7
+ #
8
+ # Creates one or more new nexus objects attached to this company.
9
+ # The concept of 'Nexus' indicates a place where your company has sufficient physical presence and is obligated
10
+ # to collect and remit transaction-based taxes.
11
+ # When defining companies in AvaTax, you must declare nexus for your company in order to correctly calculate tax
12
+ # in all jurisdictions affected by your transactions.
13
+ # Note that not all fields within a nexus can be updated; Avalara publishes a list of all defined nexus at the
14
+ # '/api/v2/definitions/nexus' endpoint.
15
+ # You may only define nexus matching the official list of declared nexus.
16
+ #
17
+ # @param int companyId The ID of the company that owns this nexus.
18
+ # @param NexusModel[] model The nexus you wish to create.
19
+ # @return NexusModel[]
20
+ def create_nexus(companyId, model)
21
+ path = "/api/v2/companies/#{companyId}/nexus"
22
+
23
+ post(path, model)
24
+ end
25
+
26
+
27
+ # Delete a single nexus
28
+ #
29
+ # Marks the existing nexus object at this URL as deleted.
30
+ #
31
+ # @param int companyId The ID of the company that owns this nexus.
32
+ # @param int id The ID of the nexus you wish to delete.
33
+ # @return ErrorDetail[]
34
+ def delete_nexus(companyId, id)
35
+ path = "/api/v2/companies/#{companyId}/nexus/#{id}"
36
+
37
+ delete(path)
38
+ end
39
+
40
+
41
+ # Retrieve a single nexus
42
+ #
43
+ # Get the nexus object identified by this URL.
44
+ # The concept of 'Nexus' indicates a place where your company has sufficient physical presence and is obligated
45
+ # to collect and remit transaction-based taxes.
46
+ # When defining companies in AvaTax, you must declare nexus for your company in order to correctly calculate tax
47
+ # in all jurisdictions affected by your transactions.
48
+ #
49
+ # @param int companyId The ID of the company that owns this nexus object
50
+ # @param int id The primary key of this nexus
51
+ # @return NexusModel
52
+ def get_nexus(companyId, id)
53
+ path = "/api/v2/companies/#{companyId}/nexus/#{id}"
54
+
55
+ get(path)
56
+ end
57
+
58
+
59
+ # List company nexus related to a tax form
60
+ #
61
+ # Retrieves a list of nexus related to a tax form.
62
+ #
63
+ # The concept of `Nexus` indicates a place where your company has sufficient physical presence and is obligated
64
+ # to collect and remit transaction-based taxes.
65
+ #
66
+ # When defining companies in AvaTax, you must declare nexus for your company in order to correctly calculate tax
67
+ # in all jurisdictions affected by your transactions.
68
+ #
69
+ # This API is intended to provide useful information when examining a tax form. If you are about to begin filing
70
+ # a tax form, you may want to know whether you have declared nexus in all the jurisdictions related to that tax
71
+ # form in order to better understand how the form will be filled out.
72
+ #
73
+ # @param int companyId The ID of the company that owns this nexus object
74
+ # @param string formCode The form code that we are looking up the nexus for
75
+ # @return NexusByTaxFormModel
76
+ def get_nexus_by_form_code(companyId, formCode)
77
+ path = "/api/v2/companies/#{companyId}/nexus/byform/#{formCode}"
78
+
79
+ get(path)
80
+ end
81
+
82
+
83
+ # Retrieve nexus for this company
84
+ #
85
+ # List all nexus objects defined for this company.
86
+ # The concept of 'Nexus' indicates a place where your company has sufficient physical presence and is obligated
87
+ # to collect and remit transaction-based taxes.
88
+ # When defining companies in AvaTax, you must declare nexus for your company in order to correctly calculate tax
89
+ # in all jurisdictions affected by your transactions.
90
+ #
91
+ # Search for specific objects using the criteria in the `$filter` parameter; full documentation is available on [Filtering in REST](http://developer.avalara.com/avatax/filtering-in-rest/) .
92
+ # Paginate your results using the `$top`, `$skip`, and `$orderby` parameters.
93
+ #
94
+ # @param int companyId The ID of the company that owns these nexus objects
95
+ # @param string filter A filter statement to identify specific records to retrieve. For more information on filtering, see [Filtering in REST](http://developer.avalara.com/avatax/filtering-in-rest/) .
96
+ # @param string include A comma separated list of child objects to return underneath the primary object.
97
+ # @param int top If nonzero, return no more than this number of results. Used with $skip to provide pagination for large datasets.
98
+ # @param int skip If nonzero, skip this number of results before returning data. Used with $top to provide pagination for large datasets.
99
+ # @param string orderBy A comma separated list of sort statements in the format `(fieldname) [ASC|DESC]`, for example `id ASC`.
100
+ # @return FetchResult
101
+ def list_nexus_by_company(companyId, options={})
102
+ path = "/api/v2/companies/#{companyId}/nexus"
103
+
104
+ get(path, options)
105
+ end
106
+
107
+
108
+ # Retrieve all nexus
109
+ #
110
+ # Get multiple nexus objects across all companies.
111
+ # The concept of 'Nexus' indicates a place where your company has sufficient physical presence and is obligated
112
+ # to collect and remit transaction-based taxes.
113
+ # When defining companies in AvaTax, you must declare nexus for your company in order to correctly calculate tax
114
+ # in all jurisdictions affected by your transactions.
115
+ #
116
+ # Search for specific objects using the criteria in the `$filter` parameter; full documentation is available on [Filtering in REST](http://developer.avalara.com/avatax/filtering-in-rest/) .
117
+ # Paginate your results using the `$top`, `$skip`, and `$orderby` parameters.
118
+ #
119
+ # @param string filter A filter statement to identify specific records to retrieve. For more information on filtering, see [Filtering in REST](http://developer.avalara.com/avatax/filtering-in-rest/) .
120
+ # @param string include A comma separated list of child objects to return underneath the primary object.
121
+ # @param int top If nonzero, return no more than this number of results. Used with $skip to provide pagination for large datasets.
122
+ # @param int skip If nonzero, skip this number of results before returning data. Used with $top to provide pagination for large datasets.
123
+ # @param string orderBy A comma separated list of sort statements in the format `(fieldname) [ASC|DESC]`, for example `id ASC`.
124
+ # @return FetchResult
125
+ def query_nexus(options={})
126
+ path = "/api/v2/nexus"
127
+
128
+ get(path, options)
129
+ end
130
+
131
+
132
+ # Update a single nexus
133
+ #
134
+ # Replace the existing nexus object at this URL with an updated object.
135
+ # The concept of 'Nexus' indicates a place where your company has sufficient physical presence and is obligated
136
+ # to collect and remit transaction-based taxes.
137
+ # When defining companies in AvaTax, you must declare nexus for your company in order to correctly calculate tax
138
+ # in all jurisdictions affected by your transactions.
139
+ # Note that not all fields within a nexus can be updated; Avalara publishes a list of all defined nexus at the
140
+ # '/api/v2/definitions/nexus' endpoint.
141
+ # You may only define nexus matching the official list of declared nexus.
142
+ # All data from the existing object will be replaced with data in the object you PUT.
143
+ # To set a field's value to null, you may either set its value to null or omit that field from the object you post.
144
+ #
145
+ # @param int companyId The ID of the company that this nexus belongs to.
146
+ # @param int id The ID of the nexus you wish to update
147
+ # @param NexusModel model The nexus object you wish to update.
148
+ # @return NexusModel
149
+ def update_nexus(companyId, id, model)
150
+ path = "/api/v2/companies/#{companyId}/nexus/#{id}"
151
+
152
+ put(path, model)
153
+ end
154
+
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,297 @@
1
+ module AvaTax
2
+ class Client
3
+ module Notices
4
+
5
+
6
+ # Create a new notice comment.
7
+ #
8
+ # This API is available by invitation only.
9
+ # 'Notice comments' are updates by the notice team on the work to be done and that has been done so far on a notice.
10
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
11
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
12
+ #
13
+ # @param int companyId The ID of the company that owns this notice.
14
+ # @param int id The ID of the tax notice we are adding the comment for.
15
+ # @param NoticeCommentModel[] model The notice comments you wish to create.
16
+ # @return NoticeCommentModel[]
17
+ def create_notice_comment(companyId, id, model)
18
+ path = "/api/v2/companies/#{companyId}/notices/#{id}/comments"
19
+
20
+ post(path, model)
21
+ end
22
+
23
+
24
+ # Create a new notice finance details.
25
+ #
26
+ # This API is available by invitation only.
27
+ # 'Notice finance details' is the categorical breakdown of the total charge levied by the tax authority on our customer,
28
+ # as broken down in our "notice log" found in Workflow. Main examples of the categories are 'Tax Due', 'Interest', 'Penalty', 'Total Abated'.
29
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
30
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
31
+ #
32
+ # @param int companyId The ID of the company that owns this notice.
33
+ # @param int id The ID of the notice added to the finance details.
34
+ # @param NoticeFinanceModel[] model The notice finance details you wish to create.
35
+ # @return NoticeFinanceModel[]
36
+ def create_notice_finance_details(companyId, id, model)
37
+ path = "/api/v2/companies/#{companyId}/notices/#{id}/financedetails"
38
+
39
+ post(path, model)
40
+ end
41
+
42
+
43
+ # Create a new notice responsibility.
44
+ #
45
+ # This API is available by invitation only.
46
+ # 'Notice comments' are updates by the notice team on the work to be done and that has been done so far on a notice.
47
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
48
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
49
+ #
50
+ # @param int companyId The ID of the company that owns this notice.
51
+ # @param int id The ID of the tax notice we are adding the responsibility for.
52
+ # @param NoticeResponsibilityDetailModel[] model The notice responsibilities you wish to create.
53
+ # @return NoticeResponsibilityDetailModel[]
54
+ def create_notice_responsibilities(companyId, id, model)
55
+ path = "/api/v2/companies/#{companyId}/notices/#{id}/responsibilities"
56
+
57
+ post(path, model)
58
+ end
59
+
60
+
61
+ # Create a new notice root cause.
62
+ #
63
+ # This API is available by invitation only.
64
+ # 'Notice root causes' are are those who are responsible for the notice.
65
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
66
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
67
+ #
68
+ # @param int companyId The ID of the company that owns this notice.
69
+ # @param int id The ID of the tax notice we are adding the responsibility for.
70
+ # @param NoticeRootCauseDetailModel[] model The notice root causes you wish to create.
71
+ # @return NoticeRootCauseDetailModel[]
72
+ def create_notice_root_causes(companyId, id, model)
73
+ path = "/api/v2/companies/#{companyId}/notices/#{id}/rootcauses"
74
+
75
+ post(path, model)
76
+ end
77
+
78
+
79
+ # Create a new notice.
80
+ #
81
+ # This API is available by invitation only.
82
+ # Create one or more new notice objects.
83
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
84
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
85
+ #
86
+ # @param int companyId The ID of the company that owns this notice.
87
+ # @param NoticeModel[] model The notice object you wish to create.
88
+ # @return NoticeModel[]
89
+ def create_notices(companyId, model)
90
+ path = "/api/v2/companies/#{companyId}/notices"
91
+
92
+ post(path, model)
93
+ end
94
+
95
+
96
+ # Delete a single notice.
97
+ #
98
+ # This API is available by invitation only.
99
+ # Mark the existing notice object at this URL as deleted.
100
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
101
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
102
+ #
103
+ # @param int companyId The ID of the company that owns this notice.
104
+ # @param int id The ID of the notice you wish to delete.
105
+ # @return ErrorDetail[]
106
+ def delete_notice(companyId, id)
107
+ path = "/api/v2/companies/#{companyId}/notices/#{id}"
108
+
109
+ delete(path)
110
+ end
111
+
112
+
113
+ # Retrieve a single attachment
114
+ #
115
+ # This API is available by invitation only.
116
+ # Get the file attachment identified by this URL.
117
+ #
118
+ # @param int companyId The ID of the company for this attachment.
119
+ # @param int id The ResourceFileId of the attachment to download.
120
+ # @return FileResult
121
+ def download_notice_attachment(companyId, id)
122
+ path = "/api/v2/companies/#{companyId}/notices/files/#{id}/attachment"
123
+
124
+ get(path)
125
+ end
126
+
127
+
128
+ # Retrieve a single notice.
129
+ #
130
+ # This API is available by invitation only.
131
+ # Get the tax notice object identified by this URL.
132
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
133
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
134
+ #
135
+ # @param int companyId The ID of the company for this notice.
136
+ # @param int id The ID of this notice.
137
+ # @return NoticeModel
138
+ def get_notice(companyId, id)
139
+ path = "/api/v2/companies/#{companyId}/notices/#{id}"
140
+
141
+ get(path)
142
+ end
143
+
144
+
145
+ # Retrieve notice comments for a specific notice.
146
+ #
147
+ # This API is available by invitation only.
148
+ # 'Notice comments' are updates by the notice team on the work to be done and that has been done so far on a notice.
149
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
150
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
151
+ #
152
+ # @param int id The ID of the notice.
153
+ # @param int companyId The ID of the company that owns these notices.
154
+ # @return FetchResult
155
+ def get_notice_comments(id, companyId)
156
+ path = "/api/v2/companies/#{companyId}/notices/#{id}/comments"
157
+
158
+ get(path)
159
+ end
160
+
161
+
162
+ # Retrieve notice finance details for a specific notice.
163
+ #
164
+ # This API is available by invitation only.
165
+ # 'Notice finance details' is the categorical breakdown of the total charge levied by the tax authority on our customer,
166
+ # as broken down in our "notice log" found in Workflow. Main examples of the categories are 'Tax Due', 'Interest', 'Penalty', 'Total Abated'.
167
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
168
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
169
+ #
170
+ # @param int id The ID of the company that owns these notices.
171
+ # @param int companyId The ID of the company that owns these notices.
172
+ # @return FetchResult
173
+ def get_notice_finance_details(id, companyId)
174
+ path = "/api/v2/companies/#{companyId}/notices/#{id}/financedetails"
175
+
176
+ get(path)
177
+ end
178
+
179
+
180
+ # Retrieve notice responsibilities for a specific notice.
181
+ #
182
+ # This API is available by invitation only.
183
+ # 'Notice responsibilities' are are those who are responsible for the notice.
184
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
185
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
186
+ #
187
+ # @param int id The ID of the notice.
188
+ # @param int companyId The ID of the company that owns these notices.
189
+ # @return FetchResult
190
+ def get_notice_responsibilities(id, companyId)
191
+ path = "/api/v2/companies/#{companyId}/notices/#{id}/responsibilities"
192
+
193
+ get(path)
194
+ end
195
+
196
+
197
+ # Retrieve notice root causes for a specific notice.
198
+ #
199
+ # This API is available by invitation only.
200
+ # 'Notice root causes' are are those who are responsible for the notice.
201
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
202
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
203
+ #
204
+ # @param int id The ID of the notice.
205
+ # @param int companyId The ID of the company that owns these notices.
206
+ # @return FetchResult
207
+ def get_notice_root_causes(id, companyId)
208
+ path = "/api/v2/companies/#{companyId}/notices/#{id}/rootcauses"
209
+
210
+ get(path)
211
+ end
212
+
213
+
214
+ # Retrieve notices for a company.
215
+ #
216
+ # This API is available by invitation only.
217
+ # List all tax notice objects assigned to this company.
218
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
219
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
220
+ #
221
+ # Search for specific objects using the criteria in the `$filter` parameter; full documentation is available on [Filtering in REST](http://developer.avalara.com/avatax/filtering-in-rest/) .
222
+ # Paginate your results using the `$top`, `$skip`, and `$orderby` parameters.
223
+ #
224
+ # @param int companyId The ID of the company that owns these notices.
225
+ # @param string filter A filter statement to identify specific records to retrieve. For more information on filtering, see [Filtering in REST](http://developer.avalara.com/avatax/filtering-in-rest/) .
226
+ # @param string include A comma separated list of child objects to return underneath the primary object.
227
+ # @param int top If nonzero, return no more than this number of results. Used with $skip to provide pagination for large datasets.
228
+ # @param int skip If nonzero, skip this number of results before returning data. Used with $top to provide pagination for large datasets.
229
+ # @param string orderBy A comma separated list of sort statements in the format `(fieldname) [ASC|DESC]`, for example `id ASC`.
230
+ # @return FetchResult
231
+ def list_notices_by_company(companyId, options={})
232
+ path = "/api/v2/companies/#{companyId}/notices"
233
+
234
+ get(path, options)
235
+ end
236
+
237
+
238
+ # Retrieve all notices.
239
+ #
240
+ # This API is available by invitation only.
241
+ # Get multiple notice objects across all companies.
242
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
243
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
244
+ #
245
+ # Search for specific objects using the criteria in the `$filter` parameter; full documentation is available on [Filtering in REST](http://developer.avalara.com/avatax/filtering-in-rest/) .
246
+ # Paginate your results using the `$top`, `$skip`, and `$orderby` parameters.
247
+ #
248
+ # @param string filter A filter statement to identify specific records to retrieve. For more information on filtering, see [Filtering in REST](http://developer.avalara.com/avatax/filtering-in-rest/) .
249
+ # @param string include A comma separated list of child objects to return underneath the primary object.
250
+ # @param int top If nonzero, return no more than this number of results. Used with $skip to provide pagination for large datasets.
251
+ # @param int skip If nonzero, skip this number of results before returning data. Used with $top to provide pagination for large datasets.
252
+ # @param string orderBy A comma separated list of sort statements in the format `(fieldname) [ASC|DESC]`, for example `id ASC`.
253
+ # @return FetchResult
254
+ def query_notices(options={})
255
+ path = "/api/v2/notices"
256
+
257
+ get(path, options)
258
+ end
259
+
260
+
261
+ # Update a single notice.
262
+ #
263
+ # This API is available by invitation only.
264
+ # Replace the existing notice object at this URL with an updated object.
265
+ # A 'notice' represents a letter sent to a business by a tax authority regarding tax filing issues. Avalara
266
+ # Returns customers often receive support and assistance from the Compliance Notices team in handling notices received by taxing authorities.
267
+ # All data from the existing object will be replaced with data in the object you PUT.
268
+ # To set a field's value to null, you may either set its value to null or omit that field from the object you post.
269
+ #
270
+ # @param int companyId The ID of the company that this notice belongs to.
271
+ # @param int id The ID of the notice you wish to update.
272
+ # @param NoticeModel model The notice object you wish to update.
273
+ # @return NoticeModel
274
+ def update_notice(companyId, id, model)
275
+ path = "/api/v2/companies/#{companyId}/notices/#{id}"
276
+
277
+ put(path, model)
278
+ end
279
+
280
+
281
+ # Retrieve a single attachment
282
+ #
283
+ # This API is available by invitation only.
284
+ # Get the file attachment identified by this URL.
285
+ #
286
+ # @param int companyId The ID of the company for this attachment.
287
+ # @param ResourceFileUploadRequestModel model The ResourceFileId of the attachment to download.
288
+ # @return FileResult
289
+ def upload_attachment(companyId, model)
290
+ path = "/api/v2/companies/#{companyId}/notices/files/attachment"
291
+
292
+ post(path, model)
293
+ end
294
+
295
+ end
296
+ end
297
+ end