Completed
Pull Request — master (#46)
by
unknown
02:14
created

ConsumoFolio::setResumen()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 15
rs 9.2
cc 4
eloc 7
nc 5
nop 1
1
<?php
2
3
/**
4
 * LibreDTE
5
 * Copyright (C) SASCO SpA (https://sasco.cl)
6
 *
7
 * Este programa es software libre: usted puede redistribuirlo y/o
8
 * modificarlo bajo los términos de la Licencia Pública General Affero de GNU
9
 * publicada por la Fundación para el Software Libre, ya sea la versión
10
 * 3 de la Licencia, o (a su elección) cualquier versión posterior de la
11
 * misma.
12
 *
13
 * Este programa se distribuye con la esperanza de que sea útil, pero
14
 * SIN GARANTÍA ALGUNA; ni siquiera la garantía implícita
15
 * MERCANTIL o de APTITUD PARA UN PROPÓSITO DETERMINADO.
16
 * Consulte los detalles de la Licencia Pública General Affero de GNU para
17
 * obtener una información más detallada.
18
 *
19
 * Debería haber recibido una copia de la Licencia Pública General Affero de GNU
20
 * junto a este programa.
21
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
22
 */
23
24
namespace sasco\LibreDTE\Sii;
25
26
/**
27
 * Clase que representa el envío de un Consumo de Folios
28
 * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
29
 * @version 2016-02-14
30
 */
31
class ConsumoFolio extends \sasco\LibreDTE\Sii\Base\Libro
32
{
33
34
    private $documentos = []; ///< Documentos que se deben reportar en el consumo
35
36
    /**
37
     * Método que asigna los documentos que se deberán reportar en el consumo de
38
     * folios
39
     * @param documentos Arreglo con los códigos de DTEs a reportar
40
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
41
     * @version 2016-02-14
42
     */
43
    public function setDocumentos(array $documentos)
44
    {
45
        $this->documentos = $documentos;
46
    }
47
48
    /**
49
     * Método que agrega un DTE al listado que se enviará
50
     * @param detalle Arreglo con el resumen del DTE que se desea agregar
51
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
52
     * @version 2015-12-13
53
     */
54
    public function agregar(array $detalle)
55
    {
56
        $this->detalles[] = $detalle;
57
    }
58
59
    /**
60
     * Método para asignar la caratula
61
     * @param caratula Arreglo con datos del envío: RutEnvia, FchResol y NroResol, etc
62
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
63
     * @version 2016-08-06
64
     */
65
    public function setCaratula(array $caratula)
66
    {
67
        $this->caratula = array_merge([
68
            '@attributes' => [
69
                'version' => '1.0',
70
            ],
71
            'RutEmisor' => false,
72
            'RutEnvia' => isset($this->Firma) ? $this->Firma->getID() : false,
73
            'FchResol' => false,
74
            'NroResol' => false,
75
            'FchInicio' => $this->getFechaEmisionInicial(),
76
            'FchFinal' => $this->getFechaEmisionFinal(),
77
            'Correlativo' => false,
78
            'SecEnvio' => 1,
79
            'TmstFirmaEnv' => date('Y-m-d\TH:i:s'),
80
        ], $caratula);
81
        $this->id = 'LibreDTE_CONSUMO_FOLIO_'.str_replace('-', '', $this->caratula['RutEmisor']).'_'.str_replace('-', '', $this->caratula['FchInicio']).'_'.date('U');
82
    }
83
84
    /**
85
     * Método que genera el XML del consumo de folios para el envío al SII
86
     * @return XML con el envio del consumo de folios firmado o =false si no se pudo generar o firmar el envío
87
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
88
     * @version 2015-12-13
89
     */
90
    public function generar()
91
    {
92
        // si ya se había generado se entrega directamente
93
        if ($this->xml_data)
94
            return $this->xml_data;
95
        // generar XML del envío
96
        $xmlEnvio = (new \sasco\LibreDTE\XML())->generate([
97
            'ConsumoFolios' => [
98
                '@attributes' => [
99
                    'xmlns' => 'http://www.sii.cl/SiiDte',
100
                    'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
101
                    'xsi:schemaLocation' => 'http://www.sii.cl/SiiDte ConsumoFolio_v10.xsd',
102
                    'version' => '1.0',
103
                ],
104
                'DocumentoConsumoFolios' => [
105
                    '@attributes' => [
106
                        'ID' => $this->id,
107
                    ],
108
                    'Caratula' => $this->caratula,
109
                    'Resumen' => $this->getResumen(),
110
                ],
111
            ]
112
        ])->saveXML();
113
        // firmar XML del envío y entregar
114
        $this->xml_data = $this->Firma ? $this->Firma->signXML($xmlEnvio, '#'.$this->id, 'DocumentoConsumoFolios', true) : $xmlEnvio;
0 ignored issues
show
Documentation introduced by
$xmlEnvio is of type string, but the function expects a object<sasco\LibreDTE\Datos>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
115
        return $this->xml_data;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->xml_data; (boolean|string) is incompatible with the return type declared by the abstract method sasco\LibreDTE\Sii\Base\Documento::generar of type sasco\LibreDTE\Sii\Base\XML.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
116
    }
117
118
    /**
119
     * Método que entrega la fecha del primer documento que se está reportando
120
     * @return Fecha del primer documento que se está reportando
121
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
122
     * @version 2015-12-13
123
     */
124 View Code Duplication
    public function getFechaEmisionInicial()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

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

Loading history...
125
    {
126
        $fecha = '9999-12-31';
127
        foreach ($this->detalles as &$d) {
128
            if ($d['FchDoc'] < $fecha)
129
                $fecha = $d['FchDoc'];
130
        }
131
        return $fecha;
132
    }
133
134
    /**
135
     * Método que entrega la fecha del último documento que se está reportando
136
     * @return Fecha del último documento que se está reportando
137
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
138
     * @version 2015-12-13
139
     */
140 View Code Duplication
    public function getFechaEmisionFinal()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

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

Loading history...
141
    {
142
        $fecha = '0000-01-01';
143
        foreach ($this->detalles as &$d) {
144
            if ($d['FchDoc'] > $fecha)
145
                $fecha = $d['FchDoc'];
146
        }
147
        return $fecha;
148
    }
149
150
    /**
151
     * Método que permite agregar sólo resumen al libro, esto para
152
     * poder agregar, por ejemplo, un día en el cual no se consumieron folios
153
     * @param resumen Arreglo Eje: ['TipoDocumento' => 39, 'MntTotal' => 0, 'FoliosEmitidos' => 0, 'FoliosAnulados' => 0, 'FoliosUtilizados' => 0]
154
     * @author Adonias Vasquez (adonias.vasquez[at]epys.cl)
155
     * @version 2017-09-29
156
     */
157
    public function setResumen($resumen)
158
    {
159
160
        // verificar que se haya pasado el tipo de documento como mínimo
161
        foreach ($resumen as $tipo) {
162
            if (!isset($tipo['TipoDocumento'])) {
163
                return false;
164
            }
165
        }
166
        // asignar resumen
167
        $this->resumen = [];
168
        foreach ($resumen as $tipo) {
169
            $this->resumen[$tipo['TipoDocumento']] = $tipo;
170
        }
171
    }
172
173
174
    /**
175
     * Método que obtiene los datos para generar los tags de Resumen del
176
     * consumo de folios
177
     * @return Arreglo con los datos para generar los tags Resumen
178
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
179
     * @version 2016-02-14
180
     */
181
    private function getResumen()
182
    {
183
        // si hay detalles generar resumen
184
        $RangoUtilizados = [];
185
        //$RangoAnulados = [];
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
186
        foreach ($this->detalles as &$d) {
187
            // si no existe el tipo de documento se utiliza
188
            if (!isset($this->resumen[$d['TpoDoc']])) {
189
                $key = array_search($d['TpoDoc'], $this->documentos);
190
                if ($key!==false) {
191
                    unset($this->documentos[$key]);
192
                }
193
                $this->resumen[$d['TpoDoc']] = [
194
                    'TipoDocumento' => $d['TpoDoc'],
195
                    'MntNeto' => false,
196
                    'MntIva' => false,
197
                    'TasaIVA' => $d['TasaImp'] ? $d['TasaImp'] : false,
198
                    'MntExento' => false,
199
                    'MntTotal' => 0,
200
                    'FoliosEmitidos' => 0,
201
                    'FoliosAnulados' => 0,
202
                    'FoliosUtilizados' => false,
203
                    'RangoUtilizados' => false,
204
                    //'RangoAnulados' => false,
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
205
                ];
206
                $RangoUtilizados[$d['TpoDoc']] = [];
207
                //$RangoAnulados[$d['TpoDoc']] = [];
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
208
            }
209
            // ir agregando al resumen cada detalle
210
            if ($d['MntNeto']) {
211
                $this->resumen[$d['TpoDoc']]['MntNeto'] += $d['MntNeto'];
212
                $this->resumen[$d['TpoDoc']]['MntIva'] += $d['MntIVA'];
213
            }
214
            if ($d['MntExe']) {
215
                $this->resumen[$d['TpoDoc']]['MntExento'] += $d['MntExe'];
216
            }
217
            $this->resumen[$d['TpoDoc']]['MntTotal'] += $d['MntTotal'];
218
            $this->resumen[$d['TpoDoc']]['FoliosEmitidos']++;
219
            // ir guardando folios emitidos para luego crear rangos
220
            $RangoUtilizados[$d['TpoDoc']][] = $d['NroDoc'];
221
        }
222
        // ajustes post agregar detalles
223
        foreach ($this->resumen as &$r) {
224
            // obtener folios utilizados = emitidos + anulados
225
            $r['FoliosUtilizados'] = $r['FoliosEmitidos'] + $r['FoliosAnulados'];
226
            $r['RangoUtilizados'] = $this->getRangos($RangoUtilizados[$r['TipoDocumento']]);
227
        }
228
        // completar con los resumenes que no se colocaron
229
        foreach ($this->documentos as $tipo) {
230
            $this->resumen[$tipo] = [
231
                'TipoDocumento' => $tipo,
232
                'MntTotal' => 0,
233
                'FoliosEmitidos' => 0,
234
                'FoliosAnulados' => 0,
235
                'FoliosUtilizados' => 0,
236
            ];
237
        }
238
        // entregar resumen
239
        return $this->resumen;
240
    }
241
242
    /**
243
     * Método que determina los rangos de los folios para el resumen del consumo
244
     * de folios
245
     * @param folios Arreglo con los folios que se deben generar sus rangos
246
     * @return Arreglo con cada uno de los rangos de folios
247
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
248
     * @version 2015-12-13
249
     */
250
    private function getRangos($folios)
251
    {
252
        // crear auxiliar con los folios separados por rangos
253
        sort($folios);
254
        $aux = [];
255
        $inicial = $folios[0];
256
        $i = $inicial;
257
        foreach($folios as $f) {
258
            if ($i!=$f) {
259
                $inicial = $f;
260
                $i = $inicial;
261
            }
262
            $aux[$inicial][] = $f;
263
            $i++;
264
        }
265
        // crear rangos
266
        $rangos = [];
267
        foreach ($aux as $folios) {
268
            $rangos[] = [
269
                'Inicial' => $folios[0],
270
                'Final' => $folios[count($folios)-1],
271
            ];
272
        }
273
        return $rangos;
274
    }
275
276
    /**
277
     * Método que entrega la secuencia del envio
278
     * @author Esteban De La Fuente Rubio, DeLaF (esteban[at]sasco.cl)
279
     * @version 2016-02-14
280
     */
281
    public function getSecuencia()
282
    {
283
        return $this->caratula['SecEnvio'];
284
    }
285
286
}
287