diff --git a/.ruby-version b/.ruby-version index b502146..6cb9d3d 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.0.2 +3.4.3 diff --git a/Gemfile.lock b/Gemfile.lock index 6867842..fa4c1e7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,27 +2,27 @@ PATH remote: . specs: girocode (0.2.0) - bank-contact + iban-tools rqrcode GEM remote: https://rubygems.org/ specs: - bank-contact (0.0.6) chunky_png (1.4.0) - docile (1.4.0) - minitest (5.14.4) - rake (13.0.6) - rqrcode (2.1.0) + docile (1.4.1) + iban-tools (1.2.1) + minitest (5.25.5) + rake (13.3.0) + rqrcode (3.1.0) chunky_png (~> 1.0) - rqrcode_core (~> 1.0) - rqrcode_core (1.2.0) - simplecov (0.21.2) + rqrcode_core (~> 2.0) + rqrcode_core (2.0.0) + simplecov (0.22.0) docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) - simplecov-html (0.12.3) - simplecov_json_formatter (0.1.3) + simplecov-html (0.13.1) + simplecov_json_formatter (0.1.4) PLATFORMS ruby @@ -34,4 +34,4 @@ DEPENDENCIES simplecov BUNDLED WITH - 2.2.22 + 2.6.8 diff --git a/girocode.gemspec b/girocode.gemspec index c8cd13d..e6c480f 100644 --- a/girocode.gemspec +++ b/girocode.gemspec @@ -17,5 +17,5 @@ Gem::Specification.new do |s| s.require_paths = ['lib'] s.add_dependency 'rqrcode' - s.add_dependency 'bank-contact' + s.add_dependency 'iban-tools' end diff --git a/lib/girocode.rb b/lib/girocode.rb index cf1775a..6f8b99a 100644 --- a/lib/girocode.rb +++ b/lib/girocode.rb @@ -1,5 +1,5 @@ require 'bigdecimal' -require 'bank/contact' +require 'iban-tools' require 'rqrcode' require_relative 'girocode/version' diff --git a/lib/girocode/code.rb b/lib/girocode/code.rb index 9b41b2d..bf2c887 100644 --- a/lib/girocode/code.rb +++ b/lib/girocode/code.rb @@ -1,13 +1,13 @@ module Girocode class Error < StandardError; end - + class Code ATTRIBUTES = %i[bic name iban currency amount purpose creditor_reference reference bto_info] attr_reader *ATTRIBUTES - + MAX_PAYLOAD_BYTES = 331 AMOUNT_RANGE = BigDecimal('0.01')..BigDecimal('999999999.99') - + def initialize(**attrs) if keys = attrs.keys - ATTRIBUTES and not keys.empty? raise ArgumentError, "Illegal attributes #{keys.inspect}" @@ -19,17 +19,17 @@ module Girocode raise ArgumentError, "either creditor reference or reference may be set" if creditor_reference? && reference? raise ArgumentError, "payload too long" if payload.bytesize > MAX_PAYLOAD_BYTES end - + def bic=(value) if value.nil? @bic = nil + elsif value.match? /\A[A-Z0-9]{4}([A-Z]{2})([A-Z0-9]{2})([A-Z0-9]{3})?\z/ + @bic = value else - bic = Bank::BIC.new(value) - raise ArgumentError, "Invalid BIC #{value.inspect}" unless bic.valid? - @bic = bic.to_s + raise ArgumentError, "Invalid BIC #{value.inspect}" end end - + def name=(value) value = value.strip raise ArgumentError, 'name is required' unless value @@ -37,81 +37,81 @@ module Girocode raise ArgumentError, 'Illegal name' if value.include?("\n") || value.include?("\r") @name = value end - + def iban=(value) - iban = Bank::IBAN.new(value) - raise ArgumentError, "Invalid IBAN #{value.inspect}" unless iban.valid? - @iban = iban.to_s + raise ArgumentError, "Invalid IBAN #{value.inspect}" unless IBANTools::IBAN.valid?(value) + + @iban = value end - + def currency=(value) value = value.to_s.upcase raise ArgumentError, "Invalid currency" unless value.match?(/\A[A-Z]{3}\z/) @currency = value end - + def amount=(value) raise ArgumentError, 'amount is required' unless value value = BigDecimal(value, Float::DIG + 1) raise ArgumentError, "invalid amount #{value.inspect}" unless AMOUNT_RANGE.cover?(value) @amount = value end - + def purpose=(value) unless value.nil? raise ArgumentError, "invalid purpose #{value.inspect}" unless value.match?(/\A[A-z0-9]{0,4}\z/) end @purpose = value end - + def creditor_reference=(value) unless value.nil? raise ArgumentError, "invalid creditor reference #{value.inspect}" if value.include?("\n") || value.include?("\r") || value.size > 35 end @creditor_reference = value end - + def reference=(value) unless value.nil? raise ArgumentError, "invalid reference #{value.inspect}" if value.include?("\n") || value.include?("\r") || value.size > 140 end @reference = value end - + def bto_info=(value) unless value.nil? raise ArgumentError, "invalid bto_info #{value.inspect}" if value.include?("\n") || value.include?("\r") || value.size > 70 end @bto_info = value end - + ATTRIBUTES.each do |attr| define_method("#{attr}?") do value = instance_variable_get("@#{attr}") value.respond_to?(:empty?) ? !value.empty? : !!value end end - + def payload ['BCD', '002', '1', 'SCT', bic, name, iban,formatted_amount, purpose, creditor_reference || reference, bto_info].map(&:to_s).join("\n") end - + def to_qrcode RQRCode::QRCode.new(payload, level: :m, mode: :byte_8bit) end - + def to_ascii to_qrcode.to_s end - + %i[png svg html ansi].each do |format| define_method("to_#{format}") { |*args| to_qrcode.public_send("as_#{format}", *args) } end - + private - + def formatted_amount "#{currency}#{amount.round(2).to_s('F')}" if currency? && amount end