mindee 1.0.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.
- checksums.yaml +7 -0
 - data/.gitattributes +14 -0
 - data/.gitignore +69 -0
 - data/.rubocop.yml +41 -0
 - data/CHANGELOG.md +4 -0
 - data/CODE_OF_CONDUCT.md +129 -0
 - data/Gemfile +13 -0
 - data/LICENSE +21 -0
 - data/README.md +66 -0
 - data/Rakefile +5 -0
 - data/bin/console +14 -0
 - data/bin/mindee.rb +137 -0
 - data/lib/mindee/client.rb +171 -0
 - data/lib/mindee/document_config.rb +200 -0
 - data/lib/mindee/documents/base.rb +35 -0
 - data/lib/mindee/documents/custom.rb +44 -0
 - data/lib/mindee/documents/financial_doc.rb +135 -0
 - data/lib/mindee/documents/invoice.rb +162 -0
 - data/lib/mindee/documents/passport.rb +163 -0
 - data/lib/mindee/documents/receipt.rb +109 -0
 - data/lib/mindee/documents.rb +7 -0
 - data/lib/mindee/endpoint.rb +105 -0
 - data/lib/mindee/fields/amount.rb +17 -0
 - data/lib/mindee/fields/base.rb +61 -0
 - data/lib/mindee/fields/company_registration.rb +17 -0
 - data/lib/mindee/fields/datefield.rb +30 -0
 - data/lib/mindee/fields/list_field.rb +71 -0
 - data/lib/mindee/fields/locale.rb +45 -0
 - data/lib/mindee/fields/orientation.rb +26 -0
 - data/lib/mindee/fields/payment_details.rb +33 -0
 - data/lib/mindee/fields/tax.rb +35 -0
 - data/lib/mindee/fields.rb +11 -0
 - data/lib/mindee/geometry.rb +21 -0
 - data/lib/mindee/inputs.rb +153 -0
 - data/lib/mindee/response.rb +27 -0
 - data/lib/mindee/version.rb +21 -0
 - data/lib/mindee.rb +8 -0
 - data/mindee.gemspec +34 -0
 - metadata +128 -0
 
| 
         @@ -0,0 +1,162 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative '../fields'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'base'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Mindee
         
     | 
| 
      
 7 
     | 
    
         
            +
              # Invoice document.
         
     | 
| 
      
 8 
     | 
    
         
            +
              class Invoice < Document
         
     | 
| 
      
 9 
     | 
    
         
            +
                # @return [Mindee::Locale]
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader :locale
         
     | 
| 
      
 11 
     | 
    
         
            +
                # @return [Mindee::Amount]
         
     | 
| 
      
 12 
     | 
    
         
            +
                attr_reader :total_incl
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @return [Mindee::Amount]
         
     | 
| 
      
 14 
     | 
    
         
            +
                attr_reader :total_excl
         
     | 
| 
      
 15 
     | 
    
         
            +
                # @return [Mindee::Amount]
         
     | 
| 
      
 16 
     | 
    
         
            +
                attr_reader :total_tax
         
     | 
| 
      
 17 
     | 
    
         
            +
                # @return [Mindee::DateField]
         
     | 
| 
      
 18 
     | 
    
         
            +
                attr_reader :date
         
     | 
| 
      
 19 
     | 
    
         
            +
                # @return [Mindee::Field]
         
     | 
| 
      
 20 
     | 
    
         
            +
                attr_reader :invoice_number
         
     | 
| 
      
 21 
     | 
    
         
            +
                # @return [Mindee::DateField]
         
     | 
| 
      
 22 
     | 
    
         
            +
                attr_reader :due_date
         
     | 
| 
      
 23 
     | 
    
         
            +
                # @return [Array<Mindee::TaxField>]
         
     | 
| 
      
 24 
     | 
    
         
            +
                attr_reader :taxes
         
     | 
| 
      
 25 
     | 
    
         
            +
                # @return [Array<Mindee::CompanyRegistration>]
         
     | 
| 
      
 26 
     | 
    
         
            +
                attr_reader :customer_company_registration
         
     | 
| 
      
 27 
     | 
    
         
            +
                # @return [Array<Mindee::PaymentDetails>]
         
     | 
| 
      
 28 
     | 
    
         
            +
                attr_reader :payment_details
         
     | 
| 
      
 29 
     | 
    
         
            +
                # @return [Array<Mindee::CompanyRegistration>]
         
     | 
| 
      
 30 
     | 
    
         
            +
                attr_reader :company_registration
         
     | 
| 
      
 31 
     | 
    
         
            +
                # @return [Mindee::Field]
         
     | 
| 
      
 32 
     | 
    
         
            +
                attr_reader :customer_name
         
     | 
| 
      
 33 
     | 
    
         
            +
                # @return [Mindee::Field]
         
     | 
| 
      
 34 
     | 
    
         
            +
                attr_reader :supplier
         
     | 
| 
      
 35 
     | 
    
         
            +
                # @return [Mindee::Field]
         
     | 
| 
      
 36 
     | 
    
         
            +
                attr_reader :supplier_address
         
     | 
| 
      
 37 
     | 
    
         
            +
                # @return [Mindee::Field]
         
     | 
| 
      
 38 
     | 
    
         
            +
                attr_reader :customer_address
         
     | 
| 
      
 39 
     | 
    
         
            +
                # @return [Mindee::Orientation]
         
     | 
| 
      
 40 
     | 
    
         
            +
                attr_reader :orientation
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                # @param prediction [Hash]
         
     | 
| 
      
 43 
     | 
    
         
            +
                # @param input_file [Mindee::InputDocument, nil]
         
     | 
| 
      
 44 
     | 
    
         
            +
                # @param page_id [Integer, nil]
         
     | 
| 
      
 45 
     | 
    
         
            +
                def initialize(prediction, input_file: nil, page_id: nil)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  super('invoice', input_file: input_file)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @orientation = Orientation.new(prediction['orientation'], page_id) if page_id
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @locale = Locale.new(prediction['locale'])
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @total_incl = Amount.new(prediction['total_incl'], page_id)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @total_excl = Amount.new(prediction['total_excl'], page_id)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @customer_address = Field.new(prediction['customer_address'], page_id)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  @customer_name = Field.new(prediction['customer'], page_id)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @date = DateField.new(prediction['date'], page_id)
         
     | 
| 
      
 54 
     | 
    
         
            +
                  @due_date = DateField.new(prediction['due_date'], page_id)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @invoice_number = Field.new(prediction['invoice_number'], page_id)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  @supplier = Field.new(prediction['supplier'], page_id)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  @supplier_address = Field.new(prediction['supplier_address'], page_id)
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                  @customer_company_registration = []
         
     | 
| 
      
 60 
     | 
    
         
            +
                  prediction['customer_company_registration'].each do |item|
         
     | 
| 
      
 61 
     | 
    
         
            +
                    @customer_company_registration.push(CompanyRegistration.new(item, page_id))
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
      
 63 
     | 
    
         
            +
                  @taxes = []
         
     | 
| 
      
 64 
     | 
    
         
            +
                  prediction['taxes'].each do |item|
         
     | 
| 
      
 65 
     | 
    
         
            +
                    @taxes.push(TaxField.new(item, page_id))
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
                  @payment_details = []
         
     | 
| 
      
 68 
     | 
    
         
            +
                  prediction['payment_details'].each do |item|
         
     | 
| 
      
 69 
     | 
    
         
            +
                    @payment_details.push(PaymentDetails.new(item, page_id))
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                  @company_registration = []
         
     | 
| 
      
 72 
     | 
    
         
            +
                  prediction['company_registration'].each do |item|
         
     | 
| 
      
 73 
     | 
    
         
            +
                    @company_registration.push(CompanyRegistration.new(item, page_id))
         
     | 
| 
      
 74 
     | 
    
         
            +
                  end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  @total_tax = Amount.new(
         
     | 
| 
      
 77 
     | 
    
         
            +
                    { value: nil, confidence: 0.0 }, page_id
         
     | 
| 
      
 78 
     | 
    
         
            +
                  )
         
     | 
| 
      
 79 
     | 
    
         
            +
                  reconstruct(page_id)
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 83 
     | 
    
         
            +
                  customer_company_registration = @customer_company_registration.map(&:value).join('; ')
         
     | 
| 
      
 84 
     | 
    
         
            +
                  payment_details = @payment_details.map(&:to_s).join("\n                 ")
         
     | 
| 
      
 85 
     | 
    
         
            +
                  company_registration = @company_registration.map(&:to_s).join('; ')
         
     | 
| 
      
 86 
     | 
    
         
            +
                  taxes = @taxes.join("\n       ")
         
     | 
| 
      
 87 
     | 
    
         
            +
                  out_str = String.new
         
     | 
| 
      
 88 
     | 
    
         
            +
                  out_str << '-----Invoice data-----'
         
     | 
| 
      
 89 
     | 
    
         
            +
                  out_str << "\nFilename: #{@filename}".rstrip
         
     | 
| 
      
 90 
     | 
    
         
            +
                  out_str << "\nInvoice number: #{@invoice_number}".rstrip
         
     | 
| 
      
 91 
     | 
    
         
            +
                  out_str << "\nTotal amount including taxes: #{@total_incl}".rstrip
         
     | 
| 
      
 92 
     | 
    
         
            +
                  out_str << "\nTotal amount excluding taxes: #{@total_excl}".rstrip
         
     | 
| 
      
 93 
     | 
    
         
            +
                  out_str << "\nInvoice date: #{@date}".rstrip
         
     | 
| 
      
 94 
     | 
    
         
            +
                  out_str << "\nInvoice due date: #{@due_date}".rstrip
         
     | 
| 
      
 95 
     | 
    
         
            +
                  out_str << "\nSupplier name: #{@supplier}".rstrip
         
     | 
| 
      
 96 
     | 
    
         
            +
                  out_str << "\nSupplier address: #{@supplier_address}".rstrip
         
     | 
| 
      
 97 
     | 
    
         
            +
                  out_str << "\nCustomer name: #{@customer_name}".rstrip
         
     | 
| 
      
 98 
     | 
    
         
            +
                  out_str << "\nCustomer company registration: #{customer_company_registration}".rstrip
         
     | 
| 
      
 99 
     | 
    
         
            +
                  out_str << "\nCustomer address: #{@customer_address}".rstrip
         
     | 
| 
      
 100 
     | 
    
         
            +
                  out_str << "\nPayment details: #{payment_details}".rstrip
         
     | 
| 
      
 101 
     | 
    
         
            +
                  out_str << "\nCompany numbers: #{company_registration}".rstrip
         
     | 
| 
      
 102 
     | 
    
         
            +
                  out_str << "\nTaxes: #{taxes}".rstrip
         
     | 
| 
      
 103 
     | 
    
         
            +
                  out_str << "\nTotal taxes: #{@total_tax}".rstrip
         
     | 
| 
      
 104 
     | 
    
         
            +
                  out_str << "\nLocale: #{@locale}".rstrip
         
     | 
| 
      
 105 
     | 
    
         
            +
                  out_str << "\n----------------------"
         
     | 
| 
      
 106 
     | 
    
         
            +
                  out_str
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                private
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                def reconstruct(page_id)
         
     | 
| 
      
 112 
     | 
    
         
            +
                  construct_total_tax_from_taxes(page_id)
         
     | 
| 
      
 113 
     | 
    
         
            +
                  construct_total_excl_from_tcc_and_taxes(page_id)
         
     | 
| 
      
 114 
     | 
    
         
            +
                  construct_total_incl_from_taxes_plus_excl(page_id)
         
     | 
| 
      
 115 
     | 
    
         
            +
                  construct_total_tax_from_totals(page_id)
         
     | 
| 
      
 116 
     | 
    
         
            +
                end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                def construct_total_excl_from_tcc_and_taxes(page_id)
         
     | 
| 
      
 119 
     | 
    
         
            +
                  return if @total_incl.value.nil? || taxes.empty? || !@total_excl.value.nil?
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                  total_excl = {
         
     | 
| 
      
 122 
     | 
    
         
            +
                    'value' => @total_incl.value - @taxes.map(&:value).sum,
         
     | 
| 
      
 123 
     | 
    
         
            +
                    'confidence' => Field.array_confidence(@taxes) * @total_incl.confidence,
         
     | 
| 
      
 124 
     | 
    
         
            +
                  }
         
     | 
| 
      
 125 
     | 
    
         
            +
                  @total_excl = Amount.new(total_excl, page_id, reconstructed: true)
         
     | 
| 
      
 126 
     | 
    
         
            +
                end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                def construct_total_incl_from_taxes_plus_excl(page_id)
         
     | 
| 
      
 129 
     | 
    
         
            +
                  return if @total_excl.value.nil? || @taxes.empty? || !@total_incl.value.nil?
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                  total_incl = {
         
     | 
| 
      
 132 
     | 
    
         
            +
                    'value' => @taxes.map(&:value).sum + @total_excl.value,
         
     | 
| 
      
 133 
     | 
    
         
            +
                    'confidence' => Field.array_confidence(@taxes) * @total_excl.confidence,
         
     | 
| 
      
 134 
     | 
    
         
            +
                  }
         
     | 
| 
      
 135 
     | 
    
         
            +
                  @total_incl = Amount.new(total_incl, page_id, reconstructed: true)
         
     | 
| 
      
 136 
     | 
    
         
            +
                end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
                def construct_total_tax_from_taxes(page_id)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  return if @taxes.empty?
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                  total_tax = {
         
     | 
| 
      
 142 
     | 
    
         
            +
                    'value' => @taxes.map(&:value).sum,
         
     | 
| 
      
 143 
     | 
    
         
            +
                    'confidence' => Field.array_confidence(@taxes),
         
     | 
| 
      
 144 
     | 
    
         
            +
                  }
         
     | 
| 
      
 145 
     | 
    
         
            +
                  return unless total_tax['value'].positive?
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                  @total_tax = Amount.new(total_tax, page_id, reconstructed: true)
         
     | 
| 
      
 148 
     | 
    
         
            +
                end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                def construct_total_tax_from_totals(page_id)
         
     | 
| 
      
 151 
     | 
    
         
            +
                  return if !@total_tax.value.nil? || @total_incl.value.nil? || @total_excl.value.nil?
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                  total_tax = {
         
     | 
| 
      
 154 
     | 
    
         
            +
                    'value' => @total_incl.value - @total_excl.value,
         
     | 
| 
      
 155 
     | 
    
         
            +
                    'confidence' => Field.array_confidence(@taxes),
         
     | 
| 
      
 156 
     | 
    
         
            +
                  }
         
     | 
| 
      
 157 
     | 
    
         
            +
                  return unless total_tax['value'] >= 0
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                  @total_tax = Amount.new(total_tax, page_id, reconstructed: true)
         
     | 
| 
      
 160 
     | 
    
         
            +
                end
         
     | 
| 
      
 161 
     | 
    
         
            +
              end
         
     | 
| 
      
 162 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,163 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'mrz'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative '../fields'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require_relative 'base'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            # We need to do this disgusting thing to avoid the following error message:
         
     | 
| 
      
 9 
     | 
    
         
            +
            # td3 line one does not match the required format (MRZ::InvalidFormatError)
         
     | 
| 
      
 10 
     | 
    
         
            +
            #
         
     | 
| 
      
 11 
     | 
    
         
            +
            # See:
         
     | 
| 
      
 12 
     | 
    
         
            +
            # https://github.com/streetspotr/mrz/issues/2
         
     | 
| 
      
 13 
     | 
    
         
            +
            # https://github.com/streetspotr/mrz/pull/3
         
     | 
| 
      
 14 
     | 
    
         
            +
            #
         
     | 
| 
      
 15 
     | 
    
         
            +
            MRZ::TD3Parser::FORMAT_ONE = %r{\A(.{2})(.{3})([^<]+)<(.*)\z}.freeze
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            module Mindee
         
     | 
| 
      
 18 
     | 
    
         
            +
              # Passport document.
         
     | 
| 
      
 19 
     | 
    
         
            +
              class Passport < Document
         
     | 
| 
      
 20 
     | 
    
         
            +
                # @return [Mindee::Orientation]
         
     | 
| 
      
 21 
     | 
    
         
            +
                attr_reader :orientation
         
     | 
| 
      
 22 
     | 
    
         
            +
                attr_reader :country,
         
     | 
| 
      
 23 
     | 
    
         
            +
                            :id_number,
         
     | 
| 
      
 24 
     | 
    
         
            +
                            :expiry_date,
         
     | 
| 
      
 25 
     | 
    
         
            +
                            :issuance_date,
         
     | 
| 
      
 26 
     | 
    
         
            +
                            :surname,
         
     | 
| 
      
 27 
     | 
    
         
            +
                            :given_names,
         
     | 
| 
      
 28 
     | 
    
         
            +
                            :full_name,
         
     | 
| 
      
 29 
     | 
    
         
            +
                            :birth_date,
         
     | 
| 
      
 30 
     | 
    
         
            +
                            :birth_place,
         
     | 
| 
      
 31 
     | 
    
         
            +
                            :gender,
         
     | 
| 
      
 32 
     | 
    
         
            +
                            :mrz1,
         
     | 
| 
      
 33 
     | 
    
         
            +
                            :mrz2,
         
     | 
| 
      
 34 
     | 
    
         
            +
                            :mrz
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                # @param prediction [Hash]
         
     | 
| 
      
 37 
     | 
    
         
            +
                # @param input_file [Mindee::InputDocument, nil]
         
     | 
| 
      
 38 
     | 
    
         
            +
                # @param page_id [Integer, nil]
         
     | 
| 
      
 39 
     | 
    
         
            +
                def initialize(prediction, input_file: nil, page_id: nil)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  super('passport', input_file: input_file)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @orientation = Orientation.new(prediction['orientation'], page_id) if page_id
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @country = Field.new(prediction['country'], page_id)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @id_number = Field.new(prediction['id_number'], page_id)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @birth_date = DateField.new(prediction['birth_date'], page_id)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  @expiry_date = DateField.new(prediction['expiry_date'], page_id)
         
     | 
| 
      
 46 
     | 
    
         
            +
                  @issuance_date = DateField.new(prediction['issuance_date'], page_id)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @birth_place = Field.new(prediction['birth_place'], page_id)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @gender = Field.new(prediction['gender'], page_id)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @surname = Field.new(prediction['surname'], page_id)
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @mrz1 = Field.new(prediction['mrz1'], page_id)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  @mrz2 = Field.new(prediction['mrz2'], page_id)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  @given_names = []
         
     | 
| 
      
 53 
     | 
    
         
            +
                  prediction['given_names'].each do |item|
         
     | 
| 
      
 54 
     | 
    
         
            +
                    @given_names.push(Field.new(item, page_id))
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                  @full_name = construct_full_name(page_id)
         
     | 
| 
      
 57 
     | 
    
         
            +
                  @mrz = construct_mrz(page_id)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  check_mrz
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 62 
     | 
    
         
            +
                  given_names = @given_names.join(' ')
         
     | 
| 
      
 63 
     | 
    
         
            +
                  out_str = String.new
         
     | 
| 
      
 64 
     | 
    
         
            +
                  out_str << '-----Passport data-----'
         
     | 
| 
      
 65 
     | 
    
         
            +
                  out_str << "\nFilename: #{@filename}".rstrip
         
     | 
| 
      
 66 
     | 
    
         
            +
                  out_str << "\nFull name: #{@full_name}".rstrip
         
     | 
| 
      
 67 
     | 
    
         
            +
                  out_str << "\nGiven names: #{given_names}".rstrip
         
     | 
| 
      
 68 
     | 
    
         
            +
                  out_str << "\nSurname: #{@surname}".rstrip
         
     | 
| 
      
 69 
     | 
    
         
            +
                  out_str << "\nCountry: #{@country}".rstrip
         
     | 
| 
      
 70 
     | 
    
         
            +
                  out_str << "\nID Number: #{@id_number}".rstrip
         
     | 
| 
      
 71 
     | 
    
         
            +
                  out_str << "\nIssuance date: #{@issuance_date}".rstrip
         
     | 
| 
      
 72 
     | 
    
         
            +
                  out_str << "\nBirth date: #{@birth_date}".rstrip
         
     | 
| 
      
 73 
     | 
    
         
            +
                  out_str << "\nExpiry date: #{@expiry_date}".rstrip
         
     | 
| 
      
 74 
     | 
    
         
            +
                  out_str << "\nMRZ 1: #{@mrz1}".rstrip
         
     | 
| 
      
 75 
     | 
    
         
            +
                  out_str << "\nMRZ 2: #{@mrz2}".rstrip
         
     | 
| 
      
 76 
     | 
    
         
            +
                  out_str << "\nMRZ: #{@mrz}".rstrip
         
     | 
| 
      
 77 
     | 
    
         
            +
                  out_str << "\n----------------------"
         
     | 
| 
      
 78 
     | 
    
         
            +
                  out_str
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 82 
     | 
    
         
            +
                def expired?
         
     | 
| 
      
 83 
     | 
    
         
            +
                  return true unless @expiry_date.date_object
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  @expiry_date.date_object < Date.today
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                private
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                def check_mrz
         
     | 
| 
      
 91 
     | 
    
         
            +
                  return if @mrz1.value.nil? || @mrz2.value.nil?
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                  mrz = MRZ.parse([@mrz1.value, @mrz2.value])
         
     | 
| 
      
 94 
     | 
    
         
            +
                  checks = {
         
     | 
| 
      
 95 
     | 
    
         
            +
                    mrz_valid: valid_mrz?(mrz),
         
     | 
| 
      
 96 
     | 
    
         
            +
                    mrz_valid_birth_date: valid_birth_date?(mrz),
         
     | 
| 
      
 97 
     | 
    
         
            +
                    mrz_valid_expiry_date: valid_expiry_date?(mrz),
         
     | 
| 
      
 98 
     | 
    
         
            +
                    mrz_valid_id_number: valid_id_number?(mrz),
         
     | 
| 
      
 99 
     | 
    
         
            +
                    mrz_valid_surname: valid_surname?(mrz),
         
     | 
| 
      
 100 
     | 
    
         
            +
                    mrz_valid_country: valid_country?(mrz),
         
     | 
| 
      
 101 
     | 
    
         
            +
                  }
         
     | 
| 
      
 102 
     | 
    
         
            +
                  @checklist.merge!(checks)
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                def valid_mrz?(mrz)
         
     | 
| 
      
 106 
     | 
    
         
            +
                  check = mrz.valid?
         
     | 
| 
      
 107 
     | 
    
         
            +
                  @mrz.confidence = 1.0 if check
         
     | 
| 
      
 108 
     | 
    
         
            +
                  check
         
     | 
| 
      
 109 
     | 
    
         
            +
                end
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                def valid_birth_date?(mrz)
         
     | 
| 
      
 112 
     | 
    
         
            +
                  check = mrz.valid_birth_date? && mrz.birth_date == @birth_date.date_object
         
     | 
| 
      
 113 
     | 
    
         
            +
                  @birth_date.confidence = 1.0 if check
         
     | 
| 
      
 114 
     | 
    
         
            +
                  check
         
     | 
| 
      
 115 
     | 
    
         
            +
                end
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
                def valid_expiry_date?(mrz)
         
     | 
| 
      
 118 
     | 
    
         
            +
                  check = mrz.valid_expiration_date? && mrz.expiration_date == @expiry_date.date_object
         
     | 
| 
      
 119 
     | 
    
         
            +
                  @expiry_date.confidence = 1.0 if check
         
     | 
| 
      
 120 
     | 
    
         
            +
                  check
         
     | 
| 
      
 121 
     | 
    
         
            +
                end
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                def valid_id_number?(mrz)
         
     | 
| 
      
 124 
     | 
    
         
            +
                  check = mrz.valid_document_number? && mrz.document_number == @id_number.value
         
     | 
| 
      
 125 
     | 
    
         
            +
                  @id_number.confidence = 1.0 if check
         
     | 
| 
      
 126 
     | 
    
         
            +
                  check
         
     | 
| 
      
 127 
     | 
    
         
            +
                end
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                def valid_surname?(mrz)
         
     | 
| 
      
 130 
     | 
    
         
            +
                  check = mrz.last_name == @surname.value
         
     | 
| 
      
 131 
     | 
    
         
            +
                  @surname.confidence = 1.0 if check
         
     | 
| 
      
 132 
     | 
    
         
            +
                  check
         
     | 
| 
      
 133 
     | 
    
         
            +
                end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                def valid_country?(mrz)
         
     | 
| 
      
 136 
     | 
    
         
            +
                  check = mrz.nationality == @country.value
         
     | 
| 
      
 137 
     | 
    
         
            +
                  @country.confidence = 1.0 if check
         
     | 
| 
      
 138 
     | 
    
         
            +
                  check
         
     | 
| 
      
 139 
     | 
    
         
            +
                end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                def construct_full_name(page_id)
         
     | 
| 
      
 142 
     | 
    
         
            +
                  return unless @surname.value &&
         
     | 
| 
      
 143 
     | 
    
         
            +
                                !@given_names.empty? &&
         
     | 
| 
      
 144 
     | 
    
         
            +
                                @given_names[0].value
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                  full_name = {
         
     | 
| 
      
 147 
     | 
    
         
            +
                    'value' => "#{@given_names[0].value} #{@surname.value}",
         
     | 
| 
      
 148 
     | 
    
         
            +
                    'confidence' => Field.array_confidence([@surname, @given_names[0]]),
         
     | 
| 
      
 149 
     | 
    
         
            +
                  }
         
     | 
| 
      
 150 
     | 
    
         
            +
                  Field.new(full_name, page_id, reconstructed: true)
         
     | 
| 
      
 151 
     | 
    
         
            +
                end
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                def construct_mrz(page_id)
         
     | 
| 
      
 154 
     | 
    
         
            +
                  return if @mrz1.value.nil? || @mrz2.value.nil?
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                  mrz = {
         
     | 
| 
      
 157 
     | 
    
         
            +
                    'value' => @mrz1.value + @mrz2.value,
         
     | 
| 
      
 158 
     | 
    
         
            +
                    'confidence' => Field.array_confidence([@mrz1, @mrz2]),
         
     | 
| 
      
 159 
     | 
    
         
            +
                  }
         
     | 
| 
      
 160 
     | 
    
         
            +
                  Field.new(mrz, page_id, reconstructed: true)
         
     | 
| 
      
 161 
     | 
    
         
            +
                end
         
     | 
| 
      
 162 
     | 
    
         
            +
              end
         
     | 
| 
      
 163 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,109 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative '../fields'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'base'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Mindee
         
     | 
| 
      
 7 
     | 
    
         
            +
              # Receipt document.
         
     | 
| 
      
 8 
     | 
    
         
            +
              class Receipt < Document
         
     | 
| 
      
 9 
     | 
    
         
            +
                # @return [Mindee::Locale]
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader :locale
         
     | 
| 
      
 11 
     | 
    
         
            +
                # @return [Mindee::Amount]
         
     | 
| 
      
 12 
     | 
    
         
            +
                attr_reader :total_incl
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @return [Mindee::Amount]
         
     | 
| 
      
 14 
     | 
    
         
            +
                attr_reader :total_excl
         
     | 
| 
      
 15 
     | 
    
         
            +
                # @return [Mindee::Amount]
         
     | 
| 
      
 16 
     | 
    
         
            +
                attr_reader :total_tax
         
     | 
| 
      
 17 
     | 
    
         
            +
                # @return [Mindee::DateField]
         
     | 
| 
      
 18 
     | 
    
         
            +
                attr_reader :date
         
     | 
| 
      
 19 
     | 
    
         
            +
                # @return [Mindee::Field]
         
     | 
| 
      
 20 
     | 
    
         
            +
                attr_reader :supplier
         
     | 
| 
      
 21 
     | 
    
         
            +
                # @return [Array<Mindee::TaxField>]
         
     | 
| 
      
 22 
     | 
    
         
            +
                attr_reader :taxes
         
     | 
| 
      
 23 
     | 
    
         
            +
                # @return [Mindee::Orientation]
         
     | 
| 
      
 24 
     | 
    
         
            +
                attr_reader :orientation
         
     | 
| 
      
 25 
     | 
    
         
            +
                # @return [Mindee::Field]
         
     | 
| 
      
 26 
     | 
    
         
            +
                attr_reader :time
         
     | 
| 
      
 27 
     | 
    
         
            +
                # @return [Mindee::Field]
         
     | 
| 
      
 28 
     | 
    
         
            +
                attr_reader :category
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                # @param prediction [Hash]
         
     | 
| 
      
 31 
     | 
    
         
            +
                # @param input_file [Mindee::InputDocument, nil]
         
     | 
| 
      
 32 
     | 
    
         
            +
                # @param page_id [Integer, nil]
         
     | 
| 
      
 33 
     | 
    
         
            +
                def initialize(prediction, input_file: nil, page_id: nil)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  super('receipt', input_file: input_file)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @orientation = Orientation.new(prediction['orientation'], page_id) if page_id
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @locale = Locale.new(prediction['locale'])
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @total_incl = Amount.new(prediction['total_incl'], page_id)
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @date = DateField.new(prediction['date'], page_id)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @category = Field.new(prediction['category'], page_id)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  @supplier = Field.new(prediction['supplier'], page_id)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @time = Field.new(prediction['time'], page_id)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @taxes = []
         
     | 
| 
      
 43 
     | 
    
         
            +
                  prediction['taxes'].each do |item|
         
     | 
| 
      
 44 
     | 
    
         
            +
                    @taxes.push(TaxField.new(item, page_id))
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  @total_tax = Amount.new(
         
     | 
| 
      
 48 
     | 
    
         
            +
                    { value: nil, confidence: 0.0 }, page_id
         
     | 
| 
      
 49 
     | 
    
         
            +
                  )
         
     | 
| 
      
 50 
     | 
    
         
            +
                  @total_excl = Amount.new(
         
     | 
| 
      
 51 
     | 
    
         
            +
                    { value: nil, confidence: 0.0 }, page_id
         
     | 
| 
      
 52 
     | 
    
         
            +
                  )
         
     | 
| 
      
 53 
     | 
    
         
            +
                  reconstruct(page_id)
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 57 
     | 
    
         
            +
                  taxes = @taxes.join("\n       ")
         
     | 
| 
      
 58 
     | 
    
         
            +
                  out_str = String.new
         
     | 
| 
      
 59 
     | 
    
         
            +
                  out_str << '-----Receipt data-----'
         
     | 
| 
      
 60 
     | 
    
         
            +
                  out_str << "\nFilename: #{@filename}".rstrip
         
     | 
| 
      
 61 
     | 
    
         
            +
                  out_str << "\nTotal amount including taxes: #{@total_incl}".rstrip
         
     | 
| 
      
 62 
     | 
    
         
            +
                  out_str << "\nTotal amount excluding taxes: #{@total_excl}".rstrip
         
     | 
| 
      
 63 
     | 
    
         
            +
                  out_str << "\nDate: #{@date}".rstrip
         
     | 
| 
      
 64 
     | 
    
         
            +
                  out_str << "\nCategory: #{@category}".rstrip
         
     | 
| 
      
 65 
     | 
    
         
            +
                  out_str << "\nTime: #{@time}".rstrip
         
     | 
| 
      
 66 
     | 
    
         
            +
                  out_str << "\nMerchant name: #{@supplier}".rstrip
         
     | 
| 
      
 67 
     | 
    
         
            +
                  out_str << "\nTaxes: #{taxes}".rstrip
         
     | 
| 
      
 68 
     | 
    
         
            +
                  out_str << "\nTotal taxes: #{@total_tax}".rstrip
         
     | 
| 
      
 69 
     | 
    
         
            +
                  out_str << "\nLocale: #{@locale}".rstrip
         
     | 
| 
      
 70 
     | 
    
         
            +
                  out_str << "\n----------------------"
         
     | 
| 
      
 71 
     | 
    
         
            +
                  out_str
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                private
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                def reconstruct(page_id)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  construct_total_tax_from_taxes(page_id)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  construct_total_excl(page_id)
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def construct_total_tax_from_taxes(page_id)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  return if @taxes.empty? || !@total_tax.value.nil?
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  total_tax = {
         
     | 
| 
      
 85 
     | 
    
         
            +
                    'value' => @taxes.map do |tax|
         
     | 
| 
      
 86 
     | 
    
         
            +
                      if tax.value.nil?
         
     | 
| 
      
 87 
     | 
    
         
            +
                        0
         
     | 
| 
      
 88 
     | 
    
         
            +
                      else
         
     | 
| 
      
 89 
     | 
    
         
            +
                        tax.value
         
     | 
| 
      
 90 
     | 
    
         
            +
                      end
         
     | 
| 
      
 91 
     | 
    
         
            +
                    end.sum,
         
     | 
| 
      
 92 
     | 
    
         
            +
                    'confidence' => Field.array_confidence(@taxes),
         
     | 
| 
      
 93 
     | 
    
         
            +
                  }
         
     | 
| 
      
 94 
     | 
    
         
            +
                  return unless total_tax['value'].positive?
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                  @total_tax = Amount.new(total_tax, page_id, reconstructed: true)
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                def construct_total_excl(page_id)
         
     | 
| 
      
 100 
     | 
    
         
            +
                  return if @taxes.empty? || @total_incl.value.nil?
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                  total_excl = {
         
     | 
| 
      
 103 
     | 
    
         
            +
                    'value' => @total_incl.value - Field.array_sum(@taxes),
         
     | 
| 
      
 104 
     | 
    
         
            +
                    'confidence' => Field.array_confidence(@taxes) * @total_incl.confidence,
         
     | 
| 
      
 105 
     | 
    
         
            +
                  }
         
     | 
| 
      
 106 
     | 
    
         
            +
                  @total_excl = Amount.new(total_excl, page_id, reconstructed: true)
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
              end
         
     | 
| 
      
 109 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,105 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'net/http'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'version'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Mindee
         
     | 
| 
      
 7 
     | 
    
         
            +
              MINDEE_API_URL = 'https://api.mindee.net/v1'
         
     | 
| 
      
 8 
     | 
    
         
            +
              USER_AGENT = "mindee-api-ruby@v#{Mindee::VERSION} ruby-v#{RUBY_VERSION} #{Mindee::PLATFORM}"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              INVOICE_VERSION = '3'
         
     | 
| 
      
 11 
     | 
    
         
            +
              INVOICE_URL_NAME = 'invoices'
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              RECEIPT_VERSION = '3'
         
     | 
| 
      
 14 
     | 
    
         
            +
              RECEIPT_URL_NAME = 'expense_receipts'
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              PASSPORT_VERSION = '1'
         
     | 
| 
      
 17 
     | 
    
         
            +
              PASSPORT_URL_NAME = 'passport'
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              # Generic API endpoint for a product.
         
     | 
| 
      
 20 
     | 
    
         
            +
              class Endpoint
         
     | 
| 
      
 21 
     | 
    
         
            +
                attr_reader :api_key
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def initialize(owner, url_name, version, key_name: nil, api_key: nil)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @owner = owner
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @url_name = url_name
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @version = version
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @key_name = key_name || url_name
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @api_key = api_key || set_api_key_from_env
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @url_root = "#{MINDEE_API_URL}/products/#{@owner}/#{@url_name}/v#{@version}"
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                # @param input_doc [Mindee::InputDocument]
         
     | 
| 
      
 33 
     | 
    
         
            +
                # @param include_words [Boolean]
         
     | 
| 
      
 34 
     | 
    
         
            +
                # @param close_file [Boolean]
         
     | 
| 
      
 35 
     | 
    
         
            +
                # @return [Net::HTTPResponse]
         
     | 
| 
      
 36 
     | 
    
         
            +
                def predict_request(input_doc, include_words: false, close_file: true)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  uri = URI("#{@url_root}/predict")
         
     | 
| 
      
 38 
     | 
    
         
            +
                  headers = {
         
     | 
| 
      
 39 
     | 
    
         
            +
                    'Authorization' => "Token #{@api_key}",
         
     | 
| 
      
 40 
     | 
    
         
            +
                    'User-Agent' => USER_AGENT,
         
     | 
| 
      
 41 
     | 
    
         
            +
                  }
         
     | 
| 
      
 42 
     | 
    
         
            +
                  req = Net::HTTP::Post.new(uri, headers)
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  params = {
         
     | 
| 
      
 45 
     | 
    
         
            +
                    'document' => input_doc.read_document(close: close_file),
         
     | 
| 
      
 46 
     | 
    
         
            +
                  }
         
     | 
| 
      
 47 
     | 
    
         
            +
                  params.push ['include_mvision', 'true'] if include_words
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  req.set_form(params, 'multipart/form-data')
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
         
     | 
| 
      
 52 
     | 
    
         
            +
                    http.request(req)
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def envvar_key_name
         
     | 
| 
      
 57 
     | 
    
         
            +
                  key_name = to_envar(@key_name)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  key_name = "#{to_envar(@owner)}_#{key_name}" if @owner != 'mindee'
         
     | 
| 
      
 59 
     | 
    
         
            +
                  "MINDEE_#{key_name}_API_KEY"
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                private
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                # Create a standard way to get/set environment variable names.
         
     | 
| 
      
 65 
     | 
    
         
            +
                def to_envar(name)
         
     | 
| 
      
 66 
     | 
    
         
            +
                  name.sub('-', '_').upcase
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                # Set the endpoint's API key from an environment variable, if present.
         
     | 
| 
      
 70 
     | 
    
         
            +
                # We look first for the specific key, if not set, we'll use the generic key
         
     | 
| 
      
 71 
     | 
    
         
            +
                def set_api_key_from_env
         
     | 
| 
      
 72 
     | 
    
         
            +
                  env_key = ENV.fetch(envvar_key_name, nil)
         
     | 
| 
      
 73 
     | 
    
         
            +
                  env_key = ENV.fetch('MINDEE_API_KEY', nil) if env_key.nil?
         
     | 
| 
      
 74 
     | 
    
         
            +
                  @api_key = env_key if env_key
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
              end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
              # Invoice API endpoint
         
     | 
| 
      
 79 
     | 
    
         
            +
              class InvoiceEndpoint < Endpoint
         
     | 
| 
      
 80 
     | 
    
         
            +
                def initialize(api_key)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  super('mindee', INVOICE_URL_NAME, INVOICE_VERSION, key_name: 'invoice', api_key: api_key)
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
              end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
              # Receipt API endpoint
         
     | 
| 
      
 86 
     | 
    
         
            +
              class ReceiptEndpoint < Endpoint
         
     | 
| 
      
 87 
     | 
    
         
            +
                def initialize(api_key)
         
     | 
| 
      
 88 
     | 
    
         
            +
                  super('mindee', RECEIPT_URL_NAME, RECEIPT_VERSION, key_name: 'receipt', api_key: api_key)
         
     | 
| 
      
 89 
     | 
    
         
            +
                end
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
              # Passport API endpoint
         
     | 
| 
      
 93 
     | 
    
         
            +
              class PassportEndpoint < Endpoint
         
     | 
| 
      
 94 
     | 
    
         
            +
                def initialize(api_key)
         
     | 
| 
      
 95 
     | 
    
         
            +
                  super('mindee', PASSPORT_URL_NAME, PASSPORT_VERSION, api_key: api_key)
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
              end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
              # Custom (constructed) API endpoint
         
     | 
| 
      
 100 
     | 
    
         
            +
              class CustomEndpoint < Endpoint
         
     | 
| 
      
 101 
     | 
    
         
            +
                def initialize(document_type, account_name, version, api_key)
         
     | 
| 
      
 102 
     | 
    
         
            +
                  super(account_name, document_type, version, api_key: api_key)
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
              end
         
     | 
| 
      
 105 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative 'base'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Mindee
         
     | 
| 
      
 6 
     | 
    
         
            +
              # Represents tax information.
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Amount < Field
         
     | 
| 
      
 8 
     | 
    
         
            +
                # Amount value as 3 decimal float
         
     | 
| 
      
 9 
     | 
    
         
            +
                # @return [Float, nil]
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader :value
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                def initialize(prediction, page_id, reconstructed: false)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  super
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @value = @value.round(3) unless @value.nil?
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,61 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require_relative '../geometry'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Mindee
         
     | 
| 
      
 6 
     | 
    
         
            +
              # Base field object.
         
     | 
| 
      
 7 
     | 
    
         
            +
              class Field
         
     | 
| 
      
 8 
     | 
    
         
            +
                # @return [String, Float, Integer, Boolean]
         
     | 
| 
      
 9 
     | 
    
         
            +
                attr_reader :value
         
     | 
| 
      
 10 
     | 
    
         
            +
                # @return [Array<Array<Float>>]
         
     | 
| 
      
 11 
     | 
    
         
            +
                attr_reader :bbox
         
     | 
| 
      
 12 
     | 
    
         
            +
                # @return [Array<Array<Float>>]
         
     | 
| 
      
 13 
     | 
    
         
            +
                attr_reader :polygon
         
     | 
| 
      
 14 
     | 
    
         
            +
                # @return [Integer, nil]
         
     | 
| 
      
 15 
     | 
    
         
            +
                attr_reader :page_id
         
     | 
| 
      
 16 
     | 
    
         
            +
                # true if the field was reconstructed or computed using other fields.
         
     | 
| 
      
 17 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 18 
     | 
    
         
            +
                attr_reader :reconstructed
         
     | 
| 
      
 19 
     | 
    
         
            +
                # The confidence score, value will be between 0.0 and 1.0
         
     | 
| 
      
 20 
     | 
    
         
            +
                # @return [Float]
         
     | 
| 
      
 21 
     | 
    
         
            +
                attr_accessor :confidence
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                # @param prediction [Hash]
         
     | 
| 
      
 24 
     | 
    
         
            +
                # @param page_id [Integer, nil]
         
     | 
| 
      
 25 
     | 
    
         
            +
                # @param reconstructed [Boolean]
         
     | 
| 
      
 26 
     | 
    
         
            +
                def initialize(prediction, page_id, reconstructed: false)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @value = prediction['value']
         
     | 
| 
      
 28 
     | 
    
         
            +
                  @confidence = prediction['confidence']
         
     | 
| 
      
 29 
     | 
    
         
            +
                  @polygon = prediction['polygon']
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @bbox = Geometry.get_bbox_as_polygon(@polygon) unless @polygon.nil? || @polygon.empty?
         
     | 
| 
      
 31 
     | 
    
         
            +
                  @page_id = page_id || prediction['page_id']
         
     | 
| 
      
 32 
     | 
    
         
            +
                  @reconstructed = reconstructed
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def to_s
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @value ? @value.to_s : ''
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                # Multiply all the Mindee::Field confidences in the array.
         
     | 
| 
      
 40 
     | 
    
         
            +
                def self.array_confidence(field_array)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  product = 1
         
     | 
| 
      
 42 
     | 
    
         
            +
                  field_array.each do |field|
         
     | 
| 
      
 43 
     | 
    
         
            +
                    return 0.0 if field.confidence.nil?
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                    product *= field.confidence
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
                  product.to_f
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                # Add all the Mindee::Field values in the array.
         
     | 
| 
      
 51 
     | 
    
         
            +
                def self.array_sum(field_array)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  arr_sum = 0
         
     | 
| 
      
 53 
     | 
    
         
            +
                  field_array.each do |field|
         
     | 
| 
      
 54 
     | 
    
         
            +
                    return 0.0 if field.value.nil?
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                    arr_sum += field.value
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
      
 58 
     | 
    
         
            +
                  arr_sum.to_f
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Mindee
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Company registration number or code, and its type.
         
     | 
| 
      
 5 
     | 
    
         
            +
              class CompanyRegistration < Field
         
     | 
| 
      
 6 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :type
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # @param prediction [Hash]
         
     | 
| 
      
 10 
     | 
    
         
            +
                # @param page_id [Integer, nil]
         
     | 
| 
      
 11 
     | 
    
         
            +
                # @param reconstructed [Boolean]
         
     | 
| 
      
 12 
     | 
    
         
            +
                def initialize(prediction, page_id, reconstructed: false)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  super
         
     | 
| 
      
 14 
     | 
    
         
            +
                  @type = prediction['type']
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'date'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require_relative 'base'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            module Mindee
         
     | 
| 
      
 8 
     | 
    
         
            +
              # Represents a date.
         
     | 
| 
      
 9 
     | 
    
         
            +
              class DateField < Field
         
     | 
| 
      
 10 
     | 
    
         
            +
                # The date as a standard Ruby `Date` object.
         
     | 
| 
      
 11 
     | 
    
         
            +
                # @return [Date, nil]
         
     | 
| 
      
 12 
     | 
    
         
            +
                attr_reader :date_object
         
     | 
| 
      
 13 
     | 
    
         
            +
                # The ISO 8601 representation of the date, regardless of the `raw` contents.
         
     | 
| 
      
 14 
     | 
    
         
            +
                # @return [String, nil]
         
     | 
| 
      
 15 
     | 
    
         
            +
                attr_reader :value
         
     | 
| 
      
 16 
     | 
    
         
            +
                # The textual representation of the date as found on the document.
         
     | 
| 
      
 17 
     | 
    
         
            +
                # @return [String, nil]
         
     | 
| 
      
 18 
     | 
    
         
            +
                attr_reader :raw
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                # @param prediction [Hash]
         
     | 
| 
      
 21 
     | 
    
         
            +
                # @param page_id [Integer, nil]
         
     | 
| 
      
 22 
     | 
    
         
            +
                def initialize(prediction, page_id)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  super
         
     | 
| 
      
 24 
     | 
    
         
            +
                  return unless @value
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  @date_object = Date.parse(@value)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @raw = prediction['raw']
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     |