From 60f35a4aa72eb6022e48f14d3327f377b27bacd8 Mon Sep 17 00:00:00 2001 From: 800a7b32 <1313697+800a7b32@users.noreply.github.com> Date: Wed, 1 Jun 2022 16:58:02 +0000 Subject: [PATCH 01/14] Update documentation to guide development --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index d0759a1..51bb8a5 100644 --- a/README.md +++ b/README.md @@ -45,12 +45,15 @@ QRBills.create_creditor_reference("MTR81UUWZYO48NY55NP3") ```ruby params[:output_params][:format] = "html" # OR +params[:output_params][:format] = "prawn" +# OR params[:output_params][:format] = "png" # OR params[:output_params][:format] = "svg" ``` * `html` returns a full qr-bill as a html-template string, uses `params[:qrcode_format]` for the qrcode format which supports `png` and `svg`. Defaults to `png`. +* `prawn` returns a full qr-bill in pure Ruby for inclusion in a [Prawn PDF template](https://github.com/prawnpdf/prawn), uses `params[:qrcode_format]` for the qrcode format which supports `png` and `svg`. Defaults to `png`. * `png` returns the qrcode of the qr-bill as a ChunkyPNG::Image object. * `svg` returns the qrcode of the qr-bill as a svg string. From f12e6dbb56a1af4f98c037871ae639fca0f08989 Mon Sep 17 00:00:00 2001 From: 800a7b32 <1313697+800a7b32@users.noreply.github.com> Date: Wed, 1 Jun 2022 16:59:13 +0000 Subject: [PATCH 02/14] bump ruby version --- .ruby-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ruby-version b/.ruby-version index 860487c..49cdd66 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.1 +2.7.6 From 91e149cbc25151ab1774f6dd6dbe31e81c36961f Mon Sep 17 00:00:00 2001 From: 800a7b32 <1313697+800a7b32@users.noreply.github.com> Date: Wed, 1 Jun 2022 17:00:36 +0000 Subject: [PATCH 03/14] bump required ruby version in gemspec --- qr-bills.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qr-bills.gemspec b/qr-bills.gemspec index 468f258..d38bb01 100644 --- a/qr-bills.gemspec +++ b/qr-bills.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |s| "source_code_uri" => "https://github.com/damoiser/qr-bills", "wiki_uri" => "https://github.com/damoiser/qr-bills" } - s.required_ruby_version = ">= 2.7.1" + s.required_ruby_version = ">= 2.7.6" s.add_runtime_dependency("i18n", ">= 1.8.3", "< 2") s.add_runtime_dependency("rqrcode", ">= 2.1", "< 3") s.add_development_dependency("rspec", "~> 3.9") From b0046bba190c7eb2e1eb872ba10e60564ee9458f Mon Sep 17 00:00:00 2001 From: 800a7b32 <1313697+800a7b32@users.noreply.github.com> Date: Wed, 1 Jun 2022 17:10:16 +0000 Subject: [PATCH 04/14] create spec for qr-prawn --- spec/qr-prawn-layout_spec.rb | 134 +++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 spec/qr-prawn-layout_spec.rb diff --git a/spec/qr-prawn-layout_spec.rb b/spec/qr-prawn-layout_spec.rb new file mode 100644 index 0000000..f59ff10 --- /dev/null +++ b/spec/qr-prawn-layout_spec.rb @@ -0,0 +1,134 @@ +require 'i18n' +require 'fileutils' +require 'qr-bills/qr-prawn-layout' +require 'qr-bills/qr-params' + +RSpec.configure do |config| + config.before(:each) do + @params = QRParams.get_qr_params + @params[:fonts][:eot] = "../web/assets/fonts/LiberationSans-Regular.eot" + @params[:fonts][:woff] = "../web/assets/fonts/LiberationSans-Regular.woff" + @params[:fonts][:ttf] = "../web/assets/fonts/LiberationSans-Regular.ttf" + @params[:fonts][:svg] = "../web/assets/fonts/LiberationSans-Regular.svg" + @params[:locales][:path] = "config/locales/" + @params[:qrcode_format] = 'png' + @params[:bill_params][:creditor][:iban] = "CH9300762011623852957" + @params[:bill_params][:creditor][:address][:type] = "S" + @params[:bill_params][:creditor][:address][:name] = "Compagnia di assicurazione forma & scalciante" + @params[:bill_params][:creditor][:address][:line1] = "Via cantonale" + @params[:bill_params][:creditor][:address][:line2] = "24" + @params[:bill_params][:creditor][:address][:postal_code] = "3000" + @params[:bill_params][:creditor][:address][:town] = "Lugano" + @params[:bill_params][:creditor][:address][:country] = "CH" + @params[:bill_params][:amount] = 12345.15 + @params[:bill_params][:currency] = "CHF" + @params[:bill_params][:debtor][:address][:type] = "S" + @params[:bill_params][:debtor][:address][:name] = "Foobar Barfoot" + @params[:bill_params][:debtor][:address][:line1] = "Via cantonale" + @params[:bill_params][:debtor][:address][:line2] = "25" + @params[:bill_params][:debtor][:address][:postal_code] = "3001" + @params[:bill_params][:debtor][:address][:town] = "Comano" + @params[:bill_params][:debtor][:address][:country] = "CH" + @params[:bill_params][:reference] = "RF89MTR81UUWZYO48NY55NP3" + @params[:bill_params][:reference_type] = "SCOR" + @params[:bill_params][:additionally_information] = "pagamento riparazione monopattino" + + I18n.load_path << File.join(@params[:locales][:path], "qrbills.it.yml") + I18n.load_path << File.join(@params[:locales][:path], "qrbills.en.yml") + I18n.load_path << File.join(@params[:locales][:path], "qrbills.de.yml") + I18n.load_path << File.join(@params[:locales][:path], "qrbills.fr.yml") + I18n.default_locale = :it + end +end + +RSpec.describe "QRPRAWNLayout" do + before do + FileUtils.mkdir_p "#{Dir.pwd}/tmp/" + File.delete filepath if File.exist?(filepath) + end + + let(:filepath) { "#{Dir.pwd}/tmp/prawn-layout.pdf" } + + describe "layout generation" do + before do + @params[:qrcode_format] = 'png' + end + + it "successfully generates prawn/ruby layout + qr code" do + expect{QRPRAWNLayout.create(@params)}.not_to raise_error + end + + it "generates legacy png qrcode" do + @params[:qrcode_format] = nil + @params[:qrcode_filepath] = "#{Dir.pwd}/tmp/qrcode-html.png" + + IO.binwrite("#{Dir.pwd}/tmp/prawn-layout.pdf", QRPRAWNLayout.create(@params).to_s) + expect(File.exist?(filepath)).to be_truthy + expect(File.exist?("#{Dir.pwd}/tmp/qrcode-html.png")).to be_truthy + end + + it "generates png qrcode" do + prawn_output = QRPRAWNLayout.create(@params).to_s + IO.binwrite(filepath, prawn_output) + expect(File.exist?(filepath)).to be_truthy + + # TODO + # Parse generated PDF and determine if it has QR code as ChunkyPNG + # expect(prawn_output).to include("data:image/png;base64,") + end + + it "generates svg qrcode" do + @params[:qrcode_format] = 'svg' + + prawn_output = QRPRAWNLayout.create(@params).to_s + IO.binwrite(filepath, prawn_output) + expect(File.exist?(filepath)).to be_truthy + + # TODO + # Parse generated PDF and determine if it has QR code as svg + # expect(prawn_output).to include("data:image/svg+xml;charset=utf-8,") + end + + it "does not overwrite locale" do + @params[:bill_params][:language] = :de + + QRPRAWNLayout.create(@params) + + expect(I18n.locale).to be :it + end + + it "rounds correctly (1)" do + prawn_output = QRPRAWNLayout.create(@params).to_s + + IO.binwrite(filepath, prawn_output) + expect(File.exist?(filepath)).to be_truthy + + # TODO + # expect(prawn_output).to include("12345.15") + end + + it "rounds correctly (2)" do + @params[:bill_params][:amount] = 12345.1 + + prawn_output = QRPRAWNLayout.create(@params).to_s + + IO.binwrite(filepath, prawn_output) + expect(File.exist?(filepath)).to be_truthy + + # TODO + # expect(prawn_output).to include("12345.10") + end + + it "rounds correctly (3)" do + @params[:bill_params][:amount] = 12345.10 + + prawn_output = QRPRAWNLayout.create(@params).to_s + + IO.binwrite(filepath, prawn_output) + expect(File.exist?(filepath)).to be_truthy + + # TODO + # expect(prawn_output).to include("12345.10") + end + end +end From 52bd8c7e731149ab3c84a2c16383fec92640076c Mon Sep 17 00:00:00 2001 From: 800a7b32 <1313697+800a7b32@users.noreply.github.com> Date: Wed, 1 Jun 2022 17:12:52 +0000 Subject: [PATCH 05/14] add case/when to support prawn --- lib/qr-bills.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/qr-bills.rb b/lib/qr-bills.rb index 6602684..d472ef9 100644 --- a/lib/qr-bills.rb +++ b/lib/qr-bills.rb @@ -2,6 +2,7 @@ require 'qr-bills/qr-exceptions' require 'qr-bills/qr-params' require 'qr-bills/qr-html-layout' +require 'qr-bills/qr-prawn-layout' require 'qr-bills/qr-creditor-reference' module QRBills @@ -19,6 +20,8 @@ def self.generate(qr_params) output = case qr_params[:output_params][:format] when 'html' QRHTMLLayout.create(qr_params) + when 'prawn' + QRPRAWNLayout.create(qr_params) else QRGenerator.create(qr_params, qr_params[:qrcode_filepath]) end From 708660496a5826dd7e489049b2fcb4ea13cda5ae Mon Sep 17 00:00:00 2001 From: 800a7b32 <1313697+800a7b32@users.noreply.github.com> Date: Wed, 1 Jun 2022 17:15:56 +0000 Subject: [PATCH 06/14] Placeholder for qr-prawn-layout --- lib/qr-bills/qr-prawn-layout.rb | 256 ++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 lib/qr-bills/qr-prawn-layout.rb diff --git a/lib/qr-bills/qr-prawn-layout.rb b/lib/qr-bills/qr-prawn-layout.rb new file mode 100644 index 0000000..000054c --- /dev/null +++ b/lib/qr-bills/qr-prawn-layout.rb @@ -0,0 +1,256 @@ +require 'qr-bills/qr-generator' + +module QRPRAWNLayout + def self.create(params) + qrcode = QRGenerator.create(params, params[:qrcode_filepath]) + params[:qrcode_filepath] = convert_qrcode_to_data_url(qrcode) + prawn_layout(params) + end + + def self.convert_qrcode_to_data_url(qrcode) + case qrcode + when ChunkyPNG::Image + qrcode.to_data_url + else + # Stolen from sprockets + # https://github.com/rails/sprockets/blob/0f3e0e93dabafa8f3027e8036e40fd08902688c8/lib/sprockets/context.rb#L295-L303 + data = CGI.escape(qrcode) + data.gsub!('%3D', '=') + data.gsub!('%3A', ':') + data.gsub!('%2F', '/') + data.gsub!('%27', "'") + data.tr!('+', ' ') + + "data:image/svg+xml;charset=utf-8,#{data}" + end + end + + def self.prawn_layout(params) + I18n.with_locale(params[:bill_params][:language]) do + layout = "