Class: Prawn::SwissQRBill::Reference

Inherits:
Object
  • Object
show all
Defined in:
lib/prawn/swiss_qr_bill/reference.rb

Overview

Check validity of reference number

QRR reference: Refer to the implementation guides of SIX: www.paymentstandards.ch/dam/downloads/ig-qr-bill-en.pdf

Constant Summary collapse

MODULO_TABLE =
[
  [0, 9, 4, 6, 8, 2, 7, 1, 3, 5],
  [9, 4, 6, 8, 2, 7, 1, 3, 5, 0],
  [4, 6, 8, 2, 7, 1, 3, 5, 0, 9],
  [6, 8, 2, 7, 1, 3, 5, 0, 9, 4],
  [8, 2, 7, 1, 3, 5, 0, 9, 4, 6],
  [2, 7, 1, 3, 5, 0, 9, 4, 6, 8],
  [7, 1, 3, 5, 0, 9, 4, 6, 8, 2],
  [1, 3, 5, 0, 9, 4, 6, 8, 2, 7],
  [3, 5, 0, 9, 4, 6, 8, 2, 7, 1],
  [5, 0, 9, 4, 6, 8, 2, 7, 1, 3]
].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(reference, type = 'QRR') ⇒ Reference

Returns a new instance of Reference.



23
24
25
26
# File 'lib/prawn/swiss_qr_bill/reference.rb', line 23

def initialize(reference, type = 'QRR')
  @type = type
  @reference = standardize(reference)
end

Class Method Details

.modulo10_recursive(reference) ⇒ Object

Generate a check digit with modulo 10 recursive:

Can be used as an instance method:

Prawn::SwissQRBill::Reference.modulo10_recursive("2202202029999")
# will return 1


84
85
86
87
88
89
# File 'lib/prawn/swiss_qr_bill/reference.rb', line 84

def self.modulo10_recursive(reference)
  numbers = reference.to_s.chars.map(&:to_i)
  report = numbers.inject(0) { |memo, c| MODULO_TABLE[memo][c] }

  (10 - report) % 10
end

Instance Method Details

#check_digitsObject

QRR: Last number, the check digit SCOR: 2 numbers after RF



40
41
42
43
44
45
46
47
# File 'lib/prawn/swiss_qr_bill/reference.rb', line 40

def check_digits
  case @type
  when 'QRR'
    @reference[-1].to_i
  when 'SCOR'
    @reference[2..3]
  end
end

#numberObject

Number without check digit



29
30
31
32
33
34
35
36
# File 'lib/prawn/swiss_qr_bill/reference.rb', line 29

def number
  case @type
  when 'QRR'
    @reference[0...-1]
  when 'SCOR'
    @reference[4..-1]
  end
end

#scor_to_iObject

NOTE: for SCOR only



63
64
65
# File 'lib/prawn/swiss_qr_bill/reference.rb', line 63

def scor_to_i
  "#{number}RF#{check_digits}".gsub(/[A-Z]/) { |c| c.ord - 55 }.to_i
end

#valid?Boolean

Returns:

  • (Boolean)


49
50
51
# File 'lib/prawn/swiss_qr_bill/reference.rb', line 49

def valid?
  valid_check_digits? && valid_length?
end

#valid_check_digits?Boolean

Returns:

  • (Boolean)


53
54
55
56
57
58
59
60
# File 'lib/prawn/swiss_qr_bill/reference.rb', line 53

def valid_check_digits?
  case @type
  when 'QRR'
    check_digits == Reference.modulo10_recursive(number)
  when 'SCOR'
    scor_to_i % 97 == 1
  end
end

#valid_length?Boolean

According to the payment standards (PDF, Annex B): The QR reference consists of 27 positions and is numerical.

Returns:

  • (Boolean)


69
70
71
72
73
74
75
76
# File 'lib/prawn/swiss_qr_bill/reference.rb', line 69

def valid_length?
  case @type
  when 'QRR'
    @reference.length <= 27
  when 'SCOR'
    @reference.length <= 25
  end
end