Skip to main content

Read, parse, analyze, and validate CFDI 4.0 XML invoices with pandas.

Project description

cfdi-pandas

cfdi-pandas is a Python library to read CFDI 4.0 XML invoices and work with them as pandas DataFrames for analysis and validation.

Features

  • Read one XML or a full folder of XMLs.
  • Parse CFDI nodes into structured tables.
  • Analyze invoices by RFC, month, and tax regime.
  • Calculate tax totals (VAT, IEPS, withholdings).
  • Validate duplicates, tax consistency, and date ranges.
  • Export nested JSON per invoice (concepts + taxes).

Installation

From PyPI

pip install cfdi-pandas

From this repository (editable mode)

pip install -e .

Docker usage

This repository includes a dockerized setup to run the library, examples, tests, and notebook with the same environment.

Build image

docker build -t cfdi-pandas:local .

Run interactive shell

docker run --rm -it -v "$(pwd)":/app -w /app cfdi-pandas:local

Run repository example (test.py)

This script uses the local example data in cfdis_test (or cfdi_data if present).

docker run --rm -it -v "$(pwd)":/app -w /app cfdi-pandas:local ./scripts/docker_example.sh

Run tests

docker run --rm -it -v "$(pwd)":/app -w /app cfdi-pandas:local ./scripts/docker_tests.sh

Quick start

from pathlib import Path
from cfdi_pandas import read_cfdi_folder, monthly_summary, check_duplicate_uuid

folder = Path("cfdi_data")
data = read_cfdi_folder(folder)

invoices = data["comprobantes"]
print("Invoices:", len(invoices))
print(monthly_summary(invoices))
print(check_duplicate_uuid(invoices))

Data model

read_cfdi(...) and read_cfdi_folder(...) return a CFDIData object (dict-like):

  • data["comprobantes"]: one row per invoice.
  • data["conceptos"]: one row per concept line.
  • data["impuestos"]: one row per tax line.

You can also export nested JSON:

json_invoices = data.to_json()
print(json_invoices[0].keys())

Main API

Reader

  • read_cfdi(path): read one CFDI XML.
  • read_cfdi_folder(folder, recursive=False): read all XML files in a folder.

Analysis

  • group_by_rfc(df, by="emisor" | "receptor")
  • group_by_month(df)
  • group_by_regimen(df)
  • calculate_taxes(df, period=None)
  • monthly_summary(df)
  • top_n(df, by="emisor" | "receptor", n=10)
  • detect_cancelled(df)

Validation

  • check_duplicate_uuid(comprobantes_df)
  • check_tax_math(comprobantes_df, conceptos_df)
  • check_date_range(comprobantes_df, start, end)
  • validate_all(comprobantes_df, conceptos_df, start=None, end=None)

Full example

from pathlib import Path
from cfdi_pandas import (
    read_cfdi_folder,
    group_by_rfc,
    group_by_month,
    group_by_regimen,
    calculate_taxes,
    monthly_summary,
    top_n,
    detect_cancelled,
    check_duplicate_uuid,
    check_tax_math,
    check_date_range,
    validate_all,
)

folder = Path("cfdi_data")
if not folder.exists():
    folder = Path("cfdis_test")

data = read_cfdi_folder(folder)
comprobantes = data["comprobantes"]
conceptos = data["conceptos"]
impuestos = data["impuestos"]

print(group_by_rfc(comprobantes, by="emisor"))
print(group_by_month(comprobantes))
print(group_by_regimen(comprobantes))
print(monthly_summary(comprobantes))
print(top_n(comprobantes, by="receptor", n=10))
print(calculate_taxes(impuestos))
print(calculate_taxes(conceptos))
print(detect_cancelled(comprobantes))
print(check_duplicate_uuid(comprobantes))
print(check_tax_math(comprobantes, conceptos))
print(check_date_range(comprobantes, "2025-01-01", "2025-12-31"))
print(validate_all(comprobantes, conceptos, "2025-01-01", "2025-12-31"))
print(data.to_json()[:1])

Notes

  • This project expects CFDI 4.0 structure.
  • Tax calculations can be run from impuestos or from concept-level taxes in conceptos.
  • Empty DataFrames in validations mean no issues were found for that check.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cfdi_pandas-0.1.0.tar.gz (9.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cfdi_pandas-0.1.0-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

Details for the file cfdi_pandas-0.1.0.tar.gz.

File metadata

  • Download URL: cfdi_pandas-0.1.0.tar.gz
  • Upload date:
  • Size: 9.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for cfdi_pandas-0.1.0.tar.gz
Algorithm Hash digest
SHA256 4dfa47454e40502b49ab1929052892a253b0f1c4260e9ec5359a4c116cc52df7
MD5 1b2ef9043bb73b5f65207c1a45eb5e62
BLAKE2b-256 7fcaf2a654db87edb5b8edb0714072d232a4e27235edf4194f52a2e1836acc34

See more details on using hashes here.

File details

Details for the file cfdi_pandas-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: cfdi_pandas-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for cfdi_pandas-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 11a19c9c8e01802c256ad33c1dc17bacfcfab5096a1b4dbf1ab2b813c47b479b
MD5 2da5e162a707109ccd2eb9bdd6c74f9a
BLAKE2b-256 29902f50d8c770eba6fc4f9950722502a60b25e2c1d1db46529ee2ba9dbcf551

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page