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
|
|
|
|