Completed
Push — master ( f48ccd...5f3052 )
by Francimar
03:37
created

Nota::loadNode()   F

Complexity

Conditions 15
Paths 590

Size

Total Lines 245
Code Lines 187

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 208
CRAP Score 15.0029

Importance

Changes 0
Metric Value
dl 0
loc 245
ccs 208
cts 213
cp 0.9765
rs 2.477
c 0
b 0
f 0
cc 15
eloc 187
nc 590
nop 2
crap 15.0029

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 2022 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 277 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 29
    public function __construct($nota = array())
280
    {
281 29
        $this->fromArray($nota);
282 29
    }
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 27
    public function getID($normalize = false)
290
    {
291 27
        if (!$normalize) {
292 27
            return $this->id;
293
        }
294 27
        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 29
    public function setID($id)
303
    {
304 29
        $this->id = $id;
305 29
        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 27
    public function getNumero($normalize = false)
314
    {
315 27
        if (!$normalize) {
316 27
            return $this->numero;
317
        }
318 27
        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 29
    public function setNumero($numero)
327
    {
328 29
        $this->numero = $numero;
329 29
        return $this;
330
    }
331
332
    /**
333
     * Emitente da nota fiscal
334
     * @return mixed emitente da Nota
335
     */
336 27
    public function getEmitente()
337
    {
338 27
        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 29
    public function setEmitente($emitente)
347
    {
348 29
        $this->emitente = $emitente;
349 29
        return $this;
350
    }
351
352
    /**
353
     * Destinatário que receberá os produtos
354
     * @return mixed destinatario da Nota
355
     */
356 27
    public function getDestinatario()
357
    {
358 27
        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 29
    public function setDestinatario($destinatario)
367
    {
368 29
        $this->destinatario = $destinatario;
369 29
        return $this;
370
    }
371
372
    /**
373
     * Produtos adicionados na nota
374
     * @return mixed produtos da Nota
375
     */
376 27
    public function getProdutos()
377
    {
378 27
        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 29
    public function setProdutos($produtos)
387
    {
388 29
        $this->produtos = $produtos;
389 29
        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 27
    public function getTransporte()
408
    {
409 27
        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 29
    public function setTransporte($transporte)
418
    {
419 29
        $this->transporte = $transporte;
420 29
        return $this;
421
    }
422
423
    /**
424
     * Pagamentos realizados
425
     * @return mixed pagamentos da Nota
426
     */
427 27
    public function getPagamentos()
428
    {
429 27
        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 29
    public function setPagamentos($pagamentos)
438
    {
439 29
        $this->pagamentos = $pagamentos;
440 29
        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 27
    public function getDataMovimentacao($normalize = false)
460
    {
461 27
        if (!$normalize || is_null($this->data_movimentacao)) {
462 27
            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 29
    public function setDataMovimentacao($data_movimentacao)
473
    {
474 29
        if (!is_null($data_movimentacao) && !is_numeric($data_movimentacao)) {
475
            $data_movimentacao = strtotime($data_movimentacao);
476
        }
477 29
        $this->data_movimentacao = $data_movimentacao;
478 29
        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 29
    public function setDataContingencia($data_contingencia)
500
    {
501 29
        if (!is_null($data_contingencia) && !is_numeric($data_contingencia)) {
502
            $data_contingencia = strtotime($data_contingencia);
503
        }
504 29
        $this->data_contingencia = $data_contingencia;
505 29
        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 29
    public function setJustificativa($justificativa)
527
    {
528 29
        $this->justificativa = $justificativa;
529 29
        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 27
    public function getModelo($normalize = false)
538
    {
539 27
        if (!$normalize) {
540 26
            return $this->modelo;
541
        }
542 27
        switch ($this->modelo) {
543 27
            case self::MODELO_NFE:
544
                return '55';
545 27
            case self::MODELO_NFCE:
546 27
                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 29
    public function setModelo($modelo)
557
    {
558
        switch ($modelo) {
559 29
            case '55':
560
                $modelo = self::MODELO_NFE;
561
                break;
562 29
            case '65':
563 25
                $modelo = self::MODELO_NFCE;
564 25
                break;
565
        }
566 29
        $this->modelo = $modelo;
567 29
        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 27
    public function getTipo($normalize = false)
576
    {
577 27
        if (!$normalize) {
578 3
            return $this->tipo;
579
        }
580 27
        switch ($this->tipo) {
581 27
            case self::TIPO_ENTRADA:
582
                return '0';
583 27
            case self::TIPO_SAIDA:
584 27
                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 29
    public function setTipo($tipo)
595
    {
596
        switch ($tipo) {
597 29
            case '0':
598
                $tipo = self::TIPO_ENTRADA;
599
                break;
600 29
            case '1':
601 25
                $tipo = self::TIPO_SAIDA;
602 25
                break;
603
        }
604 29
        $this->tipo = $tipo;
605 29
        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 27
    public function getDestino($normalize = false)
615
    {
616 27
        if (!$normalize) {
617 3
            return $this->destino;
618
        }
619 27
        switch ($this->destino) {
620 27
            case self::DESTINO_INTERNA:
621 27
                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 29
    public function setDestino($destino)
636
    {
637
        switch ($destino) {
638 29
            case '1':
639 25
                $destino = self::DESTINO_INTERNA;
640 25
                break;
641 29
            case '2':
642
                $destino = self::DESTINO_INTERESTADUAL;
643
                break;
644 29
            case '3':
645
                $destino = self::DESTINO_EXTERIOR;
646
                break;
647
        }
648 29
        $this->destino = $destino;
649 29
        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 27
    public function getNatureza($normalize = false)
658
    {
659 27
        if (!$normalize) {
660 3
            return $this->natureza;
661
        }
662 27
        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 29
    public function setNatureza($natureza)
671
    {
672 29
        $this->natureza = $natureza;
673 29
        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 27
    public function getCodigo($normalize = false)
683
    {
684 27
        if (!$normalize) {
685 27
            return $this->codigo;
686
        }
687 27
        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 29
    public function setCodigo($codigo)
696
    {
697 29
        $this->codigo = $codigo;
698 29
        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 27
    public function getIndicador($normalize = false)
708
    {
709 27
        if (!$normalize) {
710 3
            return $this->indicador;
711
        }
712 27
        switch ($this->indicador) {
713 27
            case self::INDICADOR_AVISTA:
714 27
                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 29
    public function setIndicador($indicador)
729
    {
730
        switch ($indicador) {
731 29
            case '0':
732 25
                $indicador = self::INDICADOR_AVISTA;
733 25
                break;
734 29
            case '1':
735
                $indicador = self::INDICADOR_APRAZO;
736
                break;
737 29
            case '2':
738
                $indicador = self::INDICADOR_OUTROS;
739
                break;
740
        }
741 29
        $this->indicador = $indicador;
742 29
        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 27
    public function getDataEmissao($normalize = false)
751
    {
752 27
        if (!$normalize) {
753 27
            return $this->data_emissao;
754
        }
755 27
        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 29
    public function setDataEmissao($data_emissao)
764
    {
765 29
        if (!is_numeric($data_emissao)) {
766 29
            $data_emissao = strtotime($data_emissao);
767 29
        }
768 29
        $this->data_emissao = $data_emissao;
769 29
        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 27
    public function getSerie($normalize = false)
779
    {
780 27
        if (!$normalize) {
781 27
            return $this->serie;
782
        }
783 27
        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 29
    public function setSerie($serie)
792
    {
793 29
        $this->serie = $serie;
794 29
        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 27
    public function getFormato($normalize = false)
805
    {
806 27
        if (!$normalize) {
807 3
            return $this->formato;
808
        }
809 27
        switch ($this->formato) {
810 27
            case self::FORMATO_NENHUMA:
811
                return '0';
812 27
            case self::FORMATO_RETRATO:
813
                return '1';
814 27
            case self::FORMATO_PAISAGEM:
815
                return '2';
816 27
            case self::FORMATO_SIMPLIFICADO:
817
                return '3';
818 27
            case self::FORMATO_CONSUMIDOR:
819 27
                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 29
    public function setFormato($formato)
832
    {
833
        switch ($formato) {
834 29
            case '0':
835
                $formato = self::FORMATO_NENHUMA;
836
                break;
837 29
            case '1':
838
                $formato = self::FORMATO_RETRATO;
839
                break;
840 29
            case '2':
841
                $formato = self::FORMATO_PAISAGEM;
842
                break;
843 29
            case '3':
844
                $formato = self::FORMATO_SIMPLIFICADO;
845
                break;
846 29
            case '4':
847 25
                $formato = self::FORMATO_CONSUMIDOR;
848 25
                break;
849 29
            case '5':
850
                $formato = self::FORMATO_MENSAGEM;
851
                break;
852
        }
853 29
        $this->formato = $formato;
854 29
        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 27
    public function getEmissao($normalize = false)
863
    {
864 27
        if (!$normalize) {
865 27
            return $this->emissao;
866
        }
867 27
        switch ($this->emissao) {
868 27
            case self::EMISSAO_NORMAL:
869 27
                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 29
    public function setEmissao($emissao)
882
    {
883
        switch ($emissao) {
884 29
            case '1':
885 25
                $emissao = self::EMISSAO_NORMAL;
886 25
                break;
887 29
            case '9':
888
                $emissao = self::EMISSAO_CONTINGENCIA;
889
                break;
890
        }
891 29
        $this->emissao = $emissao;
892 29
        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 27
    public function getDigitoVerificador($normalize = false)
901
    {
902 27
        if (!$normalize) {
903 3
            return $this->digito_verificador;
904
        }
905 27
        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 29
    public function setDigitoVerificador($digito_verificador)
914
    {
915 29
        $this->digito_verificador = $digito_verificador;
916 29
        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 27
    public function getAmbiente($normalize = false)
925
    {
926 27
        if (!$normalize) {
927 27
            return $this->ambiente;
928
        }
929 27
        switch ($this->ambiente) {
930 27
            case self::AMBIENTE_PRODUCAO:
931
                return '1';
932 27
            case self::AMBIENTE_HOMOLOGACAO:
933 27
                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 29
    public function setAmbiente($ambiente)
944
    {
945
        switch ($ambiente) {
946 29
            case '1':
947
                $ambiente = self::AMBIENTE_PRODUCAO;
948
                break;
949 29
            case '2':
950 25
                $ambiente = self::AMBIENTE_HOMOLOGACAO;
951 25
                break;
952
        }
953 29
        $this->ambiente = $ambiente;
954 29
        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 27
    public function getFinalidade($normalize = false)
964
    {
965 27
        if (!$normalize) {
966 3
            return $this->finalidade;
967
        }
968 27
        switch ($this->finalidade) {
969 27
            case self::FINALIDADE_NORMAL:
970 27
                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 29
    public function setFinalidade($finalidade)
987
    {
988
        switch ($finalidade) {
989 29
            case '1':
990 25
                $finalidade = self::FINALIDADE_NORMAL;
991 25
                break;
992 29
            case '2':
993
                $finalidade = self::FINALIDADE_COMPLEMENTAR;
994
                break;
995 29
            case '3':
996
                $finalidade = self::FINALIDADE_AJUSTE;
997
                break;
998 29
            case '4':
999
                $finalidade = self::FINALIDADE_RETORNO;
1000
                break;
1001
        }
1002 29
        $this->finalidade = $finalidade;
1003 29
        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 27
    public function getConsumidorFinal($normalize = false)
1012
    {
1013 27
        if (!$normalize) {
1014 3
            return $this->consumidor_final;
1015
        }
1016 27
        switch ($this->consumidor_final) {
1017 27
            case 'N':
1018
                return '0';
1019 27
            case 'Y':
1020 27
                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 29
    public function setConsumidorFinal($consumidor_final)
1040
    {
1041 29
        if (!in_array($consumidor_final, array('N', 'Y'))) {
1042 25
            $consumidor_final = $consumidor_final?'Y':'N';
1043 25
        }
1044 29
        $this->consumidor_final = $consumidor_final;
1045 29
        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 27
    public function getPresenca($normalize = false)
1058
    {
1059 27
        if (!$normalize) {
1060 3
            return $this->presenca;
1061
        }
1062 27
        switch ($this->presenca) {
1063 27
            case self::PRESENCA_NENHUM:
1064
                return '0';
1065 27
            case self::PRESENCA_PRESENCIAL:
1066 27
                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 29
    public function setPresenca($presenca)
1085
    {
1086
        switch ($presenca) {
1087 29
            case '0':
1088
                $presenca = self::PRESENCA_NENHUM;
1089
                break;
1090 29
            case '1':
1091 25
                $presenca = self::PRESENCA_PRESENCIAL;
1092 25
                break;
1093 29
            case '2':
1094
                $presenca = self::PRESENCA_INTERNET;
1095
                break;
1096 29
            case '3':
1097
                $presenca = self::PRESENCA_TELEATENDIMENTO;
1098
                break;
1099 29
            case '4':
1100
                $presenca = self::PRESENCA_ENTREGA;
1101
                break;
1102 29
            case '9':
1103
                $presenca = self::PRESENCA_OUTROS;
1104
                break;
1105
        }
1106 29
        $this->presenca = $presenca;
1107 29
        return $this;
1108
    }
1109
1110
    /**
1111
     * Dados dos totais da NF-e
1112
     * @return mixed total da Nota
1113
     */
1114 27
    public function getTotal()
1115
    {
1116 27
        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 29
    public function setTotal($total)
1125
    {
1126 29
        $this->total = $total;
1127 29
        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 27
    public function getAdicionais($normalize = false)
1136
    {
1137 27
        if (!$normalize) {
1138 27
            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 29
    public function setAdicionais($adicionais)
1149
    {
1150 29
        $this->adicionais = $adicionais;
1151 29
        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 27
    public function getObservacoes()
1160
    {
1161 27
        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 29
    public function setObservacoes($observacoes)
1170
    {
1171 29
        $this->observacoes = $observacoes;
1172 29
        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 27
    public function getInformacoes()
1192
    {
1193 27
        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 29
    public function setInformacoes($informacoes)
1202
    {
1203 29
        $this->informacoes = $informacoes;
1204 29
        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 25
    public function getProtocolo()
1223
    {
1224 25
        return $this->protocolo;
1225
    }
1226
1227 29
    public function setProtocolo($protocolo)
1228
    {
1229 29
        $this->protocolo = $protocolo;
1230 29
        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 29
    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 29
        if ($nota instanceof Nota) {
1310
            $nota = $nota->toArray();
1311 29
        } elseif (!is_array($nota)) {
1312
            return $this;
1313
        }
1314 29
        if (isset($nota['id'])) {
1315
            $this->setID($nota['id']);
1316
        } else {
1317 29
            $this->setID(null);
1318
        }
1319 29
        if (isset($nota['numero'])) {
1320 2
            $this->setNumero($nota['numero']);
1321 2
        } else {
1322 29
            $this->setNumero(null);
1323
        }
1324 29
        if (!isset($nota['emitente']) || is_null($nota['emitente'])) {
1325 29
            $this->setEmitente(new Emitente());
1326 29
        } else {
1327 2
            $this->setEmitente($nota['emitente']);
1328
        }
1329 29
        if (!isset($nota['destinatario']) || is_null($nota['destinatario'])) {
1330 29
            $this->setDestinatario(new Destinatario());
1331 29
        } else {
1332 2
            $this->setDestinatario($nota['destinatario']);
1333
        }
1334 29
        if (!isset($nota['produtos']) || is_null($nota['produtos'])) {
1335 29
            $this->setProdutos(array());
1336 29
        } else {
1337 2
            $this->setProdutos($nota['produtos']);
1338
        }
1339 29
        if (!isset($nota['transporte']) || is_null($nota['transporte'])) {
1340 29
            $this->setTransporte(new Transporte());
1341 29
        } else {
1342 2
            $this->setTransporte($nota['transporte']);
1343
        }
1344 29
        if (!isset($nota['pagamentos']) || is_null($nota['pagamentos'])) {
1345 29
            $this->setPagamentos(array());
1346 29
        } else {
1347 2
            $this->setPagamentos($nota['pagamentos']);
1348
        }
1349 29
        if (isset($nota['data_movimentacao'])) {
1350
            $this->setDataMovimentacao($nota['data_movimentacao']);
1351
        } else {
1352 29
            $this->setDataMovimentacao(null);
1353
        }
1354 29
        if (isset($nota['data_contingencia'])) {
1355
            $this->setDataContingencia($nota['data_contingencia']);
1356
        } else {
1357 29
            $this->setDataContingencia(null);
1358
        }
1359 29
        if (isset($nota['justificativa'])) {
1360
            $this->setJustificativa($nota['justificativa']);
1361
        } else {
1362 29
            $this->setJustificativa(null);
1363
        }
1364 29
        if (isset($nota['modelo'])) {
1365 2
            $this->setModelo($nota['modelo']);
1366 2
        } else {
1367 29
            $this->setModelo(null);
1368
        }
1369 29
        if (!isset($nota['tipo']) || is_null($nota['tipo'])) {
1370 29
            $this->setTipo(self::TIPO_SAIDA);
1371 29
        } else {
1372 2
            $this->setTipo($nota['tipo']);
1373
        }
1374 29
        if (!isset($nota['destino']) || is_null($nota['destino'])) {
1375 29
            $this->setDestino(self::DESTINO_INTERNA);
1376 29
        } else {
1377 2
            $this->setDestino($nota['destino']);
1378
        }
1379 29
        if (!isset($nota['natureza']) || is_null($nota['natureza'])) {
1380 29
            $this->setNatureza('VENDA PARA CONSUMIDOR FINAL');
1381 29
        } else {
1382 2
            $this->setNatureza($nota['natureza']);
1383
        }
1384 29
        if (isset($nota['codigo'])) {
1385 2
            $this->setCodigo($nota['codigo']);
1386 2
        } else {
1387 29
            $this->setCodigo(null);
1388
        }
1389 29
        if (!isset($nota['indicador']) || is_null($nota['indicador'])) {
1390 29
            $this->setIndicador(self::INDICADOR_AVISTA);
1391 29
        } else {
1392 2
            $this->setIndicador($nota['indicador']);
1393
        }
1394 29
        if (isset($nota['data_emissao'])) {
1395 2
            $this->setDataEmissao($nota['data_emissao']);
1396 2
        } else {
1397 29
            $this->setDataEmissao(null);
1398
        }
1399 29
        if (isset($nota['serie'])) {
1400 2
            $this->setSerie($nota['serie']);
1401 2
        } else {
1402 29
            $this->setSerie(null);
1403
        }
1404 29
        if (!isset($nota['formato']) || is_null($nota['formato'])) {
1405 29
            $this->setFormato(self::FORMATO_NENHUMA);
1406 29
        } else {
1407 2
            $this->setFormato($nota['formato']);
1408
        }
1409 29
        if (!isset($nota['emissao']) || is_null($nota['emissao'])) {
1410 29
            $this->setEmissao(self::EMISSAO_NORMAL);
1411 29
        } else {
1412 2
            $this->setEmissao($nota['emissao']);
1413
        }
1414 29
        if (isset($nota['digito_verificador'])) {
1415
            $this->setDigitoVerificador($nota['digito_verificador']);
1416
        } else {
1417 29
            $this->setDigitoVerificador(null);
1418
        }
1419 29
        if (!isset($nota['ambiente']) || is_null($nota['ambiente'])) {
1420 29
            $this->setAmbiente(self::AMBIENTE_HOMOLOGACAO);
1421 29
        } else {
1422 2
            $this->setAmbiente($nota['ambiente']);
1423
        }
1424 29
        if (!isset($nota['finalidade']) || is_null($nota['finalidade'])) {
1425 29
            $this->setFinalidade(self::FINALIDADE_NORMAL);
1426 29
        } else {
1427 2
            $this->setFinalidade($nota['finalidade']);
1428
        }
1429 29
        if (!isset($nota['consumidor_final']) || is_null($nota['consumidor_final'])) {
1430 29
            $this->setConsumidorFinal('Y');
1431 29
        } else {
1432 2
            $this->setConsumidorFinal($nota['consumidor_final']);
1433
        }
1434 29
        if (isset($nota['presenca'])) {
1435 2
            $this->setPresenca($nota['presenca']);
1436 2
        } else {
1437 29
            $this->setPresenca(null);
1438
        }
1439 29
        if (!isset($nota['total'])) {
1440 29
            $this->setTotal(new Total());
1441 29
        } else {
1442 2
            $this->setTotal($nota['total']);
1443
        }
1444 29
        if (!array_key_exists('adicionais', $nota)) {
1445 29
            $this->setAdicionais(null);
1446 29
        } else {
1447 2
            $this->setAdicionais($nota['adicionais']);
1448
        }
1449 29
        if (!array_key_exists('observacoes', $nota)) {
1450 29
            $this->setObservacoes(null);
1451 29
        } else {
1452 2
            $this->setObservacoes($nota['observacoes']);
1453
        }
1454 29
        if (!array_key_exists('informacoes', $nota)) {
1455 29
            $this->setInformacoes(null);
1456 29
        } else {
1457 2
            $this->setInformacoes($nota['informacoes']);
1458
        }
1459 29
        if (isset($nota['protocolo'])) {
1460
            $this->setProtocolo($nota['protocolo']);
1461
        } else {
1462 29
            $this->setProtocolo(null);
1463
        }
1464 29
        return $this;
1465
    }
1466
1467 27
    public function gerarID()
1468
    {
1469 27
        $estado = $this->getEmitente()->getEndereco()->getMunicipio()->getEstado();
1470 27
        $estado->checkCodigos();
1471 27
        $id = sprintf(
1472 27
            '%02d%02d%02d%s%02d%03d%09d%01d%08d',
1473 27
            $estado->getCodigo(),
1474 27
            date('y', $this->getDataEmissao()), // Ano 2 dígitos
1475 27
            date('m', $this->getDataEmissao()), // Mês 2 dígitos
1476 27
            $this->getEmitente()->getCNPJ(),
1477 27
            $this->getModelo(true),
1478 27
            $this->getSerie(),
1479 27
            $this->getNumero(),
1480 27
            $this->getEmissao(true),
1481 27
            $this->getCodigo()
1482 27
        );
1483 27
        return $id.Util::getDAC($id, 11);
1484
    }
1485
1486 27
    protected function getTotais()
1487
    {
1488 27
        $total = array();
1489 27
        $total['produtos'] = 0.00;
1490 27
        $total['desconto'] = 0.00;
1491 27
        $total['frete'] = 0.00;
1492 27
        $total['seguro'] = 0.00;
1493 27
        $total['despesas'] = 0.00;
1494 27
        $total['tributos'] = 0.00;
1495 27
        $total['icms'] = 0.00;
1496 27
        $total['icms.st'] = 0.00;
1497 27
        $total['base'] = 0.00;
1498 27
        $total['base.st'] = 0.00;
1499 27
        $total['ii'] = 0.00;
1500 27
        $total['ipi'] = 0.00;
1501 27
        $total['pis'] = 0.00;
1502 27
        $total['cofins'] = 0.00;
1503 27
        $total['desoneracao'] = 0.00;
1504 27
        $_produtos = $this->getProdutos();
1505 27
        foreach ($_produtos as $_produto) {
1506 27
            if (!$_produto->getMultiplicador()) {
1507
                continue;
1508
            }
1509 27
            $imposto_info = $_produto->getImpostoInfo();
1510 27
            $total['produtos'] += round($_produto->getPreco(), 2);
1511 27
            $total['desconto'] += round($_produto->getDesconto(), 2);
1512 27
            $total['frete'] += round($_produto->getFrete(), 2);
1513 27
            $total['seguro'] += round($_produto->getSeguro(), 2);
1514 27
            $total['despesas'] += round($_produto->getDespesas(), 2);
1515 27
            $total['tributos'] += round($imposto_info['total'], 2);
1516 27
            $_impostos = $_produto->getImpostos();
1517 27
            foreach ($_impostos as $_imposto) {
1518 27
                switch ($_imposto->getGrupo()) {
1519 27
                    case Imposto::GRUPO_ICMS:
1520 27
                        if (($_imposto instanceof \NFe\Entity\Imposto\ICMS\Cobranca) ||
1521 27
                                ($_imposto instanceof \NFe\Entity\Imposto\ICMS\Simples\Cobranca)) {
1522 27
                            $total[$_imposto->getGrupo()] += round($_imposto->getNormal()->getValor(), 2);
1523 27
                            $total['base'] += round($_imposto->getNormal()->getBase(), 2);
1524 27
                        }
1525 27
                        if (($_imposto instanceof \NFe\Entity\Imposto\ICMS\Parcial) ||
1526 27
                                ($_imposto instanceof \NFe\Entity\Imposto\ICMS\Simples\Parcial)) {
1527 27
                            $total['icms.st'] += round($_imposto->getValor(), 2);
1528 27
                            $total['base.st'] += round($_imposto->getBase(), 2);
1529 27
                        } else {
1530
                            $total[$_imposto->getGrupo()] += round($_imposto->getValor(), 2);
1531
                            $total['base'] += round($_imposto->getBase(), 2);
1532
                        }
1533 27
                        break;
1534 27
                    default:
1535 27
                        $total[$_imposto->getGrupo()] += round($_imposto->getValor(), 2);
1536 27
                }
1537 27
            }
1538 27
        }
1539 27
        $produtos = round($total['produtos'], 2) - round($total['desconto'], 2);
1540 27
        $servicos = round($total['frete'], 2) + round($total['seguro'], 2) + round($total['despesas'], 2);
1541 27
        $impostos = round($total['ii'], 2) + round($total['ipi'], 2) + round($total['icms.st'], 2);
1542 27
        $impostos = $impostos - round($total['desoneracao'], 2);
1543 27
        $total['nota'] = $produtos + $servicos + $impostos;
1544 27
        return $total;
1545
    }
1546
1547 27
    private function getNodeTotal($name = null)
1548
    {
1549 27
        $dom = new \DOMDocument('1.0', 'UTF-8');
1550 27
        $element = $dom->createElement(is_null($name)?'total':$name);
1551
1552
        // Totais referentes ao ICMS
1553 27
        $total = $this->getTotais();
1554 27
        $icms = $dom->createElement('ICMSTot');
1555 27
        Util::appendNode($icms, 'vBC', Util::toCurrency($total['base']));
1556 27
        Util::appendNode($icms, 'vICMS', Util::toCurrency($total['icms']));
1557 27
        Util::appendNode($icms, 'vICMSDeson', Util::toCurrency($total['desoneracao']));
1558 27
        Util::appendNode($icms, 'vBCST', Util::toCurrency($total['base.st']));
1559 27
        Util::appendNode($icms, 'vST', Util::toCurrency($total['icms.st']));
1560 27
        Util::appendNode($icms, 'vProd', Util::toCurrency($total['produtos']));
1561 27
        Util::appendNode($icms, 'vFrete', Util::toCurrency($total['frete']));
1562 27
        Util::appendNode($icms, 'vSeg', Util::toCurrency($total['seguro']));
1563 27
        Util::appendNode($icms, 'vDesc', Util::toCurrency($total['desconto']));
1564 27
        Util::appendNode($icms, 'vII', Util::toCurrency($total['ii']));
1565 27
        Util::appendNode($icms, 'vIPI', Util::toCurrency($total['ipi']));
1566 27
        Util::appendNode($icms, 'vPIS', Util::toCurrency($total['pis']));
1567 27
        Util::appendNode($icms, 'vCOFINS', Util::toCurrency($total['cofins']));
1568 27
        Util::appendNode($icms, 'vOutro', Util::toCurrency($total['despesas']));
1569 27
        Util::appendNode($icms, 'vNF', Util::toCurrency($total['nota']));
1570 27
        Util::appendNode($icms, 'vTotTrib', Util::toCurrency($total['tributos']));
1571 27
        $element->appendChild($icms);
1572 27
        $this->setTotal(new Total($total));
1573 27
        $this->getTotal()->setProdutos($total['produtos']);
1574
1575
        // TODO: Totais referentes ao ISSQN
1576
1577
        // TODO: Retenção de Tributos Federais
1578 27
        return $element;
1579
    }
1580
1581 27
    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 27
        $this->getEmitente()->getEndereco()->checkCodigos();
1584 27
        $this->setID($this->gerarID());
1585 27
        $this->setDigitoVerificador(substr($this->getID(), -1, 1));
1586
1587 27
        $dom = new \DOMDocument('1.0', 'UTF-8');
1588 27
        $element = $dom->createElement(is_null($name)?'NFe':$name);
1589 27
        $element->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', self::PORTAL);
1590
1591 27
        $info = $dom->createElement('infNFe');
1592 27
        $id = $dom->createAttribute('Id');
1593 27
        $id->value = $this->getID(true);
1594 27
        $info->appendChild($id);
1595 27
        $versao = $dom->createAttribute('versao');
1596 27
        $versao->value = self::VERSAO;
1597 27
        $info->appendChild($versao);
1598
1599 27
        $municipio = $this->getEmitente()->getEndereco()->getMunicipio();
1600 27
        $estado = $municipio->getEstado();
1601 27
        $ident = $dom->createElement('ide');
1602 27
        Util::appendNode($ident, 'cUF', $estado->getCodigo(true));
1603 27
        Util::appendNode($ident, 'cNF', $this->getCodigo(true));
1604 27
        Util::appendNode($ident, 'natOp', $this->getNatureza(true));
1605 27
        Util::appendNode($ident, 'indPag', $this->getIndicador(true));
1606 27
        Util::appendNode($ident, 'mod', $this->getModelo(true));
1607 27
        Util::appendNode($ident, 'serie', $this->getSerie(true));
1608 27
        Util::appendNode($ident, 'nNF', $this->getNumero(true));
1609 27
        Util::appendNode($ident, 'dhEmi', $this->getDataEmissao(true));
1610 27
        Util::appendNode($ident, 'tpNF', $this->getTipo(true));
1611 27
        Util::appendNode($ident, 'idDest', $this->getDestino(true));
1612 27
        Util::appendNode($ident, 'cMunFG', $municipio->getCodigo(true));
1613 27
        Util::appendNode($ident, 'tpImp', $this->getFormato(true));
1614 27
        Util::appendNode($ident, 'tpEmis', $this->getEmissao(true));
1615 27
        Util::appendNode($ident, 'cDV', $this->getDigitoVerificador(true));
1616 27
        Util::appendNode($ident, 'tpAmb', $this->getAmbiente(true));
1617 27
        Util::appendNode($ident, 'finNFe', $this->getFinalidade(true));
1618 27
        Util::appendNode($ident, 'indFinal', $this->getConsumidorFinal(true));
1619 27
        Util::appendNode($ident, 'indPres', $this->getPresenca(true));
1620 27
        Util::appendNode($ident, 'procEmi', 0); // emissão de NF-e com aplicativo do contribuinte
1621 27
        Util::appendNode($ident, 'verProc', self::APP_VERSAO);
1622 27
        if (!is_null($this->getDataMovimentacao())) {
1623
            Util::appendNode($ident, 'dhSaiEnt', $this->getDataMovimentacao(true));
1624
        }
1625 27
        if ($this->getEmissao() != self::EMISSAO_NORMAL) {
1626
            Util::appendNode($ident, 'dhCont', $this->getDataContingencia(true));
1627
            Util::appendNode($ident, 'xJust', $this->getJustificativa(true));
1628
        }
1629 27
        $info->appendChild($ident);
1630
1631 27
        $emitente = $this->getEmitente()->getNode();
1632 27
        $emitente = $dom->importNode($emitente, true);
1633 27
        $info->appendChild($emitente);
1634 27
        if ($this->getAmbiente() == self::AMBIENTE_HOMOLOGACAO && !is_null($this->getDestinatario())) {
1635 27
            $this->getDestinatario()->setNome('NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL');
1636 27
        }
1637 27
        if (!is_null($this->getDestinatario())) {
1638 27
            $destinatario = $this->getDestinatario()->getNode();
1639 27
            $destinatario = $dom->importNode($destinatario, true);
1640 27
            $info->appendChild($destinatario);
1641 27
        }
1642 27
        $item = 0;
1643 27
        $tributos = array();
1644 27
        $_produtos = $this->getProdutos();
1645 27
        foreach ($_produtos as $_produto) {
1646 27
            if (is_null($_produto->getItem())) {
1647 2
                $item += 1;
1648 2
                $_produto->setItem($item);
1649 2
            } else {
1650 25
                $item = $_produto->getItem();
1651
            }
1652 27
            if ($this->getAmbiente() == self::AMBIENTE_HOMOLOGACAO) {
1653 27
                $_produto->setDescricao('NOTA FISCAL EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL');
1654 27
            }
1655 27
            $produto = $_produto->getNode();
1656 27
            $produto = $dom->importNode($produto, true);
1657 27
            $info->appendChild($produto);
1658
            // Soma os tributos aproximados dos produtos
1659 27
            $imposto_info = $_produto->getImpostoInfo();
1660 27
            $tributos['info'] = $imposto_info['info'];
1661 27
            foreach ($imposto_info as $key => $value) {
1662 27
                if (!is_numeric($value)) {
1663 27
                    continue;
1664
                }
1665 27
                if (!isset($tributos[$key])) {
1666 27
                    $tributos[$key] = 0.00;
1667 27
                }
1668 27
                $tributos[$key] += $value;
1669 27
            }
1670 27
        }
1671 27
        $total = $this->getNodeTotal();
1672 27
        $total = $dom->importNode($total, true);
1673 27
        $info->appendChild($total);
1674 27
        $transporte = $this->getTransporte()->getNode();
1675 27
        $transporte = $dom->importNode($transporte, true);
1676 27
        $info->appendChild($transporte);
1677
        // TODO: adicionar cobrança
1678 27
        $_pagamentos = $this->getPagamentos();
1679 27
        foreach ($_pagamentos as $_pagamento) {
1680 27
            $pagamento = $_pagamento->getNode();
1681 27
            $pagamento = $dom->importNode($pagamento, true);
1682 27
            $info->appendChild($pagamento);
1683 27
        }
1684 27
        $info_adic = $dom->createElement('infAdic');
1685 27
        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 27
        $_complemento = Produto::addNodeInformacoes($tributos, $info_adic, 'infCpl');
1690 27
        $this->getTotal()->setComplemento($_complemento);
1691 27
        if (!is_null($this->getObservacoes())) {
1692 27
            $_observacoes = $this->getObservacoes();
1693 27
            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 27
                $observacoes = $dom->createElement('obsCont');
1695 27
                $campo = $dom->createAttribute('xCampo');
1696 27
                $campo->value = $_observacao['campo'];
1697 27
                $observacoes->appendChild($campo);
1698 27
                Util::appendNode($observacoes, 'xTexto', $_observacao['valor']);
1699 27
                $info_adic->appendChild($observacoes);
1700 27
            }
1701 27
        }
1702 27
        if (!is_null($this->getInformacoes())) {
1703 27
            $_informacoes = $this->getInformacoes();
1704 27
            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 27
                $informacoes = $dom->createElement('obsFisco');
1706 27
                $campo = $dom->createAttribute('xCampo');
1707 27
                $campo->value = $_informacao['campo'];
1708 27
                $informacoes->appendChild($campo);
1709 27
                Util::appendNode($informacoes, 'xTexto', $_informacao['valor']);
1710 27
                $info_adic->appendChild($informacoes);
1711 27
            }
1712 27
        }
1713 27
        $info->appendChild($info_adic);
1714
        // TODO: adicionar exportação
1715
        // TODO: adicionar compra
1716
        // TODO: adicionar cana
1717 27
        $element->appendChild($info);
1718 27
        $dom->appendChild($element);
1719 27
        return $element;
1720
    }
1721
1722 25
    public function loadNode($element, $name = null)
0 ignored issues
show
Complexity introduced by
This operation has 30720 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 25
        $root = $element;
1725 25
        $name = is_null($name)?'NFe':$name;
1726 25
        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 25
        $_fields = $element->getElementsByTagName('infNFe');
1734 25
        if ($_fields->length > 0) {
1735 25
            $info = $_fields->item(0);
1736 25
        } else {
1737
            throw new \Exception('Tag "infNFe" não encontrada', 404);
1738
        }
1739 25
        $id = $info->getAttribute('Id');
1740 25
        if (strlen($id) != 47) {
1741
            throw new \Exception('Atributo "Id" inválido, encontrado: "'.$id.'"', 500);
1742
        }
1743 25
        $this->setID(substr($id, 3));
1744 25
        $_fields = $info->getElementsByTagName('ide');
1745 25
        if ($_fields->length > 0) {
1746 25
            $ident = $_fields->item(0);
1747 25
        } else {
1748
            throw new \Exception('Tag "ide" não encontrada', 404);
1749
        }
1750 25
        $emitente = new Emitente();
1751 25
        $emitente->getEndereco()->getMunicipio()->getEstado()->setCodigo(
1752 25
            Util::loadNode(
1753 25
                $ident,
1754 25
                'cUF',
1755
                'Tag "cUF" do campo "Codigo IBGE da UF" não encontrada'
1756 25
            )
1757 25
        );
1758 25
        $this->setCodigo(
1759 25
            Util::loadNode(
1760 25
                $ident,
1761 25
                'cNF',
1762
                'Tag "cNF" do campo "Codigo" não encontrada'
1763 25
            )
1764 25
        );
1765 25
        $this->setNatureza(
1766 25
            Util::loadNode(
1767 25
                $ident,
1768 25
                'natOp',
1769
                'Tag "natOp" do campo "Natureza" não encontrada'
1770 25
            )
1771 25
        );
1772 25
        $this->setIndicador(
1773 25
            Util::loadNode(
1774 25
                $ident,
1775 25
                'indPag',
1776
                'Tag "indPag" do campo "Indicador" não encontrada'
1777 25
            )
1778 25
        );
1779 25
        $this->setModelo(
1780 25
            Util::loadNode(
1781 25
                $ident,
1782 25
                'mod',
1783
                'Tag "mod" do campo "Modelo" não encontrada'
1784 25
            )
1785 25
        );
1786 25
        $this->setSerie(
1787 25
            Util::loadNode(
1788 25
                $ident,
1789 25
                'serie',
1790
                'Tag "serie" do campo "Serie" não encontrada'
1791 25
            )
1792 25
        );
1793 25
        $this->setNumero(
1794 25
            Util::loadNode(
1795 25
                $ident,
1796 25
                'nNF',
1797
                'Tag "nNF" do campo "Numero" não encontrada'
1798 25
            )
1799 25
        );
1800 25
        $this->setDataEmissao(
1801 25
            Util::loadNode(
1802 25
                $ident,
1803 25
                'dhEmi',
1804
                'Tag "dhEmi" do campo "DataEmissao" não encontrada'
1805 25
            )
1806 25
        );
1807 25
        $this->setTipo(
1808 25
            Util::loadNode(
1809 25
                $ident,
1810 25
                'tpNF',
1811
                'Tag "tpNF" do campo "Tipo" não encontrada'
1812 25
            )
1813 25
        );
1814 25
        $this->setDestino(
1815 25
            Util::loadNode(
1816 25
                $ident,
1817 25
                'idDest',
1818
                'Tag "idDest" do campo "Destino" não encontrada'
1819 25
            )
1820 25
        );
1821 25
        $emitente->getEndereco()->getMunicipio()->setCodigo(
1822 25
            Util::loadNode(
1823 25
                $ident,
1824 25
                'cMunFG',
1825
                'Tag "cMunFG" do campo "Codigo IBGE do município" não encontrada'
1826 25
            )
1827 25
        );
1828 25
        $this->setDataMovimentacao(Util::loadNode($ident, 'dhSaiEnt'));
1829 25
        $this->setFormato(
1830 25
            Util::loadNode(
1831 25
                $ident,
1832 25
                'tpImp',
1833
                'Tag "tpImp" do campo "Formato" não encontrada'
1834 25
            )
1835 25
        );
1836 25
        $this->setEmissao(
1837 25
            Util::loadNode(
1838 25
                $ident,
1839 25
                'tpEmis',
1840
                'Tag "tpEmis" do campo "Emissao" não encontrada'
1841 25
            )
1842 25
        );
1843 25
        $this->setDigitoVerificador(
1844 25
            Util::loadNode(
1845 25
                $ident,
1846 25
                'cDV',
1847
                'Tag "cDV" do campo "DigitoVerificador" não encontrada'
1848 25
            )
1849 25
        );
1850 25
        $this->setAmbiente(
1851 25
            Util::loadNode(
1852 25
                $ident,
1853 25
                'tpAmb',
1854
                'Tag "tpAmb" do campo "Ambiente" não encontrada'
1855 25
            )
1856 25
        );
1857 25
        $this->setFinalidade(
1858 25
            Util::loadNode(
1859 25
                $ident,
1860 25
                'finNFe',
1861
                'Tag "finNFe" do campo "Finalidade" não encontrada'
1862 25
            )
1863 25
        );
1864 25
        $this->setConsumidorFinal(
1865 25
            Util::loadNode(
1866 25
                $ident,
1867 25
                'indFinal',
1868
                'Tag "indFinal" do campo "ConsumidorFinal" não encontrada'
1869 25
            )
1870 25
        );
1871 25
        $this->setPresenca(
1872 25
            Util::loadNode(
1873 25
                $ident,
1874 25
                'indPres',
1875
                'Tag "indPres" do campo "Presenca" não encontrada'
1876 25
            )
1877 25
        );
1878 25
        $this->setDataContingencia(Util::loadNode($ident, 'dhCont'));
1879 25
        $this->setJustificativa(Util::loadNode($ident, 'xJust'));
1880 25
        $emitente->loadNode(
1881 25
            Util::findNode(
1882 25
                $info,
1883 25
                'emit',
1884
                'Tag "emit" do objeto "Emitente" não encontrada'
1885 25
            ),
1886
            'emit'
1887 25
        );
1888 25
        $this->setEmitente($emitente);
1889 25
        $_fields = $info->getElementsByTagName('dest');
1890 25
        $destinatario = null;
1891 25
        if ($_fields->length > 0) {
1892 25
            $destinatario = new Destinatario();
1893 25
            $destinatario->loadNode($_fields->item(0), 'dest');
1894 25
        }
1895 25
        $this->setDestinatario($destinatario);
1896 25
        $produtos = array();
1897 25
        $_items = $info->getElementsByTagName('det');
1898 25
        foreach ($_items as $_item) {
1899 25
            $produto = new Produto();
1900 25
            $produto->loadNode($_item, 'det');
1901 25
            $produtos[] = $produto;
1902 25
        }
1903 25
        $this->setProdutos($produtos);
1904 25
        $_fields = $info->getElementsByTagName('transp');
1905 25
        $transporte = null;
1906 25
        if ($_fields->length > 0) {
1907 25
            $transporte = new Transporte();
1908 25
            $transporte->loadNode($_fields->item(0), 'transp');
1909 25
        }
1910 25
        $this->setTransporte($transporte);
1911 25
        $pagamentos = array();
1912 25
        $_items = $info->getElementsByTagName('pag');
1913 25
        foreach ($_items as $_item) {
1914 25
            $pagamento = new Pagamento();
1915 25
            $pagamento->loadNode($_item, 'pag');
1916 25
            $pagamentos[] = $pagamento;
1917 25
        }
1918 25
        $this->setPagamentos($pagamentos);
1919 25
        $_fields = $info->getElementsByTagName('total');
1920 25
        if ($_fields->length > 0) {
1921 25
            $total = new Total();
1922 25
            $total->loadNode($_fields->item(0), 'total');
1923 25
            $total->setComplemento(Util::loadNode($info, 'infCpl'));
1924 25
        } else {
1925
            throw new \Exception('Tag "total" do objeto "Total" não encontrada na Nota', 404);
1926
        }
1927 25
        $this->setTotal($total);
1928 25
        $this->setAdicionais(Util::loadNode($info, 'infAdFisco'));
1929 25
        $observacoes = array();
1930 25
        $_items = $info->getElementsByTagName('obsCont');
1931 25
        foreach ($_items as $_item) {
1932
            $observacao = array(
1933 25
                'campo' => $_item->getAttribute('xCampo'),
1934 25
                'valor' => Util::loadNode(
1935 25
                    $_item,
1936 25
                    'xTexto',
1937
                    'Tag "xTexto" do campo "Observação" não encontrada'
1938 25
                )
1939 25
            );
1940 25
            $observacoes[] = $observacao;
1941 25
        }
1942 25
        $this->setObservacoes($observacoes);
1943 25
        $informacoes = array();
1944 25
        $_items = $info->getElementsByTagName('obsFisco');
1945 25
        foreach ($_items as $_item) {
1946
            $informacao = array(
1947 25
                'campo' => $_item->getAttribute('xCampo'),
1948 25
                'valor' => Util::loadNode(
1949 25
                    $_item,
1950 25
                    'xTexto',
1951
                    'Tag "xTexto" do campo "Informação" não encontrada'
1952 25
                )
1953 25
            );
1954 25
            $informacoes[] = $informacao;
1955 25
        }
1956 25
        $this->setInformacoes($informacoes);
1957
1958 25
        $_fields = $root->getElementsByTagName('protNFe');
1959 25
        $protocolo = null;
1960 25
        if ($_fields->length > 0) {
1961 2
            $protocolo = new Protocolo();
1962 2
            $protocolo->loadNode($_fields->item(0), 'infProt');
1963 2
        }
1964 25
        $this->setProtocolo($protocolo);
1965 25
        return $element;
1966
    }
1967
1968
    /**
1969
     * Carrega um arquivo XML e preenche a nota com as informações dele
1970
     * @param  string $filename caminho do arquivo
1971
     * @return DOMDocument      objeto do documento carregado
1972
     */
1973 24
    public function load($filename)
1974
    {
1975 24
        $dom = new \DOMDocument();
1976 24
        if (!file_exists($filename)) {
1977
            throw new \Exception('Arquivo XML "'.$filename.'" não encontrado', 404);
1978
        }
1979 24
        $dom->load($filename);
1980 24
        $this->loadNode($dom->documentElement);
1981 24
        return $dom;
1982
    }
1983
1984
    /**
1985
     * Assina o XML com a assinatura eletrônica do tipo A1
1986
     */
1987 25
    public function assinar($dom = null)
1988
    {
1989 25
        if (is_null($dom)) {
1990 24
            $xml = $this->getNode();
1991 24
            $dom = $xml->ownerDocument;
1992 24
        }
1993 25
        $config = SEFAZ::getInstance()->getConfiguracao();
1994
1995 25
        $adapter = new XmlseclibsAdapter();
1996 25
        $adapter->setPrivateKey($config->getChavePrivada());
1997 25
        $adapter->setPublicKey($config->getChavePublica());
1998 25
        $adapter->addTransform(AdapterInterface::ENVELOPED);
1999 25
        $adapter->addTransform(AdapterInterface::XML_C14N);
2000 25
        $adapter->sign($dom, 'infNFe');
2001 25
        return $dom;
2002
    }
2003
2004
    /**
2005
     * Valida o documento após assinar
2006
     */
2007 23
    public function validar($dom)
2008
    {
2009 23
        $dom->loadXML($dom->saveXML());
2010 23
        $xsd_path = __DIR__ . '/schema';
2011 23
        if (is_null($this->getProtocolo())) {
2012 23
            $xsd_file = $xsd_path . '/nfe_v3.10.xsd';
2013 23
        } else {
2014
            $xsd_file = $xsd_path . '/procNFe_v3.10.xsd';
2015
        }
2016 23
        if (!file_exists($xsd_file)) {
2017
            throw new \Exception('O arquivo "'.$xsd_file.'" de esquema XSD não existe!', 404);
2018
        }
2019
        // Enable user error handling
2020 23
        $save = libxml_use_internal_errors(true);
2021 23
        if ($dom->schemaValidate($xsd_file)) {
2022 23
            libxml_use_internal_errors($save);
2023 23
            return $dom;
2024
        }
2025
        $msg = array();
2026
        $errors = libxml_get_errors();
2027
        foreach ($errors as $error) {
2028
            $msg[] = 'Não foi possível validar o XML: '.$error->message;
2029
        }
2030
        libxml_clear_errors();
2031
        libxml_use_internal_errors($save);
2032
        throw new ValidationException($msg);
2033
    }
2034
2035
    /**
2036
     * Adiciona o protocolo no XML da nota
2037
     */
2038 2
    public function addProtocolo($dom)
2039
    {
2040 2
        if (is_null($this->getProtocolo())) {
2041
            throw new \Exception('O protocolo não foi informado na nota "'.$this->getID().'"', 404);
2042
        }
2043 2
        $notae = $dom->getElementsByTagName('NFe')->item(0);
2044
        // Corrige xmlns:default
2045 2
        $notae_xml = $dom->saveXML($notae);
2046
2047 2
        $element = $dom->createElement('nfeProc');
2048 2
        $element->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', self::PORTAL);
2049 2
        $versao = $dom->createAttribute('versao');
2050 2
        $versao->value = self::VERSAO;
2051 2
        $element->appendChild($versao);
2052 2
        $dom->removeChild($notae);
2053
        // Corrige xmlns:default
2054 2
        $notae = $dom->createElement('NFe', 0);
2055
2056 2
        $element->appendChild($notae);
2057 2
        $info = $this->getProtocolo()->getNode();
2058 2
        $info = $dom->importNode($info, true);
2059 2
        $element->appendChild($info);
2060 2
        $dom->appendChild($element);
2061
        // Corrige xmlns:default
2062 2
        $xml = $dom->saveXML();
2063 2
        $xml = str_replace('<NFe>0</NFe>', $notae_xml, $xml);
2064 2
        $dom->loadXML($xml);
2065
2066 2
        return $dom;
2067
    }
2068
}
2069