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

SunatDocument::getFileName()   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 0
dl 0
loc 2
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\Document;
12
13
use F72X\Company;
14
use F72X\UblComponent\Invoice;
15
use F72X\Sunat\InvoiceDocument;
16
use F72X\Sunat\InvoiceItems;
17
use F72X\Sunat\Catalogo;
18
use F72X\Sunat\SunatVars;
19
use F72X\Tools\UblHelper;
20
use F72X\UblComponent\OrderReference;
21
use F72X\UblComponent\Party;
22
use F72X\UblComponent\PartyIdentification;
23
use F72X\UblComponent\PartyName;
24
use F72X\UblComponent\AccountingSupplierParty;
25
use F72X\UblComponent\AccountingCustomerParty;
26
use F72X\UblComponent\PartyLegalEntity;
27
use F72X\UblComponent\TaxTotal;
28
use F72X\UblComponent\TaxSubTotal;
29
use F72X\UblComponent\TaxCategory;
30
use F72X\UblComponent\TaxScheme;
31
use F72X\UblComponent\LegalMonetaryTotal;
32
use F72X\UblComponent\InvoiceLine;
33
use F72X\UblComponent\PricingReference;
34
use F72X\UblComponent\AlternativeConditionPrice;
35
use F72X\UblComponent\Item;
36
use F72X\UblComponent\SellersItemIdentification;
37
use F72X\UblComponent\CommodityClassification;
38
use F72X\UblComponent\Price;
39
40
abstract class SunatDocument extends Invoice {
41
42
    const UBL_VERSION_ID = '2.1';
43
    const CUSTUMIZATION_ID = '2.0';
44
45
    /** @var InvoiceDocument */
46
    private $invoiceDocument;
47
48
    /** @var InvoiceItems */
49
    private $_detailMatrix;
50
51
    public function __construct(InvoiceDocument $document) {
52
        $this->invoiceDocument = $document;
53
        $currencyType = $document->getCurrencyType();
54
        $Items = $document->getItems();
55
        // Invoice Type
56
        $this->setInvoiceTypeCode($document->getInvoiceType());
57
        // ID
58
        $this->setID($document->getVoucherId());
59
        // Tipo de operación
60
        $this->setProfileID($document->getOperationType());
61
        // Fecha de emisión
62
        $this->setIssueDate($document->getIssueDate());
63
        // Tipo de moneda
64
        $this->setDocumentCurrencyCode($currencyType);
65
        // Orden de compra
66
        $this->addInvoiceOrderReference();
67
        // Información de la empresa
68
        $this->addInvoiceAccountingSupplierParty();
69
        // Información del cliente
70
        $this->addInvoiceAccountingCustomerParty();
71
        // Total items
72
        $this->setLineCountNumeric($document->getTotalItems());
73
        // Detalle
74
        $this->addInvoiceItems();
75
        // Impuestos
76
        $this->addInvoiceTaxes();
77
        // Descuentos globales
78
        $ac = $document->getAllowancesAndCharges();
79
        $baseAmount = $Items->getTotalTaxableAmount();
80
        foreach ($ac as $item) {
81
            $k = $item['multiplierFactor'];
82
            $amount = $baseAmount * $k;
83
            $chargeIndicator = $item['isCharge'] ? 'true' : 'false';
84
            UblHelper::addAllowanceCharge($this, $currencyType, $chargeIndicator, $item['reasonCode'], $item['multiplierFactor'], $amount, $baseAmount);
85
        }
86
        // Totales
87
        $this->addInvoiceLegalMonetaryTotal();
88
    }
89
90
    public function getInvoiceDocument() {
91
        return $this->invoiceDocument;
92
    }
93
94
    /**
95
     * 
96
     * @return InvoiceItems
97
     */
98
    public function getItems() {
99
        return $this->invoiceDocument->getItems();
100
    }
101
102
    public function getDetailMatrix() {
103
        return $this->_detailMatrix;
104
    }
105
106
    public function setDetailMatrix(InvoiceItems $DetailMatrix) {
107
        $this->_detailMatrix = $DetailMatrix;
108
        return $this;
109
    }
110
111
    private function addInvoiceItems() {
112
        $ln = $this->invoiceDocument->getTotalItems();
113
        // Loop
114
        for ($i = 0; $i < $ln; $i++) {
115
            $this->addInvoiceItem($i);
116
        }
117
    }
118
119
    private function addInvoiceOrderReference() {
120
        $orderNumer = $this->invoiceDocument->getPurchaseOrder();
121
        if ($orderNumer) {
122
            // Xml Node
123
            $orderRef = new OrderReference();
124
            // Añadir al documento
125
            $this->setOrderReference($orderRef
126
                            ->setID($orderNumer));
127
        }
128
    }
129
130
    private function addInvoiceTaxes() {
131
        $Invoice                   = $this->invoiceDocument;
132
        $currencyID                = $Invoice->getCurrencyType();              // Tipo de moneda
133
        $totalTaxableOperations    = $Invoice->getTotalTaxableOperations();    // Total operaciones gravadas
134
        $totalTaxes                = $Invoice->getTotalTaxes();                // Total operaciones gravadas
135
        $Igv                       = $Invoice->getIGV();                       // Total IGV
136
        $totalExemptedOperations   = $Invoice->getTotalExemptedOperations();   // Total operaciones exoneradas
137
        $totalUnaffectedOperations = $Invoice->getTotalUnaffectedOperations(); // Total operaciones inafectas
138
        $totalFreeOpertions        = $Invoice->getTotalFreeOperations();       // Total operaciones gratuitas
139
140
        // XML nodes
141
        $TaxTotal = new TaxTotal();
142
143
        // Operaciones gravadas
144
        if ($Igv) {
145
            UblHelper::addTaxSubtotal($TaxTotal, $currencyID, $Igv, $totalTaxableOperations, Catalogo::CAT5_IGV);
146
        }
147
        // Total operaciones exoneradas
148
        if ($totalExemptedOperations) {
149
            UblHelper::addTaxSubtotal($TaxTotal, $currencyID, 0, $totalExemptedOperations,   Catalogo::CAT5_EXO);
150
        }
151
        // Total operaciones inafectas
152
        if ($totalUnaffectedOperations) {
153
            UblHelper::addTaxSubtotal($TaxTotal, $currencyID, 0, $totalUnaffectedOperations, Catalogo::CAT5_INA);
154
        }
155
        // Total operaciones gratuitas solo aplica a FACTURA
156
        if ($totalFreeOpertions && $Invoice->getInvoiceType() === Catalogo::CAT1_FACTURA) {
157
            UblHelper::addTaxSubtotal($TaxTotal, $currencyID, 0, $totalFreeOpertions,        Catalogo::CAT5_GRA);
158
        }
159
160
        // Total impuestos
161
        $TaxTotal
162
                ->setCurrencyID($currencyID)
163
                ->setTaxAmount($totalTaxes);
164
        // Anadir al documento
165
        $this->setTaxTotal($TaxTotal);
166
    }
167
168
    /**
169
     * 
170
     * @param int $itemIndex Index del item
171
     */
172
    private function addInvoiceItem($itemIndex) {
173
174
        // XML Nodes
175
        $InvoiceLine      = new InvoiceLine();
176
        $PricingReference = new PricingReference();
177
        $TaxTotal         = new TaxTotal();
178
        $TaxSubTotal      = new TaxSubTotal();
179
        $TaxCategory      = new TaxCategory();
180
        $TaxCategory
181
                ->setElementAttributes('ID', [
182
                    'schemeID'         => 'UN/ECE 5305',
183
                    'schemeName'       => 'Tax Category Identifier',
184
                    'schemeAgencyName' => 'United Nations Economic Commission for Europe'])
185
                ->setElementAttributes('TaxExemptionReasonCode', [
186
                    'listAgencyName'   => 'PE:SUNAT',
187
                    'listName'         => 'SUNAT:Codigo de Tipo de Afectación del IGV',
188
                    'listURI'          => 'urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo07']);
189
190
        $TaxScheme = new TaxScheme();
191
        $TaxScheme
192
                ->setElementAttributes('ID', [
193
                    'schemeID'         => 'UN/ECE 5153',
194
                    'schemeName'       => 'Tax Scheme Identifier',
195
                    'schemeAgencyName' => 'United Nations Economic Commission for Europe']);
196
197
        $AlternativeConditionPrice  = new AlternativeConditionPrice();
198
        $Item                       = new Item();
199
        $SellersItemIdentification  = new SellersItemIdentification();
200
        $CommodityClassification    = new CommodityClassification();
201
        $Price                      = new Price();
202
        // Detail Operation Matrix
203
        $Items = $this->invoiceDocument->getItems();
204
        // Vars
205
        $productCode        = $Items->getProductCode($itemIndex);
206
        $sunatProductCode   = $Items->getUNPSC($itemIndex);
207
        $unitCode           = $Items->getUnitCode($itemIndex);
208
        $quantity           = $Items->getQunatity($itemIndex);
209
        $description        = $Items->getDescription($itemIndex);
210
        $currencyID         = $Items->getCurrencyCode($itemIndex);
211
        $unitBillableValue  = $Items->getUnitBillableValue($itemIndex);
212
        $priceTypeCode      = $Items->getPriceTypeCode($itemIndex);
213
        $taxTypeCode        = $Items->getTaxTypeCode($itemIndex);
214
        $igvAffectationCode = $Items->getIgvAffectationCode($itemIndex);
215
216
        $itemValue          = $Items->getItemValue($itemIndex);
217
        $ac                 = $Items->getAllowancesAndCharges($itemIndex);
218
        $itemTaxableAmount  = $Items->getTaxableAmount($itemIndex);
219
        $itemTaxAmount      = $Items->getIgv($itemIndex);
220
        $unitPrice          = $Items->getUnitTaxedValue($itemIndex);
221
222
        // Catálogo 5 Ipuesto aplicable
223
        $cat5Item = Catalogo::getCatItem(5, $taxTypeCode);
224
225
        // Descuentos y cargos
226
        foreach ($ac as $item) {
227
            $multFactor = $item['multiplierFactor'];
228
            $amount = $itemValue * $multFactor;
229
            $chargeIndicator = $item['isCharge'] ? 'true' : 'false';
230
            UblHelper::addAllowanceCharge($InvoiceLine, $currencyID, $chargeIndicator, $item['reasonCode'], $multFactor, $amount, $itemValue);
231
        }
232
233
        $InvoiceLine
234
                ->setCurrencyID($currencyID)                    // Tipo de moneda
235
                ->setID($itemIndex + 1)                         // Número de orden
236
                ->setUnitCode($unitCode)                        // Codigo de unidad de medida
237
                ->setInvoicedQuantity($quantity)                // Cantidad
238
                ->setLineExtensionAmount($itemTaxableAmount)    // Valor de venta del ítem, sin impuestos
239
                ->setPricingReference($PricingReference
240
                        ->setAlternativeConditionPrice($AlternativeConditionPrice
241
                                ->setCurrencyID($currencyID)            // Tipo de moneda
242
                                ->setPriceAmount($unitPrice)            // Precio de venta unitario
243
                                ->setPriceTypeCode($priceTypeCode)))    // Price
244
                ->setTaxTotal($TaxTotal
245
                        ->setCurrencyID($currencyID)
246
                        ->setTaxAmount($itemTaxAmount)
247
                        ->addTaxSubTotal($TaxSubTotal
248
                                ->setCurrencyID($currencyID)            // Tipo de moneda
249
                                ->setTaxableAmount($itemTaxableAmount)  // Valor de venta del item sin impuestos
250
                                ->setTaxAmount($itemTaxAmount)          // IGV
251
                                ->setTaxCategory($TaxCategory
252
                                        ->setID($cat5Item['categoria'])                     // Codigo de categoria de immpuestos @CAT5
253
                                        ->setPercent(SunatVars::IGV_PERCENT)                // Porcentaje de IGV (18.00)
254
                                        ->setTaxExemptionReasonCode($igvAffectationCode)    // Código de afectación del IGV
255
                                        ->setTaxScheme($TaxScheme
256
                                                ->setID($taxTypeCode)                       // Codigo de categoria de impuesto
257
                                                ->setName($cat5Item['name'])
258
                                                ->setTaxTypeCode($cat5Item['UN_ECE_5153'])))))
259
                ->setItem($Item
260
                        ->setDescription($description)                              // Descripción
261
                        ->setSellersItemIdentification($SellersItemIdentification
262
                                ->setID($productCode))                              // Código de producto
263
                        ->setCommodityClassification($CommodityClassification
264
                                ->setItemClassificationCode($sunatProductCode)))    // Código de producto SUNAT
265
                ->setPrice($Price
266
                        ->setCurrencyID($currencyID)    // Tipo de moneda
267
                        ->setPriceAmount($unitBillableValue)    // Precio unitario del item
268
        );
269
        // Añade item
270
        $this->addInvoiceLine($InvoiceLine);
271
    }
272
273
    private function addInvoiceLegalMonetaryTotal() {
274
        $Invoice            = $this->invoiceDocument;
275
        $Items              = $this->getItems();
0 ignored issues
show
Unused Code introduced by
The assignment to $Items is dead and can be removed.
Loading history...
276
        $currencyID         = $this->getDocumentCurrencyCode(); // Tipo de moneda
277
        $totalAllowances    = $Invoice->getTotalAllowances();   // Total descuentos
278
        $payableAmount      = $Invoice->getPayableAmount();     // Total a pagar
279
        $billableAmount     = $Invoice->getBillableValue();
280
        // LegalMonetaryTotal
281
        $LegalMonetaryTotal = new LegalMonetaryTotal();
282
        $LegalMonetaryTotal
283
                ->setCurrencyID($currencyID)
284
                ->setLineExtensionAmount($billableAmount)
285
                ->setTaxInclusiveAmount($payableAmount)
286
                ->setAllowanceTotalAmount($totalAllowances)
287
                ->setPayableAmount($payableAmount);
288
289
        $this->setLegalMonetaryTotal($LegalMonetaryTotal);
290
    }
291
292
    private function addInvoiceAccountingSupplierParty() {
293
        // Info
294
        $partyName  = Company::getBusinessName();
295
        $regName    = Company::getCompanyName();
296
        $docNumber  = Company::getRUC();
297
        $docType    = Catalogo::IDENTIFICATION_DOC_RUC;
298
299
        // XML nodes
300
        $AccountingSupplierParty    = new AccountingSupplierParty();
301
        $Party                      = new Party();
302
        $PartyIdentification        = new PartyIdentification();
303
        $PartyIdentification
304
                ->setElementAttributes('ID', [
305
                    'schemeAgencyName'  => 'PE:SUNAT',
306
                    'schemeID'          => $docType,
307
                    'schemeName'        => 'Documento de Identidad',
308
                    'schemeURI'         => 'urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo06']);
309
        $PartyName                  = new PartyName();
310
        $PartyLegalEntity           = new PartyLegalEntity();
311
312
        $AccountingSupplierParty
313
                ->setParty($Party
314
                        ->setPartyIdentification($PartyIdentification
315
                                ->setID($docNumber))
316
                        ->setPartyName($PartyName
317
                                ->setName($partyName))
318
                        ->setPartyLegalEntity($PartyLegalEntity
319
                                ->setRegistrationName($regName)));
320
        // Add to Document
321
        $this->setAccountingSupplierParty($AccountingSupplierParty);
322
    }
323
324
    private function addInvoiceAccountingCustomerParty() {
325
        $Invoice   = $this->invoiceDocument;
326
        // Info
327
        $regName   = $Invoice->getCustomerRegName();
328
        $docNumber = $Invoice->getCustomerDocNumber();
329
        $docType   = $Invoice->getCustomerDocType();
330
331
        // XML nodes
332
        $AccountingCustomerParty    = new AccountingCustomerParty();
333
        $Party                      = new Party();
334
        $PartyIdentification        = new PartyIdentification();
335
        $PartyLegalEntity           = new PartyLegalEntity();
336
        $PartyIdentification
337
                ->setElementAttributes('ID', [
338
                    'schemeAgencyName'  => 'PE:SUNAT',
339
                    'schemeID'          => $docType,
340
                    'schemeName'        => 'Documento de Identidad',
341
                    'schemeURI'         => 'urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo06']);
342
343
        $AccountingCustomerParty
344
                ->setParty($Party
345
                        ->setPartyIdentification($PartyIdentification
346
                                ->setID($docNumber))
347
                        ->setPartyLegalEntity($PartyLegalEntity
348
                                ->setRegistrationName($regName)));
349
        // Add to Document
350
        $this->setAccountingCustomerParty($AccountingCustomerParty);
351
    }
352
353
    /**
354
     *    
355
     * @return string Nombre del comprobante de acuerdo con las especificaciones de la SUNAT
356
     */
357
    public function getBillName() {
358
        return Company::getRUC() . '-' . $this->InvoiceTypeCode . '-' . $this->ID;
359
    }
360
361
}
362