Catalogo   B
last analyzed

Complexity

Total Complexity 47

Size/Duplication

Total Lines 278
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 141
dl 0
loc 278
rs 8.64
c 1
b 0
f 0
wmc 47

15 Methods

Rating   Name   Duplication   Size   Complexity  
A itemExist() 0 4 1
A getUnitName() 0 3 1
A getAllCatNumbers() 0 19 6
A getCatItemFieldValue() 0 10 3
A getDocumentShortCode() 0 13 5
A getCustomList() 0 23 3
A getDocumentSeriesPrefix() 0 18 6
A getCatItemValue() 0 7 2
A getCatItems() 0 11 2
A getOfficialDocumentName() 0 13 5
A getCatItem() 0 9 3
A getCatFileName() 0 3 1
A getDocumentType() 0 13 5
A getCustomListItem() 0 7 2
A getCurrencyPlural() 0 7 2

How to fix   Complexity   

Complex Class

Complex classes like Catalogo often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Catalogo, and based on these observations, apply Extract Interface, too.

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\Sunat;
12
13
use InvalidArgumentException;
14
use F72X\F72X;
15
use F72X\Company;
16
use F72X\Exception\ConfigException;
17
18
class Catalogo
19
{
20
21
    const CAT_TAX_DOCUMENT_TYPE    = 1;
22
    const CAT_CURRENCY_TYPE        = 2;
23
    const CAT_MEASUREMENT_UNIT     = 3;
24
    const CAT_COUNTRY_CODE         = 4;
25
    const CAT_TAX_TYPE             = 5;
26
    const CAT_IDENT_DOCUMENT_TYPE  = 6;
27
    const CAT_IGV_AFFECTATION_TYPE = 7;
28
    const CAT_ISC_CALC_SYSTEM_TYPE = 8;
29
    const CAT_NOTA_CREDITO_TYPE    = 9;
30
    const CAT_NOTA_DEBITO_TYPE     = 10;
31
    const CAT_PERCEPCION_REGIME    = 22;
32
    const CAT_RETENCION_REGIME     = 23;
33
    const CAT_FACTURA_TYPE         = 51;
34
35
    /** @CAT1 Código tipo de documento */
36
    const DOCTYPE_FACTURA = '01';
37
    const DOCTYPE_BOLETA = '03';
38
    const DOCTYPE_NOTA_CREDITO = '07';
39
    const DOCTYPE_NOTA_DEBITO = '08';
40
    const DOCTYPE_VOUCHER = '12';
41
    const DOCTYPE_SC_FACTURA = 'FAC';
42
    const DOCTYPE_SC_BOLETA = 'BOL';
43
    const DOCTYPE_SC_NOTA_CREDITO = 'NCR';
44
    const DOCTYPE_SC_NOTA_DEBITO = 'NDE';
45
46
    /** @CAT5 Tipo de impuesto */
47
    const CAT5_IGV = '1000';
48
    const CAT5_IVAP = '1016';
49
    const CAT5_ISC = '2000';
50
    const CAT5_EXP = '9995';
51
    const CAT5_GRA = '9996';
52
    const CAT5_EXO = '9997';
53
    const CAT5_INA = '9998';
54
    const CAT5_OTROS = '9999';
55
56
    /** @CAT7 Tipo de afectación del IGV */
57
    const CAT7_GRA_IGV = '10';
58
59
    /** @CAT16 Tipo de precio */
60
    const CAT16_UNITARY_PRICE = '01';
61
    const CAT16_REF_VALUE = '02';
62
63
    /** @CAT6 */
64
    const IDENTIFICATION_DOC_DNI = '1';
65
    const IDENTIFICATION_DOC_RUC = '6';
66
67
    // Formas de pago
68
    public static $FAC_FORMS_OF_PAYMENT = ['Contado', 'Credito'];
69
    const FAC_FORM_OF_PAYMENT_CONTADO = 'Contado';
70
    const FAC_FORM_OF_PAYMENT_CREDITO = 'Credito';
71
    private static $_CAT = [];
72
    private static $_LIST = [];
73
    /**
74
     *
75
     * @param string $documentType 01|03|07|08
76
     * @param string $affectedDocumentType 01|03
77
     * @return string F|B
78
     */
79
    public static function getDocumentSeriesPrefix($documentType, $affectedDocumentType = null)
80
    {
81
        if ($documentType == self::DOCTYPE_FACTURA) {
82
            return 'F';
83
        }
84
        if ($documentType == self::DOCTYPE_BOLETA) {
85
            return 'B';
86
        }
87
        if ($documentType == self::DOCTYPE_NOTA_CREDITO) {
88
            return self::getDocumentSeriesPrefix($affectedDocumentType);
89
        }
90
        if ($documentType == self::DOCTYPE_NOTA_DEBITO) {
91
            return self::getDocumentSeriesPrefix($affectedDocumentType);
92
        }
93
        if ($documentType == self::DOCTYPE_VOUCHER) {
94
            throw new InvalidArgumentException("Error: Cash register ticket isn't supported yet.");
95
        }
96
        throw new InvalidArgumentException("Error: $documentType isn't a valid document type");
97
    }
98
99
    /**
100
     *
101
     * @param string $documentType 01|03|07|08
102
     * @return string FACTURA|BOLETA|NOTA DE CRÉDITO|NOTA DE DÉBITO
103
     */
104
    public static function getOfficialDocumentName($documentType)
105
    {
106
        switch ($documentType) {
107
            case self::DOCTYPE_FACTURA:
108
                return 'FACTURA';
109
            case self::DOCTYPE_BOLETA:
110
                return 'BOLETA DE VENTA';
111
            case self::DOCTYPE_NOTA_CREDITO:
112
                return 'NOTA DE CRÉDITO';
113
            case self::DOCTYPE_NOTA_DEBITO:
114
                return 'NOTA DE DÉBITO';
115
        }
116
        throw new InvalidArgumentException("Error: $documentType isn't a valid document type");
117
    }
118
119
    /**
120
     *
121
     * @param string $shortCode BOL|FAC|NCR|NDE
122
     * @return string 01|03|07|08
123
     */
124
    public static function getDocumentType($shortCode)
125
    {
126
        switch ($shortCode) {
127
            case self::DOCTYPE_SC_FACTURA:
128
                return self::DOCTYPE_FACTURA;
129
            case self::DOCTYPE_SC_BOLETA:
130
                return self::DOCTYPE_BOLETA;
131
            case self::DOCTYPE_SC_NOTA_CREDITO:
132
                return self::DOCTYPE_NOTA_CREDITO;
133
            case self::DOCTYPE_SC_NOTA_DEBITO:
134
                return self::DOCTYPE_NOTA_DEBITO;
135
        }
136
        throw new InvalidArgumentException("Error: $shortCode isn't valid short code use (BOL|FAC|NCR|NDE)");
137
    }
138
139
    /**
140
     *
141
     * @param string $docType 01|03|07|08
142
     * @return string BOL|FAC|NCR|NDE
143
     */
144
    public static function getDocumentShortCode($docType)
145
    {
146
        switch ($docType) {
147
            case self::DOCTYPE_FACTURA:
148
                return self::DOCTYPE_SC_FACTURA;
149
            case self::DOCTYPE_BOLETA:
150
                return self::DOCTYPE_SC_BOLETA;
151
            case self::DOCTYPE_NOTA_CREDITO:
152
                return self::DOCTYPE_SC_NOTA_CREDITO;
153
            case self::DOCTYPE_NOTA_DEBITO:
154
                return self::DOCTYPE_SC_NOTA_DEBITO;
155
        }
156
        throw new InvalidArgumentException("Error: $docType isn't valid document type use (01|03|07|08)");
157
    }
158
159
    public static function itemExist($catNumber, $itemID)
160
    {
161
        $items = self::getCatItems($catNumber);
162
        return key_exists($itemID, $items);
163
    }
164
165
    /**
166
     * Valor de item de catálogo
167
     * @param int $catNumber
168
     * @param string $itemID
169
     * @return string
170
     * @throws InvalidArgumentException cuando el item no existe en el catálogo.
171
     */
172
    public static function getCatItemValue($catNumber, $itemID)
173
    {
174
        $item = self::getCatItem($catNumber, $itemID);
175
        if ($item) {
176
            return $item['value'];
177
        }
178
        throw new InvalidArgumentException("Catálogo Error, no existe un item con ID='$itemID' en el cátalogo='$catNumber'");
179
    }
180
181
    /**
182
     * Valor de item de catálogo
183
     * @param int $catNumber
184
     * @param string $itemID
185
     * @return string
186
     * @throws InvalidArgumentException cuando el item no existe en el catálogo.
187
     */
188
    public static function getCatItemFieldValue($catNumber, $itemID, $field)
189
    {
190
        $item = self::getCatItem($catNumber, $itemID);
191
        if ($item) {
192
            if (isset($item[$field])) {
193
                return $item[$field];
194
            }
195
            throw new InvalidArgumentException("Catálogo Error, no existe el campo '$field' en el cátalogo='$catNumber'");
196
        }
197
        throw new InvalidArgumentException("Catálogo Error, no existe un item con ID='$itemID' en el cátalogo='$catNumber'");
198
    }
199
200
    public static function getCatItem($catNumber, $itemID, $key = 'id')
201
    {
202
        $items = self::getCatItems($catNumber);
203
        foreach ($items as $item) {
204
            if ($item[$key] === strval($itemID)) {
205
                return $item;
206
            }
207
        }
208
        return null;
209
    }
210
211
    public static function getCatItems($catNumber, $useXmlFiles = false)
212
    {
213
        // returns from cache
214
        if (isset(self::$_CAT['CAT_' . $catNumber])) {
215
            return self::$_CAT['CAT_' . $catNumber];
216
        }
217
        // Load from file
218
        $fileName = strtoupper(self::getCatFileName($catNumber));
219
        $items = require F72X::getCatalogoSunatDir() . "/$fileName.php";
220
        self::$_CAT['CAT_' . $catNumber] = $items;
221
        return $items;
222
    }
223
224
    private static function getCatFileName($catNumeber)
225
    {
226
        return 'cat_' . str_pad($catNumeber, 2, '0', STR_PAD_LEFT);
227
    }
228
229
    public static function getCurrencyPlural($currencyCode)
230
    {
231
        $currencies = self::getCustomList('currencies');
232
        if (isset($currencies[$currencyCode])) {
233
            return $currencies[$currencyCode];
234
        }
235
        throw new ConfigException("El código de moneda $currencyCode aún no ha sido configurado para su uso.");
236
    }
237
238
    public static function getUnitName($unitCode)
239
    {
240
        return self::getCustomListItem('unitcode', $unitCode);
241
    }
242
243
    public static function getCustomListItem($listName, $itemId)
244
    {
245
        $customList = self::getCustomList($listName);
246
        if (isset($customList[$itemId])) {
247
            return $customList[$itemId];
248
        }
249
        throw new ConfigException("El codigó de item '$itemId' no existe en la lista $listName");
250
    }
251
252
    public static function getCustomList($listName)
253
    {
254
        // returns from cache
255
        if (isset(self::$_LIST['LIST_' . $listName])) {
256
            return self::$_LIST['LIST_' . $listName];
257
        }
258
        // Company customization
259
        $customListsPath = Company::getListsPath();
260
        $fileName = "$customListsPath/$listName.php";
261
        if (file_exists($fileName)) {
262
            $customListsPath = Company::getListsPath();
263
            $list = require $fileName;
264
            // Cache
265
            self::$_CAT['LIST_' . $listName] = $list;
266
            return $list;
267
        }
268
        // Defaults
269
        $defaultListsPath = F72X::getDefaultListsPath();
270
        $fileName2 = "$defaultListsPath/$listName.php";
271
        $list = require $fileName2;
272
        // Cache
273
        self::$_CAT['LIST_' . $listName] = $list;
274
        return $list;
275
    }
276
277
    public static function getAllCatNumbers()
278
    {
279
        $catNumbers = [];
280
        for ($i = 1; $i <= 3; $i++) {
281
            $catNumbers[] = $i;
282
        }
283
        for ($i = 5; $i <= 9; $i++) {
284
            $catNumbers[] = $i;
285
        }
286
        for ($i = 10; $i <= 11; $i++) {
287
            $catNumbers[] = $i;
288
        }
289
        for ($i = 13; $i <= 27; $i++) {
290
            $catNumbers[] = $i;
291
        }
292
        for ($i = 51; $i <= 59; $i++) {
293
            $catNumbers[] = $i;
294
        }
295
        return $catNumbers;
296
    }
297
}
298