commit
2af0fe7c30
2 changed files with 54 additions and 20 deletions
|
@ -1,22 +1,35 @@
|
||||||
class SiretFormatValidator < ActiveModel::EachValidator
|
class SiretFormatValidator < ActiveModel::EachValidator
|
||||||
def validate_each(record,attribute,value)
|
def validate_each(record, attribute, value)
|
||||||
if !(value =~ /^\d{14}$/)
|
if !format_is_valid(value)
|
||||||
record.errors.add(attribute, :format)
|
record.errors.add(attribute, :format)
|
||||||
end
|
end
|
||||||
if value.nil? || (luhn_checksum(value) % 10 != 0)
|
|
||||||
|
if !luhn_passed(value)
|
||||||
record.errors.add(attribute, :checksum)
|
record.errors.add(attribute, :checksum)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
LA_POSTE_SIREN = '356000000'
|
||||||
|
|
||||||
|
def format_is_valid(value)
|
||||||
|
value.match?(/^\d{14}$/)
|
||||||
|
end
|
||||||
|
|
||||||
|
def luhn_passed(value)
|
||||||
|
# Do not enforce Luhn for La Poste SIRET numbers, the only exception to this rule
|
||||||
|
siret_is_attached_to_la_poste(value) || (luhn_checksum(value) % 10 == 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
def siret_is_attached_to_la_poste(value)
|
||||||
|
value[0..8] == LA_POSTE_SIREN
|
||||||
|
end
|
||||||
|
|
||||||
def luhn_checksum(value)
|
def luhn_checksum(value)
|
||||||
accum = 0
|
value.reverse.each_char.map(&:to_i).map.with_index do |digit, index|
|
||||||
value.reverse.each_char.map(&:to_i).each_with_index do |digit, index|
|
|
||||||
t = index.even? ? digit : digit * 2
|
t = index.even? ? digit : digit * 2
|
||||||
t = t - 9 if t >= 10
|
t < 10 ? t : t - 9
|
||||||
accum += t
|
end.sum
|
||||||
end
|
|
||||||
accum
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,26 +1,47 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe Siret, type: :model do
|
describe Siret, type: :model do
|
||||||
let(:valid_siret) { '41816609600051' }
|
subject { Siret.new(siret: siret) }
|
||||||
let(:invalid_siret) { '111111111' }
|
|
||||||
|
|
||||||
context 'with no siret provided' do
|
context 'with no siret provided' do
|
||||||
it { is_expected.to validate_presence_of(:siret) }
|
let(:siret) { '' }
|
||||||
|
|
||||||
|
it { is_expected.to be_invalid }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'init with valid siret' do
|
context 'with a siret that contains letters' do
|
||||||
it { is_expected.to allow_value(valid_siret).for(:siret) }
|
let(:siret) { 'A1B1C6D9E0F0G1' }
|
||||||
|
|
||||||
|
it { is_expected.to be_invalid }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'init with invalid siret' do
|
context 'with a siret that is too short' do
|
||||||
it { is_expected.not_to allow_value(invalid_siret).for(:siret) }
|
let(:siret) { '1234567890' }
|
||||||
|
|
||||||
|
it { is_expected.to be_invalid }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'init with bullshit siret' do
|
context 'with a siret that is too long' do
|
||||||
it { is_expected.not_to allow_value('bullshit').for(:siret) }
|
let(:siret) { '12345678901234567890' }
|
||||||
|
|
||||||
|
it { is_expected.to be_invalid }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'init with a siret that is too long' do
|
context 'with a lunh-invalid siret' do
|
||||||
it { is_expected.not_to allow_value('9' * 15).for(:siret) }
|
let(:siret) { '41816609600052' }
|
||||||
|
|
||||||
|
it { is_expected.to be_invalid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a lunh-invalid La Poste siret' do
|
||||||
|
let(:siret) { '35600000018723' }
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a valid siret' do
|
||||||
|
let(:siret) { '41816609600051' }
|
||||||
|
|
||||||
|
it { is_expected.to be_valid }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue