romanianvalidators 0.1.6 → 0.2.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 +4 -4
- data/.rubocop.yml +13 -0
- data/.ruby-version +1 -1
- data/.travis.yml +4 -1
- data/README.md +71 -26
- data/lib/romanianvalidators.rb +6 -31
- data/lib/romanianvalidators/active_model.rb +32 -0
- data/lib/romanianvalidators/active_model/validations/bic_validator.rb +13 -0
- data/lib/romanianvalidators/active_model/validations/cif_validator.rb +13 -0
- data/lib/romanianvalidators/active_model/validations/cnp_validator.rb +13 -0
- data/lib/romanianvalidators/active_model/validations/iban_validator.rb +13 -0
- data/lib/romanianvalidators/bic.rb +25 -0
- data/lib/romanianvalidators/cif.rb +61 -0
- data/lib/romanianvalidators/cnp.rb +34 -0
- data/lib/romanianvalidators/iban.rb +25 -0
- data/romanianvalidators.gemspec +7 -7
- data/test/test_helper.rb +2 -0
- metadata +14 -8
- data/lib/active_model/validations/bic_validator.rb +0 -25
- data/lib/active_model/validations/cif_validator.rb +0 -30
- data/lib/active_model/validations/cnp_validator.rb +0 -51
- data/lib/active_model/validations/iban_validator.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ad45c5638e6e12b9fd6e9914810400220a0de56
|
4
|
+
data.tar.gz: a8ca1b49f450c18bd755980695c27e1d70abe65c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68dc85bf25ffa47139957327a360fb62f6dab5d39a837c14f2cee4c7243764a1931a91a940cfd89789cfc31899092d134dc01c42ddbfa55e0c3535485041f218
|
7
|
+
data.tar.gz: 9c16e8cf4a240f82fa6b9da7deff1db68526f36dd050848ccf8bba8faf83cb667d4482a06730634a191cc169083238ec3113f1285d3d9424fba3f08e288fb975
|
data/.rubocop.yml
ADDED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.
|
1
|
+
ruby-2.3.0
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -1,55 +1,100 @@
|
|
1
|
-
# Romanian Validators [](https://travis-ci.org/mtarnovan/romanianvalidators) [](https://badge.fury.io/rb/romanianvalidators) [](https://codeclimate.com/github/mtarnovan/romanianvalidators)
|
2
2
|
|
3
|
-
|
3
|
+
Validators for:
|
4
4
|
|
5
5
|
* Cod Numeric Personal (CNP)
|
6
6
|
* Cod de identificare fiscală (CIF) and
|
7
7
|
* IBAN (only Romanian format as published by Romanian National Bank).
|
8
8
|
* BIC
|
9
9
|
|
10
|
-
Extracted from [
|
10
|
+
Extracted from [openapi.ro](https://openapi.ro), business APIs for Romanian developers.
|
11
|
+
Includes `ActiveModel` validators.
|
11
12
|
|
12
13
|
## Installation
|
13
14
|
|
14
|
-
|
15
|
+
Include it in your `Gemfile`. If you just want the validation, without `ActiveModel`, use:
|
15
16
|
|
16
|
-
|
17
|
+
gem 'romanianvalidators'
|
17
18
|
|
18
|
-
|
19
|
-
...
|
20
|
-
gem 'romanianvalidations'
|
21
|
-
...
|
19
|
+
If you want ActiveModel integration, use instead:
|
22
20
|
|
23
|
-
|
21
|
+
gem 'romanianvalidators', require: 'romanian_validators/active_model'
|
24
22
|
|
25
|
-
|
23
|
+
Has no other dependency (other than `ActiveModel` if you require it).
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
Tested with MRI 1.8.7, 1.9.3, 2.0.0, REE, Rubinius and JRuby (see `.travis.yml`)
|
25
|
+
Tested with MRI 1.9.3, 2.0, 2.1, 2.3, REE, Rubinius and JRuby (see `.travis.yml`)
|
30
26
|
|
31
27
|
## Usage
|
32
28
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
29
|
+
Without `ActiveModel`, just call the `valid?` method on the corresponding module
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
> RomanianValidators::Cif.valid?(13548146)
|
33
|
+
=> true
|
34
|
+
> RomanianValidators::Iban.valid?(123)
|
35
|
+
=> false
|
36
|
+
```
|
38
37
|
|
39
|
-
|
38
|
+
With `ActiveModel`, include it in your model
|
40
39
|
|
40
|
+
```ruby
|
41
|
+
include RomanianValidators::ActiveModel::Validations
|
42
|
+
```
|
43
|
+
|
44
|
+
then use like this:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
validates :my_attribute, cif: true
|
48
|
+
```
|
49
|
+
|
50
|
+
Example:
|
41
51
|
```ruby
|
42
52
|
class User
|
43
|
-
|
44
|
-
|
53
|
+
include ActiveModel::Model
|
54
|
+
include RomanianValidators::ActiveModel::Validations
|
55
|
+
attr_accessor :cnp, :company_cif
|
56
|
+
|
57
|
+
validates :cnp, cnp: { message: 'This is not a valid CNP' }
|
58
|
+
validates :company_cif, cif: true
|
45
59
|
end
|
60
|
+
|
61
|
+
> u = User.new(cnp: 123, company_cif: 123)
|
62
|
+
=> #<User:0x007fbf7f959b38 @cnp=123, @company_cif=123>
|
63
|
+
> u.valid?
|
64
|
+
=> false
|
65
|
+
> u.errors
|
66
|
+
=> #<ActiveModel::Errors:0x007fbf80958548 @base=#<User:0x007fbf7f959b38 @cnp=123, @company_cif=123, @validation_context=nil, @errors=#<ActiveModel::Errors:0x007fbf80958548 ...>>, @messages={:cnp=>["This is not a valid CNP"], :company_cif=>["is invalid"]}, @details={:cnp=>[{:error=>"This is not a valid CNP"}], :company_cif=>[{:error=>:invalid}]}>
|
67
|
+
```
|
68
|
+
|
69
|
+
For CIFs, a (lazy) enumerator is provided. This enumerator is significantly
|
70
|
+
more efficient than iterating over a range of numbers and filtering valid CIFs, because
|
71
|
+
it generates the control digit from `cif % 10` directly.
|
72
|
+
|
73
|
+
Example:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
> RomanianValidators::Cif.enumerator(1).take(10).to_a
|
77
|
+
=> [19, 27, 35, 43, 51, 60, 78, 86, 94, 108]
|
78
|
+
> RomanianValidators::Cif.enumerator(1_000_000, :down).take(10).to_a
|
79
|
+
=> [999993, 999985, 999977, 999969, 999950, 999942, 999934, 999926, 999918, 999900]
|
80
|
+
```
|
81
|
+
|
82
|
+
### Upgrading
|
83
|
+
|
84
|
+
If upgrading from `0.1.x`, note that the `ActiveModel` validations are now in a separate module so you need to add
|
85
|
+
`include RomanianValidators::ActiveModel::Validations` in your models. Additionaly you need to add a `require` in your Gemfile (again, only if using `ActiveModel`):
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
gem 'romanianvalidators', require: 'romanianvalidators/active_model'
|
46
89
|
```
|
47
90
|
|
48
|
-
###
|
91
|
+
### Changelog
|
49
92
|
|
50
|
-
|
51
|
-
|
93
|
+
#### 0.2.0
|
94
|
+
* moved validations from `ActiveModel::Validations` to `RomanianValidators::ActiveModel::Validations`.
|
95
|
+
This module must be manually required in models.
|
96
|
+
* added a lazy enumerator that generates valid CIFs: `RomanianValidators::Cif.enumerator(start, direction = :up)`
|
52
97
|
|
53
98
|
### Copyright
|
54
99
|
|
55
|
-
Copyright (c) 2007-
|
100
|
+
Copyright (c) 2007-2018 Mihai Târnovan. MIT LICENSE. See LICENSE for details.
|
data/lib/romanianvalidators.rb
CHANGED
@@ -1,34 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
def self.romanianvalidators
|
6
|
-
%w(cif cnp iban bic)
|
7
|
-
end
|
8
|
-
|
9
|
-
module EmptyBlankEachValidator
|
10
|
-
def validate_each(record, attribute, value)
|
11
|
-
allow_blank = options.fetch(:allow_blank, false)
|
12
|
-
allow_nil = options.fetch(:allow_nil, false)
|
13
|
-
message = options.fetch(:message, :invalid)
|
14
|
-
record.errors.add_on_empty(attribute) && return if value.nil? && !allow_nil
|
15
|
-
record.errors.add_on_blank(attribute) && return if value.blank? && !allow_blank
|
16
|
-
record.errors.add(attribute, message) && return unless valid?(value)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
romanianvalidators.each do |validator_name|
|
21
|
-
require "active_model/validations/#{validator_name}_validator"
|
22
|
-
end
|
1
|
+
module RomanianValidators
|
2
|
+
def self.available_validators
|
3
|
+
%w(cif cnp iban bic)
|
4
|
+
end
|
23
5
|
|
24
|
-
|
25
|
-
|
26
|
-
define_method('validates_' + validator) do |*fields|
|
27
|
-
options ||= (fields.delete(fields.find { |f| f.is_a? Hash })) || true
|
28
|
-
args = fields.push(validator => options)
|
29
|
-
validates(*args)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
6
|
+
available_validators.each do |validator_name|
|
7
|
+
require "romanianvalidators/#{validator_name}"
|
33
8
|
end
|
34
9
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'romanianvalidators'
|
2
|
+
require 'active_model'
|
3
|
+
module RomanianValidators
|
4
|
+
module ActiveModel
|
5
|
+
module Validations
|
6
|
+
module EmptyBlankEachValidator
|
7
|
+
def validate_each(record, attribute, value)
|
8
|
+
allow_blank = options.fetch(:allow_blank, false)
|
9
|
+
allow_nil = options.fetch(:allow_nil, false)
|
10
|
+
message = options.fetch(:message, :invalid)
|
11
|
+
record.errors.add_on_empty(attribute) && return if value.nil? && !allow_nil
|
12
|
+
record.errors.add_on_blank(attribute) && return if value.blank? && !allow_blank
|
13
|
+
record.errors.add(attribute, message) && return unless valid?(value)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
RomanianValidators.available_validators.each do |validator_name|
|
18
|
+
require "romanianvalidators/active_model/validations/#{validator_name}_validator"
|
19
|
+
end
|
20
|
+
|
21
|
+
module HelperMethods
|
22
|
+
RomanianValidators.available_validators.each do |validator|
|
23
|
+
define_method('validates_' + validator) do |*fields|
|
24
|
+
options ||= fields.delete(fields.find { |f| f.is_a? Hash }) || true
|
25
|
+
args = fields.push(validator => options)
|
26
|
+
validates(*args)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module RomanianValidators
|
2
|
+
module ActiveModel
|
3
|
+
module Validations
|
4
|
+
class BicValidator < ::ActiveModel::EachValidator
|
5
|
+
include ActiveModel::Validations::EmptyBlankEachValidator
|
6
|
+
|
7
|
+
def valid?(bic)
|
8
|
+
RomanianValidators::Bic.valid?(bic)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module RomanianValidators
|
2
|
+
module ActiveModel
|
3
|
+
module Validations
|
4
|
+
class CifValidator < ::ActiveModel::EachValidator
|
5
|
+
include ActiveModel::Validations::EmptyBlankEachValidator
|
6
|
+
|
7
|
+
def valid?(cif)
|
8
|
+
RomanianValidators::Cif.valid?(cif)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module RomanianValidators
|
2
|
+
module ActiveModel
|
3
|
+
module Validations
|
4
|
+
class CnpValidator < ::ActiveModel::EachValidator
|
5
|
+
include ActiveModel::Validations::EmptyBlankEachValidator
|
6
|
+
|
7
|
+
def valid?(cnp)
|
8
|
+
RomanianValidators::Cnp.valid?(cnp)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module RomanianValidators
|
2
|
+
module ActiveModel
|
3
|
+
module Validations
|
4
|
+
class IbanValidator < ::ActiveModel::EachValidator
|
5
|
+
include ActiveModel::Validations::EmptyBlankEachValidator
|
6
|
+
|
7
|
+
def valid?(iban)
|
8
|
+
RomanianValidators::Iban.valid?(iban)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RomanianValidators
|
2
|
+
module Bic
|
3
|
+
COUNTRY_CODES =
|
4
|
+
%w(AF AL DZ AS AD AO AI AG AR AM AW AU AT AZ BS BH BD BB BY BE BZ BJ BM
|
5
|
+
BT BO BA BW BR BN BG BF BI KH CM CA CV KY CF TD CL CN CO KM CG CD CK CR
|
6
|
+
CI HR CU CY CZ DK DJ DM DO EC EG SV GQ ER EE ET FK FO FJ FI FR GF PF GA
|
7
|
+
GM GE DE GH GI GR GL GD GP GU GT GN GW GY HT VA HN HK HU IS IN ID IR IQ
|
8
|
+
IE IL IT JM JP JO KZ KE KI KP KR KW KG LA LV LB LS LR LY LI LT LU MO MK
|
9
|
+
MG MW MY MV ML MT MH MQ MR MU MX FM MD MC MN MS MA MZ MM NA NR NP NL AN
|
10
|
+
NC NZ NI NE NG NU NF MP NO OM PK PW PA PG PY PE PH PN PL PT PR QA RE RO
|
11
|
+
RU RW SH KN LC PM VC WS SM ST SA SN SC SL SG SK SI SB SO ZA ES LK SD SR
|
12
|
+
SJ SZ SE CH SY TW TJ TZ TH TG TK TO TT TN TR TM TC TV UG UA AE GB US UY
|
13
|
+
UZ VU VE VN VG VI WF EH YE ZM ZW).freeze
|
14
|
+
|
15
|
+
module_function
|
16
|
+
|
17
|
+
# This is only a basic validation of a BIC
|
18
|
+
# http://www.swift.com/biconline/index.cfm?fuseaction=display_aboutbic
|
19
|
+
def valid?(bic)
|
20
|
+
return false unless bic.size == 8 || bic.size == 11 # length 8 or 11
|
21
|
+
return false unless (bic[0..3] =~ /[^A-Z]/).nil? # first 4 must be letters only
|
22
|
+
COUNTRY_CODES.include?(bic[4..5])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module RomanianValidators
|
2
|
+
module Cif
|
3
|
+
TEST_KEY = '753217532'.to_s.chars.map(&:to_i).reverse.freeze
|
4
|
+
FIRST_CIF = 19 # used to break iteration when direction is :down
|
5
|
+
|
6
|
+
module_function
|
7
|
+
|
8
|
+
def valid?(cif)
|
9
|
+
return false unless well_formed?(cif)
|
10
|
+
control, sum = control_sum(cif, TEST_KEY)
|
11
|
+
sum * 10 % 11 % 10 == control
|
12
|
+
end
|
13
|
+
|
14
|
+
def well_formed?(cif)
|
15
|
+
cif.present? && (2..10).cover?(cif.size) && (cif =~ /[^0-9]/).nil?
|
16
|
+
end
|
17
|
+
|
18
|
+
def next_valid_cif(cif)
|
19
|
+
control, sum = control_sum(cif, TEST_KEY)
|
20
|
+
last_digit_of_next_cif = sum * 10 % 11 % 10
|
21
|
+
|
22
|
+
if last_digit_of_next_cif < control
|
23
|
+
next_valid_cif(((cif / 10) + 1) * 10)
|
24
|
+
else
|
25
|
+
replace_last_digit(cif, last_digit_of_next_cif)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def prev_valid_cif(cif)
|
30
|
+
control, sum = control_sum(cif, TEST_KEY)
|
31
|
+
last_digit_of_next_cif = sum * 10 % 11 % 10
|
32
|
+
|
33
|
+
if last_digit_of_next_cif > control
|
34
|
+
next_valid_cif(((cif / 10) - 1) * 10)
|
35
|
+
else
|
36
|
+
replace_last_digit(cif, last_digit_of_next_cif)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def enumerator(start, direction = :up)
|
41
|
+
Enumerator.new do |yielder|
|
42
|
+
memo = direction == :up ? next_valid_cif(start + 1) : prev_valid_cif(start - 1)
|
43
|
+
loop do
|
44
|
+
yielder << memo
|
45
|
+
memo = direction == :up ? next_valid_cif(memo + 1) : prev_valid_cif(memo - 1)
|
46
|
+
break if memo < FIRST_CIF
|
47
|
+
end
|
48
|
+
end.lazy
|
49
|
+
end
|
50
|
+
|
51
|
+
def replace_last_digit(number, digit)
|
52
|
+
((number / 10).to_s + digit.to_s).to_i
|
53
|
+
end
|
54
|
+
|
55
|
+
def control_sum(n, test_key)
|
56
|
+
control, *rest_digits = n.to_s.chars.map(&:to_i).reverse
|
57
|
+
sum = rest_digits.zip(test_key).map { |a, b| a * b }.reduce(0, &:+)
|
58
|
+
[control, sum]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module RomanianValidators
|
2
|
+
module Cnp
|
3
|
+
TEST_KEY = '279146358279'.each_char.map(&:to_i)
|
4
|
+
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def valid?(cnp)
|
8
|
+
return false unless well_formed?(cnp) && valid_birthdate?(cnp)
|
9
|
+
control = (0..11).reduce(0) { |acc, elem| acc + TEST_KEY[elem] * cnp[elem].chr.to_i } % 11
|
10
|
+
control = 1 if control == 10
|
11
|
+
control == cnp[12].chr.to_i
|
12
|
+
end
|
13
|
+
|
14
|
+
def well_formed?(cnp)
|
15
|
+
(cnp =~ /[^0-9]/).nil? && cnp.size == 13
|
16
|
+
end
|
17
|
+
|
18
|
+
def valid_birthdate?(cnp)
|
19
|
+
year_code = cnp[0].chr.to_i
|
20
|
+
year =
|
21
|
+
case year_code
|
22
|
+
when 1..2 then '19'
|
23
|
+
when 3..4 then '18'
|
24
|
+
when 5..6 then '20'
|
25
|
+
when 9 then '19' # oare se sare peste un an bisect intre 1800-2099 ?
|
26
|
+
else return false
|
27
|
+
end
|
28
|
+
year = (year + cnp[1..2]).to_i
|
29
|
+
Date.valid_civil?(year, cnp[3..4].to_i, cnp[5..6].to_i) ? true : false
|
30
|
+
rescue ArgumentError
|
31
|
+
return false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module RomanianValidators
|
2
|
+
module Iban
|
3
|
+
# use ord for ruby >= 1.9
|
4
|
+
USE_ORD = ''.respond_to?(:ord)
|
5
|
+
|
6
|
+
module_function
|
7
|
+
|
8
|
+
# Descrierea algoritmului:
|
9
|
+
# http://www.bnr.ro/files/d/Legislatie/EN/Reg_IBAN.pdf
|
10
|
+
def valid?(iban)
|
11
|
+
return false if iban.size < 3
|
12
|
+
transpose((iban.slice(4, iban.size) + iban[0..3])).to_i % 97 == 1
|
13
|
+
rescue
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
# replace letters according to algorithm
|
18
|
+
# algorithm conversion maps chars to ASCII value - 55
|
19
|
+
def transpose(iban)
|
20
|
+
iban.upcase.gsub(/[A-Z]/) do |s|
|
21
|
+
USE_ORD ? (s[0].ord - 55).to_s : (s[0].to_i - 55).to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/romanianvalidators.gemspec
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
Gem::Specification.new do |s|
|
3
3
|
s.name = 'romanianvalidators'
|
4
|
-
s.version = '0.
|
4
|
+
s.version = '0.2.0'
|
5
5
|
s.authors = ['Mihai Târnovan']
|
6
6
|
s.email = ['mihai.tarnovan@cubus.ro']
|
7
7
|
s.homepage = 'http://github.com/mtarnovan/romanianvalidators'
|
8
8
|
s.license = 'MIT'
|
9
|
-
s.summary =
|
10
|
-
s.description =
|
9
|
+
s.summary = 'Collection of validations for Cod Numeric Personal (CNP), Cod de identificare fiscală (CIF) and IBAN (only Romanian format, as published by Romanian National Bank)'
|
10
|
+
s.description = s.summary
|
11
11
|
|
12
12
|
s.add_development_dependency 'bundler'
|
13
13
|
s.add_development_dependency 'minitest'
|
14
|
-
s.add_dependency 'rake'
|
15
|
-
s.add_dependency 'activemodel'
|
14
|
+
s.add_dependency 'rake', '>= 0.8.7'
|
15
|
+
s.add_dependency 'activemodel', '>= 3.0.0'
|
16
16
|
|
17
17
|
s.files = `git ls-files`.split("\n")
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
-
s.rubyforge_project =
|
20
|
-
end
|
19
|
+
s.rubyforge_project = 'romanianvalidators'
|
20
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -11,12 +11,14 @@ require 'minitest/autorun'
|
|
11
11
|
$-w = old_w
|
12
12
|
|
13
13
|
require 'romanianvalidators'
|
14
|
+
require 'romanianvalidators/active_model'
|
14
15
|
require 'active_support/core_ext/array/wrap'
|
15
16
|
|
16
17
|
I18n.enforce_available_locales = true
|
17
18
|
|
18
19
|
class TestRecord
|
19
20
|
include ActiveModel::Validations
|
21
|
+
include RomanianValidators::ActiveModel::Validations
|
20
22
|
attr_accessor :cnp, :bic, :cif, :iban
|
21
23
|
|
22
24
|
def initialize(attrs = {})
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: romanianvalidators
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mihai Târnovan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -68,7 +68,7 @@ dependencies:
|
|
68
68
|
version: 3.0.0
|
69
69
|
description: Collection of validations for Cod Numeric Personal (CNP), Cod de identificare
|
70
70
|
fiscală (CIF) and IBAN (only Romanian format, as published by Romanian National
|
71
|
-
Bank)
|
71
|
+
Bank)
|
72
72
|
email:
|
73
73
|
- mihai.tarnovan@cubus.ro
|
74
74
|
executables: []
|
@@ -76,6 +76,7 @@ extensions: []
|
|
76
76
|
extra_rdoc_files: []
|
77
77
|
files:
|
78
78
|
- ".gitignore"
|
79
|
+
- ".rubocop.yml"
|
79
80
|
- ".ruby-gemset"
|
80
81
|
- ".ruby-version"
|
81
82
|
- ".travis.yml"
|
@@ -84,11 +85,16 @@ files:
|
|
84
85
|
- LICENSE
|
85
86
|
- README.md
|
86
87
|
- Rakefile
|
87
|
-
- lib/active_model/validations/bic_validator.rb
|
88
|
-
- lib/active_model/validations/cif_validator.rb
|
89
|
-
- lib/active_model/validations/cnp_validator.rb
|
90
|
-
- lib/active_model/validations/iban_validator.rb
|
91
88
|
- lib/romanianvalidators.rb
|
89
|
+
- lib/romanianvalidators/active_model.rb
|
90
|
+
- lib/romanianvalidators/active_model/validations/bic_validator.rb
|
91
|
+
- lib/romanianvalidators/active_model/validations/cif_validator.rb
|
92
|
+
- lib/romanianvalidators/active_model/validations/cnp_validator.rb
|
93
|
+
- lib/romanianvalidators/active_model/validations/iban_validator.rb
|
94
|
+
- lib/romanianvalidators/bic.rb
|
95
|
+
- lib/romanianvalidators/cif.rb
|
96
|
+
- lib/romanianvalidators/cnp.rb
|
97
|
+
- lib/romanianvalidators/iban.rb
|
92
98
|
- romanianvalidators.gemspec
|
93
99
|
- test/data/valid_bics.txt
|
94
100
|
- test/data/valid_cifs.txt
|
@@ -119,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
119
125
|
version: '0'
|
120
126
|
requirements: []
|
121
127
|
rubyforge_project: romanianvalidators
|
122
|
-
rubygems_version: 2.
|
128
|
+
rubygems_version: 2.6.7
|
123
129
|
signing_key:
|
124
130
|
specification_version: 4
|
125
131
|
summary: Collection of validations for Cod Numeric Personal (CNP), Cod de identificare
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module ActiveModel
|
2
|
-
module Validations
|
3
|
-
class BicValidator < EachValidator
|
4
|
-
include ActiveModel::Validations::EmptyBlankEachValidator
|
5
|
-
COUNTRY_CODES =
|
6
|
-
%w(AF AL DZ AS AD AO AI AG AR AM AW AU AT AZ BS BH BD BB BY BE BZ BJ BM
|
7
|
-
BT BO BA BW BR BN BG BF BI KH CM CA CV KY CF TD CL CN CO KM CG CD CK CR
|
8
|
-
CI HR CU CY CZ DK DJ DM DO EC EG SV GQ ER EE ET FK FO FJ FI FR GF PF GA
|
9
|
-
GM GE DE GH GI GR GL GD GP GU GT GN GW GY HT VA HN HK HU IS IN ID IR IQ
|
10
|
-
IE IL IT JM JP JO KZ KE KI KP KR KW KG LA LV LB LS LR LY LI LT LU MO MK
|
11
|
-
MG MW MY MV ML MT MH MQ MR MU MX FM MD MC MN MS MA MZ MM NA NR NP NL AN
|
12
|
-
NC NZ NI NE NG NU NF MP NO OM PK PW PA PG PY PE PH PN PL PT PR QA RE RO
|
13
|
-
RU RW SH KN LC PM VC WS SM ST SA SN SC SL SG SK SI SB SO ZA ES LK SD SR
|
14
|
-
SJ SZ SE CH SY TW TJ TZ TH TG TK TO TT TN TR TM TC TV UG UA AE GB US UY
|
15
|
-
UZ VU VE VN VG VI WF EH YE ZM ZW)
|
16
|
-
# This is only a basic validation of a BIC
|
17
|
-
# http://www.swift.com/biconline/index.cfm?fuseaction=display_aboutbic
|
18
|
-
def valid?(bic)
|
19
|
-
return false unless bic.size == 8 || bic.size == 11 # length 8 or 11
|
20
|
-
return false unless (bic[0..3] =~ (/[^A-Z]/)).nil? # first 4 must be letters only
|
21
|
-
COUNTRY_CODES.include?(bic[4..5])
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module ActiveModel
|
2
|
-
module Validations
|
3
|
-
class CifValidator < EachValidator
|
4
|
-
|
5
|
-
# reversed test key (753217532)
|
6
|
-
TEST_KEY = '235712357'.freeze
|
7
|
-
|
8
|
-
include ActiveModel::Validations::EmptyBlankEachValidator
|
9
|
-
|
10
|
-
# Algoritmul de validare al unui cod CUI
|
11
|
-
# Pas preliminar: Se testeaza daca codul respecta formatul unui cod CUI. Adica lungimea maxima sa fie de 10 cifre si sa contina doar caractere numerice.
|
12
|
-
# Pas 1: Se foloseste cheia de testare "753217532". Se inverseaza ordinea cifrelor codului CUI precum si a cheii de testare.
|
13
|
-
# Pas 2: Se ignora prima cifra din codul CUI inversat (aceasta este cifra de control) si se inmulteste fiecare cifra cu cifra corespunzatoare din cheia de testare inversata.
|
14
|
-
# Pas 3: Se aduna toate produsele obtinute. Suma rezultata se inmulteste cu 10 si apoi se afla restul impartirii la 11.
|
15
|
-
# Pas 4: Pentru un CUI valid cifra obtinuta, in urma operatiei MODULO 11, va trebui sa corespunda cu cifra de control a codului CUI initial .
|
16
|
-
def valid?(cif)
|
17
|
-
return false unless well_formed?(cif)
|
18
|
-
rc = cif.reverse.freeze
|
19
|
-
(1..(cif.size - 1)).inject(0) {|sum, n| sum += TEST_KEY[n-1].chr.to_i * rc[n].chr.to_i} * 10 % 11 % 10 == rc[0].chr.to_i
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def well_formed?(cif)
|
25
|
-
cif.present? && (2..10).include?(cif.size) && (cif=~(/[^0-9]/)).nil?
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
module ActiveModel
|
2
|
-
module Validations
|
3
|
-
class CnpValidator < EachValidator
|
4
|
-
TEST_KEY = '279146358279'.each_char.map(&:to_i)
|
5
|
-
|
6
|
-
include ActiveModel::Validations::EmptyBlankEachValidator
|
7
|
-
|
8
|
-
# Algoritm de validare CNP
|
9
|
-
# Pas preliminar: Se testeaza daca codul respecta formatul unui cod CNP.
|
10
|
-
# Adica prima cifra sa fie cuprinsa in intervalul 1 - 6 sau sa fie 9 pentru straini.
|
11
|
-
# Urmatoarele sase cifre trebuie sa constituie o data calendaristica valida in formatul AALLZZ.
|
12
|
-
#
|
13
|
-
# Pas 1:
|
14
|
-
# Se foloseste cheia de testare "279146358279". Primele douasprezece cifre se inmultesc pe rand de la
|
15
|
-
# stanga spre dreapta cu cifra corespunzatoare din cheia de testare.
|
16
|
-
#
|
17
|
-
# Pas 2: Cele douasprezece produse obtinute se aduna si suma obtinuta se imparte la 11.
|
18
|
-
# * Daca restul impartirii la 11 este mai mic ca 10, atunci acesta va reprezenta cifra de control.
|
19
|
-
# * Daca restul impartirii este 10 atunci cifra de control este 1.
|
20
|
-
# Restul impartirii reprezinta cifra de control. Pentru un CNP valid acest rest va trebui
|
21
|
-
# sa coincida cu cifra de pe pozitia treisprezece din CNP-ul initial.
|
22
|
-
def valid?(cnp)
|
23
|
-
return false unless well_formed?(cnp) && valid_birthdate?(cnp)
|
24
|
-
control = (0..11).reduce(0) { |a, e| a + TEST_KEY[e] * cnp[e].chr.to_i } % 11
|
25
|
-
control = 1 if control == 10
|
26
|
-
control == cnp[12].chr.to_i
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def well_formed?(cnp)
|
32
|
-
(cnp =~ (/[^0-9]/)).nil? && cnp.size == 13
|
33
|
-
end
|
34
|
-
|
35
|
-
def valid_birthdate?(cnp)
|
36
|
-
year_code = cnp[0].chr.to_i
|
37
|
-
year = case year_code
|
38
|
-
when 1..2 then '19'
|
39
|
-
when 3..4 then '18'
|
40
|
-
when 5..6 then '20'
|
41
|
-
when 9 then '19' # oare se sare peste un an bisect intre 1800-2099 ?
|
42
|
-
else return false
|
43
|
-
end
|
44
|
-
year = (year + cnp[1..2]).to_i
|
45
|
-
Date.valid_civil?(year, cnp[3..4].to_i, cnp[5..6].to_i) ? true : false
|
46
|
-
rescue ArgumentError
|
47
|
-
return false
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module ActiveModel
|
2
|
-
module Validations
|
3
|
-
class IbanValidator < EachValidator
|
4
|
-
|
5
|
-
# use ord for ruby >= 1.9
|
6
|
-
USE_ORD = ''.respond_to?(:ord)
|
7
|
-
|
8
|
-
include ActiveModel::Validations::EmptyBlankEachValidator
|
9
|
-
|
10
|
-
# Descrierea algoritmului:
|
11
|
-
# http://www.bnr.ro/files/d/Legislatie/EN/Reg_IBAN.pdf
|
12
|
-
def valid?(iban)
|
13
|
-
return false if iban.size < 3
|
14
|
-
transpose((iban.slice(4, iban.size) + iban[0..3])).to_i % 97 == 1
|
15
|
-
rescue
|
16
|
-
false
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
# replace letters according to algorithm
|
22
|
-
# algorithm conversion maps chars to ASCII value - 55
|
23
|
-
def transpose(iban)
|
24
|
-
iban.upcase.gsub(/[A-Z]/) do |s|
|
25
|
-
USE_ORD ? (s[0].ord - 55).to_s : (s[0].to_i - 55).to_s
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|