Test Failed
Push — master ( 1f5d45...b072a0 )
by JAIME ELMER
04:15
created

Catalogo::catItemsToPhpArray()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 33
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 24
nc 6
nop 2
dl 0
loc 33
rs 9.2248
c 0
b 0
f 0
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\Sunat;
12
13
use InvalidArgumentException;
14
use DOMDocument;
15
use F72X\F72X;
16
use F72X\Company;
17
use F72X\Exception\ConfigException;
18
use Sabre\Xml\Reader;
19
20
class Catalogo {
21
22
    const CAT_TAX_DOCUMENT_TYPE    = 1;
23
    const CAT_CURRENCY_TYPE        = 2;
24
    const CAT_MEASUREMENT_UNIT     = 3;
25
    const CAT_COUNTRY_CODE         = 4;
26
    const CAT_TAX_TYPE             = 5;
27
    const CAT_IDENT_DOCUMENT_TYPE  = 6;
28
    const CAT_IGV_AFFECTATION_TYPE = 7;
29
    const CAT_ISC_CALC_SYSTEM_TYPE = 8;
30
    const CAT_NOTA_CREDITO_TYPE    = 9;
31
    const CAT_NOTA_DEBITO_TYPE     = 10;
32
    const CAT_FACTURA_TYPE         = 51;
33
    /** @CAT1 Código tipo de documento */
34
    const DOCTYPE_FACTURA      = '01';
35
    const DOCTYPE_BOLETA       = '03';
36
    const DOCTYPE_NOTA_CREDITO = '07';
37
    const DOCTYPE_NOTA_DEBITO  = '08';
38
    const DOCTYPE_VOUCHER      = '12';
39
    const DOCTYPE_SC_FACTURA      = 'FAC';
40
    const DOCTYPE_SC_BOLETA       = 'BOL';
41
    const DOCTYPE_SC_NOTA_CREDITO = 'NCR';
42
    const DOCTYPE_SC_NOTA_DEBITO  = 'NDE';
43
    /** @CAT5 Tipo de impuesto*/
44
    const CAT5_IGV   = '1000';
45
    const CAT5_IVAP  = '1016';
46
    const CAT5_ISC   = '2000';
47
    const CAT5_EXP   = '9995';
48
    const CAT5_GRA   = '9996';
49
    const CAT5_EXO   = '9997';
50
    const CAT5_INA   = '9998';
51
    const CAT5_OTROS = '9999';
52
53
    /** @CAT7 Tipo de afectación del IGV */
54
    const CAT7_GRA_IGV        = '10';
55
    /** @CAT16 Tipo de precio */
56
    const CAT16_UNITARY_PRICE = '01';
57
    const CAT16_REF_VALUE     = '02';
58
59
    /** @CAT6*/
60
    const IDENTIFICATION_DOC_DNI = '1';
61
    const IDENTIFICATION_DOC_RUC = '6';
62
63
    private static $_CAT = [];
64
    private static $_LIST = [];
65
66
    /**
67
     * 
68
     * @param string $documentType 01|03|07|08
69
     * @param string $affectedDocumentType 01|03
70
     * @return string F|B
71
     */
72
    public static function getDocumentSeriesPrefix($documentType, $affectedDocumentType = null) {
73
        if ($documentType == self::DOCTYPE_FACTURA) {
74
            return 'F';
75
        }
76
        if ($documentType == self::DOCTYPE_BOLETA) {
77
            return 'B';
78
        }
79
        if ($documentType == self::DOCTYPE_NOTA_CREDITO) {
80
            return self::getDocumentSeriesPrefix($affectedDocumentType);
81
        }
82
        if ($documentType == self::DOCTYPE_NOTA_DEBITO) {
83
            return self::getDocumentSeriesPrefix($affectedDocumentType);
84
        }
85
        if ($documentType == self::DOCTYPE_VOUCHER) {
86
            throw new InvalidArgumentException("Error: Cash register ticket isn't supported yet.");
87
        }
88
        throw new InvalidArgumentException("Error: $documentType isn't a valid document type");
89
    }
90
91
    /**
92
     * 
93
     * @param string $documentType 01|03|07|08
94
     * @return string FACTURA|BOLETA|NOTA DE CRÉDITO|NOTA DE DÉBITO
95
     */
96
    public static function getDocumentName($documentType) {
97
        switch ($documentType) {
98
            case self::DOCTYPE_FACTURA      : return 'FACTURA';
99
            case self::DOCTYPE_BOLETA       : return 'BOLETA DE VENTA';
100
            case self::DOCTYPE_NOTA_CREDITO : return 'NOTA DE CRÉDITO';
101
            case self::DOCTYPE_NOTA_DEBITO  : return 'NOTA DE DÉBITO';
102
        }
103
        throw new InvalidArgumentException("Error: $documentType isn't a valid document type");
104
    }
105
106
    /**
107
     * 
108
     * @param string $shortCode BOL|FAC|NCR|NDE
109
     * @return string 01|03|07|08
110
     */
111
    public static function getDocumentType($shortCode) {
112
        switch ($shortCode) {
113
            case self::DOCTYPE_SC_FACTURA:      return self::DOCTYPE_FACTURA ;
114
            case self::DOCTYPE_SC_BOLETA:       return self::DOCTYPE_BOLETA;
115
            case self::DOCTYPE_SC_NOTA_CREDITO: return self::DOCTYPE_NOTA_CREDITO;
116
            case self::DOCTYPE_SC_NOTA_DEBITO:  return self::DOCTYPE_NOTA_DEBITO;
117
        }
118
        throw new InvalidArgumentException("Error: $shortCode isn't valid short code");
119
    }
120
121
    public static function itemExist($catNumber, $itemID) {
122
        $items = self::getCatItems($catNumber);
123
        return key_exists($itemID, $items);
124
    }
125
    
126
    public static function getCatItem($catNumber, $itemID, $key = 'id') {
127
        $items = self::getCatItems($catNumber);
128
        foreach ($items as $item) {
129
            if ($item[$key] === strval($itemID)) {
130
                return $item;
131
            }
132
        }
133
        return null;
134
    }
135
136
    public static function getCatItems($catNumber, $useXmlFiles = false) {
137
        // returns from cache
138
        if (isset(self::$_CAT['CAT_' . $catNumber])) {
139
            return self::$_CAT['CAT_' . $catNumber];
140
        }
141
        // Load from file
142
        $items = $useXmlFiles ? self::getCatItemsFromXmlFile($catNumber) : self::getCatItemsFromPhpFile($catNumber);
143
        self::$_CAT['CAT_' . $catNumber] = $items;
144
        return $items;
145
    }
146
147
    private static function getCatItemsFromXmlFile($catNumber) {
148
        // Load the XML
149
        $xmlName = self::getCatFileName($catNumber);
150
        $doc = new DOMDocument();
151
        $doc->load(SunatVars::DIR_CATS . "/$xmlName.xml");
152
153
        $reader = new Reader();
154
        $reader->xml($doc->saveXML());
155
156
        $catData = $reader->parse();
157
        $items = $catData['value'];
158
        $itemsO = [];
159
        foreach ($items as &$item) {
160
            unset($item['name']); // Here because the item may contain the name attribute!
161
            foreach ($item['attributes'] as $attKey => $att) {
162
                $item[$attKey] = $att;
163
            }
164
            unset($item['attributes']);
165
            $itemsO[$item['id']] = $item;
166
        }
167
        return $itemsO;
168
    }
169
170
    private static function getCatItemsFromPhpFile($catNumber) {
171
        // Load the XML
172
        $fileName = strtoupper(self::getCatFileName($catNumber));
173
        return require SunatVars::DIR_CATS . "/$fileName.php";
174
    }
175
176
    private static function getCatFileName($catNumeber) {
177
        return 'cat_' . str_pad($catNumeber, 2, '0', STR_PAD_LEFT);
178
    }
179
180
    public static function getCurrencyPlural($currencyCode) {
181
        $currencies = self::getCustomList('currencies');
182
        if (isset($currencies[$currencyCode])) {
183
            return $currencies[$currencyCode];
184
        }
185
        throw new ConfigException("El código de moneda $currencyCode aún no ha sido configurado para su uso.");
186
    }
187
188
    public static function getUnitName($unitCode) {
189
        return self::getCustomListItem('unitcode', $unitCode);
190
    }
191
192
    public static function getCustomListItem($listName, $itemId) {
193
        $customList = self::getCustomList($listName);
194
        if(isset($customList[$itemId])){
195
            return $customList[$itemId];
196
        }
197
        throw new ConfigException("El codigó de item $itemId no existe en la lista $listName");
198
    }
199
    public static function getCustomList($listName) {
200
        // returns from cache
201
        if (isset(self::$_LIST['LIST_' . $listName])) {
202
            return self::$_LIST['LIST_' . $listName];
203
        }
204
        // Company customization
205
        $customListsPath = Company::getListsPath();
206
        $fileName = "$customListsPath/$listName.php";
207
        if(file_exists($fileName)){
208
            $customListsPath = Company::getListsPath();
209
            $list = require $fileName;
210
            // Cache
211
            self::$_CAT['LIST_' . $listName] = $list;
212
            return $list;
213
        }
214
        // Defaults
215
        $defaultListsPath = F72X::getDefaultListsPath();
216
        $fileName2 = "$defaultListsPath/$listName.php";
217
        $list = require $fileName2;
218
        // Cache
219
        self::$_CAT['LIST_' . $listName] = $list;
220
        return $list;
221
    }
222
223
    public static function catItemsToPhpArray($catNumber, $resultPath) {
224
        $items = Catalogo::getCatItems($catNumber, true);
225
        $lines = [];
226
        $ENTER = chr(13) . chr(10);
227
        foreach ($items as $item) {
228
            $line = [];
229
            $k = 0;
230
            foreach ($item as $key => $val) {
231
                if (!$k) {
232
                    $id = $item['id'];
233
                    $line[] = "'id' => '$id'";
234
                }
235
                if ($key != 'id') {
236
                    $line[] = "'$key' => '$val'";
237
                }
238
                $k++;
239
            }
240
            $lineS = implode(', ', $line);
241
            $id = $item['id'];
242
            $lines[] = "    '$id' => [$lineS]";
243
        }
244
        $joinedLines = implode(',' . $ENTER, $lines);
245
        $result = <<<FILE
246
<?php
247
248
//Catálogo N° $catNumber:
249
250
return [
251
$joinedLines
252
];
253
254
FILE;
255
        file_put_contents($resultPath, $result);
256
    }
257
258
}
259