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\Tools;
|
12
|
|
|
|
13
|
|
|
use F72X\Company;
|
14
|
|
|
use F72X\Sunat\DataMap;
|
15
|
|
|
use F72X\Sunat\Operations;
|
16
|
|
|
use F72X\Sunat\Catalogo;
|
17
|
|
|
use F72X\Sunat\SunatVars;
|
18
|
|
|
|
19
|
|
|
/**
|
20
|
|
|
* Genera archivos de texto para el Facuturador SUNAT
|
21
|
|
|
*/
|
22
|
|
|
class FSInputGenerator {
|
23
|
|
|
|
24
|
|
|
/**
|
25
|
|
|
* Ruta a directorio DATA del Facturador
|
26
|
|
|
*/
|
27
|
|
|
const FS_DATA_DIR = 'F:\SUNAT/SFS_v1.2/sunat_archivos/sfs/DATA';
|
28
|
|
|
|
29
|
|
|
public static function generateFactura(array $data, $companyRUC) {
|
30
|
|
|
$Invoice = new DataMap($data, '01');
|
31
|
|
|
self::generateFSTextInput($Invoice, $companyRUC);
|
32
|
|
|
}
|
33
|
|
|
|
34
|
|
|
public static function generateBoleta(array $data, $companyRUC) {
|
35
|
|
|
$Invoice = new DataMap($data, 'BOLETA');
|
36
|
|
|
self::generateFSTextInput($Invoice, $companyRUC);
|
37
|
|
|
}
|
38
|
|
|
|
39
|
|
|
private static function generateFSTextInput(DataMap $Invoice, $companyRUC) {
|
40
|
|
|
$issueDate = $Invoice->getIssueDate();
|
41
|
|
|
$Items = $Invoice->getItems();
|
42
|
|
|
$json = [
|
43
|
|
|
'cabecera' => [
|
44
|
|
|
'tipOperacion' => $Invoice->getOperationType(),
|
45
|
|
|
'fecEmision' => $issueDate->format('Y-m-d'),
|
46
|
|
|
'horEmision' => $issueDate->format('H:i:s'),
|
47
|
|
|
'fecVencimiento' => '-',
|
48
|
|
|
'codLocalEmisor' => Company::getRegAddressCode(),
|
49
|
|
|
'tipDocUsuario' => $Invoice->getCustomerDocType(),
|
50
|
|
|
'numDocUsuario' => $Invoice->getCustomerDocNumber(),
|
51
|
|
|
'rznSocialUsuario' => $Invoice->getCustomerRegName(),
|
52
|
|
|
'tipMoneda' => $Invoice->getCurrencyCode(),
|
53
|
|
|
|
54
|
|
|
'sumTotTributos' => Operations::formatAmount($Invoice->getTotalTaxes()),
|
55
|
|
|
'sumTotValVenta' => Operations::formatAmount($Invoice->getBillableValue()),
|
56
|
|
|
'sumPrecioVenta' => Operations::formatAmount($Invoice->getPayableAmount()),
|
57
|
|
|
'sumDescTotal' => Operations::formatAmount($Invoice->getTotalAllowances()),
|
58
|
|
|
'sumOtrosCargos' => 0.00,
|
59
|
|
|
'sumTotalAnticipos' => 0.00,
|
60
|
|
|
'sumImpVenta' => Operations::formatAmount($Invoice->getPayableAmount()),
|
61
|
|
|
|
62
|
|
|
'ublVersionId' => '2.1',
|
63
|
|
|
'customizationId' => '2.0'
|
64
|
|
|
],
|
65
|
|
|
'detalle' => [],
|
66
|
|
|
'variablesGlobales' => self::getVariablesGlobales($Invoice)
|
67
|
|
|
];
|
68
|
|
|
$ln = $Items->getCount();
|
69
|
|
|
for ($rowIndex = 0; $rowIndex < $ln; $rowIndex++) {
|
70
|
|
|
$cat5Item = Catalogo::getCatItem(5, $Items->getTaxTypeCode($rowIndex));
|
71
|
|
|
// IGV percent
|
72
|
|
|
if ($cat5Item['id'] === Catalogo::CAT5_IGV) {
|
73
|
|
|
$porIgvItem = Operations::formatAmount(SunatVars::IGV_PERCENT);
|
74
|
|
|
} else {
|
75
|
|
|
$porIgvItem = '0.00';
|
76
|
|
|
}
|
77
|
|
|
if ($Items->getPriceTypeCode($rowIndex) === Catalogo::CAT16_REF_VALUE) {
|
78
|
|
|
$mtoPrecioVentaUnitario = '0.00';
|
79
|
|
|
$mtoValorReferencialUnitario = Operations::formatAmount($Items->getUnitValue($rowIndex));
|
80
|
|
|
} else {
|
81
|
|
|
$mtoPrecioVentaUnitario = Operations::formatAmount($Items->getUnitTaxedValue($rowIndex));
|
82
|
|
|
$mtoValorReferencialUnitario = '0.00';
|
83
|
|
|
}
|
84
|
|
|
$item = [
|
85
|
|
|
'codUnidadMedida' => $Items->getUnitCode($rowIndex),
|
86
|
|
|
'ctdUnidadItem' => $Items->getQunatity($rowIndex),
|
87
|
|
|
'codProducto' => $Items->getProductCode($rowIndex),
|
88
|
|
|
'codProductoSUNAT' => $Items->getUNPSC($rowIndex),
|
89
|
|
|
'desItem' => $Items->getDescription($rowIndex),
|
90
|
|
|
'mtoValorUnitario' => Operations::formatAmount($Items->getUnitBillableValue($rowIndex)),
|
91
|
|
|
'sumTotTributosItem' => Operations::formatAmount($Items->getIgv($rowIndex)),
|
92
|
|
|
'codTriIGV' => $Items->getTaxTypeCode($rowIndex),
|
93
|
|
|
'mtoIgvItem' => Operations::formatAmount($Items->getIgv($rowIndex)),
|
94
|
|
|
'mtoBaseIgvItem' => Operations::formatAmount($Items->getTaxableAmount($rowIndex)),
|
95
|
|
|
'nomTributoIgvItem' => $cat5Item['name'],
|
96
|
|
|
'codTipTributoIgvItem' => $cat5Item['UN_ECE_5153'],
|
97
|
|
|
'tipAfeIGV' => $Items->getIgvAffectationType($rowIndex),
|
98
|
|
|
'porIgvItem' => $porIgvItem,
|
99
|
|
|
'codTriISC' => '-',
|
100
|
|
|
'mtoIscItem' => '0.00',
|
101
|
|
|
'mtoBaseIscItem' => '0.00',
|
102
|
|
|
'nomTributoIscItem' => '0.00',
|
103
|
|
|
'codTipTributoIscItem' => '0.00',
|
104
|
|
|
'tipSisISC' => '0.00',
|
105
|
|
|
'porIscItem' => '0.00',
|
106
|
|
|
'codTriOtroItem' => '-',
|
107
|
|
|
'mtoTriOtroItem' => '0.00',
|
108
|
|
|
'mtoBaseTriOtroItem' => '0.00',
|
109
|
|
|
'nomTributoIOtroItem' => '0.00',
|
110
|
|
|
'codTipTributoIOtroItem' => '0.00',
|
111
|
|
|
'porTriOtroItem' => '0.00',
|
112
|
|
|
'mtoPrecioVentaUnitario' => $mtoPrecioVentaUnitario,
|
113
|
|
|
'mtoValorVentaItem' => Operations::formatAmount($Items->getItemBillableValue($rowIndex)),
|
114
|
|
|
'mtoValorReferencialUnitario' => $mtoValorReferencialUnitario,
|
115
|
|
|
];
|
116
|
|
|
$json['detalle'][] = $item;
|
117
|
|
|
}
|
118
|
|
|
// Line jump
|
119
|
|
|
$ENTER = chr(13) . chr(10);
|
120
|
|
|
$cabContent = implode('|', $json['cabecera']);
|
121
|
|
|
|
122
|
|
|
$detContent = '';
|
123
|
|
|
for ($rowIndex = 0; $rowIndex < $ln; $rowIndex++) {
|
124
|
|
|
$detContent .= implode('|', $json['detalle'][$rowIndex]) . $ENTER;
|
125
|
|
|
}
|
126
|
|
|
$invoiceId = $Invoice->getDocumentId();
|
127
|
|
|
$documentType = $Invoice->getDocumentType();
|
128
|
|
|
self::writeFSFile("$companyRUC-$documentType-$invoiceId.CAB", $cabContent);
|
129
|
|
|
self::writeFSFile("$companyRUC-$documentType-$invoiceId.DET", $detContent);
|
130
|
|
|
//CABECERA VARIABLE
|
131
|
|
|
if (!empty($json['variablesGlobales'])) {
|
132
|
|
|
$glovalVars = $json['variablesGlobales'];
|
133
|
|
|
$varGlobalContent = '';
|
134
|
|
|
foreach ($glovalVars as $row) {
|
135
|
|
|
$varGlobalContent .= implode('|', $row) . $ENTER;
|
136
|
|
|
}
|
137
|
|
|
self::writeFSFile("$companyRUC-$documentType-$invoiceId.ACV", $varGlobalContent);
|
138
|
|
|
}
|
139
|
|
|
}
|
140
|
|
|
|
141
|
|
|
private static function writeFSFile($filename, $content) {
|
142
|
|
|
file_put_contents(self::FS_DATA_DIR . '/' . $filename, $content);
|
143
|
|
|
}
|
144
|
|
|
|
145
|
|
|
private static function getVariablesGlobales(DataMap $Invoice) {
|
146
|
|
|
$data = [];
|
147
|
|
|
$currencyCode = $Invoice->getCurrencyCode();
|
148
|
|
|
$ac = $Invoice->getAllowancesAndCharges();
|
149
|
|
|
$baseAmount = $Invoice->getItems()->getTotalTaxableAmount();
|
150
|
|
|
foreach ($ac as $item) {
|
151
|
|
|
$k = $item['multiplierFactor'];
|
152
|
|
|
$amount = $baseAmount * $k;
|
153
|
|
|
$chargeIndicator = $item['isCharge'] ? 'true' : 'false';
|
154
|
|
|
$item = [
|
155
|
|
|
'tipVariableGlobal' => $chargeIndicator,
|
156
|
|
|
'codTipoVariableGlobal' => $item['reasonCode'],
|
157
|
|
|
'porVariableGlobal' => $k,
|
158
|
|
|
'monMontoVariableGlobal' => $currencyCode,
|
159
|
|
|
'mtoVariableGlobal' => Operations::formatAmount($amount),
|
160
|
|
|
'monBaseImponibleVariableGlobal' => $currencyCode,
|
161
|
|
|
'mtoBaseImpVariableGlobal' => Operations::formatAmount($baseAmount)
|
162
|
|
|
];
|
163
|
|
|
$data[] = $item;
|
164
|
|
|
}
|
165
|
|
|
return $data;
|
166
|
|
|
}
|
167
|
|
|
|
168
|
|
|
}
|
169
|
|
|
|