Completed
Push — master ( f6da78...86bb06 )
by Francimar
03:45
created

Nota::setPresenca()   C

Complexity

Conditions 7
Paths 7

Size

Total Lines 25
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 12.2913

Importance

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

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

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

Loading history...
Complexity introduced by
This class has 1457 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 65 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 a complexity of 240 which exceeds the configured maximum of 50.

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

Some resources for further reading:

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

Loading history...
Complexity introduced by
The class Nota has a coupling between objects value of 19. Consider to reduce the number of dependencies under 13.
Loading history...
47
{
48
49
    const VERSAO = '3.10';
50
    const APP_VERSAO = '1.0';
51
    const PORTAL = 'http://www.portalfiscal.inf.br/nfe';
52
53
    /**
54
     * Código do modelo do Documento Fiscal. 55 = NF-e; 65 = NFC-e.
55
     */
56
    const MODELO_NFE = 'nfe';
57
    const MODELO_NFCE = 'nfce';
58
59
    /**
60
     * Tipo do Documento Fiscal (0 - entrada; 1 - saída)
61
     */
62
    const TIPO_ENTRADA = 'entrada';
63
    const TIPO_SAIDA = 'saida';
64
65
    /**
66
     * Identificador de Local de destino da operação
67
     * (1-Interna;2-Interestadual;3-Exterior)
68
     */
69
    const DESTINO_INTERNA = 'interna';
70
    const DESTINO_INTERESTADUAL = 'interestadual';
71
    const DESTINO_EXTERIOR = 'exterior';
72
73
    /**
74
     * Indicador da forma de pagamento: 0 – pagamento à vista; 1 – pagamento à
75
     * prazo; 2 – outros.
76
     */
77
    const INDICADOR_AVISTA = 'avista';
78
    const INDICADOR_APRAZO = 'aprazo';
79
    const INDICADOR_OUTROS = 'outros';
80
81
    /**
82
     * Formato de impressão do DANFE (0-sem DANFE;1-DANFe Retrato; 2-DANFe
83
     * Paisagem;3-DANFe Simplificado;4-DANFe NFC-e;5-DANFe NFC-e em mensagem
84
     * eletrônica)
85
     */
86
    const FORMATO_NENHUMA = 'nenhuma';
87
    const FORMATO_RETRATO = 'retrato';
88
    const FORMATO_PAISAGEM = 'paisagem';
89
    const FORMATO_SIMPLIFICADO = 'simplificado';
90
    const FORMATO_CONSUMIDOR = 'consumidor';
91
    const FORMATO_MENSAGEM = 'mensagem';
92
93
    /**
94
     * Forma de emissão da NF-e
95
     */
96
    const EMISSAO_NORMAL = 'normal';
97
    const EMISSAO_CONTINGENCIA = 'contingencia';
98
99
    /**
100
     * Identificação do Ambiente: 1 - Produção, 2 - Homologação
101
     */
102
    const AMBIENTE_PRODUCAO = 'producao';
103
    const AMBIENTE_HOMOLOGACAO = 'homologacao';
104
105
    /**
106
     * Finalidade da emissão da NF-e: 1 - NFe normal, 2 - NFe complementar, 3 -
107
     * NFe de ajuste, 4 - Devolução/Retorno
108
     */
109
    const FINALIDADE_NORMAL = 'normal';
110
    const FINALIDADE_COMPLEMENTAR = 'complementar';
111
    const FINALIDADE_AJUSTE = 'ajuste';
112
    const FINALIDADE_RETORNO = 'retorno';
113
114
    /**
115
     * Indicador de presença do comprador no estabelecimento comercial no
116
     * momento da oepração (0-Não se aplica, ex.: Nota Fiscal complementar ou
117
     * de ajuste;1-Operação presencial;2-Não presencial, internet;3-Não
118
     * presencial, teleatendimento;4-NFC-e entrega em domicílio;9-Não
119
     * presencial, outros)
120
     */
121
    const PRESENCA_NENHUM = 'nenhum';
122
    const PRESENCA_PRESENCIAL = 'presencial';
123
    const PRESENCA_INTERNET = 'internet';
124
    const PRESENCA_TELEATENDIMENTO = 'teleatendimento';
125
    const PRESENCA_ENTREGA = 'entrega';
126
    const PRESENCA_OUTROS = 'outros';
127
128
    private $id;
129
    private $numero;
130
    private $emitente;
131
    private $destinatario;
132
    private $produtos;
133
    private $transporte;
134
    private $pagamentos;
135
    private $data_movimentacao;
136
    private $data_contingencia;
137
    private $justificativa;
138
    private $modelo;
139
    private $tipo;
140
    private $destino;
141
    private $natureza;
142
    private $codigo;
143
    private $indicador;
144
    private $data_emissao;
145
    private $serie;
146
    private $formato;
147
    private $emissao;
148
    private $digito_verificador;
149
    private $ambiente;
150
    private $finalidade;
151
    private $consumidor_final;
152
    private $presenca;
153
    private $protocolo;
154
155 7
    public function __construct($nota = array())
156
    {
157 7
        $this->fromArray($nota);
158 7
    }
159
160 5
    public function getID($normalize = false)
161
    {
162 5
        if (!$normalize) {
163 5
            return $this->id;
164
        }
165 5
        return 'NFe'.$this->id;
166
    }
167
168 7
    public function setID($id)
169
    {
170 7
        $this->id = $id;
171 7
        return $this;
172
    }
173
174
    /**
175
     * Número do Documento Fiscal
176
     */
177 5
    public function getNumero($normalize = false)
178
    {
179 5
        if (!$normalize) {
180 5
            return $this->numero;
181
        }
182 5
        return $this->numero;
183
    }
184
185 7
    public function setNumero($numero)
186
    {
187 7
        $this->numero = $numero;
188 7
        return $this;
189
    }
190
191 5
    public function getEmitente()
192
    {
193 5
        return $this->emitente;
194
    }
195
196 7
    public function setEmitente($emitente)
197
    {
198 7
        $this->emitente = $emitente;
199 7
        return $this;
200
    }
201
202 5
    public function getDestinatario()
203
    {
204 5
        return $this->destinatario;
205
    }
206
207 7
    public function setDestinatario($destinatario)
208
    {
209 7
        $this->destinatario = $destinatario;
210 7
        return $this;
211
    }
212
213 5
    public function getProdutos()
214
    {
215 5
        return $this->produtos;
216
    }
217
218 7
    public function setProdutos($produtos)
219
    {
220 7
        $this->produtos = $produtos;
221 7
        return $this;
222
    }
223
224 2
    public function addProduto($produto)
225
    {
226 2
        $this->produtos[] = $produto;
227 2
        return $this;
228
    }
229
230 5
    public function getTransporte()
231
    {
232 5
        return $this->transporte;
233
    }
234
235 7
    public function setTransporte($transporte)
236
    {
237 7
        $this->transporte = $transporte;
238 7
        return $this;
239
    }
240
241 5
    public function getPagamentos()
242
    {
243 5
        return $this->pagamentos;
244
    }
245
246 7
    public function setPagamentos($pagamentos)
247
    {
248 7
        $this->pagamentos = $pagamentos;
249 7
        return $this;
250
    }
251
252 2
    public function addPagamento($pagamento)
253
    {
254 2
        $this->pagamentos[] = $pagamento;
255 2
        return $this;
256
    }
257
258
    /**
259
     * Data e Hora da saída ou de entrada da mercadoria / produto
260
     */
261 5
    public function getDataMovimentacao($normalize = false)
262
    {
263 5
        if (!$normalize) {
264 5
            return $this->data_movimentacao;
265
        }
266
        return Util::toDateTime($this->data_movimentacao);
267
    }
268
269 7
    public function setDataMovimentacao($data_movimentacao)
270
    {
271 7
        if (!is_null($data_movimentacao) && !is_numeric($data_movimentacao)) {
272
            $data_movimentacao = strtotime($data_movimentacao);
273
        }
274 7
        $this->data_movimentacao = $data_movimentacao;
275 7
        return $this;
276
    }
277
278
    /**
279
     * Informar a data e hora de entrada em contingência
280
     */
281 2
    public function getDataContingencia($normalize = false)
282
    {
283 2
        if (!$normalize) {
284 2
            return $this->data_contingencia;
285
        }
286
        return Util::toDateTime($this->data_contingencia);
287
    }
288
289 7
    public function setDataContingencia($data_contingencia)
290
    {
291 7
        if (!is_null($data_contingencia) && !is_numeric($data_contingencia)) {
292
            $data_contingencia = strtotime($data_contingencia);
293
        }
294 7
        $this->data_contingencia = $data_contingencia;
295 7
        return $this;
296
    }
297
298
    /**
299
     * Informar a Justificativa da entrada em contingência
300
     */
301 2
    public function getJustificativa($normalize = false)
302
    {
303 2
        if (!$normalize) {
304 2
            return $this->justificativa;
305
        }
306
        return $this->justificativa;
307
    }
308
309 7
    public function setJustificativa($justificativa)
310
    {
311 7
        $this->justificativa = $justificativa;
312 7
        return $this;
313
    }
314
315
    /**
316
     * Código do modelo do Documento Fiscal. 55 = NF-e; 65 = NFC-e.
317
     */
318 5
    public function getModelo($normalize = false)
319
    {
320 5
        if (!$normalize) {
321 4
            return $this->modelo;
322
        }
323 5
        switch ($this->modelo) {
324 5
            case self::MODELO_NFE:
325
                return '55';
326 5
            case self::MODELO_NFCE:
327 5
                return '65';
328
        }
329
        return $this->modelo;
330
    }
331
332 7
    public function setModelo($modelo)
333
    {
334
        switch ($modelo) {
335 7
            case '55':
336
                $modelo = self::MODELO_NFE;
337
                break;
338 7
            case '65':
339 3
                $modelo = self::MODELO_NFCE;
340 3
                break;
341
        }
342 7
        $this->modelo = $modelo;
343 7
        return $this;
344
    }
345
346
    /**
347
     * Tipo do Documento Fiscal (0 - entrada; 1 - saída)
348
     */
349 5
    public function getTipo($normalize = false)
350
    {
351 5
        if (!$normalize) {
352 2
            return $this->tipo;
353
        }
354 5
        switch ($this->tipo) {
355 5
            case self::TIPO_ENTRADA:
356
                return '0';
357 5
            case self::TIPO_SAIDA:
358 5
                return '1';
359
        }
360
        return $this->tipo;
361
    }
362
363 7
    public function setTipo($tipo)
364
    {
365
        switch ($tipo) {
366 7
            case '0':
367
                $tipo = self::TIPO_ENTRADA;
368
                break;
369 7
            case '1':
370 3
                $tipo = self::TIPO_SAIDA;
371 3
                break;
372
        }
373 7
        $this->tipo = $tipo;
374 7
        return $this;
375
    }
376
377
    /**
378
     * Identificador de Local de destino da operação
379
     * (1-Interna;2-Interestadual;3-Exterior)
380
     */
381 5
    public function getDestino($normalize = false)
382
    {
383 5
        if (!$normalize) {
384 2
            return $this->destino;
385
        }
386 5
        switch ($this->destino) {
387 5
            case self::DESTINO_INTERNA:
388 5
                return '1';
389
            case self::DESTINO_INTERESTADUAL:
390
                return '2';
391
            case self::DESTINO_EXTERIOR:
392
                return '3';
393
        }
394
        return $this->destino;
395
    }
396
397 7
    public function setDestino($destino)
398
    {
399
        switch ($destino) {
400 7
            case '1':
401 3
                $destino = self::DESTINO_INTERNA;
402 3
                break;
403 7
            case '2':
404
                $destino = self::DESTINO_INTERESTADUAL;
405
                break;
406 7
            case '3':
407
                $destino = self::DESTINO_EXTERIOR;
408
                break;
409
        }
410 7
        $this->destino = $destino;
411 7
        return $this;
412
    }
413
414
    /**
415
     * Descrição da Natureza da Operação
416
     */
417 5
    public function getNatureza($normalize = false)
418
    {
419 5
        if (!$normalize) {
420 2
            return $this->natureza;
421
        }
422 5
        return $this->natureza;
423
    }
424
425 7
    public function setNatureza($natureza)
426
    {
427 7
        $this->natureza = $natureza;
428 7
        return $this;
429
    }
430
431
    /**
432
     * Código numérico que compõe a Chave de Acesso. Número aleatório gerado
433
     * pelo emitente para cada NF-e.
434
     */
435 5
    public function getCodigo($normalize = false)
436
    {
437 5
        if (!$normalize) {
438 5
            return $this->codigo;
439
        }
440 5
        return Util::padDigit($this->codigo % 100000000, 8);
441
    }
442
443 7
    public function setCodigo($codigo)
444
    {
445 7
        $this->codigo = $codigo;
446 7
        return $this;
447
    }
448
449
    /**
450
     * Indicador da forma de pagamento: 0 – pagamento à vista; 1 – pagamento à
451
     * prazo; 2 – outros.
452
     */
453 5
    public function getIndicador($normalize = false)
454
    {
455 5
        if (!$normalize) {
456 2
            return $this->indicador;
457
        }
458 5
        switch ($this->indicador) {
459 5
            case self::INDICADOR_AVISTA:
460 5
                return '0';
461
            case self::INDICADOR_APRAZO:
462
                return '1';
463
            case self::INDICADOR_OUTROS:
464
                return '2';
465
        }
466
        return $this->indicador;
467
    }
468
469 7
    public function setIndicador($indicador)
470
    {
471
        switch ($indicador) {
472 7
            case '0':
473 3
                $indicador = self::INDICADOR_AVISTA;
474 3
                break;
475 7
            case '1':
476
                $indicador = self::INDICADOR_APRAZO;
477
                break;
478 7
            case '2':
479
                $indicador = self::INDICADOR_OUTROS;
480
                break;
481
        }
482 7
        $this->indicador = $indicador;
483 7
        return $this;
484
    }
485
486
    /**
487
     * Data e Hora de emissão do Documento Fiscal
488
     */
489 5
    public function getDataEmissao($normalize = false)
490
    {
491 5
        if (!$normalize) {
492 5
            return $this->data_emissao;
493
        }
494 5
        return Util::toDateTime($this->data_emissao);
495
    }
496
497 7
    public function setDataEmissao($data_emissao)
498
    {
499 7
        if (!is_numeric($data_emissao)) {
500 7
            $data_emissao = strtotime($data_emissao);
501 7
        }
502 7
        $this->data_emissao = $data_emissao;
503 7
        return $this;
504
    }
505
506
    /**
507
     * Série do Documento Fiscal: série normal 0-889, Avulsa Fisco 890-899,
508
     * SCAN 900-999
509
     */
510 5
    public function getSerie($normalize = false)
511
    {
512 5
        if (!$normalize) {
513 5
            return $this->serie;
514
        }
515 5
        return $this->serie;
516
    }
517
518 7
    public function setSerie($serie)
519
    {
520 7
        $this->serie = $serie;
521 7
        return $this;
522
    }
523
524
    /**
525
     * Formato de impressão do DANFE (0-sem DANFE;1-DANFe Retrato; 2-DANFe
526
     * Paisagem;3-DANFe Simplificado;4-DANFe NFC-e;5-DANFe NFC-e em mensagem
527
     * eletrônica)
528
     */
529 5
    public function getFormato($normalize = false)
530
    {
531 5
        if (!$normalize) {
532 2
            return $this->formato;
533
        }
534 5
        switch ($this->formato) {
535 5
            case self::FORMATO_NENHUMA:
536
                return '0';
537 5
            case self::FORMATO_RETRATO:
538
                return '1';
539 5
            case self::FORMATO_PAISAGEM:
540
                return '2';
541 5
            case self::FORMATO_SIMPLIFICADO:
542
                return '3';
543 5
            case self::FORMATO_CONSUMIDOR:
544 5
                return '4';
545
            case self::FORMATO_MENSAGEM:
546
                return '5';
547
        }
548
        return $this->formato;
549
    }
550
551 7
    public function setFormato($formato)
552
    {
553
        switch ($formato) {
554 7
            case '0':
555
                $formato = self::FORMATO_NENHUMA;
556
                break;
557 7
            case '1':
558
                $formato = self::FORMATO_RETRATO;
559
                break;
560 7
            case '2':
561
                $formato = self::FORMATO_PAISAGEM;
562
                break;
563 7
            case '3':
564
                $formato = self::FORMATO_SIMPLIFICADO;
565
                break;
566 7
            case '4':
567 3
                $formato = self::FORMATO_CONSUMIDOR;
568 3
                break;
569 7
            case '5':
570
                $formato = self::FORMATO_MENSAGEM;
571
                break;
572
        }
573 7
        $this->formato = $formato;
574 7
        return $this;
575
    }
576
577
    /**
578
     * Forma de emissão da NF-e
579
     */
580 5
    public function getEmissao($normalize = false)
581
    {
582 5
        if (!$normalize) {
583 5
            return $this->emissao;
584
        }
585 5
        switch ($this->emissao) {
586 5
            case self::EMISSAO_NORMAL:
587 5
                return '1';
588
            case self::EMISSAO_CONTINGENCIA:
589
                return '9';
590
        }
591
        return $this->emissao;
592
    }
593
594 7
    public function setEmissao($emissao)
595
    {
596
        switch ($emissao) {
597 7
            case '1':
598 3
                $emissao = self::EMISSAO_NORMAL;
599 3
                break;
600 7
            case '9':
601
                $emissao = self::EMISSAO_CONTINGENCIA;
602
                break;
603
        }
604 7
        $this->emissao = $emissao;
605 7
        return $this;
606
    }
607
608
    /**
609
     * Digito Verificador da Chave de Acesso da NF-e
610
     */
611 5
    public function getDigitoVerificador($normalize = false)
612
    {
613 5
        if (!$normalize) {
614 2
            return $this->digito_verificador;
615
        }
616 5
        return $this->digito_verificador;
617
    }
618
619 7
    public function setDigitoVerificador($digito_verificador)
620
    {
621 7
        $this->digito_verificador = $digito_verificador;
622 7
        return $this;
623
    }
624
625
    /**
626
     * Identificação do Ambiente: 1 - Produção, 2 - Homologação
627
     */
628 5
    public function getAmbiente($normalize = false)
629
    {
630 5
        if (!$normalize) {
631 5
            return $this->ambiente;
632
        }
633 5
        switch ($this->ambiente) {
634 5
            case self::AMBIENTE_PRODUCAO:
635
                return '1';
636 5
            case self::AMBIENTE_HOMOLOGACAO:
637 5
                return '2';
638
        }
639
        return $this->ambiente;
640
    }
641
642 7
    public function setAmbiente($ambiente)
643
    {
644
        switch ($ambiente) {
645 7
            case '1':
646
                $ambiente = self::AMBIENTE_PRODUCAO;
647
                break;
648 7
            case '2':
649 3
                $ambiente = self::AMBIENTE_HOMOLOGACAO;
650 3
                break;
651
        }
652 7
        $this->ambiente = $ambiente;
653 7
        return $this;
654
    }
655
656
    /**
657
     * Finalidade da emissão da NF-e: 1 - NFe normal, 2 - NFe complementar, 3 -
658
     * NFe de ajuste, 4 - Devolução/Retorno
659
     */
660 5
    public function getFinalidade($normalize = false)
661
    {
662 5
        if (!$normalize) {
663 2
            return $this->finalidade;
664
        }
665 5
        switch ($this->finalidade) {
666 5
            case self::FINALIDADE_NORMAL:
667 5
                return '1';
668
            case self::FINALIDADE_COMPLEMENTAR:
669
                return '2';
670
            case self::FINALIDADE_AJUSTE:
671
                return '3';
672
            case self::FINALIDADE_RETORNO:
673
                return '4';
674
        }
675
        return $this->finalidade;
676
    }
677
678 7
    public function setFinalidade($finalidade)
679
    {
680
        switch ($finalidade) {
681 7
            case '1':
682 3
                $finalidade = self::FINALIDADE_NORMAL;
683 3
                break;
684 7
            case '2':
685
                $finalidade = self::FINALIDADE_COMPLEMENTAR;
686
                break;
687 7
            case '3':
688
                $finalidade = self::FINALIDADE_AJUSTE;
689
                break;
690 7
            case '4':
691
                $finalidade = self::FINALIDADE_RETORNO;
692
                break;
693
        }
694 7
        $this->finalidade = $finalidade;
695 7
        return $this;
696
    }
697
698
    /**
699
     * Indica operação com consumidor final (0-Não;1-Consumidor Final)
700
     */
701 5
    public function getConsumidorFinal($normalize = false)
702
    {
703 5
        if (!$normalize) {
704 2
            return $this->consumidor_final;
705
        }
706 5
        switch ($this->consumidor_final) {
707 5
            case 'N':
708
                return '0';
709 5
            case 'Y':
710 5
                return '1';
711
        }
712
        return $this->consumidor_final;
713
    }
714
715
    /**
716
     * Indica operação com consumidor final (0-Não;1-Consumidor Final)
717
     */
718
    public function isConsumidorFinal()
719
    {
720
        return $this->consumidor_final == 'Y';
721
    }
722
723 7
    public function setConsumidorFinal($consumidor_final)
724
    {
725 7
        if (!in_array($consumidor_final, array('N', 'Y'))) {
726 3
            $consumidor_final = $consumidor_final?'Y':'N';
727 3
        }
728 7
        $this->consumidor_final = $consumidor_final;
729 7
        return $this;
730
    }
731
732
    /**
733
     * Indicador de presença do comprador no estabelecimento comercial no
734
     * momento da oepração (0-Não se aplica, ex.: Nota Fiscal complementar ou
735
     * de ajuste;1-Operação presencial;2-Não presencial, internet;3-Não
736
     * presencial, teleatendimento;4-NFC-e entrega em domicílio;9-Não
737
     * presencial, outros)
738
     */
739 5
    public function getPresenca($normalize = false)
740
    {
741 5
        if (!$normalize) {
742 2
            return $this->presenca;
743
        }
744 5
        switch ($this->presenca) {
745 5
            case self::PRESENCA_NENHUM:
746
                return '0';
747 5
            case self::PRESENCA_PRESENCIAL:
748 5
                return '1';
749
            case self::PRESENCA_INTERNET:
750
                return '2';
751
            case self::PRESENCA_TELEATENDIMENTO:
752
                return '3';
753
            case self::PRESENCA_ENTREGA:
754
                return '4';
755
            case self::PRESENCA_OUTROS:
756
                return '9';
757
        }
758
        return $this->presenca;
759
    }
760
761 7
    public function setPresenca($presenca)
762
    {
763
        switch ($presenca) {
764 7
            case '0':
765
                $presenca = self::PRESENCA_NENHUM;
766
                break;
767 7
            case '1':
768 3
                $presenca = self::PRESENCA_PRESENCIAL;
769 3
                break;
770 7
            case '2':
771
                $presenca = self::PRESENCA_INTERNET;
772
                break;
773 7
            case '3':
774
                $presenca = self::PRESENCA_TELEATENDIMENTO;
775
                break;
776 7
            case '4':
777
                $presenca = self::PRESENCA_ENTREGA;
778
                break;
779 7
            case '9':
780
                $presenca = self::PRESENCA_OUTROS;
781
                break;
782
        }
783 7
        $this->presenca = $presenca;
784 7
        return $this;
785
    }
786
787
    /**
788
     * Protocolo de autorização da nota, informado apenas quando a nota for
789
     * enviada e autorizada
790
     */
791 3
    public function getProtocolo()
792
    {
793 3
        return $this->protocolo;
794
    }
795
796 7
    public function setProtocolo($protocolo)
797
    {
798 7
        $this->protocolo = $protocolo;
799 7
        return $this;
800
    }
801
802 2
    public function toArray()
803
    {
804 2
        $nota = array();
805 2
        $nota['id'] = $this->getID();
806 2
        $nota['numero'] = $this->getNumero();
807 2
        $nota['emitente'] = $this->getEmitente();
808 2
        $nota['destinatario'] = $this->getDestinatario();
809 2
        $nota['produtos'] = $this->getProdutos();
810 2
        $nota['transporte'] = $this->getTransporte();
811 2
        $nota['pagamentos'] = $this->getPagamentos();
812 2
        $nota['data_movimentacao'] = $this->getDataMovimentacao();
813 2
        $nota['data_contingencia'] = $this->getDataContingencia();
814 2
        $nota['justificativa'] = $this->getJustificativa();
815 2
        $nota['modelo'] = $this->getModelo();
816 2
        $nota['tipo'] = $this->getTipo();
817 2
        $nota['destino'] = $this->getDestino();
818 2
        $nota['natureza'] = $this->getNatureza();
819 2
        $nota['codigo'] = $this->getCodigo();
820 2
        $nota['indicador'] = $this->getIndicador();
821 2
        $nota['data_emissao'] = $this->getDataEmissao();
822 2
        $nota['serie'] = $this->getSerie();
823 2
        $nota['formato'] = $this->getFormato();
824 2
        $nota['emissao'] = $this->getEmissao();
825 2
        $nota['digito_verificador'] = $this->getDigitoVerificador();
826 2
        $nota['ambiente'] = $this->getAmbiente();
827 2
        $nota['finalidade'] = $this->getFinalidade();
828 2
        $nota['consumidor_final'] = $this->getConsumidorFinal();
829 2
        $nota['presenca'] = $this->getPresenca();
830 2
        $nota['protocolo'] = $this->getProtocolo();
831 2
        return $nota;
832
    }
833
834 7
    public function fromArray($nota = array())
0 ignored issues
show
Complexity introduced by
This operation has 58773123072 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...
835
    {
836 7
        if ($nota instanceof Nota) {
837
            $nota = $nota->toArray();
838 7
        } elseif (!is_array($nota)) {
839
            return $this;
840
        }
841 7
        if (isset($nota['id'])) {
842
            $this->setID($nota['id']);
843
        } else {
844 7
            $this->setID(null);
845
        }
846 7
        if (isset($nota['numero'])) {
847 2
            $this->setNumero($nota['numero']);
848 2
        } else {
849 7
            $this->setNumero(null);
850
        }
851 7
        if (!isset($nota['emitente']) || is_null($nota['emitente'])) {
852 7
            $this->setEmitente(new Emitente());
853 7
        } else {
854 2
            $this->setEmitente($nota['emitente']);
855
        }
856 7
        if (!isset($nota['destinatario']) || is_null($nota['destinatario'])) {
857 7
            $this->setDestinatario(new Destinatario());
858 7
        } else {
859 2
            $this->setDestinatario($nota['destinatario']);
860
        }
861 7
        if (!isset($nota['produtos']) || is_null($nota['produtos'])) {
862 7
            $this->setProdutos(array());
863 7
        } else {
864 2
            $this->setProdutos($nota['produtos']);
865
        }
866 7
        if (!isset($nota['transporte']) || is_null($nota['transporte'])) {
867 7
            $this->setTransporte(new Transporte());
868 7
        } else {
869 2
            $this->setTransporte($nota['transporte']);
870
        }
871 7
        if (!isset($nota['pagamentos']) || is_null($nota['pagamentos'])) {
872 7
            $this->setPagamentos(array());
873 7
        } else {
874 2
            $this->setPagamentos($nota['pagamentos']);
875
        }
876 7
        if (isset($nota['data_movimentacao'])) {
877
            $this->setDataMovimentacao($nota['data_movimentacao']);
878
        } else {
879 7
            $this->setDataMovimentacao(null);
880
        }
881 7
        if (isset($nota['data_contingencia'])) {
882
            $this->setDataContingencia($nota['data_contingencia']);
883
        } else {
884 7
            $this->setDataContingencia(null);
885
        }
886 7
        if (isset($nota['justificativa'])) {
887
            $this->setJustificativa($nota['justificativa']);
888
        } else {
889 7
            $this->setJustificativa(null);
890
        }
891 7
        if (isset($nota['modelo'])) {
892 2
            $this->setModelo($nota['modelo']);
893 2
        } else {
894 7
            $this->setModelo(null);
895
        }
896 7
        if (!isset($nota['tipo']) || is_null($nota['tipo'])) {
897 7
            $this->setTipo(self::TIPO_SAIDA);
898 7
        } else {
899 2
            $this->setTipo($nota['tipo']);
900
        }
901 7
        if (!isset($nota['destino']) || is_null($nota['destino'])) {
902 7
            $this->setDestino(self::DESTINO_INTERNA);
903 7
        } else {
904 2
            $this->setDestino($nota['destino']);
905
        }
906 7
        if (!isset($nota['natureza']) || is_null($nota['natureza'])) {
907 7
            $this->setNatureza('VENDA PARA CONSUMIDOR FINAL');
908 7
        } else {
909 2
            $this->setNatureza($nota['natureza']);
910
        }
911 7
        if (isset($nota['codigo'])) {
912 2
            $this->setCodigo($nota['codigo']);
913 2
        } else {
914 7
            $this->setCodigo(null);
915
        }
916 7
        if (!isset($nota['indicador']) || is_null($nota['indicador'])) {
917 7
            $this->setIndicador(self::INDICADOR_AVISTA);
918 7
        } else {
919 2
            $this->setIndicador($nota['indicador']);
920
        }
921 7
        if (isset($nota['data_emissao'])) {
922 2
            $this->setDataEmissao($nota['data_emissao']);
923 2
        } else {
924 7
            $this->setDataEmissao(null);
925
        }
926 7
        if (isset($nota['serie'])) {
927 2
            $this->setSerie($nota['serie']);
928 2
        } else {
929 7
            $this->setSerie(null);
930
        }
931 7
        if (!isset($nota['formato']) || is_null($nota['formato'])) {
932 7
            $this->setFormato(self::FORMATO_NENHUMA);
933 7
        } else {
934 2
            $this->setFormato($nota['formato']);
935
        }
936 7
        if (!isset($nota['emissao']) || is_null($nota['emissao'])) {
937 7
            $this->setEmissao(self::EMISSAO_NORMAL);
938 7
        } else {
939 2
            $this->setEmissao($nota['emissao']);
940
        }
941 7
        if (isset($nota['digito_verificador'])) {
942
            $this->setDigitoVerificador($nota['digito_verificador']);
943
        } else {
944 7
            $this->setDigitoVerificador(null);
945
        }
946 7
        if (!isset($nota['ambiente']) || is_null($nota['ambiente'])) {
947 7
            $this->setAmbiente(self::AMBIENTE_HOMOLOGACAO);
948 7
        } else {
949 2
            $this->setAmbiente($nota['ambiente']);
950
        }
951 7
        if (!isset($nota['finalidade']) || is_null($nota['finalidade'])) {
952 7
            $this->setFinalidade(self::FINALIDADE_NORMAL);
953 7
        } else {
954 2
            $this->setFinalidade($nota['finalidade']);
955
        }
956 7
        if (!isset($nota['consumidor_final']) || is_null($nota['consumidor_final'])) {
957 7
            $this->setConsumidorFinal('Y');
958 7
        } else {
959 2
            $this->setConsumidorFinal($nota['consumidor_final']);
960
        }
961 7
        if (isset($nota['presenca'])) {
962 2
            $this->setPresenca($nota['presenca']);
963 2
        } else {
964 7
            $this->setPresenca(null);
965
        }
966 7
        if (isset($nota['protocolo'])) {
967
            $this->setProtocolo($nota['protocolo']);
968
        } else {
969 7
            $this->setProtocolo(null);
970
        }
971 7
        return $this;
972
    }
973
974 5
    public function gerarID()
975
    {
976 5
        $estado = $this->getEmitente()->getEndereco()->getMunicipio()->getEstado();
977 5
        $estado->checkCodigos();
978 5
        $id = sprintf(
979 5
            '%02d%02d%02d%s%02d%03d%09d%01d%08d',
980 5
            $estado->getCodigo(),
981 5
            date('y', $this->getDataEmissao()), // Ano 2 dígitos
982 5
            date('m', $this->getDataEmissao()), // Mês 2 dígitos
983 5
            $this->getEmitente()->getCNPJ(),
984 5
            $this->getModelo(true),
985 5
            $this->getSerie(),
986 5
            $this->getNumero(),
987 5
            $this->getEmissao(true),
988 5
            $this->getCodigo()
989 5
        );
990 5
        return $id.Util::getDAC($id, 11);
991
    }
992
993 5
    protected function getTotais()
994
    {
995 5
        $total = array();
996 5
        $total['produtos'] = 0.00;
997 5
        $total['descontos'] = 0.00;
998 5
        $total['frete'] = 0.00;
999 5
        $total['seguro'] = 0.00;
1000 5
        $total['outros'] = 0.00;
1001 5
        $total['nota'] = 0.00;
1002 5
        $total['tributos'] = 0.00;
1003 5
        $total['icms'] = 0.00;
1004 5
        $total['icms.st'] = 0.00;
1005 5
        $total['base'] = 0.00;
1006 5
        $total['base.st'] = 0.00;
1007 5
        $total['ii'] = 0.00;
1008 5
        $total['ipi'] = 0.00;
1009 5
        $total['pis'] = 0.00;
1010 5
        $total['cofins'] = 0.00;
1011 5
        $total['desoneracao'] = 0.00;
1012 5
        $_produtos = $this->getProdutos();
1013 5
        foreach ($_produtos as $_produto) {
1014 5
            $imposto_info = $_produto->getImpostoInfo();
1015 5
            $total['produtos'] += $_produto->getPreco();
1016 5
            $total['descontos'] += $_produto->getDesconto();
1017 5
            $total['frete'] += $_produto->getFrete();
1018 5
            $total['seguro'] += $_produto->getSeguro();
1019 5
            $total['outros'] += $_produto->getDespesas();
1020 5
            $total['nota'] += $_produto->getContabilizado();
1021 5
            $total['tributos'] += $imposto_info['total'];
1022 5
            $_impostos = $_produto->getImpostos();
1023 5
            foreach ($_impostos as $_imposto) {
1024 5
                switch ($_imposto->getGrupo()) {
1025 5
                    case Imposto::GRUPO_ICMS:
1026 5
                        if (($_imposto instanceof \NFe\Entity\Imposto\ICMS\Cobranca) ||
1027 5
                                ($_imposto instanceof \NFe\Entity\Imposto\ICMS\Simples\Cobranca)) {
1028 5
                            $total[$_imposto->getGrupo()] += round($_imposto->getNormal()->getValor(), 2);
1029 5
                            $total['base'] += $_imposto->getNormal()->getBase();
1030 5
                        }
1031 5
                        if (($_imposto instanceof \NFe\Entity\Imposto\ICMS\Parcial) ||
1032 5
                                ($_imposto instanceof \NFe\Entity\Imposto\ICMS\Simples\Parcial)) {
1033 5
                            $total['icms.st'] += $_imposto->getValor();
1034 5
                            $total['base.st'] += $_imposto->getBase();
1035 5
                        } else {
1036
                            $total[$_imposto->getGrupo()] += round($_imposto->getValor(), 2);
1037
                            $total['base'] += $_imposto->getBase();
1038
                        }
1039 5
                        break;
1040 5
                    default:
1041 5
                        $total[$_imposto->getGrupo()] += round($_imposto->getValor(), 2);
1042 5
                }
1043 5
            }
1044 5
        }
1045 5
        return $total;
1046
    }
1047
1048 5
    private function getNodeTotal($name = null)
1049
    {
1050 5
        $dom = new \DOMDocument('1.0', 'UTF-8');
1051 5
        $element = $dom->createElement(is_null($name)?'total':$name);
1052
1053
        // Totais referentes ao ICMS
1054 5
        $total = $this->getTotais();
1055 5
        $icms = $dom->createElement('ICMSTot');
1056 5
        Util::appendNode($icms, 'vBC', Util::toCurrency($total['base']));
1057 5
        Util::appendNode($icms, 'vICMS', Util::toCurrency($total['icms']));
1058 5
        Util::appendNode($icms, 'vICMSDeson', Util::toCurrency($total['desoneracao']));
1059 5
        Util::appendNode($icms, 'vBCST', Util::toCurrency($total['base.st']));
1060 5
        Util::appendNode($icms, 'vST', Util::toCurrency($total['icms.st']));
1061 5
        Util::appendNode($icms, 'vProd', Util::toCurrency($total['produtos']));
1062 5
        Util::appendNode($icms, 'vFrete', Util::toCurrency($total['frete']));
1063 5
        Util::appendNode($icms, 'vSeg', Util::toCurrency($total['seguro']));
1064 5
        Util::appendNode($icms, 'vDesc', Util::toCurrency($total['descontos']));
1065 5
        Util::appendNode($icms, 'vII', Util::toCurrency($total['ii']));
1066 5
        Util::appendNode($icms, 'vIPI', Util::toCurrency($total['ipi']));
1067 5
        Util::appendNode($icms, 'vPIS', Util::toCurrency($total['pis']));
1068 5
        Util::appendNode($icms, 'vCOFINS', Util::toCurrency($total['cofins']));
1069 5
        Util::appendNode($icms, 'vOutro', Util::toCurrency($total['outros']));
1070 5
        Util::appendNode($icms, 'vNF', Util::toCurrency($total['nota']));
1071 5
        Util::appendNode($icms, 'vTotTrib', Util::toCurrency($total['tributos']));
1072 5
        $element->appendChild($icms);
1073
1074
        // TODO: Totais referentes ao ISSQN
1075
1076
        // TODO: Retenção de Tributos Federais
1077 5
        return $element;
1078
    }
1079
1080 5
    public function getNode($name = null)
0 ignored issues
show
Complexity introduced by
This operation has 5040 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...
1081
    {
1082 5
        $this->getEmitente()->getEndereco()->checkCodigos();
1083 5
        $this->setID($this->gerarID());
1084 5
        $this->setDigitoVerificador(substr($this->getID(), -1, 1));
1085
1086 5
        $dom = new \DOMDocument('1.0', 'UTF-8');
1087 5
        $element = $dom->createElement(is_null($name)?'NFe':$name);
1088 5
        $element->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', self::PORTAL);
1089
1090 5
        $info = $dom->createElement('infNFe');
1091 5
        $id = $dom->createAttribute('Id');
1092 5
        $id->value = $this->getID(true);
1093 5
        $info->appendChild($id);
1094 5
        $versao = $dom->createAttribute('versao');
1095 5
        $versao->value = self::VERSAO;
1096 5
        $info->appendChild($versao);
1097
1098 5
        $municipio = $this->getEmitente()->getEndereco()->getMunicipio();
1099 5
        $estado = $municipio->getEstado();
1100 5
        $ident = $dom->createElement('ide');
1101 5
        Util::appendNode($ident, 'cUF', $estado->getCodigo(true));
1102 5
        Util::appendNode($ident, 'cNF', $this->getCodigo(true));
1103 5
        Util::appendNode($ident, 'natOp', $this->getNatureza(true));
1104 5
        Util::appendNode($ident, 'indPag', $this->getIndicador(true));
1105 5
        Util::appendNode($ident, 'mod', $this->getModelo(true));
1106 5
        Util::appendNode($ident, 'serie', $this->getSerie(true));
1107 5
        Util::appendNode($ident, 'nNF', $this->getNumero(true));
1108 5
        Util::appendNode($ident, 'dhEmi', $this->getDataEmissao(true));
1109 5
        Util::appendNode($ident, 'tpNF', $this->getTipo(true));
1110 5
        Util::appendNode($ident, 'idDest', $this->getDestino(true));
1111 5
        Util::appendNode($ident, 'cMunFG', $municipio->getCodigo(true));
1112 5
        Util::appendNode($ident, 'tpImp', $this->getFormato(true));
1113 5
        Util::appendNode($ident, 'tpEmis', $this->getEmissao(true));
1114 5
        Util::appendNode($ident, 'cDV', $this->getDigitoVerificador(true));
1115 5
        Util::appendNode($ident, 'tpAmb', $this->getAmbiente(true));
1116 5
        Util::appendNode($ident, 'finNFe', $this->getFinalidade(true));
1117 5
        Util::appendNode($ident, 'indFinal', $this->getConsumidorFinal(true));
1118 5
        Util::appendNode($ident, 'indPres', $this->getPresenca(true));
1119 5
        Util::appendNode($ident, 'procEmi', 0); // emissão de NF-e com aplicativo do contribuinte
1120 5
        Util::appendNode($ident, 'verProc', self::APP_VERSAO);
1121 5
        if (!is_null($this->getDataMovimentacao())) {
1122
            Util::appendNode($ident, 'dhSaiEnt', $this->getDataMovimentacao(true));
1123
        }
1124 5
        if ($this->getEmissao() != self::EMISSAO_NORMAL) {
1125
            Util::appendNode($ident, 'dhCont', $this->getDataContingencia(true));
1126
            Util::appendNode($ident, 'xJust', $this->getJustificativa(true));
1127
        }
1128 5
        $info->appendChild($ident);
1129
1130 5
        $emitente = $this->getEmitente()->getNode();
1131 5
        $emitente = $dom->importNode($emitente, true);
1132 5
        $info->appendChild($emitente);
1133 5
        if ($this->getAmbiente() == self::AMBIENTE_HOMOLOGACAO && !is_null($this->getDestinatario())) {
1134 5
            $this->getDestinatario()->setNome('NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL');
1135 5
        }
1136 5
        if (!is_null($this->getDestinatario())) {
1137 5
            $destinatario = $this->getDestinatario()->getNode();
1138 5
            $destinatario = $dom->importNode($destinatario, true);
1139 5
            $info->appendChild($destinatario);
1140 5
        }
1141 5
        $item = 0;
1142 5
        $tributos = array();
1143 5
        $_produtos = $this->getProdutos();
1144 5
        foreach ($_produtos as $_produto) {
1145 5
            if (is_null($_produto->getItem())) {
1146 2
                $item += 1;
1147 2
                $_produto->setItem($item);
1148 2
            } else {
1149 3
                $item = $_produto->getItem();
1150
            }
1151 5
            if ($this->getAmbiente() == self::AMBIENTE_HOMOLOGACAO) {
1152 5
                $_produto->setDescricao('NOTA FISCAL EMITIDA EM AMBIENTE DE HOMOLOGACAO - SEM VALOR FISCAL');
1153 5
            }
1154 5
            $produto = $_produto->getNode();
1155 5
            $produto = $dom->importNode($produto, true);
1156 5
            $info->appendChild($produto);
1157
            // Soma os tributos aproximados dos produtos
1158 5
            $imposto_info = $_produto->getImpostoInfo();
1159 5
            $tributos['info'] = $imposto_info['info'];
1160 5
            foreach ($imposto_info as $key => $value) {
1161 5
                if (!is_numeric($value)) {
1162 5
                    continue;
1163
                }
1164 5
                if (!isset($tributos[$key])) {
1165 5
                    $tributos[$key] = 0.00;
1166 5
                }
1167 5
                $tributos[$key] += $value;
1168 5
            }
1169 5
        }
1170 5
        $total = $this->getNodeTotal();
1171 5
        $total = $dom->importNode($total, true);
1172 5
        $info->appendChild($total);
1173 5
        $transporte = $this->getTransporte()->getNode();
1174 5
        $transporte = $dom->importNode($transporte, true);
1175 5
        $info->appendChild($transporte);
1176
        // TODO: adicionar cobrança
1177 5
        $_pagamentos = $this->getPagamentos();
1178 5
        foreach ($_pagamentos as $_pagamento) {
1179 5
            $pagamento = $_pagamento->getNode();
1180 5
            $pagamento = $dom->importNode($pagamento, true);
1181 5
            $info->appendChild($pagamento);
1182 5
        }
1183
        // TODO: adicionar informações adicionais somente na NFC-e?
1184 5
        $adicional = $dom->createElement('infAdic');
1185 5
        Produto::addNodeInformacoes($tributos, $adicional, 'infCpl');
1186 5
        $info->appendChild($adicional);
1187
        // TODO: adicionar exportação
1188
        // TODO: adicionar compra
1189
        // TODO: adicionar cana
1190 5
        $element->appendChild($info);
1191 5
        $dom->appendChild($element);
1192 5
        return $element;
1193
    }
1194
1195 3
    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...
1196
    {
1197 3
        $root = $element;
1198 3
        $name = is_null($name)?'NFe':$name;
1199 3
        if ($element->tagName != $name) {
1200
            $_fields = $element->getElementsByTagName($name);
1201
            if ($_fields->length == 0) {
1202
                throw new \Exception('Tag "'.$name.'" não encontrada', 404);
1203
            }
1204
            $element = $_fields->item(0);
1205
        }
1206 3
        $_fields = $element->getElementsByTagName('infNFe');
1207 3
        if ($_fields->length > 0) {
1208 3
            $info = $_fields->item(0);
1209 3
        } else {
1210
            throw new \Exception('Tag "infNFe" não encontrada', 404);
1211
        }
1212 3
        $id = $info->getAttribute('Id');
1213 3
        if (strlen($id) != 47) {
1214
            throw new \Exception('Atributo "Id" inválido, encontrado: "'.$id.'"', 500);
1215
        }
1216 3
        $this->setID(substr($id, 3));
1217 3
        $_fields = $info->getElementsByTagName('ide');
1218 3
        if ($_fields->length > 0) {
1219 3
            $ident = $_fields->item(0);
1220 3
        } else {
1221
            throw new \Exception('Tag "ide" não encontrada', 404);
1222
        }
1223 3
        $emitente = new Emitente();
1224 3
        $_fields = $ident->getElementsByTagName('cUF');
1225 3
        if ($_fields->length > 0) {
1226 3
            $codigo = $_fields->item(0)->nodeValue;
1227 3
        } else {
1228
            throw new \Exception('Tag "cUF" do campo "Codigo IBGE da UF" não encontrada', 404);
1229
        }
1230 3
        $emitente->getEndereco()->getMunicipio()->getEstado()->setCodigo($codigo);
1231 3
        $this->setCodigo(
1232 3
            Util::loadNode(
1233 3
                $ident,
1234 3
                'cNF',
1235
                'Tag "cNF" do campo "Codigo" não encontrada'
1236 3
            )
1237 3
        );
1238 3
        $this->setNatureza(
1239 3
            Util::loadNode(
1240 3
                $ident,
1241 3
                'natOp',
1242
                'Tag "natOp" do campo "Natureza" não encontrada'
1243 3
            )
1244 3
        );
1245 3
        $this->setIndicador(
1246 3
            Util::loadNode(
1247 3
                $ident,
1248 3
                'indPag',
1249
                'Tag "indPag" do campo "Indicador" não encontrada'
1250 3
            )
1251 3
        );
1252 3
        $this->setModelo(
1253 3
            Util::loadNode(
1254 3
                $ident,
1255 3
                'mod',
1256
                'Tag "mod" do campo "Modelo" não encontrada'
1257 3
            )
1258 3
        );
1259 3
        $this->setSerie(
1260 3
            Util::loadNode(
1261 3
                $ident,
1262 3
                'serie',
1263
                'Tag "serie" do campo "Serie" não encontrada'
1264 3
            )
1265 3
        );
1266 3
        $this->setNumero(
1267 3
            Util::loadNode(
1268 3
                $ident,
1269 3
                'nNF',
1270
                'Tag "nNF" do campo "Numero" não encontrada'
1271 3
            )
1272 3
        );
1273 3
        $this->setDataEmissao(
1274 3
            Util::loadNode(
1275 3
                $ident,
1276 3
                'dhEmi',
1277
                'Tag "dhEmi" do campo "DataEmissao" não encontrada'
1278 3
            )
1279 3
        );
1280 3
        $this->setTipo(
1281 3
            Util::loadNode(
1282 3
                $ident,
1283 3
                'tpNF',
1284
                'Tag "tpNF" do campo "Tipo" não encontrada'
1285 3
            )
1286 3
        );
1287 3
        $this->setDestino(
1288 3
            Util::loadNode(
1289 3
                $ident,
1290 3
                'idDest',
1291
                'Tag "idDest" do campo "Destino" não encontrada'
1292 3
            )
1293 3
        );
1294 3
        $_fields = $ident->getElementsByTagName('cMunFG');
1295 3
        if ($_fields->length > 0) {
1296 3
            $codigo = $_fields->item(0)->nodeValue;
1297 3
        } else {
1298
            throw new \Exception('Tag "cMunFG" do campo "Codigo IBGE do município" não encontrada', 404);
1299
        }
1300 3
        $emitente->getEndereco()->getMunicipio()->setCodigo($codigo);
1301 3
        $this->setDataMovimentacao(Util::loadNode($ident, 'dhSaiEnt'));
1302 3
        $this->setFormato(
1303 3
            Util::loadNode(
1304 3
                $ident,
1305 3
                'tpImp',
1306
                'Tag "tpImp" do campo "Formato" não encontrada'
1307 3
            )
1308 3
        );
1309 3
        $this->setEmissao(
1310 3
            Util::loadNode(
1311 3
                $ident,
1312 3
                'tpEmis',
1313
                'Tag "tpEmis" do campo "Emissao" não encontrada'
1314 3
            )
1315 3
        );
1316 3
        $this->setDigitoVerificador(
1317 3
            Util::loadNode(
1318 3
                $ident,
1319 3
                'cDV',
1320
                'Tag "cDV" do campo "DigitoVerificador" não encontrada'
1321 3
            )
1322 3
        );
1323 3
        $this->setAmbiente(
1324 3
            Util::loadNode(
1325 3
                $ident,
1326 3
                'tpAmb',
1327
                'Tag "tpAmb" do campo "Ambiente" não encontrada'
1328 3
            )
1329 3
        );
1330 3
        $this->setFinalidade(
1331 3
            Util::loadNode(
1332 3
                $ident,
1333 3
                'finNFe',
1334
                'Tag "finNFe" do campo "Finalidade" não encontrada'
1335 3
            )
1336 3
        );
1337 3
        $this->setConsumidorFinal(
1338 3
            Util::loadNode(
1339 3
                $ident,
1340 3
                'indFinal',
1341
                'Tag "indFinal" do campo "ConsumidorFinal" não encontrada'
1342 3
            )
1343 3
        );
1344 3
        $this->setPresenca(
1345 3
            Util::loadNode(
1346 3
                $ident,
1347 3
                'indPres',
1348
                'Tag "indPres" do campo "Presenca" não encontrada'
1349 3
            )
1350 3
        );
1351 3
        $this->setDataContingencia(Util::loadNode($ident, 'dhCont'));
1352 3
        $this->setJustificativa(Util::loadNode($ident, 'xJust'));
1353
1354 3
        $_fields = $info->getElementsByTagName('emit');
1355 3
        if ($_fields->length > 0) {
1356 3
            $emitente->loadNode($_fields->item(0), 'emit');
1357 3
        } else {
1358
            throw new \Exception('Tag "emit" do objeto "Emitente" não encontrada', 404);
1359
        }
1360 3
        $this->setEmitente($emitente);
1361 3
        $_fields = $info->getElementsByTagName('dest');
1362 3
        $destinatario = null;
1363 3
        if ($_fields->length > 0) {
1364 3
            $destinatario = new Destinatario();
1365 3
            $destinatario->loadNode($_fields->item(0), 'dest');
1366 3
        }
1367 3
        $this->setDestinatario($destinatario);
1368 3
        $produtos = array();
1369 3
        $_items = $info->getElementsByTagName('det');
1370 3
        foreach ($_items as $_item) {
1371 3
            $produto = new Produto();
1372 3
            $produto->loadNode($_item, 'det');
1373 3
            $produtos[] = $produto;
1374 3
        }
1375 3
        $this->setProdutos($produtos);
1376 3
        $_fields = $info->getElementsByTagName('transp');
1377 3
        $transporte = null;
1378 3
        if ($_fields->length > 0) {
1379 3
            $transporte = new Transporte();
1380 3
            $transporte->loadNode($_fields->item(0), 'transp');
1381 3
        }
1382 3
        $this->setTransporte($transporte);
1383 3
        $pagamentos = array();
1384 3
        $_items = $info->getElementsByTagName('pag');
1385 3
        foreach ($_items as $_item) {
1386 3
            $pagamento = new Pagamento();
1387 3
            $pagamento->loadNode($_item, 'pag');
1388 3
            $pagamentos[] = $pagamento;
1389 3
        }
1390 3
        $this->setPagamentos($pagamentos);
1391
1392 3
        $_fields = $root->getElementsByTagName('protNFe');
1393 3
        $protocolo = null;
1394 3
        if ($_fields->length > 0) {
1395
            $protocolo = new Protocolo();
1396
            $protocolo->loadNode($_fields->item(0), 'infProt');
1397
        }
1398 3
        $this->setProtocolo($protocolo);
1399 3
        return $element;
1400
    }
1401
1402
    /**
1403
     * Carrega um arquivo XML e preenche a nota com as informações dele
1404
     * @param  string $filename caminho do arquivo
1405
     * @return DOMDocument      objeto do documento carregado
1406
     */
1407 1
    public function load($filename)
1408
    {
1409 1
        $dom = new \DOMDocument();
1410 1
        if (!file_exists($filename)) {
1411
            throw new \Exception('Arquivo XML "'.$filename.'" não encontrado', 404);
1412
        }
1413 1
        $dom->load($filename);
1414 1
        $this->loadNode($dom->documentElement);
1415 1
        return $dom;
1416
    }
1417
1418
    /**
1419
     * Assina o XML com a assinatura eletrônica do tipo A1
1420
     */
1421 3
    public function assinar($dom = null)
1422
    {
1423 3
        if (is_null($dom)) {
1424 1
            $xml = $this->getNode();
1425 1
            $dom = $xml->ownerDocument;
1426 1
        }
1427 3
        $config = SEFAZ::getInstance()->getConfiguracao();
1428
1429 3
        $adapter = new XmlseclibsAdapter();
1430 3
        $adapter->setPrivateKey($config->getChavePrivada());
1431 3
        $adapter->setPublicKey($config->getChavePublica());
1432 3
        $adapter->addTransform(AdapterInterface::ENVELOPED);
1433 3
        $adapter->addTransform(AdapterInterface::XML_C14N);
1434 3
        $adapter->sign($dom, 'infNFe');
1435 3
        return $dom;
1436
    }
1437
1438
    /**
1439
     * Valida o documento após assinar
1440
     */
1441 1
    public function validar($dom)
1442
    {
1443 1
        $dom->loadXML($dom->saveXML());
1444 1
        $xsd_path = __DIR__ . '/schema';
1445 1
        if (is_null($this->getProtocolo())) {
1446 1
            $xsd_file = $xsd_path . '/nfe_v3.10.xsd';
1447 1
        } else {
1448
            $xsd_file = $xsd_path . '/procNFe_v3.10.xsd';
1449
        }
1450 1
        if (!file_exists($xsd_file)) {
1451
            throw new \Exception('O arquivo "'.$xsd_file.'" de esquema XSD não existe!', 404);
1452
        }
1453
        // Enable user error handling
1454 1
        $save = libxml_use_internal_errors(true);
1455 1
        if ($dom->schemaValidate($xsd_file)) {
1456 1
            libxml_use_internal_errors($save);
1457 1
            return $dom;
1458
        }
1459
        $msg = array();
1460
        $errors = libxml_get_errors();
1461
        foreach ($errors as $error) {
1462
            $msg[] = 'Não foi possível validar o XML: '.$error->message;
1463
        }
1464
        libxml_clear_errors();
1465
        libxml_use_internal_errors($save);
1466
        throw new ValidationException($msg);
1467
    }
1468
1469
    /**
1470
     * Adiciona o protocolo no XML da nota
1471
     */
1472
    public function addProtocolo($dom)
1473
    {
1474
        if (is_null($this->getProtocolo())) {
1475
            throw new \Exception('O protocolo não foi informado na nota "'.$this->getID().'"', 404);
1476
        }
1477
        $notae = $dom->getElementsByTagName('NFe')->item(0);
1478
        // Corrige xmlns:default
1479
        $notae_xml = $dom->saveXML($notae);
1480
1481
        $element = $dom->createElement('nfeProc');
1482
        $element->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', self::PORTAL);
1483
        $versao = $dom->createAttribute('versao');
1484
        $versao->value = self::VERSAO;
1485
        $element->appendChild($versao);
1486
        $dom->removeChild($notae);
1487
        // Corrige xmlns:default
1488
        $notae = $dom->createElement('NFe', 0);
1489
1490
        $element->appendChild($notae);
1491
        $info = $this->getProtocolo()->getNode();
1492
        $info = $dom->importNode($info, true);
1493
        $element->appendChild($info);
1494
        $dom->appendChild($element);
1495
        // Corrige xmlns:default
1496
        $xml = $dom->saveXML();
1497
        $xml = str_replace('<NFe>0</NFe>', $notae_xml, $xml);
1498
        $dom->loadXML($xml);
1499
1500
        return $dom;
1501
    }
1502
}
1503