BillMixin   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 319
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 199
dl 0
loc 319
rs 10
c 0
b 0
f 0
wmc 27

12 Methods

Rating   Name   Duplication   Size   Complexity  
A addInvoiceOrderReference() 0 8 2
A addDocumentItems() 0 5 2
A getItems() 0 2 1
A getDataMap() 0 2 1
B addDocumentItem() 0 101 4
A addDocumentLine() 0 11 4
A addInvoiceLegalMonetaryTotal() 0 16 1
A addInvoiceAccountingCustomerParty() 0 27 1
A setDocumentLineQuantity() 0 11 4
A addDocumentTaxes() 0 36 5
A addInvoiceAccountingSupplierParty() 0 36 1
A getDocumentName() 0 2 1
1
<?php
2
3
/**
4
 * MÓDULO DE EMISIÓN ELECTRÓNICA F72X
5
 * UBL 2.1
6
 * Version 1.0
7
 * 
8
 * Copyright 2019, Jaime Cruz
9
 */
10
11
namespace F72X\Sunat\Document;
12
13
use F72X\Company;
14
use F72X\Sunat\DataMap;
15
use F72X\Sunat\InvoiceItems;
16
use F72X\Sunat\Catalogo;
17
use F72X\Sunat\SunatVars;
18
use F72X\Tools\UblHelper;
19
use F72X\UblComponent\OrderReference;
20
use F72X\UblComponent\Party;
21
use F72X\UblComponent\PartyIdentification;
22
use F72X\UblComponent\PartyTaxScheme;
23
use F72X\UblComponent\RegistrationAddress;
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\CreditNoteLine;
35
use F72X\UblComponent\DebitNoteLine;
36
use F72X\UblComponent\PricingReference;
37
use F72X\UblComponent\AlternativeConditionPrice;
38
use F72X\UblComponent\Item;
39
use F72X\UblComponent\SellersItemIdentification;
40
use F72X\UblComponent\CommodityClassification;
41
use F72X\UblComponent\Price;
42
43
trait BillMixin {
44
45
    
46
47
    /** @var DataMap */
48
    private $dataMap;
49
50
    public function getDataMap() {
51
        return $this->dataMap;
52
    }
53
54
    /**
55
     * 
56
     * @return InvoiceItems
57
     */
58
    public function getItems() {
59
        return $this->dataMap->getItems();
60
    }
61
62
    /**
63
     * 
64
     * @param string $lineType InvoiceLine|CreditNoteLine|DebitNoteLine
65
     */
66
    private function addDocumentItems($lineType) {
67
        $ln = $this->dataMap->getTotalItems();
68
        // Loop
69
        for ($i = 0; $i < $ln; $i++) {
70
            $this->addDocumentItem($i, $lineType);
71
        }
72
    }
73
74
    private function addInvoiceOrderReference() {
75
        $orderNumer = $this->dataMap->getPurchaseOrder();
76
        if ($orderNumer) {
77
            // Xml Node
78
            $orderRef = new OrderReference();
79
            $orderRef->setID($orderNumer);
80
            // Añadir al documento
81
            parent::setOrderReference($orderRef);
82
        }
83
    }
84
85
    private function addDocumentTaxes() {
86
        $Invoice                   = $this->dataMap;
87
        $currencyID                = $Invoice->getCurrencyCode();              // Tipo de moneda
88
        $totalTaxableOperations    = $Invoice->getTotalTaxableOperations();    // Total operaciones gravadas
89
        $totalTaxes                = $Invoice->getTotalTaxes();                // Total operaciones gravadas
90
        $Igv                       = $Invoice->getIGV();                       // Total IGV
91
        $totalExemptedOperations   = $Invoice->getTotalExemptedOperations();   // Total operaciones exoneradas
92
        $totalUnaffectedOperations = $Invoice->getTotalUnaffectedOperations(); // Total operaciones inafectas
93
        $totalFreeOpertions        = $Invoice->getTotalFreeOperations();       // Total operaciones gratuitas
94
95
        // XML nodes
96
        $TaxTotal = new TaxTotal();
97
98
        // Operaciones gravadas
99
        if ($Igv) {
100
            UblHelper::addTaxSubtotal($TaxTotal, $currencyID, $Igv, $totalTaxableOperations, Catalogo::CAT5_IGV);
101
        }
102
        // Total operaciones exoneradas
103
        if ($totalExemptedOperations) {
104
            UblHelper::addTaxSubtotal($TaxTotal, $currencyID, 0, $totalExemptedOperations,   Catalogo::CAT5_EXO);
105
        }
106
        // Total operaciones inafectas
107
        if ($totalUnaffectedOperations) {
108
            UblHelper::addTaxSubtotal($TaxTotal, $currencyID, 0, $totalUnaffectedOperations, Catalogo::CAT5_INA);
109
        }
110
        // Total operaciones gratuitas
111
        if ($totalFreeOpertions) {
112
            UblHelper::addTaxSubtotal($TaxTotal, $currencyID, 0, $totalFreeOpertions,        Catalogo::CAT5_GRA);
113
        }
114
115
        // Total impuestos
116
        $TaxTotal
117
                ->setCurrencyID($currencyID)
118
                ->setTaxAmount($totalTaxes);
119
        // Anadir al documento
120
        parent::setTaxTotal($TaxTotal);
121
    }
122
123
    /**
124
     * 
125
     * @param int $itemIndex Index del item
126
     * @param string $lineType InvoiceLine|CreditNoteLine|DebitNoteLine
127
     */
128
    
129
    private function addDocumentItem($itemIndex, $lineType) {
130
        $docLineClassName = "\F72X\UblComponent\\$lineType";
131
        // XML Nodes
132
        $DocumentLine     = new $docLineClassName();
133
        $PricingReference = new PricingReference();
134
        $TaxTotal         = new TaxTotal();
135
        $TaxSubTotal      = new TaxSubTotal();
136
        $TaxCategory      = new TaxCategory();
137
        $TaxCategory
138
                ->setElementAttributes('ID', [
139
                    'schemeID'         => 'UN/ECE 5305',
140
                    'schemeName'       => 'Tax Category Identifier',
141
                    'schemeAgencyName' => 'United Nations Economic Commission for Europe'])
142
                ->setElementAttributes('TaxExemptionReasonCode', [
143
                    'listAgencyName'   => 'PE:SUNAT',
144
                    'listName'         => 'SUNAT:Codigo de Tipo de Afectación del IGV',
145
                    'listURI'          => 'urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo07']);
146
147
        $TaxScheme = new TaxScheme();
148
        $TaxScheme
149
                ->setElementAttributes('ID', [
150
                    'schemeID'         => 'UN/ECE 5153',
151
                    'schemeName'       => 'Tax Scheme Identifier',
152
                    'schemeAgencyName' => 'United Nations Economic Commission for Europe']);
153
154
        $AlternativeConditionPrice  = new AlternativeConditionPrice();
155
        $Item                       = new Item();
156
        $SellersItemIdentification  = new SellersItemIdentification();
157
        $CommodityClassification    = new CommodityClassification();
158
        $Price                      = new Price();
159
        // Detail Operation Matrix
160
        $Items = $this->dataMap->getItems();
161
        // Vars
162
        $productCode        = $Items->getProductCode($itemIndex);
163
        $sunatProductCode   = $Items->getUNPSC($itemIndex);
164
        $unitCode           = $Items->getUnitCode($itemIndex);
165
        $quantity           = $Items->getQunatity($itemIndex);
166
        $description        = $Items->getDescription($itemIndex);
167
        $currencyCode       = $Items->getCurrencyCode($itemIndex);
168
        $unitBillableValue  = $Items->getUnitBillableValue($itemIndex);
169
        $priceTypeCode      = $Items->getPriceTypeCode($itemIndex);
170
        $taxTypeCode        = $Items->getTaxTypeCode($itemIndex);
171
        $igvAffectationType = $Items->getIgvAffectationType($itemIndex);
172
        $taxCategoryPercent = $igvAffectationType === '10' ? SunatVars::IGV_PERCENT : '0.00';
173
174
        $itemValue          = $Items->getItemValue($itemIndex);
175
        $ac                 = $Items->getAllowancesAndCharges($itemIndex);
176
        $itemTaxableAmount  = $Items->getTaxableAmount($itemIndex);
177
        $itemTaxAmount      = $Items->getIgv($itemIndex);
178
        $unitPrice          = $Items->getUnitTaxedValue($itemIndex);
179
180
        // Catálogo 5 Ipuesto aplicable
181
        $cat5Item = Catalogo::getCatItem(5, $taxTypeCode);
182
183
        // Descuentos y cargos
184
        UblHelper::addAllowancesCharges($DocumentLine, $ac, $itemValue, $currencyCode);
185
186
        // Config Item
187
        $Item->setDescription($description); // Descripción
188
        // Código de producto
189
        if ($productCode) {
190
            $Item->setSellersItemIdentification($SellersItemIdentification->setID($productCode));
191
        }
192
        // Código de producto SUNAT
193
        if ($sunatProductCode) {
194
            $Item->setCommodityClassification($CommodityClassification->setItemClassificationCode($sunatProductCode));
195
        }
196
        $DocumentLine
197
                ->setCurrencyID($currencyCode)                    // Tipo de moneda
198
                ->setID($itemIndex + 1)                         // Número de orden
199
                ->setUnitCode($unitCode)                        // Codigo de unidad de medida
200
                ->setLineExtensionAmount($itemTaxableAmount)    // Valor de venta del ítem, sin impuestos
201
                ->setPricingReference($PricingReference
202
                        ->setAlternativeConditionPrice($AlternativeConditionPrice
203
                                ->setCurrencyID($currencyCode)            // Tipo de moneda
204
                                ->setPriceAmount($unitPrice)            // Precio de venta unitario
205
                                ->setPriceTypeCode($priceTypeCode)))    // Price
206
                ->setTaxTotal($TaxTotal
207
                        ->setCurrencyID($currencyCode)
208
                        ->setTaxAmount($itemTaxAmount)
209
                        ->addTaxSubTotal($TaxSubTotal
210
                                ->setCurrencyID($currencyCode)          // Tipo de moneda
211
                                ->setTaxableAmount($itemTaxableAmount)  // Valor de venta del item sin impuestos
212
                                ->setTaxAmount($itemTaxAmount)          // IGV
213
                                ->setTaxCategory($TaxCategory
214
                                        ->setID($cat5Item['categoria'])                     // Codigo de categoria de immpuestos @CAT5
215
                                        ->setPercent($taxCategoryPercent)                // Porcentaje de IGV (18.00)
216
                                        ->setTaxExemptionReasonCode($igvAffectationType)    // Código de afectación del IGV
217
                                        ->setTaxScheme($TaxScheme
218
                                                ->setID($taxTypeCode)                       // Codigo de categoria de impuesto
219
                                                ->setName($cat5Item['name'])
220
                                                ->setTaxTypeCode($cat5Item['UN_ECE_5153'])))))
221
                ->setItem($Item)
222
                ->setPrice($Price
223
                        ->setCurrencyID($currencyCode)    // Tipo de moneda
224
                        ->setPriceAmount($unitBillableValue)    // Precio unitario del item
225
        );
226
        // Set Quantity
227
        $this->setDocumentLineQuantity($DocumentLine, $lineType, $quantity);
228
        // Añade item
229
        $this->addDocumentLine($DocumentLine, $lineType);
230
    }
231
232
    /**
233
     * 
234
     * @param InvoiceLine|CreditNoteLine|DebitNoteLine $DocumentLine
235
     * @param string $lineType InvoiceLine|CreditNoteLine|DebitNoteLine
236
     * @param int $quantity
237
     */
238
    private function addDocumentLine($DocumentLine, $lineType) {
239
        switch ($lineType) {
240
            case 'InvoiceLine' :
241
                parent::addInvoiceLine($DocumentLine);
242
                break;
243
            case 'CreditNoteLine' :
244
                parent::addCreditNoteLine($DocumentLine);
245
                break;
246
            case 'DebitNoteLine' :
247
                parent::addDebitNoteLine($DocumentLine);
248
                break;
249
        }
250
    }
251
    /**
252
     * 
253
     * @param InvoiceLine|CreditNoteLine|DebitNoteLine $DocumentLine
254
     * @param string $lineType InvoiceLine|CreditNoteLine|DebitNoteLine
255
     * @param int $quantity
256
     */
257
    private function setDocumentLineQuantity($DocumentLine, $lineType, $quantity) {
258
        switch ($lineType) {
259
            case 'InvoiceLine' :
260
                $DocumentLine->setInvoicedQuantity($quantity);
0 ignored issues
show
Bug introduced by
The method setInvoicedQuantity() does not exist on F72X\UblComponent\CreditNoteLine. ( Ignorable by Annotation )

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

260
                $DocumentLine->/** @scrutinizer ignore-call */ 
261
                               setInvoicedQuantity($quantity);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method setInvoicedQuantity() does not exist on F72X\UblComponent\DebitNoteLine. ( Ignorable by Annotation )

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

260
                $DocumentLine->/** @scrutinizer ignore-call */ 
261
                               setInvoicedQuantity($quantity);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
261
                break;
262
            case 'CreditNoteLine' :
263
                $DocumentLine->setCreditedQuantity($quantity);
0 ignored issues
show
Bug introduced by
The method setCreditedQuantity() does not exist on F72X\UblComponent\DebitNoteLine. ( Ignorable by Annotation )

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

263
                $DocumentLine->/** @scrutinizer ignore-call */ 
264
                               setCreditedQuantity($quantity);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method setCreditedQuantity() does not exist on F72X\UblComponent\InvoiceLine. ( Ignorable by Annotation )

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

263
                $DocumentLine->/** @scrutinizer ignore-call */ 
264
                               setCreditedQuantity($quantity);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
264
                break;
265
            case 'DebitNoteLine' :
266
                $DocumentLine->setDebitedQuantity($quantity);
0 ignored issues
show
Bug introduced by
The method setDebitedQuantity() does not exist on F72X\UblComponent\CreditNoteLine. ( Ignorable by Annotation )

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

266
                $DocumentLine->/** @scrutinizer ignore-call */ 
267
                               setDebitedQuantity($quantity);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method setDebitedQuantity() does not exist on F72X\UblComponent\InvoiceLine. ( Ignorable by Annotation )

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

266
                $DocumentLine->/** @scrutinizer ignore-call */ 
267
                               setDebitedQuantity($quantity);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
267
                break;
268
        }
269
    }
270
271
    private function addInvoiceLegalMonetaryTotal() {
272
        $Invoice            = $this->dataMap;
273
        $currencyID         = $this->getDocumentCurrencyCode(); // Tipo de moneda
0 ignored issues
show
Bug introduced by
It seems like getDocumentCurrencyCode() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

273
        /** @scrutinizer ignore-call */ 
274
        $currencyID         = $this->getDocumentCurrencyCode(); // Tipo de moneda
Loading history...
274
        $totalAllowances    = $Invoice->getTotalAllowances();   // Total descuentos
275
        $payableAmount      = $Invoice->getPayableAmount();     // Total a pagar
276
        $billableAmount     = $Invoice->getBillableValue();
277
        // LegalMonetaryTotal
278
        $LegalMonetaryTotal = new LegalMonetaryTotal();
279
        $LegalMonetaryTotal
280
                ->setCurrencyID($currencyID)
281
                ->setLineExtensionAmount($billableAmount)
282
                ->setTaxInclusiveAmount($payableAmount)
283
                ->setAllowanceTotalAmount($totalAllowances)
284
                ->setPayableAmount($payableAmount);
285
286
        parent::setLegalMonetaryTotal($LegalMonetaryTotal);
287
    }
288
289
    private function addInvoiceAccountingSupplierParty() {
290
        // Info
291
        $partyName  = Company::getBusinessName();
292
        $regName    = Company::getCompanyName();
293
        $docNumber  = Company::getRUC();
294
        $addressRegCode = Company::getRegAddressCode(); // Código de domicilio fiscal o anexo
295
        $docType    = Catalogo::IDENTIFICATION_DOC_RUC;
296
297
        // XML nodes
298
        $AccountingSupplierParty    = new AccountingSupplierParty();
299
        $Party                      = new Party();
300
        $PartyIdentification        = new PartyIdentification();
301
        $PartyTaxScheme             = new PartyTaxScheme();
302
        $RegistrationAddress        = new RegistrationAddress();
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
                        ->setPartyTaxScheme($PartyTaxScheme
319
                                ->setRegistrationAddress($RegistrationAddress
320
                                        ->setAddressTypeCode($addressRegCode)))
321
                        ->setPartyLegalEntity($PartyLegalEntity
322
                                ->setRegistrationName($regName)));
323
        // Add to Document
324
        parent::setAccountingSupplierParty($AccountingSupplierParty);
325
    }
326
327
    private function addInvoiceAccountingCustomerParty() {
328
        $Invoice   = $this->dataMap;
329
        // Info
330
        $regName   = $Invoice->getCustomerRegName();
331
        $docNumber = $Invoice->getCustomerDocNumber();
332
        $docType   = $Invoice->getCustomerDocType();
333
334
        // XML nodes
335
        $AccountingCustomerParty    = new AccountingCustomerParty();
336
        $Party                      = new Party();
337
        $PartyIdentification        = new PartyIdentification();
338
        $PartyLegalEntity           = new PartyLegalEntity();
339
        $PartyIdentification
340
                ->setElementAttributes('ID', [
341
                    'schemeAgencyName'  => 'PE:SUNAT',
342
                    'schemeID'          => $docType,
343
                    'schemeName'        => 'Documento de Identidad',
344
                    'schemeURI'         => 'urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo06']);
345
346
        $AccountingCustomerParty
347
                ->setParty($Party
348
                        ->setPartyIdentification($PartyIdentification
349
                                ->setID($docNumber))
350
                        ->setPartyLegalEntity($PartyLegalEntity
351
                                ->setRegistrationName($regName)));
352
        // Add to Document
353
        parent::setAccountingCustomerParty($AccountingCustomerParty);
354
    }
355
356
    /**
357
     *    
358
     * @return string Nombre del comprobante de acuerdo con las especificaciones de la SUNAT
359
     */
360
    public function getDocumentName() {
361
        return $this->dataMap->getDocumentName();
362
    }
363
364
}
365