dfe-taxweb 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 458abd1c13f96e05f8564ca6266474fa3b9992b0
4
+ data.tar.gz: 14468b63d6fc68b000cfd0865de8e7de64402305
5
+ SHA512:
6
+ metadata.gz: d6cc139f52963e514258f4c7b3a1de36557f44a5b788721427342eae5680b3c008d2e3e2d92ec2fd560a39df5f88d401f58f9e270eb7f60daad4cb8b4b860fdb
7
+ data.tar.gz: d00db6f05b8e1b159e75bd1ec7a34a4c4b8f693bb8e03665f3ae2ef4569abc962c5fdf31682b8cd70738f87a953657cdc6cd9239cd524da41510ec17519a88fb
@@ -0,0 +1 @@
1
+ require 'dfe_taxweb'
@@ -0,0 +1,14 @@
1
+ # http://guides.rubyonrails.org/active_support_core_extensions.html
2
+ require 'active_support/core_ext/hash'
3
+ require 'active_support/core_ext/enumerable'
4
+
5
+ require 'dfe_taxweb/conjunto'
6
+ require 'dfe_taxweb/nfe'
7
+
8
+ module DfeTaxweb
9
+
10
+ def self.nfe(xml_or_hash)
11
+ DfeTaxweb::Nfe.new xml_or_hash
12
+ end
13
+
14
+ end
@@ -0,0 +1,72 @@
1
+ module DfeTaxweb
2
+ class Conjunto
3
+
4
+ attr_reader :conjunto
5
+ attr_accessor :dados
6
+ delegate :present?, :to_s, to: :conjunto
7
+
8
+ def initialize(hash)
9
+ @conjunto = hash.deep_symbolize_keys
10
+ @dados = {}
11
+ end
12
+
13
+ def to_h
14
+ conjunto
15
+ end
16
+
17
+ def [](key)
18
+ conjunto[key]
19
+ end
20
+
21
+ def dados(key, valor=nil)
22
+ if valor.present?
23
+ @dados[key.to_sym] = valor
24
+ else
25
+ @dados.try(:[], key.to_sym)
26
+ end
27
+ end
28
+
29
+ def atributo(path)
30
+ valor = path.split(".").inject(conjunto) do |item, key|
31
+ next if item.nil?
32
+ if key =~ /\[\d+\]/
33
+ item[key.sub(/\[\d+\]/, '').to_sym][key[/\[(\d+)\]/, 1].to_i]
34
+ else
35
+ item[key.to_sym]
36
+ end
37
+ end
38
+ if valor.is_a?(Array)
39
+ valor.map {|v| normaliza_valores(v)}.compact
40
+ else
41
+ normaliza_valores(valor)
42
+ end
43
+ end
44
+
45
+ def atualizar(hash)
46
+ if hash.is_a?(Hash)
47
+ conjunto.deep_merge!(hash.deep_symbolize_keys)
48
+ end
49
+ self
50
+ end
51
+
52
+ private
53
+ def normaliza_valores(valor)
54
+ if valor.is_a?(Hash)
55
+ Conjunto.new(valor)
56
+ else
57
+ valor
58
+ end
59
+ end
60
+
61
+ end
62
+ end
63
+
64
+ # FIX nil.atributo() nil.dados()
65
+ class NilClass
66
+ def atributo(*_)
67
+ nil
68
+ end
69
+ def dados(*_)
70
+ nil
71
+ end
72
+ end
@@ -0,0 +1,460 @@
1
+ module DfeTaxweb
2
+ class Nfe
3
+
4
+ attr_reader :nfe, :documento
5
+
6
+ def initialize(nfe)
7
+ @documento = {}
8
+ hash = nfe.is_a?(Hash) ? nfe : Hash.from_xml(nfe)
9
+ if hash.blank?
10
+ raise TypeError, 'Invalid NFe type, need Hash ou XML(string)'
11
+ end
12
+ @nfe = Conjunto.new(hash)
13
+ end
14
+
15
+ def to_dfe
16
+ @documento = mapear_documento
17
+ end
18
+
19
+ def mapear_documento
20
+ {
21
+ idDocFiscal: inf_nfe.atributo('ide.cNF'),
22
+ natOp: inf_nfe.atributo('ide.natOp'),
23
+ tipoPagto: inf_nfe.atributo('ide.indPag'),
24
+ modelo: inf_nfe.atributo('ide.mod'),
25
+ serie: inf_nfe.atributo('ide.serie'),
26
+ numero: inf_nfe.atributo('ide.nNF'),
27
+ dtEmissao: data_de_emissao,
28
+ dtES: inf_nfe.atributo('ide.dSaiEnt'),
29
+ dtPagto: inf_nfe.atributo('ide.dSaiEnt'),
30
+ cMunFG: inf_nfe.atributo('ide.cMunFg'),
31
+ refNFP: inf_nfe.atributo('ide.refNFP'),
32
+ refCTE: inf_nfe.atributo('ide.refCTE'),
33
+ refECF: inf_nfe.atributo('ide.refECF'),
34
+ tpImp: inf_nfe.atributo('ide.tpImp'),
35
+ tpEmis: inf_nfe.atributo('ide.tpEmis'),
36
+ cDV: inf_nfe.atributo('ide.cDV'),
37
+ tpAmb: inf_nfe.atributo('ide.tpAmb'),
38
+ finNFe: inf_nfe.atributo('ide.finNFe'),
39
+ procEmi: inf_nfe.atributo('ide.procEmi'),
40
+ verProc: inf_nfe.atributo('ide.verProc'),
41
+ dhCont: inf_nfe.atributo('ide.dhCont'),
42
+ xJust: inf_nfe.atributo('ide.xJust'),
43
+ emitente: emitente,
44
+ destinatario: destinatario,
45
+ retirada: retirada,
46
+ entrega: entrega,
47
+ itensDocFiscal: itens,
48
+ tipoOperacao: tipo_de_operacao,
49
+ tpDocFiscal: 'FT',
50
+ naturezaOperacao: '002'
51
+ }.compact
52
+ end
53
+
54
+ def emitente
55
+ emit = inf_nfe.atributo('emit')
56
+ endereco = endereco(emit.atributo('enderEmit'))
57
+ {
58
+ cnpj: emit.atributo('CNPJ'),
59
+ cpf: emit.atributo('CPF'),
60
+ nome: emit.atributo('xNome'),
61
+ xFant: emit.atributo('xFant'),
62
+ inscricaoEstadual: emit.atributo('IE'),
63
+ IEST: emit.atributo('IEST'),
64
+ inscricaoMunicipal: emit.atributo('IM'),
65
+ cdAtividadeEconomica: emit.atributo('CNAE'),
66
+ contribuinteICMS: emit.atributo('IE') ? 'S' : 'N',
67
+ # contribuinteIPI: emit.atributo('IE') ? 'S' : 'N',
68
+ contribuinteST: emit.atributo('IEST') ? 'S' : 'N',
69
+ contribuinteISS: emit.atributo('IM') ? 'S' : 'N',
70
+ contribuintePIS: emit.atributo('CNPJ') ? 'S' : 'N',
71
+ contribuinteCOFINS: emit.atributo('CNPJ') ? 'S' : 'N',
72
+ contribuinteII: 'S',
73
+ simplesNac: [1, 2].include?(emit.atributo('CRT')) ? 'S' : 'N'
74
+ }.merge(endereco).compact
75
+ end
76
+
77
+ def destinatario
78
+ dest = inf_nfe.atributo('dest')
79
+ endereco = endereco(dest.atributo('enderDest'))
80
+ {
81
+ cnpj: dest.atributo('CNPJ'),
82
+ cpf: dest.atributo('CPF'),
83
+ nome: dest.atributo('xNome'),
84
+ inscricaoEstadual: dest.atributo('IE'),
85
+ contribuinteICMS: dest.atributo('IE') ? 'S' : 'N',
86
+ # contribuinteIPI: dest.atributo('IE') ? 'S' : 'N',
87
+ contribuintePIS: dest.atributo('CNPJ') ? 'S' : 'N',
88
+ contribuinteCOFINS: dest.atributo('CNPJ') ? 'S' : 'N',
89
+ contribuinteII: 'S',
90
+ ISUF: dest.atributo('ISUF'),
91
+ email: dest.atributo('email')
92
+ }.merge(endereco).compact
93
+ end
94
+
95
+ def endereco(ender)
96
+ return {} unless ender.present?
97
+ {
98
+ xLgr: ender.atributo('xLgr'),
99
+ Nro: ender.atributo('Nro'),
100
+ xCpl: ender.atributo('xCpl'),
101
+ xBairro: ender.atributo('xBairro'),
102
+ cdMunicipio: ender.atributo('cMun'),
103
+ xMun: ender.atributo('xMun'),
104
+ uf: ender.atributo('UF'),
105
+ cep: ender.atributo('CEP'),
106
+ cdPais: codigo_pais(ender.atributo('cPais')),
107
+ xPais: ender.atributo('xPais'),
108
+ fone: ender.atributo('fone')
109
+ }.compact
110
+ end
111
+
112
+ def retirada
113
+ inf_nfe.atributo('retirada')
114
+ end
115
+
116
+ def entrega
117
+ inf_nfe.atributo('entrega')
118
+ end
119
+
120
+ def itens
121
+ itens = inf_nfe.atributo('det')
122
+ itens = [itens] unless itens.is_a?(Array)
123
+ itens.map do |item|
124
+ produto = item.atributo('prod')
125
+ next unless produto.present?
126
+ {
127
+ cdCSTICMS: cst_icms_do_item(item),
128
+ cdCSTIPI: cst_ipi_do_item(item),
129
+ cdCSTPIS: cst_pis_do_item(item),
130
+ cdCSTCOFINS: cst_cofins_do_item(item),
131
+ cdItemDocFiscal: item.atributo('nItem'),
132
+ cdCfop: produto.atributo('CFOP'),
133
+ unidade: produto.atributo('uCom'),
134
+ qtItemDocFiscal: produto.atributo('qCom'),
135
+ vlUnitario: produto.atributo('vUnCom'),
136
+ vlTotalCI: produto.atributo('vProd'),
137
+ vlTotal: produto.atributo('vProd'),
138
+ qtTributariaUnidade: produto.atributo('uTrib'),
139
+ qtTributaria: quantidade_tributaria_do_item(item),
140
+ vUnTrib: produto.atributo('vUnTrib'),
141
+ vlFrete: produto.atributo('vFrete'),
142
+ vlSeguro: produto.atributo('vSeg'),
143
+ vlDesconto: produto.atributo('vDesc'),
144
+ vlOda: produto.atributo('vOutro'),
145
+ DI: produto.atributo('DI'),
146
+ xPed: produto.atributo('xPed'),
147
+ nItemPed: produto.atributo('nItemPed'),
148
+ cdClassificacao: 'M',
149
+ deduzCFOP: 'S',
150
+ deduzCSTICMS: 'S',
151
+ deduzCSTPIS: 'S',
152
+ deduzCSTCOFINS: 'S',
153
+ deduzCSTIPI: 'S',
154
+ prodItem: produto_do_item(item),
155
+ enquadramentos: enquadramentos_do_item(item)
156
+ }.compact
157
+ end.compact
158
+ end
159
+
160
+ def produto_do_item(item)
161
+ produto = item.atributo('prod')
162
+ return {} unless produto.present?
163
+ {
164
+ indTot: produto.atributo('indTot'),
165
+ cEANTrib: produto.atributo('cEANTrib'),
166
+ codigo: produto.atributo('cProd'),
167
+ EAN: produto.atributo('cEAN'),
168
+ descricao: produto.atributo('xProd'),
169
+ NCM: produto.atributo('NCM'),
170
+ CEST: produto.atributo('CEST'),
171
+ exTIPI: produto.atributo('EXTIPI'),
172
+ cdOrigem: origem_do_produto(item),
173
+ aplicacao: 'C'
174
+ }.compact
175
+ end
176
+
177
+ def icms_do_item(item)
178
+ unless item.dados(:icms).present?
179
+ imposto = item.atributo('imposto.ICMS')
180
+ ['ICMS00', 'ICMS10', 'ICMS20', 'ICMS30', 'ICMS40', 'ICMS51', 'ICMS60', 'ICMS70', 'ICMS90'].each do |tipo_icms|
181
+ item.dados(:icms, imposto.atributo(tipo_icms))
182
+ if item.dados(:icms).present?
183
+ item.dados(:icms).atualizar(tipo: tipo_icms)
184
+ break
185
+ end
186
+ end
187
+ end
188
+ item.dados(:icms)
189
+ end
190
+
191
+ def ipi_do_item(item)
192
+ unless item.dados(:ipi).present?
193
+ item.dados(:ipi, item.atributo('imposto.IPI'))
194
+ ['IPINT', 'IPITrib'].each do |tipo|
195
+ imposto = item.dados(:ipi).atributo(tipo)
196
+ if imposto.present?
197
+ item.dados(:ipi).atualizar(imposto.to_h)
198
+ item.dados(:ipi).atualizar(tipo: tipo)
199
+ break
200
+ end
201
+ end
202
+ end
203
+ item.dados(:ipi)
204
+ end
205
+
206
+ def pis_do_item(item)
207
+ unless item.dados(:pis).present?
208
+ imposto = item.atributo('imposto.PIS')
209
+ ['PISNT', 'PISAliq', 'PISQtde', 'PISOutr'].each do |tipo|
210
+ item.dados(:pis, imposto.atributo(tipo))
211
+ if item.dados(:pis).present?
212
+ item.dados(:pis).atualizar(tipo: tipo)
213
+ break
214
+ end
215
+ end
216
+ end
217
+ item.dados(:pis)
218
+ end
219
+
220
+ def cofins_do_item(item)
221
+ unless item.dados(:cofins).present?
222
+ imposto = item.atributo('imposto.COFINS')
223
+ ['COFINSAliq', 'COFINSQtde', 'COFINSNT', 'COFINSOutr'].each do |tipo|
224
+ item.dados(:cofins, imposto.atributo(tipo))
225
+ if item.dados(:cofins).present?
226
+ item.dados(:cofins).atualizar(tipo: tipo)
227
+ break
228
+ end
229
+ end
230
+ end
231
+ item.dados(:cofins)
232
+ end
233
+
234
+ def enquadramentos_do_item(item)
235
+ imposto = item.atributo('imposto')
236
+ icms = icms_do_item(item)
237
+ [
238
+ enquadramento_icms(icms), # 0 ICMS
239
+ enquadramento_icmsst(icms), # 1 ST
240
+ nil, # 2 ???
241
+ enquadramento_icmsste(icms), # 3 STE
242
+ enquadramento_ipi(ipi_do_item(item)), # 4 IPI
243
+ enquadramento_ii(imposto.atributo('II')), # 5 II
244
+ enquadramento_pis(pis_do_item(item)), # 6 PIS
245
+ enquadramento_pisst(imposto.atributo('PISST')), # 7 PISST
246
+ enquadramento_cofins(cofins_do_item(item)), # 8 COFINS
247
+ enquadramento_cofinsst(imposto.atributo('COFINSST')), # 9 COFINSST
248
+ ]
249
+ end
250
+
251
+ def enquadramento_icms(icms)
252
+ return if icms.blank? ||
253
+ ['ICMS00', 'ICMS10', 'ICMS20', 'ICMS40', 'ICMS51', 'ICMS70', 'ICMS90'].exclude?(icms.atributo('tipo'))
254
+ {
255
+ dsSigla: 'ICMS',
256
+ situacao: situacao_do_icms_cst(icms.atributo('CST')),
257
+ tpEnquadramento: 'IM',
258
+ vlTributavel: icms.atributo('vBC'),
259
+ vlAliquota: icms.atributo('pICMS'),
260
+ vlImposto: icms.atributo('vICMS'),
261
+ percReducaoBase: icms.atributo('pRedBC'),
262
+ modbc: icms.atributo('modbc')
263
+ }.compact
264
+ end
265
+
266
+ def enquadramento_icmsst(icms)
267
+ return if icms.blank? ||
268
+ ['ICMS10', 'ICMS30', 'ICMS70', 'ICMS90'].exclude?(icms.atributo('tipo'))
269
+ {
270
+ dsSigla: 'ST',
271
+ situacao: situacao_do_icms_cst(icms.atributo('CST')),
272
+ tpEnquadramento: 'IM',
273
+ vlBase: icms.atributo('vBCST'),
274
+ vlTributavel: icms.atributo('vBCST'),
275
+ vlAliquota: icms.atributo('pICMSST'),
276
+ vlImposto: icms.atributo('vICMSST'),
277
+ vlPercentualMVA: icms.atributo('pMVAST'),
278
+ percReducaoBase: icms.atributo('pRedBCST'),
279
+ modBCST: icms.atributo('modBCST')
280
+ }.compact
281
+ end
282
+
283
+ def enquadramento_icmsste(icms)
284
+ return if icms.blank? ||
285
+ ['ICMS60'].exclude?(icms.atributo('tipo'))
286
+ {
287
+ dsSigla: 'STE',
288
+ situacao: situacao_do_icms_cst(icms.atributo('CST')),
289
+ tpEnquadramento: 'IM',
290
+ vlBase: icms.atributo('vBCST'),
291
+ vlTributavel: icms.atributo('vBCSTRet'),
292
+ vlImposto: icms.atributo('vICMSSTRet'),
293
+ vlPercentualMVA: icms.atributo('pMVAST')
294
+ }.compact
295
+ end
296
+
297
+ def enquadramento_ipi(ipi)
298
+ return if ipi.blank?
299
+ vlr_unid = ipi.atributo('vUnid')
300
+ {
301
+ dsSigla: 'IPI',
302
+ situacao: 'T',
303
+ tpEnquadramento: 'IM',
304
+ clEnq: ipi.atributo('clEnq'),
305
+ CNPJProd: ipi.atributo('CNPJProd'),
306
+ cSelo: ipi.atributo('cSelo'),
307
+ qSelo: ipi.atributo('qSelo'),
308
+ cEnq: ipi.atributo('cEnq'),
309
+ vlImposto: ipi.atributo('vIPI'),
310
+ vlTributavel: (vlr_unid.present? && vlr_unid.to_f > 0 ? 0 : ipi.atributo('vBC')),
311
+ vlAliquota: ipi.atributo('pIPI'),
312
+ vUnid: vlr_unid,
313
+ qUnid: ipi.atributo('qUnid')
314
+ }.compact
315
+ end
316
+
317
+ def enquadramento_ii(ii)
318
+ return if ii.blank? || ii.atributo('vII').to_f <= 0.0
319
+ {
320
+ dsSigla: 'II',
321
+ situacao: 'T',
322
+ vlTributavel: ii.atributo('vBC'),
323
+ vlImposto: ii.atributo('vII'),
324
+ vlIOF: ii.atributo('vlIOF'),
325
+ vDespAdu: ii.atributo('vDespAdu'),
326
+ tpEnquadramento: 'IM'
327
+ }.compact
328
+ end
329
+
330
+ def enquadramento_pis(pis)
331
+ return unless pis.present?
332
+ {
333
+ dsSigla: 'PIS',
334
+ tpEnquadramento: 'IM',
335
+ situacao: 'T',
336
+ vlTributavel: pis.atributo('vBC'),
337
+ vlAliquota: pis.atributo('pPIS'),
338
+ vlImposto: pis.atributo('vPIS'),
339
+ qBCProd: pis.atributo('qBCProd'),
340
+ vlImpostoUnitario: pis.atributo('vAliqProd')
341
+ }.compact
342
+ end
343
+
344
+ def enquadramento_pisst(pisst)
345
+ return unless pisst.present?
346
+ {
347
+ dsSigla: 'PISST',
348
+ tpEnquadramento: 'IM',
349
+ situacao: 'T',
350
+ vlTributavel: pisst.atributo('vBC'),
351
+ vlAliquota: pisst.atributo('pPIS'),
352
+ vlImposto: pisst.atributo('vPIS'),
353
+ vlImpostoUnitario: pisst.atributo('vAliqProd')
354
+ }.compact
355
+ end
356
+
357
+ def enquadramento_cofins(cofins)
358
+ return unless cofins.present?
359
+ {
360
+ dsSigla: 'COFINS',
361
+ tpEnquadramento: 'IM',
362
+ situacao: cofins.atributo('tipo') == 'COFINSNT' ? 'N' : 'T',
363
+ vlTributavel: cofins.atributo('vBC'),
364
+ vlAliquota: cofins.atributo('pCOFINS'),
365
+ vlImposto: cofins.atributo('vCOFINS'),
366
+ qBCProd: cofins.atributo('qBCProd'),
367
+ vlImpostoUnitario: cofins.atributo('vAliqProd')
368
+ }.compact
369
+ end
370
+
371
+ def enquadramento_cofinsst(cofinsst)
372
+ return unless cofinsst.present?
373
+ {
374
+ dsSigla: 'COFINSST',
375
+ tpEnquadramento: 'IM',
376
+ situacao: 'T',
377
+ vlTributavel: cofinsst.atributo('vBC'),
378
+ vlAliquota: cofinsst.atributo('pCOFINS'),
379
+ vlImposto: cofinsst.atributo('vCOFINS'),
380
+ vlImpostoUnitario: cofinsst.atributo('vAliqProd')
381
+ }.compact
382
+ end
383
+
384
+ def data_de_emissao
385
+ inf_nfe.atributo('ide.dEmi') || inf_nfe.atributo('ide.dhEmi')
386
+ end
387
+
388
+ def tipo_de_operacao
389
+ emit_uf = inf_nfe.atributo('emit.UF')
390
+ dest_uf = inf_nfe.atributo('dest.UF')
391
+ if emit_uf && dest_uf
392
+ emit_uf == dest_uf ? 'E' : 'I'
393
+ end
394
+ end
395
+
396
+ # cod_pais = NFe cPais
397
+ def codigo_pais(cod_pais)
398
+ if cod_pais.nil? || cod_pais == '1058'
399
+ '105'
400
+ else
401
+ cod_pais
402
+ end
403
+ end
404
+
405
+ def origem_do_produto(item)
406
+ ipi_do_item(item).atributo('orig') || icms_do_item(item).atributo('orig')
407
+ end
408
+
409
+ def cst_icms_do_item(item)
410
+ icms = icms_do_item(item)
411
+ cst_icms = "#{icms.atributo('orig')}#{icms.atributo('CST')}"
412
+ cst_icms.present? ? cst_icms : nil
413
+ end
414
+
415
+ def cst_ipi_do_item(item)
416
+ ipi_do_item(item).atributo('CST')
417
+ end
418
+
419
+ def cst_pis_do_item(item)
420
+ pis_do_item(item).atributo('CST')
421
+ end
422
+
423
+ def cst_cofins_do_item(item)
424
+ cofins_do_item(item).atributo('CST')
425
+ end
426
+
427
+ def situacao_do_icms_cst(cst)
428
+ return if cst.blank?
429
+ case cst.to_s
430
+ when '40' # Isenta
431
+ 'I'
432
+ when '41' # Não tributada
433
+ 'N'
434
+ when '50' # Suspensão
435
+ 'S'
436
+ when '51' # Diferimento
437
+ 'D'
438
+ else # Tributada
439
+ 'T'
440
+ end
441
+ end
442
+
443
+ def quantidade_tributaria_do_item(item)
444
+ item.atributo('imposto.COFINSST.qBCProd') ||
445
+ item.atributo('imposto.COFINS.COFINSOutr.qBCProd') ||
446
+ item.atributo('imposto.PISST.qBCProd') ||
447
+ item.atributo('imposto.PIS.PISOutr.qBCProd') ||
448
+ item.atributo('prod.qTrib')
449
+ end
450
+
451
+ private
452
+ def inf_nfe
453
+ @inf_nfe ||= nfe.atributo('nfeProc.NFe.infNFe') ||
454
+ nfe.atributo('NFe.infNFe') ||
455
+ nfe.atributo('infNFe') ||
456
+ Conjunto.new({})
457
+ end
458
+
459
+ end
460
+ end