mindee 3.6.0 → 3.7.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: 28d1e6c48c575030a3c6519080f7cff23b52745c212d8db9cc43f8c800c1c3d8
4
- data.tar.gz: a96015beeeac1378f72f77bd3bcb73c3032e0946e39cc7a4519b5db3eca3e8c4
3
+ metadata.gz: 0b22c708fcdd44e0e5104e5b5e0f9cf669b7f41e46f1c627af252b86ed5b45d7
4
+ data.tar.gz: 5695f02623e644bbce0d26a3cec7096370d103b01914a97402887a87eba8cc2d
5
5
  SHA512:
6
- metadata.gz: 2ca08ce6349eb1ebeaf7cf2bbba6004ff638cfc0db480d7b41bf183f6f6a4066bd1a76a36edbf4282eb65f31c89487cad388cc1f2ea6bfa2bb6bed7ff6c6e517
7
- data.tar.gz: e18f1c1f8190c73987b036745fba0e6dca91b98ee71bc6144d8f1612be4c497cbb5f0301951b91db494c4812ca07ef6ec86fdeee17bdb3e83aacaef481b2fb3f
6
+ metadata.gz: 6b1e14cdac5f7e0a54d5326a2a9a54387568bddc7060e505468ee3f56896cba9a6d1da341d9a5918f695e99ef7aa79d95d065b43a692f8f036892fd0c4fae070
7
+ data.tar.gz: 92a95c7c1802fc6099a5ce13a869add7d7865ace5331c8d5a449ca4ed83d4e5e6573a193ed151e75f7b4ec8c2da41f30bd23cc2c71e1889d83ddf4012978123d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Mindee Ruby API Library Changelog
2
2
 
3
+ ## v3.6.2 - 2024-03-28
4
+ ### Changes
5
+ * :sparkles: update Invoice to v4.5
6
+ ### Fixes
7
+ * :bug: fix invalid error codes
8
+
9
+
10
+ ## v3.6.1 - 2024-03-07
11
+ ### Changes
12
+ * :recycle: update error handling to account for future evolutions
13
+ * :memo: update miscellaneous product documentations
14
+ * :memo: add used environment variables to readme
15
+
16
+
3
17
  ## v3.6.0 - 2024-02-21
4
18
  ### Changes
5
19
  * :sparkles: add support for resume V1
data/README.md CHANGED
@@ -1,12 +1,15 @@
1
1
  [![License: MIT](https://img.shields.io/github/license/mindee/mindee-api-ruby)](https://opensource.org/licenses/MIT) [![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/mindee/mindee-api-ruby/test.yml)](https://github.com/mindee/mindee-api-ruby) [![Gem Version](https://img.shields.io/gem/v/mindee)](https://rubygems.org/gems/mindee) [![Downloads](https://img.shields.io/gem/dt/mindee.svg)](https://rubygems.org/gems/mindee)
2
2
 
3
3
  # Mindee API Helper Library for Ruby
4
+
4
5
  Quickly and easily connect to Mindee's API services using Ruby.
5
6
 
6
7
  ## Requirements
8
+
7
9
  The following Ruby versions are tested and supported: 2.6, 2.7, 3.0, 3.1, 3.2
8
10
 
9
11
  ## Quick Start
12
+
10
13
  Here's the TL;DR of getting started.
11
14
 
12
15
  First, get an [API Key](https://developers.mindee.com/docs/create-api-key)
@@ -18,15 +21,38 @@ gem 'mindee'
18
21
  ```
19
22
 
20
23
  And then execute:
24
+
21
25
  ```sh
22
26
  bundle install
23
27
  ```
24
28
 
25
29
  Finally, Ruby away!
26
30
 
31
+ ### Environment Variables
32
+
33
+ This library offers customizable features through environment variables. While there may be instances where you need to
34
+ rely on them, it's crucial to exercise caution when modifying them to avoid unintended consequences.
35
+
36
+ If you're unsure whether you need to adjust these variables, it's advisable to refrain from doing so unless you have a
37
+ specific reason. Accidentally overwriting them can lead to unexpected behavior.
38
+
39
+ Before making any changes, we recommend reviewing the following information to understand the purpose and potential
40
+ impact of each environment variable:
41
+
42
+ * `MINDEE_API_KEY`:
43
+ * **Description**: Your personal Mindee API Key as shown on the platform. Be careful not to show this publicly!
44
+ * **Default Value**: `nil`
45
+ * `MINDEE_BASE_URL`:
46
+ * **Description**: The default base URL of the API endpoint. Use this variable to specify the root URL for API requests. Modify as needed for proxy configurations or changes in API endpoint location.
47
+ * **Default Value**: `https://api.mindee.net/v1`
48
+ * `MINDEE_REQUEST_TIMEOUT`:
49
+ * **Description**: The default timeout for HTTP requests (in seconds).
50
+ * **Default Value**: `120`
51
+
27
52
  ### Loading a File and Parsing It
28
53
 
29
54
  #### Global Documents
55
+
30
56
  ```ruby
31
57
  require 'mindee'
32
58
 
@@ -47,26 +73,31 @@ puts result.document
47
73
  **Note:** Files can also be loaded from:
48
74
 
49
75
  A URL (`https`):
76
+
50
77
  ```rb
51
78
  input_source = mindee_client.source_from_url("https://my-url")
52
79
  ```
53
80
 
54
81
  A bytes input stream:
82
+
55
83
  ```rb
56
84
  input_source = mindee_client.source_from_bytes('/path/to/the/file.ext', "name-of-my-file.ext")
57
85
  ```
58
86
 
59
87
  A base64 encoded string:
88
+
60
89
  ```rb
61
90
  input_source = mindee_client.source_from_b64string('/path/to/the/file.ext', "name-of-my-file.ext")
62
91
  ```
63
92
 
64
93
  A ruby `file` object:
94
+
65
95
  ```rb
66
96
  input_source = mindee_client.source_from_file(input_file, "name-of-my-file.ext")
67
97
  ```
68
98
 
69
99
  #### Region-Specific Documents
100
+
70
101
  ```ruby
71
102
  require 'mindee'
72
103
 
@@ -86,6 +117,7 @@ puts result.document
86
117
  ```
87
118
 
88
119
  ### Custom Document (API Builder)
120
+
89
121
  ```ruby
90
122
  require 'mindee'
91
123
 
@@ -119,17 +151,19 @@ end
119
151
  ## CLI Tool
120
152
 
121
153
  A command-line interface tool is available to quickly test documents:
154
+
122
155
  ```sh
123
156
  ruby ./bin/mindee.rb invoice path/to/your/file.ext
124
157
  ```
125
158
 
126
-
127
159
  Using the ruby bundler:
160
+
128
161
  ```sh
129
162
  bundle exec ruby ./bin/mindee.rb invoice path/to/your/file.ext
130
163
  ```
131
164
 
132
165
  ## Further Reading
166
+
133
167
  There's more to it than that for those that need more features, or want to
134
168
  customize the experience.
135
169
 
@@ -157,15 +191,15 @@ customize the experience.
157
191
  * [Invoice Splitter API Ruby](https://developers.mindee.com/docs/invoice-splitter-api-ruby)
158
192
  * [Multi Receipts Detector API Ruby](https://developers.mindee.com/docs/multi-receipts-detector-api-ruby)
159
193
 
160
-
161
194
  You can also take a look at the
162
195
  [Reference Documentation](https://mindee.github.io/mindee-api-ruby/).
163
196
 
164
-
165
197
  ## License
198
+
166
199
  Copyright © Mindee, SA
167
200
 
168
201
  Available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
169
202
 
170
203
  ## Questions?
204
+
171
205
  [Join our Slack](https://join.slack.com/t/mindee-community/shared_invite/zt-2d0ds7dtz-DPAF81ZqTy20chsYpQBW5g)
@@ -31,6 +31,37 @@ puts result.document
31
31
 
32
32
  **Output (RST):**
33
33
  ```rst
34
+ ########
35
+ Document
36
+ ########
37
+ :Mindee ID: cfa20a58-20cf-43b6-8cec-9505fa69d1c2
38
+ :Filename: default_sample.jpg
39
+
40
+ Inference
41
+ #########
42
+ :Product: mindee/international_id v2.0
43
+ :Rotation applied: No
44
+
45
+ Prediction
46
+ ==========
47
+ :Document Type: IDENTIFICATION_CARD
48
+ :Document Number: 12345678A
49
+ :Surnames: MUESTRA
50
+ MUESTRA
51
+ :Given Names: CARMEN
52
+ :Sex: F
53
+ :Birth Date: 1980-01-01
54
+ :Birth Place: CAMPO DE CRIPTANA CIUDAD REAL ESPANA
55
+ :Nationality: ESP
56
+ :Personal Number: BAB1834284<44282767Q0
57
+ :Country of Issue: ESP
58
+ :State of Issue: MADRID
59
+ :Issue Date:
60
+ :Expiration Date: 2030-01-01
61
+ :Address: C/REAL N13, 1 DCHA COLLADO VILLALBA MADRID MADRID MADRID
62
+ :MRZ Line 1: IDESPBAB1834284<44282767Q0<<<<
63
+ :MRZ Line 2: 8001010F1301017ESP<<<<<<<<<<<3
64
+ :MRZ Line 3: MUESTRA<MUESTRA<<CARMEN<<<<<<<
34
65
  ```
35
66
 
36
67
  # Field Types
data/docs/invoices_v4.md CHANGED
@@ -34,12 +34,12 @@ puts result.document
34
34
  ########
35
35
  Document
36
36
  ########
37
- :Mindee ID: 80f2328c-58a5-486a-9599-eb2d738680f0
37
+ :Mindee ID: a9062dd1-0d34-42ab-9505-0481a8545106
38
38
  :Filename: default_sample.jpg
39
39
 
40
40
  Inference
41
41
  #########
42
- :Product: mindee/invoices v4.4
42
+ :Product: mindee/invoices v4.5
43
43
  :Rotation applied: Yes
44
44
 
45
45
  Prediction
@@ -65,6 +65,8 @@ Prediction
65
65
  :Customer Name: JIRO DOI
66
66
  :Customer Company Registrations:
67
67
  :Customer Address: 1954 Bloor Street West Toronto, ON, M6P 3K9 Canada
68
+ :Shipping Address:
69
+ :Billing Address: 1954 Bloor Street West Toronto, ON, M6P 3K9 Canada
68
70
  :Document Type: INVOICE
69
71
  :Line Items:
70
72
  +--------------------------------------+--------------+----------+------------+--------------+--------------+------------+
@@ -103,6 +105,8 @@ Page 0
103
105
  :Customer Name: JIRO DOI
104
106
  :Customer Company Registrations:
105
107
  :Customer Address: 1954 Bloor Street West Toronto, ON, M6P 3K9 Canada
108
+ :Shipping Address:
109
+ :Billing Address: 1954 Bloor Street West Toronto, ON, M6P 3K9 Canada
106
110
  :Document Type: INVOICE
107
111
  :Line Items:
108
112
  +--------------------------------------+--------------+----------+------------+--------------+--------------+------------+
@@ -205,6 +209,13 @@ A `InvoiceV4LineItem` implements the following attributes:
205
209
  # Attributes
206
210
  The following fields are extracted for Invoice V4:
207
211
 
212
+ ## Billing Address
213
+ **billing_address** ([StringField](#string-field)): The customer's address used for billing.
214
+
215
+ ```rb
216
+ puts result.document.inference.prediction.billing_address.value
217
+ ```
218
+
208
219
  ## Customer Address
209
220
  **customer_address** ([StringField](#string-field)): The address of the customer.
210
221
 
@@ -281,6 +292,13 @@ for reference_numbers_elem in result.document.inference.prediction.reference_num
281
292
  end
282
293
  ```
283
294
 
295
+ ## Shipping Address
296
+ **shipping_address** ([StringField](#string-field)): Customer's delivery address.
297
+
298
+ ```rb
299
+ puts result.document.inference.prediction.shipping_address.value
300
+ ```
301
+
284
302
  ## Supplier Address
285
303
  **supplier_address** ([StringField](#string-field)): The address of the supplier or merchant.
286
304
 
data/lib/mindee/client.rb CHANGED
@@ -138,9 +138,9 @@ module Mindee
138
138
  # * `:on_min_pages` Apply the operation only if document has at least this many pages.
139
139
  # @param cropper [Boolean, nil] Whether to include cropper results for each page.
140
140
  # This performs a cropping operation on the server and will increase response time.
141
- # @param initial_delay_sec [Integer, Float, nil] initial delay before polling. Defaults to 4.
142
- # @param delay_sec [Integer, Float, nil] delay between polling attempts. Defaults to 2.
143
- # @param max_retries [Integer, nil] maximum amount of retries. Defaults to 60.
141
+ # @param initial_delay_sec [Integer, Float] initial delay before polling. Defaults to 4.
142
+ # @param delay_sec [Integer, Float] delay between polling attempts. Defaults to 2.
143
+ # @param max_retries [Integer] maximum amount of retries. Defaults to 60.
144
144
  # @return [Mindee::Parsing::Common::ApiResponse]
145
145
  def enqueue_and_parse(
146
146
  input_source,
@@ -167,7 +167,7 @@ module Mindee
167
167
  polling_attempts = 1
168
168
  job_id = enqueue_res.job.id
169
169
  queue_res = parse_queued(job_id, product_class, endpoint: endpoint)
170
- while (queue_res.job.status != Mindee::Parsing::Common::JobStatus::COMPLETED) && (polling_attempts < max_retries)
170
+ while queue_res.job.status != Mindee::Parsing::Common::JobStatus::COMPLETED && polling_attempts < max_retries
171
171
  sleep(delay_sec)
172
172
  queue_res = parse_queued(job_id, product_class, endpoint: endpoint)
173
173
  polling_attempts += 1
@@ -4,6 +4,7 @@ require 'json'
4
4
  require 'net/http'
5
5
  require_relative 'error'
6
6
  require_relative '../version'
7
+ require_relative 'response_validation'
7
8
 
8
9
  module Mindee
9
10
  module HTTP
@@ -49,14 +50,15 @@ module Mindee
49
50
  # @param all_words [Boolean] Whether the full word extraction needs to be performed
50
51
  # @param close_file [Boolean] Whether the file will be closed after reading
51
52
  # @param cropper [Boolean] Whether a cropping operation will be applied
52
- # @return [Hash]
53
+ # @return [Array]
53
54
  def predict(input_source, all_words, close_file, cropper)
54
55
  check_api_key
55
56
  response = predict_req_post(input_source, all_words: all_words, close_file: close_file, cropper: cropper)
56
57
  hashed_response = JSON.parse(response.body, object_class: Hash)
57
- return [hashed_response, response.body] if (200..299).include?(response.code.to_i)
58
+ return [hashed_response, response.body] if ResponseValidation.valid_sync_response?(response)
58
59
 
59
- error = Error.handle_error!(@url_name, hashed_response, response.code.to_i)
60
+ ResponseValidation.clean_request!(response)
61
+ error = Error.handle_error(@url_name, response)
60
62
  raise error
61
63
  end
62
64
 
@@ -65,27 +67,29 @@ module Mindee
65
67
  # @param all_words [Boolean] Whether the full word extraction needs to be performed
66
68
  # @param close_file [Boolean] Whether the file will be closed after reading
67
69
  # @param cropper [Boolean] Whether a cropping operation will be applied
68
- # @return [Hash]
70
+ # @return [Array]
69
71
  def predict_async(input_source, all_words, close_file, cropper)
70
72
  check_api_key
71
73
  response = document_queue_req_get(input_source, all_words, close_file, cropper)
72
74
  hashed_response = JSON.parse(response.body, object_class: Hash)
73
- return [hashed_response, response.body] if (200..299).include?(response.code.to_i)
75
+ return [hashed_response, response.body] if ResponseValidation.valid_async_response?(response)
74
76
 
75
- error = Error.handle_error!(@url_name, hashed_response, response.code.to_i)
77
+ ResponseValidation.clean_request!(response)
78
+ error = Error.handle_error(@url_name, response)
76
79
  raise error
77
80
  end
78
81
 
79
82
  # Calls the parsed async doc.
80
83
  # @param job_id [String]
81
- # @return [Hash]
84
+ # @return [Array]
82
85
  def parse_async(job_id)
83
86
  check_api_key
84
87
  response = document_queue_req(job_id)
85
88
  hashed_response = JSON.parse(response.body, object_class: Hash)
86
- return [hashed_response, response.body] if (200..299).include?(response.code.to_i)
89
+ return [hashed_response, response.body] if ResponseValidation.valid_async_response?(response)
87
90
 
88
- error = Error.handle_error!(@url_name, hashed_response, response.code.to_i)
91
+ ResponseValidation.clean_request!(response)
92
+ error = Error.handle_error(@url_name, response)
89
93
  raise error
90
94
  end
91
95
 
@@ -95,7 +99,7 @@ module Mindee
95
99
  # @param all_words [Boolean] Whether the full word extraction needs to be performed
96
100
  # @param close_file [Boolean] Whether the file will be closed after reading
97
101
  # @param cropper [Boolean] Whether a cropping operation will be applied
98
- # @return [Net::HTTP, nil]
102
+ # @return [Net::HTTPResponse, nil]
99
103
  def predict_req_post(input_source, all_words: false, close_file: true, cropper: false)
100
104
  uri = URI("#{@url_root}/predict")
101
105
 
@@ -116,17 +120,18 @@ module Mindee
116
120
  form_data.push ['include_mvision', 'true'] if all_words
117
121
 
118
122
  req.set_form(form_data, 'multipart/form-data')
119
-
123
+ response = nil
120
124
  Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, read_timeout: @request_timeout) do |http|
121
- http.request(req)
125
+ response = http.request(req)
122
126
  end
127
+ response
123
128
  end
124
129
 
125
130
  # @param input_source [Mindee::Input::Source::LocalInputSource, Mindee::Input::Source::UrlInputSource]
126
131
  # @param all_words [Boolean] Whether the full word extraction needs to be performed
127
132
  # @param close_file [Boolean] Whether the file will be closed after reading
128
133
  # @param cropper [Boolean] Whether a cropping operation will be applied
129
- # @return [Net::HTTPResponse]
134
+ # @return [Net::HTTPResponse, nil]
130
135
  def document_queue_req_get(input_source, all_words, close_file, cropper)
131
136
  uri = URI("#{@url_root}/predict_async")
132
137
 
@@ -148,13 +153,15 @@ module Mindee
148
153
 
149
154
  req.set_form(form_data, 'multipart/form-data')
150
155
 
156
+ response = nil
151
157
  Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, read_timeout: @request_timeout) do |http|
152
- http.request(req)
158
+ response = http.request(req)
153
159
  end
160
+ response
154
161
  end
155
162
 
156
163
  # @param job_id [String]
157
- # @return [Net::HTTPResponse]
164
+ # @return [Net::HTTPResponse, nil]
158
165
  def document_queue_req(job_id)
159
166
  uri = URI("#{@url_root}/documents/queue/#{job_id}")
160
167
 
@@ -171,8 +178,8 @@ module Mindee
171
178
 
172
179
  if response.code.to_i > 299 && response.code.to_i < 400
173
180
  req = Net::HTTP::Get.new(response['location'], headers)
174
- response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, read_timeout: @request_timeout) do |http|
175
- http.request(req)
181
+ Net::HTTP.start(uri.hostname, uri.port, use_ssl: true, read_timeout: @request_timeout) do |http|
182
+ response = http.request(req)
176
183
  end
177
184
  end
178
185
  response
@@ -1,15 +1,29 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+
3
5
  module Mindee
4
6
  module HTTP
5
7
  # Mindee HTTP error module.
6
8
  module Error
7
9
  module_function
8
10
 
11
+ # Extracts the HTTP error from the response hash, or the job error if there is one.
12
+ # @param response [Hash] dictionary response retrieved by the server
13
+ def extract_error(response)
14
+ return unless response.respond_to?(:each_pair)
15
+
16
+ if !response.dig('api_request', 'error').empty?
17
+ response.dig('api_request', 'error')
18
+ elsif !response.dig('job', 'error').empty?
19
+ response.dig('job', 'error')
20
+ end
21
+ end
22
+
9
23
  # Creates an error object based on what's retrieved from a request.
10
24
  # @param response [Hash] dictionary response retrieved by the server
11
25
  def create_error_obj(response)
12
- error_obj = response.respond_to?(:each_pair) ? response.dig('api_request', 'error') : nil
26
+ error_obj = extract_error(response)
13
27
  if error_obj.nil?
14
28
  error_obj = if response.include?('Maximum pdf pages')
15
29
  {
@@ -50,15 +64,20 @@ module Mindee
50
64
  end
51
65
 
52
66
  end
53
- error_obj
67
+ error_obj.nil? ? {} : error_obj
54
68
  end
55
69
 
56
70
  # Creates an appropriate HTTP error exception, based on retrieved http error code
57
71
  # @param url [String] the url of the product
58
72
  # @param response [Hash] dictionary response retrieved by the server
59
- # @param code [Integer] http error code of the response
60
- def handle_error!(url, response, code)
61
- error_obj = create_error_obj(response)
73
+ def handle_error(url, response)
74
+ code = response.code.to_i
75
+ begin
76
+ parsed_hash = JSON.parse(response.body, object_class: Hash)
77
+ rescue JSON::ParserError
78
+ parsed_hash = response.body.to_s
79
+ end
80
+ error_obj = create_error_obj(parsed_hash)
62
81
  case code
63
82
  when 400..499
64
83
  MindeeHttpClientError.new(error_obj, url, code)
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'net/http'
5
+
6
+ module Mindee
7
+ module HTTP
8
+ # Module dedicated to the validation & sanitizing of HTTP responses.
9
+ module ResponseValidation
10
+ # Checks if the synchronous response is valid. Returns True if the response is valid.
11
+ # @param [Net::HTTPResponse] response
12
+ # @return [Boolean]
13
+ def self.valid_sync_response?(response)
14
+ return false unless (200..399).cover?(response.code.to_i)
15
+
16
+ begin
17
+ JSON.parse(response.body, object_class: Hash)
18
+ rescue StandardError
19
+ return false
20
+ end
21
+ true
22
+ end
23
+
24
+ # Checks if the asynchronous response is valid. Also checks if it is a valid synchronous response.
25
+ # Returns true if the response is valid.
26
+ # @param [Net::HTTPResponse] response
27
+ # @return [Boolean]
28
+ def self.valid_async_response?(response)
29
+ return false unless valid_sync_response?(response)
30
+
31
+ return false unless (200..302).cover?(response.code.to_i)
32
+
33
+ hashed_response = JSON.parse(response.body, object_class: Hash)
34
+
35
+ return false if hashed_response.dig('job', 'status') == Mindee::Parsing::Common::JobStatus::FAILURE
36
+
37
+ return false if hashed_response.dig('job', 'error') && !hashed_response.dig('job', 'error').empty?
38
+
39
+ true
40
+ end
41
+
42
+ # Checks and correct the response object depending on the possible kinds of returns.
43
+ # @param response [Net::HTTPResponse]
44
+ def self.clean_request!(response)
45
+ return response if (response.code.to_i < 200) || (response.code.to_i > 302)
46
+
47
+ return response if response.body.empty?
48
+
49
+ hashed_response = JSON.parse(response.body, object_class: Hash)
50
+ if hashed_response.dig('api_request', 'status_code').to_i > 399
51
+ response.instance_variable_set(:@code, hashed_response['api_request']['status_code'].to_s)
52
+ end
53
+
54
+ return if !hashed_response.dig('job', 'error').empty? &&
55
+ (hashed_response.dig('job', 'status') != Mindee::Parsing::Common::JobStatus::FAILURE.to_s)
56
+
57
+ response.instance_variable_set(:@code, '500')
58
+ end
59
+ end
60
+ end
61
+ end
@@ -14,6 +14,8 @@ module Mindee
14
14
  PROCESSING = :processing
15
15
  # Document parsing is complete.
16
16
  COMPLETED = :completed
17
+ # Job failed
18
+ FAILURE = :failed
17
19
  end
18
20
 
19
21
  # Potential values for requests.
@@ -36,10 +38,13 @@ module Mindee
36
38
  attr_reader :status
37
39
  # @return [Integer, nil]
38
40
  attr_reader :millisecs_taken
41
+ # @return [Hash, nil]
42
+ attr_reader :error
39
43
 
40
44
  # @param http_response [Hash]
41
45
  def initialize(http_response)
42
46
  @id = http_response['id']
47
+ @error = http_response['error']
43
48
  @issued_at = Time.iso8601(http_response['issued_at'])
44
49
  if http_response.key?('available_at') && !http_response['available_at'].nil?
45
50
  @available_at = Time.iso8601(http_response['available_at'])
@@ -108,7 +113,7 @@ module Mindee
108
113
  end
109
114
  if http_response.key?('document') &&
110
115
  (!http_response.key?('job') ||
111
- http_response['job']['status'] == 'completed') &&
116
+ http_response['job']['status'] == 'completed') &&
112
117
  @api_request.status == RequestStatus::SUCCESS
113
118
  @document = Mindee::Parsing::Common::Document.new(product_class, http_response['document'])
114
119
  end
@@ -9,6 +9,9 @@ module Mindee
9
9
  # Invoice V4 document prediction.
10
10
  class InvoiceV4Document < Mindee::Parsing::Common::Prediction
11
11
  include Mindee::Parsing::Standard
12
+ # The customer's address used for billing.
13
+ # @return [Mindee::Parsing::Standard::StringField]
14
+ attr_reader :billing_address
12
15
  # The address of the customer.
13
16
  # @return [Mindee::Parsing::Standard::StringField]
14
17
  attr_reader :customer_address
@@ -39,6 +42,9 @@ module Mindee
39
42
  # List of Reference numbers, including PO number.
40
43
  # @return [Array<Mindee::Parsing::Standard::StringField>]
41
44
  attr_reader :reference_numbers
45
+ # Customer's delivery address.
46
+ # @return [Mindee::Parsing::Standard::StringField]
47
+ attr_reader :shipping_address
42
48
  # The address of the supplier or merchant.
43
49
  # @return [Mindee::Parsing::Standard::StringField]
44
50
  attr_reader :supplier_address
@@ -68,6 +74,7 @@ module Mindee
68
74
  # @param page_id [Integer, nil]
69
75
  def initialize(prediction, page_id)
70
76
  super()
77
+ @billing_address = StringField.new(prediction['billing_address'], page_id)
71
78
  @customer_address = StringField.new(prediction['customer_address'], page_id)
72
79
  @customer_company_registrations = []
73
80
  prediction['customer_company_registrations'].each do |item|
@@ -87,6 +94,7 @@ module Mindee
87
94
  prediction['reference_numbers'].each do |item|
88
95
  @reference_numbers.push(StringField.new(item, page_id))
89
96
  end
97
+ @shipping_address = StringField.new(prediction['shipping_address'], page_id)
90
98
  @supplier_address = StringField.new(prediction['supplier_address'], page_id)
91
99
  @supplier_company_registrations = []
92
100
  prediction['supplier_company_registrations'].each do |item|
@@ -127,6 +135,8 @@ module Mindee
127
135
  out_str << "\n:Customer Name: #{@customer_name}".rstrip
128
136
  out_str << "\n:Customer Company Registrations: #{customer_company_registrations}".rstrip
129
137
  out_str << "\n:Customer Address: #{@customer_address}".rstrip
138
+ out_str << "\n:Shipping Address: #{@shipping_address}".rstrip
139
+ out_str << "\n:Billing Address: #{@billing_address}".rstrip
130
140
  out_str << "\n:Document Type: #{@document_type}".rstrip
131
141
  out_str << "\n:Line Items:"
132
142
  out_str << line_items
@@ -3,7 +3,7 @@
3
3
  # Mindee
4
4
  module Mindee
5
5
  # Current version.
6
- VERSION = '3.6.0'
6
+ VERSION = '3.7.0'
7
7
 
8
8
  # Finds and return the current platform.
9
9
  # @return [String]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mindee
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.0
4
+ version: 3.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mindee, SA
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-02-21 00:00:00.000000000 Z
11
+ date: 2024-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: marcel
@@ -181,6 +181,7 @@ files:
181
181
  - lib/mindee/http/.rubocop.yml
182
182
  - lib/mindee/http/endpoint.rb
183
183
  - lib/mindee/http/error.rb
184
+ - lib/mindee/http/response_validation.rb
184
185
  - lib/mindee/input.rb
185
186
  - lib/mindee/input/sources.rb
186
187
  - lib/mindee/parsing.rb