1
|
1 |
|
import warnings
|
2
|
1 |
|
from datetime import datetime
|
3
|
|
|
|
4
|
1 |
|
import requests
|
5
|
1 |
|
from bs4 import BeautifulSoup, XMLParsedAsHTMLWarning
|
6
|
|
|
|
7
|
1 |
|
from .. import __version__
|
8
|
1 |
|
from ..catalogs import select_all
|
9
|
1 |
|
from ..exceptions import ResponseError
|
10
|
1 |
|
from ..models import Code
|
11
|
1 |
|
from ..sat_requests_utils import SSLAdapter
|
12
|
|
|
|
13
|
1 |
|
warnings.filterwarnings("ignore", category=XMLParsedAsHTMLWarning)
|
14
|
|
|
|
15
|
|
|
|
16
|
1 |
|
def retrieve(rfc: str, id_cif: str):
|
17
|
1 |
|
data = _request_constancia(rfc, id_cif)
|
18
|
1 |
|
return _parse_response(data)
|
19
|
|
|
|
20
|
|
|
|
21
|
1 |
|
def url(rfc: str, id_cif: str):
|
22
|
1 |
|
return f"https://siat.sat.gob.mx/app/qr/faces/pages/mobile/validadorqr.jsf?D1=10&D2=1&D3={id_cif}_{rfc}"
|
23
|
|
|
|
24
|
|
|
|
25
|
1 |
|
def _request_constancia(rfc: str, id_cif: str):
|
26
|
1 |
|
with requests.Session() as s:
|
27
|
1 |
|
s.mount('https://', SSLAdapter())
|
28
|
1 |
|
res = s.get(
|
29
|
|
|
url=url(rfc, id_cif),
|
30
|
|
|
headers={
|
31
|
|
|
"User-Agent": __version__.__user_agent__,
|
32
|
|
|
}
|
33
|
|
|
)
|
34
|
1 |
|
if res.ok:
|
35
|
1 |
|
return res.content
|
36
|
|
|
else:
|
37
|
|
|
raise ResponseError(res)
|
38
|
|
|
|
39
|
|
|
|
40
|
1 |
|
def _find_regimen(regimen):
|
41
|
1 |
|
regimen = regimen.rstrip('.').lower()
|
42
|
1 |
|
for k, v in select_all('C756_c_RegimenFiscal').items():
|
43
|
1 |
|
if regimen.endswith(v.lower()):
|
44
|
1 |
|
return Code(k, v)
|
45
|
1 |
|
return Code(None, regimen)
|
46
|
|
|
|
47
|
|
|
|
48
|
1 |
|
def _parse_response(data):
|
49
|
1 |
|
_REGIMENES = "Regimenes"
|
50
|
1 |
|
html = BeautifulSoup(data, 'html.parser')
|
51
|
1 |
|
gc_v = html.find_all(name="td", attrs={"role": "gridcell", "style": "text-align:left;"})
|
52
|
1 |
|
if not gc_v:
|
53
|
1 |
|
raise ValueError("'rfc' or 'id_cif' is invalid")
|
54
|
1 |
|
gc_k = html.find_all(name="span", attrs={"style": "font-weight: bold;"})
|
55
|
1 |
|
result = {_REGIMENES: []}
|
56
|
|
|
|
57
|
1 |
|
for k, v in zip(gc_k, gc_v):
|
58
|
1 |
|
k = k.text.rstrip(":")
|
59
|
1 |
|
v = v.text
|
60
|
1 |
|
if k.startswith("Fecha ") and v:
|
61
|
1 |
|
v = datetime.strptime(v, "%d-%m-%Y").date()
|
62
|
|
|
|
63
|
1 |
|
if k == 'Régimen':
|
64
|
1 |
|
result[_REGIMENES].append({
|
65
|
|
|
'RegimenFiscal': _find_regimen(v),
|
66
|
|
|
})
|
67
|
1 |
|
elif k == 'Fecha de alta':
|
68
|
1 |
|
result[_REGIMENES][-1][k] = v
|
69
|
|
|
else:
|
70
|
1 |
|
result[k] = v
|
71
|
|
|
|
72
|
|
|
return result
|
73
|
|
|
|