sps_king 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +3 -3
  3. data/CHANGELOG.md +9 -0
  4. data/README.md +17 -14
  5. data/gemfiles/{Gemfile-activemodel-6.1.x → Gemfile-activemodel-7.2.x} +1 -1
  6. data/gemfiles/{Gemfile-activemodel-7.0.x → Gemfile-activemodel-8.0.x} +1 -1
  7. data/lib/sps_king/account/address.rb +55 -0
  8. data/lib/sps_king/account/creditor_account.rb +3 -0
  9. data/lib/sps_king/account/creditor_address.rb +2 -34
  10. data/lib/sps_king/account/debtor_account.rb +1 -0
  11. data/lib/sps_king/account/debtor_address.rb +2 -31
  12. data/lib/sps_king/account.rb +3 -0
  13. data/lib/sps_king/converter.rb +14 -10
  14. data/lib/sps_king/message/credit_transfer.rb +114 -111
  15. data/lib/sps_king/message/direct_debit.rb +121 -118
  16. data/lib/sps_king/message.rb +54 -48
  17. data/lib/sps_king/structured_remittance_information.rb +2 -0
  18. data/lib/sps_king/transaction/credit_transfer_transaction.rb +3 -0
  19. data/lib/sps_king/transaction/direct_debit_transaction.rb +9 -6
  20. data/lib/sps_king/transaction.rb +10 -7
  21. data/lib/sps_king/validator.rb +9 -0
  22. data/lib/sps_king/version.rb +3 -1
  23. data/lib/sps_king.rb +1 -0
  24. data/spec/lib/sps_king/account/address_spec.rb +85 -0
  25. data/spec/lib/sps_king/account/creditor_account_spec.rb +14 -13
  26. data/spec/lib/sps_king/account/debtor_account_spec.rb +1 -0
  27. data/spec/lib/sps_king/account_spec.rb +12 -2
  28. data/spec/lib/sps_king/converter_spec.rb +25 -5
  29. data/spec/lib/sps_king/message/credit_transfer_spec.rb +184 -45
  30. data/spec/lib/sps_king/message/direct_debit_spec.rb +218 -102
  31. data/spec/lib/sps_king/message_spec.rb +23 -8
  32. data/spec/lib/sps_king/structured_remittance_information_spec.rb +7 -2
  33. data/spec/lib/sps_king/transaction/credit_transfer_transaction_spec.rb +14 -2
  34. data/spec/lib/sps_king/transaction/direct_debit_transaction_spec.rb +8 -7
  35. data/spec/lib/sps_king/transaction_spec.rb +62 -27
  36. data/spec/lib/sps_king/validator_spec.rb +38 -9
  37. data/spec/spec_helper.rb +8 -4
  38. data/spec/support/active_model.rb +3 -1
  39. data/spec/support/factories.rb +11 -10
  40. data/spec/support/validations.rb +2 -0
  41. data/sps_king.gemspec +1 -0
  42. metadata +8 -12
  43. data/spec/lib/sps_king/account/creditor_address_spec.rb +0 -14
  44. data/spec/lib/sps_king/account/debtor_address_spec.rb +0 -14
@@ -1,10 +1,12 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module SPS
4
+
4
5
  PAIN_008_001_02_CH_03 = 'pain.008.001.02.ch.03'
5
6
  PAIN_001_001_03_CH_02 = 'pain.001.001.03.ch.02'
6
7
 
7
8
  class Message
9
+
8
10
  include ActiveModel::Validations
9
11
 
10
12
  attr_reader :account, :grouped_transactions
@@ -16,7 +18,7 @@ module SPS
16
18
 
17
19
  class_attribute :account_class, :transaction_class, :xml_main_tag, :known_schemas
18
20
 
19
- def initialize(account_options={})
21
+ def initialize(account_options = {})
20
22
  @grouped_transactions = {}
21
23
  @account = account_class.new(account_options)
22
24
  end
@@ -24,6 +26,7 @@ module SPS
24
26
  def add_transaction(options)
25
27
  transaction = transaction_class.new(options)
26
28
  raise ArgumentError.new(transaction.errors.full_messages.join("\n")) unless transaction.valid?
29
+
27
30
  @grouped_transactions[transaction_group(transaction)] ||= []
28
31
  @grouped_transactions[transaction_group(transaction)] << transaction
29
32
  end
@@ -33,11 +36,11 @@ module SPS
33
36
  end
34
37
 
35
38
  # @return [String] xml
36
- def to_xml(schema_name=self.known_schemas.first)
39
+ def to_xml(schema_name = self.known_schemas.first, encoding = 'UTF-8')
37
40
  raise SPS::Error.new(errors.full_messages.join("\n")) unless valid?
38
41
  raise SPS::Error.new("Incompatible with schema #{schema_name}!") unless schema_compatible?(schema_name)
39
42
 
40
- builder = Nokogiri::XML::Builder.new do |builder|
43
+ builder = Nokogiri::XML::Builder.new(encoding: encoding) do |builder|
41
44
  builder.Document(xml_schema(schema_name)) do
42
45
  builder.__send__(xml_main_tag) do
43
46
  build_group_header(builder)
@@ -50,7 +53,7 @@ module SPS
50
53
  builder.to_xml
51
54
  end
52
55
 
53
- def amount_total(selected_transactions=transactions)
56
+ def amount_total(selected_transactions = transactions)
54
57
  selected_transactions.inject(0) { |sum, t| sum + t.amount }
55
58
  end
56
59
 
@@ -58,10 +61,10 @@ module SPS
58
61
  raise ArgumentError.new("Schema #{schema_name} is unknown!") unless self.known_schemas.include?(schema_name)
59
62
 
60
63
  case schema_name
61
- when PAIN_001_001_03_CH_02
62
- transactions.all? { |t| t.schema_compatible?(schema_name) }
63
- when PAIN_008_001_02_CH_03
64
- transactions.all? { |t| t.schema_compatible?(schema_name) } &&
64
+ when PAIN_001_001_03_CH_02
65
+ transactions.all? { |t| t.schema_compatible?(schema_name) }
66
+ when PAIN_008_001_02_CH_03
67
+ transactions.all? { |t| t.schema_compatible?(schema_name) } &&
65
68
  !account.iban.to_s.match(/^(CH|LI)/).nil? # Only allowed for switzerland or liechtenstein
66
69
  end
67
70
  end
@@ -111,53 +114,56 @@ module SPS
111
114
  grouped_transactions.keys.collect { |group| payment_information_identification(group) }
112
115
  end
113
116
 
114
- private
115
- # @return {Hash<Symbol=>String>} xml schema information used in output xml
116
- def xml_schema(schema_name)
117
- {
118
- :xmlns => "http://www.six-interbank-clearing.com/de/#{schema_name}.xsd",
119
- :'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
120
- :'xsi:schemaLocation' => "http://www.six-interbank-clearing.com/de/#{schema_name}.xsd #{schema_name}.xsd"
121
- }
122
- end
117
+ private
123
118
 
124
- def build_group_header(builder)
125
- builder.GrpHdr do
126
- builder.MsgId(message_identification)
127
- builder.CreDtTm(creation_date_time)
128
- builder.NbOfTxs(transactions.length)
129
- builder.CtrlSum('%.2f' % amount_total)
130
- builder.InitgPty do
131
- builder.Nm(account.name)
132
- builder.Id do
133
- builder.OrgId do
134
- builder.Othr do
135
- builder.Id(account.creditor_identifier)
119
+ # @return {Hash<Symbol=>String>} xml schema information used in output xml
120
+ def xml_schema(schema_name)
121
+ {
122
+ :xmlns => "http://www.six-interbank-clearing.com/de/#{schema_name}.xsd",
123
+ :'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
124
+ :'xsi:schemaLocation' => "http://www.six-interbank-clearing.com/de/#{schema_name}.xsd #{schema_name}.xsd"
125
+ }
126
+ end
127
+
128
+ def build_group_header(builder)
129
+ builder.GrpHdr do
130
+ builder.MsgId(message_identification)
131
+ builder.CreDtTm(creation_date_time)
132
+ builder.NbOfTxs(transactions.length)
133
+ builder.CtrlSum('%.2f' % amount_total)
134
+ builder.InitgPty do
135
+ builder.Nm(account.name)
136
+ builder.Id do
137
+ builder.OrgId do
138
+ builder.Othr do
139
+ builder.Id(account.creditor_identifier)
140
+ end
136
141
  end
137
- end
138
- end if account.respond_to? :creditor_identifier
142
+ end if account.respond_to? :creditor_identifier
143
+ end
139
144
  end
140
145
  end
141
- end
142
146
 
143
- # Unique and consecutive identifier (used for the <PmntInf> blocks)
144
- def payment_information_identification(group)
145
- "#{message_identification}/#{grouped_transactions.keys.index(group)+1}"
146
- end
147
+ # Unique and consecutive identifier (used for the <PmntInf> blocks)
148
+ def payment_information_identification(group)
149
+ "#{message_identification}/#{grouped_transactions.keys.index(group) + 1}"
150
+ end
147
151
 
148
- # Returns a key to determine the group to which the transaction belongs
149
- def transaction_group(transaction)
150
- transaction
151
- end
152
+ # Returns a key to determine the group to which the transaction belongs
153
+ def transaction_group(transaction)
154
+ transaction
155
+ end
152
156
 
153
- def validate_final_document!(document, schema_name)
154
- xsd = Nokogiri::XML::Schema(
155
- File.read(
156
- File.expand_path("../../../lib/schema/#{schema_name}.xsd", __FILE__)
157
+ def validate_final_document!(document, schema_name)
158
+ xsd = Nokogiri::XML::Schema(
159
+ File.read(
160
+ File.expand_path("../../../lib/schema/#{schema_name}.xsd", __FILE__)
161
+ )
157
162
  )
158
- )
159
- errors = xsd.validate(document).map { |error| error.message }
160
- raise SPS::Error.new("Incompatible with schema #{schema_name}: #{errors.join(', ')}") if errors.any?
161
- end
163
+ errors = xsd.validate(document).map { |error| error.message }
164
+ raise SPS::Error.new("Incompatible with schema #{schema_name}: #{errors.join(', ')}") if errors.any?
165
+ end
166
+
162
167
  end
168
+
163
169
  end
@@ -1,5 +1,6 @@
1
1
  module SPS
2
2
  class StructuredRemittanceInformation
3
+
3
4
  include ActiveModel::Validations
4
5
  extend Converter
5
6
 
@@ -16,5 +17,6 @@ module SPS
16
17
  public_send("#{name}=", value)
17
18
  end
18
19
  end
20
+
19
21
  end
20
22
  end
@@ -1,6 +1,8 @@
1
1
  # encoding: utf-8
2
+
2
3
  module SPS
3
4
  class CreditTransferTransaction < Transaction
5
+
4
6
  attr_accessor :service_level,
5
7
  :creditor_address,
6
8
  :category_purpose,
@@ -20,5 +22,6 @@ module SPS
20
22
  !self.bic.nil?
21
23
  end
22
24
  end
25
+
23
26
  end
24
27
  end
@@ -1,6 +1,13 @@
1
1
  # encoding: utf-8
2
+
2
3
  module SPS
3
4
  class DirectDebitTransaction < Transaction
5
+
6
+ attr_accessor :service_level,
7
+ :local_instrument,
8
+ :creditor_account,
9
+ :debtor_address
10
+
4
11
  SERVICE_LEVELS = %w(CHDD CHTA)
5
12
 
6
13
  LOCAL_INSTRUMENTS_FOR_SERVICE_LEVELS = {
@@ -8,11 +15,6 @@ module SPS
8
15
  'CHTA' => %w(LSV+ BDD)
9
16
  }
10
17
 
11
- attr_accessor :service_level,
12
- :local_instrument,
13
- :creditor_account,
14
- :debtor_address
15
-
16
18
  validates_format_of :iban, with: /\A(CH|LI)/
17
19
 
18
20
  validates_presence_of :instruction,
@@ -38,7 +40,7 @@ module SPS
38
40
  case schema_name
39
41
  when PAIN_008_001_02_CH_03
40
42
  self.structured_remittance_information.present? &&
41
- self.structured_remittance_information.valid?
43
+ self.structured_remittance_information.valid?
42
44
  end
43
45
  end
44
46
 
@@ -54,5 +56,6 @@ module SPS
54
56
  end
55
57
  end
56
58
  end
59
+
57
60
  end
58
61
  end
@@ -1,11 +1,11 @@
1
1
  # encoding: utf-8
2
+
2
3
  module SPS
3
4
  class Transaction
5
+
4
6
  include ActiveModel::Validations
5
7
  extend Converter
6
8
 
7
- DEFAULT_REQUESTED_DATE = Date.new(1999, 1, 1).freeze
8
-
9
9
  attr_accessor :name,
10
10
  :iban,
11
11
  :bic,
@@ -20,6 +20,8 @@ module SPS
20
20
  :debtor_address,
21
21
  :creditor_address
22
22
 
23
+ DEFAULT_REQUESTED_DATE = Date.new(1999, 1, 1).freeze
24
+
23
25
  convert :name, :instruction, :reference, :remittance_information, to: :text
24
26
  convert :amount, to: :decimal
25
27
 
@@ -48,12 +50,13 @@ module SPS
48
50
 
49
51
  protected
50
52
 
51
- def validate_requested_date_after(min_requested_date)
52
- return unless requested_date.is_a?(Date)
53
+ def validate_requested_date_after(min_requested_date)
54
+ return unless requested_date.is_a?(Date)
53
55
 
54
- if requested_date != DEFAULT_REQUESTED_DATE && requested_date < min_requested_date
55
- errors.add(:requested_date, "must be greater or equal to #{min_requested_date}, or nil")
56
+ if requested_date != DEFAULT_REQUESTED_DATE && requested_date < min_requested_date
57
+ errors.add(:requested_date, "must be greater or equal to #{min_requested_date}, or nil")
58
+ end
56
59
  end
57
- end
60
+
58
61
  end
59
62
  end
@@ -1,6 +1,9 @@
1
1
  # encoding: utf-8
2
+
2
3
  module SPS
4
+
3
5
  class IBANValidator < ActiveModel::Validator
6
+
4
7
  # IBAN2007Identifier (taken from schema)
5
8
  REGEX = /\A[A-Z]{2,2}[0-9]{2,2}[a-zA-Z0-9]{1,30}\z/
6
9
 
@@ -12,9 +15,11 @@ module SPS
12
15
  record.errors.add(field_name, :invalid, message: options[:message])
13
16
  end
14
17
  end
18
+
15
19
  end
16
20
 
17
21
  class BICValidator < ActiveModel::Validator
22
+
18
23
  # AnyBICIdentifier (taken from schema)
19
24
  REGEX = /\A[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}\z/
20
25
 
@@ -28,9 +33,11 @@ module SPS
28
33
  end
29
34
  end
30
35
  end
36
+
31
37
  end
32
38
 
33
39
  class CreditorIdentifierValidator < ActiveModel::Validator
40
+
34
41
  REGEX = /\A[a-zA-Z]{2,2}[0-9]{2,2}([A-Za-z0-9]|[\+|\?|\/|\-|\:|\(|\)|\.|,|']){3,3}([A-Za-z0-9]|[\+|\?|\/|\-|:|\(|\)|\.|,|']){1,28}\z|\A[A-Z0-9]{5,5}\z/
35
42
 
36
43
  def validate(record)
@@ -51,5 +58,7 @@ module SPS
51
58
  end
52
59
  ok
53
60
  end
61
+
54
62
  end
63
+
55
64
  end
@@ -1,3 +1,5 @@
1
1
  module SPS
2
- VERSION = '0.5.0'
2
+
3
+ VERSION = '0.6.0'
4
+
3
5
  end
data/lib/sps_king.rb CHANGED
@@ -9,6 +9,7 @@ require 'sps_king/converter'
9
9
  require 'sps_king/validator'
10
10
  require 'sps_king/version'
11
11
  require 'sps_king/account'
12
+ require 'sps_king/account/address'
12
13
  require 'sps_king/account/debtor_account'
13
14
  require 'sps_king/account/debtor_address'
14
15
  require 'sps_king/account/creditor_account'
@@ -0,0 +1,85 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe SPS::Address do
6
+ let(:country_code) { 'CH' }
7
+ let(:street_name) { 'Mustergasse' }
8
+ let(:building_number) { '123' }
9
+ let(:post_code) { '12345' }
10
+ let(:town_name) { 'Musterstadt' }
11
+ let(:address_line1) { "#{street_name} #{building_number}" }
12
+ let(:address_line2) { "#{post_code} #{town_name}" }
13
+ let(:subject_valid) do
14
+ described_class.new(
15
+ country_code:,
16
+ address_line2:
17
+ )
18
+ end
19
+ let(:subject_too_long) do
20
+ described_class.new(
21
+ country_code:,
22
+ address_line1: 'X' * 71,
23
+ address_line2: 'X' * 71,
24
+ )
25
+ end
26
+
27
+ it 'should validate country_code format' do
28
+ subject_valid.country_code = 'ch'
29
+ expect(subject_valid).not_to be_valid
30
+ expect(subject_valid.errors.details).to include(
31
+ country_code: [
32
+ {
33
+ error: :invalid,
34
+ value: "ch"
35
+ }
36
+ ]
37
+ )
38
+ end
39
+
40
+ context 'when using address_line1 and address_line2' do
41
+ it 'should initialize a new address in line mode' do
42
+ expect(subject_valid).to be_valid
43
+ end
44
+
45
+ it 'validates address_line1 and address_line2 length' do
46
+ expect(subject_too_long).not_to be_valid
47
+ expect(subject_too_long.errors.details).to include(
48
+ address_line1: [{ error: :too_long, count: 70 }],
49
+ address_line2: [{ error: :too_long, count: 70 }]
50
+ )
51
+ end
52
+ end
53
+
54
+ context 'when using separate attributes' do
55
+ let(:subject_valid) do
56
+ described_class.new(
57
+ country_code:,
58
+ town_name:
59
+ )
60
+ end
61
+ let(:subject_too_long) do
62
+ described_class.new(
63
+ country_code:,
64
+ street_name: 'X' * 71,
65
+ building_number: 'X' * 17,
66
+ post_code: 'X' * 17,
67
+ town_name: 'X' * 36,
68
+ )
69
+ end
70
+
71
+ it 'should initialize a new address in separate mode' do
72
+ expect(subject_valid).to be_valid
73
+ end
74
+
75
+ it 'validates street_name, building_number, post_code, and town_name length' do
76
+ expect(subject_too_long).not_to be_valid
77
+ expect(subject_too_long.errors.details)
78
+ .to include(
79
+ street_name: [{ error: :too_long, count: 70 }],
80
+ post_code: [{ error: :too_long, count: 16 }],
81
+ town_name: [{ error: :too_long, count: 35 }]
82
+ )
83
+ end
84
+ end
85
+ end
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+
2
3
  require 'spec_helper'
3
4
 
4
5
  describe SPS::CreditorAccount do
@@ -17,24 +18,24 @@ describe SPS::CreditorAccount do
17
18
  it 'should accept valid value' do
18
19
  expect(SPS::CreditorAccount)
19
20
  .to accept(
20
- 'DE98ZZZ09999999999',
21
- 'AT12ZZZ00000000001',
22
- 'IT97ZZZA1B2C3D4E5F6G7H8',
23
- 'NL97ZZZ123456780001',
24
- 'FR12ZZZ123456',
25
- for: :creditor_identifier
26
- )
21
+ 'DE98ZZZ09999999999',
22
+ 'AT12ZZZ00000000001',
23
+ 'IT97ZZZA1B2C3D4E5F6G7H8',
24
+ 'NL97ZZZ123456780001',
25
+ 'FR12ZZZ123456',
26
+ for: :creditor_identifier
27
+ )
27
28
  end
28
29
 
29
30
  it 'should not accept invalid value' do
30
31
  expect(SPS::CreditorAccount)
31
32
  .not_to accept(
32
- '',
33
- 'invalid',
34
- 'DE98ZZZ099999999990',
35
- 'DEAAAAAAAAAAAAAAAA',
36
- for: :creditor_identifier
37
- )
33
+ '',
34
+ 'invalid',
35
+ 'DE98ZZZ099999999990',
36
+ 'DEAAAAAAAAAAAAAAAA',
37
+ for: :creditor_identifier
38
+ )
38
39
  end
39
40
  end
40
41
 
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+
2
3
  require 'spec_helper'
3
4
 
4
5
  describe SPS::DebtorAccount do
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+
2
3
  require 'spec_helper'
3
4
 
4
5
  describe SPS::Account do
@@ -12,7 +13,12 @@ describe SPS::Account do
12
13
 
13
14
  describe :name do
14
15
  it 'should accept valid value' do
15
- expect(SPS::Account).to accept('Gläubiger GmbH', 'Zahlemann & Söhne GbR', 'X' * 70, for: :name)
16
+ expect(SPS::Account).to accept(
17
+ 'Gläubiger GmbH',
18
+ 'Zahlemann & Söhne GbR',
19
+ 'X' * 70,
20
+ for: :name
21
+ )
16
22
  end
17
23
 
18
24
  it 'should not accept invalid value' do
@@ -22,7 +28,11 @@ describe SPS::Account do
22
28
 
23
29
  describe :iban do
24
30
  it 'should accept valid value' do
25
- expect(SPS::Account).to accept('DE21500500009876543210', 'PL61109010140000071219812874', for: :iban)
31
+ expect(SPS::Account).to accept(
32
+ 'DE21500500009876543210',
33
+ 'PL61109010140000071219812874',
34
+ for: :iban
35
+ )
26
36
  end
27
37
 
28
38
  it 'should not accept invalid value' do
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+
2
3
  require 'spec_helper'
3
4
 
4
5
  describe SPS::Converter do
@@ -8,7 +9,9 @@ describe SPS::Converter do
8
9
  context 'when the conversion method does not exist' do
9
10
  it 'raises an ArgumentError' do
10
11
  class DummyForConverter
12
+
11
13
  extend SPS::Converter
14
+
12
15
  end
13
16
 
14
17
  expect {
@@ -31,10 +34,10 @@ describe SPS::Converter do
31
34
  end
32
35
 
33
36
  it 'should convert line breaks' do
34
- expect(convert_text("one\ntwo")) .to eq('one two')
35
- expect(convert_text("one\ntwo\n")) .to eq('one two')
37
+ expect(convert_text("one\ntwo")).to eq('one two')
38
+ expect(convert_text("one\ntwo\n")).to eq('one two')
36
39
  expect(convert_text("\none\ntwo\n")).to eq('one two')
37
- expect(convert_text("one\n\ntwo")) .to eq('one two')
40
+ expect(convert_text("one\n\ntwo")).to eq('one two')
38
41
  end
39
42
 
40
43
  it 'should convert number' do
@@ -63,6 +66,14 @@ describe SPS::Converter do
63
66
  expect(convert_decimal(42.12)).to eq(BigDecimal('42.12'))
64
67
  end
65
68
 
69
+ it "should convert numeric string to BigDecimal" do
70
+ expect(convert_decimal('35.21')).to eq(BigDecimal('35.21'))
71
+ end
72
+
73
+ it "should keep BigDecimal" do
74
+ expect(convert_decimal(BigDecimal('55.01'))).to eq(BigDecimal('55.01'))
75
+ end
76
+
66
77
  it 'should round' do
67
78
  expect(convert_decimal(1.345)).to eq(BigDecimal('1.35'))
68
79
  end
@@ -81,8 +92,17 @@ describe SPS::Converter do
81
92
 
82
93
  it 'should not convert invalid value' do
83
94
  expect(convert_decimal('xyz')).to eq(nil)
84
- expect(convert_decimal('NaN')).to eq(nil)
85
- expect(convert_decimal('Infinity')).to eq(nil)
95
+ expect(convert_decimal([12.2])).to eq(nil)
96
+ expect(convert_decimal({ value: '1.1' })).to eq(nil)
97
+ expect(convert_decimal(Date.new(2025))).to eq(nil)
98
+ expect(convert_decimal(1..10)).to eq(nil)
99
+ expect(convert_decimal(Float::INFINITY)).to eq(nil)
100
+ end
101
+
102
+ it "should not convert NaN value" do
103
+ nan_value = 0.0 / 0
104
+ expect(nan_value).to be_nan
105
+ expect(convert_decimal(nan_value)).to eq(nil)
86
106
  end
87
107
  end
88
108
  end