Test Failed
Push — master ( 8feb3a...b0108d )
by
unknown
18:09
created

Nota::getDataContingencia()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

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

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1990 29
        $adapter->setPublicKey($config->getChavePublica());
0 ignored issues
show
Deprecated Code introduced by
The method NFe\Common\Configuracao::getChavePublica() has been deprecated with message: Use getCertificado()->getChavePublica

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
1991 29
        $adapter->addTransform(AdapterInterface::ENVELOPED);
1992 29
        $adapter->addTransform(AdapterInterface::XML_C14N);
1993 29
        $adapter->sign($dom, 'infNFe');
1994 29
        return $dom;
1995
    }
1996
1997
    /**
1998
     * Valida o documento após assinar
1999
     */
2000 27
    public function validar($dom)
2001
    {
2002 27
        $dom->loadXML($dom->saveXML());
2003 27
        $xsd_path = __DIR__ . '/schema';
2004 27
        if (is_null($this->getProtocolo())) {
2005 27
            $xsd_file = $xsd_path . '/nfe_v'.self::VERSAO.'.xsd';
2006
        } else {
2007
            $xsd_file = $xsd_path . '/procNFe_v'.self::VERSAO.'.xsd';
2008
        }
2009 27
        if (!file_exists($xsd_file)) {
2010
            throw new \Exception(sprintf('O arquivo "%s" de esquema XSD não existe!', $xsd_file), 404);
2011
        }
2012
        // Enable user error handling
2013 27
        $save = libxml_use_internal_errors(true);
2014 27
        if ($dom->schemaValidate($xsd_file)) {
2015 27
            libxml_use_internal_errors($save);
2016 27
            return $dom;
2017
        }
2018
        $msg = [];
2019
        $errors = libxml_get_errors();
2020
        foreach ($errors as $error) {
2021
            $msg[] = 'Não foi possível validar o XML: '.$error->message;
2022
        }
2023
        libxml_clear_errors();
2024
        libxml_use_internal_errors($save);
2025
        throw new ValidationException($msg);
2026
    }
2027
2028
    /**
2029
     * Adiciona o protocolo no XML da nota
2030
     */
2031 4
    public function addProtocolo($dom)
2032
    {
2033 4
        if (is_null($this->getProtocolo())) {
2034
            throw new \Exception('O protocolo não foi informado na nota "'.$this->getID().'"', 404);
2035
        }
2036 4
        $notae = $dom->getElementsByTagName('NFe')->item(0);
2037
        // Corrige xmlns:default
2038 4
        $notae_xml = $dom->saveXML($notae);
2039
2040 4
        $element = $dom->createElement('nfeProc');
2041 4
        $element->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', self::PORTAL);
2042 4
        $versao = $dom->createAttribute('versao');
2043 4
        $versao->value = self::VERSAO;
2044 4
        $element->appendChild($versao);
2045 4
        $dom->removeChild($notae);
2046
        // Corrige xmlns:default
2047 4
        $notae = $dom->createElement('NFe', 0);
2048
2049 4
        $element->appendChild($notae);
2050 4
        $info = $this->getProtocolo()->getNode();
2051 4
        $info = $dom->importNode($info, true);
2052 4
        $element->appendChild($info);
2053 4
        $dom->appendChild($element);
2054
        // Corrige xmlns:default
2055 4
        $xml = $dom->saveXML();
2056 4
        $xml = str_replace('<NFe>0</NFe>', $notae_xml, $xml);
2057 4
        $dom->loadXML($xml);
2058
2059 4
        return $dom;
2060
    }
2061
}
2062