-
Notifications
You must be signed in to change notification settings - Fork 0
/
Catalogo.php
335 lines (300 loc) · 10.2 KB
/
Catalogo.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
<?php
/**
* MÓDULO DE EMISIÓN ELECTRÓNICA F72X
* UBL 2.1
* Version 1.1
*
* Copyright 2018, Jaime Cruz
*/
namespace F72X\Sunat;
use InvalidArgumentException;
use DOMDocument;
use F72X\F72X;
use F72X\Company;
use F72X\Exception\ConfigException;
use Sabre\Xml\Reader;
class Catalogo {
const CAT_TAX_DOCUMENT_TYPE = 1;
const CAT_CURRENCY_TYPE = 2;
const CAT_MEASUREMENT_UNIT = 3;
const CAT_COUNTRY_CODE = 4;
const CAT_TAX_TYPE = 5;
const CAT_IDENT_DOCUMENT_TYPE = 6;
const CAT_IGV_AFFECTATION_TYPE = 7;
const CAT_ISC_CALC_SYSTEM_TYPE = 8;
const CAT_NOTA_CREDITO_TYPE = 9;
const CAT_NOTA_DEBITO_TYPE = 10;
const CAT_FACTURA_TYPE = 51;
/** @CAT1 Código tipo de documento */
const DOCTYPE_FACTURA = '01';
const DOCTYPE_BOLETA = '03';
const DOCTYPE_NOTA_CREDITO = '07';
const DOCTYPE_NOTA_DEBITO = '08';
const DOCTYPE_VOUCHER = '12';
const DOCTYPE_SC_FACTURA = 'FAC';
const DOCTYPE_SC_BOLETA = 'BOL';
const DOCTYPE_SC_NOTA_CREDITO = 'NCR';
const DOCTYPE_SC_NOTA_DEBITO = 'NDE';
/** @CAT5 Tipo de impuesto */
const CAT5_IGV = '1000';
const CAT5_IVAP = '1016';
const CAT5_ISC = '2000';
const CAT5_EXP = '9995';
const CAT5_GRA = '9996';
const CAT5_EXO = '9997';
const CAT5_INA = '9998';
const CAT5_OTROS = '9999';
/** @CAT7 Tipo de afectación del IGV */
const CAT7_GRA_IGV = '10';
/** @CAT16 Tipo de precio */
const CAT16_UNITARY_PRICE = '01';
const CAT16_REF_VALUE = '02';
/** @CAT6 */
const IDENTIFICATION_DOC_DNI = '1';
const IDENTIFICATION_DOC_RUC = '6';
private static $_CAT = [];
private static $_LIST = [];
/**
*
* @param string $documentType 01|03|07|08
* @param string $affectedDocumentType 01|03
* @return string F|B
*/
public static function getDocumentSeriesPrefix($documentType, $affectedDocumentType = null) {
if ($documentType == self::DOCTYPE_FACTURA) {
return 'F';
}
if ($documentType == self::DOCTYPE_BOLETA) {
return 'B';
}
if ($documentType == self::DOCTYPE_NOTA_CREDITO) {
return self::getDocumentSeriesPrefix($affectedDocumentType);
}
if ($documentType == self::DOCTYPE_NOTA_DEBITO) {
return self::getDocumentSeriesPrefix($affectedDocumentType);
}
if ($documentType == self::DOCTYPE_VOUCHER) {
throw new InvalidArgumentException("Error: Cash register ticket isn't supported yet.");
}
throw new InvalidArgumentException("Error: $documentType isn't a valid document type");
}
/**
*
* @param string $documentType 01|03|07|08
* @return string FACTURA|BOLETA|NOTA DE CRÉDITO|NOTA DE DÉBITO
*/
public static function getOfficialDocumentName($documentType) {
switch ($documentType) {
case self::DOCTYPE_FACTURA : return 'FACTURA';
case self::DOCTYPE_BOLETA : return 'BOLETA DE VENTA';
case self::DOCTYPE_NOTA_CREDITO : return 'NOTA DE CRÉDITO';
case self::DOCTYPE_NOTA_DEBITO : return 'NOTA DE DÉBITO';
}
throw new InvalidArgumentException("Error: $documentType isn't a valid document type");
}
/**
*
* @param string $shortCode BOL|FAC|NCR|NDE
* @return string 01|03|07|08
*/
public static function getDocumentType($shortCode) {
switch ($shortCode) {
case self::DOCTYPE_SC_FACTURA: return self::DOCTYPE_FACTURA;
case self::DOCTYPE_SC_BOLETA: return self::DOCTYPE_BOLETA;
case self::DOCTYPE_SC_NOTA_CREDITO: return self::DOCTYPE_NOTA_CREDITO;
case self::DOCTYPE_SC_NOTA_DEBITO: return self::DOCTYPE_NOTA_DEBITO;
}
throw new InvalidArgumentException("Error: $shortCode isn't valid short code");
}
public static function itemExist($catNumber, $itemID) {
$items = self::getCatItems($catNumber);
return key_exists($itemID, $items);
}
public static function getCatItem($catNumber, $itemID, $key = 'id') {
$items = self::getCatItems($catNumber);
foreach ($items as $item) {
if ($item[$key] === strval($itemID)) {
return $item;
}
}
return null;
}
public static function getCatItems($catNumber, $useXmlFiles = false) {
// returns from cache
if (isset(self::$_CAT['CAT_' . $catNumber])) {
return self::$_CAT['CAT_' . $catNumber];
}
// Load from file
$items = $useXmlFiles ? self::getCatItemsFromXmlFile($catNumber) : self::getCatItemsFromPhpFile($catNumber);
self::$_CAT['CAT_' . $catNumber] = $items;
return $items;
}
private static function getCatItemsFromXmlFile($catNumber) {
// Load the XML
$xmlName = self::getCatFileName($catNumber);
$doc = new DOMDocument();
$doc->load(SunatVars::DIR_CATS . "/$xmlName.xml");
$reader = new Reader();
$reader->xml($doc->saveXML());
$catData = $reader->parse();
$items = $catData['value'];
$itemsO = [];
foreach ($items as &$item) {
unset($item['name']); // Here because the item may contain the name attribute!
foreach ($item['attributes'] as $attKey => $att) {
$item[$attKey] = $att;
}
unset($item['attributes']);
$itemsO[$item['id']] = $item;
}
return $itemsO;
}
private static function getCatItemsFromPhpFile($catNumber) {
// Load the XML
$fileName = strtoupper(self::getCatFileName($catNumber));
return require SunatVars::DIR_CATS . "/$fileName.php";
}
private static function getCatFileName($catNumeber) {
return 'cat_' . str_pad($catNumeber, 2, '0', STR_PAD_LEFT);
}
public static function getCurrencyPlural($currencyCode) {
$currencies = self::getCustomList('currencies');
if (isset($currencies[$currencyCode])) {
return $currencies[$currencyCode];
}
throw new ConfigException("El código de moneda $currencyCode aún no ha sido configurado para su uso.");
}
public static function getUnitName($unitCode) {
return self::getCustomListItem('unitcode', $unitCode);
}
public static function getCustomListItem($listName, $itemId) {
$customList = self::getCustomList($listName);
if (isset($customList[$itemId])) {
return $customList[$itemId];
}
throw new ConfigException("El codigó de item $itemId no existe en la lista $listName");
}
public static function getCustomList($listName) {
// returns from cache
if (isset(self::$_LIST['LIST_' . $listName])) {
return self::$_LIST['LIST_' . $listName];
}
// Company customization
$customListsPath = Company::getListsPath();
$fileName = "$customListsPath/$listName.php";
if (file_exists($fileName)) {
$customListsPath = Company::getListsPath();
$list = require $fileName;
// Cache
self::$_CAT['LIST_' . $listName] = $list;
return $list;
}
// Defaults
$defaultListsPath = F72X::getDefaultListsPath();
$fileName2 = "$defaultListsPath/$listName.php";
$list = require $fileName2;
// Cache
self::$_CAT['LIST_' . $listName] = $list;
return $list;
}
public static function getAllCatNumbers() {
$catNumbers = [];
for ($i = 1; $i <= 3; $i++) {
$catNumbers[] = $i;
}
for ($i = 5; $i <= 9; $i++) {
$catNumbers[] = $i;
}
for ($i = 10; $i <= 11; $i++) {
$catNumbers[] = $i;
}
for ($i = 13; $i <= 27; $i++) {
$catNumbers[] = $i;
}
for ($i = 51; $i <= 59; $i++) {
$catNumbers[] = $i;
}
return $catNumbers;
}
public static function catItemsToPhpArray($catNumber, $resultPath) {
$items = Catalogo::getCatItems($catNumber, true);
$lines = [];
$ENTER = chr(13) . chr(10);
foreach ($items as $item) {
$line = [];
$k = 0;
foreach ($item as $key => $val) {
if (!$k) {
$id = $item['id'];
$line[] = "'id' => '$id'";
}
if ($key != 'id') {
$val = addslashes($val);
$line[] = "'$key' => '$val'";
}
$k++;
}
$lineS = implode(', ', $line);
$id = $item['id'];
$lines[] = " '$id' => [$lineS]";
}
$joinedLines = implode(',' . $ENTER, $lines);
$result = <<<FILE
<?php
//Catálogo N° $catNumber:
return [
$joinedLines
];
FILE;
file_put_contents($resultPath, $result);
}
public static function catsToJsFile($catNumbers, $resultPath) {
$cats = [];
$ENTER = chr(13) . chr(10);
foreach ($catNumbers as $catNumber) {
$catNumber = str_pad($catNumber, 2, '0', STR_PAD_LEFT);
$cats[] = self::getCatJsItem($catNumber);
}
$joinedCats = implode(',' . $ENTER, $cats);
$result = <<<FILE
({
cats: {
$joinedCats
}
});
FILE;
file_put_contents($resultPath, $result);
}
public static function getCatJsItem($catNumber) {
$items = Catalogo::getCatItems($catNumber, true);
$lines = [];
$ENTER = chr(13) . chr(10);
foreach ($items as $item) {
$line = [];
$k = 0;
foreach ($item as $key => $val) {
if (!$k) {
$id = $item['id'];
$line[] = "id: '$id'";
}
if ($key != 'id') {
$val = addslashes($val);
$line[] = "$key: '$val'";
}
$k++;
}
$lineS = implode(', ', $line);
$id = $item['id'];
$lines[] = " {{$lineS}}";
}
$joinedLines = implode(',' . $ENTER, $lines);
$result = <<<TPL
N$catNumber: {
items: [
$joinedLines
]
}
TPL;
return $result;
}
}