br_invoices_pdf 0.2.6 → 0.2.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +17 -0
- data/.rubocop.yml +1 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +2 -0
- data/Rakefile +2 -0
- data/bin/console +1 -0
- data/br_invoices_pdf.gemspec +1 -0
- data/lib/br_invoices_pdf.rb +12 -0
- data/lib/br_invoices_pdf/cfe.rb +2 -1
- data/lib/br_invoices_pdf/cfe/parser.rb +5 -3
- data/lib/br_invoices_pdf/cfe/parser/access_key.rb +3 -1
- data/lib/br_invoices_pdf/cfe/parser/cnpj.rb +3 -1
- data/lib/br_invoices_pdf/cfe/parser/company_attributes.rb +3 -1
- data/lib/br_invoices_pdf/cfe/parser/cpf.rb +3 -1
- data/lib/br_invoices_pdf/cfe/parser/document_number.rb +3 -1
- data/lib/br_invoices_pdf/cfe/parser/fisco_obs.rb +3 -1
- data/lib/br_invoices_pdf/cfe/parser/payment.rb +3 -1
- data/lib/br_invoices_pdf/cfe/parser/payments.rb +6 -16
- data/lib/br_invoices_pdf/cfe/parser/products_data.rb +4 -2
- data/lib/br_invoices_pdf/cfe/parser/sat.rb +3 -1
- data/lib/br_invoices_pdf/cfe/renderer.rb +4 -18
- data/lib/br_invoices_pdf/cfe/renderer/base_renderer.rb +5 -62
- data/lib/br_invoices_pdf/cfe/renderer/company_identification.rb +3 -0
- data/lib/br_invoices_pdf/cfe/renderer/fisco_info.rb +3 -0
- data/lib/br_invoices_pdf/cfe/renderer/header.rb +3 -0
- data/lib/br_invoices_pdf/cfe/renderer/payment_forms.rb +6 -12
- data/lib/br_invoices_pdf/cfe/renderer/product_table.rb +4 -48
- data/lib/br_invoices_pdf/cfe/renderer/qr_code.rb +5 -9
- data/lib/br_invoices_pdf/cfe/renderer/taxes_info.rb +5 -2
- data/lib/br_invoices_pdf/cfe/renderer/totals.rb +3 -24
- data/lib/br_invoices_pdf/errors/invalid_document_type.rb +2 -0
- data/lib/br_invoices_pdf/generator.rb +2 -0
- data/lib/br_invoices_pdf/nfce.rb +11 -0
- data/lib/br_invoices_pdf/nfce/parser.rb +33 -0
- data/lib/br_invoices_pdf/nfce/parser/additional_info.rb +17 -0
- data/lib/br_invoices_pdf/nfce/parser/company.rb +25 -0
- data/lib/br_invoices_pdf/nfce/parser/customer.rb +32 -0
- data/lib/br_invoices_pdf/nfce/parser/emission_details.rb +51 -0
- data/lib/br_invoices_pdf/nfce/parser/payments.rb +30 -0
- data/lib/br_invoices_pdf/nfce/parser/products.rb +39 -0
- data/lib/br_invoices_pdf/nfce/parser/totals.rb +25 -0
- data/lib/br_invoices_pdf/nfce/renderer.rb +37 -0
- data/lib/br_invoices_pdf/nfce/renderer/base_renderer.rb +22 -0
- data/lib/br_invoices_pdf/nfce/renderer/company_identification.rb +37 -0
- data/lib/br_invoices_pdf/nfce/renderer/customer_identification.rb +47 -0
- data/lib/br_invoices_pdf/nfce/renderer/fiscal_message.rb +46 -0
- data/lib/br_invoices_pdf/nfce/renderer/header.rb +32 -0
- data/lib/br_invoices_pdf/nfce/renderer/payment_forms.rb +73 -0
- data/lib/br_invoices_pdf/nfce/renderer/product_table.rb +23 -0
- data/lib/br_invoices_pdf/nfce/renderer/qr_code.rb +56 -0
- data/lib/br_invoices_pdf/nfce/renderer/taxes_info.rb +28 -0
- data/lib/br_invoices_pdf/nfce/renderer/totals.rb +30 -0
- data/lib/br_invoices_pdf/util/base_renderer.rb +121 -0
- data/lib/br_invoices_pdf/util/enum.rb +20 -0
- data/lib/br_invoices_pdf/util/mount_params.rb +26 -0
- data/lib/br_invoices_pdf/util/nfce_check_urls.rb +102 -0
- data/lib/br_invoices_pdf/util/pdf_renderer.rb +33 -0
- data/lib/br_invoices_pdf/util/product_table.rb +57 -0
- data/lib/br_invoices_pdf/util/xml_locate.rb +21 -0
- data/lib/br_invoices_pdf/version.rb +3 -1
- data/nfce.xml +160 -0
- metadata +32 -4
- data/lib/br_invoices_pdf/cfe/parser/base_parser.rb +0 -19
@@ -1,19 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BrInvoicesPdf
|
2
4
|
module Cfe
|
3
5
|
module Renderer
|
4
6
|
module PaymentForms
|
7
|
+
extend Util::BaseRenderer
|
5
8
|
extend BaseRenderer
|
6
9
|
|
7
10
|
module_function
|
8
11
|
|
9
12
|
def execute(pdf, data)
|
10
|
-
pdf
|
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)
|
13
|
+
execute_payment_form(pdf, payments_table_data(data))
|
17
14
|
end
|
18
15
|
|
19
16
|
def render_table(pdf, table_data, width)
|
@@ -33,13 +30,10 @@ module BrInvoicesPdf
|
|
33
30
|
end
|
34
31
|
private_class_method :format_table
|
35
32
|
|
36
|
-
PAYMENTS_TABLE_BASE_DATA = [['FORMA DE PAGAMENTO', 'VALOR']].freeze
|
37
33
|
def payments_table_data(data)
|
38
|
-
payments_data = data
|
39
|
-
result + [[cur[:type], format_currency(cur[:amount])]]
|
40
|
-
end
|
34
|
+
payments_data = mount_payment_data(data)
|
41
35
|
|
42
|
-
add_default_values(payments_data, data[:
|
36
|
+
add_default_values(payments_data, data[:totals])
|
43
37
|
end
|
44
38
|
private_class_method :payments_table_data
|
45
39
|
|
@@ -1,7 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BrInvoicesPdf
|
2
4
|
module Cfe
|
3
5
|
module Renderer
|
4
6
|
module ProductTable
|
7
|
+
extend Util::BaseRenderer
|
8
|
+
extend Util::ProductTable
|
5
9
|
extend BaseRenderer
|
6
10
|
|
7
11
|
module_function
|
@@ -15,54 +19,6 @@ module BrInvoicesPdf
|
|
15
19
|
|
16
20
|
pdf.move_down(5)
|
17
21
|
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.155
|
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
|
-
# :reek:FeatureEnvy
|
53
|
-
def product_table_data(data)
|
54
|
-
data[:products].reduce(PRODUCT_TABLE_BASE_DATA) do |result, cur|
|
55
|
-
result + [[
|
56
|
-
cur[:code],
|
57
|
-
cur[:description],
|
58
|
-
format_number(cur[:quantity]),
|
59
|
-
cur[:unit_label],
|
60
|
-
format_currency(cur[:unit_value]),
|
61
|
-
format_currency(cur[:total_value])
|
62
|
-
]]
|
63
|
-
end
|
64
|
-
end
|
65
|
-
private_class_method :product_table_data
|
66
22
|
end
|
67
23
|
end
|
68
24
|
end
|
@@ -1,12 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BrInvoicesPdf
|
2
4
|
module Cfe
|
3
5
|
module Renderer
|
4
6
|
module QrCode
|
7
|
+
extend Util::BaseRenderer
|
5
8
|
extend BaseRenderer
|
6
9
|
|
7
10
|
module_function
|
8
11
|
|
9
|
-
SAT_QRCODE_SEPARATOR = '|'
|
12
|
+
SAT_QRCODE_SEPARATOR = '|'
|
10
13
|
BARCODE_HEIGHT = 50
|
11
14
|
|
12
15
|
def execute(pdf, data)
|
@@ -50,19 +53,12 @@ module BrInvoicesPdf
|
|
50
53
|
end
|
51
54
|
private_class_method :generate_qr_code
|
52
55
|
|
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.to_i, border_modules: 0).to_blob
|
56
|
-
StringIO.new(blob)
|
57
|
-
end
|
58
|
-
private_class_method :generate_qr_code_data
|
59
|
-
|
60
56
|
# rubocop:disable Metrics/AbcSize
|
61
57
|
def generate_qr_code_string(access_key, data)
|
62
58
|
sat_params = data[:sat_params]
|
63
59
|
access_key + SAT_QRCODE_SEPARATOR + sat_params[:emission_date] +
|
64
60
|
SAT_QRCODE_SEPARATOR + sat_params[:emission_hour] +
|
65
|
-
SAT_QRCODE_SEPARATOR + data[:
|
61
|
+
SAT_QRCODE_SEPARATOR + data[:totals][:total].delete('.') + SAT_QRCODE_SEPARATOR +
|
66
62
|
data[:company_attributes][:cnpj] + SAT_QRCODE_SEPARATOR +
|
67
63
|
sat_params[:document_qr_code_signature]
|
68
64
|
end
|
@@ -1,14 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BrInvoicesPdf
|
2
4
|
module Cfe
|
3
5
|
module Renderer
|
4
6
|
module TaxesInfo
|
7
|
+
extend Util::BaseRenderer
|
5
8
|
extend BaseRenderer
|
6
9
|
|
7
10
|
module_function
|
8
11
|
|
9
12
|
def execute(pdf, data)
|
10
13
|
box(pdf, [0, pdf.cursor], page_content_width(pdf)) do
|
11
|
-
tribute_values(pdf, data[:
|
14
|
+
tribute_values(pdf, data[:totals])
|
12
15
|
sat_params = data[:sat_params]
|
13
16
|
sat_number(pdf, sat_params[:sat_number])
|
14
17
|
date_values(pdf, sat_params)
|
@@ -17,7 +20,7 @@ module BrInvoicesPdf
|
|
17
20
|
|
18
21
|
def date_values(pdf, data)
|
19
22
|
time = data[:emission_date] + data[:emission_hour]
|
20
|
-
pdf.text(
|
23
|
+
pdf.text(Date.parse(time).strftime('%d/%m/%Y %H:%M:%S'), align: :center)
|
21
24
|
end
|
22
25
|
private_class_method :date_values
|
23
26
|
|
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module BrInvoicesPdf
|
2
4
|
module Cfe
|
3
5
|
module Renderer
|
4
6
|
module Totals
|
7
|
+
extend Util::BaseRenderer
|
5
8
|
extend BaseRenderer
|
6
9
|
|
7
10
|
module_function
|
@@ -12,30 +15,6 @@ module BrInvoicesPdf
|
|
12
15
|
pdf.move_down(5)
|
13
16
|
end
|
14
17
|
|
15
|
-
def insert_box_info(pdf, data, xpos = 0)
|
16
|
-
third_width = page_content_width(pdf) * 0.333333333
|
17
|
-
ypos = pdf.cursor
|
18
|
-
box_info(data[:payment]).each do |(title, value)|
|
19
|
-
insert_box(pdf, title: title, value: value, xpos: xpos, ypos: ypos, third_width: third_width)
|
20
|
-
xpos += third_width
|
21
|
-
end
|
22
|
-
end
|
23
|
-
private_class_method :insert_box_info
|
24
|
-
|
25
|
-
# :reek:FeatureEnvy
|
26
|
-
def insert_box(pdf, params)
|
27
|
-
box(pdf, [params[:xpos], params[:ypos]], params[:third_width]) do
|
28
|
-
insert_texts(pdf, params[:title], params[:value])
|
29
|
-
end
|
30
|
-
end
|
31
|
-
private_class_method :insert_box
|
32
|
-
|
33
|
-
def insert_texts(pdf, title, value)
|
34
|
-
pdf.text(title, style: :italic)
|
35
|
-
pdf.text(value, align: :right)
|
36
|
-
end
|
37
|
-
private_class_method :insert_texts
|
38
|
-
|
39
18
|
def box_info(data_payment)
|
40
19
|
[
|
41
20
|
['Total bruto dos itens', format_currency(data_payment[:total_price])],
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'br_invoices_pdf/nfce/parser'
|
4
|
+
require 'br_invoices_pdf/nfce/renderer/base_renderer'
|
5
|
+
require 'br_invoices_pdf/nfce/renderer'
|
6
|
+
|
7
|
+
module BrInvoicesPdf
|
8
|
+
module Nfce
|
9
|
+
BrInvoicesPdf.register(:nfce, Nfce::Renderer, Nfce::Parser)
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'br_invoices_pdf/nfce/parser/company'
|
4
|
+
require 'br_invoices_pdf/nfce/parser/products'
|
5
|
+
require 'br_invoices_pdf/nfce/parser/payments'
|
6
|
+
require 'br_invoices_pdf/nfce/parser/customer'
|
7
|
+
require 'br_invoices_pdf/nfce/parser/totals'
|
8
|
+
require 'br_invoices_pdf/nfce/parser/additional_info'
|
9
|
+
require 'br_invoices_pdf/nfce/parser/emission_details'
|
10
|
+
|
11
|
+
module BrInvoicesPdf
|
12
|
+
module Nfce
|
13
|
+
module Parser
|
14
|
+
module_function
|
15
|
+
|
16
|
+
PARSERS = {
|
17
|
+
company: Company,
|
18
|
+
products: Products,
|
19
|
+
payments: Payments,
|
20
|
+
customer: Customer,
|
21
|
+
totals: Totals,
|
22
|
+
additional_info: AdditionalInfo,
|
23
|
+
emission_details: EmissionDetails
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
def parse(xml)
|
27
|
+
PARSERS.reduce({}) do |response, (param, parser)|
|
28
|
+
{ **response, param => parser.execute(xml) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BrInvoicesPdf
|
4
|
+
module Nfce
|
5
|
+
module Parser
|
6
|
+
module AdditionalInfo
|
7
|
+
extend Util::XmlLocate
|
8
|
+
|
9
|
+
module_function
|
10
|
+
|
11
|
+
def execute(xml)
|
12
|
+
locate_element(xml, 'NFe/infAdic/infCpl')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BrInvoicesPdf
|
4
|
+
module Nfce
|
5
|
+
module Parser
|
6
|
+
module Company
|
7
|
+
extend Util::XmlLocate
|
8
|
+
extend Util::MountParams
|
9
|
+
|
10
|
+
module_function
|
11
|
+
|
12
|
+
EMIT_ROOT_PATH = "#{Util::XmlLocate::ROOT_PATH}/emit"
|
13
|
+
|
14
|
+
def execute(xml)
|
15
|
+
{
|
16
|
+
name: locate_element(xml, "#{EMIT_ROOT_PATH}/xNome"),
|
17
|
+
cnpj: locate_element(xml, "#{EMIT_ROOT_PATH}/CNPJ"),
|
18
|
+
state_number: locate_element(xml, "#{EMIT_ROOT_PATH}/IE"),
|
19
|
+
address: mount(xml, address_params(EMIT_ROOT_PATH, 'Emit'))
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BrInvoicesPdf
|
4
|
+
module Nfce
|
5
|
+
module Parser
|
6
|
+
module Customer
|
7
|
+
extend Util::XmlLocate
|
8
|
+
extend Util::MountParams
|
9
|
+
|
10
|
+
module_function
|
11
|
+
|
12
|
+
DEST_ROOT_PATH = "#{Util::XmlLocate::ROOT_PATH}/dest"
|
13
|
+
|
14
|
+
def execute(xml)
|
15
|
+
identification_type = identification_type_by(xml)
|
16
|
+
{
|
17
|
+
identification_type: identification_type,
|
18
|
+
identification: locate_element(xml, "#{DEST_ROOT_PATH}/#{identification_type}"),
|
19
|
+
address: mount(xml, address_params(DEST_ROOT_PATH, 'Dest'))
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
def identification_type_by(xml)
|
24
|
+
return 'CNPJ' if locate_element(xml, "#{DEST_ROOT_PATH}/CNPJ")
|
25
|
+
return 'CPF' if locate_element(xml, "#{DEST_ROOT_PATH}/CPF")
|
26
|
+
return 'idEstrangeiro' if locate_element(xml, "#{DEST_ROOT_PATH}/idEstrangeiro")
|
27
|
+
end
|
28
|
+
private_class_method :identification_type_by
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BrInvoicesPdf
|
4
|
+
module Nfce
|
5
|
+
module Parser
|
6
|
+
module EmissionDetails
|
7
|
+
extend Util::XmlLocate
|
8
|
+
|
9
|
+
module_function
|
10
|
+
|
11
|
+
EMISSION_ROOT_PATH = "#{Util::XmlLocate::ROOT_PATH}/ide"
|
12
|
+
|
13
|
+
EMISSION_TYPES = {
|
14
|
+
'1': 'Emissão normal',
|
15
|
+
'2': 'Contingência FS-IA',
|
16
|
+
'3': 'Contingência SCAN',
|
17
|
+
'4': 'Contingência DPEC',
|
18
|
+
'5': 'Contingência FS-DA, com impressão do DANFE em formulário de segurança',
|
19
|
+
'6': 'Contingência SVC-AN',
|
20
|
+
'7': 'Contingência SVC-RS',
|
21
|
+
'9': 'Contingência off-line da NFC-e'
|
22
|
+
}.freeze
|
23
|
+
|
24
|
+
def execute(xml)
|
25
|
+
{
|
26
|
+
type: EMISSION_TYPES[locate_element(xml, "#{EMISSION_ROOT_PATH}/tpEmis").to_sym],
|
27
|
+
number: locate_element(xml, "#{EMISSION_ROOT_PATH}/nNF"),
|
28
|
+
serie: locate_element(xml, "#{EMISSION_ROOT_PATH}/serie"),
|
29
|
+
emission_timestamp: locate_element_to_date(xml, "#{EMISSION_ROOT_PATH}/dhEmi"),
|
30
|
+
receival_timestamp: locate_element_to_date(xml, 'protNFe/infProt/dhRecbto'),
|
31
|
+
check_url: check_url(xml),
|
32
|
+
access_key: locate_element(xml, 'protNFe/infProt/chNFe'),
|
33
|
+
qrcode_url: xml.locate('NFe/infNFeSupl/qrCode').first.nodes.first.value,
|
34
|
+
authorization_protocol: locate_element(xml, 'protNFe/infProt/nProt')
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_url(xml)
|
39
|
+
check_urls = Util::NfceCheckUrls::URLS[locate_element(xml, "#{EMISSION_ROOT_PATH}/cUF").to_sym]
|
40
|
+
check_urls[locate_element(xml, "#{EMISSION_ROOT_PATH}/tpAmb").to_sym]
|
41
|
+
end
|
42
|
+
private_class_method :check_url
|
43
|
+
|
44
|
+
def locate_element_to_date(xml, path)
|
45
|
+
Time.new(locate_element(xml, path)).utc
|
46
|
+
end
|
47
|
+
private_class_method :locate_element_to_date
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module BrInvoicesPdf
|
4
|
+
module Nfce
|
5
|
+
module Parser
|
6
|
+
module Payments
|
7
|
+
extend Util::XmlLocate
|
8
|
+
|
9
|
+
module_function
|
10
|
+
|
11
|
+
ROOT_PATH = Util::XmlLocate::ROOT_PATH
|
12
|
+
|
13
|
+
def execute(xml)
|
14
|
+
node_payments = xml.locate("#{ROOT_PATH}/pag")
|
15
|
+
|
16
|
+
node_payments.map(&method(:payment_by))
|
17
|
+
end
|
18
|
+
|
19
|
+
def payment_by(element)
|
20
|
+
{
|
21
|
+
type: Util::Enum::PAYMENT_TYPES[locate_element(element, 'tPag')],
|
22
|
+
amount: locate_element(element, 'vPag'),
|
23
|
+
cashback: locate_element(element, 'vTroco')
|
24
|
+
}
|
25
|
+
end
|
26
|
+
private_class_method :payment_by
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|