hexapdf-extras 1.1.1 → 1.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.rdoc +34 -0
- data/lib/hexapdf/extras/layout/swiss_qr_bill.rb +39 -6
- data/lib/hexapdf/extras/version.rb +1 -1
- data/test/hexapdf/extras/layout/test_swiss_qr_bill.rb +19 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c7f4718bb802b0d1dd228a9fa22fb44ed10dd95402d72c664d937dc8368c5c2
|
4
|
+
data.tar.gz: 7a8111bdb4d323ae5ca910bb215c6aacdbb0799ea05a264a5d4d459a7b21c67c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdf857f06fc000adb0a716bcb4d039b314a0acd3f424a2e39f370bf61851741467f4b3e6319b02d7d0f86d95179ab399ad88cdf0ba95f2202efbae9e422c3ef1
|
7
|
+
data.tar.gz: a9ba5813153564d05eff9c10e538a1793c3c6f469025969d50e17ffeb2755e64c7b2c57d88f4a0acb18ef1dfdc853f22d8238fb559e665261134bae5c44ff850
|
data/README.rdoc
CHANGED
@@ -36,3 +36,37 @@ for details.
|
|
36
36
|
|
37
37
|
Note: There was a {bug in poppler}[https://gitlab.freedesktop.org/poppler/poppler/-/issues/1281]
|
38
38
|
(already fixed) which leads to invalid rendering in Okular (as of 2022-08-06).
|
39
|
+
|
40
|
+
|
41
|
+
=== Swiss QR-bill generator
|
42
|
+
|
43
|
+
This extension provides a box class for the document layouting facilities of HexaPDF to easily
|
44
|
+
create a {Swiss QR-bill}[https://www.six-group.com/en/products-services/banking-services/payment-standardization/standards/qr-bill.html]:
|
45
|
+
|
46
|
+
HexaPDF::Composer.create("sample-qr-bill.pdf", margin: 0) do |composer|
|
47
|
+
data = {
|
48
|
+
lang: :de,
|
49
|
+
creditor: {
|
50
|
+
iban: "CH44 3199 9123 0008 8901 2",
|
51
|
+
name: "Max Muster & Söhne",
|
52
|
+
address_line1: "Musterstrasse",
|
53
|
+
address_line2: "123",
|
54
|
+
postal_code: "8000",
|
55
|
+
town: "Seldwyla",
|
56
|
+
country: "CH",
|
57
|
+
},
|
58
|
+
debtor: {
|
59
|
+
address_type: :combined,
|
60
|
+
name: "Simon Muster",
|
61
|
+
address_line1: "Musterstrasse 1",
|
62
|
+
address_line2: "8000 Seldwyla",
|
63
|
+
country: "CH"
|
64
|
+
},
|
65
|
+
amount: 2500.25,
|
66
|
+
currency: 'CHF',
|
67
|
+
}
|
68
|
+
composer.swiss_qr_bill(data: data, style: {valign: :bottom})
|
69
|
+
end
|
70
|
+
|
71
|
+
See {HexaPDF::Extras::Layout::SwissQRBill}[https://hexapdf-extras.gettalong.org/api/HexaPDF/Extras/Layout/SwissQRBill.html]
|
72
|
+
for details.
|
@@ -66,8 +66,8 @@ module HexaPDF
|
|
66
66
|
# following elements:
|
67
67
|
#
|
68
68
|
# :iban::
|
69
|
-
# (required) The IBAN of the creditor (21 characters,
|
70
|
-
#
|
69
|
+
# (required) The IBAN of the creditor (21 characters, only IBANs for CH or LI). The
|
70
|
+
# IBAN is only validated with respect to its check digits.
|
71
71
|
#
|
72
72
|
# :name::
|
73
73
|
# (required) The name of the creditor (maximum 70 characters).
|
@@ -158,7 +158,7 @@ module HexaPDF
|
|
158
158
|
# amount: 2500.25,
|
159
159
|
# currency: 'CHF',
|
160
160
|
# }
|
161
|
-
# composer.swiss_qr_bill(data: data, valign: :bottom)
|
161
|
+
# composer.swiss_qr_bill(data: data, style: {valign: :bottom})
|
162
162
|
# end
|
163
163
|
#
|
164
164
|
# == References
|
@@ -262,6 +262,25 @@ module HexaPDF
|
|
262
262
|
raise Error, "Data field :amount must be between 0.01 and 999_999_999.99"
|
263
263
|
end
|
264
264
|
|
265
|
+
if !@data[:creditor]
|
266
|
+
raise Error, "Data field :creditor is missing"
|
267
|
+
end
|
268
|
+
|
269
|
+
value = @data[:creditor][:iban]
|
270
|
+
if !value
|
271
|
+
raise Error, "Data field :iban of :creditor is missing"
|
272
|
+
end
|
273
|
+
value.gsub!(/\s+/, '')
|
274
|
+
value.upcase!
|
275
|
+
if value.size != 21
|
276
|
+
raise Error, "Data field :iban of :creditor must contain exactly 21 characters"
|
277
|
+
end
|
278
|
+
# https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN
|
279
|
+
result = "#{value[4..-1]}#{value[0, 4]}".gsub(/[A-Z]/) {|c| c.ord - 55 }.to_i % 97
|
280
|
+
unless result == 1
|
281
|
+
raise Error, "Data field :iban of :creditor has invalid check digits"
|
282
|
+
end
|
283
|
+
|
265
284
|
validate_address = lambda do |hash|
|
266
285
|
hash[:address_type] ||= :structured
|
267
286
|
if hash[:address_type] != :structured && hash[:address_type] != :combined
|
@@ -452,7 +471,7 @@ module HexaPDF
|
|
452
471
|
col.text(text('Receipt'), height: 7.mm, style: styles[:section_heading])
|
453
472
|
col.container(height: 56.mm) do |info|
|
454
473
|
info.text(text('Account / Payable to'), style: styles[:receipt_heading])
|
455
|
-
info.text("#{
|
474
|
+
info.text("#{formatted_iban}\n#{address(@data[:creditor])}", style: styles[:receipt_value])
|
456
475
|
|
457
476
|
if @data[:reference_type] != 'NON'
|
458
477
|
info.text(text('Reference'), style: styles[:receipt_heading])
|
@@ -506,11 +525,11 @@ module HexaPDF
|
|
506
525
|
end
|
507
526
|
col.container(height: 85.mm) do |info|
|
508
527
|
info.text(text('Account / Payable to'), style: styles[:payment_heading])
|
509
|
-
info.text("#{
|
528
|
+
info.text("#{formatted_iban}\n#{address(@data[:creditor])}", style: styles[:payment_value])
|
510
529
|
|
511
530
|
if @data[:reference_type] != 'NON'
|
512
531
|
info.text(text('Reference'), style: styles[:payment_heading])
|
513
|
-
info.text(
|
532
|
+
info.text(formatted_reference, style: styles[:payment_value])
|
514
533
|
end
|
515
534
|
|
516
535
|
if @data[:message] || @data[:billing_information]
|
@@ -563,6 +582,11 @@ module HexaPDF
|
|
563
582
|
TEXT_LITERALS.dig(@data[:lang], str) || str
|
564
583
|
end
|
565
584
|
|
585
|
+
# Returns the formatted IBAN.
|
586
|
+
def formatted_iban
|
587
|
+
@data[:creditor][:iban].gsub(/(.{4})/, '\1 ')
|
588
|
+
end
|
589
|
+
|
566
590
|
# Returns a string containing the formatted address for output using the provided data.
|
567
591
|
def address(data)
|
568
592
|
result = +''
|
@@ -584,6 +608,15 @@ module HexaPDF
|
|
584
608
|
a.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1 ") << '.' << b
|
585
609
|
end
|
586
610
|
|
611
|
+
# Returns the reference field correctly formatted.
|
612
|
+
def formatted_reference
|
613
|
+
if @data[:reference_type] == 'QRR'
|
614
|
+
"#{@data[:reference][0, 2]} #{@data[:reference][2..-1].gsub(/(.{5})/, '\1 ').strip}"
|
615
|
+
else
|
616
|
+
@data[:reference].gsub(/(.{4})/, '\1 ').strip
|
617
|
+
end
|
618
|
+
end
|
619
|
+
|
587
620
|
# Creates the content of the QR code using the information provided in #data.
|
588
621
|
def qr_code_data
|
589
622
|
qr_code_data = []
|
@@ -13,7 +13,7 @@ describe HexaPDF::Extras::Layout::SwissQRBill do
|
|
13
13
|
def data
|
14
14
|
@data ||= {
|
15
15
|
creditor: {
|
16
|
-
iban: "
|
16
|
+
iban: "CH4431999123000889012",
|
17
17
|
name: "Max Muster & Söhne",
|
18
18
|
address_line1: "Musterstrasse",
|
19
19
|
address_line2: "123",
|
@@ -64,6 +64,22 @@ describe HexaPDF::Extras::Layout::SwissQRBill do
|
|
64
64
|
assert_equal('NICHT ZUR ZAHLUNG VERWENDEN', create_box(data).data[:message])
|
65
65
|
end
|
66
66
|
|
67
|
+
it "ensures the creditor value exists" do
|
68
|
+
data.delete(:creditor)
|
69
|
+
assert_invalid_data(/:creditor is missing/)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "ensures a correct iban value in the creditor field" do
|
73
|
+
data[:creditor].delete(:iban)
|
74
|
+
assert_invalid_data(/:iban of :creditor is missing/)
|
75
|
+
data[:creditor][:iban] = 'CH44 319 39912300088901 2'
|
76
|
+
assert_invalid_data(/:iban of :creditor.*21/)
|
77
|
+
data[:creditor][:iban] = 'CH4431999123000889013'
|
78
|
+
assert_invalid_data(/:iban of :creditor.*invalid check digits/)
|
79
|
+
data[:creditor][:iban] = 'CH4431999123000889012'
|
80
|
+
assert(create_box(data))
|
81
|
+
end
|
82
|
+
|
67
83
|
it "sets the address type to structured by default" do
|
68
84
|
assert_equal(:structured, create_box(data, width: 10, height: 15).data[:creditor][:address_type])
|
69
85
|
end
|
@@ -220,6 +236,8 @@ describe HexaPDF::Extras::Layout::SwissQRBill do
|
|
220
236
|
it "works with no amount and no debtor" do
|
221
237
|
data.delete(:debtor)
|
222
238
|
data.delete(:amount)
|
239
|
+
data[:reference_type] = 'SCOR'
|
240
|
+
data[:reference] = 'RF48 5000056789012345'
|
223
241
|
assert(@composer.box(:swiss_qr_bill, data: data))
|
224
242
|
end
|
225
243
|
|