Passed
Branch develop (5fc816)
by JAIME ELMER
01:58
created

InvoiceDocument::setAllowances()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * MÓDULO DE EMISIÓN ELECTRÓNICA F72X
5
 * UBL 2.1
6
 * Version 1.1
7
 * 
8
 * Copyright 2018, Jaime Cruz
9
 */
10
11
namespace F72X\Sunat;
12
13
use DateTime;
14
/**
15
 * InvoiceDocument
16
 * 
17
 * Esta clase es una representación interna de una factura o boleta, la cual se
18
 * encarga de aplicar toda la logica de negocio en cuanto a cálculos de tributos
19
 * y totales
20
 * 
21
 */
22
class InvoiceDocument {
23
24
    const BOLETA_PREFIX = 'B';
25
    const FACTURA_PREFIX = 'F';
26
27
    private $_rawData;
28
    private $invoiceType;
29
    private $currencyType;
30
    private $voucherId;
31
    private $voucherIdPrefix;
32
    private $voucherSeries;
33
    private $voucherNumber;
34
35
    /** @var DateTime */
36
    private $issueDate;
37
38
    /** @var DateTime */
39
    protected $DueDate;
40
    private $operationType;
41
    private $customerDocType;
42
    private $customerDocNumber;
43
    private $customerRegName;
44
    private $purchaseOrder;
45
46
    /** @var InvoiceItems */
47
    private $_items;
48
    private $_rawItems;
49
    private $allowancesAndCharges = [];
50
51
    /**
52
     * 
53
     * @param array $data
54
     * @param string $type Catalogo::CAT1_BOLETA|Catalogo::CAT1_FACTURA
55
     * @param string $currencyType
56
     */
57
    public function __construct(array $data, $type, $currencyType = 'PEN') {
58
        // Items
59
        $items = new InvoiceItems();
60
        $items->populate($data['items'], $currencyType);
61
62
        $this->_rawData = $data;
63
        $this->_rawItems = $data['items'];
64
        $this->addDefaults($data);
65
        $this->currencyType = $currencyType;
66
        $this->voucherSeries = $data['voucherSeries'];
67
        $this->voucherNumber = $data['voucherNumber'];
68
        // requires voucherSeries and voucherNumber
69
        $this->setTypeProperties($type);
70
        $this->issueDate = $data['issueDate'];
71
        $this->purchaseOrder = $data['purchaseOrder'];
72
        $this->operationType = $data['operationType'];
73
        $this->customerDocType = $data['customerDocType'];
74
        $this->customerDocNumber = $data['customerDocNumber'];
75
        $this->customerRegName = mb_strtoupper($data['customerRegName']);
76
        $this->_items = $items;
77
        $this->allowancesAndCharges = $data['allowancesCharges'];
78
    }
79
80
    private function addDefaults(array &$data) {
81
        $data['allowancesCharges'] = isset($data['allowancesCharges']) ? $data['allowancesCharges'] : [];
82
        $data['issueDate']  = isset($data['issueDate']) ? $data['issueDate'] : new DateTime();
83
        $data['purchaseOrder'] = isset($data['purchaseOrder']) ? $data['purchaseOrder'] : null;
84
    }
85
86
    private function setTypeProperties($type) {
87
        $this->invoiceType = $type;
88
        if ($type === Catalogo::CAT1_BOLETA) {
89
            $this->voucherIdPrefix = self::BOLETA_PREFIX;
90
        } else {
91
            $this->voucherIdPrefix = self::FACTURA_PREFIX;
92
        }
93
        $this->voucherId = $this->voucherIdPrefix . str_pad($this->voucherSeries, 3, '0', STR_PAD_LEFT) . '-' . str_pad($this->voucherNumber, 8, '0', STR_PAD_LEFT);
94
    }
95
96
    public function getVoucherId() {
97
        return $this->voucherId;
98
    }
99
100
    public function getRawData() {
101
        return $this->_rawData;
102
    }
103
104
    /**
105
     * Boleta o Factura @CAT1
106
     * @return string
107
     */
108
    public function getInvoiceType() {
109
        return $this->invoiceType;
110
    }
111
112
    public function getCurrencyType() {
113
        return $this->currencyType;
114
    }
115
116
    public function getVoucherIdPrefix() {
117
        return $this->voucherIdPrefix;
118
    }
119
120
    public function getVoucherSeries() {
121
        return $this->voucherSeries;
122
    }
123
124
    public function setVoucherSeries($voucherSeries) {
125
        $this->voucherSeries = $voucherSeries;
126
        return $this;
127
    }
128
129
    public function getVoucherNumber() {
130
        return $this->voucherNumber;
131
    }
132
133
    public function setVoucherNumber($voucherNumber) {
134
        $this->voucherNumber = $voucherNumber;
135
        return $this;
136
    }
137
138
    public function getIssueDate() {
139
        return $this->issueDate;
140
    }
141
142
    public function setIssueDate(DateTime $IssueDate) {
143
        $this->issueDate = $IssueDate;
144
        return $this;
145
    }
146
147
    public function getDueDate() {
148
        return $this->DueDate;
149
    }
150
151
    public function setDueDate(DateTime $DueDate) {
152
        $this->DueDate = $DueDate;
153
        return $this;
154
    }
155
156
    public function getOperationType() {
157
        return $this->operationType;
158
    }
159
160
    public function setOperationType($operationType) {
161
        $this->operationType = $operationType;
162
        return $this;
163
    }
164
165
    public function getCustomerDocType() {
166
        return $this->customerDocType;
167
    }
168
169
    public function setCustomerDocType($customerDocType) {
170
        $this->customerDocType = $customerDocType;
171
        return $this;
172
    }
173
174
    public function getCustomerDocNumber() {
175
        return $this->customerDocNumber;
176
    }
177
178
    public function setCustomerDocNumber($customerDocNumber) {
179
        $this->customerDocNumber = $customerDocNumber;
180
        return $this;
181
    }
182
183
    public function getCustomerRegName() {
184
        return $this->customerRegName;
185
    }
186
187
    public function setCustomerRegName($customerRegName) {
188
        $this->customerRegName = $customerRegName;
189
        return $this;
190
    }
191
192
    public function getPurchaseOrder() {
193
        return $this->purchaseOrder;
194
    }
195
196
    public function setPurchaseOrder($purchaseOrder) {
197
        $this->purchaseOrder = $purchaseOrder;
198
        return $this;
199
    }
200
201
    /**
202
     * 
203
     * @return InvoiceItems
204
     */
205
    public function getItems() {
206
        return $this->_items;
207
    }
208
209
    /**
210
     * Numero de items del documento
211
     * @return int
212
     */
213
    public function getTotalItems() {
214
        return $this->_items->getCount();
215
    }
216
217
    public function getRawItems() {
218
        return $this->_rawItems;
219
    }
220
221
    public function getAllowancesAndCharges() {
222
        return $this->allowancesAndCharges;
223
    }
224
225
    public function setAllowancesAndCharges($allowancesAndCharges) {
226
        $this->allowancesAndCharges = $allowancesAndCharges;
227
        return $this;
228
    }
229
230
    /**
231
     * Base imponible
232
     * 
233
     * Formula = SUM(BASE_IMPONIBLE_X_ITEM) - DESCUENTOS_GLOBALES + CARGOS_GLOBALES
234
     * 
235
     * @return float
236
     */
237
    public function getTaxableAmount() {
238
        $totalItems = $this->_items->getTotalTaxableOperations();
239
        return $this->applyAllowancesAndCharges($totalItems);
240
    }
241
    /**
242
     * Monto con impuestos
243
     * 
244
     * Formula = BASE_IMPONIBLE + IGV
245
     * 
246
     * @return float
247
     */
248
    public function getTaxedAmount() {
249
        $totalTaxableAmount = $this->getTaxableAmount();
250
        $totalIgv = $this->getIGV();
251
        return $totalTaxableAmount + $totalIgv;
252
    }
253
254
    /**
255
     * Total operaciones gravadas
256
     * @return float
257
     */
258
    public function getTotalTaxableOperations() {
259
        return $this->getTaxableAmount();
260
    }
261
    /**
262
     * Total operaciones gratuitas
263
     * @return float
264
     */
265
    public function getTotalFreeOperations() {
266
        return $this->_items->getTotalFreeOperations();
267
    }
268
269
    /**
270
     * Total operationes exoneradas
271
     * 
272
     * Formula = SUM(EXEMPTED_OPERATIONS_X_ITEM) - DESCUENTOS_GLOBALES + CARGOS_GLOBALES
273
     * 
274
     * @return float
275
     */
276
    public function getTotalExemptedOperations() {
277
        $totalItems = $this->_items->getTotalExemptedOperations();
278
        return $this->applyAllowancesAndCharges($totalItems);
279
    }
280
281
    /**
282
     * Total operaciones inafectas
283
     * @return float
284
     */
285
    public function getTotalUnaffectedOperations() {
286
        $totalItems = $this->_items->getTotalUnaffectedOperations();
287
        return $this->applyAllowancesAndCharges($totalItems);
288
    }
289
    /**
290
     * Valor de venta
291
     * 
292
     * Valor total de la factura sin considerar descuentos impuestos u otros tributos
293
     * @return float
294
     */
295
    public function getBillableValue() {
296
        return $this->_items->getTotalBillableValue();
297
    }
298
299
    /**
300
     * Total descuentos
301
     * 
302
     * Formula: SUM(DESCUENTOS_X_ITEM) + DESCUENTOS_GLOBALES
303
     * @return float
304
     */
305
    public function getTotalAllowances() {
306
        $totalItems = $this->_items->getTotalAllowances();
307
        $totalTaxableAmountItems = $this->_items->getTotalTaxableAmount();
308
        $globalAllowancesAmount = Operations::getTotalAllowances($totalTaxableAmountItems, $this->allowancesAndCharges);
309
        return $totalItems + $globalAllowancesAmount;
310
    }
311
    /**
312
     * Total a pagar
313
     * 
314
     * El importe que el usuario está obligado a pagar
315
     * 
316
     * Formula = OPERACIONES_GRAVADAS + IGV + OPERACIONES_EXONERADAS + OPERACIONES_INAFECTAS
317
     * 
318
     * @return float
319
     */
320
    public function getPayableAmount() {
321
        // Totals
322
        $totalTaxableOperations  = $this->getTotalTaxableOperations();
323
        $totalIGV                = $this->getIGV();
324
        $totalExemptedOperations = $this->getTotalExemptedOperations();
325
        return $totalTaxableOperations + $totalIGV + $totalExemptedOperations;
326
    }
327
328
    /**
329
     * 
330
     * Total impuestos
331
     * 
332
     * Fórmula: IGV + ISC + IVAP
333
     * 
334
     * @return float
335
     */
336
    public function getTotalTaxes() {
337
        $IGV  = $this->getIGV();
338
        $ISC  = $this->getISC();
339
        $IVAP = $this->getIVAP();
340
        return $IGV + $ISC + $IVAP;
341
    }
342
343
    /**
344
     * IGV
345
     * @return float
346
     */
347
    public function getIGV() {
348
        $baseAmount = $this->getTaxableAmount();
349
        return Operations::calcIGV($baseAmount);
350
    }
351
352
    /**
353
     * ISC
354
     * @IMP
355
     * @return float
356
     */
357
    public function getISC() {
358
        return Operations::calcISC();
359
    }
360
    /**
361
     * IVAP
362
     * @IMP
363
     * @return float
364
     */
365
    public function getIVAP() {
366
        return Operations::calcIVAP();
367
    }
368
    /**
369
     * 
370
     * @param float $amount
371
     * @return float
372
     */
373
    private function applyAllowancesAndCharges($amount) {
374
        return Operations::applyAllowancesAndCharges($amount, $this->allowancesAndCharges);
375
    }
376
377
}
378