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