Class: SEFAZ::Webservice::SAT::Templates::CupomFiscal80mm

Inherits:
Base
  • Object
show all
Defined in:
lib/sefaz/webservice/sat/templates/cupom_fiscal_80mm.rb

Overview

Template para CFe-SAT 80mm em PDF

Instance Method Summary collapse

Methods inherited from Base

#render

Methods included from Utils::PrawnHelper

#barcode_128c, #dash, #qrcode

Constructor Details

#initializeCupomFiscal80mm

Returns a new instance of CupomFiscal80mm.



10
11
12
13
14
# File 'lib/sefaz/webservice/sat/templates/cupom_fiscal_80mm.rb', line 10

def initialize
  super
  @page_width = Configuration.default.cfe_page_width_80mm
  @margin = Configuration.default.cfe_margin_55mm
end

Instance Method Details

#body(doc, aut, summary, chCanc) ⇒ Object

CORPO DO EXTRATO (Aut)

Exibe os dados de forma dinâmica: Quando CFe Movimento: exibe lista dos itens a partir do XML AUTORIZADO (Resumido ou Não Resumido). Quando CFe Cancelamento: exibe os dados do XML AUTORIZADO em modo cancelado.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/sefaz/webservice/sat/templates/cupom_fiscal_80mm.rb', line 49

def body(doc, aut, summary, chCanc)
  tpAmb = aut.dig(:CFe, :infCFe, :ide, :tpAmb)
  nCFe = (tpAmb == 1) ? aut.dig(:CFe, :infCFe, :ide, :nCFe) : "000000"

  # (I) - Título
  doc.move_down 1.mm
  doc.text "Extrato #{nCFe} do CUPOM FISCAL ELETRÔNICO - SAT", style: :bold, align: :center

  # (A) - Título - Cancelamento
  if chCanc
    doc.move_down 1.mm
    doc.text "CANCELAMENTO", style: :bold, align: :center
  end

  # (TESTE) Marca de Teste
  if tpAmb == "2"
    doc.move_down doc.font_size

    doc.text "= TESTE =", style: :italic, align: :center
    doc.move_down doc.font_size
    3.times do
      doc.text_box (">" * 100), at: [0, doc.cursor], height: doc.font_size, width: doc.bounds.width
      doc.move_down doc.font_size
      doc.move_down doc.font_size
    end
  end

  # Exibe o extrato no modo cancelado caso exista Chave de Cancelamento, caso contrário exibe no modo movimento
  if chCanc
    body_canceled_mode(doc, aut)
  else
    body_movement_mode(doc, aut, summary)
  end
end

#body_canceled_mode(doc, aut) ⇒ Object

CORPO DO EXTRATO > MODO CANCELADO (Aut)

Exibe os dados do XML AUTORIZADO em modo cancelado. É renderizado o rodapé do XML AUTORIZADO no final do corpo do extrato.



222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/sefaz/webservice/sat/templates/cupom_fiscal_80mm.rb', line 222

def body_canceled_mode(doc, aut)
  total = aut.dig(:CFe, :infCFe, :total)
  infCFe = aut.dig(:CFe, :infCFe)

  # (B) - Dados do Cupom Fiscal Cancelado
  doc.move_down 1.mm
  doc.text "DADOS DO CUPOM ELETRÔNICO CANCELADO", style: :bold
  doc.text "TOTAL R$ #{total.dig(:vCFe).to_f.to_currency}"

  # (RODAPÉ DE MOVIMENTO) Exibe o rodapé do Extrato de Movimento no corpo do Extrato de Cancelamento
  footer(doc, infCFe, vl_aprox_trib: false)
end

#body_movement_mode(doc, aut, summary) ⇒ Object

CORPO DO EXTRATO > MODO MOVIMENTO (Aut)

Exibe lista dos itens.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/sefaz/webservice/sat/templates/cupom_fiscal_80mm.rb', line 89

def body_movement_mode(doc, aut, summary)
  # (II) - Legenda
  doc.text "#|COD|DESC|QTD|UN|VL UN R$|(VL TR R$)*|VL ITEM R$", size: 6.7
  dash(doc, gap: 2, space: 0.5, line_width: 0.1, x1: 0, x2: doc.bounds.width, y: doc.cursor)

  # (III) - Registros de item
  unless summary
    det = aut.dig(:CFe, :infCFe, :det)
    det = det.is_a?(Array) ? det : [det]
    det.each do |i|
      # DADOS: #|COD|DESC|QTD|UN|VL UN R$|(VL TR R$)*
      doc.bounding_box([0, doc.cursor], width: (doc.bounds.width - 13.mm)) do
        doc.text "#{i.dig(:@nItem)} #{i.dig(:prod, :cProd)} #{i.dig(:prod, :xProd)} #{i.dig(:prod, :qCom)} #{i.dig(:prod, :uCom)} X #{i.dig(:prod, :vUnCom).to_f.to_currency} (#{i.dig(:imposto, :vItem12741).to_f.to_currency})"
      end
  
      # DADOS: VL ITEM R$
      doc.move_down -doc.font_size
      doc.text i.dig(:prod, :vProd).to_f.to_currency, align: :right
  
      # DADOS: DESCONTO
      if i.dig(:prod, :vDesc).to_f > 0
        doc.float { doc.text "-#{i.dig(:prod, :vDesc).to_f.to_currency}", align: :right }
        doc.text "desconto sobre item"
      end
  
      # DADOS: ACRÉSCIMO
      if i.dig(:prod, :vOutro).to_f > 0
        doc.float { doc.text "+#{i.dig(:prod, :vOutro).to_f.to_currency}", align: :right }
        doc.text "acréscimo sobre item"
      end
  
      # DADOS: RATEIO DESCONTO
      if i.dig(:prod, :vRatDesc).to_f > 0
        doc.float { doc.text "-#{i.dig(:prod, :vRatDesc).to_f.to_currency}", align: :right }
        doc.text "rateio de desconto sobre subtotal"
      end
  
      # DADOS: RATEIO ACRÉSCIMO
      if i.dig(:prod, :vRatAcr).to_f > 0
        doc.float { doc.text "+#{i.dig(:prod, :vRatAcr).to_f.to_currency}", align: :right }
        doc.text "rateio de acréscimo sobre subtotal"
      end
  
      # DADOS: ISSQN
      if i.dig(:imposto, :ISSQN, :vDeducISSQN).to_f > 0
        doc.float { doc.text "-#{i.dig(:imposto, :ISSQN, :vDeducISSQN).to_f.to_currency}", align: :right }
        doc.text "dedução para ISSQN"
        doc.float { doc.text i.dig(:imposto, :ISSQN, :vBC).to_f.to_currency, align: :right }
        doc.text "base de cálculo ISSQN"
      end
    end
  end

  # (IV) - Total do Cupom
  total = aut.dig(:CFe, :infCFe, :total)

  # DADOS: VALOR BRUTO
  if (total.dig(:DescAcrEntr, :vDescSubtot).to_f > 0) || (total.dig(:DescAcrEntr, :vAcresSubtot).to_f > 0) || (total.dig(:ICMSTot, :vDesc).to_f > 0) || (total.dig(:ICMSTot, :vOutro).to_f > 0)
    doc.float { doc.text total.dig(:ICMSTot, :vProd).to_f.to_currency, align: :right }
    doc.text "Total bruto de itens"
  end

  # DADOS: TOTAL DESC/ACRES SOBRE ITENS
  if (total.dig(:ICMSTot, :vDesc).to_f > 0) || (total.dig(:ICMSTot, :vOutro).to_f > 0)
    valor11 = total.dig(:ICMSTot, :vOutro).to_f - total.dig(:ICMSTot, :vDesc).to_f
    doc.text "Total de descontos/acréscimos sobre item"
    doc.text "#{ valor11 > 0 ? '+' : '-' }#{valor11.abs.to_currency}", align: :right
  end

  # DADOS: DESCONTO SOBRE TOTAL
  if total.dig(:DescAcrEntr, :vDescSubtot).to_f > 0
    doc.float { doc.text "-#{total.dig(:DescAcrEntr, :vDescSubtot).to_f.to_currency}", align: :right }
    doc.text "Desconto sobre subtotal"
  end

  # DADOS: ACRÉSCIMO SOBRE TOTAL
  if total.dig(:DescAcrEntr, :vAcresSubtot).to_f > 0
    doc.float { doc.text "+#{total.dig(:DescAcrEntr, :vAcresSubtot).to_f.to_currency}", align: :right }
    doc.text "Acréscimo sobre subtotal"
  end

  # DADOS: TOTAL FINAL
  doc.float { doc.text total.dig(:vCFe).to_f.to_currency, style: :bold, align: :right }
  doc.text "Total R$", style: :bold

  # (V) - Meio de Pagamento
  pgto = aut.dig(:CFe, :infCFe, :pgto)
  mp = aut.dig(:CFe, :infCFe, :pgto, :MP)
  mp = mp.is_a?(Array) ? mp : [mp]
  mp.each do |i|
    # DADOS: DESCRIÇÃO MEIO DE PAGAMENTO
    doc.bounding_box([0, doc.cursor], width: (doc.bounds.width - 13.mm)) do
      doc.text Configuration.default.cfe_cMP_cod_desc[i.dig(:cMP)]
    end

    # DADOS: VALOR PAGAMENTO
    doc.move_down -doc.font_size
    doc.text i.dig(:vMP).to_f.to_currency, align: :right
  end

  # DADOS: TROCO
  doc.float { doc.text pgto.dig(:vTroco).to_f.to_currency, align: :right }
  doc.text "Troco R$"

  # (VI) - Observações do Fisco
  obsFisco = aut.dig(:CFe, :infCFe, :obsFisco)
  if obsFisco
    obsFisco = obsFisco.is_a?(Array) ? obsFisco : [obsFisco]
    obsFisco.each do |i|
      doc.text "#{i.dig(:xCampo)}: #{i.dig(:xTexto)}"
    end
  end

  # (VII) - Dados para Entrega
  entrega = aut.dig(:CFe, :infCFe, :entrega)
  doc.text "ENDEREÇO DE ENTREGA: #{entrega.dig(:xLgr)} #{entrega.dig(:nro)} #{entrega.dig(:xCpl)} #{entrega.dig(:xBairro)} #{entrega.dig(:xMun)} #{entrega.dig(:UF)}".to_s.strip.upcase if entrega

  # (VIII) - Observações do Contribuinte
  infCFe = aut.dig(:CFe, :infCFe)
  doc.text "OBSERVAÇÕES DO CONTRIBUINTE"
  doc.text infCFe.dig(:infCpl)
  doc.text "Valor aproximado dos tributos deste cupom R$"
  doc.text total.dig(:vCFeLei12741).to_f.to_currency, align: :right
  doc.text "(conforme Lei Fed. 12.741/2012)"
  doc.move_down doc.font_size
end

#build(doc, aut, canc, summary, infAdic) ⇒ Object



16
17
18
19
20
21
22
23
24
# File 'lib/sefaz/webservice/sat/templates/cupom_fiscal_80mm.rb', line 16

def build(doc, aut, canc, summary, infAdic)
  doc.font "Courier", style: :normal
  doc.font_size 7

  infCFe = (canc ? canc.dig(:CFeCanc, :infCFe) : aut.dig(:CFe, :infCFe))
  header(doc, aut)
  body(doc, aut, summary, infCFe.dig(:@chCanc))
  footer(doc, infCFe, infAdic)
end

RODAPÉ (Aut/Canc)

Exibe os elementos de rodapé (QR Code, código de barras, número da chave, mensagens fixas, etc). O método permite exibir o rodapé no modo movimento ou cancelado.



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/sefaz/webservice/sat/templates/cupom_fiscal_80mm.rb', line 241

def footer(doc, infCFe, infAdic = nil, vl_aprox_trib: true)
  id = infCFe.dig(:@Id)
  chCanc = infCFe.dig(:@chCanc)
  ide = infCFe.dig(:ide)
  total = infCFe.dig(:total)

  # Título do cancelamento
  if chCanc
    doc.move_down 2
    dash(doc, gap: 2, space: 0.5, line_width: 0.1, x1: 0, x2: doc.bounds.width, y: doc.cursor)
    doc.text "DADOS DO CUPOM FISCAL ELETRÔNICO DE CANCELAMENTO", align: :center, style: :bold, size: 6.8
  end

  # Número da chave do Cupom Fiscal (dividos em 11 blocos com 4 números cada)
  doc.move_down 2
  doc.text id.to_s.delete("^0-9").scan(/.{4}/).join("  "), align: :center, style: :bold
  doc.move_down doc.font_size

  # Código de barra CODE 128-C (divido em duas partes)
  barcode_128c(doc, value: id.to_s.delete("^0-9"), x: 0, y: doc.cursor, xdim: 0.72)
  doc.move_down 1.mm

  # Informação do consumidor, SAT e mensagens fixas
  doc.float do
    doc.move_down 5.mm
    doc.bounding_box([80, doc.cursor], width: 115) do
      # Informação do consumidor (CNPJ/CPF e NOME)
      if !chCanc && (infCFe.dig(:dest, :CNPJ) || infCFe.dig(:dest, :CPF))
        info = "<b>Consumidor:</b> "
        info = info + infCFe.dig(:dest, :CNPJ).to_s.mask!("##.###.###/####-##") if infCFe.dig(:dest, :CNPJ)
        info = info + infCFe.dig(:dest, :CPF).to_s.mask!("###.###.###-##") if infCFe.dig(:dest, :CPF)
        doc.text info, inline_format: true, size: 6
        doc.text infCFe.dig(:dest, :xNome), size: 6 if infCFe.dig(:dest, :xNome)
      end

      # Informação do SAT (Nº Série SAT)
      doc.text "<b>No. Serie do SAT:</b> #{ide.dig(:nserieSAT)}", inline_format: true, size: 6
      doc.text DateTime.parse("#{ide.dig(:dEmi)}T#{ide.dig(:hEmi)}").strftime("%d/%m/%Y - %H:%M:%S"), size: 6
      doc.move_down doc.font_size

      # Mensagens fixas do Cupom Fiscal
      if !chCanc
        doc.text "Consulte o QR Code pelo aplicativo \"#{Configuration.default.cfe_qr_code_aplicativo}\", disponível na AppStore (Apple) e PlayStore (Android)", size: 6
        doc.move_down doc.font_size
        doc.text "*valor aproximado dos tributos do item", size: 5 if vl_aprox_trib
      end
    end
  end

  # QR Code do Cupom Fiscal = Id|(dEmi)(hEmi)|vCFe|(CNPJ/CPF)|assinaturaQRCODE
  doc.move_down 2.mm
  codigo_qr_code = "#{id}|#{ide.dig(:dEmi)}#{ide.dig(:hEmi)}|#{total.dig(:vCFe)}|#{(infCFe.dig(:dest, :CNPJ) || infCFe.dig(:dest, :CPF))}|#{ide.dig(:assinaturaQRCODE)}"
  qrcode(doc, value: codigo_qr_code, x: 0, y: doc.cursor)
  doc.move_down 3.mm

  # Informações adicionais do Cupom Fiscal (customizado pelo contribuinte)
  if infAdic
    dash(doc, gap: 2, space: 0.5, line_width: 0.1, x1: 0, x2: doc.bounds.width, y: doc.cursor)
    doc.text infAdic, align: :justify, size: 6
  end
end

#header(doc, aut) ⇒ Object

CABEÇALHO (Aut)



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/sefaz/webservice/sat/templates/cupom_fiscal_80mm.rb', line 29

def header(doc, aut)
  emit = aut.dig(:CFe, :infCFe, :emit)
  enderEmit = aut.dig(:CFe, :infCFe, :emit, :enderEmit)

  # Dados do emitente
  doc.text emit.dig(:xFant).to_s.strip.upcase, align: :center
  doc.text emit.dig(:xNome).to_s.strip.upcase, align: :center
  doc.text "#{enderEmit.dig(:xLgr)} #{enderEmit.dig(:nro)} #{enderEmit.dig(:xCpl)} #{enderEmit.dig(:xBairro)} #{enderEmit.dig(:xMun)} #{enderEmit.dig(:CEP)}".to_s.strip.upcase, align: :center
  doc.move_down doc.font_size
  doc.text "CNPJ #{emit.dig(:CNPJ).to_s.mask!("##.###.###/####-##")} IE #{emit.dig(:IE).to_s.mask!("###.###.###.###")}".to_s.strip.upcase, align: :center
  doc.text "IM #{emit.dig(:IM).to_s.mask!("####.###.###.###")}".to_s.strip.upcase, align: :center if emit.dig(:IM)
end