br_invoices_pdf 0.1.5 → 0.2.0.alpha.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +10 -0
- data/CHANGELOG.md +16 -0
- data/bin/console +5 -3
- data/br_invoices_pdf.gemspec +11 -8
- data/cfe.xml +2 -0
- data/lib/br_invoices_pdf.rb +36 -0
- data/lib/br_invoices_pdf/cfe.rb +10 -0
- data/lib/br_invoices_pdf/cfe/parser.rb +35 -0
- data/lib/br_invoices_pdf/cfe/parser/access_key.rb +19 -0
- data/lib/br_invoices_pdf/cfe/parser/base_parser.rb +19 -0
- data/lib/br_invoices_pdf/cfe/parser/company_attributes.rb +45 -0
- data/lib/br_invoices_pdf/cfe/parser/cpf.rb +15 -0
- data/lib/br_invoices_pdf/cfe/parser/document_number.rb +15 -0
- data/lib/br_invoices_pdf/cfe/parser/fisco_obs.rb +23 -0
- data/lib/br_invoices_pdf/cfe/parser/payment.rb +22 -0
- data/lib/br_invoices_pdf/cfe/parser/payments.rb +45 -0
- data/lib/br_invoices_pdf/cfe/parser/products_data.rb +37 -0
- data/lib/br_invoices_pdf/cfe/parser/sat.rb +25 -0
- data/lib/br_invoices_pdf/cfe/renderer.rb +49 -0
- data/lib/br_invoices_pdf/cfe/renderer/base_renderer.rb +72 -0
- data/lib/br_invoices_pdf/cfe/renderer/company_identification.rb +36 -0
- data/lib/br_invoices_pdf/cfe/renderer/fisco_info.rb +26 -0
- data/lib/br_invoices_pdf/cfe/renderer/header.rb +36 -0
- data/lib/br_invoices_pdf/cfe/renderer/payment_forms.rb +54 -0
- data/lib/br_invoices_pdf/cfe/renderer/product_table.rb +68 -0
- data/lib/br_invoices_pdf/cfe/renderer/qr_code.rb +110 -0
- data/lib/br_invoices_pdf/cfe/renderer/taxes_info.rb +39 -0
- data/lib/br_invoices_pdf/cfe/renderer/totals.rb +50 -0
- data/lib/br_invoices_pdf/errors/invalid_document_type.rb +12 -0
- data/lib/br_invoices_pdf/generator.rb +17 -0
- data/lib/br_invoices_pdf/version.rb +1 -1
- metadata +130 -6
@@ -0,0 +1,25 @@
|
|
1
|
+
module BrInvoicesPdf
|
2
|
+
module Cfe
|
3
|
+
module Parser
|
4
|
+
module Sat
|
5
|
+
extend BaseParser
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
AVAILABLE_UF = { '35' => 'São Paulo' }.freeze
|
10
|
+
|
11
|
+
def execute(xml)
|
12
|
+
{
|
13
|
+
pos_number: locate_element(xml, 'infCFe/ide/numeroCaixa'),
|
14
|
+
ncfe_number: locate_element(xml, 'infCFe/ide/nCFe'),
|
15
|
+
uf: AVAILABLE_UF[locate_element(xml, 'infCFe/ide/cUF')],
|
16
|
+
sat_number: locate_element(xml, 'infCFe/ide/nserieSAT'),
|
17
|
+
emission_date: locate_element(xml, 'infCFe/ide/dEmi'),
|
18
|
+
emission_hour: locate_element(xml, 'infCFe/ide/hEmi'),
|
19
|
+
document_qr_code_signature: locate_element(xml, 'infCFe/ide/assinaturaQRCODE')
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'br_invoices_pdf/cfe/renderer/company_identification'
|
2
|
+
require 'br_invoices_pdf/cfe/renderer/fisco_info'
|
3
|
+
require 'br_invoices_pdf/cfe/renderer/header'
|
4
|
+
require 'br_invoices_pdf/cfe/renderer/payment_forms'
|
5
|
+
require 'br_invoices_pdf/cfe/renderer/product_table'
|
6
|
+
require 'br_invoices_pdf/cfe/renderer/qr_code'
|
7
|
+
require 'br_invoices_pdf/cfe/renderer/taxes_info'
|
8
|
+
require 'br_invoices_pdf/cfe/renderer/totals'
|
9
|
+
|
10
|
+
module BrInvoicesPdf
|
11
|
+
module Cfe
|
12
|
+
module Renderer
|
13
|
+
module_function
|
14
|
+
|
15
|
+
AUTO_HEIGHT_MOCK = 2000
|
16
|
+
|
17
|
+
RENDERERS = [
|
18
|
+
CompanyIdentification,
|
19
|
+
Header,
|
20
|
+
ProductTable,
|
21
|
+
Totals,
|
22
|
+
PaymentForms,
|
23
|
+
TaxesInfo,
|
24
|
+
QrCode,
|
25
|
+
FiscoInfo
|
26
|
+
].freeze
|
27
|
+
|
28
|
+
# :reek:FeatureEnvy
|
29
|
+
def pdf(data, options)
|
30
|
+
page_width = Renderer::BaseRenderer.page_paper_width(options[:page_size])
|
31
|
+
|
32
|
+
Prawn::Document.new(options.merge(page_size: [page_width, AUTO_HEIGHT_MOCK])) do |pdf|
|
33
|
+
pdf_content(pdf, data, page_width)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def pdf_content(pdf, data, page_width)
|
38
|
+
pdf.font_size(7) do
|
39
|
+
RENDERERS.each do |renderer|
|
40
|
+
renderer.execute(pdf, data)
|
41
|
+
end
|
42
|
+
|
43
|
+
page = pdf.page
|
44
|
+
page.dictionary.data[:MediaBox] = [0, pdf.y - page.margins[:bottom], page_width, AUTO_HEIGHT_MOCK]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module BrInvoicesPdf
|
2
|
+
module Cfe
|
3
|
+
module Renderer
|
4
|
+
module BaseRenderer
|
5
|
+
module_function
|
6
|
+
|
7
|
+
ADDRESS_FORMAT = '%s, %s, %s, %s, %s/%s'.freeze
|
8
|
+
def format_address(address)
|
9
|
+
ADDRESS_FORMAT % %i[public_place number complement neighborhood city state].map(&address.method(:[]))
|
10
|
+
end
|
11
|
+
|
12
|
+
def box(pdf, position, width)
|
13
|
+
pdf.bounding_box(position, width: width) do
|
14
|
+
pdf.pad(2) do
|
15
|
+
pdf.indent(2, 2) do
|
16
|
+
yield
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
pdf.stroke_bounds
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# :reek:FeatureEnvy
|
25
|
+
def pdf_setup(pdf)
|
26
|
+
pdf.bounding_box([0, pdf.cursor], width: page_content_width(pdf)) do
|
27
|
+
pdf.pad(10) do
|
28
|
+
pdf.indent(10, 10) do
|
29
|
+
yield
|
30
|
+
end
|
31
|
+
end
|
32
|
+
pdf.stroke_bounds
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
CNPJ_FORMAT = '%d.%d.%d/%d-%d'.freeze
|
37
|
+
# :reek:FeatureEnvy
|
38
|
+
def format_cnpj(cnpj)
|
39
|
+
format(CNPJ_FORMAT, cnpj[0, 2], cnpj[2, 3], cnpj[5, 3], cnpj[8, 4], cnpj[12, 2])
|
40
|
+
end
|
41
|
+
|
42
|
+
CPF_FORMAT = '%d.%d.%d-%d'.freeze
|
43
|
+
# :reek:FeatureEnvy
|
44
|
+
def format_cpf(cpf)
|
45
|
+
format(CPF_FORMAT, cpf[0, 3], cpf[3, 3], cpf[6, 3], cpf[9, 2])
|
46
|
+
end
|
47
|
+
|
48
|
+
# :reek:FeatureEnvy
|
49
|
+
def format_currency(num)
|
50
|
+
num.truncate.to_s.reverse.split(/.../).join('.').reverse + format(',%02d', (num.frac * 100).truncate)
|
51
|
+
end
|
52
|
+
|
53
|
+
# :reek:FeatureEnvy
|
54
|
+
def format_number(num, prec: 4)
|
55
|
+
num.truncate.to_s + (prec > 0 ? format(",%0#{prec}d", (num.frac * 10**prec).truncate) : '')
|
56
|
+
end
|
57
|
+
|
58
|
+
# :reek:FeatureEnvy
|
59
|
+
def page_paper_width(name)
|
60
|
+
(name.is_a?(Array) ? name : PDF::Core::PageGeometry::SIZES[name]).first
|
61
|
+
end
|
62
|
+
|
63
|
+
# :reek:FeatureEnvy
|
64
|
+
def page_content_width(pdf)
|
65
|
+
page = pdf.page
|
66
|
+
margins = page.margins
|
67
|
+
page_paper_width(page.size) - margins[:left] - margins[:right]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module BrInvoicesPdf
|
2
|
+
module Cfe
|
3
|
+
module Renderer
|
4
|
+
# :reek:DataClump
|
5
|
+
module CompanyIdentification
|
6
|
+
extend BaseRenderer
|
7
|
+
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def execute(pdf, data)
|
11
|
+
attributes = data[:company_attributes]
|
12
|
+
pdf_setup(pdf) do
|
13
|
+
company_params(pdf, attributes)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# :reek:FeatureEnvy
|
18
|
+
def company_params(pdf, data)
|
19
|
+
pdf.text(data[:trading_name], align: :center)
|
20
|
+
pdf.text(data[:company_name], align: :center)
|
21
|
+
pdf.text(format_address(data[:address]), align: :center)
|
22
|
+
insert_fiscal_numbers(pdf, data)
|
23
|
+
end
|
24
|
+
private_class_method :company_params
|
25
|
+
|
26
|
+
# :reek:FeatureEnvy
|
27
|
+
def insert_fiscal_numbers(pdf, data)
|
28
|
+
pdf.text('CNPJ: ' + format_cnpj(data[:cnpj]), align: :center)
|
29
|
+
pdf.text('Inscrição Estadual: ' + data[:ie], align: :center)
|
30
|
+
pdf.text('Inscrição Municipal: ' + data[:im], align: :center)
|
31
|
+
end
|
32
|
+
private_class_method :insert_fiscal_numbers
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module BrInvoicesPdf
|
2
|
+
module Cfe
|
3
|
+
module Renderer
|
4
|
+
module FiscoInfo
|
5
|
+
extend BaseRenderer
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
# :reek:FeatureEnvy
|
10
|
+
def execute(pdf, data)
|
11
|
+
box(pdf, [0, pdf.cursor], page_content_width(pdf)) do
|
12
|
+
pdf.text("Observações do fisco\n\n", style: :italic)
|
13
|
+
add_fisco_obs(pdf, data[:fisco_obs])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_fisco_obs(pdf, fisco_obs)
|
18
|
+
fisco_obs.each do |element|
|
19
|
+
pdf.text(element[:field] + ': ' + element[:text], align: :center)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
private_class_method :add_fisco_obs
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module BrInvoicesPdf
|
2
|
+
module Cfe
|
3
|
+
module Renderer
|
4
|
+
module Header
|
5
|
+
extend BaseRenderer
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
# :reek:FeatureEnvy
|
10
|
+
def execute(pdf, data)
|
11
|
+
cpf = cpf_vlue(data[:cpf])
|
12
|
+
|
13
|
+
pdf_setup(pdf) do
|
14
|
+
add_header_config(pdf, data, cpf)
|
15
|
+
end
|
16
|
+
|
17
|
+
pdf.move_down(5)
|
18
|
+
end
|
19
|
+
|
20
|
+
def cpf_vlue(cpf)
|
21
|
+
cpf ? 'CONSUMIDOR: ' + format_cpf(cpf) : 'CONSUMIDOR NAO IDENTIFICADO'
|
22
|
+
end
|
23
|
+
private_class_method :cpf_vlue
|
24
|
+
|
25
|
+
def add_header_config(pdf, data, cpf)
|
26
|
+
pdf.font('Helvetica', style: :bold)
|
27
|
+
pdf.text("Extrato: #{data[:document_number]}", align: :center)
|
28
|
+
pdf.text(cpf, align: :center)
|
29
|
+
pdf.text('CUPOM FISCAL ELETRONICO - SAT', align: :center)
|
30
|
+
pdf.font('Helvetica', style: :normal, align: :center)
|
31
|
+
end
|
32
|
+
private_class_method :add_header_config
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module BrInvoicesPdf
|
2
|
+
module Cfe
|
3
|
+
module Renderer
|
4
|
+
module PaymentForms
|
5
|
+
extend BaseRenderer
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def execute(pdf, data)
|
10
|
+
pdf.font_size(6) do
|
11
|
+
width = page_content_width(pdf)
|
12
|
+
table_data = payments_table_data(data)
|
13
|
+
render_table(pdf, table_data, width)
|
14
|
+
end
|
15
|
+
|
16
|
+
pdf.move_down(5)
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_table(pdf, table_data, width)
|
20
|
+
pdf.table(table_data, width: width) do |table|
|
21
|
+
format_table(table, table_data)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
private_class_method :render_table
|
25
|
+
|
26
|
+
# :reek:FeatureEnvy
|
27
|
+
def format_table(table, table_data)
|
28
|
+
table.columns([0, 1]).valign = :center
|
29
|
+
table.columns(1).align = :right
|
30
|
+
table_size = table_data.size
|
31
|
+
table.row([0, table_size - 1]).font_style = :bold
|
32
|
+
table.row([0, table_size - 2]).font_style = :bold
|
33
|
+
end
|
34
|
+
private_class_method :format_table
|
35
|
+
|
36
|
+
PAYMENTS_TABLE_BASE_DATA = [['FORMA DE PAGAMENTO', 'VALOR']].freeze
|
37
|
+
def payments_table_data(data)
|
38
|
+
payments_data = data[:payments].reduce(PAYMENTS_TABLE_BASE_DATA) do |result, cur|
|
39
|
+
result + [[cur[:type], format_currency(BigDecimal(cur[:amount]))]]
|
40
|
+
end
|
41
|
+
|
42
|
+
add_default_values(payments_data, data[:payment])
|
43
|
+
end
|
44
|
+
private_class_method :payments_table_data
|
45
|
+
|
46
|
+
def add_default_values(payments_data, data)
|
47
|
+
payments_data.push(['TROCO', format_currency(BigDecimal(data[:cashback]))])
|
48
|
+
payments_data.push(['TOTAL', format_currency(BigDecimal(data[:paid]))])
|
49
|
+
end
|
50
|
+
private_class_method :add_default_values
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module BrInvoicesPdf
|
2
|
+
module Cfe
|
3
|
+
module Renderer
|
4
|
+
module ProductTable
|
5
|
+
extend BaseRenderer
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def execute(pdf, data)
|
10
|
+
table_data = product_table_data(data)
|
11
|
+
|
12
|
+
pdf.font_size(6) do
|
13
|
+
format_table(pdf, table_data)
|
14
|
+
end
|
15
|
+
|
16
|
+
pdf.move_down(5)
|
17
|
+
end
|
18
|
+
|
19
|
+
def format_table(pdf, table_data)
|
20
|
+
width = page_content_width(pdf)
|
21
|
+
pdf.table(table_data, width: width) do |table|
|
22
|
+
format_row(table.row(0))
|
23
|
+
format_columns(table)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
private_class_method :format_table
|
27
|
+
|
28
|
+
def format_row(row)
|
29
|
+
row.font_style = :bold
|
30
|
+
row.align = :center
|
31
|
+
end
|
32
|
+
private_class_method :format_row
|
33
|
+
|
34
|
+
# :reek:FeatureEnvy
|
35
|
+
def format_columns(table)
|
36
|
+
table.columns(0..5).valign = :center
|
37
|
+
table.columns([2, 4, 5]).align = :right
|
38
|
+
table.column(3).align = :center
|
39
|
+
table_widths(table, table.width)
|
40
|
+
end
|
41
|
+
private_class_method :format_columns
|
42
|
+
|
43
|
+
# :reek:FeatureEnvy
|
44
|
+
def table_widths(table, width)
|
45
|
+
table.column(0).width = width * 0.16
|
46
|
+
table.columns([2, 3]).width = width * 0.13
|
47
|
+
table.column([4, 5]).width = width * 0.135
|
48
|
+
end
|
49
|
+
private_class_method :table_widths
|
50
|
+
|
51
|
+
PRODUCT_TABLE_BASE_DATA = [['CÓD.', 'DESCRIÇÃO', 'QTD.', 'UND.', 'V.UNIT', 'V.TOT']].freeze
|
52
|
+
def product_table_data(data)
|
53
|
+
data[:products].reduce(PRODUCT_TABLE_BASE_DATA) do |result, cur|
|
54
|
+
result + [[
|
55
|
+
cur[:code],
|
56
|
+
cur[:description],
|
57
|
+
format_number(BigDecimal(cur[:quantity])),
|
58
|
+
cur[:unit_label],
|
59
|
+
format_currency(BigDecimal(cur[:unit_value])),
|
60
|
+
format_currency(BigDecimal(cur[:total_value]))
|
61
|
+
]]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
private_class_method :product_table_data
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module BrInvoicesPdf
|
2
|
+
module Cfe
|
3
|
+
module Renderer
|
4
|
+
module QrCode
|
5
|
+
extend BaseRenderer
|
6
|
+
|
7
|
+
module_function
|
8
|
+
|
9
|
+
SAT_QRCODE_SEPARATOR = '|'.freeze
|
10
|
+
BARCODE_HEIGHT = 50
|
11
|
+
|
12
|
+
def execute(pdf, data)
|
13
|
+
render_box(pdf) do
|
14
|
+
options = pdf_options(page_paper_width(pdf.page.size), data)
|
15
|
+
|
16
|
+
generate_barcodes(pdf, options)
|
17
|
+
generate_qr_code(pdf, data, options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# :reek:FeatureEnvy
|
22
|
+
def render_box(pdf)
|
23
|
+
box(pdf, [0, pdf.cursor], page_content_width(pdf)) do
|
24
|
+
pdf.text("Códigos de barra e QR Code\n\n", style: :italic)
|
25
|
+
yield
|
26
|
+
pdf.move_down(10)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
private_class_method :render_box
|
30
|
+
|
31
|
+
def pdf_options(page_width, data)
|
32
|
+
qrcode_size = page_width * 0.65
|
33
|
+
barcodes_size = page_width * 0.85
|
34
|
+
access_key = data[:access_key][4..48]
|
35
|
+
|
36
|
+
{ access_key: access_key, barcodes_size: barcodes_size, qrcode_size: qrcode_size, page_width: page_width }
|
37
|
+
end
|
38
|
+
private_class_method :pdf_options
|
39
|
+
|
40
|
+
# :reek:FeatureEnvy
|
41
|
+
def generate_qr_code(pdf, data, options)
|
42
|
+
qrcode_string = generate_qr_code_string(options[:access_key], data)
|
43
|
+
qrcode_size = options[:qrcode_size]
|
44
|
+
opts = {
|
45
|
+
at: [(options[:page_width] - qrcode_size) / 2, pdf.cursor],
|
46
|
+
width: qrcode_size,
|
47
|
+
height: qrcode_size
|
48
|
+
}
|
49
|
+
insert_image(pdf, generate_qr_code_data(qrcode_string, qrcode_size), opts)
|
50
|
+
end
|
51
|
+
private_class_method :generate_qr_code
|
52
|
+
|
53
|
+
def generate_qr_code_data(qr_code_string, qrcode_size)
|
54
|
+
qrcode = RQRCode::QRCode.new(qr_code_string)
|
55
|
+
blob = qrcode.as_png(size: qrcode_size, border_modules: 0).to_blob
|
56
|
+
StringIO.new(blob)
|
57
|
+
end
|
58
|
+
private_class_method :generate_qr_code_data
|
59
|
+
|
60
|
+
# rubocop:disable Metrics/AbcSize
|
61
|
+
def generate_qr_code_string(access_key, data)
|
62
|
+
sat_params = data[:sat_params]
|
63
|
+
access_key + SAT_QRCODE_SEPARATOR + sat_params[:emission_date] +
|
64
|
+
SAT_QRCODE_SEPARATOR + sat_params[:emission_hour] +
|
65
|
+
SAT_QRCODE_SEPARATOR + data[:payment][:total].delete('.') + SAT_QRCODE_SEPARATOR +
|
66
|
+
data[:company_attributes][:cnpj] + SAT_QRCODE_SEPARATOR +
|
67
|
+
sat_params[:document_qr_code_signature]
|
68
|
+
end
|
69
|
+
private_class_method :generate_qr_code_string
|
70
|
+
|
71
|
+
def generate_barcodes(pdf, pdf_options)
|
72
|
+
options = barcode_options(pdf, pdf_options[:page_width], pdf_options[:barcodes_size])
|
73
|
+
access_key = pdf_options[:access_key]
|
74
|
+
insert_image(pdf, generate_barcode_one(access_key), options)
|
75
|
+
insert_image(pdf, generate_barcode_two(access_key), options)
|
76
|
+
end
|
77
|
+
private_class_method :generate_barcodes
|
78
|
+
|
79
|
+
def insert_image(pdf, image, options)
|
80
|
+
pdf.image(image, options)
|
81
|
+
pdf.move_down(options[:height])
|
82
|
+
end
|
83
|
+
private_class_method :insert_image
|
84
|
+
|
85
|
+
def generate_barcode_one(access_key)
|
86
|
+
key = access_key[0..21]
|
87
|
+
blob = Barby::PngOutputter.new(Barby::Code128A.new(key)).to_png
|
88
|
+
StringIO.new(blob)
|
89
|
+
end
|
90
|
+
private_class_method :generate_barcode_one
|
91
|
+
|
92
|
+
def generate_barcode_two(access_key)
|
93
|
+
key = access_key[22..44]
|
94
|
+
blob = Barby::PngOutputter.new(Barby::Code128A.new(key)).to_png
|
95
|
+
StringIO.new(blob)
|
96
|
+
end
|
97
|
+
private_class_method :generate_barcode_two
|
98
|
+
|
99
|
+
def barcode_options(pdf, page_width, qrcode_size)
|
100
|
+
{
|
101
|
+
at: [(page_width - qrcode_size) / 2, pdf.cursor],
|
102
|
+
width: qrcode_size,
|
103
|
+
height: BARCODE_HEIGHT
|
104
|
+
}
|
105
|
+
end
|
106
|
+
private_class_method :barcode_options
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|