prawn-swiss_qr_bill 0.4.2 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +37 -7
- data/lib/prawn/swiss_qr_bill/bill.rb +3 -2
- data/lib/prawn/swiss_qr_bill/corner_box.rb +2 -0
- data/lib/prawn/swiss_qr_bill/extension.rb +2 -2
- data/lib/prawn/swiss_qr_bill/qr/data.rb +76 -16
- data/lib/prawn/swiss_qr_bill/reference.rb +98 -0
- data/lib/prawn/swiss_qr_bill/sections/payment_information.rb +2 -2
- data/lib/prawn/swiss_qr_bill/sections/qr_code.rb +9 -7
- data/lib/prawn/swiss_qr_bill/sections/section.rb +2 -1
- data/lib/prawn/swiss_qr_bill/sections.rb +2 -2
- data/lib/prawn/swiss_qr_bill/specifications.rb +1 -0
- data/lib/prawn/swiss_qr_bill/version.rb +1 -1
- data/lib/prawn/swiss_qr_bill.rb +1 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38df96b8ac1e36c19b8e887a1704dc3af8494bec29fa2cbd99f4e7d536079b09
|
4
|
+
data.tar.gz: a996978e775f4a7cbbdefce2ebec4b2e6fc1ba12d3916da6b6ee9eed22b4a754
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b5f1530805035de0d2a744f1ac3ed83520710dfc4de4bb3b0b01fcaf430f41fbe3fb86720c0f1dcb41cfbdfeedf9be6bdf9d28bf9bb7fe2a4c90ed32f982d48a
|
7
|
+
data.tar.gz: d2b5985d953531ad271585cdd6f7bc8f4a223a764254c5b558c87de7f9adb2035e64450410d9d100a7ed0056eb3ef676e9db22c3e7fad79ba968502b56b93828
|
data/README.md
CHANGED
@@ -30,7 +30,7 @@ Define the relevant information for the Swiss QR-bill and render it inside the P
|
|
30
30
|
require 'prawn'
|
31
31
|
require 'prawn/swiss_qr_bill'
|
32
32
|
|
33
|
-
@
|
33
|
+
@bill_data = {
|
34
34
|
creditor: {
|
35
35
|
iban: 'CH08 3080 8004 1110 4136 9',
|
36
36
|
address: {
|
@@ -43,13 +43,15 @@ require 'prawn/swiss_qr_bill'
|
|
43
43
|
amount: 9.90,
|
44
44
|
currency: 'CHF',
|
45
45
|
reference: '00 00000 00000 02202 20202 99991',
|
46
|
-
reference_type: 'QRR'
|
46
|
+
reference_type: 'QRR',
|
47
|
+
unstructured_message: 'Bill number 2202.20202.9999',
|
48
|
+
bill_information: '//S1/10/2202202029999/11/220819'
|
47
49
|
}
|
48
50
|
|
49
51
|
Prawn::Document.generate('output.pdf', page_size: 'A4') do
|
50
52
|
text 'A Swiss QR bill'
|
51
53
|
|
52
|
-
swiss_qr_bill(@
|
54
|
+
swiss_qr_bill(@bill_data)
|
53
55
|
end
|
54
56
|
```
|
55
57
|
|
@@ -57,13 +59,13 @@ This will render the Swiss QR-bill at the bottom of the page:
|
|
57
59
|
|
58
60
|
![Swiss QR-bill Example, PDF](./images/sqb_example_01.png)
|
59
61
|
|
60
|
-
###
|
62
|
+
### Bill data structure
|
61
63
|
|
62
|
-
The following
|
64
|
+
The following data structure for the bill can be specified:
|
63
65
|
|
64
66
|
```ruby
|
65
67
|
# *: mandatory
|
66
|
-
@
|
68
|
+
@bill_data = {
|
67
69
|
creditor: {
|
68
70
|
iban: '<iban>', # *
|
69
71
|
address: { # *
|
@@ -96,9 +98,37 @@ The following options are available:
|
|
96
98
|
|
97
99
|
If `debtor` or `amount` amount is not given, a box will be printed.
|
98
100
|
|
101
|
+
### Options
|
102
|
+
|
103
|
+
Calling `swiss_qr_bill()` method with options:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
# ...
|
107
|
+
Prawn::Document.generate('output.pdf', page_size: 'A4') do
|
108
|
+
# ...
|
109
|
+
|
110
|
+
# raises InvalidIBANError when @bill_data[:creditor][:iban] is invalid
|
111
|
+
swiss_qr_bill(@bill_data, validate: true)
|
112
|
+
end
|
113
|
+
```
|
114
|
+
|
115
|
+
Available options:
|
116
|
+
|
117
|
+
| Option | Data type | Description | Default |
|
118
|
+
| --- | --- | --- | --- |
|
119
|
+
| `validate` | boolean | Validates IBAN and Reference Number and raises several errors | `false` |
|
120
|
+
|
121
|
+
Errors which can be raised during validation:
|
122
|
+
|
123
|
+
* `MissingIBANError`: When IBAN is missing.
|
124
|
+
* `InvalidIBANError`: When IBAN is invalid. It checks for CH-IBAN only.
|
125
|
+
* `InvalidReferenceError`: When reference is invalid. It checks for a valid QRR or SCOR reference
|
126
|
+
|
99
127
|
## Important
|
100
128
|
|
101
|
-
This library
|
129
|
+
This library can validate IBAN (switzerland only) and reference number (types QRR and SCOR).
|
130
|
+
It does not however validate, if the given data is fully valid according to the implementation guidelines.
|
131
|
+
|
102
132
|
Please refer to the implementation guidelines and the Swiss QR-bill validaton
|
103
133
|
portal by SIX below.
|
104
134
|
|
@@ -6,16 +6,17 @@ module Prawn
|
|
6
6
|
class Bill
|
7
7
|
FONT_DIR = File.expand_path("#{__dir__}/../../../assets/fonts")
|
8
8
|
|
9
|
-
def initialize(document, data)
|
9
|
+
def initialize(document, data, options = {})
|
10
10
|
@doc = document
|
11
11
|
@data = data
|
12
|
+
@options = options || {}
|
12
13
|
end
|
13
14
|
|
14
15
|
def draw
|
15
16
|
set_font
|
16
17
|
|
17
18
|
@doc.canvas do
|
18
|
-
Sections.draw_all(@doc, @data)
|
19
|
+
Sections.draw_all(@doc, @data, @options)
|
19
20
|
CuttingLines.new(@doc).draw
|
20
21
|
end
|
21
22
|
end
|
@@ -4,8 +4,8 @@ module Prawn
|
|
4
4
|
module SwissQRBill
|
5
5
|
# Extend prawn with *swiss_qr_bill* methods
|
6
6
|
module Extension
|
7
|
-
def swiss_qr_bill(data)
|
8
|
-
Prawn::SwissQRBill::Bill.new(self, data).draw
|
7
|
+
def swiss_qr_bill(data, options = {})
|
8
|
+
Prawn::SwissQRBill::Bill.new(self, data, options).draw
|
9
9
|
end
|
10
10
|
|
11
11
|
def swiss_qr_bill_sections
|
@@ -3,21 +3,24 @@
|
|
3
3
|
module Prawn
|
4
4
|
module SwissQRBill
|
5
5
|
module QR
|
6
|
+
class MissingIBANError < StandardError; end
|
7
|
+
class InvalidIBANError < StandardError; end
|
8
|
+
class InvalidReferenceError < StandardError; end
|
9
|
+
|
6
10
|
# The data of the Swiss QR-bill
|
7
11
|
#
|
8
12
|
# References:
|
9
13
|
# https://www.paymentstandards.ch/dam/downloads/ig-qr-bill-en.pdf
|
10
14
|
# * Chapter 4, Page 25
|
11
|
-
#
|
12
|
-
# TODO: implement skippable (alt schemas, bill info. fields after trailer)
|
13
|
-
# TODO: check if addr-type has to be mentioned if not given?
|
14
|
-
# OPTIMIZE: implement non-changable?
|
15
15
|
class Data
|
16
|
-
#
|
16
|
+
# Field structure:
|
17
17
|
# * :default => default value to be set, if key is not given
|
18
18
|
# * :format => Proc to call when generating output
|
19
19
|
# * :skippable => Do not output in QR data if not given
|
20
|
-
|
20
|
+
# * :validation => Proc or symbol for validation
|
21
|
+
# * if Proc given: will be called with value as argument
|
22
|
+
# * if symbol given: method "#{:symbol}_validator" will be called with value as argument
|
23
|
+
Field = Struct.new(:default, :format, :skippable, :validation)
|
21
24
|
|
22
25
|
# Available fields of the QR code data, ordered.
|
23
26
|
FIELDS = {
|
@@ -26,9 +29,7 @@ module Prawn
|
|
26
29
|
version: Field.new('0200'),
|
27
30
|
# fixed: 1
|
28
31
|
coding: Field.new('1'),
|
29
|
-
|
30
|
-
# iban: Field.new(nil, ->(value) { value.delete(' ') }),
|
31
|
-
iban: Field.new,
|
32
|
+
iban: Field.new(nil, nil, false, :iban),
|
32
33
|
# enum: S, K
|
33
34
|
creditor_address_type: Field.new('K'),
|
34
35
|
creditor_address_name: Field.new,
|
@@ -59,22 +60,20 @@ module Prawn
|
|
59
60
|
debtor_address_country: Field.new,
|
60
61
|
# enum: QRR, SCOR, NON
|
61
62
|
reference_type: Field.new('NON'),
|
62
|
-
reference: Field.new(nil, ->(
|
63
|
+
reference: Field.new(nil, ->(v) { v && v.delete(' ') }, false, :reference),
|
63
64
|
unstructured_message: Field.new,
|
64
65
|
# fixed: EPD
|
65
66
|
trailer: Field.new('EPD'),
|
66
|
-
|
67
|
-
# additional:
|
68
|
-
|
69
67
|
bill_information: Field.new(nil, nil, true),
|
70
68
|
# key-value pairs:
|
71
69
|
alternative_parameters: Field.new(nil, nil, true)
|
72
70
|
}.freeze
|
73
71
|
|
74
|
-
# TODO: check if all fields can be changed by user?
|
75
72
|
attr_accessor(*FIELDS.keys)
|
76
73
|
|
77
|
-
def initialize(fields = {})
|
74
|
+
def initialize(fields = {}, options = {})
|
75
|
+
@options = options || {}
|
76
|
+
|
78
77
|
# set defaults
|
79
78
|
FIELDS.each_key do |field|
|
80
79
|
instance_variable_set("@#{field}", FIELDS[field].default)
|
@@ -87,18 +86,79 @@ module Prawn
|
|
87
86
|
end
|
88
87
|
|
89
88
|
def generate
|
89
|
+
validate if @options[:validate]
|
90
|
+
|
90
91
|
stack = []
|
91
|
-
FIELDS.
|
92
|
+
FIELDS.each_key do |k|
|
92
93
|
var = instance_variable_get("@#{k}")
|
93
94
|
|
95
|
+
# TODO: fix possible wrong format if alt parameters (last one) is given
|
94
96
|
next if FIELDS[k][:skippable] && var.nil?
|
95
97
|
|
98
|
+
# TODO: use #process; generate method should only call validate, then process, then render as string
|
96
99
|
var = FIELDS[k][:format].call(var) if FIELDS[k][:format].is_a?(Proc)
|
97
100
|
|
98
101
|
stack << var
|
99
102
|
end
|
100
103
|
stack.join("\r\n")
|
101
104
|
end
|
105
|
+
|
106
|
+
def process
|
107
|
+
FIELDS.each_key do |k|
|
108
|
+
var = instance_variable_get("@#{k}")
|
109
|
+
|
110
|
+
instance_variable_set("@#{k}", FIELDS[k][:format].call(var)) if FIELDS[k][:format].is_a?(Proc)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def validate
|
115
|
+
FIELDS.each_key do |k|
|
116
|
+
next unless FIELDS[k][:validation]
|
117
|
+
|
118
|
+
var = instance_variable_get("@#{k}")
|
119
|
+
|
120
|
+
call_validator(FIELDS[k][:validation], var)
|
121
|
+
end
|
122
|
+
|
123
|
+
true
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def call_validator(validator, value)
|
129
|
+
case validator
|
130
|
+
when Proc
|
131
|
+
# NOTE: currently not in use
|
132
|
+
# :nocov:
|
133
|
+
validator.call(value)
|
134
|
+
# :nocov:
|
135
|
+
when Symbol
|
136
|
+
send("#{validator}_validator", value)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def iban_validator(value)
|
141
|
+
# IBAN must be given
|
142
|
+
raise MissingIBANError, 'IBAN is missing' if value.nil? || value.empty?
|
143
|
+
|
144
|
+
# IBAN must be valid
|
145
|
+
iban = IBAN.new(value)
|
146
|
+
raise InvalidIBANError, "IBAN #{iban.prettify} is invalid" unless iban.valid?
|
147
|
+
|
148
|
+
true
|
149
|
+
end
|
150
|
+
|
151
|
+
def reference_validator(value)
|
152
|
+
reference = Reference.new(value, reference_type)
|
153
|
+
|
154
|
+
unless %w[QRR SCOR].include?(reference_type)
|
155
|
+
raise InvalidReferenceError, "Reference Type #{reference_type} invalid. Allowed: QRR, SCOR"
|
156
|
+
end
|
157
|
+
|
158
|
+
raise InvalidReferenceError, "Reference #{value} is invalid" unless reference.valid?
|
159
|
+
|
160
|
+
true
|
161
|
+
end
|
102
162
|
end
|
103
163
|
end
|
104
164
|
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Prawn
|
4
|
+
module SwissQRBill
|
5
|
+
# Check validity of reference number
|
6
|
+
#
|
7
|
+
# QRR reference:
|
8
|
+
# Refer to the implementation guides of SIX: https://www.paymentstandards.ch/dam/downloads/ig-qr-bill-en.pdf
|
9
|
+
class Reference
|
10
|
+
MODULO_TABLE = [
|
11
|
+
[0, 9, 4, 6, 8, 2, 7, 1, 3, 5],
|
12
|
+
[9, 4, 6, 8, 2, 7, 1, 3, 5, 0],
|
13
|
+
[4, 6, 8, 2, 7, 1, 3, 5, 0, 9],
|
14
|
+
[6, 8, 2, 7, 1, 3, 5, 0, 9, 4],
|
15
|
+
[8, 2, 7, 1, 3, 5, 0, 9, 4, 6],
|
16
|
+
[2, 7, 1, 3, 5, 0, 9, 4, 6, 8],
|
17
|
+
[7, 1, 3, 5, 0, 9, 4, 6, 8, 2],
|
18
|
+
[1, 3, 5, 0, 9, 4, 6, 8, 2, 7],
|
19
|
+
[3, 5, 0, 9, 4, 6, 8, 2, 7, 1],
|
20
|
+
[5, 0, 9, 4, 6, 8, 2, 7, 1, 3]
|
21
|
+
].freeze
|
22
|
+
|
23
|
+
def initialize(reference, type = 'QRR')
|
24
|
+
@type = type
|
25
|
+
@reference = standardize(reference)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Number without check digit
|
29
|
+
def number
|
30
|
+
case @type
|
31
|
+
when 'QRR'
|
32
|
+
@reference[0...-1]
|
33
|
+
when 'SCOR'
|
34
|
+
@reference[4..-1]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# QRR: Last number, the check digit
|
39
|
+
# SCOR: 2 numbers after RF
|
40
|
+
def check_digits
|
41
|
+
case @type
|
42
|
+
when 'QRR'
|
43
|
+
@reference[-1].to_i
|
44
|
+
when 'SCOR'
|
45
|
+
@reference[2..3]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def valid?
|
50
|
+
valid_check_digits? && valid_length?
|
51
|
+
end
|
52
|
+
|
53
|
+
def valid_check_digits?
|
54
|
+
case @type
|
55
|
+
when 'QRR'
|
56
|
+
check_digits == Reference.modulo10_recursive(number)
|
57
|
+
when 'SCOR'
|
58
|
+
scor_to_i % 97 == 1
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# NOTE: for SCOR only
|
63
|
+
def scor_to_i
|
64
|
+
"#{number}RF#{check_digits}".gsub(/[A-Z]/) { |c| c.ord - 55 }.to_i
|
65
|
+
end
|
66
|
+
|
67
|
+
# According to the payment standards (PDF, Annex B):
|
68
|
+
# The QR reference consists of 27 positions and is numerical.
|
69
|
+
def valid_length?
|
70
|
+
case @type
|
71
|
+
when 'QRR'
|
72
|
+
@reference.length <= 27
|
73
|
+
when 'SCOR'
|
74
|
+
@reference.length <= 25
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Generate a check digit with modulo 10 recursive:
|
79
|
+
#
|
80
|
+
# Can be used as an instance method:
|
81
|
+
#
|
82
|
+
# Prawn::SwissQRBill::Reference.modulo10_recursive("2202202029999")
|
83
|
+
# # will return 1
|
84
|
+
def self.modulo10_recursive(reference)
|
85
|
+
numbers = reference.to_s.chars.map(&:to_i)
|
86
|
+
report = numbers.inject(0) { |memo, c| MODULO_TABLE[memo][c] }
|
87
|
+
|
88
|
+
(10 - report) % 10
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def standardize(reference)
|
94
|
+
reference.to_s.strip.gsub(/\s+/, '').upcase
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -13,7 +13,7 @@ module Prawn
|
|
13
13
|
box do
|
14
14
|
draw_payable_to
|
15
15
|
draw_reference if @data.key?(:reference)
|
16
|
-
draw_additional_information if @data.key?(:
|
16
|
+
draw_additional_information if @data.key?(:unstructured_message) || @data.key?(:bill_information)
|
17
17
|
draw_payable_by
|
18
18
|
end
|
19
19
|
end
|
@@ -37,7 +37,7 @@ module Prawn
|
|
37
37
|
|
38
38
|
def draw_additional_information
|
39
39
|
label I18n.t('additional_info', scope: i18n_scope)
|
40
|
-
content @data[:
|
40
|
+
content [@data[:unstructured_message], @data[:bill_information]].join(' ')
|
41
41
|
|
42
42
|
line_spacing
|
43
43
|
end
|
@@ -11,8 +11,6 @@ module Prawn
|
|
11
11
|
#
|
12
12
|
# swiss_cross.png => 166px ~> 7.mm
|
13
13
|
# QR-code: 1090px <~ 46.mm
|
14
|
-
#
|
15
|
-
# TODO: iban check -> raise exception if configured
|
16
14
|
class QRCode < Section
|
17
15
|
KEY = 'payment.qr_code'
|
18
16
|
|
@@ -26,6 +24,7 @@ module Prawn
|
|
26
24
|
creditor_address_line1: %i[creditor address line1],
|
27
25
|
creditor_address_line2: %i[creditor address line2],
|
28
26
|
creditor_address_postal_code: %i[creditor address postal_code],
|
27
|
+
creditor_address_city: %i[creditor address city],
|
29
28
|
creditor_address_country: %i[creditor address country],
|
30
29
|
debtor_address_type: %i[debtor address type],
|
31
30
|
debtor_address_name: %i[debtor address name],
|
@@ -37,7 +36,9 @@ module Prawn
|
|
37
36
|
amount: [:amount],
|
38
37
|
currency: [:currency],
|
39
38
|
reference: [:reference],
|
40
|
-
reference_type: [:reference_type]
|
39
|
+
reference_type: [:reference_type],
|
40
|
+
unstructured_message: [:unstructured_message],
|
41
|
+
bill_information: [:bill_information]
|
41
42
|
}.freeze
|
42
43
|
|
43
44
|
def draw
|
@@ -71,16 +72,17 @@ module Prawn
|
|
71
72
|
end
|
72
73
|
|
73
74
|
def generate_qr_data(data)
|
74
|
-
|
75
|
+
flat_data = {}
|
75
76
|
MAPPING.each_key do |key|
|
76
|
-
# check if the exists
|
77
|
+
# check if the key exists
|
77
78
|
next unless deep_key?(data, MAPPING[key])
|
78
79
|
|
79
|
-
|
80
|
+
flat_data[key] = data.dig(*MAPPING[key])
|
80
81
|
end
|
81
82
|
|
82
83
|
iban = IBAN.new(data[:creditor][:iban])
|
83
|
-
|
84
|
+
|
85
|
+
qr_data = QR::Data.new(flat_data.merge(iban: iban.code), validate: @options[:validate])
|
84
86
|
qr_data.generate
|
85
87
|
end
|
86
88
|
|
@@ -19,13 +19,14 @@ module Prawn
|
|
19
19
|
# specifications for subclass' section, @see Specification for details
|
20
20
|
attr_accessor :specs
|
21
21
|
|
22
|
-
def initialize(document, data)
|
22
|
+
def initialize(document, data, options = {})
|
23
23
|
unless self.class.const_defined?(:KEY)
|
24
24
|
raise NotImplementedError, "constant KEY not defined in class #{self.class}"
|
25
25
|
end
|
26
26
|
|
27
27
|
@doc = document
|
28
28
|
@data = data
|
29
|
+
@options = options || {}
|
29
30
|
|
30
31
|
load_specs
|
31
32
|
end
|
@@ -19,9 +19,9 @@ module Prawn
|
|
19
19
|
].freeze
|
20
20
|
|
21
21
|
# Draw all sections in the right order.
|
22
|
-
def self.draw_all(document, data)
|
22
|
+
def self.draw_all(document, data, options = {})
|
23
23
|
SECTION_CLASSES.each do |klass|
|
24
|
-
klass.new(document, data).draw
|
24
|
+
klass.new(document, data, options).draw
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
data/lib/prawn/swiss_qr_bill.rb
CHANGED
@@ -17,6 +17,7 @@ require 'prawn/swiss_qr_bill/helpers/box_helper'
|
|
17
17
|
|
18
18
|
require 'prawn/swiss_qr_bill/qr/data'
|
19
19
|
require 'prawn/swiss_qr_bill/iban'
|
20
|
+
require 'prawn/swiss_qr_bill/reference'
|
20
21
|
require 'prawn/swiss_qr_bill/padded_box'
|
21
22
|
require 'prawn/swiss_qr_bill/corner_box'
|
22
23
|
require 'prawn/swiss_qr_bill/cutting_lines'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prawn-swiss_qr_bill
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mischa Schindowski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -179,6 +179,7 @@ files:
|
|
179
179
|
- lib/prawn/swiss_qr_bill/iban.rb
|
180
180
|
- lib/prawn/swiss_qr_bill/padded_box.rb
|
181
181
|
- lib/prawn/swiss_qr_bill/qr/data.rb
|
182
|
+
- lib/prawn/swiss_qr_bill/reference.rb
|
182
183
|
- lib/prawn/swiss_qr_bill/sections.rb
|
183
184
|
- lib/prawn/swiss_qr_bill/sections/payment_amount.rb
|
184
185
|
- lib/prawn/swiss_qr_bill/sections/payment_further_information.rb
|
@@ -214,7 +215,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
214
215
|
- !ruby/object:Gem::Version
|
215
216
|
version: '0'
|
216
217
|
requirements: []
|
217
|
-
rubygems_version: 3.
|
218
|
+
rubygems_version: 3.2.32
|
218
219
|
signing_key:
|
219
220
|
specification_version: 4
|
220
221
|
summary: Swiss QR-Bill PDFs in Ruby with Prawn
|