Test Failed
Push — master ( e53a66...43458c )
by Francimar
16:26
created

Nota::getIndicador()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 7.3471

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 6
cts 11
cp 0.5455
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 11
nc 5
nop 1
crap 7.3471
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\Total;
34
use NFe\Entity\Imposto;
35
use NFe\Entity\Produto;
36
use NFe\Entity\Emitente;
37
use NFe\Entity\Pagamento;
38
use NFe\Entity\Transporte;
39
use NFe\Entity\Destinatario;
40
use NFe\Exception\ValidationException;
41
use FR3D\XmlDSig\Adapter\AdapterInterface;
42
use FR3D\XmlDSig\Adapter\XmlseclibsAdapter;
43
44
/**
45
 * Classe base para a formação da nota fiscal
46
 */
47
abstract class Nota implements Node
0 ignored issues
show
Complexity introduced by
This class has 1972 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 73 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 29 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 262 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...
Complexity introduced by
The class Nota has a coupling between objects value of 23. Consider to reduce the number of dependencies under 13.
Loading history...
48
{
49
50
    /**
51
     * Versão da nota fiscal
52
     */
53
    const VERSAO = '4.00';
54
55
    /**
56
     * Versão do aplicativo gerador da nota
57
     */
58
    const APP_VERSAO = '1.0';
59
60
    /**
61
     * Portal da nota fiscal
62
     */
63
    const PORTAL = 'http://www.portalfiscal.inf.br/nfe';
64
65
    /**
66
     * Código do modelo do Documento Fiscal. 55 = NF-e; 65 = NFC-e.
67
     */
68
    const MODELO_NFE = 'nfe';
69
    const MODELO_NFCE = 'nfce';
70
71
    /**
72
     * Tipo do Documento Fiscal (0 - entrada; 1 - saída)
73
     */
74
    const TIPO_ENTRADA = 'entrada';
75
    const TIPO_SAIDA = 'saida';
76
77
    /**
78
     * Identificador de Local de destino da operação
79
     * (1-Interna;2-Interestadual;3-Exterior)
80
     */
81
    const DESTINO_INTERNA = 'interna';
82
    const DESTINO_INTERESTADUAL = 'interestadual';
83
    const DESTINO_EXTERIOR = 'exterior';
84
85
    /**
86
     * Formato de impressão do DANFE (0-sem DANFE;1-DANFe Retrato; 2-DANFe
87
     * Paisagem;3-DANFe Simplificado;4-DANFe NFC-e;5-DANFe NFC-e em mensagem
88
     * eletrônica)
89
     */
90
    const FORMATO_NENHUMA = 'nenhuma';
91
    const FORMATO_RETRATO = 'retrato';
92
    const FORMATO_PAISAGEM = 'paisagem';
93
    const FORMATO_SIMPLIFICADO = 'simplificado';
94
    const FORMATO_CONSUMIDOR = 'consumidor';
95
    const FORMATO_MENSAGEM = 'mensagem';
96
97
    /**
98
     * Forma de emissão da NF-e
99
     */
100
    const EMISSAO_NORMAL = 'normal';
101
    const EMISSAO_CONTINGENCIA = 'contingencia';
102
103
    /**
104
     * Identificação do Ambiente: 1 - Produção, 2 - Homologação
105
     */
106
    const AMBIENTE_PRODUCAO = 'producao';
107
    const AMBIENTE_HOMOLOGACAO = 'homologacao';
108
109
    /**
110
     * Finalidade da emissão da NF-e: 1 - NFe normal, 2 - NFe complementar, 3 -
111
     * NFe de ajuste, 4 - Devolução/Retorno
112
     */
113
    const FINALIDADE_NORMAL = 'normal';
114
    const FINALIDADE_COMPLEMENTAR = 'complementar';
115
    const FINALIDADE_AJUSTE = 'ajuste';
116
    const FINALIDADE_RETORNO = 'retorno';
117
118
    /**
119
     * Indicador de presença do comprador no estabelecimento comercial no
120
     * momento da operação (0-Não se aplica ex.: Nota Fiscal complementar ou de
121
     * ajuste;1-Operação presencial;2-Não presencial, internet;3-Não
122
     * presencial, teleatendimento;4-NFC-e entrega em domicílio;5-Operação
123
     * presencial, fora do estabelecimento;9-Não presencial, outros)
124
     */
125
    const PRESENCA_NENHUM = 'nenhum';
126
    const PRESENCA_PRESENCIAL = 'presencial';
127
    const PRESENCA_INTERNET = 'internet';
128
    const PRESENCA_TELEATENDIMENTO = 'teleatendimento';
129
    const PRESENCA_ENTREGA = 'entrega';
130
    const PRESENCA_AMBULANTE = 'ambulante';
131
    const PRESENCA_OUTROS = 'outros';
132
133
    /**
134
     * Chave da nota fiscal
135
     */
136
    private $id;
137
    /**
138
     * Número do Documento Fiscal
139
     */
140
    private $numero;
141
    /**
142
     * Emitente da nota fiscal
143
     */
144
    private $emitente;
145
    /**
146
     * Destinatário que receberá os produtos
147
     */
148
    private $destinatario;
149
    /**
150
     * Produtos adicionados na nota
151
     */
152
    private $produtos;
153
    /**
154
     * Informações de trasnporte da mercadoria
155
     */
156
    private $transporte;
157
    /**
158
     * Pagamentos realizados
159
     */
160
    private $pagamentos;
161
    /**
162
     * Data e Hora da saída ou de entrada da mercadoria / produto
163
     */
164
    private $data_movimentacao;
165
    /**
166
     * Informar a data e hora de entrada em contingência
167
     */
168
    private $data_contingencia;
169
    /**
170
     * Informar a Justificativa da entrada em contingência
171
     */
172
    private $justificativa;
173
    /**
174
     * Código do modelo do Documento Fiscal. 55 = NF-e; 65 = NFC-e.
175
     */
176
    private $modelo;
177
    /**
178
     * Tipo do Documento Fiscal (0 - entrada; 1 - saída)
179
     */
180
    private $tipo;
181
    /**
182
     * Identificador de Local de destino da operação
183
     * (1-Interna;2-Interestadual;3-Exterior)
184
     */
185
    private $destino;
186
    /**
187
     * Descrição da Natureza da Operação
188
     */
189
    private $natureza;
190
    /**
191
     * Código numérico que compõe a Chave de Acesso. Número aleatório gerado
192
     * pelo emitente para cada NF-e.
193
     */
194
    private $codigo;
195
    /**
196
     * Data e Hora de emissão do Documento Fiscal
197
     */
198
    private $data_emissao;
199
    /**
200
     * Série do Documento Fiscal: série normal 0-889, Avulsa Fisco 890-899,
201
     * SCAN 900-999
202
     */
203
    private $serie;
204
    /**
205
     * Formato de impressão do DANFE (0-sem DANFE;1-DANFe Retrato; 2-DANFe
206
     * Paisagem;3-DANFe Simplificado;4-DANFe NFC-e;5-DANFe NFC-e em mensagem
207
     * eletrônica)
208
     */
209
    private $formato;
210
    /**
211
     * Forma de emissão da NF-e
212
     */
213
    private $emissao;
214
    /**
215
     * Digito Verificador da Chave de Acesso da NF-e
216
     */
217
    private $digito_verificador;
218
    /**
219
     * Identificação do Ambiente: 1 - Produção, 2 - Homologação
220
     */
221
    private $ambiente;
222
    /**
223
     * Finalidade da emissão da NF-e: 1 - NFe normal, 2 - NFe complementar, 3 -
224
     * NFe de ajuste, 4 - Devolução/Retorno
225
     */
226
    private $finalidade;
227
    /**
228
     * Indica operação com consumidor final (0-Não;1-Consumidor Final)
229
     */
230
    private $consumidor_final;
231
    /**
232
     * Indicador de presença do comprador no estabelecimento comercial no
233
     * momento da oepração (0-Não se aplica, ex.: Nota Fiscal complementar ou
234
     * de ajuste;1-Operação presencial;2-Não presencial, internet;3-Não
235
     * presencial, teleatendimento;4-NFC-e entrega em domicílio;9-Não
236
     * presencial, outros)
237
     */
238
    private $presenca;
239
    /**
240
     * Dados dos totais da NF-e
241
     */
242
    private $total;
243
    /**
244
     * Informações adicionais de interesse do Fisco
245
     */
246
    private $adicionais;
247
    /**
248
     * Campo de uso livre do contribuinte informar o nome do campo no atributo
249
     * xCampo e o conteúdo do campo no xTexto
250
     */
251
    private $observacoes;
252
    /**
253
     * Campo de uso exclusivo do Fisco informar o nome do campo no atributo
254
     * xCampo e o conteúdo do campo no xTexto
255
     */
256
    private $informacoes;
257
    /**
258
     * Protocolo de autorização da nota, informado apenas quando a nota for
259
     * enviada e autorizada
260
     */
261
    private $protocolo;
262
263
    /**
264
     * Constroi uma instância de Nota vazia
265
     * @param  array $nota Array contendo dados da Nota
266
     */
267 34
    public function __construct($nota = [])
268
    {
269 34
        $this->fromArray($nota);
270 34
    }
271
272
    /**
273
     * Chave da nota fiscal
274
     * @param boolean $normalize informa se o id deve estar no formato do XML
275
     * @return mixed id da Nota
276
     */
277 32
    public function getID($normalize = false)
278
    {
279 32
        if (!$normalize) {
280 32
            return $this->id;
281
        }
282 32
        return 'NFe'.$this->id;
283
    }
284
285
    /**
286
     * Altera o valor do ID para o informado no parâmetro
287
     * @param mixed $id novo valor para ID
288
     * @return Nota A própria instância da classe
289
     */
290 34
    public function setID($id)
291
    {
292 34
        $this->id = $id;
293 34
        return $this;
294
    }
295
296
    /**
297
     * Número do Documento Fiscal
298
     * @param boolean $normalize informa se o numero deve estar no formato do XML
299
     * @return mixed numero da Nota
300
     */
301 32
    public function getNumero($normalize = false)
302
    {
303 32
        if (!$normalize) {
304 32
            return $this->numero;
305
        }
306 32
        return $this->numero;
307
    }
308
309
    /**
310
     * Altera o valor do Numero para o informado no parâmetro
311
     * @param mixed $numero novo valor para Numero
312
     * @return Nota A própria instância da classe
313
     */
314 34
    public function setNumero($numero)
315
    {
316 34
        $this->numero = $numero;
317 34
        return $this;
318
    }
319
320
    /**
321
     * Emitente da nota fiscal
322
     * @return mixed emitente da Nota
323
     */
324 32
    public function getEmitente()
325
    {
326 32
        return $this->emitente;
327
    }
328
329
    /**
330
     * Altera o valor do Emitente para o informado no parâmetro
331
     * @param mixed $emitente novo valor para Emitente
332
     * @return Nota A própria instância da classe
333
     */
334 34
    public function setEmitente($emitente)
335
    {
336 34
        $this->emitente = $emitente;
337 34
        return $this;
338
    }
339
340
    /**
341
     * Destinatário que receberá os produtos
342
     * @return mixed destinatario da Nota
343
     */
344 32
    public function getDestinatario()
345
    {
346 32
        return $this->destinatario;
347
    }
348
349
    /**
350
     * Altera o valor do Destinatario para o informado no parâmetro
351
     * @param mixed $destinatario novo valor para Destinatario
352
     * @return Nota A própria instância da classe
353
     */
354 34
    public function setDestinatario($destinatario)
355
    {
356 34
        $this->destinatario = $destinatario;
357 34
        return $this;
358
    }
359
360
    /**
361
     * Produtos adicionados na nota
362
     * @return \NFe\Entity\Produto[] produtos da Nota
363
     */
364 32
    public function getProdutos()
365
    {
366 32
        return $this->produtos;
367
    }
368
369
    /**
370
     * Altera o valor do Produtos para o informado no parâmetro
371
     * @param mixed $produtos novo valor para Produtos
372
     * @return Nota A própria instância da classe
373
     */
374 34
    public function setProdutos($produtos)
375
    {
376 34
        $this->produtos = $produtos;
377 34
        return $this;
378
    }
379
380
    /**
381
     * Adiciona um(a) Produto para a lista de produto
382
     * @param Produto $produto Instância do Produto que será adicionada
383
     * @return Nota A própria instância da classe
384
     */
385 6
    public function addProduto($produto)
386
    {
387 6
        $this->produtos[] = $produto;
388 6
        return $this;
389
    }
390
391
    /**
392
     * Informações de trasnporte da mercadoria
393
     * @return mixed transporte da Nota
394
     */
395 32
    public function getTransporte()
396
    {
397 32
        return $this->transporte;
398
    }
399
400
    /**
401
     * Altera o valor da Transporte para o informado no parâmetro
402
     * @param mixed $transporte novo valor para Transporte
403
     * @return Nota A própria instância da classe
404
     */
405 34
    public function setTransporte($transporte)
406
    {
407 34
        $this->transporte = $transporte;
408 34
        return $this;
409
    }
410
411
    /**
412
     * Pagamentos realizados
413
     * @return mixed pagamentos da Nota
414
     */
415 32
    public function getPagamentos()
416
    {
417 32
        return $this->pagamentos;
418
    }
419
420
    /**
421
     * Altera o valor do Pagamentos para o informado no parâmetro
422
     * @param mixed $pagamentos novo valor para Pagamentos
423
     * @return Nota A própria instância da classe
424
     */
425 34
    public function setPagamentos($pagamentos)
426
    {
427 34
        $this->pagamentos = $pagamentos;
428 34
        return $this;
429
    }
430
431
    /**
432
     * Adiciona um(a) Pagamento para a lista de pagamento
433
     * @param Pagamento $pagamento Instância do Pagamento que será adicionada
434
     * @return Nota A própria instância da classe
435
     */
436 5
    public function addPagamento($pagamento)
437
    {
438 5
        $this->pagamentos[] = $pagamento;
439 5
        return $this;
440
    }
441
442
    /**
443
     * Data e Hora da saída ou de entrada da mercadoria / produto
444
     * @param boolean $normalize informa se a data_movimentacao deve estar no formato do XML
445
     * @return mixed data_movimentacao da Nota
446
     */
447 32
    public function getDataMovimentacao($normalize = false)
448
    {
449 32
        if (!$normalize || is_null($this->data_movimentacao)) {
450 32
            return $this->data_movimentacao;
451
        }
452
        return Util::toDateTime($this->data_movimentacao);
453
    }
454
455
    /**
456
     * Altera o valor da DataMovimentacao para o informado no parâmetro
457
     * @param mixed $data_movimentacao novo valor para DataMovimentacao
458
     * @return Nota A própria instância da classe
459
     */
460 34
    public function setDataMovimentacao($data_movimentacao)
461
    {
462 34
        if (!is_null($data_movimentacao) && !is_numeric($data_movimentacao)) {
463
            $data_movimentacao = strtotime($data_movimentacao);
464
        }
465 34
        $this->data_movimentacao = $data_movimentacao;
466 34
        return $this;
467
    }
468
469
    /**
470
     * Informar a data e hora de entrada em contingência
471
     * @param boolean $normalize informa se a data_contingencia deve estar no formato do XML
472
     * @return mixed data_contingencia da Nota
473
     */
474 6
    public function getDataContingencia($normalize = false)
475
    {
476 6
        if (!$normalize || is_null($this->data_contingencia)) {
477 6
            return $this->data_contingencia;
478
        }
479
        return Util::toDateTime($this->data_contingencia);
480
    }
481
482
    /**
483
     * Altera o valor da DataContingencia para o informado no parâmetro
484
     * @param mixed $data_contingencia novo valor para DataContingencia
485
     * @return Nota A própria instância da classe
486
     */
487 34
    public function setDataContingencia($data_contingencia)
488
    {
489 34
        if (!is_null($data_contingencia) && !is_numeric($data_contingencia)) {
490
            $data_contingencia = strtotime($data_contingencia);
491
        }
492 34
        $this->data_contingencia = $data_contingencia;
493 34
        return $this;
494
    }
495
496
    /**
497
     * Informar a Justificativa da entrada em contingência
498
     * @param boolean $normalize informa se a justificativa deve estar no formato do XML
499
     * @return mixed justificativa da Nota
500
     */
501 6
    public function getJustificativa($normalize = false)
502
    {
503 6
        if (!$normalize) {
504 6
            return $this->justificativa;
505
        }
506
        return $this->justificativa;
507
    }
508
509
    /**
510
     * Altera o valor da Justificativa para o informado no parâmetro
511
     * @param mixed $justificativa novo valor para Justificativa
512
     * @return Nota A própria instância da classe
513
     */
514 34
    public function setJustificativa($justificativa)
515
    {
516 34
        $this->justificativa = $justificativa;
517 34
        return $this;
518
    }
519
520
    /**
521
     * Código do modelo do Documento Fiscal. 55 = NF-e; 65 = NFC-e.
522
     * @param boolean $normalize informa se o modelo deve estar no formato do XML
523
     * @return mixed modelo da Nota
524
     */
525 32
    public function getModelo($normalize = false)
526
    {
527 32
        if (!$normalize) {
528 31
            return $this->modelo;
529
        }
530 32
        switch ($this->modelo) {
531 32
            case self::MODELO_NFE:
532 1
                return '55';
533 31
            case self::MODELO_NFCE:
534 31
                return '65';
535
        }
536
        return $this->modelo;
537
    }
538
539
    /**
540
     * Altera o valor do Modelo para o informado no parâmetro
541
     * @param mixed $modelo novo valor para Modelo
542
     * @return Nota A própria instância da classe
543
     */
544 34
    public function setModelo($modelo)
545
    {
546
        switch ($modelo) {
547 34
            case '55':
548
                $modelo = self::MODELO_NFE;
549
                break;
550 34
            case '65':
551 26
                $modelo = self::MODELO_NFCE;
552 26
                break;
553
        }
554 34
        $this->modelo = $modelo;
555 34
        return $this;
556
    }
557
558
    /**
559
     * Tipo do Documento Fiscal (0 - entrada; 1 - saída)
560
     * @param boolean $normalize informa se o tipo deve estar no formato do XML
561
     * @return mixed tipo da Nota
562
     */
563 32
    public function getTipo($normalize = false)
564
    {
565 32
        if (!$normalize) {
566 6
            return $this->tipo;
567
        }
568 32
        switch ($this->tipo) {
569 32
            case self::TIPO_ENTRADA:
570
                return '0';
571 32
            case self::TIPO_SAIDA:
572 32
                return '1';
573
        }
574
        return $this->tipo;
575
    }
576
577
    /**
578
     * Altera o valor do Tipo para o informado no parâmetro
579
     * @param mixed $tipo novo valor para Tipo
580
     * @return Nota A própria instância da classe
581
     */
582 34
    public function setTipo($tipo)
583
    {
584
        switch ($tipo) {
585 34
            case '0':
586
                $tipo = self::TIPO_ENTRADA;
587
                break;
588 34
            case '1':
589 26
                $tipo = self::TIPO_SAIDA;
590 26
                break;
591
        }
592 34
        $this->tipo = $tipo;
593 34
        return $this;
594
    }
595
596
    /**
597
     * Identificador de Local de destino da operação
598
     * (1-Interna;2-Interestadual;3-Exterior)
599
     * @param boolean $normalize informa se o destino deve estar no formato do XML
600
     * @return mixed destino da Nota
601
     */
602 32
    public function getDestino($normalize = false)
603
    {
604 32
        if (!$normalize) {
605 6
            return $this->destino;
606
        }
607 32
        switch ($this->destino) {
608 32
            case self::DESTINO_INTERNA:
609 32
                return '1';
610
            case self::DESTINO_INTERESTADUAL:
611
                return '2';
612
            case self::DESTINO_EXTERIOR:
613
                return '3';
614
        }
615
        return $this->destino;
616
    }
617
618
    /**
619
     * Altera o valor do Destino para o informado no parâmetro
620
     * @param mixed $destino novo valor para Destino
621
     * @return Nota A própria instância da classe
622
     */
623 34
    public function setDestino($destino)
624
    {
625
        switch ($destino) {
626 34
            case '1':
627 26
                $destino = self::DESTINO_INTERNA;
628 26
                break;
629 34
            case '2':
630
                $destino = self::DESTINO_INTERESTADUAL;
631
                break;
632 34
            case '3':
633
                $destino = self::DESTINO_EXTERIOR;
634
                break;
635
        }
636 34
        $this->destino = $destino;
637 34
        return $this;
638
    }
639
640
    /**
641
     * Descrição da Natureza da Operação
642
     * @param boolean $normalize informa se a natureza deve estar no formato do XML
643
     * @return mixed natureza da Nota
644
     */
645 32
    public function getNatureza($normalize = false)
646
    {
647 32
        if (!$normalize) {
648 6
            return $this->natureza;
649
        }
650 32
        return $this->natureza;
651
    }
652
653
    /**
654
     * Altera o valor da Natureza para o informado no parâmetro
655
     * @param mixed $natureza novo valor para Natureza
656
     * @return Nota A própria instância da classe
657
     */
658 34
    public function setNatureza($natureza)
659
    {
660 34
        $this->natureza = $natureza;
661 34
        return $this;
662
    }
663
664
    /**
665
     * Código numérico que compõe a Chave de Acesso. Número aleatório gerado
666
     * pelo emitente para cada NF-e.
667
     * @param boolean $normalize informa se o codigo deve estar no formato do XML
668
     * @return mixed codigo da Nota
669
     */
670 32
    public function getCodigo($normalize = false)
671
    {
672 32
        if (!$normalize) {
673 32
            return $this->codigo;
674
        }
675 32
        return Util::padDigit($this->codigo % 100000000, 8);
676
    }
677
678
    /**
679
     * Altera o valor do Codigo para o informado no parâmetro
680
     * @param mixed $codigo novo valor para Codigo
681
     * @return Nota A própria instância da classe
682
     */
683 34
    public function setCodigo($codigo)
684
    {
685 34
        $this->codigo = $codigo;
686 34
        return $this;
687
    }
688
689
    /**
690
     * Data e Hora de emissão do Documento Fiscal
691
     * @param boolean $normalize informa se o data_emissao deve estar no formato do XML
692
     * @return mixed data_emissao da Nota
693
     */
694 32
    public function getDataEmissao($normalize = false)
695
    {
696 32
        if (!$normalize) {
697 32
            return $this->data_emissao;
698
        }
699 32
        return Util::toDateTime($this->data_emissao);
700
    }
701
702
    /**
703
     * Altera o valor do DataEmissao para o informado no parâmetro
704
     * @param mixed $data_emissao novo valor para DataEmissao
705
     * @return Nota A própria instância da classe
706
     */
707 34
    public function setDataEmissao($data_emissao)
708
    {
709 34
        if (!is_numeric($data_emissao)) {
710 34
            $data_emissao = strtotime($data_emissao);
711
        }
712 34
        $this->data_emissao = $data_emissao;
713 34
        return $this;
714
    }
715
716
    /**
717
     * Série do Documento Fiscal: série normal 0-889, Avulsa Fisco 890-899,
718
     * SCAN 900-999
719
     * @param boolean $normalize informa se o serie deve estar no formato do XML
720
     * @return mixed serie da Nota
721
     */
722 32
    public function getSerie($normalize = false)
723
    {
724 32
        if (!$normalize) {
725 32
            return $this->serie;
726
        }
727 32
        return $this->serie;
728
    }
729
730
    /**
731
     * Altera o valor do Serie para o informado no parâmetro
732
     * @param mixed $serie novo valor para Serie
733
     * @return Nota A própria instância da classe
734
     */
735 34
    public function setSerie($serie)
736
    {
737 34
        $this->serie = $serie;
738 34
        return $this;
739
    }
740
741
    /**
742
     * Formato de impressão do DANFE (0-sem DANFE;1-DANFe Retrato; 2-DANFe
743
     * Paisagem;3-DANFe Simplificado;4-DANFe NFC-e;5-DANFe NFC-e em mensagem
744
     * eletrônica)
745
     * @param boolean $normalize informa se o formato deve estar no formato do XML
746
     * @return mixed formato da Nota
747
     */
748 32
    public function getFormato($normalize = false)
749
    {
750 32
        if (!$normalize) {
751 6
            return $this->formato;
752
        }
753 32
        switch ($this->formato) {
754 32
            case self::FORMATO_NENHUMA:
755 1
                return '0';
756 31
            case self::FORMATO_RETRATO:
757
                return '1';
758 31
            case self::FORMATO_PAISAGEM:
759
                return '2';
760 31
            case self::FORMATO_SIMPLIFICADO:
761
                return '3';
762 31
            case self::FORMATO_CONSUMIDOR:
763 31
                return '4';
764
            case self::FORMATO_MENSAGEM:
765
                return '5';
766
        }
767
        return $this->formato;
768
    }
769
770
    /**
771
     * Altera o valor do Formato para o informado no parâmetro
772
     * @param mixed $formato novo valor para Formato
773
     * @return Nota A própria instância da classe
774
     */
775 34
    public function setFormato($formato)
776
    {
777
        switch ($formato) {
778 34
            case '0':
779
                $formato = self::FORMATO_NENHUMA;
780
                break;
781 34
            case '1':
782
                $formato = self::FORMATO_RETRATO;
783
                break;
784 34
            case '2':
785
                $formato = self::FORMATO_PAISAGEM;
786
                break;
787 34
            case '3':
788
                $formato = self::FORMATO_SIMPLIFICADO;
789
                break;
790 34
            case '4':
791 26
                $formato = self::FORMATO_CONSUMIDOR;
792 26
                break;
793 34
            case '5':
794
                $formato = self::FORMATO_MENSAGEM;
795
                break;
796
        }
797 34
        $this->formato = $formato;
798 34
        return $this;
799
    }
800
801
    /**
802
     * Forma de emissão da NF-e
803
     * @param boolean $normalize informa se o emissao deve estar no formato do XML
804
     * @return mixed emissao da Nota
805
     */
806 32
    public function getEmissao($normalize = false)
807
    {
808 32
        if (!$normalize) {
809 32
            return $this->emissao;
810
        }
811 32
        switch ($this->emissao) {
812 32
            case self::EMISSAO_NORMAL:
813 32
                return '1';
814
            case self::EMISSAO_CONTINGENCIA:
815
                return '9';
816
        }
817
        return $this->emissao;
818
    }
819
820
    /**
821
     * Altera o valor do Emissao para o informado no parâmetro
822
     * @param mixed $emissao novo valor para Emissao
823
     * @return Nota A própria instância da classe
824
     */
825 34
    public function setEmissao($emissao)
826
    {
827
        switch ($emissao) {
828 34
            case '1':
829 26
                $emissao = self::EMISSAO_NORMAL;
830 26
                break;
831 34
            case '9':
832
                $emissao = self::EMISSAO_CONTINGENCIA;
833
                break;
834
        }
835 34
        $this->emissao = $emissao;
836 34
        return $this;
837
    }
838
839
    /**
840
     * Digito Verificador da Chave de Acesso da NF-e
841
     * @param boolean $normalize informa se o digito_verificador deve estar no formato do XML
842
     * @return mixed digito_verificador da Nota
843
     */
844 32
    public function getDigitoVerificador($normalize = false)
845
    {
846 32
        if (!$normalize) {
847 6
            return $this->digito_verificador;
848
        }
849 32
        return $this->digito_verificador;
850
    }
851
852
    /**
853
     * Altera o valor do DigitoVerificador para o informado no parâmetro
854
     * @param mixed $digito_verificador novo valor para DigitoVerificador
855
     * @return Nota A própria instância da classe
856
     */
857 34
    public function setDigitoVerificador($digito_verificador)
858
    {
859 34
        $this->digito_verificador = $digito_verificador;
860 34
        return $this;
861
    }
862
863
    /**
864
     * Identificação do Ambiente: 1 - Produção, 2 - Homologação
865
     * @param boolean $normalize informa se o ambiente deve estar no formato do XML
866
     * @return mixed ambiente da Nota
867
     */
868 32
    public function getAmbiente($normalize = false)
869
    {
870 32
        if (!$normalize) {
871 32
            return $this->ambiente;
872
        }
873 32
        switch ($this->ambiente) {
874 32
            case self::AMBIENTE_PRODUCAO:
875
                return '1';
876 32
            case self::AMBIENTE_HOMOLOGACAO:
877 32
                return '2';
878
        }
879
        return $this->ambiente;
880
    }
881
882
    /**
883
     * Altera o valor do Ambiente para o informado no parâmetro
884
     * @param mixed $ambiente novo valor para Ambiente
885
     * @return Nota A própria instância da classe
886
     */
887 34
    public function setAmbiente($ambiente)
888
    {
889
        switch ($ambiente) {
890 34
            case '1':
891
                $ambiente = self::AMBIENTE_PRODUCAO;
892
                break;
893 34
            case '2':
894 26
                $ambiente = self::AMBIENTE_HOMOLOGACAO;
895 26
                break;
896
        }
897 34
        $this->ambiente = $ambiente;
898 34
        return $this;
899
    }
900
901
    /**
902
     * Finalidade da emissão da NF-e: 1 - NFe normal, 2 - NFe complementar, 3 -
903
     * NFe de ajuste, 4 - Devolução/Retorno
904
     * @param boolean $normalize informa se a finalidade deve estar no formato do XML
905
     * @return mixed finalidade da Nota
906
     */
907 32
    public function getFinalidade($normalize = false)
908
    {
909 32
        if (!$normalize) {
910 6
            return $this->finalidade;
911
        }
912 32
        switch ($this->finalidade) {
913 32
            case self::FINALIDADE_NORMAL:
914 32
                return '1';
915
            case self::FINALIDADE_COMPLEMENTAR:
916
                return '2';
917
            case self::FINALIDADE_AJUSTE:
918
                return '3';
919
            case self::FINALIDADE_RETORNO:
920
                return '4';
921
        }
922
        return $this->finalidade;
923
    }
924
925
    /**
926
     * Altera o valor da Finalidade para o informado no parâmetro
927
     * @param mixed $finalidade novo valor para Finalidade
928
     * @return Nota A própria instância da classe
929
     */
930 34
    public function setFinalidade($finalidade)
931
    {
932
        switch ($finalidade) {
933 34
            case '1':
934 26
                $finalidade = self::FINALIDADE_NORMAL;
935 26
                break;
936 34
            case '2':
937
                $finalidade = self::FINALIDADE_COMPLEMENTAR;
938
                break;
939 34
            case '3':
940
                $finalidade = self::FINALIDADE_AJUSTE;
941
                break;
942 34
            case '4':
943
                $finalidade = self::FINALIDADE_RETORNO;
944
                break;
945
        }
946 34
        $this->finalidade = $finalidade;
947 34
        return $this;
948
    }
949
950
    /**
951
     * Indica operação com consumidor final (0-Não;1-Consumidor Final)
952
     * @param boolean $normalize informa se o consumidor_final deve estar no formato do XML
953
     * @return mixed consumidor_final da Nota
954
     */
955 32
    public function getConsumidorFinal($normalize = false)
956
    {
957 32
        if (!$normalize) {
958 6
            return $this->consumidor_final;
959
        }
960 32
        switch ($this->consumidor_final) {
961 32
            case 'N':
962
                return '0';
963 32
            case 'Y':
964 6
                return '1';
965
        }
966 26
        return $this->consumidor_final;
967
    }
968
969
    /**
970
     * Indica operação com consumidor final (0-Não;1-Consumidor Final)
971
     * @return boolean informa se o ConsumidorFinal está habilitado
972
     */
973
    public function isConsumidorFinal()
974
    {
975
        return $this->consumidor_final == 'Y';
976
    }
977
978
    /**
979
     * Altera o valor do ConsumidorFinal para o informado no parâmetro
980
     * @param mixed $consumidor_final novo valor para ConsumidorFinal
981
     * @return Nota A própria instância da classe
982
     */
983 34
    public function setConsumidorFinal($consumidor_final)
984
    {
985 34
        if (is_bool($consumidor_final)) {
986
            $consumidor_final = $consumidor_final ? 'Y': 'N';
987
        }
988 34
        $this->consumidor_final = $consumidor_final;
989 34
        return $this;
990
    }
991
992
    /**
993
     * Indicador de presença do comprador no estabelecimento comercial no
994
     * momento da oepração (0-Não se aplica (ex.: Nota Fiscal complementar ou
995
     * de ajuste;1-Operação presencial;2-Não presencial, internet;
996
     * 3-Não presencial, teleatendimento;4-NFC-e entrega em domicílio;
997
     * 5-Operação presencial, fora do estabelecimento;9-Não presencial, outros)
998
     * @param boolean $normalize informa se a presenca deve estar no formato do XML
999
     * @return mixed presenca da Nota
1000
     */
1001 32
    public function getPresenca($normalize = false)
1002
    {
1003 32
        if (!$normalize) {
1004 6
            return $this->presenca;
1005
        }
1006 32
        switch ($this->presenca) {
1007 32
            case self::PRESENCA_NENHUM:
1008
                return '0';
1009 32
            case self::PRESENCA_PRESENCIAL:
1010 32
                return '1';
1011
            case self::PRESENCA_INTERNET:
1012
                return '2';
1013
            case self::PRESENCA_TELEATENDIMENTO:
1014
                return '3';
1015
            case self::PRESENCA_ENTREGA:
1016
                return '4';
1017
            case self::PRESENCA_AMBULANTE:
1018
                return '5';
1019
            case self::PRESENCA_OUTROS:
1020
                return '9';
1021
        }
1022
        return $this->presenca;
1023
    }
1024
1025
    /**
1026
     * Altera o valor da Presenca para o informado no parâmetro
1027
     * @param mixed $presenca novo valor para Presenca
1028
     * @return Nota A própria instância da classe
1029
     */
1030 34
    public function setPresenca($presenca)
1031
    {
1032
        switch ($presenca) {
1033 34
            case '0':
1034
                $presenca = self::PRESENCA_NENHUM;
1035
                break;
1036 34
            case '1':
1037 26
                $presenca = self::PRESENCA_PRESENCIAL;
1038 26
                break;
1039 34
            case '2':
1040
                $presenca = self::PRESENCA_INTERNET;
1041
                break;
1042 34
            case '3':
1043
                $presenca = self::PRESENCA_TELEATENDIMENTO;
1044
                break;
1045 34
            case '4':
1046
                $presenca = self::PRESENCA_ENTREGA;
1047
                break;
1048 34
            case '5':
1049
                $presenca = self::PRESENCA_AMBULANTE;
1050
                break;
1051 34
            case '9':
1052
                $presenca = self::PRESENCA_OUTROS;
1053
                break;
1054
        }
1055 34
        $this->presenca = $presenca;
1056 34
        return $this;
1057
    }
1058
1059
    /**
1060
     * Dados dos totais da NF-e
1061
     * @return mixed total da Nota
1062
     */
1063 32
    public function getTotal()
1064
    {
1065 32
        return $this->total;
1066
    }
1067
    
1068
    /**
1069
     * Altera o valor do Total para o informado no parâmetro
1070
     * @param mixed $total novo valor para Total
1071
     * @return Nota A própria instância da classe
1072
     */
1073 34
    public function setTotal($total)
1074
    {
1075 34
        $this->total = $total;
1076 34
        return $this;
1077
    }
1078
1079
    /**
1080
     * Informações adicionais de interesse do Fisco
1081
     * @param boolean $normalize informa se a adicionais deve estar no formato do XML
1082
     * @return mixed adicionais da Nota
1083
     */
1084 32
    public function getAdicionais($normalize = false)
1085
    {
1086 32
        if (!$normalize) {
1087 32
            return $this->adicionais;
1088
        }
1089
        return $this->adicionais;
1090
    }
1091
    
1092
    /**
1093
     * Altera o valor da Adicionais para o informado no parâmetro
1094
     * @param mixed $adicionais novo valor para Adicionais
1095
     * @return Nota A própria instância da classe
1096
     */
1097 34
    public function setAdicionais($adicionais)
1098
    {
1099 34
        $this->adicionais = $adicionais;
1100 34
        return $this;
1101
    }
1102
1103
    /**
1104
     * Campo de uso livre do contribuinte informar o nome do campo no atributo
1105
     * xCampo e o conteúdo do campo no xTexto
1106
     * @return mixed observacoes da Nota
1107
     */
1108 32
    public function getObservacoes()
1109
    {
1110 32
        return $this->observacoes;
1111
    }
1112
    
1113
    /**
1114
     * Altera o valor da Observacoes para o informado no parâmetro
1115
     * @param mixed $observacoes novo valor para Observacoes
1116
     * @return Nota A própria instância da classe
1117
     */
1118 34
    public function setObservacoes($observacoes)
1119
    {
1120 34
        $this->observacoes = $observacoes;
1121 34
        return $this;
1122
    }
1123
1124
    /**
1125
     * Adiciona um(a) Observacao para a lista de observacao
1126
     * @param Observacao $observacao Instância da Observacao que será adicionada
1127
     * @return Nota A própria instância da classe
1128
     */
1129 6
    public function addObservacao($campo, $observacao)
1130
    {
1131 6
        $this->observacoes[] = ['campo' => $campo, 'valor' => $observacao];
1132 6
        return $this;
1133
    }
1134
1135
    /**
1136
     * Campo de uso exclusivo do Fisco informar o nome do campo no atributo
1137
     * xCampo e o conteúdo do campo no xTexto
1138
     * @return mixed informacoes da Nota
1139
     */
1140 32
    public function getInformacoes()
1141
    {
1142 32
        return $this->informacoes;
1143
    }
1144
    
1145
    /**
1146
     * Altera o valor da Informacoes para o informado no parâmetro
1147
     * @param mixed $informacoes novo valor para Informacoes
1148
     * @return Nota A própria instância da classe
1149
     */
1150 34
    public function setInformacoes($informacoes)
1151
    {
1152 34
        $this->informacoes = $informacoes;
1153 34
        return $this;
1154
    }
1155
1156
    /**
1157
     * Adiciona um(a) Informacao para a lista de informacao
1158
     * @param Informacao $informacao Instância da Informacao que será adicionada
1159
     * @return Nota A própria instância da classe
1160
     */
1161 6
    public function addInformacao($campo, $informacao)
1162
    {
1163 6
        $this->informacoes[] = ['campo' => $campo, 'valor' => $informacao];
1164 6
        return $this;
1165
    }
1166
1167
    /**
1168
     * Protocolo de autorização da nota, informado apenas quando a nota for
1169
     * enviada e autorizada
1170
     */
1171 30
    public function getProtocolo()
1172
    {
1173 30
        return $this->protocolo;
1174
    }
1175
1176 34
    public function setProtocolo($protocolo)
1177
    {
1178 34
        $this->protocolo = $protocolo;
1179 34
        return $this;
1180
    }
1181
1182 6
    public function toArray($recursive = false)
0 ignored issues
show
Complexity introduced by
This operation has 2187 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...
1183
    {
1184 6
        $nota = [];
1185 6
        $nota['id'] = $this->getID();
1186 6
        $nota['numero'] = $this->getNumero();
1187 6
        if (!is_null($this->getEmitente()) && $recursive) {
1188
            $nota['emitente'] = $this->getEmitente()->toArray($recursive);
1189
        } else {
1190 6
            $nota['emitente'] = $this->getEmitente();
1191
        }
1192 6
        if (!is_null($this->getDestinatario()) && $recursive) {
1193
            $nota['destinatario'] = $this->getDestinatario()->toArray($recursive);
1194
        } else {
1195 6
            $nota['destinatario'] = $this->getDestinatario();
1196
        }
1197 6
        if ($recursive) {
1198
            $produtos = [];
1199
            $_produtos = $this->getProdutos();
1200
            foreach ($_produtos as $_produto) {
1201
                $produtos[] = $_produto->toArray($recursive);
1202
            }
1203
            $nota['produtos'] = $produtos;
1204
        } else {
1205 6
            $nota['produtos'] = $this->getProdutos();
1206
        }
1207 6
        if (!is_null($this->getTransporte()) && $recursive) {
1208
            $nota['transporte'] = $this->getTransporte()->toArray($recursive);
1209
        } else {
1210 6
            $nota['transporte'] = $this->getTransporte();
1211
        }
1212 6
        if ($recursive) {
1213
            $pagamentos = [];
1214
            $_pagamentos = $this->getPagamentos();
1215
            foreach ($_pagamentos as $_pagamento) {
1216
                $pagamentos[] = $_pagamento->toArray($recursive);
1217
            }
1218
            $nota['pagamentos'] = $pagamentos;
1219
        } else {
1220 6
            $nota['pagamentos'] = $this->getPagamentos();
1221
        }
1222 6
        $nota['data_movimentacao'] = $this->getDataMovimentacao($recursive);
1223 6
        $nota['data_contingencia'] = $this->getDataContingencia($recursive);
1224 6
        $nota['justificativa'] = $this->getJustificativa();
1225 6
        $nota['modelo'] = $this->getModelo();
1226 6
        $nota['tipo'] = $this->getTipo();
1227 6
        $nota['destino'] = $this->getDestino();
1228 6
        $nota['natureza'] = $this->getNatureza();
1229 6
        $nota['codigo'] = $this->getCodigo();
1230 6
        $nota['data_emissao'] = $this->getDataEmissao($recursive);
1231 6
        $nota['serie'] = $this->getSerie();
1232 6
        $nota['formato'] = $this->getFormato();
1233 6
        $nota['emissao'] = $this->getEmissao();
1234 6
        $nota['digito_verificador'] = $this->getDigitoVerificador();
1235 6
        $nota['ambiente'] = $this->getAmbiente();
1236 6
        $nota['finalidade'] = $this->getFinalidade();
1237 6
        $nota['consumidor_final'] = $this->getConsumidorFinal();
1238 6
        $nota['presenca'] = $this->getPresenca();
1239 6
        if (!is_null($this->getTotal()) && $recursive) {
1240
            $nota['total'] = $this->getTotal()->toArray($recursive);
1241
        } else {
1242 6
            $nota['total'] = $this->getTotal();
1243
        }
1244 6
        $nota['adicionais'] = $this->getAdicionais();
1245 6
        $nota['observacoes'] = $this->getObservacoes();
1246 6
        $nota['informacoes'] = $this->getInformacoes();
1247 6
        if (!is_null($this->getProtocolo()) && $recursive) {
1248
            $nota['protocolo'] = $this->getProtocolo()->toArray($recursive);
1249
        } else {
1250 6
            $nota['protocolo'] = $this->getProtocolo();
1251
        }
1252 6
        return $nota;
1253
    }
1254
1255 34
    public function fromArray($nota = [])
0 ignored issues
show
Complexity introduced by
This operation has 62914560000 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...
1256
    {
1257 34
        if ($nota instanceof Nota) {
1258
            $nota = $nota->toArray();
1259 34
        } elseif (!is_array($nota)) {
1260
            return $this;
1261
        }
1262 34
        if (isset($nota['id'])) {
1263
            $this->setID($nota['id']);
1264
        } else {
1265 34
            $this->setID(null);
1266
        }
1267 34
        if (isset($nota['numero'])) {
1268 6
            $this->setNumero($nota['numero']);
1269
        } else {
1270 34
            $this->setNumero(null);
1271
        }
1272 34
        $this->setEmitente(new Emitente(isset($nota['emitente']) ? $nota['emitente'] : []));
1273 34
        $this->setDestinatario(new Destinatario(isset($nota['destinatario']) ? $nota['destinatario'] : []));
1274 34
        if (!isset($nota['produtos'])) {
1275 34
            $this->setProdutos([]);
1276
        } else {
1277 6
            $this->setProdutos($nota['produtos']);
1278
        }
1279 34
        $this->setTransporte(new Transporte(isset($nota['transporte']) ? $nota['transporte'] : []));
1280 34
        if (!isset($nota['pagamentos'])) {
1281 34
            $this->setPagamentos([]);
1282
        } else {
1283 6
            $this->setPagamentos($nota['pagamentos']);
1284
        }
1285 34
        if (isset($nota['data_movimentacao'])) {
1286
            $this->setDataMovimentacao($nota['data_movimentacao']);
1287
        } else {
1288 34
            $this->setDataMovimentacao(null);
1289
        }
1290 34
        if (isset($nota['data_contingencia'])) {
1291
            $this->setDataContingencia($nota['data_contingencia']);
1292
        } else {
1293 34
            $this->setDataContingencia(null);
1294
        }
1295 34
        if (isset($nota['justificativa'])) {
1296
            $this->setJustificativa($nota['justificativa']);
1297
        } else {
1298 34
            $this->setJustificativa(null);
1299
        }
1300 34
        if (isset($nota['modelo'])) {
1301 6
            $this->setModelo($nota['modelo']);
1302
        } else {
1303 34
            $this->setModelo(null);
1304
        }
1305 34
        if (!isset($nota['tipo'])) {
1306 34
            $this->setTipo(self::TIPO_SAIDA);
1307
        } else {
1308 6
            $this->setTipo($nota['tipo']);
1309
        }
1310 34
        if (!isset($nota['destino'])) {
1311 34
            $this->setDestino(self::DESTINO_INTERNA);
1312
        } else {
1313 6
            $this->setDestino($nota['destino']);
1314
        }
1315 34
        if (!isset($nota['natureza'])) {
1316 34
            $this->setNatureza('VENDA PARA CONSUMIDOR FINAL');
1317
        } else {
1318 6
            $this->setNatureza($nota['natureza']);
1319
        }
1320 34
        if (isset($nota['codigo'])) {
1321 6
            $this->setCodigo($nota['codigo']);
1322
        } else {
1323 34
            $this->setCodigo(null);
1324
        }
1325 34
        if (isset($nota['data_emissao'])) {
1326 6
            $this->setDataEmissao($nota['data_emissao']);
1327
        } else {
1328 34
            $this->setDataEmissao(null);
1329
        }
1330 34
        if (isset($nota['serie'])) {
1331 6
            $this->setSerie($nota['serie']);
1332
        } else {
1333 34
            $this->setSerie(null);
1334
        }
1335 34
        if (!isset($nota['formato'])) {
1336 34
            $this->setFormato(self::FORMATO_NENHUMA);
1337
        } else {
1338 6
            $this->setFormato($nota['formato']);
1339
        }
1340 34
        if (!isset($nota['emissao'])) {
1341 34
            $this->setEmissao(self::EMISSAO_NORMAL);
1342
        } else {
1343 6
            $this->setEmissao($nota['emissao']);
1344
        }
1345 34
        if (isset($nota['digito_verificador'])) {
1346
            $this->setDigitoVerificador($nota['digito_verificador']);
1347
        } else {
1348 34
            $this->setDigitoVerificador(null);
1349
        }
1350 34
        if (!isset($nota['ambiente'])) {
1351 34
            $this->setAmbiente(self::AMBIENTE_HOMOLOGACAO);
1352
        } else {
1353 6
            $this->setAmbiente($nota['ambiente']);
1354
        }
1355 34
        if (!isset($nota['finalidade'])) {
1356 34
            $this->setFinalidade(self::FINALIDADE_NORMAL);
1357
        } else {
1358 6
            $this->setFinalidade($nota['finalidade']);
1359
        }
1360 34
        if (!isset($nota['consumidor_final'])) {
1361 34
            $this->setConsumidorFinal('Y');
1362
        } else {
1363 6
            $this->setConsumidorFinal($nota['consumidor_final']);
1364
        }
1365 34
        if (isset($nota['presenca'])) {
1366 6
            $this->setPresenca($nota['presenca']);
1367
        } else {
1368 34
            $this->setPresenca(null);
1369
        }
1370 34
        $this->setTotal(new Total(isset($nota['total']) ? $nota['total'] : []));
1371 34
        if (!array_key_exists('adicionais', $nota)) {
1372 34
            $this->setAdicionais(null);
1373
        } else {
1374 6
            $this->setAdicionais($nota['adicionais']);
1375
        }
1376 34
        if (!array_key_exists('observacoes', $nota)) {
1377 34
            $this->setObservacoes(null);
1378
        } else {
1379 6
            $this->setObservacoes($nota['observacoes']);
1380
        }
1381 34
        if (!array_key_exists('informacoes', $nota)) {
1382 34
            $this->setInformacoes(null);
1383
        } else {
1384 6
            $this->setInformacoes($nota['informacoes']);
1385
        }
1386 34
        if (isset($nota['protocolo'])) {
1387
            $this->setProtocolo($nota['protocolo']);
1388
        } else {
1389 34
            $this->setProtocolo(null);
1390
        }
1391 34
        return $this;
1392
    }
1393
1394 32
    public function gerarID()
1395
    {
1396 32
        $estado = $this->getEmitente()->getEndereco()->getMunicipio()->getEstado();
1397 32
        $estado->checkCodigos();
1398 32
        $id = sprintf(
1399 32
            '%02d%02d%02d%s%02d%03d%09d%01d%08d',
1400 32
            $estado->getCodigo(),
1401 32
            date('y', $this->getDataEmissao()), // Ano 2 dígitos
1402 32
            date('m', $this->getDataEmissao()), // Mês 2 dígitos
1403 32
            $this->getEmitente()->getCNPJ(),
1404 32
            $this->getModelo(true),
1405 32
            $this->getSerie(),
1406 32
            $this->getNumero(),
1407 32
            $this->getEmissao(true),
1408 32
            $this->getCodigo()
1409
        );
1410 32
        return $id.Util::getDAC($id, 11);
1411
    }
1412
1413 32
    protected function getTotais()
1414
    {
1415 32
        $total = [];
1416 32
        $total['produtos'] = 0.00;
1417 32
        $total['desconto'] = 0.00;
1418 32
        $total['frete'] = 0.00;
1419 32
        $total['seguro'] = 0.00;
1420 32
        $total['despesas'] = 0.00;
1421 32
        $total['tributos'] = 0.00;
1422 32
        $total['icms'] = 0.00;
1423 32
        $total['icms.st'] = 0.00;
1424 32
        $total['base'] = 0.00;
1425 32
        $total['base.st'] = 0.00;
1426 32
        $total['ii'] = 0.00;
1427 32
        $total['ipi'] = 0.00;
1428 32
        $total['pis'] = 0.00;
1429 32
        $total['cofins'] = 0.00;
1430 32
        $total['desoneracao'] = 0.00;
1431 32
        $total['fundo'] = 0.00;
1432 32
        $total['fundo.st'] = 0.00;
1433 32
        $total['fundo.retido.st'] = 0.00;
1434 32
        $total['ipi.devolvido'] = 0.00;
1435 32
        $_produtos = $this->getProdutos();
1436 32
        foreach ($_produtos as $_produto) {
1437 32
            if (!$_produto->getMultiplicador()) {
1438
                continue;
1439
            }
1440 32
            $imposto_info = $_produto->getImpostoInfo();
1441 32
            $total['produtos'] += round($_produto->getPreco(), 2);
1442 32
            $total['desconto'] += round($_produto->getDesconto(), 2);
1443 32
            $total['frete'] += round($_produto->getFrete(), 2);
1444 32
            $total['seguro'] += round($_produto->getSeguro(), 2);
1445 32
            $total['despesas'] += round($_produto->getDespesas(), 2);
1446 32
            $total['tributos'] += round($imposto_info['total'], 2);
1447 32
            $_impostos = $_produto->getImpostos();
1448 32
            foreach ($_impostos as $_imposto) {
1449 32
                switch ($_imposto->getGrupo()) {
1450 32
                    case Imposto::GRUPO_ICMS:
1451 32
                        if (($_imposto instanceof \NFe\Entity\Imposto\ICMS\Cobranca) ||
1452 32
                                ($_imposto instanceof \NFe\Entity\Imposto\ICMS\Simples\Cobranca)
1453
                        ) {
1454 32
                            $total[$_imposto->getGrupo()] += round($_imposto->getNormal()->getValor(), 2);
1455 32
                            $total['base'] += round($_imposto->getNormal()->getBase(), 2);
1456
                        }
1457 32
                        if (($_imposto instanceof \NFe\Entity\Imposto\ICMS\Parcial) ||
1458 32
                                ($_imposto instanceof \NFe\Entity\Imposto\ICMS\Simples\Parcial)
1459
                        ) {
1460 32
                            $total['icms.st'] += round($_imposto->getValor(), 2);
1461 32
                            $total['base.st'] += round($_imposto->getBase(), 2);
1462
                        } else {
1463
                            $total[$_imposto->getGrupo()] += round($_imposto->getValor(), 2);
1464
                            $total['base'] += round($_imposto->getBase(), 2);
1465
                        }
1466 32
                        $fundo = $_imposto->getFundo();
1467
                        // a ordem de comparação importa pois uma classe estende da outra
1468 32
                        if ($fundo instanceof \NFe\Entity\Imposto\Fundo\Retido) {
1469 32
                            $total['fundo.retido.st'] += round($fundo->getTotal(), 2);
1470
                        } elseif ($fundo instanceof \NFe\Entity\Imposto\Fundo\Substituido) {
1471
                            $total['fundo.st'] += round($fundo->getTotal(), 2);
1472
                        } elseif ($fundo instanceof \NFe\Entity\Imposto\Fundo\Base) {
1473
                            $total['fundo'] += round($fundo->getTotal(), 2);
1474
                        }
1475 32
                        break;
1476
                    default:
1477 32
                        $total[$_imposto->getGrupo()] += round($_imposto->getValor(), 2);
1478
                }
1479
            }
1480
        }
1481 32
        $produtos = round($total['produtos'], 2) - round($total['desconto'], 2);
1482 32
        $servicos = round($total['frete'], 2) + round($total['seguro'], 2) + round($total['despesas'], 2);
1483 32
        $impostos = round($total['ii'], 2) + round($total['ipi'], 2) + round($total['icms.st'], 2);
1484 32
        $impostos = $impostos - round($total['desoneracao'], 2);
1485 32
        $total['nota'] = $produtos + $servicos + $impostos;
1486 32
        return $total;
1487
    }
1488
1489 32
    private function getNodeTotal($name = null)
1490
    {
1491 32
        $dom = new \DOMDocument('1.0', 'UTF-8');
1492 32
        $element = $dom->createElement(is_null($name)?'total':$name);
1493
1494
        // Totais referentes ao ICMS
1495 32
        $total = $this->getTotais();
1496 32
        $icms = $dom->createElement('ICMSTot');
1497 32
        Util::appendNode($icms, 'vBC', Util::toCurrency($total['base']));
1498 32
        Util::appendNode($icms, 'vICMS', Util::toCurrency($total['icms']));
1499 32
        Util::appendNode($icms, 'vICMSDeson', Util::toCurrency($total['desoneracao']));
1500 32
        Util::appendNode($icms, 'vFCP', Util::toCurrency($total['fundo']));
1501 32
        Util::appendNode($icms, 'vBCST', Util::toCurrency($total['base.st']));
1502 32
        Util::appendNode($icms, 'vST', Util::toCurrency($total['icms.st']));
1503 32
        Util::appendNode($icms, 'vFCPST', Util::toCurrency($total['fundo.st']));
1504 32
        Util::appendNode($icms, 'vFCPSTRet', Util::toCurrency($total['fundo.retido.st']));
1505 32
        Util::appendNode($icms, 'vProd', Util::toCurrency($total['produtos']));
1506 32
        Util::appendNode($icms, 'vFrete', Util::toCurrency($total['frete']));
1507 32
        Util::appendNode($icms, 'vSeg', Util::toCurrency($total['seguro']));
1508 32
        Util::appendNode($icms, 'vDesc', Util::toCurrency($total['desconto']));
1509 32
        Util::appendNode($icms, 'vII', Util::toCurrency($total['ii']));
1510 32
        Util::appendNode($icms, 'vIPI', Util::toCurrency($total['ipi']));
1511 32
        Util::appendNode($icms, 'vIPIDevol', Util::toCurrency($total['ipi.devolvido']));
1512 32
        Util::appendNode($icms, 'vPIS', Util::toCurrency($total['pis']));
1513 32
        Util::appendNode($icms, 'vCOFINS', Util::toCurrency($total['cofins']));
1514 32
        Util::appendNode($icms, 'vOutro', Util::toCurrency($total['despesas']));
1515 32
        Util::appendNode($icms, 'vNF', Util::toCurrency($total['nota']));
1516 32
        Util::appendNode($icms, 'vTotTrib', Util::toCurrency($total['tributos']));
1517 32
        $element->appendChild($icms);
1518 32
        $this->setTotal(new Total($total));
1519 32
        $this->getTotal()->setProdutos($total['produtos']);
1520
1521
        // TODO: Totais referentes ao ISSQN
1522
1523
        // TODO: Retenção de Tributos Federais
1524 32
        return $element;
1525
    }
1526
1527 32
    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...
1528
    {
1529 32
        $this->getEmitente()->getEndereco()->checkCodigos();
1530 32
        $this->setID($this->gerarID());
1531 32
        $this->setDigitoVerificador(substr($this->getID(), -1, 1));
1532
1533 32
        $dom = new \DOMDocument('1.0', 'UTF-8');
1534 32
        $element = $dom->createElement(is_null($name)?'NFe':$name);
1535 32
        $element->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', self::PORTAL);
1536
1537 32
        $info = $dom->createElement('infNFe');
1538 32
        $id = $dom->createAttribute('Id');
1539 32
        $id->value = $this->getID(true);
1540 32
        $info->appendChild($id);
1541 32
        $versao = $dom->createAttribute('versao');
1542 32
        $versao->value = self::VERSAO;
1543 32
        $info->appendChild($versao);
1544
1545 32
        $municipio = $this->getEmitente()->getEndereco()->getMunicipio();
1546 32
        $estado = $municipio->getEstado();
1547 32
        $ident = $dom->createElement('ide');
1548 32
        Util::appendNode($ident, 'cUF', $estado->getCodigo(true));
1549 32
        Util::appendNode($ident, 'cNF', $this->getCodigo(true));
1550 32
        Util::appendNode($ident, 'natOp', $this->getNatureza(true));
1551 32
        Util::appendNode($ident, 'mod', $this->getModelo(true));
1552 32
        Util::appendNode($ident, 'serie', $this->getSerie(true));
1553 32
        Util::appendNode($ident, 'nNF', $this->getNumero(true));
1554 32
        Util::appendNode($ident, 'dhEmi', $this->getDataEmissao(true));
1555 32
        Util::appendNode($ident, 'tpNF', $this->getTipo(true));
1556 32
        Util::appendNode($ident, 'idDest', $this->getDestino(true));
1557 32
        Util::appendNode($ident, 'cMunFG', $municipio->getCodigo(true));
1558 32
        Util::appendNode($ident, 'tpImp', $this->getFormato(true));
1559 32
        Util::appendNode($ident, 'tpEmis', $this->getEmissao(true));
1560 32
        Util::appendNode($ident, 'cDV', $this->getDigitoVerificador(true));
1561 32
        Util::appendNode($ident, 'tpAmb', $this->getAmbiente(true));
1562 32
        Util::appendNode($ident, 'finNFe', $this->getFinalidade(true));
1563 32
        Util::appendNode($ident, 'indFinal', $this->getConsumidorFinal(true));
1564 32
        Util::appendNode($ident, 'indPres', $this->getPresenca(true));
1565 32
        Util::appendNode($ident, 'procEmi', 0); // emissão de NF-e com aplicativo do contribuinte
1566 32
        Util::appendNode($ident, 'verProc', self::APP_VERSAO);
1567 32
        if (!is_null($this->getDataMovimentacao())) {
1568
            Util::appendNode($ident, 'dhSaiEnt', $this->getDataMovimentacao(true));
1569
        }
1570 32
        if ($this->getEmissao() != self::EMISSAO_NORMAL) {
1571
            Util::appendNode($ident, 'dhCont', $this->getDataContingencia(true));
1572
            Util::appendNode($ident, 'xJust', $this->getJustificativa(true));
1573
        }
1574 32
        $info->appendChild($ident);
1575
1576 32
        $emitente = $this->getEmitente()->getNode();
1577 32
        $emitente = $dom->importNode($emitente, true);
1578 32
        $info->appendChild($emitente);
1579 32
        if ($this->getAmbiente() == self::AMBIENTE_HOMOLOGACAO && !is_null($this->getDestinatario())) {
1580 32
            $this->getDestinatario()->setNome('NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL');
1581
        }
1582 32
        if (!is_null($this->getDestinatario())) {
1583 32
            $destinatario = $this->getDestinatario()->getNode();
1584 32
            $destinatario = $dom->importNode($destinatario, true);
1585 32
            $info->appendChild($destinatario);
1586
        }
1587 32
        $item = 0;
1588 32
        $tributos = [];
1589 32
        $_produtos = $this->getProdutos();
1590 32
        foreach ($_produtos as $_produto) {
1591 32
            if (is_null($_produto->getItem())) {
1592 6
                $item += 1;
1593 6
                $_produto->setItem($item);
1594
            } else {
1595 26
                $item = $_produto->getItem();
1596
            }
1597 32
            if ($this->getAmbiente() == self::AMBIENTE_HOMOLOGACAO) {
1598 32
                $_produto->setDescricao('NOTA FISCAL EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL');
1599
            }
1600 32
            $produto = $_produto->getNode();
1601 32
            $produto = $dom->importNode($produto, true);
1602 32
            $info->appendChild($produto);
1603
            // Soma os tributos aproximados dos produtos
1604 32
            $imposto_info = $_produto->getImpostoInfo();
1605 32
            $tributos['info'] = $imposto_info['info'];
1606 32
            foreach ($imposto_info as $key => $value) {
1607 32
                if (!is_numeric($value)) {
1608 32
                    continue;
1609
                }
1610 32
                if (!isset($tributos[$key])) {
1611 32
                    $tributos[$key] = 0.00;
1612
                }
1613 32
                $tributos[$key] += $value;
1614
            }
1615
        }
1616 32
        $total = $this->getNodeTotal();
1617 32
        $total = $dom->importNode($total, true);
1618 32
        $info->appendChild($total);
1619 32
        $transporte = $this->getTransporte()->getNode();
1620 32
        $transporte = $dom->importNode($transporte, true);
1621 32
        $info->appendChild($transporte);
1622
        // TODO: adicionar cobrança
1623 32
        $pag = $dom->createElement('pag');
1624 32
        $_pagamentos = $this->getPagamentos();
1625 32
        foreach ($_pagamentos as $_pagamento) {
1626 31
            $pagamento = $_pagamento->getNode();
1627 31
            $pagamento = $dom->importNode($pagamento, true);
1628 31
            $pag->appendChild($pagamento);
1629
        }
1630 32
        $info->appendChild($pag);
1631 32
        $info_adic = $dom->createElement('infAdic');
1632 32
        if (!is_null($this->getAdicionais())) {
1633
            Util::appendNode($info_adic, 'infAdFisco', $this->getAdicionais(true));
1634
        }
1635
        // TODO: adicionar informações adicionais somente na NFC-e?
1636 32
        $_complemento = Produto::addNodeInformacoes($tributos, $info_adic, 'infCpl');
1637 32
        $this->getTotal()->setComplemento($_complemento);
1638 32
        if (!is_null($this->getObservacoes())) {
1639 32
            $_observacoes = $this->getObservacoes();
1640 32
            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...
1641 32
                $observacoes = $dom->createElement('obsCont');
1642 32
                Util::addAttribute($observacoes, 'xCampo', $_observacao['campo']);
1643 32
                Util::appendNode($observacoes, 'xTexto', $_observacao['valor']);
1644 32
                $info_adic->appendChild($observacoes);
1645
            }
1646
        }
1647 32
        if (!is_null($this->getInformacoes())) {
1648 32
            $_informacoes = $this->getInformacoes();
1649 32
            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...
1650 32
                $informacoes = $dom->createElement('obsFisco');
1651 32
                Util::addAttribute($informacoes, 'xCampo', $_informacao['campo']);
1652 32
                Util::appendNode($informacoes, 'xTexto', $_informacao['valor']);
1653 32
                $info_adic->appendChild($informacoes);
1654
            }
1655
        }
1656 32
        $info->appendChild($info_adic);
1657
        // TODO: adicionar exportação
1658
        // TODO: adicionar compra
1659
        // TODO: adicionar cana
1660 32
        $element->appendChild($info);
1661 32
        $dom->appendChild($element);
1662 32
        return $element;
1663
    }
1664
1665 26
    public function loadNode($element, $name = null)
0 ignored issues
show
Complexity introduced by
This operation has 215040 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...
1666
    {
1667 26
        if (is_null($element)) {
1668
            throw new \Exception("Nota com XML mal formado ou vazio", 500);
1669
        }
1670 26
        $root = $element;
1671 26
        $name = is_null($name)?'NFe':$name;
1672 26
        if ($element->nodeName != $name) {
1673 3
            $_fields = $element->getElementsByTagName($name);
1674 3
            if ($_fields->length == 0) {
1675
                throw new \Exception('Tag "'.$name.'" não encontrada', 404);
1676
            }
1677 3
            $element = $_fields->item(0);
1678
        }
1679 26
        $_fields = $element->getElementsByTagName('infNFe');
1680 26
        if ($_fields->length > 0) {
1681 26
            $info = $_fields->item(0);
1682
        } else {
1683
            throw new \Exception('Tag "infNFe" não encontrada', 404);
1684
        }
1685 26
        $id = $info->getAttribute('Id');
1686 26
        if (strlen($id) != 47) {
1687
            throw new \Exception('Atributo "Id" inválido, encontrado: "'.$id.'"', 500);
1688
        }
1689 26
        $this->setID(substr($id, 3));
1690 26
        $_fields = $info->getElementsByTagName('ide');
1691 26
        if ($_fields->length > 0) {
1692 26
            $ident = $_fields->item(0);
1693
        } else {
1694
            throw new \Exception('Tag "ide" não encontrada', 404);
1695
        }
1696 26
        $emitente = new Emitente();
1697 26
        $emitente->getEndereco()->getMunicipio()->getEstado()->setCodigo(
1698 26
            Util::loadNode(
1699 26
                $ident,
1700 26
                'cUF',
1701 26
                'Tag "cUF" do campo "Codigo IBGE da UF" não encontrada'
1702
            )
1703
        );
1704 26
        $this->setCodigo(
1705 26
            Util::loadNode(
1706 26
                $ident,
1707 26
                'cNF',
1708 26
                'Tag "cNF" do campo "Codigo" não encontrada'
1709
            )
1710
        );
1711 26
        $this->setNatureza(
1712 26
            Util::loadNode(
1713 26
                $ident,
1714 26
                'natOp',
1715 26
                'Tag "natOp" do campo "Natureza" não encontrada'
1716
            )
1717
        );
1718 26
        $this->setModelo(
1719 26
            Util::loadNode(
1720 26
                $ident,
1721 26
                'mod',
1722 26
                'Tag "mod" do campo "Modelo" não encontrada'
1723
            )
1724
        );
1725 26
        $this->setSerie(
1726 26
            Util::loadNode(
1727 26
                $ident,
1728 26
                'serie',
1729 26
                'Tag "serie" do campo "Serie" não encontrada'
1730
            )
1731
        );
1732 26
        $this->setNumero(
1733 26
            Util::loadNode(
1734 26
                $ident,
1735 26
                'nNF',
1736 26
                'Tag "nNF" do campo "Numero" não encontrada'
1737
            )
1738
        );
1739 26
        $this->setDataEmissao(
1740 26
            Util::loadNode(
1741 26
                $ident,
1742 26
                'dhEmi',
1743 26
                'Tag "dhEmi" do campo "DataEmissao" não encontrada'
1744
            )
1745
        );
1746 26
        $this->setTipo(
1747 26
            Util::loadNode(
1748 26
                $ident,
1749 26
                'tpNF',
1750 26
                'Tag "tpNF" do campo "Tipo" não encontrada'
1751
            )
1752
        );
1753 26
        $this->setDestino(
1754 26
            Util::loadNode(
1755 26
                $ident,
1756 26
                'idDest',
1757 26
                'Tag "idDest" do campo "Destino" não encontrada'
1758
            )
1759
        );
1760 26
        $emitente->getEndereco()->getMunicipio()->setCodigo(
1761 26
            Util::loadNode(
1762 26
                $ident,
1763 26
                'cMunFG',
1764 26
                'Tag "cMunFG" do campo "Codigo IBGE do município" não encontrada'
1765
            )
1766
        );
1767 26
        $this->setDataMovimentacao(Util::loadNode($ident, 'dhSaiEnt'));
1768 26
        $this->setFormato(
1769 26
            Util::loadNode(
1770 26
                $ident,
1771 26
                'tpImp',
1772 26
                'Tag "tpImp" do campo "Formato" não encontrada'
1773
            )
1774
        );
1775 26
        $this->setEmissao(
1776 26
            Util::loadNode(
1777 26
                $ident,
1778 26
                'tpEmis',
1779 26
                'Tag "tpEmis" do campo "Emissao" não encontrada'
1780
            )
1781
        );
1782 26
        $this->setDigitoVerificador(
1783 26
            Util::loadNode(
1784 26
                $ident,
1785 26
                'cDV',
1786 26
                'Tag "cDV" do campo "DigitoVerificador" não encontrada'
1787
            )
1788
        );
1789 26
        $this->setAmbiente(
1790 26
            Util::loadNode(
1791 26
                $ident,
1792 26
                'tpAmb',
1793 26
                'Tag "tpAmb" do campo "Ambiente" não encontrada'
1794
            )
1795
        );
1796 26
        $this->setFinalidade(
1797 26
            Util::loadNode(
1798 26
                $ident,
1799 26
                'finNFe',
1800 26
                'Tag "finNFe" do campo "Finalidade" não encontrada'
1801
            )
1802
        );
1803 26
        $this->setConsumidorFinal(
1804 26
            Util::loadNode(
1805 26
                $ident,
1806 26
                'indFinal',
1807 26
                'Tag "indFinal" do campo "ConsumidorFinal" não encontrada'
1808
            )
1809
        );
1810 26
        $this->setPresenca(
1811 26
            Util::loadNode(
1812 26
                $ident,
1813 26
                'indPres',
1814 26
                'Tag "indPres" do campo "Presenca" não encontrada'
1815
            )
1816
        );
1817 26
        $this->setDataContingencia(Util::loadNode($ident, 'dhCont'));
1818 26
        $this->setJustificativa(Util::loadNode($ident, 'xJust'));
1819 26
        $emitente->loadNode(
1820 26
            Util::findNode(
1821 26
                $info,
1822 26
                'emit',
1823 26
                'Tag "emit" do objeto "Emitente" não encontrada'
1824
            ),
1825 26
            'emit'
1826
        );
1827 26
        $this->setEmitente($emitente);
1828 26
        $_fields = $info->getElementsByTagName('dest');
1829 26
        $destinatario = null;
1830 26
        if ($_fields->length > 0) {
1831 26
            $destinatario = new Destinatario();
1832 26
            $destinatario->loadNode($_fields->item(0), 'dest');
1833
        }
1834 26
        $this->setDestinatario($destinatario);
1835 26
        $produtos = [];
1836 26
        $_items = $info->getElementsByTagName('det');
1837 26
        foreach ($_items as $_item) {
1838 26
            $produto = new Produto();
1839 26
            $produto->loadNode($_item, 'det');
1840 26
            $produtos[] = $produto;
1841
        }
1842 26
        $this->setProdutos($produtos);
1843 26
        $_fields = $info->getElementsByTagName('transp');
1844 26
        $transporte = null;
1845 26
        if ($_fields->length > 0) {
1846 26
            $transporte = new Transporte();
1847 26
            $transporte->loadNode($_fields->item(0), 'transp');
1848
        }
1849 26
        $this->setTransporte($transporte);
1850 26
        $pagamentos = [];
1851 26
        $_items = $info->getElementsByTagName('pag');
1852 26
        foreach ($_items as $_item) {
1853 26
            $_det_items = $_item->getElementsByTagName('detPag');
1854 26
            foreach ($_det_items as $_det_item) {
1855 26
                $pagamento = new Pagamento();
1856 26
                $pagamento->loadNode($_det_item, 'detPag');
1857 26
                $pagamentos[] = $pagamento;
1858
            }
1859 26
            if (Util::nodeExists($_item, 'vTroco')) {
1860 1
                $pagamento = new Pagamento();
1861 1
                $pagamento->loadNode($_item, 'vTroco');
1862 1
                if ($pagamento->getValor() < 0) {
1863 26
                    $pagamentos[] = $pagamento;
1864
                }
1865
            }
1866
        }
1867 26
        $this->setPagamentos($pagamentos);
1868 26
        $_fields = $info->getElementsByTagName('total');
1869 26
        if ($_fields->length > 0) {
1870 26
            $total = new Total();
1871 26
            $total->loadNode($_fields->item(0), 'total');
1872 26
            $total->setComplemento(Util::loadNode($info, 'infCpl'));
1873
        } else {
1874
            throw new \Exception('Tag "total" do objeto "Total" não encontrada na Nota', 404);
1875
        }
1876 26
        $this->setTotal($total);
1877 26
        $this->setAdicionais(Util::loadNode($info, 'infAdFisco'));
1878 26
        $observacoes = [];
1879 26
        $_items = $info->getElementsByTagName('obsCont');
1880 26
        foreach ($_items as $_item) {
1881
            $observacao = [
1882 26
                'campo' => $_item->getAttribute('xCampo'),
1883 26
                'valor' => Util::loadNode(
1884 26
                    $_item,
1885 26
                    'xTexto',
1886 26
                    'Tag "xTexto" do campo "Observação" não encontrada'
1887
                )
1888
            ];
1889 26
            $observacoes[] = $observacao;
1890
        }
1891 26
        $this->setObservacoes($observacoes);
1892 26
        $informacoes = [];
1893 26
        $_items = $info->getElementsByTagName('obsFisco');
1894 26
        foreach ($_items as $_item) {
1895
            $informacao = [
1896 26
                'campo' => $_item->getAttribute('xCampo'),
1897 26
                'valor' => Util::loadNode(
1898 26
                    $_item,
1899 26
                    'xTexto',
1900 26
                    'Tag "xTexto" do campo "Informação" não encontrada'
1901
                )
1902
            ];
1903 26
            $informacoes[] = $informacao;
1904
        }
1905 26
        $this->setInformacoes($informacoes);
1906
1907 26
        $_fields = $root->getElementsByTagName('protNFe');
1908 26
        $protocolo = null;
1909 26
        if ($_fields->length > 0) {
1910 2
            $protocolo = new Protocolo();
1911 2
            $protocolo->loadNode($_fields->item(0), 'infProt');
1912
        }
1913 26
        $this->setProtocolo($protocolo);
1914 26
        return $element;
1915
    }
1916
1917
    /**
1918
     * Carrega um arquivo XML e preenche a nota com as informações dele
1919
     * @param  string $filename caminho do arquivo
1920
     * @return DOMDocument      objeto do documento carregado
1921
     */
1922 25
    public function load($filename)
1923
    {
1924 25
        $dom = new \DOMDocument();
1925 25
        if (!file_exists($filename)) {
1926
            throw new \Exception('Arquivo XML "'.$filename.'" não encontrado', 404);
1927
        }
1928 25
        $dom->load($filename);
1929 25
        $this->loadNode($dom->documentElement);
1930 25
        return $dom;
1931
    }
1932
1933
    /**
1934
     * Assina o XML com a assinatura eletrônica do tipo A1
1935
     */
1936 29
    public function assinar($dom = null)
1937
    {
1938 29
        if (is_null($dom)) {
1939 25
            $xml = $this->getNode();
1940 25
            $dom = $xml->ownerDocument;
1941
        }
1942 29
        $config = SEFAZ::getInstance()->getConfiguracao();
1943 29
        $config->verificaValidadeCertificado();
1944
1945 29
        $adapter = new XmlseclibsAdapter();
1946 29
        $adapter->setPrivateKey($config->getChavePrivada());
1947 29
        $adapter->setPublicKey($config->getChavePublica());
1948 29
        $adapter->addTransform(AdapterInterface::ENVELOPED);
1949 29
        $adapter->addTransform(AdapterInterface::XML_C14N);
1950 29
        $adapter->sign($dom, 'infNFe');
1951 29
        return $dom;
1952
    }
1953
1954
    /**
1955
     * Valida o documento após assinar
1956
     */
1957 27
    public function validar($dom)
1958
    {
1959 27
        $dom->loadXML($dom->saveXML());
1960 27
        $xsd_path = __DIR__ . '/schema';
1961 27
        if (is_null($this->getProtocolo())) {
1962 27
            $xsd_file = $xsd_path . '/nfe_v'.self::VERSAO.'.xsd';
1963
        } else {
1964
            $xsd_file = $xsd_path . '/procNFe_v'.self::VERSAO.'.xsd';
1965
        }
1966 27
        if (!file_exists($xsd_file)) {
1967
            throw new \Exception(sprintf('O arquivo "%s" de esquema XSD não existe!', $xsd_file), 404);
1968
        }
1969
        // Enable user error handling
1970 27
        $save = libxml_use_internal_errors(true);
1971 27
        if ($dom->schemaValidate($xsd_file)) {
1972
            libxml_use_internal_errors($save);
1973
            return $dom;
1974
        }
1975 27
        $msg = [];
1976 27
        $errors = libxml_get_errors();
1977 27
        foreach ($errors as $error) {
1978 27
            $msg[] = 'Não foi possível validar o XML: '.$error->message;
1979
        }
1980 27
        libxml_clear_errors();
1981 27
        libxml_use_internal_errors($save);
1982 27
        throw new ValidationException($msg);
1983
    }
1984
1985
    /**
1986
     * Adiciona o protocolo no XML da nota
1987
     */
1988
    public function addProtocolo($dom)
1989
    {
1990
        if (is_null($this->getProtocolo())) {
1991
            throw new \Exception('O protocolo não foi informado na nota "'.$this->getID().'"', 404);
1992
        }
1993
        $notae = $dom->getElementsByTagName('NFe')->item(0);
1994
        // Corrige xmlns:default
1995
        $notae_xml = $dom->saveXML($notae);
1996
1997
        $element = $dom->createElement('nfeProc');
1998
        $element->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', self::PORTAL);
1999
        $versao = $dom->createAttribute('versao');
2000
        $versao->value = self::VERSAO;
2001
        $element->appendChild($versao);
2002
        $dom->removeChild($notae);
2003
        // Corrige xmlns:default
2004
        $notae = $dom->createElement('NFe', 0);
2005
2006
        $element->appendChild($notae);
2007
        $info = $this->getProtocolo()->getNode();
2008
        $info = $dom->importNode($info, true);
2009
        $element->appendChild($info);
2010
        $dom->appendChild($element);
2011
        // Corrige xmlns:default
2012
        $xml = $dom->saveXML();
2013
        $xml = str_replace('<NFe>0</NFe>', $notae_xml, $xml);
2014
        $dom->loadXML($xml);
2015
2016
        return $dom;
2017
    }
2018
}
2019