|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/** |
|
4
|
|
|
* FACTURA ELECTRÓNICA SUNAT |
|
5
|
|
|
* UBL 2.1 |
|
6
|
|
|
* Version 1.0 |
|
7
|
|
|
* |
|
8
|
|
|
* Copyright 2018, Jaime Cruz |
|
9
|
|
|
*/ |
|
10
|
|
|
|
|
11
|
|
|
namespace F72X\Sunat; |
|
12
|
|
|
|
|
13
|
|
|
use InvalidArgumentException; |
|
14
|
|
|
use DateTime; |
|
15
|
|
|
|
|
16
|
|
|
use F72X\Tools\XmlService; |
|
17
|
|
|
use F72X\Tools\XmlDSig; |
|
18
|
|
|
use F72X\Tools\FileService; |
|
19
|
|
|
use F72X\Company; |
|
20
|
|
|
use F72X\Sunat\Document\SunatDocument; |
|
21
|
|
|
use F72X\Sunat\Document\Factura; |
|
22
|
|
|
use F72X\Sunat\SunatVars; |
|
23
|
|
|
|
|
24
|
|
|
use F72X\UblComponent\OrderReference; |
|
25
|
|
|
use F72X\UblComponent\Signature; |
|
26
|
|
|
use F72X\UblComponent\SignatoryParty; |
|
27
|
|
|
use F72X\UblComponent\Party; |
|
28
|
|
|
use F72X\UblComponent\PartyIdentification; |
|
29
|
|
|
use F72X\UblComponent\PartyName; |
|
30
|
|
|
use F72X\UblComponent\DigitalSignatureAttachment; |
|
31
|
|
|
use F72X\UblComponent\ExternalReference; |
|
32
|
|
|
use F72X\UblComponent\AccountingSupplierParty; |
|
33
|
|
|
use F72X\UblComponent\AccountingCustomerParty; |
|
34
|
|
|
use F72X\UblComponent\PartyLegalEntity; |
|
35
|
|
|
use F72X\UblComponent\TaxTotal; |
|
36
|
|
|
use F72X\UblComponent\TaxSubTotal; |
|
37
|
|
|
use F72X\UblComponent\TaxCategory; |
|
38
|
|
|
use F72X\UblComponent\TaxScheme; |
|
39
|
|
|
use F72X\UblComponent\LegalMonetaryTotal; |
|
40
|
|
|
use F72X\UblComponent\InvoiceLine; |
|
41
|
|
|
use F72X\UblComponent\AllowanceCharge; |
|
42
|
|
|
use F72X\UblComponent\PricingReference; |
|
43
|
|
|
use F72X\UblComponent\AlternativeConditionPrice; |
|
44
|
|
|
use F72X\UblComponent\Item; |
|
45
|
|
|
use F72X\UblComponent\SellersItemIdentification; |
|
46
|
|
|
use F72X\UblComponent\CommodityClassification; |
|
47
|
|
|
use F72X\UblComponent\Price; |
|
48
|
|
|
|
|
49
|
|
|
class DocumentGenerator { |
|
50
|
|
|
|
|
51
|
|
|
public static function generateFactura($data, $currencyID = 'PEN') { |
|
52
|
|
|
|
|
53
|
|
|
if (!is_array($data)) { |
|
54
|
|
|
throw new InvalidArgumentException('$data, Se esperá un array!'); |
|
55
|
|
|
} |
|
56
|
|
|
|
|
57
|
|
|
// Documento XML para la factura |
|
58
|
|
|
$Document = new Factura(); |
|
59
|
|
|
|
|
60
|
|
|
// Tipo de operación |
|
61
|
|
|
$Document->setProfileID($data['operationTypeCode']); |
|
62
|
|
|
|
|
63
|
|
|
// ID Serie + Numero |
|
64
|
|
|
$ID = 'F' . str_pad($data['voucherSeries'], 3, '0', STR_PAD_LEFT) . '-' . str_pad($data['voucherNumber'], 8, '0', STR_PAD_LEFT); |
|
65
|
|
|
$Document->setID($ID); |
|
66
|
|
|
|
|
67
|
|
|
// Fecha de emisión |
|
68
|
|
|
$IssueDate = isset($data['date']) ? $data['date'] : new DateTime(); |
|
69
|
|
|
$Document->setIssueDate($IssueDate); |
|
70
|
|
|
|
|
71
|
|
|
// Currency code |
|
72
|
|
|
$Document->setDocumentCurrencyCode($currencyID); |
|
73
|
|
|
|
|
74
|
|
|
// LineCountNumeric: Total items |
|
75
|
|
|
$Document->setLineCountNumeric(count($data['items'])); |
|
76
|
|
|
|
|
77
|
|
|
// Reference order |
|
78
|
|
|
$orderRef = new OrderReference(); |
|
79
|
|
|
$orderRef->setID($data['purchaseOrder']); |
|
80
|
|
|
$Document->setOrderReference($orderRef); |
|
81
|
|
|
|
|
82
|
|
|
// AccountingSupplierParty: Company info |
|
83
|
|
|
self::addAccountingSupplierParty($Document); |
|
84
|
|
|
|
|
85
|
|
|
// 11. AccountingCustomerParty: Customer info |
|
86
|
|
|
self::addAccountingCustomerParty($Document, $data); |
|
87
|
|
|
|
|
88
|
|
|
// Detalle |
|
89
|
|
|
self::addInvoiceLines($Document, $data['items']); |
|
90
|
|
|
|
|
91
|
|
|
// Detail opertions matrix |
|
92
|
|
|
$DOM = $Document->getDetailMatrix(); |
|
93
|
|
|
|
|
94
|
|
|
// Descuentos globales |
|
95
|
|
|
if (isset($data['allowances'])) { |
|
96
|
|
|
foreach ($data['allowances'] as $discount) { |
|
97
|
|
|
$baseAmount = $DOM->getTotalTaxableAmount(); |
|
98
|
|
|
$k = $discount['multiplierFactor']; |
|
99
|
|
|
$amount = $baseAmount * $k; |
|
100
|
|
|
self::addAllowanceCharge($Document, $currencyID, 'false', $discount['reasonCode'], $discount['multiplierFactor'], $amount, $baseAmount); |
|
101
|
|
|
} |
|
102
|
|
|
} |
|
103
|
|
|
|
|
104
|
|
|
// Impuestos |
|
105
|
|
|
self::addTaxes($Document); |
|
106
|
|
|
|
|
107
|
|
|
// Totales |
|
108
|
|
|
self::addLegalMonetaryTotal($Document); |
|
109
|
|
|
|
|
110
|
|
|
// Save Document |
|
111
|
|
|
self::saveInvoice($Document); |
|
112
|
|
|
// Sign Document |
|
113
|
|
|
self::singInvoice($Document); |
|
114
|
|
|
// Compress Document |
|
115
|
|
|
self::zipInvoice($Document); |
|
116
|
|
|
} |
|
117
|
|
|
private static function singInvoice(SunatDocument $Document){ |
|
118
|
|
|
$xmlFile = $Document->getFileName(); |
|
119
|
|
|
XmlDSig::sign($xmlFile); |
|
120
|
|
|
} |
|
121
|
|
|
private static function zipInvoice(SunatDocument $Document){ |
|
122
|
|
|
$xmlFile = $Document->getFileName(); |
|
123
|
|
|
FileService::doZip($xmlFile); |
|
124
|
|
|
} |
|
125
|
|
|
private static function addLegalMonetaryTotal(SunatDocument $Invoice) { |
|
126
|
|
|
|
|
127
|
|
|
$DOM = $Invoice->getDetailMatrix(); |
|
128
|
|
|
$currencyID = $Invoice->getDocumentCurrencyCode(); // Tipo de moneda |
|
129
|
|
|
$itemsAllowance = $DOM->getTotalAllowances(); // Total descuentos por item |
|
130
|
|
|
$taxableOperations = $DOM->getTotalTaxableOperations(); // Total operaciones gravadas |
|
131
|
|
|
$exemptedOperations = $DOM->getTotalExcemptedOperations(); // Total operaciones exoneradas |
|
132
|
|
|
|
|
133
|
|
|
// Total descuentos globales |
|
134
|
|
|
$gloabalAllowance = 0; |
|
135
|
|
|
$AllowanceCharges = $Invoice->getAllowanceCharges(); |
|
136
|
|
|
foreach ($AllowanceCharges as $AllowanceCharge) { |
|
137
|
|
|
if ($AllowanceCharge->getChargeIndicator() === 'false') { |
|
138
|
|
|
$gloabalAllowance += $AllowanceCharge->getAmount(); |
|
139
|
|
|
} |
|
140
|
|
|
} |
|
141
|
|
|
// Descuentos totales = Total descuentos globales + Total descuentos por item |
|
142
|
|
|
$totalAllowance = $gloabalAllowance + $itemsAllowance; |
|
143
|
|
|
|
|
144
|
|
|
// Total a pagar = (Operaciones gravadas - descuentos + cargos)*(1+IGV) + (Operaciones exóneradas - descuentos + cargos) |
|
145
|
|
|
$payableAmount = self::applyAllowancesAndCharges($Invoice, $taxableOperations) * (1 + SunatVars::IGV) + self::applyAllowancesAndCharges($Invoice, $exemptedOperations); |
|
146
|
|
|
// LegalMonetaryTotal |
|
147
|
|
|
$LegalMonetaryTotal = new LegalMonetaryTotal(); |
|
148
|
|
|
$LegalMonetaryTotal |
|
149
|
|
|
->setCurrencyID($currencyID) |
|
150
|
|
|
->setLineExtensionAmount($DOM->getTotalPayableValue()) // Valor de la venta |
|
151
|
|
|
->setTaxInclusiveAmount($payableAmount) // Valor de la venta incluido impuestos |
|
152
|
|
|
->setAllowanceTotalAmount($totalAllowance) |
|
153
|
|
|
->setPayableAmount($payableAmount); |
|
154
|
|
|
|
|
155
|
|
|
$Invoice->setLegalMonetaryTotal($LegalMonetaryTotal); |
|
156
|
|
|
} |
|
157
|
|
|
|
|
158
|
|
|
/** |
|
159
|
|
|
* |
|
160
|
|
|
* @param SunatDocument|InvoiceLine $source |
|
161
|
|
|
* @param float $baseAmount |
|
162
|
|
|
* @return float |
|
163
|
|
|
*/ |
|
164
|
|
|
private static function applyAllowancesAndCharges($source, $baseAmount) { |
|
165
|
|
|
$AllowanceCharges = $source->getAllowanceCharges(); |
|
166
|
|
|
$allowance = 0; |
|
167
|
|
|
$charge = 0; |
|
168
|
|
|
foreach ($AllowanceCharges as $AllowanceCharge) { |
|
169
|
|
|
$k = $AllowanceCharge->getMultiplierFactorNumeric(); |
|
170
|
|
|
if ($AllowanceCharge->getChargeIndicator() === 'false') { |
|
171
|
|
|
$allowance += $baseAmount * $k; |
|
172
|
|
|
} else { |
|
173
|
|
|
$charge += $baseAmount * $k; |
|
174
|
|
|
} |
|
175
|
|
|
} |
|
176
|
|
|
return $baseAmount - $allowance + $charge; |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
private static function addInvoiceLines(SunatDocument $Invoice, $items) { |
|
180
|
|
|
$currencyID = $Invoice->getDocumentCurrencyCode(); // Tipo de moneda |
|
181
|
|
|
$DetailMatrix = new DetailMatrix(); // Matriz de calculos |
|
182
|
|
|
$DetailMatrix->populate($items, $currencyID); |
|
183
|
|
|
$Invoice->setDetailMatrix($DetailMatrix); |
|
184
|
|
|
$ln = count($items); |
|
185
|
|
|
// Loop |
|
186
|
|
|
for ($i = 0; $i < $ln; $i++) { |
|
187
|
|
|
self::addInvoiceLine($Invoice, $i); |
|
188
|
|
|
} |
|
189
|
|
|
} |
|
190
|
|
|
|
|
191
|
|
|
/** |
|
192
|
|
|
* |
|
193
|
|
|
* @param SunatDocument $Invoice |
|
194
|
|
|
* @param int $itemIndex Index del item |
|
195
|
|
|
*/ |
|
196
|
|
|
private static function addInvoiceLine(SunatDocument $Invoice, $itemIndex) { |
|
197
|
|
|
|
|
198
|
|
|
// XML Nodes |
|
199
|
|
|
$InvoiceLine = new InvoiceLine(); |
|
200
|
|
|
$PricingReference = new PricingReference(); |
|
201
|
|
|
$TaxTotal = new TaxTotal(); |
|
202
|
|
|
$TaxSubTotal = new TaxSubTotal(); |
|
203
|
|
|
$TaxCategory = new TaxCategory(); |
|
204
|
|
|
$TaxCategory |
|
205
|
|
|
->setElementAttributes('ID', [ |
|
206
|
|
|
'schemeID' => 'UN/ECE 5305', |
|
207
|
|
|
'schemeName' => 'Tax Category Identifier', |
|
208
|
|
|
'schemeAgencyName' => 'United Nations Economic Commission for Europe']) |
|
209
|
|
|
->setElementAttributes('TaxExemptionReasonCode', [ |
|
210
|
|
|
'listAgencyName' => 'PE:SUNAT', |
|
211
|
|
|
'listName' => 'SUNAT:Codigo de Tipo de Afectación del IGV', |
|
212
|
|
|
'listURI' => 'urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo07']); |
|
213
|
|
|
|
|
214
|
|
|
$TaxScheme = new TaxScheme(); |
|
215
|
|
|
$TaxScheme |
|
216
|
|
|
->setElementAttributes('ID', [ |
|
217
|
|
|
'schemeID' => 'UN/ECE 5153', |
|
218
|
|
|
'schemeName' => 'Tax Scheme Identifier', |
|
219
|
|
|
'schemeAgencyName' => 'United Nations Economic Commission for Europe']); |
|
220
|
|
|
|
|
221
|
|
|
$AlternativeConditionPrice = new AlternativeConditionPrice(); |
|
222
|
|
|
$Item = new Item(); |
|
223
|
|
|
$SellersItemIdentification = new SellersItemIdentification(); |
|
224
|
|
|
$CommodityClassification = new CommodityClassification(); |
|
225
|
|
|
$Price = new Price(); |
|
226
|
|
|
// Detail Operation Matrix |
|
227
|
|
|
$DOM = $Invoice->getDetailMatrix(); |
|
228
|
|
|
// Vars |
|
229
|
|
|
$productCode = $DOM->getProductCode($itemIndex); |
|
230
|
|
|
$sunatProductCode = $DOM->getUNPSC($itemIndex); |
|
231
|
|
|
$unitCode = $DOM->getUnitCode($itemIndex); |
|
232
|
|
|
$quantity = $DOM->getQunatity($itemIndex); |
|
233
|
|
|
$description = $DOM->getDescription($itemIndex); |
|
234
|
|
|
$currencyID = $DOM->getCurrencyCode($itemIndex); |
|
235
|
|
|
$unitBillableValue = $DOM->getUnitBillableValue($itemIndex); |
|
236
|
|
|
$priceTypeCode = $DOM->getPriceTypeCode($itemIndex); |
|
237
|
|
|
$taxTypeCode = $DOM->getTaxTypeCode($itemIndex); |
|
238
|
|
|
$igvAffectationCode = $DOM->getIgvAffectationCode($itemIndex); |
|
239
|
|
|
|
|
240
|
|
|
$itemValue = $DOM->getItemValue($itemIndex); |
|
241
|
|
|
$allowances = $DOM->getAllowances($itemIndex); |
|
242
|
|
|
$charges = $DOM->getCharges($itemIndex); |
|
243
|
|
|
$itemTaxableAmount = $DOM->getTaxableAmount($itemIndex); |
|
244
|
|
|
$itemTaxAmount = $DOM->getIgv($itemIndex); |
|
245
|
|
|
$unitPrice = $DOM->getUnitPayableAmount($itemIndex); |
|
246
|
|
|
|
|
247
|
|
|
// Catálogo 5 Ipuesto aplicable |
|
248
|
|
|
$cat5Item = Catalogo::getCatItem(5, $taxTypeCode); |
|
249
|
|
|
|
|
250
|
|
|
// Descuentos/Cargos |
|
251
|
|
|
// Descuentos |
|
252
|
|
|
foreach ($allowances as $item) { |
|
253
|
|
|
$multFactor = $item['multiplierFactor']; |
|
254
|
|
|
$amount = $itemValue * $multFactor; |
|
255
|
|
|
self::addAllowanceCharge($InvoiceLine, $currencyID, 'false', $item['reasonCode'], $multFactor, $amount, $itemValue); |
|
256
|
|
|
} |
|
257
|
|
|
// Cargos |
|
258
|
|
|
foreach ($charges as $item) { |
|
259
|
|
|
$multFactor = $item['multiplierFactor']; |
|
260
|
|
|
$amount = $itemValue * $multFactor; |
|
261
|
|
|
self::addAllowanceCharge($InvoiceLine, $currencyID, 'true', $item['reasonCode'], $multFactor, $amount, $itemValue); |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
|
|
$InvoiceLine |
|
265
|
|
|
->setCurrencyID($currencyID) // Tipo de moneda |
|
266
|
|
|
->setID($itemIndex + 1) // Número de orden |
|
267
|
|
|
->setUnitCode($unitCode) // Codigo de unidad de medida |
|
268
|
|
|
->setInvoicedQuantity($quantity) // Cantidad |
|
269
|
|
|
->setLineExtensionAmount($itemTaxableAmount) // Valor de venta del ítem, sin impuestos |
|
270
|
|
|
->setPricingReference($PricingReference |
|
271
|
|
|
->setAlternativeConditionPrice($AlternativeConditionPrice |
|
272
|
|
|
->setCurrencyID($currencyID) // Tipo de moneda |
|
273
|
|
|
->setPriceAmount($unitPrice) // Precio de venta unitario |
|
274
|
|
|
->setPriceTypeCode($priceTypeCode))) // Price |
|
275
|
|
|
->setTaxTotal($TaxTotal |
|
276
|
|
|
->setCurrencyID($currencyID) |
|
277
|
|
|
->setTaxAmount($itemTaxAmount) |
|
278
|
|
|
->addTaxSubTotal($TaxSubTotal |
|
279
|
|
|
->setCurrencyID($currencyID) // Tipo de moneda |
|
280
|
|
|
->setTaxableAmount($itemTaxableAmount) // Valor de venta del item sin impuestos |
|
281
|
|
|
->setTaxAmount($itemTaxAmount) // IGV |
|
282
|
|
|
->setTaxCategory($TaxCategory |
|
283
|
|
|
->setID($cat5Item['categoria']) // Codigo de categoria de immpuestos @CAT5 |
|
284
|
|
|
->setPercent(SunatVars::IGV_PERCENT) // Porcentaje de IGV (18.00) |
|
285
|
|
|
->setTaxExemptionReasonCode($igvAffectationCode) // Código de afectación del IGV |
|
286
|
|
|
->setTaxScheme($TaxScheme |
|
287
|
|
|
->setID($taxTypeCode) // Codigo de categoria de impuesto |
|
288
|
|
|
->setName($cat5Item['name']) |
|
289
|
|
|
->setTaxTypeCode($cat5Item['UN_ECE_5153']))))) |
|
290
|
|
|
->setItem($Item |
|
291
|
|
|
->setDescription($description) // Descripción |
|
292
|
|
|
->setSellersItemIdentification($SellersItemIdentification |
|
293
|
|
|
->setID($productCode)) // Código de producto |
|
294
|
|
|
->setCommodityClassification($CommodityClassification |
|
295
|
|
|
->setItemClassificationCode($sunatProductCode))) // Código de producto SUNAT |
|
296
|
|
|
->setPrice($Price |
|
297
|
|
|
->setCurrencyID($currencyID) // Tipo de moneda |
|
298
|
|
|
->setPriceAmount($unitBillableValue) // Precio unitario del item |
|
299
|
|
|
); |
|
300
|
|
|
// Añade item |
|
301
|
|
|
$Invoice->addInvoiceLine($InvoiceLine); |
|
302
|
|
|
} |
|
303
|
|
|
|
|
304
|
|
|
/** |
|
305
|
|
|
* |
|
306
|
|
|
* @param SunatDocument|InvoiceLine $target |
|
307
|
|
|
* @param string $currencyID |
|
308
|
|
|
* @param string $ChargeIndicator |
|
309
|
|
|
* @param string $AllowanceChargeReasonCode |
|
310
|
|
|
* @param float $Amount |
|
311
|
|
|
* @param float $BaseAmount |
|
312
|
|
|
*/ |
|
313
|
|
|
private static function addAllowanceCharge($target, $currencyID, $ChargeIndicator, $AllowanceChargeReasonCode, $MultiplierFactorNumeric, $Amount, $BaseAmount) { |
|
314
|
|
|
$AllowanceCharge = new AllowanceCharge(); |
|
315
|
|
|
$AllowanceCharge |
|
316
|
|
|
->setCurrencyID($currencyID) |
|
317
|
|
|
->setChargeIndicator($ChargeIndicator) |
|
318
|
|
|
->setAllowanceChargeReasonCode($AllowanceChargeReasonCode) |
|
319
|
|
|
->setMultiplierFactorNumeric($MultiplierFactorNumeric) |
|
320
|
|
|
->setAmount($Amount) |
|
321
|
|
|
->setBaseAmount($BaseAmount); |
|
322
|
|
|
// Add AllowanceCharge |
|
323
|
|
|
$target |
|
324
|
|
|
->addAllowanceCharge($AllowanceCharge); |
|
325
|
|
|
} |
|
326
|
|
|
|
|
327
|
|
|
private static function addTaxes(SunatDocument $Invoice) { |
|
328
|
|
|
$DOM = $Invoice->getDetailMatrix(); |
|
329
|
|
|
$currencyID = $Invoice->getDocumentCurrencyCode(); // Tipo de moneda |
|
330
|
|
|
$taxableOperations = $DOM->getTotalTaxableOperations(); // Total operaciones gravadas |
|
331
|
|
|
$exemptedOperations = $DOM->getTotalExcemptedOperations(); // Total operaciones exoneradas |
|
332
|
|
|
$unaffectedOperations = $DOM->getTotalUnaffectedOperations(); // Total operaciones inafectas |
|
333
|
|
|
|
|
334
|
|
|
// XML nodes |
|
335
|
|
|
$TaxTotal = new TaxTotal(); |
|
336
|
|
|
|
|
337
|
|
|
|
|
338
|
|
|
// Operaciones gravadas - aplicando cargos y descuetos |
|
339
|
|
|
$igvBaseAmount = self::applyAllowancesAndCharges($Invoice, $taxableOperations); |
|
340
|
|
|
$taxAmount = $igvBaseAmount * SunatVars::IGV; |
|
341
|
|
|
self::addTaxSubtotal($TaxTotal, $currencyID, $taxAmount, $igvBaseAmount, DetailMatrix::TAX_IGV); |
|
342
|
|
|
|
|
343
|
|
|
// Total operaciones exoneradas - aplicando cargos y descuetos |
|
344
|
|
|
$exoBaseAmount = self::applyAllowancesAndCharges($Invoice, $exemptedOperations); |
|
345
|
|
|
self::addTaxSubtotal($TaxTotal, $currencyID, 0, $exoBaseAmount, DetailMatrix::TAX_EXO); |
|
346
|
|
|
|
|
347
|
|
|
// Total operaciones inafectas |
|
348
|
|
|
self::addTaxSubtotal($TaxTotal, $currencyID, 0, $unaffectedOperations, DetailMatrix::TAX_INA); |
|
349
|
|
|
|
|
350
|
|
|
// Total impuestos |
|
351
|
|
|
$TaxTotal |
|
352
|
|
|
->setCurrencyID($currencyID) |
|
353
|
|
|
->setTaxAmount($taxAmount); |
|
354
|
|
|
// Anadir al documento |
|
355
|
|
|
$Invoice->setTaxTotal($TaxTotal); |
|
356
|
|
|
} |
|
357
|
|
|
|
|
358
|
|
|
private static function addTaxSubtotal(TaxTotal $TaxTotal, $currencyID, $taxAmount, $taxableAmount, $taxTypeCode) { |
|
359
|
|
|
// XML nodes |
|
360
|
|
|
$TaxSubTotal = new TaxSubTotal(); |
|
361
|
|
|
$TaxCategory = new TaxCategory(); |
|
362
|
|
|
$TaxCategory->setElementAttributes('ID', [ |
|
363
|
|
|
'schemeID' => 'UN/ECE 5305', |
|
364
|
|
|
'schemeName' => 'Tax Category Identifier', |
|
365
|
|
|
'schemeAgencyName' => 'United Nations Economic Commission for Europe' |
|
366
|
|
|
]); |
|
367
|
|
|
$TaxScheme = new TaxScheme(); |
|
368
|
|
|
$TaxScheme->setElementAttributes('ID', [ |
|
369
|
|
|
'schemeID' => 'UN/ECE 5153', |
|
370
|
|
|
'schemeAgencyID' => '6']); |
|
371
|
|
|
|
|
372
|
|
|
$cat5Item = Catalogo::getCatItem(5, $taxTypeCode); |
|
373
|
|
|
|
|
374
|
|
|
$TaxSubTotal |
|
375
|
|
|
->setCurrencyID($currencyID) |
|
376
|
|
|
->setTaxAmount($taxAmount) |
|
377
|
|
|
->setTaxableAmount($taxableAmount) |
|
378
|
|
|
->setTaxCategory($TaxCategory |
|
379
|
|
|
->setID($cat5Item['categoria']) |
|
380
|
|
|
->setTaxScheme($TaxScheme |
|
381
|
|
|
->setID($taxTypeCode) |
|
382
|
|
|
->setName($cat5Item['name']) |
|
383
|
|
|
->setTaxTypeCode($cat5Item['UN_ECE_5153']))); |
|
384
|
|
|
$TaxTotal->addTaxSubTotal($TaxSubTotal); |
|
385
|
|
|
} |
|
386
|
|
|
|
|
387
|
|
|
public static function addAccountingSupplierParty(SunatDocument $Document) { |
|
388
|
|
|
// Info |
|
389
|
|
|
$partyName = Company::getBusinessName(); |
|
390
|
|
|
$regName = Company::getCompanyName(); |
|
391
|
|
|
$docNumber = Company::getRUC(); |
|
392
|
|
|
$docType = Catalogo::IDENTIFICATION_DOC_RUC; |
|
393
|
|
|
|
|
394
|
|
|
// XML nodes |
|
395
|
|
|
$AccountingSupplierParty = new AccountingSupplierParty(); |
|
396
|
|
|
$Party = new Party(); |
|
397
|
|
|
$PartyIdentification = new PartyIdentification(); |
|
398
|
|
|
$PartyIdentification |
|
399
|
|
|
->setElementAttributes('ID', [ |
|
400
|
|
|
'schemeAgencyName' => 'PE:SUNAT', |
|
401
|
|
|
'schemeID' => $docType, |
|
402
|
|
|
'schemeName' => 'Documento de Identidad', |
|
403
|
|
|
'schemeURI' => 'urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo06']); |
|
404
|
|
|
$PartyName = new PartyName(); |
|
405
|
|
|
$PartyLegalEntity = new PartyLegalEntity(); |
|
406
|
|
|
|
|
407
|
|
|
$AccountingSupplierParty |
|
408
|
|
|
->setParty($Party |
|
409
|
|
|
->setPartyIdentification($PartyIdentification |
|
410
|
|
|
->setID($docNumber)) |
|
411
|
|
|
->setPartyName($PartyName |
|
412
|
|
|
->setName($partyName)) |
|
413
|
|
|
->setPartyLegalEntity($PartyLegalEntity |
|
414
|
|
|
->setRegistrationName($regName))); |
|
415
|
|
|
// Add to Document |
|
416
|
|
|
$Document->setAccountingSupplierParty($AccountingSupplierParty); |
|
417
|
|
|
} |
|
418
|
|
|
|
|
419
|
|
|
public static function addAccountingCustomerParty(SunatDocument $Document, $data) { |
|
420
|
|
|
// Info |
|
421
|
|
|
$regName = $data['customerName']; |
|
422
|
|
|
$docNumber = $data['customerDocNumber']; |
|
423
|
|
|
$docType = $data['customerDocType']; |
|
424
|
|
|
// $taxSchemeID = '-'; |
|
425
|
|
|
|
|
426
|
|
|
// XML nodes |
|
427
|
|
|
$AccountingCustomerParty = new AccountingCustomerParty(); |
|
428
|
|
|
$Party = new Party(); |
|
429
|
|
|
$PartyIdentification = new PartyIdentification(); |
|
430
|
|
|
$PartyLegalEntity = new PartyLegalEntity(); |
|
431
|
|
|
$PartyIdentification |
|
432
|
|
|
->setElementAttributes('ID', [ |
|
433
|
|
|
'schemeAgencyName' => 'PE:SUNAT', |
|
434
|
|
|
'schemeID' => $docType, |
|
435
|
|
|
'schemeName' => 'Documento de Identidad', |
|
436
|
|
|
'schemeURI' => 'urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo06']); |
|
437
|
|
|
|
|
438
|
|
|
$AccountingCustomerParty |
|
439
|
|
|
->setParty($Party |
|
440
|
|
|
->setPartyIdentification($PartyIdentification |
|
441
|
|
|
->setID($docNumber)) |
|
442
|
|
|
->setPartyLegalEntity($PartyLegalEntity |
|
443
|
|
|
->setRegistrationName($regName))); |
|
444
|
|
|
// Add to Document |
|
445
|
|
|
$Document->setAccountingCustomerParty($AccountingCustomerParty); |
|
446
|
|
|
} |
|
447
|
|
|
|
|
448
|
|
|
public static function saveInvoice(SunatDocument $invoice) { |
|
449
|
|
|
$repository = Company::getRepositoryPath(); |
|
450
|
|
|
$xmlService = new XmlService('1.0', 'ISO-8859-1'); |
|
451
|
|
|
|
|
452
|
|
|
$xmlService->namespaceMap = [ |
|
453
|
|
|
"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" => '', |
|
454
|
|
|
"urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" => 'cac', |
|
455
|
|
|
"urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" => 'cbc', |
|
456
|
|
|
"urn:un:unece:uncefact:documentation:2" => 'ccts', |
|
457
|
|
|
"http://www.w3.org/2000/09/xmldsig#" => 'ds', |
|
458
|
|
|
"urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" => 'ext', |
|
459
|
|
|
"urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2" => 'qdt', |
|
460
|
|
|
"urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2" => 'udt', |
|
461
|
|
|
"http://www.w3.org/2001/XMLSchema-instance" => 'xsi' |
|
462
|
|
|
]; |
|
463
|
|
|
$fileName = $invoice->getFileName(); |
|
464
|
|
|
file_put_contents("$repository/xml/$fileName", $xmlService->write('Invoice', $invoice)); |
|
465
|
|
|
} |
|
466
|
|
|
|
|
467
|
|
|
} |
|
468
|
|
|
|