catalogmx 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. catalogmx/__init__.py +56 -0
  2. catalogmx/catalogs/__init__.py +5 -0
  3. catalogmx/catalogs/banxico/__init__.py +24 -0
  4. catalogmx/catalogs/banxico/banks.py +136 -0
  5. catalogmx/catalogs/banxico/codigos_plaza.py +287 -0
  6. catalogmx/catalogs/banxico/instituciones_financieras.py +338 -0
  7. catalogmx/catalogs/banxico/monedas_divisas.py +386 -0
  8. catalogmx/catalogs/banxico/udis.py +279 -0
  9. catalogmx/catalogs/ift/__init__.py +15 -0
  10. catalogmx/catalogs/ift/codigos_lada.py +426 -0
  11. catalogmx/catalogs/ift/operadores_moviles.py +315 -0
  12. catalogmx/catalogs/inegi/__init__.py +21 -0
  13. catalogmx/catalogs/inegi/localidades.py +207 -0
  14. catalogmx/catalogs/inegi/municipios.py +73 -0
  15. catalogmx/catalogs/inegi/municipios_completo.py +236 -0
  16. catalogmx/catalogs/inegi/states.py +148 -0
  17. catalogmx/catalogs/mexico/__init__.py +17 -0
  18. catalogmx/catalogs/mexico/hoy_no_circula.py +215 -0
  19. catalogmx/catalogs/mexico/placas_formatos.py +184 -0
  20. catalogmx/catalogs/mexico/salarios_minimos.py +156 -0
  21. catalogmx/catalogs/mexico/uma.py +207 -0
  22. catalogmx/catalogs/sat/__init__.py +13 -0
  23. catalogmx/catalogs/sat/carta_porte/__init__.py +19 -0
  24. catalogmx/catalogs/sat/carta_porte/aeropuertos.py +76 -0
  25. catalogmx/catalogs/sat/carta_porte/carreteras.py +59 -0
  26. catalogmx/catalogs/sat/carta_porte/config_autotransporte.py +54 -0
  27. catalogmx/catalogs/sat/carta_porte/material_peligroso.py +66 -0
  28. catalogmx/catalogs/sat/carta_porte/puertos_maritimos.py +63 -0
  29. catalogmx/catalogs/sat/carta_porte/tipo_embalaje.py +48 -0
  30. catalogmx/catalogs/sat/carta_porte/tipo_permiso.py +54 -0
  31. catalogmx/catalogs/sat/cfdi_4/__init__.py +42 -0
  32. catalogmx/catalogs/sat/cfdi_4/clave_prod_serv.py +383 -0
  33. catalogmx/catalogs/sat/cfdi_4/clave_unidad.py +298 -0
  34. catalogmx/catalogs/sat/cfdi_4/exportacion.py +45 -0
  35. catalogmx/catalogs/sat/cfdi_4/forma_pago.py +45 -0
  36. catalogmx/catalogs/sat/cfdi_4/impuesto.py +57 -0
  37. catalogmx/catalogs/sat/cfdi_4/meses.py +34 -0
  38. catalogmx/catalogs/sat/cfdi_4/metodo_pago.py +45 -0
  39. catalogmx/catalogs/sat/cfdi_4/objeto_imp.py +45 -0
  40. catalogmx/catalogs/sat/cfdi_4/periodicidad.py +34 -0
  41. catalogmx/catalogs/sat/cfdi_4/regimen_fiscal.py +57 -0
  42. catalogmx/catalogs/sat/cfdi_4/tasa_o_cuota.py +42 -0
  43. catalogmx/catalogs/sat/cfdi_4/tipo_comprobante.py +45 -0
  44. catalogmx/catalogs/sat/cfdi_4/tipo_factor.py +34 -0
  45. catalogmx/catalogs/sat/cfdi_4/tipo_relacion.py +45 -0
  46. catalogmx/catalogs/sat/cfdi_4/uso_cfdi.py +45 -0
  47. catalogmx/catalogs/sat/comercio_exterior/__init__.py +39 -0
  48. catalogmx/catalogs/sat/comercio_exterior/claves_pedimento.py +77 -0
  49. catalogmx/catalogs/sat/comercio_exterior/estados.py +122 -0
  50. catalogmx/catalogs/sat/comercio_exterior/incoterms.py +226 -0
  51. catalogmx/catalogs/sat/comercio_exterior/monedas.py +107 -0
  52. catalogmx/catalogs/sat/comercio_exterior/motivos_traslado.py +54 -0
  53. catalogmx/catalogs/sat/comercio_exterior/paises.py +88 -0
  54. catalogmx/catalogs/sat/comercio_exterior/registro_ident_trib.py +76 -0
  55. catalogmx/catalogs/sat/comercio_exterior/unidades_aduana.py +54 -0
  56. catalogmx/catalogs/sat/comercio_exterior/validator.py +212 -0
  57. catalogmx/catalogs/sat/nomina/__init__.py +19 -0
  58. catalogmx/catalogs/sat/nomina/banco.py +50 -0
  59. catalogmx/catalogs/sat/nomina/periodicidad_pago.py +48 -0
  60. catalogmx/catalogs/sat/nomina/riesgo_puesto.py +56 -0
  61. catalogmx/catalogs/sat/nomina/tipo_contrato.py +47 -0
  62. catalogmx/catalogs/sat/nomina/tipo_jornada.py +42 -0
  63. catalogmx/catalogs/sat/nomina/tipo_nomina.py +52 -0
  64. catalogmx/catalogs/sat/nomina/tipo_regimen.py +47 -0
  65. catalogmx/catalogs/sepomex/__init__.py +5 -0
  66. catalogmx/catalogs/sepomex/codigos_postales.py +184 -0
  67. catalogmx/cli.py +185 -0
  68. catalogmx/helpers.py +324 -0
  69. catalogmx/utils/text.py +55 -0
  70. catalogmx/validators/__init__.py +0 -0
  71. catalogmx/validators/clabe.py +233 -0
  72. catalogmx/validators/curp.py +623 -0
  73. catalogmx/validators/nss.py +255 -0
  74. catalogmx/validators/rfc.py +1004 -0
  75. catalogmx-0.3.0.dist-info/METADATA +644 -0
  76. catalogmx-0.3.0.dist-info/RECORD +81 -0
  77. catalogmx-0.3.0.dist-info/WHEEL +5 -0
  78. catalogmx-0.3.0.dist-info/entry_points.txt +2 -0
  79. catalogmx-0.3.0.dist-info/licenses/AUTHORS.rst +5 -0
  80. catalogmx-0.3.0.dist-info/licenses/LICENSE +19 -0
  81. catalogmx-0.3.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,59 @@
1
+ """Catálogo c_Carreteras - Carreteras Federales"""
2
+
3
+ import json
4
+ from pathlib import Path
5
+
6
+ from catalogmx.utils.text import normalize_text
7
+
8
+
9
+ class CarreterasCatalog:
10
+ _data: list[dict] | None = None
11
+ _by_code: dict[str, dict] | None = None
12
+
13
+ @classmethod
14
+ def _load_data(cls) -> None:
15
+ if cls._data is None:
16
+ path = (
17
+ Path(__file__).parent.parent.parent.parent.parent.parent
18
+ / "shared-data"
19
+ / "sat"
20
+ / "carta_porte_3"
21
+ / "carreteras.json"
22
+ )
23
+ with open(path, encoding="utf-8") as f:
24
+ cls._data = json.load(f)
25
+ cls._by_code = {item["code"]: item for item in cls._data}
26
+
27
+ @classmethod
28
+ def get_carretera(cls, code: str) -> dict | None:
29
+ """Obtiene carretera por código"""
30
+ cls._load_data()
31
+ return cls._by_code.get(code)
32
+
33
+ @classmethod
34
+ def is_valid(cls, code: str) -> bool:
35
+ """Verifica si un código de carretera es válido"""
36
+ return cls.get_carretera(code) is not None
37
+
38
+ @classmethod
39
+ def get_all(cls) -> list[dict]:
40
+ """Obtiene todas las carreteras"""
41
+ cls._load_data()
42
+ return cls._data.copy()
43
+
44
+ @classmethod
45
+ def get_by_type(cls, tipo: str) -> list[dict]:
46
+ """Obtiene carreteras por tipo (Cuota, Libre)"""
47
+ cls._load_data()
48
+ return [c for c in cls._data if c["type"] == tipo]
49
+
50
+ @classmethod
51
+ def search_by_name(cls, name: str) -> list[dict]:
52
+ """Busca carreteras por nombre (insensible a acentos)"""
53
+ cls._load_data()
54
+ name_normalized = normalize_text(name)
55
+ return [
56
+ c
57
+ for c in cls._data
58
+ if name_normalized in normalize_text(c.get("nombre", c.get("name", "")))
59
+ ]
@@ -0,0 +1,54 @@
1
+ """Catálogo c_ConfigAutotransporte - Configuraciones Vehiculares"""
2
+
3
+ import json
4
+ from pathlib import Path
5
+
6
+
7
+ class ConfigAutotransporteCatalog:
8
+ _data: list[dict] | None = None
9
+ _by_code: dict[str, dict] | None = None
10
+
11
+ @classmethod
12
+ def _load_data(cls) -> None:
13
+ if cls._data is None:
14
+ path = (
15
+ Path(__file__).parent.parent.parent.parent.parent.parent
16
+ / "shared-data"
17
+ / "sat"
18
+ / "carta_porte_3"
19
+ / "config_autotransporte.json"
20
+ )
21
+ with open(path, encoding="utf-8") as f:
22
+ data = json.load(f)
23
+ # Handle both list and dict formats
24
+ cls._data = data if isinstance(data, list) else data.get("configuraciones", data)
25
+ cls._by_code = {item["code"]: item for item in cls._data}
26
+
27
+ @classmethod
28
+ def get_config(cls, code: str) -> dict | None:
29
+ """Obtiene configuración por código"""
30
+ cls._load_data()
31
+ return cls._by_code.get(code)
32
+
33
+ @classmethod
34
+ def is_valid(cls, code: str) -> bool:
35
+ """Verifica si un código de configuración es válido"""
36
+ return cls.get_config(code) is not None
37
+
38
+ @classmethod
39
+ def get_all(cls) -> list[dict]:
40
+ """Obtiene todas las configuraciones"""
41
+ cls._load_data()
42
+ return cls._data.copy()
43
+
44
+ @classmethod
45
+ def get_by_type(cls, tipo: str) -> list[dict]:
46
+ """Obtiene configuraciones por tipo (Unitario, Articulado)"""
47
+ cls._load_data()
48
+ return [c for c in cls._data if c["type"] == tipo]
49
+
50
+ @classmethod
51
+ def get_axes_count(cls, code: str) -> int | None:
52
+ """Obtiene el número de ejes de una configuración"""
53
+ config = cls.get_config(code)
54
+ return config.get("axes") if config else None
@@ -0,0 +1,66 @@
1
+ """Catálogo c_MaterialPeligroso - Materiales Peligrosos ONU"""
2
+
3
+ import json
4
+ from pathlib import Path
5
+
6
+
7
+ class MaterialPeligrosoCatalog:
8
+ _data: list[dict] | None = None
9
+ _by_un_number: dict[str, dict] | None = None
10
+
11
+ @classmethod
12
+ def _load_data(cls) -> None:
13
+ if cls._data is None:
14
+ path = (
15
+ Path(__file__).parent.parent.parent.parent.parent.parent
16
+ / "shared-data"
17
+ / "sat"
18
+ / "carta_porte_3"
19
+ / "material_peligroso.json"
20
+ )
21
+ with open(path, encoding="utf-8") as f:
22
+ data = json.load(f)
23
+ # Handle both list and dict formats
24
+ cls._data = data if isinstance(data, list) else data.get("materiales", data)
25
+ # JSON has "code" field, map it as un_number
26
+ cls._by_un_number = {item["code"]: item for item in cls._data}
27
+
28
+ @classmethod
29
+ def get_material(cls, un_number: str) -> dict | None:
30
+ """Obtiene material peligroso por número ONU"""
31
+ cls._load_data()
32
+ return cls._by_un_number.get(un_number)
33
+
34
+ @classmethod
35
+ def is_valid(cls, un_number: str) -> bool:
36
+ """Verifica si un número ONU es válido"""
37
+ return cls.get_material(un_number) is not None
38
+
39
+ @classmethod
40
+ def get_all(cls) -> list[dict]:
41
+ """Obtiene todos los materiales peligrosos"""
42
+ cls._load_data()
43
+ return cls._data.copy()
44
+
45
+ @classmethod
46
+ def get_by_class(cls, hazard_class: str) -> list[dict]:
47
+ """Obtiene materiales por clase de peligro (1-9)"""
48
+ cls._load_data()
49
+ # Handle both "class" and "clase_riesgo" field names
50
+ return [m for m in cls._data if m.get("class", m.get("clase_riesgo", "")).startswith(hazard_class)]
51
+
52
+ @classmethod
53
+ def get_by_packing_group(cls, packing_group: str) -> list[dict]:
54
+ """Obtiene materiales por grupo de embalaje (I, II, III)"""
55
+ cls._load_data()
56
+ return [
57
+ m for m in cls._data if m.get("packing_group") and packing_group in m["packing_group"]
58
+ ]
59
+
60
+ @classmethod
61
+ def requires_special_handling(cls, un_number: str) -> bool:
62
+ """Verifica si requiere manejo especial (grupos I y II)"""
63
+ material = cls.get_material(un_number)
64
+ if not material or not material.get("packing_group"):
65
+ return False
66
+ return "I" in material["packing_group"] or "II" in material["packing_group"]
@@ -0,0 +1,63 @@
1
+ """Catálogo c_NumAutorizacionNaviero - Puertos Marítimos"""
2
+
3
+ import json
4
+ from pathlib import Path
5
+
6
+ from catalogmx.utils.text import normalize_text
7
+
8
+
9
+ class PuertosMaritimos:
10
+ _data: list[dict] | None = None
11
+ _by_code: dict[str, dict] | None = None
12
+
13
+ @classmethod
14
+ def _load_data(cls) -> None:
15
+ if cls._data is None:
16
+ path = (
17
+ Path(__file__).parent.parent.parent.parent.parent.parent
18
+ / "shared-data"
19
+ / "sat"
20
+ / "carta_porte_3"
21
+ / "puertos_maritimos.json"
22
+ )
23
+ with open(path, encoding="utf-8") as f:
24
+ cls._data = json.load(f)
25
+ cls._by_code = {item["code"]: item for item in cls._data}
26
+
27
+ @classmethod
28
+ def get_puerto(cls, code: str) -> dict | None:
29
+ """Obtiene puerto por código"""
30
+ cls._load_data()
31
+ return cls._by_code.get(code)
32
+
33
+ @classmethod
34
+ def is_valid(cls, code: str) -> bool:
35
+ """Verifica si un código de puerto es válido"""
36
+ return cls.get_puerto(code) is not None
37
+
38
+ @classmethod
39
+ def get_all(cls) -> list[dict]:
40
+ """Obtiene todos los puertos"""
41
+ cls._load_data()
42
+ return cls._data.copy()
43
+
44
+ @classmethod
45
+ def get_by_coast(cls, coast: str) -> list[dict]:
46
+ """Obtiene puertos por costa (insensible a acentos)"""
47
+ cls._load_data()
48
+ coast_normalized = normalize_text(coast)
49
+ return [p for p in cls._data if normalize_text(p["coast"]) == coast_normalized]
50
+
51
+ @classmethod
52
+ def get_by_state(cls, state: str) -> list[dict]:
53
+ """Obtiene puertos por estado (insensible a acentos)"""
54
+ cls._load_data()
55
+ state_normalized = normalize_text(state)
56
+ return [p for p in cls._data if normalize_text(p["state"]) == state_normalized]
57
+
58
+ @classmethod
59
+ def search_by_name(cls, name: str) -> list[dict]:
60
+ """Busca puertos por nombre (insensible a acentos)"""
61
+ cls._load_data()
62
+ name_normalized = normalize_text(name)
63
+ return [p for p in cls._data if name_normalized in normalize_text(p["name"])]
@@ -0,0 +1,48 @@
1
+ """Catálogo c_TipoEmbalaje - Tipos de Embalaje"""
2
+
3
+ import json
4
+ from pathlib import Path
5
+
6
+
7
+ class TipoEmbalajeCatalog:
8
+ _data: list[dict] | None = None
9
+ _by_code: dict[str, dict] | None = None
10
+
11
+ @classmethod
12
+ def _load_data(cls) -> None:
13
+ if cls._data is None:
14
+ path = (
15
+ Path(__file__).parent.parent.parent.parent.parent.parent
16
+ / "shared-data"
17
+ / "sat"
18
+ / "carta_porte_3"
19
+ / "tipo_embalaje.json"
20
+ )
21
+ with open(path, encoding="utf-8") as f:
22
+ data = json.load(f)
23
+ # Handle both list and dict formats
24
+ cls._data = data if isinstance(data, list) else data.get("embalajes", data)
25
+ cls._by_code = {item["code"]: item for item in cls._data}
26
+
27
+ @classmethod
28
+ def get_embalaje(cls, code: str) -> dict | None:
29
+ """Obtiene embalaje por código"""
30
+ cls._load_data()
31
+ return cls._by_code.get(code)
32
+
33
+ @classmethod
34
+ def is_valid(cls, code: str) -> bool:
35
+ """Verifica si un código de embalaje es válido"""
36
+ return cls.get_embalaje(code) is not None
37
+
38
+ @classmethod
39
+ def get_all(cls) -> list[dict]:
40
+ """Obtiene todos los embalajes"""
41
+ cls._load_data()
42
+ return cls._data.copy()
43
+
44
+ @classmethod
45
+ def get_by_material(cls, material: str) -> list[dict]:
46
+ """Obtiene embalajes por material (Acero, Plástico, Madera, etc.)"""
47
+ cls._load_data()
48
+ return [e for e in cls._data if e["material"] == material]
@@ -0,0 +1,54 @@
1
+ """Catálogo c_TipoPermiso - Tipos de Permiso"""
2
+
3
+ import json
4
+ from pathlib import Path
5
+
6
+
7
+ class TipoPermisoCatalog:
8
+ _data: list[dict] | None = None
9
+ _by_code: dict[str, dict] | None = None
10
+
11
+ @classmethod
12
+ def _load_data(cls) -> None:
13
+ if cls._data is None:
14
+ path = (
15
+ Path(__file__).parent.parent.parent.parent.parent.parent
16
+ / "shared-data"
17
+ / "sat"
18
+ / "carta_porte_3"
19
+ / "tipo_permiso.json"
20
+ )
21
+ with open(path, encoding="utf-8") as f:
22
+ data = json.load(f)
23
+ # Handle both list and dict formats
24
+ cls._data = data if isinstance(data, list) else data.get("permisos", data)
25
+ cls._by_code = {item["code"]: item for item in cls._data}
26
+
27
+ @classmethod
28
+ def get_permiso(cls, code: str) -> dict | None:
29
+ """Obtiene permiso por código"""
30
+ cls._load_data()
31
+ return cls._by_code.get(code)
32
+
33
+ @classmethod
34
+ def is_valid(cls, code: str) -> bool:
35
+ """Verifica si un código de permiso es válido"""
36
+ return cls.get_permiso(code) is not None
37
+
38
+ @classmethod
39
+ def get_all(cls) -> list[dict]:
40
+ """Obtiene todos los permisos"""
41
+ cls._load_data()
42
+ return cls._data.copy()
43
+
44
+ @classmethod
45
+ def get_by_type(cls, tipo: str) -> list[dict]:
46
+ """Obtiene permisos por tipo (Carga, Pasajeros)"""
47
+ cls._load_data()
48
+ return [p for p in cls._data if p["type"] == tipo]
49
+
50
+ @classmethod
51
+ def is_carga_permit(cls, code: str) -> bool:
52
+ """Verifica si es un permiso de carga"""
53
+ permiso = cls.get_permiso(code)
54
+ return permiso.get("type") == "Carga" if permiso else False
@@ -0,0 +1,42 @@
1
+ """
2
+ Catálogos del SAT para CFDI 4.0
3
+
4
+ Catálogos incluidos:
5
+ - c_RegimenFiscal: Regímenes fiscales
6
+ - c_UsoCFDI: Usos del CFDI
7
+ - c_FormaPago: Formas de pago
8
+ - c_MetodoPago: Método de pago
9
+ - c_TipoComprobante: Tipos de comprobante
10
+ - c_Impuesto: Impuestos
11
+ - c_Exportacion: Claves de exportación
12
+ - c_TipoRelacion: Tipos de relación entre CFDI
13
+ - c_ObjetoImp: Objeto de impuesto
14
+ - c_ClaveUnidad: Claves de unidad de medida (~2,400 unidades)
15
+ - c_ClaveProdServ: Claves de productos y servicios (~52,000 códigos - SQLite)
16
+ """
17
+
18
+ from .clave_prod_serv import ClaveProdServCatalog
19
+ from .clave_unidad import ClaveUnidadCatalog
20
+ from .exportacion import ExportacionCatalog
21
+ from .forma_pago import FormaPagoCatalog
22
+ from .impuesto import ImpuestoCatalog
23
+ from .metodo_pago import MetodoPagoCatalog
24
+ from .objeto_imp import ObjetoImpCatalog
25
+ from .regimen_fiscal import RegimenFiscalCatalog
26
+ from .tipo_comprobante import TipoComprobanteCatalog
27
+ from .tipo_relacion import TipoRelacionCatalog
28
+ from .uso_cfdi import UsoCFDICatalog
29
+
30
+ __all__ = [
31
+ "RegimenFiscalCatalog",
32
+ "UsoCFDICatalog",
33
+ "FormaPagoCatalog",
34
+ "MetodoPagoCatalog",
35
+ "TipoComprobanteCatalog",
36
+ "ImpuestoCatalog",
37
+ "ExportacionCatalog",
38
+ "TipoRelacionCatalog",
39
+ "ObjetoImpCatalog",
40
+ "ClaveUnidadCatalog",
41
+ "ClaveProdServCatalog",
42
+ ]