Passed
Push — master ( c1d1cf...f48ccd )
by Francimar
03:58
created

Nota::isConsumidorFinal()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * MIT License
4
 *
5
 * Copyright (c) 2016 MZ Desenvolvimento de Sistemas LTDA
6
 *
7
 * @author Francimar Alves <[email protected]>
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy
10
 * of this software and associated documentation files (the "Software"), to deal
11
 * in the Software without restriction, including without limitation the rights
12
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
 * copies of the Software, and to permit persons to whom the Software is
14
 * furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in all
17
 * copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
 * SOFTWARE.
26
 *
27
 */
28
namespace NFe\Core;
29
30
use NFe\Common\Util;
31
use NFe\Common\Node;
32
use NFe\Task\Protocolo;
33
use NFe\Entity\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 75 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
The class Nota has a coupling between objects value of 20. Consider to reduce the number of dependencies under 13.
Loading history...
Complexity introduced by
This class has 2021 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 a complexity of 278 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...
48
{
49
50
    /**
51
     * Versão da nota fiscal
52
     */
53
    const VERSAO = '3.10';
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
     * Indicador da forma de pagamento: 0 – pagamento à vista; 1 – pagamento à
87
     * prazo; 2 – outros.
88
     */
89
    const INDICADOR_AVISTA = 'avista';
90
    const INDICADOR_APRAZO = 'aprazo';
91
    const INDICADOR_OUTROS = 'outros';
92
93
    /**
94
     * Formato de impressão do DANFE (0-sem DANFE;1-DANFe Retrato; 2-DANFe
95
     * Paisagem;3-DANFe Simplificado;4-DANFe NFC-e;5-DANFe NFC-e em mensagem
96
     * eletrônica)
97
     */
98
    const FORMATO_NENHUMA = 'nenhuma';
99
    const FORMATO_RETRATO = 'retrato';
100
    const FORMATO_PAISAGEM = 'paisagem';
101
    const FORMATO_SIMPLIFICADO = 'simplificado';
102
    const FORMATO_CONSUMIDOR = 'consumidor';
103
    const FORMATO_MENSAGEM = 'mensagem';
104
105
    /**
106
     * Forma de emissão da NF-e
107
     */
108
    const EMISSAO_NORMAL = 'normal';
109
    const EMISSAO_CONTINGENCIA = 'contingencia';
110
111
    /**
112
     * Identificação do Ambiente: 1 - Produção, 2 - Homologação
113
     */
114
    const AMBIENTE_PRODUCAO = 'producao';
115
    const AMBIENTE_HOMOLOGACAO = 'homologacao';
116
117
    /**
118
     * Finalidade da emissão da NF-e: 1 - NFe normal, 2 - NFe complementar, 3 -
119
     * NFe de ajuste, 4 - Devolução/Retorno
120
     */
121
    const FINALIDADE_NORMAL = 'normal';
122
    const FINALIDADE_COMPLEMENTAR = 'complementar';
123
    const FINALIDADE_AJUSTE = 'ajuste';
124
    const FINALIDADE_RETORNO = 'retorno';
125
126
    /**
127
     * Indicador de presença do comprador no estabelecimento comercial no
128
     * momento da oepração (0-Não se aplica, ex.: Nota Fiscal complementar ou
129
     * de ajuste;1-Operação presencial;2-Não presencial, internet;3-Não
130
     * presencial, teleatendimento;4-NFC-e entrega em domicílio;9-Não
131
     * presencial, outros)
132
     */
133
    const PRESENCA_NENHUM = 'nenhum';
134
    const PRESENCA_PRESENCIAL = 'presencial';
135
    const PRESENCA_INTERNET = 'internet';
136
    const PRESENCA_TELEATENDIMENTO = 'teleatendimento';
137
    const PRESENCA_ENTREGA = 'entrega';
138
    const PRESENCA_OUTROS = 'outros';
139
140
    /**
141
     * Chave da nota fiscal
142
     */
143
    private $id;
144
    /**
145
     * Número do Documento Fiscal
146
     */
147
    private $numero;
148
    /**
149
     * Emitente da nota fiscal
150
     */
151
    private $emitente;
152
    /**
153
     * Destinatário que receberá os produtos
154
     */
155
    private $destinatario;
156
    /**
157
     * Produtos adicionados na nota
158
     */
159
    private $produtos;
160
    /**
161
     * Informações de trasnporte da mercadoria
162
     */
163
    private $transporte;
164
    /**
165
     * Pagamentos realizados
166
     */
167
    private $pagamentos;
168
    /**
169
     * Data e Hora da saída ou de entrada da mercadoria / produto
170
     */
171
    private $data_movimentacao;
172
    /**
173
     * Informar a data e hora de entrada em contingência
174
     */
175
    private $data_contingencia;
176
    /**
177
     * Informar a Justificativa da entrada em contingência
178
     */
179
    private $justificativa;
180
    /**
181
     * Código do modelo do Documento Fiscal. 55 = NF-e; 65 = NFC-e.
182
     */
183
    private $modelo;
184
    /**
185
     * Tipo do Documento Fiscal (0 - entrada; 1 - saída)
186
     */
187
    private $tipo;
188
    /**
189
     * Identificador de Local de destino da operação
190
     * (1-Interna;2-Interestadual;3-Exterior)
191
     */
192
    private $destino;
193
    /**
194
     * Descrição da Natureza da Operação
195
     */
196
    private $natureza;
197
    /**
198
     * Código numérico que compõe a Chave de Acesso. Número aleatório gerado
199
     * pelo emitente para cada NF-e.
200
     */
201
    private $codigo;
202
    /**
203
     * Indicador da forma de pagamento: 0 – pagamento à vista; 1 – pagamento à
204
     * prazo; 2 – outros.
205
     */
206
    private $indicador;
207
    /**
208
     * Data e Hora de emissão do Documento Fiscal
209
     */
210
    private $data_emissao;
211
    /**
212
     * Série do Documento Fiscal: série normal 0-889, Avulsa Fisco 890-899,
213
     * SCAN 900-999
214
     */
215
    private $serie;
216
    /**
217
     * Formato de impressão do DANFE (0-sem DANFE;1-DANFe Retrato; 2-DANFe
218
     * Paisagem;3-DANFe Simplificado;4-DANFe NFC-e;5-DANFe NFC-e em mensagem
219
     * eletrônica)
220
     */
221
    private $formato;
222
    /**
223
     * Forma de emissão da NF-e
224
     */
225
    private $emissao;
226
    /**
227
     * Digito Verificador da Chave de Acesso da NF-e
228
     */
229
    private $digito_verificador;
230
    /**
231
     * Identificação do Ambiente: 1 - Produção, 2 - Homologação
232
     */
233
    private $ambiente;
234
    /**
235
     * Finalidade da emissão da NF-e: 1 - NFe normal, 2 - NFe complementar, 3 -
236
     * NFe de ajuste, 4 - Devolução/Retorno
237
     */
238
    private $finalidade;
239
    /**
240
     * Indica operação com consumidor final (0-Não;1-Consumidor Final)
241
     */
242
    private $consumidor_final;
243
    /**
244
     * Indicador de presença do comprador no estabelecimento comercial no
245
     * momento da oepração (0-Não se aplica, ex.: Nota Fiscal complementar ou
246
     * de ajuste;1-Operação presencial;2-Não presencial, internet;3-Não
247
     * presencial, teleatendimento;4-NFC-e entrega em domicílio;9-Não
248
     * presencial, outros)
249
     */
250
    private $presenca;
251
    /**
252
     * Dados dos totais da NF-e
253
     */
254
    private $total;
255
    /**
256
     * Informações adicionais de interesse do Fisco
257
     */
258
    private $adicionais;
259
    /**
260
     * Campo de uso livre do contribuinte informar o nome do campo no atributo
261
     * xCampo e o conteúdo do campo no xTexto
262
     */
263
    private $observacoes;
264
    /**
265
     * Campo de uso exclusivo do Fisco informar o nome do campo no atributo
266
     * xCampo e o conteúdo do campo no xTexto
267
     */
268
    private $informacoes;
269
    /**
270
     * Protocolo de autorização da nota, informado apenas quando a nota for
271
     * enviada e autorizada
272
     */
273
    private $protocolo;
274
275
    /**
276
     * Constroi uma instância de Nota vazia
277
     * @param  array $nota Array contendo dados da Nota
278
     */
279 27
    public function __construct($nota = array())
280
    {
281 27
        $this->fromArray($nota);
282 27
    }
283
284
    /**
285
     * Chave da nota fiscal
286
     * @param boolean $normalize informa se o id deve estar no formato do XML
287
     * @return mixed id da Nota
288
     */
289 25
    public function getID($normalize = false)
290
    {
291 25
        if (!$normalize) {
292 25
            return $this->id;
293
        }
294 25
        return 'NFe'.$this->id;
295
    }
296
297
    /**
298
     * Altera o valor do ID para o informado no parâmetro
299
     * @param mixed $id novo valor para ID
300
     * @return Nota A própria instância da classe
301
     */
302 27
    public function setID($id)
303
    {
304 27
        $this->id = $id;
305 27
        return $this;
306
    }
307
308
    /**
309
     * Número do Documento Fiscal
310
     * @param boolean $normalize informa se o numero deve estar no formato do XML
311
     * @return mixed numero da Nota
312
     */
313 25
    public function getNumero($normalize = false)
314
    {
315 25
        if (!$normalize) {
316 25
            return $this->numero;
317
        }
318 25
        return $this->numero;
319
    }
320
321
    /**
322
     * Altera o valor do Numero para o informado no parâmetro
323
     * @param mixed $numero novo valor para Numero
324
     * @return Nota A própria instância da classe
325
     */
326 27
    public function setNumero($numero)
327
    {
328 27
        $this->numero = $numero;
329 27
        return $this;
330
    }
331
332
    /**
333
     * Emitente da nota fiscal
334
     * @return mixed emitente da Nota
335
     */
336 25
    public function getEmitente()
337
    {
338 25
        return $this->emitente;
339
    }
340
341
    /**
342
     * Altera o valor do Emitente para o informado no parâmetro
343
     * @param mixed $emitente novo valor para Emitente
344
     * @return Nota A própria instância da classe
345
     */
346 27
    public function setEmitente($emitente)
347
    {
348 27
        $this->emitente = $emitente;
349 27
        return $this;
350
    }
351
352
    /**
353
     * Destinatário que receberá os produtos
354
     * @return mixed destinatario da Nota
355
     */
356 25
    public function getDestinatario()
357
    {
358 25
        return $this->destinatario;
359
    }
360
361
    /**
362
     * Altera o valor do Destinatario para o informado no parâmetro
363
     * @param mixed $destinatario novo valor para Destinatario
364
     * @return Nota A própria instância da classe
365
     */
366 27
    public function setDestinatario($destinatario)
367
    {
368 27
        $this->destinatario = $destinatario;
369 27
        return $this;
370
    }
371
372
    /**
373
     * Produtos adicionados na nota
374
     * @return mixed produtos da Nota
375
     */
376 25
    public function getProdutos()
377
    {
378 25
        return $this->produtos;
379
    }
380
381
    /**
382
     * Altera o valor do Produtos para o informado no parâmetro
383
     * @param mixed $produtos novo valor para Produtos
384
     * @return Nota A própria instância da classe
385
     */
386 27
    public function setProdutos($produtos)
387
    {
388 27
        $this->produtos = $produtos;
389 27
        return $this;
390
    }
391
392
    /**
393
     * Adiciona um(a) Produto para a lista de produto
394
     * @param Produto $produto Instância do Produto que será adicionada
395
     * @return Nota A própria instância da classe
396
     */
397 2
    public function addProduto($produto)
398
    {
399 2
        $this->produtos[] = $produto;
400 2
        return $this;
401
    }
402
403
    /**
404
     * Informações de trasnporte da mercadoria
405
     * @return mixed transporte da Nota
406
     */
407 25
    public function getTransporte()
408
    {
409 25
        return $this->transporte;
410
    }
411
412
    /**
413
     * Altera o valor da Transporte para o informado no parâmetro
414
     * @param mixed $transporte novo valor para Transporte
415
     * @return Nota A própria instância da classe
416
     */
417 27
    public function setTransporte($transporte)
418
    {
419 27
        $this->transporte = $transporte;
420 27
        return $this;
421
    }
422
423
    /**
424
     * Pagamentos realizados
425
     * @return mixed pagamentos da Nota
426
     */
427 25
    public function getPagamentos()
428
    {
429 25
        return $this->pagamentos;
430
    }
431
432
    /**
433
     * Altera o valor do Pagamentos para o informado no parâmetro
434
     * @param mixed $pagamentos novo valor para Pagamentos
435
     * @return Nota A própria instância da classe
436
     */
437 27
    public function setPagamentos($pagamentos)
438
    {
439 27
        $this->pagamentos = $pagamentos;
440 27
        return $this;
441
    }
442
443
    /**
444
     * Adiciona um(a) Pagamento para a lista de pagamento
445
     * @param Pagamento $pagamento Instância do Pagamento que será adicionada
446
     * @return Nota A própria instância da classe
447
     */
448 2
    public function addPagamento($pagamento)
449
    {
450 2
        $this->pagamentos[] = $pagamento;
451 2
        return $this;
452
    }
453
454
    /**
455
     * Data e Hora da saída ou de entrada da mercadoria / produto
456
     * @param boolean $normalize informa se a data_movimentacao deve estar no formato do XML
457
     * @return mixed data_movimentacao da Nota
458
     */
459 25
    public function getDataMovimentacao($normalize = false)
460
    {
461 25
        if (!$normalize || is_null($this->data_movimentacao)) {
462 25
            return $this->data_movimentacao;
463
        }
464
        return Util::toDateTime($this->data_movimentacao);
465
    }
466
467
    /**
468
     * Altera o valor da DataMovimentacao para o informado no parâmetro
469
     * @param mixed $data_movimentacao novo valor para DataMovimentacao
470
     * @return Nota A própria instância da classe
471
     */
472 27
    public function setDataMovimentacao($data_movimentacao)
473
    {
474 27
        if (!is_null($data_movimentacao) && !is_numeric($data_movimentacao)) {
475
            $data_movimentacao = strtotime($data_movimentacao);
476
        }
477 27
        $this->data_movimentacao = $data_movimentacao;
478 27
        return $this;
479
    }
480
481
    /**
482
     * Informar a data e hora de entrada em contingência
483
     * @param boolean $normalize informa se a data_contingencia deve estar no formato do XML
484
     * @return mixed data_contingencia da Nota
485
     */
486 3
    public function getDataContingencia($normalize = false)
487
    {
488 3
        if (!$normalize || is_null($this->data_contingencia)) {
489 3
            return $this->data_contingencia;
490
        }
491
        return Util::toDateTime($this->data_contingencia);
492
    }
493
494
    /**
495
     * Altera o valor da DataContingencia para o informado no parâmetro
496
     * @param mixed $data_contingencia novo valor para DataContingencia
497
     * @return Nota A própria instância da classe
498
     */
499 27
    public function setDataContingencia($data_contingencia)
500
    {
501 27
        if (!is_null($data_contingencia) && !is_numeric($data_contingencia)) {
502
            $data_contingencia = strtotime($data_contingencia);
503
        }
504 27
        $this->data_contingencia = $data_contingencia;
505 27
        return $this;
506
    }
507
508
    /**
509
     * Informar a Justificativa da entrada em contingência
510
     * @param boolean $normalize informa se a justificativa deve estar no formato do XML
511
     * @return mixed justificativa da Nota
512
     */
513 5
    public function getJustificativa($normalize = false)
514
    {
515 5
        if (!$normalize) {
516 5
            return $this->justificativa;
517
        }
518
        return $this->justificativa;
519
    }
520
521
    /**
522
     * Altera o valor da Justificativa para o informado no parâmetro
523
     * @param mixed $justificativa novo valor para Justificativa
524
     * @return Nota A própria instância da classe
525
     */
526 27
    public function setJustificativa($justificativa)
527
    {
528 27
        $this->justificativa = $justificativa;
529 27
        return $this;
530
    }
531
532
    /**
533
     * Código do modelo do Documento Fiscal. 55 = NF-e; 65 = NFC-e.
534
     * @param boolean $normalize informa se o modelo deve estar no formato do XML
535
     * @return mixed modelo da Nota
536
     */
537 25
    public function getModelo($normalize = false)
538
    {
539 25
        if (!$normalize) {
540 24
            return $this->modelo;
541
        }
542 25
        switch ($this->modelo) {
543 25
            case self::MODELO_NFE:
544
                return '55';
545 25
            case self::MODELO_NFCE:
546 25
                return '65';
547
        }
548
        return $this->modelo;
549
    }
550
551
    /**
552
     * Altera o valor do Modelo para o informado no parâmetro
553
     * @param mixed $modelo novo valor para Modelo
554
     * @return Nota A própria instância da classe
555
     */
556 27
    public function setModelo($modelo)
557
    {
558
        switch ($modelo) {
559 27
            case '55':
560
                $modelo = self::MODELO_NFE;
561
                break;
562 27
            case '65':
563 23
                $modelo = self::MODELO_NFCE;
564 23
                break;
565
        }
566 27
        $this->modelo = $modelo;
567 27
        return $this;
568
    }
569
570
    /**
571
     * Tipo do Documento Fiscal (0 - entrada; 1 - saída)
572
     * @param boolean $normalize informa se o tipo deve estar no formato do XML
573
     * @return mixed tipo da Nota
574
     */
575 25
    public function getTipo($normalize = false)
576
    {
577 25
        if (!$normalize) {
578 3
            return $this->tipo;
579
        }
580 25
        switch ($this->tipo) {
581 25
            case self::TIPO_ENTRADA:
582
                return '0';
583 25
            case self::TIPO_SAIDA:
584 25
                return '1';
585
        }
586
        return $this->tipo;
587
    }
588
589
    /**
590
     * Altera o valor do Tipo para o informado no parâmetro
591
     * @param mixed $tipo novo valor para Tipo
592
     * @return Nota A própria instância da classe
593
     */
594 27
    public function setTipo($tipo)
595
    {
596
        switch ($tipo) {
597 27
            case '0':
598
                $tipo = self::TIPO_ENTRADA;
599
                break;
600 27
            case '1':
601 23
                $tipo = self::TIPO_SAIDA;
602 23
                break;
603
        }
604 27
        $this->tipo = $tipo;
605 27
        return $this;
606
    }
607
608
    /**
609
     * Identificador de Local de destino da operação
610
     * (1-Interna;2-Interestadual;3-Exterior)
611
     * @param boolean $normalize informa se o destino deve estar no formato do XML
612
     * @return mixed destino da Nota
613
     */
614 25
    public function getDestino($normalize = false)
615
    {
616 25
        if (!$normalize) {
617 3
            return $this->destino;
618
        }
619 25
        switch ($this->destino) {
620 25
            case self::DESTINO_INTERNA:
621 25
                return '1';
622
            case self::DESTINO_INTERESTADUAL:
623
                return '2';
624
            case self::DESTINO_EXTERIOR:
625
                return '3';
626
        }
627
        return $this->destino;
628
    }
629
630
    /**
631
     * Altera o valor do Destino para o informado no parâmetro
632
     * @param mixed $destino novo valor para Destino
633
     * @return Nota A própria instância da classe
634
     */
635 27
    public function setDestino($destino)
636
    {
637
        switch ($destino) {
638 27
            case '1':
639 23
                $destino = self::DESTINO_INTERNA;
640 23
                break;
641 27
            case '2':
642
                $destino = self::DESTINO_INTERESTADUAL;
643
                break;
644 27
            case '3':
645
                $destino = self::DESTINO_EXTERIOR;
646
                break;
647
        }
648 27
        $this->destino = $destino;
649 27
        return $this;
650
    }
651
652
    /**
653
     * Descrição da Natureza da Operação
654
     * @param boolean $normalize informa se a natureza deve estar no formato do XML
655
     * @return mixed natureza da Nota
656
     */
657 25
    public function getNatureza($normalize = false)
658
    {
659 25
        if (!$normalize) {
660 3
            return $this->natureza;
661
        }
662 25
        return $this->natureza;
663
    }
664
665
    /**
666
     * Altera o valor da Natureza para o informado no parâmetro
667
     * @param mixed $natureza novo valor para Natureza
668
     * @return Nota A própria instância da classe
669
     */
670 27
    public function setNatureza($natureza)
671
    {
672 27
        $this->natureza = $natureza;
673 27
        return $this;
674
    }
675
676
    /**
677
     * Código numérico que compõe a Chave de Acesso. Número aleatório gerado
678
     * pelo emitente para cada NF-e.
679
     * @param boolean $normalize informa se o codigo deve estar no formato do XML
680
     * @return mixed codigo da Nota
681
     */
682 25
    public function getCodigo($normalize = false)
683
    {
684 25
        if (!$normalize) {
685 25
            return $this->codigo;
686
        }
687 25
        return Util::padDigit($this->codigo % 100000000, 8);
688
    }
689
690
    /**
691
     * Altera o valor do Codigo para o informado no parâmetro
692
     * @param mixed $codigo novo valor para Codigo
693
     * @return Nota A própria instância da classe
694
     */
695 27
    public function setCodigo($codigo)
696
    {
697 27
        $this->codigo = $codigo;
698 27
        return $this;
699
    }
700
701
    /**
702
     * Indicador da forma de pagamento: 0 – pagamento à vista; 1 – pagamento à
703
     * prazo; 2 – outros.
704
     * @param boolean $normalize informa se o indicador deve estar no formato do XML
705
     * @return mixed indicador da Nota
706
     */
707 25
    public function getIndicador($normalize = false)
708
    {
709 25
        if (!$normalize) {
710 3
            return $this->indicador;
711
        }
712 25
        switch ($this->indicador) {
713 25
            case self::INDICADOR_AVISTA:
714 25
                return '0';
715
            case self::INDICADOR_APRAZO:
716
                return '1';
717
            case self::INDICADOR_OUTROS:
718
                return '2';
719
        }
720
        return $this->indicador;
721
    }
722
723
    /**
724
     * Altera o valor do Indicador para o informado no parâmetro
725
     * @param mixed $indicador novo valor para Indicador
726
     * @return Nota A própria instância da classe
727
     */
728 27
    public function setIndicador($indicador)
729
    {
730
        switch ($indicador) {
731 27
            case '0':
732 23
                $indicador = self::INDICADOR_AVISTA;
733 23
                break;
734 27
            case '1':
735
                $indicador = self::INDICADOR_APRAZO;
736
                break;
737 27
            case '2':
738
                $indicador = self::INDICADOR_OUTROS;
739
                break;
740
        }
741 27
        $this->indicador = $indicador;
742 27
        return $this;
743
    }
744
745
    /**
746
     * Data e Hora de emissão do Documento Fiscal
747
     * @param boolean $normalize informa se o data_emissao deve estar no formato do XML
748
     * @return mixed data_emissao da Nota
749
     */
750 25
    public function getDataEmissao($normalize = false)
751
    {
752 25
        if (!$normalize) {
753 25
            return $this->data_emissao;
754
        }
755 25
        return Util::toDateTime($this->data_emissao);
756
    }
757
758
    /**
759
     * Altera o valor do DataEmissao para o informado no parâmetro
760
     * @param mixed $data_emissao novo valor para DataEmissao
761
     * @return Nota A própria instância da classe
762
     */
763 27
    public function setDataEmissao($data_emissao)
764
    {
765 27
        if (!is_numeric($data_emissao)) {
766 27
            $data_emissao = strtotime($data_emissao);
767 27
        }
768 27
        $this->data_emissao = $data_emissao;
769 27
        return $this;
770
    }
771
772
    /**
773
     * Série do Documento Fiscal: série normal 0-889, Avulsa Fisco 890-899,
774
     * SCAN 900-999
775
     * @param boolean $normalize informa se o serie deve estar no formato do XML
776
     * @return mixed serie da Nota
777
     */
778 25
    public function getSerie($normalize = false)
779
    {
780 25
        if (!$normalize) {
781 25
            return $this->serie;
782
        }
783 25
        return $this->serie;
784
    }
785
786
    /**
787
     * Altera o valor do Serie para o informado no parâmetro
788
     * @param mixed $serie novo valor para Serie
789
     * @return Nota A própria instância da classe
790
     */
791 27
    public function setSerie($serie)
792
    {
793 27
        $this->serie = $serie;
794 27
        return $this;
795
    }
796
797
    /**
798
     * Formato de impressão do DANFE (0-sem DANFE;1-DANFe Retrato; 2-DANFe
799
     * Paisagem;3-DANFe Simplificado;4-DANFe NFC-e;5-DANFe NFC-e em mensagem
800
     * eletrônica)
801
     * @param boolean $normalize informa se o formato deve estar no formato do XML
802
     * @return mixed formato da Nota
803
     */
804 25
    public function getFormato($normalize = false)
805
    {
806 25
        if (!$normalize) {
807 3
            return $this->formato;
808
        }
809 25
        switch ($this->formato) {
810 25
            case self::FORMATO_NENHUMA:
811
                return '0';
812 25
            case self::FORMATO_RETRATO:
813
                return '1';
814 25
            case self::FORMATO_PAISAGEM:
815
                return '2';
816 25
            case self::FORMATO_SIMPLIFICADO:
817
                return '3';
818 25
            case self::FORMATO_CONSUMIDOR:
819 25
                return '4';
820
            case self::FORMATO_MENSAGEM:
821
                return '5';
822
        }
823
        return $this->formato;
824
    }
825
826
    /**
827
     * Altera o valor do Formato para o informado no parâmetro
828
     * @param mixed $formato novo valor para Formato
829
     * @return Nota A própria instância da classe
830
     */
831 27
    public function setFormato($formato)
832
    {
833
        switch ($formato) {
834 27
            case '0':
835
                $formato = self::FORMATO_NENHUMA;
836
                break;
837 27
            case '1':
838
                $formato = self::FORMATO_RETRATO;
839
                break;
840 27
            case '2':
841
                $formato = self::FORMATO_PAISAGEM;
842
                break;
843 27
            case '3':
844
                $formato = self::FORMATO_SIMPLIFICADO;
845
                break;
846 27
            case '4':
847 23
                $formato = self::FORMATO_CONSUMIDOR;
848 23
                break;
849 27
            case '5':
850
                $formato = self::FORMATO_MENSAGEM;
851
                break;
852
        }
853 27
        $this->formato = $formato;
854 27
        return $this;
855
    }
856
857
    /**
858
     * Forma de emissão da NF-e
859
     * @param boolean $normalize informa se o emissao deve estar no formato do XML
860
     * @return mixed emissao da Nota
861
     */
862 25
    public function getEmissao($normalize = false)
863
    {
864 25
        if (!$normalize) {
865 25
            return $this->emissao;
866
        }
867 25
        switch ($this->emissao) {
868 25
            case self::EMISSAO_NORMAL:
869 25
                return '1';
870
            case self::EMISSAO_CONTINGENCIA:
871
                return '9';
872
        }
873
        return $this->emissao;
874
    }
875
876
    /**
877
     * Altera o valor do Emissao para o informado no parâmetro
878
     * @param mixed $emissao novo valor para Emissao
879
     * @return Nota A própria instância da classe
880
     */
881 27
    public function setEmissao($emissao)
882
    {
883
        switch ($emissao) {
884 27
            case '1':
885 23
                $emissao = self::EMISSAO_NORMAL;
886 23
                break;
887 27
            case '9':
888
                $emissao = self::EMISSAO_CONTINGENCIA;
889
                break;
890
        }
891 27
        $this->emissao = $emissao;
892 27
        return $this;
893
    }
894
895
    /**
896
     * Digito Verificador da Chave de Acesso da NF-e
897
     * @param boolean $normalize informa se o digito_verificador deve estar no formato do XML
898
     * @return mixed digito_verificador da Nota
899
     */
900 25
    public function getDigitoVerificador($normalize = false)
901
    {
902 25
        if (!$normalize) {
903 3
            return $this->digito_verificador;
904
        }
905 25
        return $this->digito_verificador;
906
    }
907
908
    /**
909
     * Altera o valor do DigitoVerificador para o informado no parâmetro
910
     * @param mixed $digito_verificador novo valor para DigitoVerificador
911
     * @return Nota A própria instância da classe
912
     */
913 27
    public function setDigitoVerificador($digito_verificador)
914
    {
915 27
        $this->digito_verificador = $digito_verificador;
916 27
        return $this;
917
    }
918
919
    /**
920
     * Identificação do Ambiente: 1 - Produção, 2 - Homologação
921
     * @param boolean $normalize informa se o ambiente deve estar no formato do XML
922
     * @return mixed ambiente da Nota
923
     */
924 25
    public function getAmbiente($normalize = false)
925
    {
926 25
        if (!$normalize) {
927 25
            return $this->ambiente;
928
        }
929 25
        switch ($this->ambiente) {
930 25
            case self::AMBIENTE_PRODUCAO:
931
                return '1';
932 25
            case self::AMBIENTE_HOMOLOGACAO:
933 25
                return '2';
934
        }
935
        return $this->ambiente;
936
    }
937
938
    /**
939
     * Altera o valor do Ambiente para o informado no parâmetro
940
     * @param mixed $ambiente novo valor para Ambiente
941
     * @return Nota A própria instância da classe
942
     */
943 27
    public function setAmbiente($ambiente)
944
    {
945
        switch ($ambiente) {
946 27
            case '1':
947
                $ambiente = self::AMBIENTE_PRODUCAO;
948
                break;
949 27
            case '2':
950 23
                $ambiente = self::AMBIENTE_HOMOLOGACAO;
951 23
                break;
952
        }
953 27
        $this->ambiente = $ambiente;
954 27
        return $this;
955
    }
956
957
    /**
958
     * Finalidade da emissão da NF-e: 1 - NFe normal, 2 - NFe complementar, 3 -
959
     * NFe de ajuste, 4 - Devolução/Retorno
960
     * @param boolean $normalize informa se a finalidade deve estar no formato do XML
961
     * @return mixed finalidade da Nota
962
     */
963 25
    public function getFinalidade($normalize = false)
964
    {
965 25
        if (!$normalize) {
966 3
            return $this->finalidade;
967
        }
968 25
        switch ($this->finalidade) {
969 25
            case self::FINALIDADE_NORMAL:
970 25
                return '1';
971
            case self::FINALIDADE_COMPLEMENTAR:
972
                return '2';
973
            case self::FINALIDADE_AJUSTE:
974
                return '3';
975
            case self::FINALIDADE_RETORNO:
976
                return '4';
977
        }
978
        return $this->finalidade;
979
    }
980
981
    /**
982
     * Altera o valor da Finalidade para o informado no parâmetro
983
     * @param mixed $finalidade novo valor para Finalidade
984
     * @return Nota A própria instância da classe
985
     */
986 27
    public function setFinalidade($finalidade)
987
    {
988
        switch ($finalidade) {
989 27
            case '1':
990 23
                $finalidade = self::FINALIDADE_NORMAL;
991 23
                break;
992 27
            case '2':
993
                $finalidade = self::FINALIDADE_COMPLEMENTAR;
994
                break;
995 27
            case '3':
996
                $finalidade = self::FINALIDADE_AJUSTE;
997
                break;
998 27
            case '4':
999
                $finalidade = self::FINALIDADE_RETORNO;
1000
                break;
1001
        }
1002 27
        $this->finalidade = $finalidade;
1003 27
        return $this;
1004
    }
1005
1006
    /**
1007
     * Indica operação com consumidor final (0-Não;1-Consumidor Final)
1008
     * @param boolean $normalize informa se o consumidor_final deve estar no formato do XML
1009
     * @return mixed consumidor_final da Nota
1010
     */
1011 25
    public function getConsumidorFinal($normalize = false)
1012
    {
1013 25
        if (!$normalize) {
1014 3
            return $this->consumidor_final;
1015
        }
1016 25
        switch ($this->consumidor_final) {
1017 25
            case 'N':
1018
                return '0';
1019 25
            case 'Y':
1020 25
                return '1';
1021
        }
1022
        return $this->consumidor_final;
1023
    }
1024
1025
    /**
1026
     * Indica operação com consumidor final (0-Não;1-Consumidor Final)
1027
     * @return boolean informa se o ConsumidorFinal está habilitado
1028
     */
1029
    public function isConsumidorFinal()
1030
    {
1031
        return $this->consumidor_final == 'Y';
1032
    }
1033
1034
    /**
1035
     * Altera o valor do ConsumidorFinal para o informado no parâmetro
1036
     * @param mixed $consumidor_final novo valor para ConsumidorFinal
1037
     * @return Nota A própria instância da classe
1038
     */
1039 27
    public function setConsumidorFinal($consumidor_final)
1040
    {
1041 27
        if (!in_array($consumidor_final, array('N', 'Y'))) {
1042 23
            $consumidor_final = $consumidor_final?'Y':'N';
1043 23
        }
1044 27
        $this->consumidor_final = $consumidor_final;
1045 27
        return $this;
1046
    }
1047
1048
    /**
1049
     * Indicador de presença do comprador no estabelecimento comercial no
1050
     * momento da oepração (0-Não se aplica, ex.: Nota Fiscal complementar ou
1051
     * de ajuste;1-Operação presencial;2-Não presencial, internet;3-Não
1052
     * presencial, teleatendimento;4-NFC-e entrega em domicílio;9-Não
1053
     * presencial, outros)
1054
     * @param boolean $normalize informa se a presenca deve estar no formato do XML
1055
     * @return mixed presenca da Nota
1056
     */
1057 25
    public function getPresenca($normalize = false)
1058
    {
1059 25
        if (!$normalize) {
1060 3
            return $this->presenca;
1061
        }
1062 25
        switch ($this->presenca) {
1063 25
            case self::PRESENCA_NENHUM:
1064
                return '0';
1065 25
            case self::PRESENCA_PRESENCIAL:
1066 25
                return '1';
1067
            case self::PRESENCA_INTERNET:
1068
                return '2';
1069
            case self::PRESENCA_TELEATENDIMENTO:
1070
                return '3';
1071
            case self::PRESENCA_ENTREGA:
1072
                return '4';
1073
            case self::PRESENCA_OUTROS:
1074
                return '9';
1075
        }
1076
        return $this->presenca;
1077
    }
1078
1079
    /**
1080
     * Altera o valor da Presenca para o informado no parâmetro
1081
     * @param mixed $presenca novo valor para Presenca
1082
     * @return Nota A própria instância da classe
1083
     */
1084 27
    public function setPresenca($presenca)
1085
    {
1086
        switch ($presenca) {
1087 27
            case '0':
1088
                $presenca = self::PRESENCA_NENHUM;
1089
                break;
1090 27
            case '1':
1091 23
                $presenca = self::PRESENCA_PRESENCIAL;
1092 23
                break;
1093 27
            case '2':
1094
                $presenca = self::PRESENCA_INTERNET;
1095
                break;
1096 27
            case '3':
1097
                $presenca = self::PRESENCA_TELEATENDIMENTO;
1098
                break;
1099 27
            case '4':
1100
                $presenca = self::PRESENCA_ENTREGA;
1101
                break;
1102 27
            case '9':
1103
                $presenca = self::PRESENCA_OUTROS;
1104
                break;
1105
        }
1106 27
        $this->presenca = $presenca;
1107 27
        return $this;
1108
    }
1109
1110
    /**
1111
     * Dados dos totais da NF-e
1112
     * @return mixed total da Nota
1113
     */
1114 25
    public function getTotal()
1115
    {
1116 25
        return $this->total;
1117
    }
1118
    
1119
    /**
1120
     * Altera o valor do Total para o informado no parâmetro
1121
     * @param mixed $total novo valor para Total
1122
     * @return Nota A própria instância da classe
1123
     */
1124 27
    public function setTotal($total)
1125
    {
1126 27
        $this->total = $total;
1127 27
        return $this;
1128
    }
1129
1130
    /**
1131
     * Informações adicionais de interesse do Fisco
1132
     * @param boolean $normalize informa se a adicionais deve estar no formato do XML
1133
     * @return mixed adicionais da Nota
1134
     */
1135 25
    public function getAdicionais($normalize = false)
1136
    {
1137 25
        if (!$normalize) {
1138 25
            return $this->adicionais;
1139
        }
1140
        return $this->adicionais;
1141
    }
1142
    
1143
    /**
1144
     * Altera o valor da Adicionais para o informado no parâmetro
1145
     * @param mixed $adicionais novo valor para Adicionais
1146
     * @return Nota A própria instância da classe
1147
     */
1148 27
    public function setAdicionais($adicionais)
1149
    {
1150 27
        $this->adicionais = $adicionais;
1151 27
        return $this;
1152
    }
1153
1154
    /**
1155
     * Campo de uso livre do contribuinte informar o nome do campo no atributo
1156
     * xCampo e o conteúdo do campo no xTexto
1157
     * @return mixed observacoes da Nota
1158
     */
1159 25
    public function getObservacoes()
1160
    {
1161 25
        return $this->observacoes;
1162
    }
1163
    
1164
    /**
1165
     * Altera o valor da Observacoes para o informado no parâmetro
1166
     * @param mixed $observacoes novo valor para Observacoes
1167
     * @return Nota A própria instância da classe
1168
     */
1169 27
    public function setObservacoes($observacoes)
1170
    {
1171 27
        $this->observacoes = $observacoes;
1172 27
        return $this;
1173
    }
1174
1175
    /**
1176
     * Adiciona um(a) Observacao para a lista de observacao
1177
     * @param Observacao $observacao Instância da Observacao que será adicionada
1178
     * @return Nota A própria instância da classe
1179
     */
1180 2
    public function addObservacao($campo, $observacao)
1181
    {
1182 2
        $this->observacoes[] = array('campo' => $campo, 'valor' => $observacao);
1183 2
        return $this;
1184
    }
1185
1186
    /**
1187
     * Campo de uso exclusivo do Fisco informar o nome do campo no atributo
1188
     * xCampo e o conteúdo do campo no xTexto
1189
     * @return mixed informacoes da Nota
1190
     */
1191 25
    public function getInformacoes()
1192
    {
1193 25
        return $this->informacoes;
1194
    }
1195
    
1196
    /**
1197
     * Altera o valor da Informacoes para o informado no parâmetro
1198
     * @param mixed $informacoes novo valor para Informacoes
1199
     * @return Nota A própria instância da classe
1200
     */
1201 27
    public function setInformacoes($informacoes)
1202
    {
1203 27
        $this->informacoes = $informacoes;
1204 27
        return $this;
1205
    }
1206
1207
    /**
1208
     * Adiciona um(a) Informacao para a lista de informacao
1209
     * @param Informacao $informacao Instância da Informacao que será adicionada
1210
     * @return Nota A própria instância da classe
1211
     */
1212 2
    public function addInformacao($campo, $informacao)
1213
    {
1214 2
        $this->informacoes[] = array('campo' => $campo, 'valor' => $informacao);
1215 2
        return $this;
1216
    }
1217
1218
    /**
1219
     * Protocolo de autorização da nota, informado apenas quando a nota for
1220
     * enviada e autorizada
1221
     */
1222 23
    public function getProtocolo()
1223
    {
1224 23
        return $this->protocolo;
1225
    }
1226
1227 27
    public function setProtocolo($protocolo)
1228
    {
1229 27
        $this->protocolo = $protocolo;
1230 27
        return $this;
1231
    }
1232
1233 3
    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...
1234
    {
1235 3
        $nota = array();
1236 3
        $nota['id'] = $this->getID();
1237 3
        $nota['numero'] = $this->getNumero();
1238 3
        if (!is_null($this->getEmitente()) && $recursive) {
1239 1
            $nota['emitente'] = $this->getEmitente()->toArray($recursive);
1240 1
        } else {
1241 2
            $nota['emitente'] = $this->getEmitente();
1242
        }
1243 3
        if (!is_null($this->getDestinatario()) && $recursive) {
1244 1
            $nota['destinatario'] = $this->getDestinatario()->toArray($recursive);
1245 1
        } else {
1246 2
            $nota['destinatario'] = $this->getDestinatario();
1247
        }
1248 3
        if ($recursive) {
1249 1
            $produtos = array();
1250 1
            $_produtos = $this->getProdutos();
1251 1
            foreach ($_produtos as $_produto) {
1252 1
                $produtos[] = $_produto->toArray($recursive);
1253 1
            }
1254 1
            $nota['produtos'] = $produtos;
1255 1
        } else {
1256 2
            $nota['produtos'] = $this->getProdutos();
1257
        }
1258 3
        if (!is_null($this->getTransporte()) && $recursive) {
1259 1
            $nota['transporte'] = $this->getTransporte()->toArray($recursive);
1260 1
        } else {
1261 2
            $nota['transporte'] = $this->getTransporte();
1262
        }
1263 3
        if ($recursive) {
1264 1
            $pagamentos = array();
1265 1
            $_pagamentos = $this->getPagamentos();
1266 1
            foreach ($_pagamentos as $_pagamento) {
1267 1
                $pagamentos[] = $_pagamento->toArray($recursive);
1268 1
            }
1269 1
            $nota['pagamentos'] = $pagamentos;
1270 1
        } else {
1271 2
            $nota['pagamentos'] = $this->getPagamentos();
1272
        }
1273 3
        $nota['data_movimentacao'] = $this->getDataMovimentacao($recursive);
1274 3
        $nota['data_contingencia'] = $this->getDataContingencia($recursive);
1275 3
        $nota['justificativa'] = $this->getJustificativa();
1276 3
        $nota['modelo'] = $this->getModelo();
1277 3
        $nota['tipo'] = $this->getTipo();
1278 3
        $nota['destino'] = $this->getDestino();
1279 3
        $nota['natureza'] = $this->getNatureza();
1280 3
        $nota['codigo'] = $this->getCodigo();
1281 3
        $nota['indicador'] = $this->getIndicador();
1282 3
        $nota['data_emissao'] = $this->getDataEmissao($recursive);
1283 3
        $nota['serie'] = $this->getSerie();
1284 3
        $nota['formato'] = $this->getFormato();
1285 3
        $nota['emissao'] = $this->getEmissao();
1286 3
        $nota['digito_verificador'] = $this->getDigitoVerificador();
1287 3
        $nota['ambiente'] = $this->getAmbiente();
1288 3
        $nota['finalidade'] = $this->getFinalidade();
1289 3
        $nota['consumidor_final'] = $this->getConsumidorFinal();
1290 3
        $nota['presenca'] = $this->getPresenca();
1291 3
        if (!is_null($this->getTotal()) && $recursive) {
1292 1
            $nota['total'] = $this->getTotal()->toArray($recursive);
1293 1
        } else {
1294 2
            $nota['total'] = $this->getTotal();
1295
        }
1296 3
        $nota['adicionais'] = $this->getAdicionais();
1297 3
        $nota['observacoes'] = $this->getObservacoes();
1298 3
        $nota['informacoes'] = $this->getInformacoes();
1299 3
        if (!is_null($this->getProtocolo()) && $recursive) {
1300 1
            $nota['protocolo'] = $this->getProtocolo()->toArray($recursive);
1301 1
        } else {
1302 2
            $nota['protocolo'] = $this->getProtocolo();
1303
        }
1304 3
        return $nota;
1305
    }
1306
1307 27
    public function fromArray($nota = array())
0 ignored issues
show
Complexity introduced by
This operation has 940369969152 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...
1308
    {
1309 27
        if ($nota instanceof Nota) {
1310
            $nota = $nota->toArray();
1311 27
        } elseif (!is_array($nota)) {
1312
            return $this;
1313
        }
1314 27
        if (isset($nota['id'])) {
1315
            $this->setID($nota['id']);
1316
        } else {
1317 27
            $this->setID(null);
1318
        }
1319 27
        if (isset($nota['numero'])) {
1320 2
            $this->setNumero($nota['numero']);
1321 2
        } else {
1322 27
            $this->setNumero(null);
1323
        }
1324 27
        if (!isset($nota['emitente']) || is_null($nota['emitente'])) {
1325 27
            $this->setEmitente(new Emitente());
1326 27
        } else {
1327 2
            $this->setEmitente($nota['emitente']);
1328
        }
1329 27
        if (!isset($nota['destinatario']) || is_null($nota['destinatario'])) {
1330 27
            $this->setDestinatario(new Destinatario());
1331 27
        } else {
1332 2
            $this->setDestinatario($nota['destinatario']);
1333
        }
1334 27
        if (!isset($nota['produtos']) || is_null($nota['produtos'])) {
1335 27
            $this->setProdutos(array());
1336 27
        } else {
1337 2
            $this->setProdutos($nota['produtos']);
1338
        }
1339 27
        if (!isset($nota['transporte']) || is_null($nota['transporte'])) {
1340 27
            $this->setTransporte(new Transporte());
1341 27
        } else {
1342 2
            $this->setTransporte($nota['transporte']);
1343
        }
1344 27
        if (!isset($nota['pagamentos']) || is_null($nota['pagamentos'])) {
1345 27
            $this->setPagamentos(array());
1346 27
        } else {
1347 2
            $this->setPagamentos($nota['pagamentos']);
1348
        }
1349 27
        if (isset($nota['data_movimentacao'])) {
1350
            $this->setDataMovimentacao($nota['data_movimentacao']);
1351
        } else {
1352 27
            $this->setDataMovimentacao(null);
1353
        }
1354 27
        if (isset($nota['data_contingencia'])) {
1355
            $this->setDataContingencia($nota['data_contingencia']);
1356
        } else {
1357 27
            $this->setDataContingencia(null);
1358
        }
1359 27
        if (isset($nota['justificativa'])) {
1360
            $this->setJustificativa($nota['justificativa']);
1361
        } else {
1362 27
            $this->setJustificativa(null);
1363
        }
1364 27
        if (isset($nota['modelo'])) {
1365 2
            $this->setModelo($nota['modelo']);
1366 2
        } else {
1367 27
            $this->setModelo(null);
1368
        }
1369 27
        if (!isset($nota['tipo']) || is_null($nota['tipo'])) {
1370 27
            $this->setTipo(self::TIPO_SAIDA);
1371 27
        } else {
1372 2
            $this->setTipo($nota['tipo']);
1373
        }
1374 27
        if (!isset($nota['destino']) || is_null($nota['destino'])) {
1375 27
            $this->setDestino(self::DESTINO_INTERNA);
1376 27
        } else {
1377 2
            $this->setDestino($nota['destino']);
1378
        }
1379 27
        if (!isset($nota['natureza']) || is_null($nota['natureza'])) {
1380 27
            $this->setNatureza('VENDA PARA CONSUMIDOR FINAL');
1381 27
        } else {
1382 2
            $this->setNatureza($nota['natureza']);
1383
        }
1384 27
        if (isset($nota['codigo'])) {
1385 2
            $this->setCodigo($nota['codigo']);
1386 2
        } else {
1387 27
            $this->setCodigo(null);
1388
        }
1389 27
        if (!isset($nota['indicador']) || is_null($nota['indicador'])) {
1390 27
            $this->setIndicador(self::INDICADOR_AVISTA);
1391 27
        } else {
1392 2
            $this->setIndicador($nota['indicador']);
1393
        }
1394 27
        if (isset($nota['data_emissao'])) {
1395 2
            $this->setDataEmissao($nota['data_emissao']);
1396 2
        } else {
1397 27
            $this->setDataEmissao(null);
1398
        }
1399 27
        if (isset($nota['serie'])) {
1400 2
            $this->setSerie($nota['serie']);
1401 2
        } else {
1402 27
            $this->setSerie(null);
1403
        }
1404 27
        if (!isset($nota['formato']) || is_null($nota['formato'])) {
1405 27
            $this->setFormato(self::FORMATO_NENHUMA);
1406 27
        } else {
1407 2
            $this->setFormato($nota['formato']);
1408
        }
1409 27
        if (!isset($nota['emissao']) || is_null($nota['emissao'])) {
1410 27
            $this->setEmissao(self::EMISSAO_NORMAL);
1411 27
        } else {
1412 2
            $this->setEmissao($nota['emissao']);
1413
        }
1414 27
        if (isset($nota['digito_verificador'])) {
1415
            $this->setDigitoVerificador($nota['digito_verificador']);
1416
        } else {
1417 27
            $this->setDigitoVerificador(null);
1418
        }
1419 27
        if (!isset($nota['ambiente']) || is_null($nota['ambiente'])) {
1420 27
            $this->setAmbiente(self::AMBIENTE_HOMOLOGACAO);
1421 27
        } else {
1422 2
            $this->setAmbiente($nota['ambiente']);
1423
        }
1424 27
        if (!isset($nota['finalidade']) || is_null($nota['finalidade'])) {
1425 27
            $this->setFinalidade(self::FINALIDADE_NORMAL);
1426 27
        } else {
1427 2
            $this->setFinalidade($nota['finalidade']);
1428
        }
1429 27
        if (!isset($nota['consumidor_final']) || is_null($nota['consumidor_final'])) {
1430 27
            $this->setConsumidorFinal('Y');
1431 27
        } else {
1432 2
            $this->setConsumidorFinal($nota['consumidor_final']);
1433
        }
1434 27
        if (isset($nota['presenca'])) {
1435 2
            $this->setPresenca($nota['presenca']);
1436 2
        } else {
1437 27
            $this->setPresenca(null);
1438
        }
1439 27
        if (!isset($nota['total'])) {
1440 27
            $this->setTotal(new Total());
1441 27
        } else {
1442 2
            $this->setTotal($nota['total']);
1443
        }
1444 27
        if (!array_key_exists('adicionais', $nota)) {
1445 27
            $this->setAdicionais(null);
1446 27
        } else {
1447 2
            $this->setAdicionais($nota['adicionais']);
1448
        }
1449 27
        if (!array_key_exists('observacoes', $nota)) {
1450 27
            $this->setObservacoes(null);
1451 27
        } else {
1452 2
            $this->setObservacoes($nota['observacoes']);
1453
        }
1454 27
        if (!array_key_exists('informacoes', $nota)) {
1455 27
            $this->setInformacoes(null);
1456 27
        } else {
1457 2
            $this->setInformacoes($nota['informacoes']);
1458
        }
1459 27
        if (isset($nota['protocolo'])) {
1460
            $this->setProtocolo($nota['protocolo']);
1461
        } else {
1462 27
            $this->setProtocolo(null);
1463
        }
1464 27
        return $this;
1465
    }
1466
1467 25
    public function gerarID()
1468
    {
1469 25
        $estado = $this->getEmitente()->getEndereco()->getMunicipio()->getEstado();
1470 25
        $estado->checkCodigos();
1471 25
        $id = sprintf(
1472 25
            '%02d%02d%02d%s%02d%03d%09d%01d%08d',
1473 25
            $estado->getCodigo(),
1474 25
            date('y', $this->getDataEmissao()), // Ano 2 dígitos
1475 25
            date('m', $this->getDataEmissao()), // Mês 2 dígitos
1476 25
            $this->getEmitente()->getCNPJ(),
1477 25
            $this->getModelo(true),
1478 25
            $this->getSerie(),
1479 25
            $this->getNumero(),
1480 25
            $this->getEmissao(true),
1481 25
            $this->getCodigo()
1482 25
        );
1483 25
        return $id.Util::getDAC($id, 11);
1484
    }
1485
1486 25
    protected function getTotais()
1487
    {
1488 25
        $total = array();
1489 25
        $total['produtos'] = 0.00;
1490 25
        $total['desconto'] = 0.00;
1491 25
        $total['frete'] = 0.00;
1492 25
        $total['seguro'] = 0.00;
1493 25
        $total['despesas'] = 0.00;
1494 25
        $total['tributos'] = 0.00;
1495 25
        $total['icms'] = 0.00;
1496 25
        $total['icms.st'] = 0.00;
1497 25
        $total['base'] = 0.00;
1498 25
        $total['base.st'] = 0.00;
1499 25
        $total['ii'] = 0.00;
1500 25
        $total['ipi'] = 0.00;
1501 25
        $total['pis'] = 0.00;
1502 25
        $total['cofins'] = 0.00;
1503 25
        $total['desoneracao'] = 0.00;
1504 25
        $_produtos = $this->getProdutos();
1505 25
        foreach ($_produtos as $_produto) {
1506 25
            if (!$_produto->getMultiplicador()) {
1507
                continue;
1508
            }
1509 25
            $imposto_info = $_produto->getImpostoInfo();
1510 25
            $total['produtos'] += round($_produto->getPreco(), 2);
1511 25
            $total['desconto'] += round($_produto->getDesconto(), 2);
1512 25
            $total['frete'] += round($_produto->getFrete(), 2);
1513 25
            $total['seguro'] += round($_produto->getSeguro(), 2);
1514 25
            $total['despesas'] += round($_produto->getDespesas(), 2);
1515 25
            $total['tributos'] += round($imposto_info['total'], 2);
1516 25
            $_impostos = $_produto->getImpostos();
1517 25
            foreach ($_impostos as $_imposto) {
1518 25
                switch ($_imposto->getGrupo()) {
1519 25
                    case Imposto::GRUPO_ICMS:
1520 25
                        if (($_imposto instanceof \NFe\Entity\Imposto\ICMS\Cobranca) ||
1521 25
                                ($_imposto instanceof \NFe\Entity\Imposto\ICMS\Simples\Cobranca)) {
1522 25
                            $total[$_imposto->getGrupo()] += round($_imposto->getNormal()->getValor(), 2);
1523 25
                            $total['base'] += round($_imposto->getNormal()->getBase(), 2);
1524 25
                        }
1525 25
                        if (($_imposto instanceof \NFe\Entity\Imposto\ICMS\Parcial) ||
1526 25
                                ($_imposto instanceof \NFe\Entity\Imposto\ICMS\Simples\Parcial)) {
1527 25
                            $total['icms.st'] += round($_imposto->getValor(), 2);
1528 25
                            $total['base.st'] += round($_imposto->getBase(), 2);
1529 25
                        } else {
1530
                            $total[$_imposto->getGrupo()] += round($_imposto->getValor(), 2);
1531
                            $total['base'] += round($_imposto->getBase(), 2);
1532
                        }
1533 25
                        break;
1534 25
                    default:
1535 25
                        $total[$_imposto->getGrupo()] += round($_imposto->getValor(), 2);
1536 25
                }
1537 25
            }
1538 25
        }
1539 25
        $produtos = round($total['produtos'], 2) - round($total['desconto'], 2);
1540 25
        $servicos = round($total['frete'], 2) + round($total['seguro'], 2) + round($total['despesas'], 2);
1541 25
        $impostos = round($total['ii'], 2) + round($total['ipi'], 2) + round($total['icms.st'], 2);
1542 25
        $impostos = $impostos - round($total['desoneracao'], 2);
1543 25
        $total['nota'] = $produtos + $servicos + $impostos;
1544 25
        return $total;
1545
    }
1546
1547 25
    private function getNodeTotal($name = null)
1548
    {
1549 25
        $dom = new \DOMDocument('1.0', 'UTF-8');
1550 25
        $element = $dom->createElement(is_null($name)?'total':$name);
1551
1552
        // Totais referentes ao ICMS
1553 25
        $total = $this->getTotais();
1554 25
        $icms = $dom->createElement('ICMSTot');
1555 25
        Util::appendNode($icms, 'vBC', Util::toCurrency($total['base']));
1556 25
        Util::appendNode($icms, 'vICMS', Util::toCurrency($total['icms']));
1557 25
        Util::appendNode($icms, 'vICMSDeson', Util::toCurrency($total['desoneracao']));
1558 25
        Util::appendNode($icms, 'vBCST', Util::toCurrency($total['base.st']));
1559 25
        Util::appendNode($icms, 'vST', Util::toCurrency($total['icms.st']));
1560 25
        Util::appendNode($icms, 'vProd', Util::toCurrency($total['produtos']));
1561 25
        Util::appendNode($icms, 'vFrete', Util::toCurrency($total['frete']));
1562 25
        Util::appendNode($icms, 'vSeg', Util::toCurrency($total['seguro']));
1563 25
        Util::appendNode($icms, 'vDesc', Util::toCurrency($total['desconto']));
1564 25
        Util::appendNode($icms, 'vII', Util::toCurrency($total['ii']));
1565 25
        Util::appendNode($icms, 'vIPI', Util::toCurrency($total['ipi']));
1566 25
        Util::appendNode($icms, 'vPIS', Util::toCurrency($total['pis']));
1567 25
        Util::appendNode($icms, 'vCOFINS', Util::toCurrency($total['cofins']));
1568 25
        Util::appendNode($icms, 'vOutro', Util::toCurrency($total['despesas']));
1569 25
        Util::appendNode($icms, 'vNF', Util::toCurrency($total['nota']));
1570 25
        Util::appendNode($icms, 'vTotTrib', Util::toCurrency($total['tributos']));
1571 25
        $element->appendChild($icms);
1572 25
        $this->setTotal(new Total($total));
1573 25
        $this->getTotal()->setProdutos($total['produtos']);
1574
1575
        // TODO: Totais referentes ao ISSQN
1576
1577
        // TODO: Retenção de Tributos Federais
1578 25
        return $element;
1579
    }
1580
1581 25
    public function getNode($name = null)
0 ignored issues
show
Complexity introduced by
This operation has 90720 execution paths which exceeds the configured maximum of 200.

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

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

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

There are different options of fixing this problem.

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

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

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

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