Passed
Push — master ( c02ff8...8cf6c5 )
by Esteban De La Fuente
06:05
created

IvaMntTotalNormalizationTrait   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 174
Duplicated Lines 0 %

Test Coverage

Coverage 78.65%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 85
c 1
b 0
f 0
dl 0
loc 174
ccs 70
cts 89
cp 0.7865
rs 9.92
wmc 31

1 Method

Rating   Name   Duplication   Size   Complexity  
F applyIvaMntTotalNormalization() 0 155 31
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * LibreDTE: Biblioteca PHP (Núcleo).
7
 * Copyright (C) LibreDTE <https://www.libredte.cl>
8
 *
9
 * Este programa es software libre: usted puede redistribuirlo y/o modificarlo
10
 * bajo los términos de la Licencia Pública General Affero de GNU publicada
11
 * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia,
12
 * o (a su elección) cualquier versión posterior de la misma.
13
 *
14
 * Este programa se distribuye con la esperanza de que sea útil, pero SIN
15
 * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD
16
 * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública
17
 * General Affero de GNU para obtener una información más detallada.
18
 *
19
 * Debería haber recibido una copia de la Licencia Pública General Affero de
20
 * GNU junto a este programa.
21
 *
22
 * En caso contrario, consulte <http://www.gnu.org/licenses/agpl.html>.
23
 */
24
25
namespace libredte\lib\Core\Sii\Dte\Documento\Normalization;
26
27
/**
28
 * Reglas de normalización para el IVA y monto total del documento.
29
 */
30
trait IvaMntTotalNormalizationTrait
31
{
32
    /**
33
     * Calcula el monto del IVA y el monto total del documento a partir del
34
     * monto neto y la tasa de IVA si es que existe.
35
     *
36
     * WARNING: Si es una boleta y tiene impuestos adicionales, no se
37
     * consideran los casos de esos impuestos adicionales. Se deberán indicar
38
     * los campos de MntNeto e IVA y no usar esta parte de la normalización.
39
     *
40
     * WARNING: Si el valor IndMntNeto es 2 indica que los montos de las líneas
41
     * son netos en cuyo caso no aplica el cálculo de neto e IVA a partir del
42
     * total y deberá venir informado de otra forma (aun no definido).
43
     *
44
     * @param array $data Arreglo con los datos del documento a normalizar.
45
     * @return array Arreglo con los datos normalizados.
46
     * @todo Revisar si los WARNING de la descripción del método realmente son
47
     * un problema y, si lo son, corregirlos.
48
     */
49 114
    protected function applyIvaMntTotalNormalization(array $data): array
50
    {
51
        // Si es una boleta y no están los datos de monto neto ni IVA se
52
        // calculan.
53
        if (
54 114
            $this->getTipoDocumento()->esBoleta()
0 ignored issues
show
Bug introduced by
It seems like getTipoDocumento() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

54
            $this->/** @scrutinizer ignore-call */ 
55
                   getTipoDocumento()->esBoleta()
Loading history...
55
            && (
56 114
                empty($data['Encabezado']['IdDoc']['IndMntNeto'])
57 114
                || $data['Encabezado']['IdDoc']['IndMntNeto'] != 2
58
            )
59
        ) {
60 17
            $total = (int) $data['Encabezado']['Totales']['MntTotal']
61 17
                - (int)$data['Encabezado']['Totales']['MntExe']
62 17
            ;
63
            if (
64 17
                $total
65
                && (
66 17
                    empty($data['Encabezado']['Totales']['MntNeto'])
67 17
                    || empty($data['Encabezado']['Totales']['IVA'])
68
                )
69
            ) {
70 9
                list(
71 9
                    $data['Encabezado']['Totales']['MntNeto'],
72 9
                    $data['Encabezado']['Totales']['IVA']
73 9
                ) = $this->calcularNetoIVA($total);
0 ignored issues
show
Bug introduced by
It seems like calcularNetoIVA() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

73
                /** @scrutinizer ignore-call */ 
74
                list(
Loading history...
74
            }
75
        }
76
77
        // Agregar IVA y monto total.
78 114
        if (!empty($data['Encabezado']['Totales']['MntNeto'])) {
79 74
            if ($data['Encabezado']['IdDoc']['MntBruto'] == 1) {
80
                list(
81
                    $data['Encabezado']['Totales']['MntNeto'],
82
                    $data['Encabezado']['Totales']['IVA']
83
                ) = $this->calcularNetoIVA(
84
                    $data['Encabezado']['Totales']['MntNeto'],
85
                    $data['Encabezado']['Totales']['TasaIVA']
86
                );
87
            } else {
88
                if (
89 74
                    empty($data['Encabezado']['Totales']['IVA'])
90 74
                    && !empty($data['Encabezado']['Totales']['TasaIVA'])
91
                ) {
92 65
                    $data['Encabezado']['Totales']['IVA'] = round(
93 65
                        $data['Encabezado']['Totales']['MntNeto']
94 65
                            * ($data['Encabezado']['Totales']['TasaIVA'] / 100)
95 65
                    );
96
                }
97
            }
98 74
            if (empty($data['Encabezado']['Totales']['MntTotal'])) {
99 65
                $data['Encabezado']['Totales']['MntTotal'] =
100 65
                    $data['Encabezado']['Totales']['MntNeto']
101 65
                ;
102 65
                if (!empty($data['Encabezado']['Totales']['IVA'])) {
103 65
                    $data['Encabezado']['Totales']['MntTotal'] +=
104 65
                        $data['Encabezado']['Totales']['IVA']
105 65
                    ;
106
                }
107 65
                if (!empty($data['Encabezado']['Totales']['MntExe'])) {
108 74
                    $data['Encabezado']['Totales']['MntTotal'] +=
109 74
                        $data['Encabezado']['Totales']['MntExe']
110 74
                    ;
111
                }
112
            }
113
        } else {
114
            if (
115 42
                !$data['Encabezado']['Totales']['MntTotal']
116 42
                && !empty($data['Encabezado']['Totales']['MntExe'])
117
            ) {
118 25
                $data['Encabezado']['Totales']['MntTotal'] =
119 25
                    $data['Encabezado']['Totales']['MntExe']
120 25
                ;
121
            }
122
        }
123
124
        // Si hay IVA definido se cambia a valor entero. El IVA no es decimal.
125 114
        if (is_numeric($data['Encabezado']['Totales']['IVA'] ?? null)) {
126 86
            $data['Encabezado']['Totales']['IVA'] =
127 86
                (int) $data['Encabezado']['Totales']['IVA']
128 86
            ;
129
        }
130
131
        // Si hay impuesto retenido o adicional se contabiliza en el total.
132 114
        if (!empty($data['Encabezado']['Totales']['ImptoReten'])) {
133 17
            foreach ($data['Encabezado']['Totales']['ImptoReten'] as &$ImptoReten) {
134
                // Si es una retención, se resta al total y se traspasa a IVA
135
                // no retenido en caso que corresponda.
136 17
                if ($this->getImpuestosAdicionalesRepository()->getTipo($ImptoReten['TipoImp']) == 'R') {
0 ignored issues
show
Bug introduced by
It seems like getImpuestosAdicionalesRepository() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

136
                if ($this->/** @scrutinizer ignore-call */ getImpuestosAdicionalesRepository()->getTipo($ImptoReten['TipoImp']) == 'R') {
Loading history...
137 9
                    $data['Encabezado']['Totales']['MntTotal'] -=
138 9
                        $ImptoReten['MontoImp']
139 9
                    ;
140 9
                    if ($ImptoReten['MontoImp'] != $data['Encabezado']['Totales']['IVA']) {
141 9
                        $data['Encabezado']['Totales']['IVANoRet'] =
142 9
                            $data['Encabezado']['Totales']['IVA']
143 9
                                - $ImptoReten['MontoImp']
144 9
                        ;
145
                    }
146
                }
147
148
                // Si es impuesto adicional se suma al total.
149
                elseif (
150 9
                    $this->getImpuestosAdicionalesRepository()->getTipo($ImptoReten['TipoImp']) == 'A'
151 9
                    && isset($ImptoReten['MontoImp'])
152
                ) {
153 9
                    $data['Encabezado']['Totales']['MntTotal'] +=
154 9
                        $ImptoReten['MontoImp']
155 9
                    ;
156
                }
157
            }
158
        }
159
160
        // Si hay crédito aasociado al impuesto (IVA) por ser empresa
161
        // constructora se descuenta del total.
162
        if (
163 114
            !empty($data['Encabezado']['Totales']['CredEC'])
164 114
            && method_exists($this, 'getDefaultCredEC')
165
        ) {
166
            if ($data['Encabezado']['Totales']['CredEC'] === true) {
167
                $data['Encabezado']['Totales']['CredEC'] = round(
168
                    $data['Encabezado']['Totales']['IVA']
169
                        * $this->getDefaultCredEC()
170
                );
171
            }
172
            $data['Encabezado']['Totales']['MntTotal'] -=
173
                $data['Encabezado']['Totales']['CredEC']
174
            ;
175
        }
176
177
        // Si hay monto total y monto no facturable se agrega el monto del
178
        // periodo.
179 114
        if (!in_array($data['Encabezado']['IdDoc']['TipoDTE'], [39, 41])) {
180
            if (
181 97
                !empty($data['Encabezado']['Totales']['MntTotal'])
182 97
                && !empty($data['Encabezado']['Totales']['MontoNF'])
183
            ) {
184
                $data['Encabezado']['Totales']['MontoPeriodo'] =
185
                    $data['Encabezado']['Totales']['MntTotal']
186
                        + $data['Encabezado']['Totales']['MontoNF']
187
                ;
188
            }
189
        }
190
191
        // Si hay monto total definido, y el documento no es de exportación, se
192
        // cambia a valor entero. El monto total no es decimal en documentos
193
        // nacionales.
194 114
        if (is_numeric($data['Encabezado']['Totales']['MntTotal'] ?? null)) {
195 114
            if (!$this->getTipoDocumento()->esExportacion()) {
196 98
                $data['Encabezado']['Totales']['MntTotal'] =
197 98
                    (int) $data['Encabezado']['Totales']['MntTotal']
198 98
                ;
199
            }
200
        }
201
202
        // Entregar los datos normalizados.
203 114
        return $data;
204
    }
205
}
206