Test Failed
Push — master ( d3c8d8...d4fc42 )
by JAIME ELMER
02:02
created

src/Sunat/InvoiceDocument.php (2 issues)

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
/**
14
 * InvoiceDocument
15
 * 
16
 * Esta clase es una representación interna de una factura o boleta, la cual se
17
 * encarga de aplicar toda la logica de negocio en cuanto a cálculos de tributos
18
 * y totales
19
 * 
20
 */
21
class InvoiceDocument {
22
23
    const BOLETA_PREFIX = 'B';
24
    const FACTURA_PREFIX = 'F';
25
26
    private $_rawData;
27
    private $invoiceType;
28
    private $currencyType;
29
    private $voucherId;
30
    private $voucherIdPrefix;
31
    private $voucherSeries;
32
    private $voucherNumber;
33
34
    /** @var DateTime */
0 ignored issues
show
The type F72X\Sunat\DateTime was not found. Did you mean DateTime? If so, make sure to prefix the type with \.
Loading history...
35
    private $issueDate;
36
37
    /** @var DateTime */
38
    protected $DueDate;
39
    private $operationType;
40
    private $customerDocType;
41
    private $customerDocNumber;
42
    private $customerRegName;
43
    private $purchaseOrder;
44
45
    /** @var InvoiceItems */
46
    private $_items;
47
    private $_rawItems;
48
    private $allowances;
49
    private $charges;
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->allowances = $data['allowances'];
78
        $this->charges = $data['charges'];
79
    }
80
81
    private function addDefaults(array &$data) {
82
        $data['allowances'] = isset($data['allowances']) ? $data['allowances'] : [];
83
        $data['charges']    = isset($data['charges']) ? $data['charges'] : [];
84
        $data['issueDate']  = isset($data['issueDate']) ? $data['issueDate'] : new DateTime();
85
        $data['purchaseOrder'] = isset($data['purchaseOrder']) ? $data['purchaseOrder'] : null;
86
    }
87
88
    private function setTypeProperties($type) {
89
        $this->invoiceType = $type;
90
        if ($type === Catalogo::CAT1_BOLETA) {
91
            $this->voucherIdPrefix = self::BOLETA_PREFIX;
92
        } else {
93
            $this->voucherIdPrefix = self::FACTURA_PREFIX;
94
        }
95
        $this->voucherId = $this->voucherIdPrefix . str_pad($this->voucherSeries, 3, '0', STR_PAD_LEFT) . '-' . str_pad($this->voucherNumber, 8, '0', STR_PAD_LEFT);
96
    }
97
98
    public function getVoucherId() {
99
        return $this->voucherId;
100
    }
101
102
    public function getRawData() {
103
        return $this->_rawData;
104
    }
105
106
    /**
107
     * Boleta o Factura @CAT1
108
     * @return string
109
     */
110
    public function getInvoiceType() {
111
        return $this->invoiceType;
112
    }
113
114
    public function getCurrencyType() {
115
        return $this->currencyType;
116
    }
117
118
    public function getVoucherIdPrefix() {
119
        return $this->voucherIdPrefix;
120
    }
121
122
    public function getVoucherSeries() {
123
        return $this->voucherSeries;
124
    }
125
126
    public function setVoucherSeries($voucherSeries) {
127
        $this->voucherSeries = $voucherSeries;
128
        return $this;
129
    }
130
131
    public function getVoucherNumber() {
132
        return $this->voucherNumber;
133
    }
134
135
    public function setVoucherNumber($voucherNumber) {
136
        $this->voucherNumber = $voucherNumber;
137
        return $this;
138
    }
139
140
    public function getIssueDate() {
141
        return $this->issueDate;
142
    }
143
144
    public function setIssueDate(DateTime $IssueDate) {
145
        $this->issueDate = $IssueDate;
146
        return $this;
147
    }
148
149
    public function getDueDate() {
150
        return $this->DueDate;
151
    }
152
153
    public function setDueDate(DateTime $DueDate) {
154
        $this->DueDate = $DueDate;
155
        return $this;
156
    }
157
158
    public function getOperationType() {
159
        return $this->operationType;
160
    }
161
162
    public function setOperationType($operationType) {
163
        $this->operationType = $operationType;
164
        return $this;
165
    }
166
167
    public function getCustomerDocType() {
168
        return $this->customerDocType;
169
    }
170
171
    public function setCustomerDocType($customerDocType) {
172
        $this->customerDocType = $customerDocType;
173
        return $this;
174
    }
175
176
    public function getCustomerDocNumber() {
177
        return $this->customerDocNumber;
178
    }
179
180
    public function setCustomerDocNumber($customerDocNumber) {
181
        $this->customerDocNumber = $customerDocNumber;
182
        return $this;
183
    }
184
185
    public function getCustomerRegName() {
186
        return $this->customerRegName;
187
    }
188
189
    public function setCustomerRegName($customerRegName) {
190
        $this->customerRegName = $customerRegName;
191
        return $this;
192
    }
193
194
    public function getPurchaseOrder() {
195
        return $this->purchaseOrder;
196
    }
197
198
    public function setPurchaseOrder($purchaseOrder) {
199
        $this->purchaseOrder = $purchaseOrder;
200
        return $this;
201
    }
202
203
    /**
204
     * 
205
     * @return InvoiceItems
206
     */
207
    public function getItems() {
208
        return $this->_items;
209
    }
210
211
    /**
212
     * 
213
     * @return InvoiceItems
214
     */
215
    public function getTotalItems() {
216
        return $this->_items->getCount();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_items->getCount() returns the type integer which is incompatible with the documented return type F72X\Sunat\InvoiceItems.
Loading history...
217
    }
218
219
    public function getRawItems() {
220
        return $this->_rawItems;
221
    }
222
223
    public function getAllowances() {
224
        return $this->allowances;
225
    }
226
227
    public function setAllowances($allowances) {
228
        $this->allowances = $allowances;
229
        return $this;
230
    }
231
232
    public function getCharges() {
233
        return $this->charges;
234
    }
235
236
    public function setCharges($charges) {
237
        $this->charges = $charges;
238
        return $this;
239
    }
240
241
    /**
242
     * Base imponible
243
     * 
244
     * Formula = SUM(BASE_IMPONIBLE_X_ITEM) - DESCUENTOS_GLOBALES + CARGOS_GLOBALES
245
     * 
246
     * @return float
247
     */
248
    public function getTaxableAmount() {
249
        $totalItems = $this->_items->getTotalTaxableOperations();
250
        return $this->applyAllowancesAndCharges($totalItems);
251
    }
252
    /**
253
     * Monto con impuestos
254
     * 
255
     * Formula = BASE_IMPONIBLE + IGV
256
     * 
257
     * @return float
258
     */
259
    public function getTaxedAmount() {
260
        $totalTaxableAmount = $this->getTaxableAmount();
261
        $totalIgv = $this->getIGV();
262
        return $totalTaxableAmount + $totalIgv;
263
    }
264
265
    /**
266
     * Total operaciones gravadas
267
     * @return float
268
     */
269
    public function getTotalTaxableOperations() {
270
        return $this->getTaxableAmount();
271
    }
272
    /**
273
     * Total operaciones gratuitas
274
     * @return float
275
     */
276
    public function getTotalFreeOperations() {
277
        return $this->_items->getTotalFreeOperations();
278
    }
279
280
    /**
281
     * Total operationes exoneradas
282
     * 
283
     * Formula = SUM(EXEMPTED_OPERATIONS_X_ITEM) - DESCUENTOS_GLOBALES + CARGOS_GLOBALES
284
     * 
285
     * @return float
286
     */
287
    public function getTotalExemptedOperations() {
288
        $totalItems = $this->_items->getTotalExemptedOperations();
289
        return $this->applyAllowancesAndCharges($totalItems);
290
    }
291
292
    /**
293
     * Total operaciones inafectas
294
     * @return float
295
     */
296
    public function getTotalUnaffectedOperations() {
297
        $totalItems = $this->_items->getTotalUnaffectedOperations();
298
        return $this->applyAllowancesAndCharges($totalItems);
299
    }
300
    /**
301
     * Valor de venta
302
     * 
303
     * Valor total de la factura sin considerar descuentos impuestos u otros tributos
304
     * @return float
305
     */
306
    public function getBillableValue() {
307
        return $this->_items->getTotalBillableValue();
308
    }
309
310
    /**
311
     * Total descuentos
312
     * 
313
     * Formula: SUM(DESCUENTOS_X_ITEM) + DESCUENTOS_GLOBALES
314
     * @return float
315
     */
316
    public function getTotalAllowances() {
317
        $totalItems = $this->_items->getTotalAllowances();
318
        $totalTaxableAmountItems = $this->_items->getTotalTaxableAmount();
319
        $globalAllowancesAmount = Operations::getTotalAllowanceCharge($totalTaxableAmountItems, $this->allowances);
320
        return $totalItems + $globalAllowancesAmount;
321
    }
322
    /**
323
     * Total a pagar
324
     * 
325
     * El importe que el usuario está obligado a pagar
326
     * 
327
     * Formula = OPERACIONES_GRAVADAS + IGV + OPERACIONES_EXONERADAS + OPERACIONES_INAFECTAS
328
     * 
329
     * @return float
330
     */
331
    public function getPayableAmount() {
332
        // Totals
333
        $totalTaxableOperations  = $this->getTotalTaxableOperations();
334
        $totalIGV                = $this->getIGV();
335
        $totalExemptedOperations = $this->getTotalExemptedOperations();
336
        return $totalTaxableOperations + $totalIGV + $totalExemptedOperations;
337
    }
338
339
    /**
340
     * 
341
     * Total impuestos
342
     * 
343
     * Fórmula: IGV + ISC + IVAP
344
     * 
345
     * @return float
346
     */
347
    public function getTotalTaxes() {
348
        $IGV  = $this->getIGV();
349
        $ISC  = $this->getISC();
350
        $IVAP = $this->getIVAP();
351
        return $IGV + $ISC + $IVAP;
352
    }
353
354
    /**
355
     * IGV
356
     * @return float
357
     */
358
    public function getIGV() {
359
        $baseAmount = $this->getTaxableAmount();
360
        return Operations::calcIGV($baseAmount);
361
    }
362
363
    /**
364
     * ISC
365
     * @IMP
366
     * @return float
367
     */
368
    public function getISC() {
369
        return Operations::calcISC();
370
    }
371
    /**
372
     * IVAP
373
     * @IMP
374
     * @return float
375
     */
376
    public function getIVAP() {
377
        return Operations::calcIVAP();
378
    }
379
    /**
380
     * 
381
     * @param float $amount
382
     * @return float
383
     */
384
    private function applyAllowancesAndCharges($amount) {
385
        return Operations::applyAllowancesAndCharges($amount, $this->allowances, $this->charges);
386
    }
387
388
}
389