Skip to content
This repository was archived by the owner on Jul 18, 2026. It is now read-only.
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 32 additions & 7 deletions cuitonline.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,28 @@ def empleador(self) -> Optional[bool]:
return self._details.get("empleador")


def _tipo_persona_desde_cuit(cuit: str) -> str:
"""Infiere el tipo de persona a partir del prefijo del CUIT argentino."""
prefix = cuit.replace("-", "")[:2]
return "jurídica" if prefix in ("30", "33", "34") else "física"


def _parsear_filtros(filtros: Optional[str]) -> list[tuple[str, str]]:
"""Convierte 'personeria:juridica,iva:exento' en lista de (f5[], valor)."""
if not filtros:
return [("f5[]", "persona:fisica")]
return [("f5[]", f.strip()) for f in filtros.split(",")]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve each facet's query parameter

For any non-persona facet, e.g. --filtros iva:iva_exento, CUIT Online's own facet links use a different parameter (f1[] for IVA, with other facets under f0/f2/f4/f6), but this parser always submits every user-provided filter as f5[]. As a result, the advertised IVA/ganancias/monotributo filters are not applied correctly; only tipo-persona filters can work. The parser needs to keep or infer the correct facet key instead of hard-coding f5[] for all filters.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resuelto con el dict _FACETA_A_PARAM que mapea cada faceta a su parámetro correcto (iva→f1[], monotributo→f2[], ganancias→f3[], empleador→f4[], persona→f5[], nacionalidad→f6[]). Los mapeos se verifican con tests unitarios en TestParsearFiltros.



class Busqueda:
"""Consulta paginada de personas en cuitonline.com."""

def __init__(self, criterio: str, pagina_inicial: int = 1):
def __init__(
self, criterio: str, pagina_inicial: int = 1, filtros: Optional[str] = None
):
self.criterio = criterio
self.pagina_actual = pagina_inicial
self.filtros = filtros
self.resultados = self._search(criterio, pagina=pagina_inicial)

def siguiente(self):
Expand All @@ -110,24 +126,25 @@ def siguiente(self):
self.resultados = self._search(self.criterio, self.pagina_actual)

def _search(self, q: str, pagina: int = 1) -> List[Persona]:
params = {"q": q, "f5[]": "persona:fisica", "pn": pagina}
params = [("q", q), ("pn", str(pagina))] + _parsear_filtros(self.filtros)
response = requests.get(f"{base_url}/search.php", params=params)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
resultados = []
for item in soup.select(".hit"):
cuit = item.select_one(".linea-cuit-persona .cuit").get_text(strip=True)
persona = Persona(
nombre=item.select_one(".denominacion h2").get_text(strip=True),
cuit=item.select_one(".linea-cuit-persona .cuit").get_text(strip=True),
tipo_persona="física",
cuit=cuit,
tipo_persona=_tipo_persona_desde_cuit(cuit),
url=f"{base_url}/{item.select_one('.denominacion a')['href']}",
)
resultados.append(persona)
return resultados


def search(q: str, pagina: int = 1) -> List[Persona]:
return Busqueda(q, pagina_inicial=pagina).resultados
def search(q: str, pagina: int = 1, filtros: Optional[str] = None) -> List[Persona]:
return Busqueda(q, pagina_inicial=pagina, filtros=filtros).resultados


def main():
Expand All @@ -142,9 +159,17 @@ def main():
default=1,
help="Número de página a buscar (por defecto: 1)",
)
parser.add_argument(
"-f",
"--filtros",
default=None,
help="Filtros de facetados separados por coma (ej: personeria:juridica,iva:exento)",
)
args = parser.parse_args()

resultados = Busqueda(args.criterio, pagina_inicial=args.pagina)
resultados = Busqueda(
args.criterio, pagina_inicial=args.pagina, filtros=args.filtros
)

print(
json.dumps(
Expand Down
Loading