CNAB240Processor::processarHeaderArquivo()   B
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 46
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 7
Bugs 0 Features 2
Metric Value
c 7
b 0
f 2
dl 0
loc 46
rs 8.9411
cc 1
eloc 36
nc 1
nop 1
1
<?php
2
3
namespace Umbrella\Ya\RetornoBoleto\Cnab\Cnab240\Processor;
4
5
use Stringy\Stringy;
6
use Umbrella\Ya\RetornoBoleto\AbstractProcessor;
7
use Umbrella\Ya\RetornoBoleto\Cnab\Cnab240\Header;
8
use Umbrella\Ya\RetornoBoleto\Cnab\Cnab240\HeaderLote;
9
use Umbrella\Ya\RetornoBoleto\Cnab\Cnab240\Trailer;
10
use Umbrella\Ya\RetornoBoleto\Cnab\Cnab240\TrailerLote;
11
use Umbrella\Ya\RetornoBoleto\Cnab\Cnab400\Convenio\Processor\AbstractCNAB400Processor;
12
use Umbrella\Ya\RetornoBoleto\Cnab\CnabHeaderInterface;
13
use Umbrella\Ya\RetornoBoleto\Cnab\ComposableInterface;
14
use Umbrella\Ya\RetornoBoleto\LoteInterface;
15
use Umbrella\Ya\RetornoBoleto\Model\Banco;
16
use Umbrella\Ya\RetornoBoleto\Model\Cedente;
17
use Umbrella\Ya\RetornoBoleto\Model\Empresa;
18
use Umbrella\Ya\RetornoBoleto\Model\Endereco;
19
use Umbrella\Ya\RetornoBoleto\RetornoInterface;
20
21
/**
22
 * Classe para leitura_arquivos_retorno_cobranças_padrão CNAB240.<br/>
23
 * Layout Padrão Febraban 240 posições V08.4 de 01/09/2009<br/>
24
 * http://www.febraban.org.br
25
 * @author Ítalo Lelis de Vietro <[email protected]>
26
 */
27
class CNAB240Processor extends AbstractProcessor
28
{
29
    /**
30
     * @property int HEADER_ARQUIVO Define o valor que identifica uma coluna do tipo HEADER DE ARQUIVO
31
     */
32
    const HEADER_ARQUIVO = 0;
33
34
    /**
35
     * @property int HEADER_LOTE Define o valor que identifica uma coluna do tipo HEADER DE LOTE
36
     */
37
    const HEADER_LOTE = 1;
38
39
    /**
40
     * @property int DETALHE Define o valor que identifica uma coluna do tipo DETALHE
41
     */
42
    const DETALHE = 3;
43
44
    /**
45
     * @property int TRAILER_LOTE Define o valor que identifica uma coluna do tipo TRAILER DEs LOTE
46
     */
47
    const TRAILER_LOTE = 5;
48
49
    /**
50
     * @property int TRAILER_ARQUIVO Define o valor que identifica uma coluna do tipo TRAILER DE ARQUIVO
51
     */
52
    const TRAILER_ARQUIVO = 9;
53
54
    public function createHeader()
55
    {
56
        return new Header();
57
    }
58
59
    protected function processarHeaderArquivo($linha)
60
    {
61
        $header = $this->createHeader();
62
        //X = ALFANUMÉRICO 9 = NUMÉRICO V = VÍRGULA DECIMAL ASSUMIDA
63
        $header
64
            ->setRegistro($linha->substr(8, 1)->trim())
65
            ->setLote($linha->substr(4, 4)->trim())
66
            ->addCnab($linha->substr(9, 9)->trim())
67
            ->addCnab($linha->substr(133, 10)->trim())
68
            ->addCnab($linha->substr(212, 29)->trim())
69
            ->setConvenio($linha->substr(33, 20)->trim())
70
            ->setCodArquivo($linha->substr(143, 1)->trim());
71
72
        $header->setDataGeracao($this->createDateTime($linha->substr(144, 8)->trim() . " " . $linha->substr(152, 6)->trim()))
73
            ->setSequencialRet($linha->substr(158, 6)->trim())
74
            ->setVersaoLayout($linha->substr(164, 3)->trim())
75
            ->setDensidade($linha->substr(167, 5)->trim());
76
77
        $empresa = new Empresa();
78
        $empresa
79
            ->setTipoInscricao($linha->substr(18, 1)->trim())
80
            ->setNumInscricao($linha->substr(19, 14)->trim())
81
            ->setNome($linha->substr(73, 30)->trim())
82
            ->addReservado($linha->substr(192, 20)->trim());
83
84
        $banco = new Banco();
85
        $banco
86
            ->setCod($linha->substr(1, 3)->trim())
87
            ->setNome($linha->substr(103, 30)->trim())
88
            ->setAgencia($linha->substr(53, 5)->trim())
89
            ->setDvAgencia($linha->substr(58, 1)->trim())
90
            ->setConta($linha->substr(59, 12)->trim())
91
            ->setDvConta($linha->substr(71, 1)->trim())
92
            ->setDvAgenciaConta($linha->substr(72, 1)->trim())
93
            ->addReservado($linha->substr(172, 20)->trim());
94
95
96
        $cedente = new Cedente();
97
        $cedente->setBanco($banco);
98
99
        $header
100
            ->setCedente($cedente)
101
            ->setEmpresa($empresa);
102
103
        return $header;
104
    }
105
106
    protected function processarHeaderLote($linha)
107
    {
108
        $header = new HeaderLote();
109
110
        $header
111
            ->setRegistro($linha->substr(8, 1)->trim())
112
            ->setLote($linha->substr(4, 4)->trim())
113
            ->setOperacao($linha->substr(9, 1)->trim())
114
            ->setServico($linha->substr(10, 2)->trim())
115
            ->setFormaLancamento($linha->substr(12, 2)->trim())
116
            ->setVersaoLayout($linha->substr(14, 3)->trim())
117
            ->addCnab($linha->substr(17, 1)->trim())
118
            ->addCnab($linha->substr(223, 8)->trim())
119
            ->addOcorrencia($linha->substr(231, 10)->trim())
120
            ->setConvenio($linha->substr(33, 20)->trim())
121
            ->addMensagem($linha->substr(103, 40)->trim());
122
123
        $endereco = new Endereco();
124
        $endereco
125
            ->setLogradourdo($linha->substr(143, 30)->trim())
126
            ->setNumero($linha->substr(173, 5)->trim())
127
            ->setComplemento($linha->substr(178, 15)->trim())
128
            ->setCidade($linha->substr(193, 20)->trim())
129
            ->setCep($linha->substr(213, 5)->trim())
130
            ->setComplementoCep($linha->substr(218, 3)->trim())
131
            ->setEstado($linha->substr(221, 2)->trim());
132
        $empresa = new Empresa();
133
        $empresa
134
            ->setEndereco($endereco)
135
            ->setTipoInscricao($linha->substr(18, 1)->trim())
136
            ->setNumInscricao($linha->substr(19, 14)->trim())
137
            ->setNome($linha->substr(73, 30)->trim());
138
139
        $banco = new Banco();
140
        $banco
141
            ->setCod($linha->substr(1, 3)->trim())
142
            ->setNome($linha->substr(103, 30)->trim())
143
            ->setAgencia($linha->substr(53, 5)->trim())
144
            ->setDvAgencia($linha->substr(58, 1)->trim())
145
            ->setConta($linha->substr(59, 12)->trim())
146
            ->setDvConta($linha->substr(71, 1)->trim())
147
            ->setDvAgenciaConta($linha->substr(72, 1)->trim());
148
149
150
        $cedente = new Cedente();
151
        $cedente->setBanco($banco);
152
153
        $header
154
            ->setCedente($cedente)
155
            ->setEmpresa($empresa);
156
157
        return $header;
158
    }
159
160
    protected function processarDetalhe($linha)
161
    {
162
        $factory = new \Umbrella\Ya\RetornoBoleto\Cnab\Cnab240\Segmento\SegmentoFactory();
163
        $segmento = $linha->substr(14, 1)->trim();
164
        return $factory->getDetail($segmento)->buildDetail($linha);
165
    }
166
167
    protected function processarTrailerLote($linha)
168
    {
169
        $trailer = new TrailerLote();
170
171
        $banco = new Banco();
172
        $banco
173
            ->setCod($linha->substr(1, 3)->trim());
174
175
        $cedente = new Cedente();
176
        $cedente
177
            ->setNome($linha->substr(62, 30)->trim())
178
            ->setBanco($banco);
179
180
        $trailer
181
            ->setLote($linha->substr(4, 4)->trim())
182
            ->setRegistro($linha->substr(8, 1)->trim())
183
            ->addCnab($linha->substr(9, 9)->trim())
184
            ->setQuantidadeRegistros($linha->substr(18, 6)->trim())
185
            ->setValor($linha->substr(24, 16)->trim())
186
            ->setQuantidadeMoedas($linha->substr(42, 13)->trim())
187
            ->setNumAvisoDepbito($linha->substr(60, 6)->trim())
188
            ->addCnab($linha->substr(66, 165)->trim())
189
            ->addOcorrencia($linha->substr(231, 10)->trim());
190
191
        return $trailer;
192
    }
193
194
    protected function processarTrailerArquivo($linha)
195
    {
196
        $trailer = new Trailer();
197
198
        $banco = new Banco();
199
        $banco
200
            ->setCod($linha->substr(1, 3)->trim());
201
202
        $cedente = new Cedente();
203
        $cedente
204
            ->setNome($linha->substr(62, 30)->trim())
205
            ->setBanco($banco);
206
207
        $trailer
208
            ->setLote($linha->substr(4, 4)->trim())
209
            ->setRegistro($linha->substr(8, 1)->trim())
210
            ->addCnab($linha->substr(9, 9)->trim())
211
            ->setQuantidadeLotes($linha->substr(18, 6)->trim())
212
            ->setQuantidadeRegistros($linha->substr(24, 6)->trim())
213
            ->setQuantidadeContasConc($linha->substr(30, 6)->trim())
214
            ->addCnab($linha->substr(36, 205)->trim());
215
216
        return $trailer;
217
    }
218
219
    /**
220
     * Processa uma linha_arquivo_retorno.
221
     * @param int $numLn Número_linha a ser processada
222
     * @param string $linha String contendo a linha a ser processada
223
     * @return array Retorna um vetor associativo contendo os valores_linha processada.
224
     */
225
    public function processarLinha($numLn, Stringy $linha)
226
    {
227
        //é adicionado um espaço vazio no início_linha para que
228
        //possamos trabalhar com índices iniciando_1, no lugar_zero,
229
        //e assim, ter os valores_posição_campos exatamente
230
        //como no manual CNAB240
231
        $linha = $linha->insert(" ", 0);
232
        $tipoLn = $linha->substr(8, 1)->trim();
233
234
        $this->needToCreateLote = false;
235
        if ((string)$tipoLn == CNAB240Processor::HEADER_ARQUIVO) {
236
            $vlinha = $this->processarHeaderArquivo($linha);
237
        } else if ((string)$tipoLn == CNAB240Processor::HEADER_LOTE) {
238
            $this->needToCreateLote = true;
239
            $vlinha = $this->processarHeaderLote($linha);
240
        } else if ((string)$tipoLn == CNAB240Processor::DETALHE) {
241
            $vlinha = $this->processarDetalhe($linha);
242
        } else if ((string)$tipoLn == CNAB240Processor::TRAILER_LOTE) {
243
            $vlinha = $this->processarTrailerLote($linha);
244
        } else if ((string)$tipoLn == CNAB240Processor::TRAILER_ARQUIVO) {
245
            $vlinha = $this->processarTrailerArquivo($linha);
246
        }
247
248
        return $vlinha;
0 ignored issues
show
Bug introduced by
The variable $vlinha does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
249
    }
250
251
    public function processCnab(RetornoInterface $retorno, ComposableInterface $composable, LoteInterface $lote = null)
252
    {
253
        switch ((int)$composable->getRegistro()->__toString()) {
254
            case AbstractCNAB400Processor::HEADER_ARQUIVO:
255
                $retorno->setHeader($composable);
0 ignored issues
show
Compatibility introduced by
$composable of type object<Umbrella\Ya\Retor...ab\ComposableInterface> is not a sub-type of object<Umbrella\Ya\Retor...ab\CnabHeaderInterface>. It seems like you assume a child interface of the interface Umbrella\Ya\RetornoBoleto\Cnab\ComposableInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
256
                break;
257
258
            case self::TRAILER_ARQUIVO:
259
                $retorno->setTrailer($composable);
0 ignored issues
show
Compatibility introduced by
$composable of type object<Umbrella\Ya\Retor...ab\ComposableInterface> is not a sub-type of object<Umbrella\Ya\Retor...b\CnabTrailerInterface>. It seems like you assume a child interface of the interface Umbrella\Ya\RetornoBoleto\Cnab\ComposableInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
260
                break;
261
262
            case self::HEADER_LOTE:
263
                if ($composable instanceof CnabHeaderInterface) {
264
                    $lote->setHeader($composable);
0 ignored issues
show
Bug introduced by
It seems like $lote is not always an object, but can also be of type null. Maybe add an additional type check?

If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe:

function someFunction(A $objectMaybe = null)
{
    if ($objectMaybe instanceof A) {
        $objectMaybe->doSomething();
    }
}
Loading history...
265
                } else {
266
                    $lote->addDetail($composable);
0 ignored issues
show
Compatibility introduced by
$composable of type object<Umbrella\Ya\Retor...ab\ComposableInterface> is not a sub-type of object<Umbrella\Ya\Retor...ab\CnabDetailInterface>. It seems like you assume a child interface of the interface Umbrella\Ya\RetornoBoleto\Cnab\ComposableInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
267
                }
268
                break;
269
270
            case self::TRAILER_LOTE:
271
                $lote->setTrailer($composable);
0 ignored issues
show
Compatibility introduced by
$composable of type object<Umbrella\Ya\Retor...ab\ComposableInterface> is not a sub-type of object<Umbrella\Ya\Retor...b\CnabTrailerInterface>. It seems like you assume a child interface of the interface Umbrella\Ya\RetornoBoleto\Cnab\ComposableInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
272
                break;
273
274
            default:
275
                $lote->addDetail($composable);
0 ignored issues
show
Compatibility introduced by
$composable of type object<Umbrella\Ya\Retor...ab\ComposableInterface> is not a sub-type of object<Umbrella\Ya\Retor...ab\CnabDetailInterface>. It seems like you assume a child interface of the interface Umbrella\Ya\RetornoBoleto\Cnab\ComposableInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
276
                break;
277
        }
278
    }
279
}
280