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

SunatDocument::addInvoiceItem()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 105
Code Lines 87

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 87
nc 4
nop 1
dl 0
loc 105
rs 8.2836
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
21
use F72X\UblComponent\OrderReference;
22
use F72X\UblComponent\Party;
23
use F72X\UblComponent\PartyIdentification;
24
use F72X\UblComponent\PartyName;
25
use F72X\UblComponent\AccountingSupplierParty;
26
use F72X\UblComponent\AccountingCustomerParty;
27
use F72X\UblComponent\PartyLegalEntity;
28
use F72X\UblComponent\TaxTotal;
29
use F72X\UblComponent\TaxSubTotal;
30
use F72X\UblComponent\TaxCategory;
31
use F72X\UblComponent\TaxScheme;
32
use F72X\UblComponent\LegalMonetaryTotal;
33
use F72X\UblComponent\InvoiceLine;
34
use F72X\UblComponent\AllowanceCharge;
35
use F72X\UblComponent\PricingReference;
36
use F72X\UblComponent\AlternativeConditionPrice;
37
use F72X\UblComponent\Item;
38
use F72X\UblComponent\SellersItemIdentification;
39
use F72X\UblComponent\CommodityClassification;
40
use F72X\UblComponent\Price;
41
42
abstract class SunatDocument extends Invoice {
43
44
    const UBL_VERSION_ID = '2.1';
45
    const CUSTUMIZATION_ID = '2.0';
46
47
    /** @var InvoiceDocument */
48
    private $invoiceDocument;
49
50
    /** @var InvoiceItems */
51
    private $_detailMatrix;
52
53
    public function __construct(InvoiceDocument $document) {
54
        $this->invoiceDocument = $document;
55
        $currencyType = $document->getCurrencyType();
56
        $Items = $document->getItems();
57
        // Invoice Type
58
        $this->setInvoiceTypeCode($document->getInvoiceType());
59
        // ID
60
        $this->setID($document->getVoucherId());
61
        // Tipo de operación
62
        $this->setProfileID($document->getOperationType());
63
        // Fecha de emisión
64
        $this->setIssueDate($document->getIssueDate());
65
        // Tipo de moneda
66
        $this->setDocumentCurrencyCode($currencyType);
67
        // Orden de compra
68
        $this->addInvoiceOrderReference();
69
        // Información de la empresa
70
        $this->addInvoiceAccountingSupplierParty();
71
        // Información del cliente
72
        $this->addInvoiceAccountingCustomerParty();
73
        // Total items
74
        $this->setLineCountNumeric($document->getTotalItems());
75
        // Detalle
76
        $this->addInvoiceItems();
77
        // Impuestos
78
        $this->addInvoiceTaxes();
79
        // Descuentos globales
80
        $allowances = $document->getAllowances();
81
        $baseAmount = $Items->getTotalTaxableAmount();
82
        foreach ($allowances as $item) {
83
            $k = $item['multiplierFactor'];
84
            $amount = $baseAmount * $k;
85
            UblHelper::addAllowanceCharge($this, $currencyType, 'false', $item['reasonCode'], $item['multiplierFactor'], $amount, $baseAmount);
86
        }
87
       // Totales
88
       $this->addInvoiceLegalMonetaryTotal();
89
        
90
    }
91
92
    public function getInvoiceDocument() {
93
        return $this->invoiceDocument;
94
    }
95
    /**
96
     * 
97
     * @return InvoiceItems
98
     */
99
    public function getItems() {
100
        return $this->invoiceDocument->getItems();
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
    private function addInvoiceItems() {
111
        $ln = $this->invoiceDocument->getTotalItems();
112
        // Loop
113
        for ($i = 0; $i < $ln; $i++) {
114
            self::addInvoiceItem($i);
0 ignored issues
show
Bug Best Practice introduced by
The method F72X\Sunat\Document\Suna...ument::addInvoiceItem() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

114
            self::/** @scrutinizer ignore-call */ 
115
                  addInvoiceItem($i);
Loading history...
115
        }
116
    }
117
    private function addInvoiceOrderReference(){
118
        $orderNumer = $this->invoiceDocument->getPurchaseOrder();
119
        if ($orderNumer) {
120
            // Xml Node
121
            $orderRef = new OrderReference();
122
            // Añadir al documento
123
            $this->setOrderReference($orderRef
124
                    ->setID($orderNumer));
125
        }
126
    }
127
    private function addInvoiceTaxes() {
128
        $Invoice                   = $this->invoiceDocument;
129
        $currencyID                = $Invoice->getCurrencyType();              // Tipo de moneda
130
        $totalTaxableOperations    = $Invoice->getTotalTaxableOperations();    // Total operaciones gravadas
131
        $totalTaxes                = $Invoice->getTotalTaxes();                // Total operaciones gravadas
132
        $Igv                       = $Invoice->getIGV();                       // Total IGV
133
        $totalExemptedOperations   = $Invoice->getTotalExemptedOperations();   // Total operaciones exoneradas
134
        $totalUnaffectedOperations = $Invoice->getTotalUnaffectedOperations(); // Total operaciones inafectas
135
        $totalFreeOpertions        = $Invoice->getTotalFreeOperations();       // Total operaciones gratuitas
136
137
        // XML nodes
138
        $TaxTotal = new TaxTotal();
139
140
        // Operaciones gravadas
141
        if ($Igv) {
142
            UblHelper::addTaxSubtotal($TaxTotal, $currencyID, $Igv, $totalTaxableOperations, Catalogo::CAT5_IGV);
143
        }
144
        // Total operaciones exoneradas
145
        if ($totalExemptedOperations) {
146
            UblHelper::addTaxSubtotal($TaxTotal, $currencyID, 0, $totalExemptedOperations,   Catalogo::CAT5_EXO);
147
        }
148
        // Total operaciones inafectas
149
        if ($totalUnaffectedOperations) {
150
            UblHelper::addTaxSubtotal($TaxTotal, $currencyID, 0, $totalUnaffectedOperations, Catalogo::CAT5_INA);
151
        }
152
        // Total operaciones gratuitas solo aplica a FACTURA
153
        if ($totalFreeOpertions && $Invoice->getInvoiceType() === Catalogo::CAT1_FACTURA) {
154
            UblHelper::addTaxSubtotal($TaxTotal, $currencyID, 0, $totalFreeOpertions,        Catalogo::CAT5_GRA);
155
        }
156
157
        // Total impuestos
158
        $TaxTotal
159
                ->setCurrencyID($currencyID)
160
                ->setTaxAmount($totalTaxes);
161
        // Anadir al documento
162
        $this->setTaxTotal($TaxTotal);
163
    }
164
165
    /**
166
     * 
167
     * @param int $itemIndex Index del item
168
     */
169
    private function addInvoiceItem($itemIndex) {
170
171
        // XML Nodes
172
        $InvoiceLine      = new InvoiceLine();
173
        $PricingReference = new PricingReference();
174
        $TaxTotal         = new TaxTotal();
175
        $TaxSubTotal      = new TaxSubTotal();
176
        $TaxCategory      = new TaxCategory();
177
        $TaxCategory
178
                ->setElementAttributes('ID', [
179
                    'schemeID'         => 'UN/ECE 5305',
180
                    'schemeName'       => 'Tax Category Identifier',
181
                    'schemeAgencyName' => 'United Nations Economic Commission for Europe'])
182
                ->setElementAttributes('TaxExemptionReasonCode', [
183
                    'listAgencyName'   => 'PE:SUNAT',
184
                    'listName'         => 'SUNAT:Codigo de Tipo de Afectación del IGV',
185
                    'listURI'          => 'urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo07']);
186
187
        $TaxScheme = new TaxScheme();
188
        $TaxScheme
189
                ->setElementAttributes('ID', [
190
                    'schemeID'         => 'UN/ECE 5153',
191
                    'schemeName'       => 'Tax Scheme Identifier',
192
                    'schemeAgencyName' => 'United Nations Economic Commission for Europe']);
193
194
        $AlternativeConditionPrice  = new AlternativeConditionPrice();
195
        $Item                       = new Item();
196
        $SellersItemIdentification  = new SellersItemIdentification();
197
        $CommodityClassification    = new CommodityClassification();
198
        $Price                      = new Price();
199
        // Detail Operation Matrix
200
        $Items = $this->invoiceDocument->getItems();
201
        // Vars
202
        $productCode        = $Items->getProductCode($itemIndex);
203
        $sunatProductCode   = $Items->getUNPSC($itemIndex);
204
        $unitCode           = $Items->getUnitCode($itemIndex);
205
        $quantity           = $Items->getQunatity($itemIndex);
206
        $description        = $Items->getDescription($itemIndex);
207
        $currencyID         = $Items->getCurrencyCode($itemIndex);
208
        $unitBillableValue  = $Items->getUnitBillableValue($itemIndex);
209
        $priceTypeCode      = $Items->getPriceTypeCode($itemIndex);
210
        $taxTypeCode        = $Items->getTaxTypeCode($itemIndex);
211
        $igvAffectationCode = $Items->getIgvAffectationCode($itemIndex);
212
        
213
        $itemValue          = $Items->getItemValue($itemIndex);
214
        $allowances         = $Items->getAllowances($itemIndex);
215
        $charges            = $Items->getCharges($itemIndex);
216
        $itemTaxableAmount  = $Items->getTaxableAmount($itemIndex);
217
        $itemTaxAmount      = $Items->getIgv($itemIndex);
218
        $unitPrice          = $Items->getUnitTaxedValue($itemIndex);
219
220
        // Catálogo 5 Ipuesto aplicable
221
        $cat5Item = Catalogo::getCatItem(5, $taxTypeCode);
222
223
        // Descuentos
224
        foreach ($allowances as $item) {
225
            $multFactor = $item['multiplierFactor'];
226
            $amount = $itemValue * $multFactor;
227
            UblHelper::addAllowanceCharge($InvoiceLine, $currencyID, 'false', $item['reasonCode'], $multFactor, $amount, $itemValue);
228
        }
229
        // Cargos
230
        foreach ($charges as $item) {
231
            $multFactor = $item['multiplierFactor'];
232
            $amount = $itemValue * $multFactor;
233
            UblHelper::addAllowanceCharge($InvoiceLine, $currencyID, 'true', $item['reasonCode'], $multFactor, $amount, $itemValue);
234
        }
235
236
        $InvoiceLine
237
                ->setCurrencyID($currencyID)                    // Tipo de moneda
238
                ->setID($itemIndex + 1)                         // Número de orden
239
                ->setUnitCode($unitCode)                        // Codigo de unidad de medida
240
                ->setInvoicedQuantity($quantity)                // Cantidad
241
                ->setLineExtensionAmount($itemTaxableAmount)    // Valor de venta del ítem, sin impuestos
242
                ->setPricingReference($PricingReference
243
                        ->setAlternativeConditionPrice($AlternativeConditionPrice
244
                                ->setCurrencyID($currencyID)            // Tipo de moneda
245
                                ->setPriceAmount($unitPrice)            // Precio de venta unitario
246
                                ->setPriceTypeCode($priceTypeCode)))    // Price
247
                ->setTaxTotal($TaxTotal
248
                        ->setCurrencyID($currencyID)
249
                        ->setTaxAmount($itemTaxAmount)
250
                        ->addTaxSubTotal($TaxSubTotal
251
                                ->setCurrencyID($currencyID)            // Tipo de moneda
252
                                ->setTaxableAmount($itemTaxableAmount)  // Valor de venta del item sin impuestos
253
                                ->setTaxAmount($itemTaxAmount)          // IGV
254
                                ->setTaxCategory($TaxCategory
255
                                        ->setID($cat5Item['categoria'])                     // Codigo de categoria de immpuestos @CAT5
256
                                        ->setPercent(SunatVars::IGV_PERCENT)                // Porcentaje de IGV (18.00)
257
                                        ->setTaxExemptionReasonCode($igvAffectationCode)    // Código de afectación del IGV
258
                                        ->setTaxScheme($TaxScheme
259
                                                ->setID($taxTypeCode)                       // Codigo de categoria de impuesto
260
                                                ->setName($cat5Item['name'])
261
                                                ->setTaxTypeCode($cat5Item['UN_ECE_5153'])))))
262
                ->setItem($Item
263
                        ->setDescription($description)                              // Descripción
264
                        ->setSellersItemIdentification($SellersItemIdentification
265
                                ->setID($productCode))                              // Código de producto
266
                        ->setCommodityClassification($CommodityClassification
267
                                ->setItemClassificationCode($sunatProductCode)))    // Código de producto SUNAT
268
                ->setPrice($Price
269
                        ->setCurrencyID($currencyID)    // Tipo de moneda
270
                        ->setPriceAmount($unitBillableValue)    // Precio unitario del item
271
        );
272
        // Añade item
273
        $this->addInvoiceLine($InvoiceLine);
274
    }
275
    
276
    private function addInvoiceLegalMonetaryTotal() {
277
        $Invoice            = $this->invoiceDocument;
278
        $Items              = $this->getItems();
0 ignored issues
show
Unused Code introduced by
The assignment to $Items is dead and can be removed.
Loading history...
279
        $currencyID         = $this->getDocumentCurrencyCode(); // Tipo de moneda
280
        $totalAllowances    = $Invoice->getTotalAllowances();   // Total descuentos
281
        $payableAmount      = $Invoice->getPayableAmount();     // Total a pagar
282
        $billableAmount     = $Invoice->getBillableValue();
283
        // LegalMonetaryTotal
284
        $LegalMonetaryTotal = new LegalMonetaryTotal();
285
        $LegalMonetaryTotal
286
                ->setCurrencyID($currencyID)
287
                ->setLineExtensionAmount($billableAmount)
288
                ->setTaxInclusiveAmount($payableAmount)
289
                ->setAllowanceTotalAmount($totalAllowances)
290
                ->setPayableAmount($payableAmount);
291
292
        $this->setLegalMonetaryTotal($LegalMonetaryTotal);
293
    }
294
    private function addInvoiceAccountingSupplierParty() {
295
        // Info
296
        $partyName  = Company::getBusinessName();
297
        $regName    = Company::getCompanyName();
298
        $docNumber  = Company::getRUC();
299
        $docType    = Catalogo::IDENTIFICATION_DOC_RUC;
300
        
301
        // XML nodes
302
        $AccountingSupplierParty    = new AccountingSupplierParty();
303
        $Party                      = new Party();
304
        $PartyIdentification        = new PartyIdentification();
305
        $PartyIdentification
306
                ->setElementAttributes('ID', [
307
                    'schemeAgencyName'  => 'PE:SUNAT',
308
                    'schemeID'          => $docType,
309
                    'schemeName'        => 'Documento de Identidad',
310
                    'schemeURI'         => 'urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo06']);
311
        $PartyName                  = new PartyName();
312
        $PartyLegalEntity           = new PartyLegalEntity();
313
        
314
        $AccountingSupplierParty
315
                ->setParty($Party
316
                        ->setPartyIdentification($PartyIdentification
317
                                ->setID($docNumber))
318
                        ->setPartyName($PartyName
319
                                ->setName($partyName))
320
                        ->setPartyLegalEntity($PartyLegalEntity
321
                                ->setRegistrationName($regName)));
322
        // Add to Document
323
        $this->setAccountingSupplierParty($AccountingSupplierParty);
324
    }
325
326
    private function addInvoiceAccountingCustomerParty() {
327
        $Invoice   = $this->invoiceDocument;
328
        // Info
329
        $regName   = $Invoice->getCustomerRegName();
330
        $docNumber = $Invoice->getCustomerDocNumber();
331
        $docType   = $Invoice->getCustomerDocType();
332
        
333
        // XML nodes
334
        $AccountingCustomerParty    = new AccountingCustomerParty();
335
        $Party                      = new Party();
336
        $PartyIdentification        = new PartyIdentification();
337
        $PartyLegalEntity           = new PartyLegalEntity();
338
        $PartyIdentification
339
                ->setElementAttributes('ID', [
340
                    'schemeAgencyName'  => 'PE:SUNAT',
341
                    'schemeID'          => $docType,
342
                    'schemeName'        => 'Documento de Identidad',
343
                    'schemeURI'         => 'urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo06']);
344
        
345
        $AccountingCustomerParty
346
                ->setParty($Party
347
                        ->setPartyIdentification($PartyIdentification
348
                                ->setID($docNumber))
349
                        ->setPartyLegalEntity($PartyLegalEntity
350
                                ->setRegistrationName($regName)));
351
        // Add to Document
352
        $this->setAccountingCustomerParty($AccountingCustomerParty);
353
    }
354
    /**
355
     *    
356
     * @return string Nombre del comprobante de acuerdo con las especificaciones de la SUNAT
357
     */
358
    public function getFileName() {
359
        return Company::getRUC() . '-' . $this->InvoiceTypeCode . '-' . $this->ID . '.xml';
360
    }
361
362
}
363