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

DetalleNormalizationTrait   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 194
Duplicated Lines 0 %

Test Coverage

Coverage 83.06%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 113
c 1
b 0
f 0
dl 0
loc 194
ccs 103
cts 124
cp 0.8306
rs 9.84
wmc 32

1 Method

Rating   Name   Duplication   Size   Complexity  
F applyDetalleNormalization() 0 184 32
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 detalle de los documentos.
29
 */
30
trait DetalleNormalizationTrait
31
{
32
    /**
33
     * Normaliza los detalles del documento.
34
     *
35
     * @param array $data Arreglo con los datos del documento a normalizar.
36
     * @return array Arreglo con los datos normalizados.
37
     * @todo Revisar cómo se aplican descuentos y recargos. ¿Debería ser un
38
     * porcentaje del monto original?.
39
     */
40 114
    protected function applyDetalleNormalization(array $data): array
41
    {
42 114
        if (!isset($data['Detalle'][0])) {
43 9
            $data['Detalle'] = [
44 9
                $data['Detalle'],
45 9
            ];
46
        }
47
48 114
        $sumarMontoNF = (
49 114
            !isset($data['Encabezado']['Totales']['MontoNF'])
50 114
            || $data['Encabezado']['Totales']['MontoNF'] === false
51 114
        );
52
53 114
        $item = 1;
54 114
        foreach ($data['Detalle'] as &$d) {
55 114
            $d = array_merge([
56 114
                'NroLinDet' => $item++,
57 114
                'CdgItem' => false,
58 114
                'IndExe' => false,
59 114
                'Retenedor' => false,
60 114
                'NmbItem' => false,
61 114
                'DscItem' => false,
62 114
                'QtyRef' => false,
63 114
                'UnmdRef' => false,
64 114
                'PrcRef' => false,
65 114
                'QtyItem' => false,
66 114
                'Subcantidad' => false,
67 114
                'FchElabor' => false,
68 114
                'FchVencim' => false,
69 114
                'UnmdItem' => false,
70 114
                'PrcItem' => false,
71 114
                'DescuentoPct' => false,
72 114
                'DescuentoMonto' => false,
73 114
                'RecargoPct' => false,
74 114
                'RecargoMonto' => false,
75 114
                'CodImpAdic' => false,
76 114
                'MontoItem' => false,
77 114
            ], $d);
78
79
            // Corregir datos.
80 114
            $d['NmbItem'] = mb_substr($d['NmbItem'], 0, 80);
81 114
            if (!empty($d['DscItem'])) {
82 17
                $d['DscItem'] = mb_substr($d['DscItem'], 0, 1000);
83
            }
84
85
            // Normalizar.
86 114
            if ($this->getTipoDocumento()->esExportacion()) {
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

86
            if ($this->/** @scrutinizer ignore-call */ getTipoDocumento()->esExportacion()) {
Loading history...
87 17
                $d['IndExe'] = 1;
88
            }
89 114
            if (is_array($d['CdgItem'])) {
90 21
                $d['CdgItem'] = array_merge([
91 21
                    'TpoCodigo' => false,
92 21
                    'VlrCodigo' => false,
93 21
                ], $d['CdgItem']);
94
                if (
95 21
                    $d['Retenedor'] === false
96 21
                    && $d['CdgItem']['TpoCodigo'] === 'CPCS'
97
                ) {
98
                    $d['Retenedor'] = true;
99
                }
100
            }
101 114
            if ($d['Retenedor'] !== false) {
102 5
                if (!is_array($d['Retenedor'])) {
103
                    $d['Retenedor'] = ['IndAgente' => 'R'];
104
                }
105 5
                $d['Retenedor'] = array_merge([
106 5
                    'IndAgente' => 'R',
107 5
                    'MntBaseFaena' => false,
108 5
                    'MntMargComer' => false,
109 5
                    'PrcConsFinal' => false,
110 5
                ], $d['Retenedor']);
111
            }
112 114
            if ($d['CdgItem'] !== false && !is_array($d['CdgItem'])) {
113
                $d['CdgItem'] = [
114
                    'TpoCodigo' => empty($d['Retenedor']['IndAgente'])
115
                        ? 'INT1'
116
                        : 'CPCS'
117
                    ,
118
                    'VlrCodigo' => $d['CdgItem'],
119
                ];
120
            }
121 114
            if ($d['PrcItem']) {
122 106
                if (!$d['QtyItem']) {
123
                    $d['QtyItem'] = 1;
124
                }
125 106
                if (empty($d['MontoItem'])) {
126 106
                    $d['MontoItem'] = $this->round(
0 ignored issues
show
Bug introduced by
It seems like round() 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

126
                    /** @scrutinizer ignore-call */ 
127
                    $d['MontoItem'] = $this->round(
Loading history...
127 106
                        (float) $d['QtyItem'] * (float)$d['PrcItem'],
128 106
                        $data['Encabezado']['Totales']['TpoMoneda']
129 106
                    );
130
131
                    // Aplicar descuento.
132 106
                    if ($d['DescuentoPct']) {
133 5
                        $d['DescuentoMonto'] = round(
134 5
                            $d['MontoItem'] * (float) $d['DescuentoPct'] / 100
135 5
                        );
136
                    }
137 106
                    $d['MontoItem'] -= $d['DescuentoMonto'];
138
139
                    // Aplicar recargo.
140 106
                    if ($d['RecargoPct']) {
141
                        $d['RecargoMonto'] = round(
142
                            $d['MontoItem'] * (float) $d['RecargoPct'] / 100
143
                        );
144
                    }
145 106
                    $d['MontoItem'] += $d['RecargoMonto'];
146
147
                    // Aproximar monto del item.
148 106
                    $d['MontoItem'] = $this->round(
149 106
                        $d['MontoItem'],
150 106
                        $data['Encabezado']['Totales']['TpoMoneda']
151 106
                    );
152
                }
153
            }
154
            // Si el monto del item es vacío se estandariza como "0".
155 9
            elseif (empty($d['MontoItem'])) {
156 9
                $d['MontoItem'] = 0;
157
            }
158
159
            // Sumar valor del monto a MntNeto o MntExe según corresponda.
160 114
            if ($d['MontoItem']) {
161
                // Si no es boleta.
162 106
                if (!$this->getTipoDocumento()->esBoleta()) {
163
                    // Si es exento o no facturable.
164 89
                    if (!empty($d['IndExe'])) {
165 25
                        if ($d['IndExe'] == 1) {
166 25
                            $data['Encabezado']['Totales']['MntExe'] +=
167 25
                                $d['MontoItem']
168 25
                            ;
169
                        } elseif ($d['IndExe'] == 2) {
170
                            if ($sumarMontoNF) {
171
                                if (empty($data['Encabezado']['Totales']['MontoNF'])) {
172
                                    $data['Encabezado']['Totales']['MontoNF'] = 0;
173
                                }
174 25
                                $data['Encabezado']['Totales']['MontoNF'] +=
175 25
                                    $d['MontoItem']
176 25
                                ;
177
                            }
178
                        }
179
                    }
180
181
                    // Si es afecto, se agrega al monto neto.
182
                    else {
183 89
                        $data['Encabezado']['Totales']['MntNeto'] +=
184 89
                            $d['MontoItem']
185 89
                        ;
186
                    }
187
                }
188
189
                // Si es boleta.
190
                else {
191
                    // Si es exento o no facturable.
192 17
                    if (!empty($d['IndExe'])) {
193 9
                        if ($d['IndExe'] == 1) {
194 9
                            $data['Encabezado']['Totales']['MntExe'] +=
195 9
                                $d['MontoItem']
196 9
                            ;
197 9
                            $data['Encabezado']['Totales']['MntTotal'] +=
198 9
                                $d['MontoItem']
199 9
                            ;
200
                        } elseif ($d['IndExe'] == 2) {
201
                            if ($sumarMontoNF) {
202
                                if (empty($data['Encabezado']['Totales']['MontoNF'])) {
203
                                    $data['Encabezado']['Totales']['MontoNF'] = 0;
204
                                }
205 9
                                $data['Encabezado']['Totales']['MontoNF'] +=
206 9
                                    $d['MontoItem']
207 9
                                ;
208
                            }
209
                        }
210
                    }
211
212
                    // Si es afecto, sólo agregar al monto total.
213
                    else {
214 9
                        $data['Encabezado']['Totales']['MntTotal'] +=
215 9
                            $d['MontoItem']
216 9
                        ;
217
                    }
218
                }
219
            }
220
        }
221
222
        // Entregar los datos normalizados.
223 114
        return $data;
224
    }
225
}
226