Passed
Push — master ( 86bb06...22a4bb )
by Francimar
08:25
created

Nota::addInformacao()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 0
cts 3
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 2
1
<?php
2
/**
3
 * MIT License
4
 *
5
 * Copyright (c) 2016 MZ Desenvolvimento de Sistemas LTDA
6
 *
7
 * @author Francimar Alves <[email protected]>
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy
10
 * of this software and associated documentation files (the "Software"), to deal
11
 * in the Software without restriction, including without limitation the rights
12
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
 * copies of the Software, and to permit persons to whom the Software is
14
 * furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in all
17
 * copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
 * SOFTWARE.
26
 *
27
 */
28
namespace NFe\Core;
29
30
use NFe\Common\Util;
31
use NFe\Common\Node;
32
use NFe\Task\Protocolo;
33
use NFe\Entity\Imposto;
34
use NFe\Entity\Produto;
35
use NFe\Entity\Emitente;
36
use NFe\Entity\Pagamento;
37
use NFe\Entity\Transporte;
38
use NFe\Entity\Destinatario;
39
use NFe\Exception\ValidationException;
40
use FR3D\XmlDSig\Adapter\AdapterInterface;
41
use FR3D\XmlDSig\Adapter\XmlseclibsAdapter;
42
43
/**
44
 * Classe base para a formação da nota fiscal
45
 */
46
abstract class Nota implements Node
0 ignored issues
show
Complexity introduced by
The class Nota has a coupling between objects value of 19. Consider to reduce the number of dependencies under 13.
Loading history...
Complexity introduced by
This class has 2011 lines of code which exceeds the configured maximum of 1000.

Really long classes often contain too much logic and violate the single responsibility principle.

We suggest to take a look at the “Code” section for options on how to refactor this code.

Loading history...
Complexity introduced by
This class has 77 public methods and attributes which exceeds the configured maximum of 45.

The number of this metric differs depending on the chosen design (inheritance vs. composition). For inheritance, the number should generally be a bit lower.

A high number indicates a reusable class. It might also make the class harder to change without breaking other classes though.

Loading history...
Complexity introduced by
This class has 31 fields which exceeds the configured maximum of 15.

Too many fields generally indicate a class which does too much and does not follow the single responsibility principle.

We suggest taking a look at the “Code” section for further suggestions on how to fix this.

Loading history...
Complexity introduced by
This class has a complexity of 270 which exceeds the configured maximum of 50.

The class complexity is the sum of the complexity of all methods. A very high value is usually an indication that your class does not follow the single reponsibility principle and does more than one job.

Some resources for further reading:

You can also find more detailed suggestions for refactoring in the “Code” section of your repository.

Loading history...
47
{
48
49
    /**
50
     * Versão da nota fiscal
51
     */
52
    const VERSAO = '3.10';
53
54
    /**
55
     * Versão do aplicativo gerador da nota
56
     */
57
    const APP_VERSAO = '1.0';
58
59
    /**
60
     * Portal da nota fiscal
61
     */
62
    const PORTAL = 'http://www.portalfiscal.inf.br/nfe';
63
64
    /**
65
     * Código do modelo do Documento Fiscal. 55 = NF-e; 65 = NFC-e.
66
     */
67
    const MODELO_NFE = 'nfe';
68
    const MODELO_NFCE = 'nfce';
69
70
    /**
71
     * Tipo do Documento Fiscal (0 - entrada; 1 - saída)
72
     */
73
    const TIPO_ENTRADA = 'entrada';
74
    const TIPO_SAIDA = 'saida';
75
76
    /**
77
     * Identificador de Local de destino da operação
78
     * (1-Interna;2-Interestadual;3-Exterior)
79
     */
80
    const DESTINO_INTERNA = 'interna';
81
    const DESTINO_INTERESTADUAL = 'interestadual';
82
    const DESTINO_EXTERIOR = 'exterior';
83
84
    /**
85
     * Indicador da forma de pagamento: 0 – pagamento à vista; 1 – pagamento à
86
     * prazo; 2 – outros.
87
     */
88
    const INDICADOR_AVISTA = 'avista';
89
    const INDICADOR_APRAZO = 'aprazo';
90
    const INDICADOR_OUTROS = 'outros';
91
92
    /**
93
     * Formato de impressão do DANFE (0-sem DANFE;1-DANFe Retrato; 2-DANFe
94
     * Paisagem;3-DANFe Simplificado;4-DANFe NFC-e;5-DANFe NFC-e em mensagem
95
     * eletrônica)
96
     */
97
    const FORMATO_NENHUMA = 'nenhuma';
98
    const FORMATO_RETRATO = 'retrato';
99
    const FORMATO_PAISAGEM = 'paisagem';
100
    const FORMATO_SIMPLIFICADO = 'simplificado';
101
    const FORMATO_CONSUMIDOR = 'consumidor';
102
    const FORMATO_MENSAGEM = 'mensagem';
103
104
    /**
105
     * Forma de emissão da NF-e
106
     */
107
    const EMISSAO_NORMAL = 'normal';
108
    const EMISSAO_CONTINGENCIA = 'contingencia';
109
110
    /**
111
     * Identificação do Ambiente: 1 - Produção, 2 - Homologação
112
     */
113
    const AMBIENTE_PRODUCAO = 'producao';
114
    const AMBIENTE_HOMOLOGACAO = 'homologacao';
115
116
    /**
117
     * Finalidade da emissão da NF-e: 1 - NFe normal, 2 - NFe complementar, 3 -
118
     * NFe de ajuste, 4 - Devolução/Retorno
119
     */
120
    const FINALIDADE_NORMAL = 'normal';
121
    const FINALIDADE_COMPLEMENTAR = 'complementar';
122
    const FINALIDADE_AJUSTE = 'ajuste';
123
    const FINALIDADE_RETORNO = 'retorno';
124
125
    /**
126
     * Indicador de presença do comprador no estabelecimento comercial no
127
     * momento da oepração (0-Não se aplica, ex.: Nota Fiscal complementar ou
128
     * de ajuste;1-Operação presencial;2-Não presencial, internet;3-Não
129
     * presencial, teleatendimento;4-NFC-e entrega em domicílio;9-Não
130
     * presencial, outros)
131
     */
132
    const PRESENCA_NENHUM = 'nenhum';
133
    const PRESENCA_PRESENCIAL = 'presencial';
134
    const PRESENCA_INTERNET = 'internet';
135
    const PRESENCA_TELEATENDIMENTO = 'teleatendimento';
136
    const PRESENCA_ENTREGA = 'entrega';
137
    const PRESENCA_OUTROS = 'outros';
138
139
    /**
140
     * Chave da nota fiscal
141
     */
142
    private $id;
143
    /**
144
     * Número do Documento Fiscal
145
     */
146
    private $numero;
147
    /**
148
     * Emitente da nota fiscal
149
     */
150
    private $emitente;
151
    /**
152
     * Destinatário que receberá os produtos
153
     */
154
    private $destinatario;
155
    /**
156
     * Produtos adicionados na nota
157
     */
158
    private $produtos;
159
    /**
160
     * Informações de trasnporte da mercadoria
161
     */
162
    private $transporte;
163
    /**
164
     * Pagamentos realizados
165
     */
166
    private $pagamentos;
167
    /**
168
     * Data e Hora da saída ou de entrada da mercadoria / produto
169
     */
170
    private $data_movimentacao;
171
    /**
172
     * Informar a data e hora de entrada em contingência
173
     */
174
    private $data_contingencia;
175
    /**
176
     * Informar a Justificativa da entrada em contingência
177
     */
178
    private $justificativa;
179
    /**
180
     * Código do modelo do Documento Fiscal. 55 = NF-e; 65 = NFC-e.
181
     */
182
    private $modelo;
183
    /**
184
     * Tipo do Documento Fiscal (0 - entrada; 1 - saída)
185
     */
186
    private $tipo;
187
    /**
188
     * Identificador de Local de destino da operação
189
     * (1-Interna;2-Interestadual;3-Exterior)
190
     */
191
    private $destino;
192
    /**
193
     * Descrição da Natureza da Operação
194
     */
195
    private $natureza;
196
    /**
197
     * Código numérico que compõe a Chave de Acesso. Número aleatório gerado
198
     * pelo emitente para cada NF-e.
199
     */
200
    private $codigo;
201
    /**
202
     * Indicador da forma de pagamento: 0 – pagamento à vista; 1 – pagamento à
203
     * prazo; 2 – outros.
204
     */
205
    private $indicador;
206
    /**
207
     * Data e Hora de emissão do Documento Fiscal
208
     */
209
    private $data_emissao;
210
    /**
211
     * Série do Documento Fiscal: série normal 0-889, Avulsa Fisco 890-899,
212
     * SCAN 900-999
213
     */
214
    private $serie;
215
    /**
216
     * Formato de impressão do DANFE (0-sem DANFE;1-DANFe Retrato; 2-DANFe
217
     * Paisagem;3-DANFe Simplificado;4-DANFe NFC-e;5-DANFe NFC-e em mensagem
218
     * eletrônica)
219
     */
220
    private $formato;
221
    /**
222
     * Forma de emissão da NF-e
223
     */
224
    private $emissao;
225
    /**
226
     * Digito Verificador da Chave de Acesso da NF-e
227
     */
228
    private $digito_verificador;
229
    /**
230
     * Identificação do Ambiente: 1 - Produção, 2 - Homologação
231
     */
232
    private $ambiente;
233
    /**
234
     * Finalidade da emissão da NF-e: 1 - NFe normal, 2 - NFe complementar, 3 -
235
     * NFe de ajuste, 4 - Devolução/Retorno
236
     */
237
    private $finalidade;
238
    /**
239
     * Indica operação com consumidor final (0-Não;1-Consumidor Final)
240
     */
241
    private $consumidor_final;
242
    /**
243
     * Indicador de presença do comprador no estabelecimento comercial no
244
     * momento da oepração (0-Não se aplica, ex.: Nota Fiscal complementar ou
245
     * de ajuste;1-Operação presencial;2-Não presencial, internet;3-Não
246
     * presencial, teleatendimento;4-NFC-e entrega em domicílio;9-Não
247
     * presencial, outros)
248
     */
249
    private $presenca;
250
    /**
251
     * Valor estimado total de impostos federais, estaduais e municipais
252
     */
253
    private $tributos;
254
    /**
255
     * Informações adicionais de interesse do Fisco
256
     */
257
    private $adicionais;
258
    /**
259
     * Informações complementares de interesse do Contribuinte
260
     */
261
    private $complemento;
262
    /**
263
     * Campo de uso livre do contribuinte informar o nome do campo no atributo
264
     * xCampo e o conteúdo do campo no xTexto
265
     */
266
    private $observacoes;
267
    /**
268
     * Campo de uso exclusivo do Fisco informar o nome do campo no atributo
269
     * xCampo e o conteúdo do campo no xTexto
270
     */
271
    private $informacoes;
272
    /**
273
     * Protocolo de autorização da nota, informado apenas quando a nota for
274
     * enviada e autorizada
275
     */
276
    private $protocolo;
277
278
    /**
279
     * Constroi uma instância de Nota vazia
280
     * @param  array $nota Array contendo dados da Nota
281
     */
282 7
    public function __construct($nota = array())
283
    {
284 7
        $this->fromArray($nota);
285 7
    }
286
287
    /**
288
     * Chave da nota fiscal
289
     * @param boolean $normalize informa se o id deve estar no formato do XML
290
     * @return mixed id da Nota
291
     */
292 5
    public function getID($normalize = false)
293
    {
294 5
        if (!$normalize) {
295 5
            return $this->id;
296
        }
297 5
        return 'NFe'.$this->id;
298
    }
299
300
    /**
301
     * Altera o valor do ID para o informado no parâmetro
302
     * @param mixed $id novo valor para ID
303
     * @return Nota A própria instância da classe
304
     */
305 7
    public function setID($id)
306
    {
307 7
        $this->id = $id;
308 7
        return $this;
309
    }
310
311
    /**
312
     * Número do Documento Fiscal
313
     * @param boolean $normalize informa se o numero deve estar no formato do XML
314
     * @return mixed numero da Nota
315
     */
316 5
    public function getNumero($normalize = false)
317
    {
318 5
        if (!$normalize) {
319 5
            return $this->numero;
320
        }
321 5
        return $this->numero;
322
    }
323
324
    /**
325
     * Altera o valor do Numero para o informado no parâmetro
326
     * @param mixed $numero novo valor para Numero
327
     * @return Nota A própria instância da classe
328
     */
329 7
    public function setNumero($numero)
330
    {
331 7
        $this->numero = $numero;
332 7
        return $this;
333
    }
334
335
    /**
336
     * Emitente da nota fiscal
337
     * @return mixed emitente da Nota
338
     */
339 5
    public function getEmitente()
340
    {
341 5
        return $this->emitente;
342
    }
343
344
    /**
345
     * Altera o valor do Emitente para o informado no parâmetro
346
     * @param mixed $emitente novo valor para Emitente
347
     * @return Nota A própria instância da classe
348
     */
349 7
    public function setEmitente($emitente)
350
    {
351 7
        $this->emitente = $emitente;
352 7
        return $this;
353
    }
354
355
    /**
356
     * Destinatário que receberá os produtos
357
     * @return mixed destinatario da Nota
358
     */
359 5
    public function getDestinatario()
360
    {
361 5
        return $this->destinatario;
362
    }
363
364
    /**
365
     * Altera o valor do Destinatario para o informado no parâmetro
366
     * @param mixed $destinatario novo valor para Destinatario
367
     * @return Nota A própria instância da classe
368
     */
369 7
    public function setDestinatario($destinatario)
370
    {
371 7
        $this->destinatario = $destinatario;
372 7
        return $this;
373
    }
374
375
    /**
376
     * Produtos adicionados na nota
377
     * @return mixed produtos da Nota
378
     */
379 5
    public function getProdutos()
380
    {
381 5
        return $this->produtos;
382
    }
383
384
    /**
385
     * Altera o valor do Produtos para o informado no parâmetro
386
     * @param mixed $produtos novo valor para Produtos
387
     * @return Nota A própria instância da classe
388
     */
389 7
    public function setProdutos($produtos)
390
    {
391 7
        $this->produtos = $produtos;
392 7
        return $this;
393
    }
394
395
    /**
396
     * Adiciona um(a) Produto para a lista de produto
397
     * @param Produto $produto Instância do Produto que será adicionada
398
     * @return Nota A própria instância da classe
399
     */
400 2
    public function addProduto($produto)
401
    {
402 2
        $this->produtos[] = $produto;
403 2
        return $this;
404
    }
405
406
    /**
407
     * Informações de trasnporte da mercadoria
408
     * @return mixed transporte da Nota
409
     */
410 5
    public function getTransporte()
411
    {
412 5
        return $this->transporte;
413
    }
414
415
    /**
416
     * Altera o valor da Transporte para o informado no parâmetro
417
     * @param mixed $transporte novo valor para Transporte
418
     * @return Nota A própria instância da classe
419
     */
420 7
    public function setTransporte($transporte)
421
    {
422 7
        $this->transporte = $transporte;
423 7
        return $this;
424
    }
425
426
    /**
427
     * Pagamentos realizados
428
     * @return mixed pagamentos da Nota
429
     */
430 5
    public function getPagamentos()
431
    {
432 5
        return $this->pagamentos;
433
    }
434
435
    /**
436
     * Altera o valor do Pagamentos para o informado no parâmetro
437
     * @param mixed $pagamentos novo valor para Pagamentos
438
     * @return Nota A própria instância da classe
439
     */
440 7
    public function setPagamentos($pagamentos)
441
    {
442 7
        $this->pagamentos = $pagamentos;
443 7
        return $this;
444
    }
445
446
    /**
447
     * Adiciona um(a) Pagamento para a lista de pagamento
448
     * @param Pagamento $pagamento Instância do Pagamento que será adicionada
449
     * @return Nota A própria instância da classe
450
     */
451 2
    public function addPagamento($pagamento)
452
    {
453 2
        $this->pagamentos[] = $pagamento;
454 2
        return $this;
455
    }
456
457
    /**
458
     * Data e Hora da saída ou de entrada da mercadoria / produto
459
     * @param boolean $normalize informa se a data_movimentacao deve estar no formato do XML
460
     * @return mixed data_movimentacao da Nota
461
     */
462 5
    public function getDataMovimentacao($normalize = false)
463
    {
464 5
        if (!$normalize) {
465 5
            return $this->data_movimentacao;
466
        }
467
        return Util::toDateTime($this->data_movimentacao);
468
    }
469
470
    /**
471
     * Altera o valor da DataMovimentacao para o informado no parâmetro
472
     * @param mixed $data_movimentacao novo valor para DataMovimentacao
473
     * @return Nota A própria instância da classe
474
     */
475 7
    public function setDataMovimentacao($data_movimentacao)
476
    {
477 7
        if (!is_null($data_movimentacao) && !is_numeric($data_movimentacao)) {
478
            $data_movimentacao = strtotime($data_movimentacao);
479
        }
480 7
        $this->data_movimentacao = $data_movimentacao;
481 7
        return $this;
482
    }
483
484
    /**
485
     * Informar a data e hora de entrada em contingência
486
     * @param boolean $normalize informa se a data_contingencia deve estar no formato do XML
487
     * @return mixed data_contingencia da Nota
488
     */
489 2
    public function getDataContingencia($normalize = false)
490
    {
491 2
        if (!$normalize) {
492 2
            return $this->data_contingencia;
493
        }
494
        return Util::toDateTime($this->data_contingencia);
495
    }
496
497
    /**
498
     * Altera o valor da DataContingencia para o informado no parâmetro
499
     * @param mixed $data_contingencia novo valor para DataContingencia
500
     * @return Nota A própria instância da classe
501
     */
502 7
    public function setDataContingencia($data_contingencia)
503
    {
504 7
        if (!is_null($data_contingencia) && !is_numeric($data_contingencia)) {
505
            $data_contingencia = strtotime($data_contingencia);
506
        }
507 7
        $this->data_contingencia = $data_contingencia;
508 7
        return $this;
509
    }
510
511
    /**
512
     * Informar a Justificativa da entrada em contingência
513
     * @param boolean $normalize informa se a justificativa deve estar no formato do XML
514
     * @return mixed justificativa da Nota
515
     */
516 2
    public function getJustificativa($normalize = false)
517
    {
518 2
        if (!$normalize) {
519 2
            return $this->justificativa;
520
        }
521
        return $this->justificativa;
522
    }
523
524
    /**
525
     * Altera o valor da Justificativa para o informado no parâmetro
526
     * @param mixed $justificativa novo valor para Justificativa
527
     * @return Nota A própria instância da classe
528
     */
529 7
    public function setJustificativa($justificativa)
530
    {
531 7
        $this->justificativa = $justificativa;
532 7
        return $this;
533
    }
534
535
    /**
536
     * Código do modelo do Documento Fiscal. 55 = NF-e; 65 = NFC-e.
537
     * @param boolean $normalize informa se o modelo deve estar no formato do XML
538
     * @return mixed modelo da Nota
539
     */
540 5
    public function getModelo($normalize = false)
541
    {
542 5
        if (!$normalize) {
543 4
            return $this->modelo;
544
        }
545 5
        switch ($this->modelo) {
546 5
            case self::MODELO_NFE:
547
                return '55';
548 5
            case self::MODELO_NFCE:
549 5
                return '65';
550
        }
551
        return $this->modelo;
552
    }
553
554
    /**
555
     * Altera o valor do Modelo para o informado no parâmetro
556
     * @param mixed $modelo novo valor para Modelo
557
     * @return Nota A própria instância da classe
558
     */
559 7
    public function setModelo($modelo)
560
    {
561
        switch ($modelo) {
562 7
            case '55':
563
                $modelo = self::MODELO_NFE;
564
                break;
565 7
            case '65':
566 3
                $modelo = self::MODELO_NFCE;
567 3
                break;
568
        }
569 7
        $this->modelo = $modelo;
570 7
        return $this;
571
    }
572
573
    /**
574
     * Tipo do Documento Fiscal (0 - entrada; 1 - saída)
575
     * @param boolean $normalize informa se o tipo deve estar no formato do XML
576
     * @return mixed tipo da Nota
577
     */
578 5
    public function getTipo($normalize = false)
579
    {
580 5
        if (!$normalize) {
581 2
            return $this->tipo;
582
        }
583 5
        switch ($this->tipo) {
584 5
            case self::TIPO_ENTRADA:
585
                return '0';
586 5
            case self::TIPO_SAIDA:
587 5
                return '1';
588
        }
589
        return $this->tipo;
590
    }
591
592
    /**
593
     * Altera o valor do Tipo para o informado no parâmetro
594
     * @param mixed $tipo novo valor para Tipo
595
     * @return Nota A própria instância da classe
596
     */
597 7
    public function setTipo($tipo)
598
    {
599
        switch ($tipo) {
600 7
            case '0':
601
                $tipo = self::TIPO_ENTRADA;
602
                break;
603 7
            case '1':
604 3
                $tipo = self::TIPO_SAIDA;
605 3
                break;
606
        }
607 7
        $this->tipo = $tipo;
608 7
        return $this;
609
    }
610
611
    /**
612
     * Identificador de Local de destino da operação
613
     * (1-Interna;2-Interestadual;3-Exterior)
614
     * @param boolean $normalize informa se o destino deve estar no formato do XML
615
     * @return mixed destino da Nota
616
     */
617 5
    public function getDestino($normalize = false)
618
    {
619 5
        if (!$normalize) {
620 2
            return $this->destino;
621
        }
622 5
        switch ($this->destino) {
623 5
            case self::DESTINO_INTERNA:
624 5
                return '1';
625
            case self::DESTINO_INTERESTADUAL:
626
                return '2';
627
            case self::DESTINO_EXTERIOR:
628
                return '3';
629
        }
630
        return $this->destino;
631
    }
632
633
    /**
634
     * Altera o valor do Destino para o informado no parâmetro
635
     * @param mixed $destino novo valor para Destino
636
     * @return Nota A própria instância da classe
637
     */
638 7
    public function setDestino($destino)
639
    {
640
        switch ($destino) {
641 7
            case '1':
642 3
                $destino = self::DESTINO_INTERNA;
643 3
                break;
644 7
            case '2':
645
                $destino = self::DESTINO_INTERESTADUAL;
646
                break;
647 7
            case '3':
648
                $destino = self::DESTINO_EXTERIOR;
649
                break;
650
        }
651 7
        $this->destino = $destino;
652 7
        return $this;
653
    }
654
655
    /**
656
     * Descrição da Natureza da Operação
657
     * @param boolean $normalize informa se a natureza deve estar no formato do XML
658
     * @return mixed natureza da Nota
659
     */
660 5
    public function getNatureza($normalize = false)
661
    {
662 5
        if (!$normalize) {
663 2
            return $this->natureza;
664
        }
665 5
        return $this->natureza;
666
    }
667
668
    /**
669
     * Altera o valor da Natureza para o informado no parâmetro
670
     * @param mixed $natureza novo valor para Natureza
671
     * @return Nota A própria instância da classe
672
     */
673 7
    public function setNatureza($natureza)
674
    {
675 7
        $this->natureza = $natureza;
676 7
        return $this;
677
    }
678
679
    /**
680
     * Código numérico que compõe a Chave de Acesso. Número aleatório gerado
681
     * pelo emitente para cada NF-e.
682
     * @param boolean $normalize informa se o codigo deve estar no formato do XML
683
     * @return mixed codigo da Nota
684
     */
685 5
    public function getCodigo($normalize = false)
686
    {
687 5
        if (!$normalize) {
688 5
            return $this->codigo;
689
        }
690 5
        return Util::padDigit($this->codigo % 100000000, 8);
691
    }
692
693
    /**
694
     * Altera o valor do Codigo para o informado no parâmetro
695
     * @param mixed $codigo novo valor para Codigo
696
     * @return Nota A própria instância da classe
697
     */
698 7
    public function setCodigo($codigo)
699
    {
700 7
        $this->codigo = $codigo;
701 7
        return $this;
702
    }
703
704
    /**
705
     * Indicador da forma de pagamento: 0 – pagamento à vista; 1 – pagamento à
706
     * prazo; 2 – outros.
707
     * @param boolean $normalize informa se o indicador deve estar no formato do XML
708
     * @return mixed indicador da Nota
709
     */
710 5
    public function getIndicador($normalize = false)
711
    {
712 5
        if (!$normalize) {
713 2
            return $this->indicador;
714
        }
715 5
        switch ($this->indicador) {
716 5
            case self::INDICADOR_AVISTA:
717 5
                return '0';
718
            case self::INDICADOR_APRAZO:
719
                return '1';
720
            case self::INDICADOR_OUTROS:
721
                return '2';
722
        }
723
        return $this->indicador;
724
    }
725
726
    /**
727
     * Altera o valor do Indicador para o informado no parâmetro
728
     * @param mixed $indicador novo valor para Indicador
729
     * @return Nota A própria instância da classe
730
     */
731 7
    public function setIndicador($indicador)
732
    {
733
        switch ($indicador) {
734 7
            case '0':
735 3
                $indicador = self::INDICADOR_AVISTA;
736 3
                break;
737 7
            case '1':
738
                $indicador = self::INDICADOR_APRAZO;
739
                break;
740 7
            case '2':
741
                $indicador = self::INDICADOR_OUTROS;
742
                break;
743
        }
744 7
        $this->indicador = $indicador;
745 7
        return $this;
746
    }
747
748
    /**
749
     * Data e Hora de emissão do Documento Fiscal
750
     * @param boolean $normalize informa se o data_emissao deve estar no formato do XML
751
     * @return mixed data_emissao da Nota
752
     */
753 5
    public function getDataEmissao($normalize = false)
754
    {
755 5
        if (!$normalize) {
756 5
            return $this->data_emissao;
757
        }
758 5
        return Util::toDateTime($this->data_emissao);
759
    }
760
761
    /**
762
     * Altera o valor do DataEmissao para o informado no parâmetro
763
     * @param mixed $data_emissao novo valor para DataEmissao
764
     * @return Nota A própria instância da classe
765
     */
766 7
    public function setDataEmissao($data_emissao)
767
    {
768 7
        if (!is_numeric($data_emissao)) {
769 7
            $data_emissao = strtotime($data_emissao);
770 7
        }
771 7
        $this->data_emissao = $data_emissao;
772 7
        return $this;
773
    }
774
775
    /**
776
     * Série do Documento Fiscal: série normal 0-889, Avulsa Fisco 890-899,
777
     * SCAN 900-999
778
     * @param boolean $normalize informa se o serie deve estar no formato do XML
779
     * @return mixed serie da Nota
780
     */
781 5
    public function getSerie($normalize = false)
782
    {
783 5
        if (!$normalize) {
784 5
            return $this->serie;
785
        }
786 5
        return $this->serie;
787
    }
788
789
    /**
790
     * Altera o valor do Serie para o informado no parâmetro
791
     * @param mixed $serie novo valor para Serie
792
     * @return Nota A própria instância da classe
793
     */
794 7
    public function setSerie($serie)
795
    {
796 7
        $this->serie = $serie;
797 7
        return $this;
798
    }
799
800
    /**
801
     * Formato de impressão do DANFE (0-sem DANFE;1-DANFe Retrato; 2-DANFe
802
     * Paisagem;3-DANFe Simplificado;4-DANFe NFC-e;5-DANFe NFC-e em mensagem
803
     * eletrônica)
804
     * @param boolean $normalize informa se o formato deve estar no formato do XML
805
     * @return mixed formato da Nota
806
     */
807 5
    public function getFormato($normalize = false)
808
    {
809 5
        if (!$normalize) {
810 2
            return $this->formato;
811
        }
812 5
        switch ($this->formato) {
813 5
            case self::FORMATO_NENHUMA:
814
                return '0';
815 5
            case self::FORMATO_RETRATO:
816
                return '1';
817 5
            case self::FORMATO_PAISAGEM:
818
                return '2';
819 5
            case self::FORMATO_SIMPLIFICADO:
820
                return '3';
821 5
            case self::FORMATO_CONSUMIDOR:
822 5
                return '4';
823
            case self::FORMATO_MENSAGEM:
824
                return '5';
825
        }
826
        return $this->formato;
827
    }
828
829
    /**
830
     * Altera o valor do Formato para o informado no parâmetro
831
     * @param mixed $formato novo valor para Formato
832
     * @return Nota A própria instância da classe
833
     */
834 7
    public function setFormato($formato)
835
    {
836
        switch ($formato) {
837 7
            case '0':
838
                $formato = self::FORMATO_NENHUMA;
839
                break;
840 7
            case '1':
841
                $formato = self::FORMATO_RETRATO;
842
                break;
843 7
            case '2':
844
                $formato = self::FORMATO_PAISAGEM;
845
                break;
846 7
            case '3':
847
                $formato = self::FORMATO_SIMPLIFICADO;
848
                break;
849 7
            case '4':
850 3
                $formato = self::FORMATO_CONSUMIDOR;
851 3
                break;
852 7
            case '5':
853
                $formato = self::FORMATO_MENSAGEM;
854
                break;
855
        }
856 7
        $this->formato = $formato;
857 7
        return $this;
858
    }
859
860
    /**
861
     * Forma de emissão da NF-e
862
     * @param boolean $normalize informa se o emissao deve estar no formato do XML
863
     * @return mixed emissao da Nota
864
     */
865 5
    public function getEmissao($normalize = false)
866
    {
867 5
        if (!$normalize) {
868 5
            return $this->emissao;
869
        }
870 5
        switch ($this->emissao) {
871 5
            case self::EMISSAO_NORMAL:
872 5
                return '1';
873
            case self::EMISSAO_CONTINGENCIA:
874
                return '9';
875
        }
876
        return $this->emissao;
877
    }
878
879
    /**
880
     * Altera o valor do Emissao para o informado no parâmetro
881
     * @param mixed $emissao novo valor para Emissao
882
     * @return Nota A própria instância da classe
883
     */
884 7
    public function setEmissao($emissao)
885
    {
886
        switch ($emissao) {
887 7
            case '1':
888 3
                $emissao = self::EMISSAO_NORMAL;
889 3
                break;
890 7
            case '9':
891
                $emissao = self::EMISSAO_CONTINGENCIA;
892
                break;
893
        }
894 7
        $this->emissao = $emissao;
895 7
        return $this;
896
    }
897
898
    /**
899
     * Digito Verificador da Chave de Acesso da NF-e
900
     * @param boolean $normalize informa se o digito_verificador deve estar no formato do XML
901
     * @return mixed digito_verificador da Nota
902
     */
903 5
    public function getDigitoVerificador($normalize = false)
904
    {
905 5
        if (!$normalize) {
906 2
            return $this->digito_verificador;
907
        }
908 5
        return $this->digito_verificador;
909
    }
910
911
    /**
912
     * Altera o valor do DigitoVerificador para o informado no parâmetro
913
     * @param mixed $digito_verificador novo valor para DigitoVerificador
914
     * @return Nota A própria instância da classe
915
     */
916 7
    public function setDigitoVerificador($digito_verificador)
917
    {
918 7
        $this->digito_verificador = $digito_verificador;
919 7
        return $this;
920
    }
921
922
    /**
923
     * Identificação do Ambiente: 1 - Produção, 2 - Homologação
924
     * @param boolean $normalize informa se o ambiente deve estar no formato do XML
925
     * @return mixed ambiente da Nota
926
     */
927 5
    public function getAmbiente($normalize = false)
928
    {
929 5
        if (!$normalize) {
930 5
            return $this->ambiente;
931
        }
932 5
        switch ($this->ambiente) {
933 5
            case self::AMBIENTE_PRODUCAO:
934
                return '1';
935 5
            case self::AMBIENTE_HOMOLOGACAO:
936 5
                return '2';
937
        }
938
        return $this->ambiente;
939
    }
940
941
    /**
942
     * Altera o valor do Ambiente para o informado no parâmetro
943
     * @param mixed $ambiente novo valor para Ambiente
944
     * @return Nota A própria instância da classe
945
     */
946 7
    public function setAmbiente($ambiente)
947
    {
948
        switch ($ambiente) {
949 7
            case '1':
950
                $ambiente = self::AMBIENTE_PRODUCAO;
951
                break;
952 7
            case '2':
953 3
                $ambiente = self::AMBIENTE_HOMOLOGACAO;
954 3
                break;
955
        }
956 7
        $this->ambiente = $ambiente;
957 7
        return $this;
958
    }
959
960
    /**
961
     * Finalidade da emissão da NF-e: 1 - NFe normal, 2 - NFe complementar, 3 -
962
     * NFe de ajuste, 4 - Devolução/Retorno
963
     * @param boolean $normalize informa se a finalidade deve estar no formato do XML
964
     * @return mixed finalidade da Nota
965
     */
966 5
    public function getFinalidade($normalize = false)
967
    {
968 5
        if (!$normalize) {
969 2
            return $this->finalidade;
970
        }
971 5
        switch ($this->finalidade) {
972 5
            case self::FINALIDADE_NORMAL:
973 5
                return '1';
974
            case self::FINALIDADE_COMPLEMENTAR:
975
                return '2';
976
            case self::FINALIDADE_AJUSTE:
977
                return '3';
978
            case self::FINALIDADE_RETORNO:
979
                return '4';
980
        }
981
        return $this->finalidade;
982
    }
983
984
    /**
985
     * Altera o valor da Finalidade para o informado no parâmetro
986
     * @param mixed $finalidade novo valor para Finalidade
987
     * @return Nota A própria instância da classe
988
     */
989 7
    public function setFinalidade($finalidade)
990
    {
991
        switch ($finalidade) {
992 7
            case '1':
993 3
                $finalidade = self::FINALIDADE_NORMAL;
994 3
                break;
995 7
            case '2':
996
                $finalidade = self::FINALIDADE_COMPLEMENTAR;
997
                break;
998 7
            case '3':
999
                $finalidade = self::FINALIDADE_AJUSTE;
1000
                break;
1001 7
            case '4':
1002
                $finalidade = self::FINALIDADE_RETORNO;
1003
                break;
1004
        }
1005 7
        $this->finalidade = $finalidade;
1006 7
        return $this;
1007
    }
1008
1009
    /**
1010
     * Indica operação com consumidor final (0-Não;1-Consumidor Final)
1011
     * @param boolean $normalize informa se o consumidor_final deve estar no formato do XML
1012
     * @return mixed consumidor_final da Nota
1013
     */
1014 5
    public function getConsumidorFinal($normalize = false)
1015
    {
1016 5
        if (!$normalize) {
1017 2
            return $this->consumidor_final;
1018
        }
1019 5
        switch ($this->consumidor_final) {
1020 5
            case 'N':
1021
                return '0';
1022 5
            case 'Y':
1023 5
                return '1';
1024
        }
1025
        return $this->consumidor_final;
1026
    }
1027
1028
    /**
1029
     * Indica operação com consumidor final (0-Não;1-Consumidor Final)
1030
     * @return boolean informa se o ConsumidorFinal está habilitado
1031
     */
1032
    public function isConsumidorFinal()
1033
    {
1034
        return $this->consumidor_final == 'Y';
1035
    }
1036
1037
    /**
1038
     * Altera o valor do ConsumidorFinal para o informado no parâmetro
1039
     * @param mixed $consumidor_final novo valor para ConsumidorFinal
1040
     * @return Nota A própria instância da classe
1041
     */
1042 7
    public function setConsumidorFinal($consumidor_final)
1043
    {
1044 7
        if (!in_array($consumidor_final, array('N', 'Y'))) {
1045 3
            $consumidor_final = $consumidor_final?'Y':'N';
1046 3
        }
1047 7
        $this->consumidor_final = $consumidor_final;
1048 7
        return $this;
1049
    }
1050
1051
    /**
1052
     * Indicador de presença do comprador no estabelecimento comercial no
1053
     * momento da oepração (0-Não se aplica, ex.: Nota Fiscal complementar ou
1054
     * de ajuste;1-Operação presencial;2-Não presencial, internet;3-Não
1055
     * presencial, teleatendimento;4-NFC-e entrega em domicílio;9-Não
1056
     * presencial, outros)
1057
     * @param boolean $normalize informa se a presenca deve estar no formato do XML
1058
     * @return mixed presenca da Nota
1059
     */
1060 5
    public function getPresenca($normalize = false)
1061
    {
1062 5
        if (!$normalize) {
1063 2
            return $this->presenca;
1064
        }
1065 5
        switch ($this->presenca) {
1066 5
            case self::PRESENCA_NENHUM:
1067
                return '0';
1068 5
            case self::PRESENCA_PRESENCIAL:
1069 5
                return '1';
1070
            case self::PRESENCA_INTERNET:
1071
                return '2';
1072
            case self::PRESENCA_TELEATENDIMENTO:
1073
                return '3';
1074
            case self::PRESENCA_ENTREGA:
1075
                return '4';
1076
            case self::PRESENCA_OUTROS:
1077
                return '9';
1078
        }
1079
        return $this->presenca;
1080
    }
1081
1082
    /**
1083
     * Altera o valor da Presenca para o informado no parâmetro
1084
     * @param mixed $presenca novo valor para Presenca
1085
     * @return Nota A própria instância da classe
1086
     */
1087 7
    public function setPresenca($presenca)
1088
    {
1089
        switch ($presenca) {
1090 7
            case '0':
1091
                $presenca = self::PRESENCA_NENHUM;
1092
                break;
1093 7
            case '1':
1094 3
                $presenca = self::PRESENCA_PRESENCIAL;
1095 3
                break;
1096 7
            case '2':
1097
                $presenca = self::PRESENCA_INTERNET;
1098
                break;
1099 7
            case '3':
1100
                $presenca = self::PRESENCA_TELEATENDIMENTO;
1101
                break;
1102 7
            case '4':
1103
                $presenca = self::PRESENCA_ENTREGA;
1104
                break;
1105 7
            case '9':
1106
                $presenca = self::PRESENCA_OUTROS;
1107
                break;
1108
        }
1109 7
        $this->presenca = $presenca;
1110 7
        return $this;
1111
    }
1112
1113
    /**
1114
     * Valor estimado total de impostos federais, estaduais e municipais
1115
     * @param boolean $normalize informa se o tributos deve estar no formato do XML
1116
     * @return mixed tributos da Nota
1117
     */
1118 2
    public function getTributos($normalize = false)
1119
    {
1120 2
        if (!$normalize) {
1121 2
            return $this->tributos;
1122
        }
1123
        return Util::toCurrency($this->tributos);
1124
    }
1125
    
1126
    /**
1127
     * Altera o valor do Tributos para o informado no parâmetro
1128
     * @param mixed $tributos novo valor para Tributos
1129
     * @return Nota A própria instância da classe
1130
     */
1131 7
    public function setTributos($tributos)
1132
    {
1133 7
        if (trim($tributos) != '') {
1134 5
            $tributos = floatval($tributos);
1135 5
        }
1136 7
        $this->tributos = $tributos;
1137 7
        return $this;
1138
    }
1139
1140
    /**
1141
     * Informações adicionais de interesse do Fisco
1142
     * @param boolean $normalize informa se a adicionais deve estar no formato do XML
1143
     * @return mixed adicionais da Nota
1144
     */
1145 5
    public function getAdicionais($normalize = false)
1146
    {
1147 5
        if (!$normalize) {
1148 5
            return $this->adicionais;
1149
        }
1150
        return $this->adicionais;
1151
    }
1152
    
1153
    /**
1154
     * Altera o valor da Adicionais para o informado no parâmetro
1155
     * @param mixed $adicionais novo valor para Adicionais
1156
     * @return Nota A própria instância da classe
1157
     */
1158 7
    public function setAdicionais($adicionais)
1159
    {
1160 7
        $this->adicionais = $adicionais;
1161 7
        return $this;
1162
    }
1163
1164
    /**
1165
     * Informações complementares de interesse do Contribuinte
1166
     * @param boolean $normalize informa se o complemento deve estar no formato do XML
1167
     * @return mixed complemento da Nota
1168
     */
1169 2
    public function getComplemento($normalize = false)
1170
    {
1171 2
        if (!$normalize) {
1172 2
            return $this->complemento;
1173
        }
1174
        return $this->complemento;
1175
    }
1176
    
1177
    /**
1178
     * Altera o valor do Complemento para o informado no parâmetro
1179
     * @param mixed $complemento novo valor para Complemento
1180
     * @return Nota A própria instância da classe
1181
     */
1182 7
    public function setComplemento($complemento)
1183
    {
1184 7
        $this->complemento = $complemento;
1185 7
        return $this;
1186
    }
1187
1188
    /**
1189
     * Campo de uso livre do contribuinte informar o nome do campo no atributo
1190
     * xCampo e o conteúdo do campo no xTexto
1191
     * @return mixed observacoes da Nota
1192
     */
1193 5
    public function getObservacoes()
1194
    {
1195 5
        return $this->observacoes;
1196
    }
1197
    
1198
    /**
1199
     * Altera o valor da Observacoes para o informado no parâmetro
1200
     * @param mixed $observacoes novo valor para Observacoes
1201
     * @return Nota A própria instância da classe
1202
     */
1203 7
    public function setObservacoes($observacoes)
1204
    {
1205 7
        $this->observacoes = $observacoes;
1206 7
        return $this;
1207
    }
1208
1209
    /**
1210
     * Adiciona um(a) Observacao para a lista de observacao
1211
     * @param Observacao $observacao Instância da Observacao que será adicionada
1212
     * @return Nota A própria instância da classe
1213
     */
1214
    public function addObservacao($campo, $observacao)
1215
    {
1216
        $this->observacoes[] = array('campo' => $campo, 'valor' => $observacao);
1217
        return $this;
1218
    }
1219
1220
    /**
1221
     * Campo de uso exclusivo do Fisco informar o nome do campo no atributo
1222
     * xCampo e o conteúdo do campo no xTexto
1223
     * @return mixed informacoes da Nota
1224
     */
1225 5
    public function getInformacoes()
1226
    {
1227 5
        return $this->informacoes;
1228
    }
1229
    
1230
    /**
1231
     * Altera o valor da Informacoes para o informado no parâmetro
1232
     * @param mixed $informacoes novo valor para Informacoes
1233
     * @return Nota A própria instância da classe
1234
     */
1235 7
    public function setInformacoes($informacoes)
1236
    {
1237 7
        $this->informacoes = $informacoes;
1238 7
        return $this;
1239
    }
1240
1241
    /**
1242
     * Adiciona um(a) Informacao para a lista de informacao
1243
     * @param Informacao $informacao Instância da Informacao que será adicionada
1244
     * @return Nota A própria instância da classe
1245
     */
1246
    public function addInformacao($campo, $informacao)
1247
    {
1248
        $this->informacoes[] = array('campo' => $campo, 'valor' => $informacao);
1249
        return $this;
1250
    }
1251
1252
    /**
1253
     * Protocolo de autorização da nota, informado apenas quando a nota for
1254
     * enviada e autorizada
1255
     */
1256 3
    public function getProtocolo()
1257
    {
1258 3
        return $this->protocolo;
1259
    }
1260
1261 7
    public function setProtocolo($protocolo)
1262
    {
1263 7
        $this->protocolo = $protocolo;
1264 7
        return $this;
1265
    }
1266
1267 2
    public function toArray()
1268
    {
1269 2
        $nota = array();
1270 2
        $nota['id'] = $this->getID();
1271 2
        $nota['numero'] = $this->getNumero();
1272 2
        $nota['emitente'] = $this->getEmitente();
1273 2
        $nota['destinatario'] = $this->getDestinatario();
1274 2
        $nota['produtos'] = $this->getProdutos();
1275 2
        $nota['transporte'] = $this->getTransporte();
1276 2
        $nota['pagamentos'] = $this->getPagamentos();
1277 2
        $nota['data_movimentacao'] = $this->getDataMovimentacao();
1278 2
        $nota['data_contingencia'] = $this->getDataContingencia();
1279 2
        $nota['justificativa'] = $this->getJustificativa();
1280 2
        $nota['modelo'] = $this->getModelo();
1281 2
        $nota['tipo'] = $this->getTipo();
1282 2
        $nota['destino'] = $this->getDestino();
1283 2
        $nota['natureza'] = $this->getNatureza();
1284 2
        $nota['codigo'] = $this->getCodigo();
1285 2
        $nota['indicador'] = $this->getIndicador();
1286 2
        $nota['data_emissao'] = $this->getDataEmissao();
1287 2
        $nota['serie'] = $this->getSerie();
1288 2
        $nota['formato'] = $this->getFormato();
1289 2
        $nota['emissao'] = $this->getEmissao();
1290 2
        $nota['digito_verificador'] = $this->getDigitoVerificador();
1291 2
        $nota['ambiente'] = $this->getAmbiente();
1292 2
        $nota['finalidade'] = $this->getFinalidade();
1293 2
        $nota['consumidor_final'] = $this->getConsumidorFinal();
1294 2
        $nota['presenca'] = $this->getPresenca();
1295 2
        $nota['tributos'] = $this->getTributos();
1296 2
        $nota['adicionais'] = $this->getAdicionais();
1297 2
        $nota['complemento'] = $this->getComplemento();
1298 2
        $nota['observacoes'] = $this->getObservacoes();
1299 2
        $nota['informacoes'] = $this->getInformacoes();
1300 2
        $nota['protocolo'] = $this->getProtocolo();
1301 2
        return $nota;
1302
    }
1303
1304 7
    public function fromArray($nota = array())
0 ignored issues
show
Complexity introduced by
This operation has 1880739938304 execution paths which exceeds the configured maximum of 200.

A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.

You can also find more information in the “Code” section of your repository.

Loading history...
1305
    {
1306 7
        if ($nota instanceof Nota) {
1307
            $nota = $nota->toArray();
1308 7
        } elseif (!is_array($nota)) {
1309
            return $this;
1310
        }
1311 7
        if (isset($nota['id'])) {
1312
            $this->setID($nota['id']);
1313
        } else {
1314 7
            $this->setID(null);
1315
        }
1316 7
        if (isset($nota['numero'])) {
1317 2
            $this->setNumero($nota['numero']);
1318 2
        } else {
1319 7
            $this->setNumero(null);
1320
        }
1321 7
        if (!isset($nota['emitente']) || is_null($nota['emitente'])) {
1322 7
            $this->setEmitente(new Emitente());
1323 7
        } else {
1324 2
            $this->setEmitente($nota['emitente']);
1325
        }
1326 7
        if (!isset($nota['destinatario']) || is_null($nota['destinatario'])) {
1327 7
            $this->setDestinatario(new Destinatario());
1328 7
        } else {
1329 2
            $this->setDestinatario($nota['destinatario']);
1330
        }
1331 7
        if (!isset($nota['produtos']) || is_null($nota['produtos'])) {
1332 7
            $this->setProdutos(array());
1333 7
        } else {
1334 2
            $this->setProdutos($nota['produtos']);
1335
        }
1336 7
        if (!isset($nota['transporte']) || is_null($nota['transporte'])) {
1337 7
            $this->setTransporte(new Transporte());
1338 7
        } else {
1339 2
            $this->setTransporte($nota['transporte']);
1340
        }
1341 7
        if (!isset($nota['pagamentos']) || is_null($nota['pagamentos'])) {
1342 7
            $this->setPagamentos(array());
1343 7
        } else {
1344 2
            $this->setPagamentos($nota['pagamentos']);
1345
        }
1346 7
        if (isset($nota['data_movimentacao'])) {
1347
            $this->setDataMovimentacao($nota['data_movimentacao']);
1348
        } else {
1349 7
            $this->setDataMovimentacao(null);
1350
        }
1351 7
        if (isset($nota['data_contingencia'])) {
1352
            $this->setDataContingencia($nota['data_contingencia']);
1353
        } else {
1354 7
            $this->setDataContingencia(null);
1355
        }
1356 7
        if (isset($nota['justificativa'])) {
1357
            $this->setJustificativa($nota['justificativa']);
1358
        } else {
1359 7
            $this->setJustificativa(null);
1360
        }
1361 7
        if (isset($nota['modelo'])) {
1362 2
            $this->setModelo($nota['modelo']);
1363 2
        } else {
1364 7
            $this->setModelo(null);
1365
        }
1366 7
        if (!isset($nota['tipo']) || is_null($nota['tipo'])) {
1367 7
            $this->setTipo(self::TIPO_SAIDA);
1368 7
        } else {
1369 2
            $this->setTipo($nota['tipo']);
1370
        }
1371 7
        if (!isset($nota['destino']) || is_null($nota['destino'])) {
1372 7
            $this->setDestino(self::DESTINO_INTERNA);
1373 7
        } else {
1374 2
            $this->setDestino($nota['destino']);
1375
        }
1376 7
        if (!isset($nota['natureza']) || is_null($nota['natureza'])) {
1377 7
            $this->setNatureza('VENDA PARA CONSUMIDOR FINAL');
1378 7
        } else {
1379 2
            $this->setNatureza($nota['natureza']);
1380
        }
1381 7
        if (isset($nota['codigo'])) {
1382 2
            $this->setCodigo($nota['codigo']);
1383 2
        } else {
1384 7
            $this->setCodigo(null);
1385
        }
1386 7
        if (!isset($nota['indicador']) || is_null($nota['indicador'])) {
1387 7
            $this->setIndicador(self::INDICADOR_AVISTA);
1388 7
        } else {
1389 2
            $this->setIndicador($nota['indicador']);
1390
        }
1391 7
        if (isset($nota['data_emissao'])) {
1392 2
            $this->setDataEmissao($nota['data_emissao']);
1393 2
        } else {
1394 7
            $this->setDataEmissao(null);
1395
        }
1396 7
        if (isset($nota['serie'])) {
1397 2
            $this->setSerie($nota['serie']);
1398 2
        } else {
1399 7
            $this->setSerie(null);
1400
        }
1401 7
        if (!isset($nota['formato']) || is_null($nota['formato'])) {
1402 7
            $this->setFormato(self::FORMATO_NENHUMA);
1403 7
        } else {
1404 2
            $this->setFormato($nota['formato']);
1405
        }
1406 7
        if (!isset($nota['emissao']) || is_null($nota['emissao'])) {
1407 7
            $this->setEmissao(self::EMISSAO_NORMAL);
1408 7
        } else {
1409 2
            $this->setEmissao($nota['emissao']);
1410
        }
1411 7
        if (isset($nota['digito_verificador'])) {
1412
            $this->setDigitoVerificador($nota['digito_verificador']);
1413
        } else {
1414 7
            $this->setDigitoVerificador(null);
1415
        }
1416 7
        if (!isset($nota['ambiente']) || is_null($nota['ambiente'])) {
1417 7
            $this->setAmbiente(self::AMBIENTE_HOMOLOGACAO);
1418 7
        } else {
1419 2
            $this->setAmbiente($nota['ambiente']);
1420
        }
1421 7
        if (!isset($nota['finalidade']) || is_null($nota['finalidade'])) {
1422 7
            $this->setFinalidade(self::FINALIDADE_NORMAL);
1423 7
        } else {
1424 2
            $this->setFinalidade($nota['finalidade']);
1425
        }
1426 7
        if (!isset($nota['consumidor_final']) || is_null($nota['consumidor_final'])) {
1427 7
            $this->setConsumidorFinal('Y');
1428 7
        } else {
1429 2
            $this->setConsumidorFinal($nota['consumidor_final']);
1430
        }
1431 7
        if (isset($nota['presenca'])) {
1432 2
            $this->setPresenca($nota['presenca']);
1433 2
        } else {
1434 7
            $this->setPresenca(null);
1435
        }
1436 7
        if (!array_key_exists('tributos', $nota)) {
1437 7
            $this->setTributos(null);
1438 7
        } else {
1439 2
            $this->setTributos($nota['tributos']);
1440
        }
1441 7
        if (!array_key_exists('adicionais', $nota)) {
1442 7
            $this->setAdicionais(null);
1443 7
        } else {
1444 2
            $this->setAdicionais($nota['adicionais']);
1445
        }
1446 7
        if (!array_key_exists('complemento', $nota)) {
1447 7
            $this->setComplemento(null);
1448 7
        } else {
1449 2
            $this->setComplemento($nota['complemento']);
1450
        }
1451 7
        if (!array_key_exists('observacoes', $nota)) {
1452 7
            $this->setObservacoes(null);
1453 7
        } else {
1454 2
            $this->setObservacoes($nota['observacoes']);
1455
        }
1456 7
        if (!array_key_exists('informacoes', $nota)) {
1457 7
            $this->setInformacoes(null);
1458 7
        } else {
1459 2
            $this->setInformacoes($nota['informacoes']);
1460
        }
1461 7
        if (isset($nota['protocolo'])) {
1462
            $this->setProtocolo($nota['protocolo']);
1463
        } else {
1464 7
            $this->setProtocolo(null);
1465
        }
1466 7
        return $this;
1467
    }
1468
1469 5
    public function gerarID()
1470
    {
1471 5
        $estado = $this->getEmitente()->getEndereco()->getMunicipio()->getEstado();
1472 5
        $estado->checkCodigos();
1473 5
        $id = sprintf(
1474 5
            '%02d%02d%02d%s%02d%03d%09d%01d%08d',
1475 5
            $estado->getCodigo(),
1476 5
            date('y', $this->getDataEmissao()), // Ano 2 dígitos
1477 5
            date('m', $this->getDataEmissao()), // Mês 2 dígitos
1478 5
            $this->getEmitente()->getCNPJ(),
1479 5
            $this->getModelo(true),
1480 5
            $this->getSerie(),
1481 5
            $this->getNumero(),
1482 5
            $this->getEmissao(true),
1483 5
            $this->getCodigo()
1484 5
        );
1485 5
        return $id.Util::getDAC($id, 11);
1486
    }
1487
1488 5
    protected function getTotais()
1489
    {
1490 5
        $total = array();
1491 5
        $total['produtos'] = 0.00;
1492 5
        $total['descontos'] = 0.00;
1493 5
        $total['frete'] = 0.00;
1494 5
        $total['seguro'] = 0.00;
1495 5
        $total['outros'] = 0.00;
1496 5
        $total['tributos'] = 0.00;
1497 5
        $total['icms'] = 0.00;
1498 5
        $total['icms.st'] = 0.00;
1499 5
        $total['base'] = 0.00;
1500 5
        $total['base.st'] = 0.00;
1501 5
        $total['ii'] = 0.00;
1502 5
        $total['ipi'] = 0.00;
1503 5
        $total['pis'] = 0.00;
1504 5
        $total['cofins'] = 0.00;
1505 5
        $total['desoneracao'] = 0.00;
1506 5
        $_produtos = $this->getProdutos();
1507 5
        foreach ($_produtos as $_produto) {
1508 5
            if (!$_produto->getMultiplicador()) {
1509
                continue;
1510
            }
1511 5
            $imposto_info = $_produto->getImpostoInfo();
1512 5
            $total['produtos'] += round($_produto->getPreco(), 2);
1513 5
            $total['descontos'] += round($_produto->getDesconto(), 2);
1514 5
            $total['frete'] += round($_produto->getFrete(), 2);
1515 5
            $total['seguro'] += round($_produto->getSeguro(), 2);
1516 5
            $total['outros'] += round($_produto->getDespesas(), 2);
1517 5
            $total['tributos'] += round($imposto_info['total'], 2);
1518 5
            $_impostos = $_produto->getImpostos();
1519 5
            foreach ($_impostos as $_imposto) {
1520 5
                switch ($_imposto->getGrupo()) {
1521 5
                    case Imposto::GRUPO_ICMS:
1522 5
                        if (($_imposto instanceof \NFe\Entity\Imposto\ICMS\Cobranca) ||
1523 5
                                ($_imposto instanceof \NFe\Entity\Imposto\ICMS\Simples\Cobranca)) {
1524 5
                            $total[$_imposto->getGrupo()] += round($_imposto->getNormal()->getValor(), 2);
1525 5
                            $total['base'] += round($_imposto->getNormal()->getBase(), 2);
1526 5
                        }
1527 5
                        if (($_imposto instanceof \NFe\Entity\Imposto\ICMS\Parcial) ||
1528 5
                                ($_imposto instanceof \NFe\Entity\Imposto\ICMS\Simples\Parcial)) {
1529 5
                            $total['icms.st'] += round($_imposto->getValor(), 2);
1530 5
                            $total['base.st'] += round($_imposto->getBase(), 2);
1531 5
                        } else {
1532
                            $total[$_imposto->getGrupo()] += round($_imposto->getValor(), 2);
1533
                            $total['base'] += round($_imposto->getBase(), 2);
1534
                        }
1535 5
                        break;
1536 5
                    default:
1537 5
                        $total[$_imposto->getGrupo()] += round($_imposto->getValor(), 2);
1538 5
                }
1539 5
            }
1540 5
        }
1541 5
        $produtos = round($total['produtos'], 2) - round($total['descontos'], 2);
1542 5
        $servicos = round($total['frete'], 2) + round($total['seguro'], 2) + round($total['outros'], 2);
1543 5
        $impostos = round($total['ii'], 2) + round($total['ipi'], 2) + round($total['icms.st'], 2) - round($total['desoneracao'], 2);
1544 5
        $total['nota'] = $produtos + $servicos + $impostos;
1545 5
        return $total;
1546
    }
1547
1548 5
    private function getNodeTotal($name = null)
1549
    {
1550 5
        $dom = new \DOMDocument('1.0', 'UTF-8');
1551 5
        $element = $dom->createElement(is_null($name)?'total':$name);
1552
1553
        // Totais referentes ao ICMS
1554 5
        $total = $this->getTotais();
1555 5
        $icms = $dom->createElement('ICMSTot');
1556 5
        Util::appendNode($icms, 'vBC', Util::toCurrency($total['base']));
1557 5
        Util::appendNode($icms, 'vICMS', Util::toCurrency($total['icms']));
1558 5
        Util::appendNode($icms, 'vICMSDeson', Util::toCurrency($total['desoneracao']));
1559 5
        Util::appendNode($icms, 'vBCST', Util::toCurrency($total['base.st']));
1560 5
        Util::appendNode($icms, 'vST', Util::toCurrency($total['icms.st']));
1561 5
        Util::appendNode($icms, 'vProd', Util::toCurrency($total['produtos']));
1562 5
        Util::appendNode($icms, 'vFrete', Util::toCurrency($total['frete']));
1563 5
        Util::appendNode($icms, 'vSeg', Util::toCurrency($total['seguro']));
1564 5
        Util::appendNode($icms, 'vDesc', Util::toCurrency($total['descontos']));
1565 5
        Util::appendNode($icms, 'vII', Util::toCurrency($total['ii']));
1566 5
        Util::appendNode($icms, 'vIPI', Util::toCurrency($total['ipi']));
1567 5
        Util::appendNode($icms, 'vPIS', Util::toCurrency($total['pis']));
1568 5
        Util::appendNode($icms, 'vCOFINS', Util::toCurrency($total['cofins']));
1569 5
        Util::appendNode($icms, 'vOutro', Util::toCurrency($total['outros']));
1570 5
        Util::appendNode($icms, 'vNF', Util::toCurrency($total['nota']));
1571 5
        Util::appendNode($icms, 'vTotTrib', Util::toCurrency($total['tributos']));
1572 5
        $element->appendChild($icms);
1573 5
        $this->setTributos($total['tributos']);
1574
1575
        // TODO: Totais referentes ao ISSQN
1576
1577
        // TODO: Retenção de Tributos Federais
1578 5
        return $element;
1579
    }
1580
1581 5
    public function getNode($name = null)
0 ignored issues
show
Complexity introduced by
This operation has 90720 execution paths which exceeds the configured maximum of 200.

A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.

You can also find more information in the “Code” section of your repository.

Loading history...
1582
    {
1583 5
        $this->getEmitente()->getEndereco()->checkCodigos();
1584 5
        $this->setID($this->gerarID());
1585 5
        $this->setDigitoVerificador(substr($this->getID(), -1, 1));
1586
1587 5
        $dom = new \DOMDocument('1.0', 'UTF-8');
1588 5
        $element = $dom->createElement(is_null($name)?'NFe':$name);
1589 5
        $element->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', self::PORTAL);
1590
1591 5
        $info = $dom->createElement('infNFe');
1592 5
        $id = $dom->createAttribute('Id');
1593 5
        $id->value = $this->getID(true);
1594 5
        $info->appendChild($id);
1595 5
        $versao = $dom->createAttribute('versao');
1596 5
        $versao->value = self::VERSAO;
1597 5
        $info->appendChild($versao);
1598
1599 5
        $municipio = $this->getEmitente()->getEndereco()->getMunicipio();
1600 5
        $estado = $municipio->getEstado();
1601 5
        $ident = $dom->createElement('ide');
1602 5
        Util::appendNode($ident, 'cUF', $estado->getCodigo(true));
1603 5
        Util::appendNode($ident, 'cNF', $this->getCodigo(true));
1604 5
        Util::appendNode($ident, 'natOp', $this->getNatureza(true));
1605 5
        Util::appendNode($ident, 'indPag', $this->getIndicador(true));
1606 5
        Util::appendNode($ident, 'mod', $this->getModelo(true));
1607 5
        Util::appendNode($ident, 'serie', $this->getSerie(true));
1608 5
        Util::appendNode($ident, 'nNF', $this->getNumero(true));
1609 5
        Util::appendNode($ident, 'dhEmi', $this->getDataEmissao(true));
1610 5
        Util::appendNode($ident, 'tpNF', $this->getTipo(true));
1611 5
        Util::appendNode($ident, 'idDest', $this->getDestino(true));
1612 5
        Util::appendNode($ident, 'cMunFG', $municipio->getCodigo(true));
1613 5
        Util::appendNode($ident, 'tpImp', $this->getFormato(true));
1614 5
        Util::appendNode($ident, 'tpEmis', $this->getEmissao(true));
1615 5
        Util::appendNode($ident, 'cDV', $this->getDigitoVerificador(true));
1616 5
        Util::appendNode($ident, 'tpAmb', $this->getAmbiente(true));
1617 5
        Util::appendNode($ident, 'finNFe', $this->getFinalidade(true));
1618 5
        Util::appendNode($ident, 'indFinal', $this->getConsumidorFinal(true));
1619 5
        Util::appendNode($ident, 'indPres', $this->getPresenca(true));
1620 5
        Util::appendNode($ident, 'procEmi', 0); // emissão de NF-e com aplicativo do contribuinte
1621 5
        Util::appendNode($ident, 'verProc', self::APP_VERSAO);
1622 5
        if (!is_null($this->getDataMovimentacao())) {
1623
            Util::appendNode($ident, 'dhSaiEnt', $this->getDataMovimentacao(true));
1624
        }
1625 5
        if ($this->getEmissao() != self::EMISSAO_NORMAL) {
1626
            Util::appendNode($ident, 'dhCont', $this->getDataContingencia(true));
1627
            Util::appendNode($ident, 'xJust', $this->getJustificativa(true));
1628
        }
1629 5
        $info->appendChild($ident);
1630
1631 5
        $emitente = $this->getEmitente()->getNode();
1632 5
        $emitente = $dom->importNode($emitente, true);
1633 5
        $info->appendChild($emitente);
1634 5
        if ($this->getAmbiente() == self::AMBIENTE_HOMOLOGACAO && !is_null($this->getDestinatario())) {
1635 5
            $this->getDestinatario()->setNome('NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL');
1636 5
        }
1637 5
        if (!is_null($this->getDestinatario())) {
1638 5
            $destinatario = $this->getDestinatario()->getNode();
1639 5
            $destinatario = $dom->importNode($destinatario, true);
1640 5
            $info->appendChild($destinatario);
1641 5
        }
1642 5
        $item = 0;
1643 5
        $tributos = array();
1644 5
        $_produtos = $this->getProdutos();
1645 5
        foreach ($_produtos as $_produto) {
1646 5
            if (is_null($_produto->getItem())) {
1647 2
                $item += 1;
1648 2
                $_produto->setItem($item);
1649 2
            } else {
1650 3
                $item = $_produto->getItem();
1651
            }
1652 5
            if ($this->getAmbiente() == self::AMBIENTE_HOMOLOGACAO) {
1653 5
                $_produto->setDescricao('NOTA FISCAL EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL');
1654 5
            }
1655 5
            $produto = $_produto->getNode();
1656 5
            $produto = $dom->importNode($produto, true);
1657 5
            $info->appendChild($produto);
1658
            // Soma os tributos aproximados dos produtos
1659 5
            $imposto_info = $_produto->getImpostoInfo();
1660 5
            $tributos['info'] = $imposto_info['info'];
1661 5
            foreach ($imposto_info as $key => $value) {
1662 5
                if (!is_numeric($value)) {
1663 5
                    continue;
1664
                }
1665 5
                if (!isset($tributos[$key])) {
1666 5
                    $tributos[$key] = 0.00;
1667 5
                }
1668 5
                $tributos[$key] += $value;
1669 5
            }
1670 5
        }
1671 5
        $total = $this->getNodeTotal();
1672 5
        $total = $dom->importNode($total, true);
1673 5
        $info->appendChild($total);
1674 5
        $transporte = $this->getTransporte()->getNode();
1675 5
        $transporte = $dom->importNode($transporte, true);
1676 5
        $info->appendChild($transporte);
1677
        // TODO: adicionar cobrança
1678 5
        $_pagamentos = $this->getPagamentos();
1679 5
        foreach ($_pagamentos as $_pagamento) {
1680 5
            $pagamento = $_pagamento->getNode();
1681 5
            $pagamento = $dom->importNode($pagamento, true);
1682 5
            $info->appendChild($pagamento);
1683 5
        }
1684 5
        $info_adic = $dom->createElement('infAdic');
1685 5
        if (!is_null($this->getAdicionais())) {
1686
            Util::appendNode($info_adic, 'infAdFisco', $this->getAdicionais(true));
1687
        }
1688
        // TODO: adicionar informações adicionais somente na NFC-e?
1689 5
        $_complemento = Produto::addNodeInformacoes($tributos, $info_adic, 'infCpl');
1690 5
        $this->setComplemento($_complemento);
1691 5
        if (!is_null($this->getObservacoes())) {
1692 3
            $_observacoes = $this->getObservacoes();
1693 3
            foreach ($_observacoes as $_observacao) {
0 ignored issues
show
Bug introduced by
The expression $_observacoes of type object|integer|double|string|array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1694
                $observacoes = Util::appendNode($info_adic, 'obsCont', $_observacao['valor']);
1695
                $campo = $dom->createAttribute('xCampo');
1696
                $campo->value = $_observacao['campo'];
1697
                $observacoes->appendChild($campo);
1698
                $info_adic->appendChild($observacoes);
1699 3
            }
1700 3
        }
1701 5
        if (!is_null($this->getInformacoes())) {
1702 3
            $_informacoes = $this->getInformacoes();
1703 3
            foreach ($_informacoes as $_informacao) {
0 ignored issues
show
Bug introduced by
The expression $_informacoes of type object|integer|double|string|array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
1704
                $informacoes = Util::appendNode($info_adic, 'obsFisco', $_informacao['valor']);
1705
                $campo = $dom->createAttribute('xCampo');
1706
                $campo->value = $_informacao['campo'];
1707
                $informacoes->appendChild($campo);
1708
                $info_adic->appendChild($informacoes);
1709 3
            }
1710 3
        }
1711 5
        $info->appendChild($info_adic);
1712
        // TODO: adicionar exportação
1713
        // TODO: adicionar compra
1714
        // TODO: adicionar cana
1715 5
        $element->appendChild($info);
1716 5
        $dom->appendChild($element);
1717 5
        return $element;
1718
    }
1719
1720 3
    public function loadNode($element, $name = null)
0 ignored issues
show
Complexity introduced by
This operation has 245760 execution paths which exceeds the configured maximum of 200.

A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.

You can also find more information in the “Code” section of your repository.

Loading history...
1721
    {
1722 3
        $root = $element;
1723 3
        $name = is_null($name)?'NFe':$name;
1724 3
        if ($element->tagName != $name) {
1725
            $_fields = $element->getElementsByTagName($name);
1726
            if ($_fields->length == 0) {
1727
                throw new \Exception('Tag "'.$name.'" não encontrada', 404);
1728
            }
1729
            $element = $_fields->item(0);
1730
        }
1731 3
        $_fields = $element->getElementsByTagName('infNFe');
1732 3
        if ($_fields->length > 0) {
1733 3
            $info = $_fields->item(0);
1734 3
        } else {
1735
            throw new \Exception('Tag "infNFe" não encontrada', 404);
1736
        }
1737 3
        $id = $info->getAttribute('Id');
1738 3
        if (strlen($id) != 47) {
1739
            throw new \Exception('Atributo "Id" inválido, encontrado: "'.$id.'"', 500);
1740
        }
1741 3
        $this->setID(substr($id, 3));
1742 3
        $_fields = $info->getElementsByTagName('ide');
1743 3
        if ($_fields->length > 0) {
1744 3
            $ident = $_fields->item(0);
1745 3
        } else {
1746
            throw new \Exception('Tag "ide" não encontrada', 404);
1747
        }
1748 3
        $emitente = new Emitente();
1749 3
        $_fields = $ident->getElementsByTagName('cUF');
1750 3
        if ($_fields->length > 0) {
1751 3
            $codigo = $_fields->item(0)->nodeValue;
1752 3
        } else {
1753
            throw new \Exception('Tag "cUF" do campo "Codigo IBGE da UF" não encontrada', 404);
1754
        }
1755 3
        $emitente->getEndereco()->getMunicipio()->getEstado()->setCodigo($codigo);
1756 3
        $this->setCodigo(
1757 3
            Util::loadNode(
1758 3
                $ident,
1759 3
                'cNF',
1760
                'Tag "cNF" do campo "Codigo" não encontrada'
1761 3
            )
1762 3
        );
1763 3
        $this->setNatureza(
1764 3
            Util::loadNode(
1765 3
                $ident,
1766 3
                'natOp',
1767
                'Tag "natOp" do campo "Natureza" não encontrada'
1768 3
            )
1769 3
        );
1770 3
        $this->setIndicador(
1771 3
            Util::loadNode(
1772 3
                $ident,
1773 3
                'indPag',
1774
                'Tag "indPag" do campo "Indicador" não encontrada'
1775 3
            )
1776 3
        );
1777 3
        $this->setModelo(
1778 3
            Util::loadNode(
1779 3
                $ident,
1780 3
                'mod',
1781
                'Tag "mod" do campo "Modelo" não encontrada'
1782 3
            )
1783 3
        );
1784 3
        $this->setSerie(
1785 3
            Util::loadNode(
1786 3
                $ident,
1787 3
                'serie',
1788
                'Tag "serie" do campo "Serie" não encontrada'
1789 3
            )
1790 3
        );
1791 3
        $this->setNumero(
1792 3
            Util::loadNode(
1793 3
                $ident,
1794 3
                'nNF',
1795
                'Tag "nNF" do campo "Numero" não encontrada'
1796 3
            )
1797 3
        );
1798 3
        $this->setDataEmissao(
1799 3
            Util::loadNode(
1800 3
                $ident,
1801 3
                'dhEmi',
1802
                'Tag "dhEmi" do campo "DataEmissao" não encontrada'
1803 3
            )
1804 3
        );
1805 3
        $this->setTipo(
1806 3
            Util::loadNode(
1807 3
                $ident,
1808 3
                'tpNF',
1809
                'Tag "tpNF" do campo "Tipo" não encontrada'
1810 3
            )
1811 3
        );
1812 3
        $this->setDestino(
1813 3
            Util::loadNode(
1814 3
                $ident,
1815 3
                'idDest',
1816
                'Tag "idDest" do campo "Destino" não encontrada'
1817 3
            )
1818 3
        );
1819 3
        $_fields = $ident->getElementsByTagName('cMunFG');
1820 3
        if ($_fields->length > 0) {
1821 3
            $codigo = $_fields->item(0)->nodeValue;
1822 3
        } else {
1823
            throw new \Exception('Tag "cMunFG" do campo "Codigo IBGE do município" não encontrada', 404);
1824
        }
1825 3
        $emitente->getEndereco()->getMunicipio()->setCodigo($codigo);
1826 3
        $this->setDataMovimentacao(Util::loadNode($ident, 'dhSaiEnt'));
1827 3
        $this->setFormato(
1828 3
            Util::loadNode(
1829 3
                $ident,
1830 3
                'tpImp',
1831
                'Tag "tpImp" do campo "Formato" não encontrada'
1832 3
            )
1833 3
        );
1834 3
        $this->setEmissao(
1835 3
            Util::loadNode(
1836 3
                $ident,
1837 3
                'tpEmis',
1838
                'Tag "tpEmis" do campo "Emissao" não encontrada'
1839 3
            )
1840 3
        );
1841 3
        $this->setDigitoVerificador(
1842 3
            Util::loadNode(
1843 3
                $ident,
1844 3
                'cDV',
1845
                'Tag "cDV" do campo "DigitoVerificador" não encontrada'
1846 3
            )
1847 3
        );
1848 3
        $this->setAmbiente(
1849 3
            Util::loadNode(
1850 3
                $ident,
1851 3
                'tpAmb',
1852
                'Tag "tpAmb" do campo "Ambiente" não encontrada'
1853 3
            )
1854 3
        );
1855 3
        $this->setFinalidade(
1856 3
            Util::loadNode(
1857 3
                $ident,
1858 3
                'finNFe',
1859
                'Tag "finNFe" do campo "Finalidade" não encontrada'
1860 3
            )
1861 3
        );
1862 3
        $this->setConsumidorFinal(
1863 3
            Util::loadNode(
1864 3
                $ident,
1865 3
                'indFinal',
1866
                'Tag "indFinal" do campo "ConsumidorFinal" não encontrada'
1867 3
            )
1868 3
        );
1869 3
        $this->setPresenca(
1870 3
            Util::loadNode(
1871 3
                $ident,
1872 3
                'indPres',
1873
                'Tag "indPres" do campo "Presenca" não encontrada'
1874 3
            )
1875 3
        );
1876 3
        $this->setDataContingencia(Util::loadNode($ident, 'dhCont'));
1877 3
        $this->setJustificativa(Util::loadNode($ident, 'xJust'));
1878
1879 3
        $_fields = $info->getElementsByTagName('emit');
1880 3
        if ($_fields->length > 0) {
1881 3
            $emitente->loadNode($_fields->item(0), 'emit');
1882 3
        } else {
1883
            throw new \Exception('Tag "emit" do objeto "Emitente" não encontrada', 404);
1884
        }
1885 3
        $this->setEmitente($emitente);
1886 3
        $_fields = $info->getElementsByTagName('dest');
1887 3
        $destinatario = null;
1888 3
        if ($_fields->length > 0) {
1889 3
            $destinatario = new Destinatario();
1890 3
            $destinatario->loadNode($_fields->item(0), 'dest');
1891 3
        }
1892 3
        $this->setDestinatario($destinatario);
1893 3
        $produtos = array();
1894 3
        $_items = $info->getElementsByTagName('det');
1895 3
        foreach ($_items as $_item) {
1896 3
            $produto = new Produto();
1897 3
            $produto->loadNode($_item, 'det');
1898 3
            $produtos[] = $produto;
1899 3
        }
1900 3
        $this->setProdutos($produtos);
1901 3
        $_fields = $info->getElementsByTagName('transp');
1902 3
        $transporte = null;
1903 3
        if ($_fields->length > 0) {
1904 3
            $transporte = new Transporte();
1905 3
            $transporte->loadNode($_fields->item(0), 'transp');
1906 3
        }
1907 3
        $this->setTransporte($transporte);
1908 3
        $pagamentos = array();
1909 3
        $_items = $info->getElementsByTagName('pag');
1910 3
        foreach ($_items as $_item) {
1911 3
            $pagamento = new Pagamento();
1912 3
            $pagamento->loadNode($_item, 'pag');
1913 3
            $pagamentos[] = $pagamento;
1914 3
        }
1915 3
        $this->setPagamentos($pagamentos);
1916 3
        $tributos = null;
1917 3
        $_fields = $info->getElementsByTagName('total');
1918 3
        if ($_fields->length > 0) {
1919 3
            $total = $_fields->item(0);
1920 3
            $tributos = Util::loadNode($total, 'vTotTrib');
1921 3
        }
1922 3
        $this->setTributos($tributos);
1923 3
        $this->setAdicionais(Util::loadNode($info, 'infAdFisco'));
1924 3
        $this->setComplemento(Util::loadNode($info, 'infCpl'));
1925 3
        $observacoes = array();
1926 3
        $_items = $info->getElementsByTagName('obsCont'); // TODO: predictable tag name
1927 3
        foreach ($_items as $_item) {
1928
            $observacao = array(
1929
                'campo' => $_item->getAttribute('xCampo'),
1930
                'valor' => $_item->nodeValue
1931
            );
1932
            $observacoes[] = $observacao;
1933 3
        }
1934 3
        $this->setObservacoes($observacoes);
1935 3
        $informacoes = array();
1936 3
        $_items = $info->getElementsByTagName('obsFisco'); // TODO: predictable tag name
1937 3
        foreach ($_items as $_item) {
1938
            $informacao = array(
1939
                'campo' => $_item->getAttribute('xCampo'),
1940
                'valor' => $_item->nodeValue
1941
            );
1942
            $informacoes[] = $informacao;
1943 3
        }
1944 3
        $this->setInformacoes($informacoes);
1945
1946 3
        $_fields = $root->getElementsByTagName('protNFe');
1947 3
        $protocolo = null;
1948 3
        if ($_fields->length > 0) {
1949
            $protocolo = new Protocolo();
1950
            $protocolo->loadNode($_fields->item(0), 'infProt');
1951
        }
1952 3
        $this->setProtocolo($protocolo);
1953 3
        return $element;
1954
    }
1955
1956
    /**
1957
     * Carrega um arquivo XML e preenche a nota com as informações dele
1958
     * @param  string $filename caminho do arquivo
1959
     * @return DOMDocument      objeto do documento carregado
1960
     */
1961 1
    public function load($filename)
1962
    {
1963 1
        $dom = new \DOMDocument();
1964 1
        if (!file_exists($filename)) {
1965
            throw new \Exception('Arquivo XML "'.$filename.'" não encontrado', 404);
1966
        }
1967 1
        $dom->load($filename);
1968 1
        $this->loadNode($dom->documentElement);
1969 1
        return $dom;
1970
    }
1971
1972
    /**
1973
     * Assina o XML com a assinatura eletrônica do tipo A1
1974
     */
1975 3
    public function assinar($dom = null)
1976
    {
1977 3
        if (is_null($dom)) {
1978 1
            $xml = $this->getNode();
1979 1
            $dom = $xml->ownerDocument;
1980 1
        }
1981 3
        $config = SEFAZ::getInstance()->getConfiguracao();
1982
1983 3
        $adapter = new XmlseclibsAdapter();
1984 3
        $adapter->setPrivateKey($config->getChavePrivada());
1985 3
        $adapter->setPublicKey($config->getChavePublica());
1986 3
        $adapter->addTransform(AdapterInterface::ENVELOPED);
1987 3
        $adapter->addTransform(AdapterInterface::XML_C14N);
1988 3
        $adapter->sign($dom, 'infNFe');
1989 3
        return $dom;
1990
    }
1991
1992
    /**
1993
     * Valida o documento após assinar
1994
     */
1995 1
    public function validar($dom)
1996
    {
1997 1
        $dom->loadXML($dom->saveXML());
1998 1
        $xsd_path = __DIR__ . '/schema';
1999 1
        if (is_null($this->getProtocolo())) {
2000 1
            $xsd_file = $xsd_path . '/nfe_v3.10.xsd';
2001 1
        } else {
2002
            $xsd_file = $xsd_path . '/procNFe_v3.10.xsd';
2003
        }
2004 1
        if (!file_exists($xsd_file)) {
2005
            throw new \Exception('O arquivo "'.$xsd_file.'" de esquema XSD não existe!', 404);
2006
        }
2007
        // Enable user error handling
2008 1
        $save = libxml_use_internal_errors(true);
2009 1
        if ($dom->schemaValidate($xsd_file)) {
2010 1
            libxml_use_internal_errors($save);
2011 1
            return $dom;
2012
        }
2013
        $msg = array();
2014
        $errors = libxml_get_errors();
2015
        foreach ($errors as $error) {
2016
            $msg[] = 'Não foi possível validar o XML: '.$error->message;
2017
        }
2018
        libxml_clear_errors();
2019
        libxml_use_internal_errors($save);
2020
        throw new ValidationException($msg);
2021
    }
2022
2023
    /**
2024
     * Adiciona o protocolo no XML da nota
2025
     */
2026
    public function addProtocolo($dom)
2027
    {
2028
        if (is_null($this->getProtocolo())) {
2029
            throw new \Exception('O protocolo não foi informado na nota "'.$this->getID().'"', 404);
2030
        }
2031
        $notae = $dom->getElementsByTagName('NFe')->item(0);
2032
        // Corrige xmlns:default
2033
        $notae_xml = $dom->saveXML($notae);
2034
2035
        $element = $dom->createElement('nfeProc');
2036
        $element->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', self::PORTAL);
2037
        $versao = $dom->createAttribute('versao');
2038
        $versao->value = self::VERSAO;
2039
        $element->appendChild($versao);
2040
        $dom->removeChild($notae);
2041
        // Corrige xmlns:default
2042
        $notae = $dom->createElement('NFe', 0);
2043
2044
        $element->appendChild($notae);
2045
        $info = $this->getProtocolo()->getNode();
2046
        $info = $dom->importNode($info, true);
2047
        $element->appendChild($info);
2048
        $dom->appendChild($element);
2049
        // Corrige xmlns:default
2050
        $xml = $dom->saveXML();
2051
        $xml = str_replace('<NFe>0</NFe>', $notae_xml, $xml);
2052
        $dom->loadXML($xml);
2053
2054
        return $dom;
2055
    }
2056
}
2057