Test Setup Failed
Push — master ( 99ee47...d58c12 )
by JAIME ELMER
01:53
created

DetailMatrix::isIgvExempted()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * FACTURA ELECTRÓNICA SUNAT
5
 * UBL 2.1
6
 * Version 1.0
7
 * 
8
 * Copyright 2018, Jaime Cruz
9
 */
10
11
namespace F72X\Sunat;
12
13
use F72X\Tools\XMatrix;
14
15
class DetailMatrix extends XMatrix {
16
17
    /** @CAT5 Tipo de impuesto*/
18
    const TAX_IGV   = '1000';
19
    const TAX_IVAP  = '1016';
20
    const TAX_ISC   = '2000';
21
    const TAX_EXP   = '9995';
22
    const TAX_GRA   = '9996';
23
    const TAX_EXO   = '9997';
24
    const TAX_INA   = '9998';
25
    const TAX_OTROS = '9999';
26
    
27
    const COL_PRODUCT_CODE          = 0;
28
    const COL_UNPSC                 = 1;
29
    const COL_UNIT_CODE             = 2;
30
    const COL_QUANTITY              = 3;
31
    const COL_DESCRIPTION           = 4;
32
    const COL_CURRENCY_CODE         = 5;
33
    const COL_UNIT_VALUE            = 6;
34
    const COL_UNIT_BILLABLE_VALUE   = 7;
35
    const COL_UNIT_PAYABLE_AMOUNT   = 8;
36
    // Códigos de catálogos predefinidos
37
    const COL_PRICE_TYPE            = 9;
38
    const COL_TAX_TYPE              = 10;
39
    const COL_IGV_AFFECTATION       = 11;
40
41
    const COL_ITEM_VALUE            = 12;
42
    const COL_ITEM_BILLABLE_VALUE   = 13;
43
    // Cargos y descuentos
44
    const COL_ALLOWANCES            = 14;
45
    const COL_ALLOWANCES_AMOUNT     = 15;
46
    const COL_CHARGES               = 16;
47
    const COL_CHARGES_AMOUNT        = 17;
48
49
    const COL_ITEM_TAXABLE_AMOUNT   = 18;
50
51
    const COL_IGV                   = 19;
52
    const COL_ITEM_PAYABLE_AMOUNT   = 20;
53
54
    protected $columns = [
55
        'cod',
56
        'cod_sunat',
57
        'unidad',
58
        'cantidad',
59
        '============descripción============',
60
        'moneda',
61
        'valor_unitario',
62
        'valor_unitario_facturable',
63
        'precio_unitario',
64
        'tipo_precio[CAT#16]',
65
        'tipo_impuesto[CAT#5]',
66
        'afectación_igv[CAT#7]',
67
        'valor_item [valor_unitario*cantidad]',
68
        'valor_item_facturable [valor_unitario_facturable*cantidad]',
69
        'descuentos',
70
        'monto_descuentos [valor_item_facturable*k]',
71
        'cargos',
72
        'monto_cargos [valor_item_facturable*k]',
73
        'base_imponible(operacion_gravada) [valor_item_facturable-descuentos+cargos]',
74
        'IGV(operacion_gravada) [valor_item_facturable*0.18]',
75
        'precio_item [base_imponible+IGV]'
76
    ];
77
78
    public function populate($items,  $currencyCode) {
79
        foreach ($items as $idx => $item) {
80
81
            $cat7Item = Catalogo::getCatItem(7, $item['igvAffectationCode']);   // Catálogo 7 Tipo de afectación del IGV
82
            $priceType  = $item['priceTypeCode'];   // Tipo de precio
83
            
84
            $unitValue = $item['unitValue'];       // Valor unitario
85
            $igvIncluded = $item['igvIncluded'];
86
            $unitPayableAmount = $unitValue;
87
            if(isset($cat7Item['igv'])){
88
                // Aplica IGV
89
                if ($igvIncluded) {
90
                    $unitPayableAmount = $unitValue;
91
                    $unitValue = $unitPayableAmount / (1 + SunatVars::IGV);
92
                } else{
93
                    $unitPayableAmount = $unitValue * (1 + SunatVars::IGV);
94
                }
95
            }
96
            $unitBillableValue = ($priceType === SunatVars::CAT16_REF_VALUE) ? 0 : $unitValue; // Valor unitario pagable
97
            $quantity = $item['quantity'];  // Cantidad
98
99
            $itemValue  = $unitValue * $quantity;   // Valor de item
100
            $itemBillableValue  = $unitBillableValue * $quantity;   // Valor de item
101
            // Descuentos de item
102
            $itemAllowancesAmount = 0;
103
            $allowancesArray = isset($item['allowances']) ? $item['allowances'] : [];
104
            foreach ($allowancesArray as $allItem) {
105
                $multFactor = $allItem['multiplierFactor'];
106
                $amount = $itemBillableValue * $multFactor;
107
                $itemAllowancesAmount += $amount;
108
            }
109
            // Cargos de item
110
            $itemChargesAmount = 0;
111
            $chargesArray = isset($item['charges']) ? $item['charges'] : [];
112
            foreach ($chargesArray as $charItem) {
113
                $multFactor = $charItem['multiplierFactor'];
114
                $amount = $itemValue * $multFactor;
115
                $itemChargesAmount += $amount;
116
            }
117
118
            // Valor de venta del ítem = (Valor del item - Descuentos + Cargos)
119
            if ($priceType === SunatVars::CAT16_UNITARY_PRICE) {
120
                $itemTaxableAmount = $itemValue - $itemAllowancesAmount + $itemChargesAmount;
121
            } else {
122
                // 0 si el valor del item es referencial!
123
                $itemTaxableAmount = 0;
124
            }
125
126
            // Afectación al IGV por item
127
            $igvAmount = 0;
128
            // Aplica IGV
129
            if (isset($cat7Item['igv'])) {
130
                $igvAmount = $itemTaxableAmount * SunatVars::IGV;
131
            }
132
            
133
            $itemIgvTaxed = $itemBillableValue + $igvAmount;
134
            
135
            $this->set(self::COL_PRODUCT_CODE,          $idx, $item['productCode']);
136
            $this->set(self::COL_UNPSC,                 $idx, $item['sunatProductCode']);
137
            $this->set(self::COL_UNIT_CODE,             $idx, $item['unitCode']);
138
            $this->set(self::COL_QUANTITY,              $idx, $quantity);
139
            $this->set(self::COL_DESCRIPTION,           $idx, $item['description']);
140
            $this->set(self::COL_CURRENCY_CODE,         $idx, $currencyCode);
141
            // Códigos de catálogos predefinidos
142
            $this->set(self::COL_PRICE_TYPE,       $idx, $priceType);
143
            $this->set(self::COL_TAX_TYPE,         $idx, $item['taxTypeCode']);
144
            $this->set(self::COL_IGV_AFFECTATION,  $idx, $item['igvAffectationCode']);
145
146
            $this->set(self::COL_UNIT_VALUE,            $idx, $unitValue);
147
            $this->set(self::COL_UNIT_BILLABLE_VALUE,   $idx, $unitBillableValue);
148
            $this->set(self::COL_UNIT_PAYABLE_AMOUNT,   $idx, $unitPayableAmount);
149
            $this->set(self::COL_ITEM_VALUE,            $idx, $itemValue);
150
            $this->set(self::COL_ITEM_BILLABLE_VALUE,   $idx, $itemBillableValue);
151
            $this->set(self::COL_ALLOWANCES,            $idx, $allowancesArray);
152
            $this->set(self::COL_ALLOWANCES_AMOUNT,     $idx, $itemAllowancesAmount);
153
            $this->set(self::COL_CHARGES,               $idx, $chargesArray);
154
            $this->set(self::COL_CHARGES_AMOUNT,        $idx, $itemChargesAmount);
155
            $this->set(self::COL_ITEM_TAXABLE_AMOUNT,   $idx, $itemTaxableAmount);
156
            $this->set(self::COL_IGV,                   $idx, $igvAmount);
157
            $this->set(self::COL_ITEM_PAYABLE_AMOUNT,   $idx, $itemIgvTaxed);
158
        }
159
    }
160
161
    /**
162
     * Codigo de producto
163
     * 
164
     * @param int $rowIndex
165
     * @return string
166
     */
167
    public function getProductCode($rowIndex) {
168
        return $this->get(self::COL_PRODUCT_CODE, $rowIndex);
169
    }
170
171
    /**
172
     * United Nations Standard Products and Services Code
173
     * Codigo de producto SUNAT de acuerdo con UNSPSC v14_0801
174
     * @param int $rowIndex
175
     * @return string
176
     */
177
    public function getUNPSC($rowIndex) {
178
        return $this->get(self::COL_UNPSC, $rowIndex);
179
    }
180
181
    public function getUnitCode($rowIndex) {
182
        return $this->get(self::COL_UNIT_CODE, $rowIndex);
183
    }
184
185
    public function getQunatity($rowIndex) {
186
        return $this->get(self::COL_QUANTITY, $rowIndex);
187
    }
188
189
    public function getDescription($rowIndex) {
190
        return $this->get(self::COL_DESCRIPTION, $rowIndex);
191
    }
192
193
    public function getCurrencyCode($rowIndex) {
194
        return $this->get(self::COL_CURRENCY_CODE, $rowIndex);
195
    }
196
197
    public function getPriceTypeCode($rowIndex) {
198
        return $this->get(self::COL_PRICE_TYPE, $rowIndex);
199
    }
200
201
    public function getTaxTypeCode($rowIndex) {
202
        return $this->get(self::COL_TAX_TYPE, $rowIndex);
203
    }
204
205
    public function getIgvAffectationCode($rowIndex) {
206
        return $this->get(self::COL_IGV_AFFECTATION, $rowIndex);
207
    }
208
209
    public function getUnitValue($rowIndex) {
210
        return $this->get(self::COL_UNIT_VALUE, $rowIndex);
211
    }
212
213
    public function getUnitBillableValue($rowIndex) {
214
        return $this->get(self::COL_UNIT_BILLABLE_VALUE, $rowIndex);
215
    }
216
217
    public function getUnitPayableAmount($rowIndex) {
218
        return $this->get(self::COL_UNIT_PAYABLE_AMOUNT, $rowIndex);
219
    }
220
221
    public function getItemValue($rowIndex) {
222
        return $this->get(self::COL_ITEM_VALUE, $rowIndex);
223
    }
224
225
    public function getItemBillableValue($rowIndex) {
226
        return $this->get(self::COL_ITEM_BILLABLE_VALUE, $rowIndex);
227
    }
228
229
    public function getAllowances($rowIndex) {
230
        return $this->get(self::COL_ALLOWANCES, $rowIndex);
231
    }
232
233
    public function getAllowancesAmount($rowIndex) {
234
        return $this->get(self::COL_ALLOWANCES_AMOUNT, $rowIndex);
235
    }
236
237
    public function getCharges($rowIndex) {
238
        return $this->get(self::COL_CHARGES, $rowIndex);
239
    }
240
241
    public function getChargesAmount($rowIndex) {
242
        return $this->get(self::COL_CHARGES_AMOUNT, $rowIndex);
243
    }
244
245
    public function getTaxableAmount($rowIndex) {
246
        return $this->get(self::COL_ITEM_TAXABLE_AMOUNT, $rowIndex);
247
    }
248
249
    public function getIgv($rowIndex) {
250
        return $this->get(self::COL_IGV, $rowIndex);
251
    }
252
253
    public function getPayableAmount($rowIndex) {
254
        return $this->get(self::COL_ITEM_PAYABLE_AMOUNT, $rowIndex);
255
    }
256
257
    /**
258
     * Retorna el total de las operaciones gravadas
259
     * @return float
260
     */
261
    public function getTotalTaxableOperations() {
262
        $total = 0;
263
        $data = $this->getMatrix();
264
        foreach ($data as $row) {
265
            $total += ($row[self::COL_TAX_TYPE] === self::TAX_IGV) ? $row[self::COL_ITEM_TAXABLE_AMOUNT] : 0;
266
        }
267
        return $total;
268
    }
269
270
    /**
271
     * Total de las operaciones exoneradas
272
     * @return float
273
     */
274
    public function getTotalExcemptedOperations() {
275
        $total = 0;
276
        $data = $this->getMatrix();
277
        foreach ($data as $row) {
278
            $total += ($row[self::COL_TAX_TYPE] === self::TAX_EXO) ? $row[self::COL_ITEM_TAXABLE_AMOUNT] : 0;
279
        }
280
        return $total;
281
    }
282
    /**
283
     * Total de las operaciones inafectas
284
     * @return float
285
     */
286
    public function getTotalUnaffectedOperations() {
287
        $total = 0;
288
        $data = $this->getMatrix();
289
        foreach ($data as $row) {
290
            $total += ($row[self::COL_TAX_TYPE] === self::TAX_INA) ? $row[self::COL_ITEM_VALUE] : 0;
291
        }
292
        return $total;
293
    }
294
295
    /**
296
     * Todos de los descuentos.
297
     * @return float
298
     */
299
    public function getTotalAllowances() {
300
        return $this->sum(self::COL_ALLOWANCES_AMOUNT);
301
    }
302
303
    /**
304
     * Todos de los descuentos.
305
     * @return float
306
     */
307
    public function getTotalCharges() {
308
        return $this->sum(self::COL_CHARGES_AMOUNT);
309
    }
310
311
    /**
312
     * Valor total
313
     * Suma los valores de cada item
314
     * = Cantidad x (Valor unitario | Valor fererencial)
315
     * @return float
316
     */
317
    public function getTotalValue() {
318
        return $this->sum(self::COL_ITEM_VALUE);
319
    }
320
321
    /**
322
     * Suma de valores de cada item sin incluir aquellos por los que no se cobra.
323
     * @return float
324
     */
325
    public function getTotalPayableValue() {
326
        return $this->sum(self::COL_ITEM_BILLABLE_VALUE);
327
    }
328
329
    /**
330
     * Total IGV
331
     * @return float
332
     */
333
    public function getTotalIgv() {
334
        return $this->sum(self::COL_IGV);
335
    }
336
    /**
337
     * Base imponible total lista para aplicar impuestos
338
     * @return float
339
     */
340
    public function getTotalTaxableAmount() {
341
        return $this->sum(self::COL_ITEM_TAXABLE_AMOUNT);
342
    }
343
}
344