Skip to content

About

Archived experiment: fire-protection tender alerts from Spanish public-procurement open data (PLACSP). Stdlib Python, explainable scoring, case study.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

tenderwatch

tests

Spanish public-tender alerts for one niche, fire-protection installers and maintainers (protección contra incendios, PCI), built from the open data of the Plataforma de Contratación del Sector Público (PLACSP).

Status: archived experiment. This started as a side-business idea, was built as a working MVP and tested on real data, and was then dropped after a market check: free official alerts and inexpensive commercial services already cover the need. The case study explains what was built, what the data showed and why it stopped. The code stays as a reference for parsing and scoring Spanish procurement data.

What it does

  1. Ingest the two PLACSP syndication feeds (state platform and aggregated regional platforms): live ATOM pages since the last run, or monthly ZIP archives for backfill. TLS is always verified.
  2. Parse CODICE XML entries into typed Tender records: CPV codes from the project and every lot, budget, NUTS region, submission deadline, documents and status.
  3. Score relevance deterministically, with the reasons recorded: a core fire-protection CPV is high; related CPVs, or fire keywords in a building/installation context, are medium; firefighting-service supplies (vehicles, boots, uniforms) and forest work are excluded.
  4. Store the latest snapshot, status history, run cursors and per-profile deliveries in SQLite.
  5. Digest per profile (CPVs, regions, minimum budget, statuses) as HTML, Markdown or CSV, with sections for new tenders, status changes, tenders closing within 7 days and, optionally, recent awards.

Real output from 2026-10-20 (73,030 tenders ingested): Madrid (Markdown), Madrid (HTML), Andalucía.

Highlights

  • Standard library only (Python 3.12): xml.etree, sqlite3, ssl, urllib, decimal, tomllib.
  • Explainable scoring instead of a plain CPV filter: about as many relevant tenders hide inside generic "mantenimiento integral" contracts as carry the specific CPV. Every match lists its reasons (cpv:, keyword:, context:, penalty:).
  • Real-data fixtures: tests run offline on 21 real feed entries (contact data redacted), including hard cases such as firefighter PPE (CPV 35113xxx), which a naive 4-digit prefix would misclassify.
  • Defensive ingestion: bad entries are logged and skipped, pagination is bounded, and the cursor only advances when the previous run is reached.
  • Data findings about the PLACSP feeds (formats, volumes, pitfalls) are in docs/data-sources.md.

Quickstart

# Backfill a month (the state archive is about 300 MB)
python -m tenderwatch.cli backfill --month 2026-09 --source all --db data/state.sqlite

# Incremental sync of the live feeds
python -m tenderwatch.cli sync --source all --db data/state.sqlite

# Digest for one profile
python -m tenderwatch.cli digest --db data/state.sqlite \
  --profile profiles/example.toml --format html --out out/madrid.html

python -m tenderwatch.cli stats --db data/state.sqlite

Exit codes: 0 success, 1 runtime or I/O failure, 2 usage or profile error.

The PLACSP server certificate chains to the Spanish FNMT root ("AC RAIZ FNMT-RCM SERVIDORES SEGUROS"). Ubuntu trusts it; macOS often does not. Install it or pass it with --ca-file; never disable verification.

Profile example (profiles/example.toml):

name = "PCI Madrid"
cpv_prefixes = []        # empty = use the fire-protection scorer
nuts_prefixes = ["ES30"] # ES30 Madrid, ES61 Andalucía, ES51 Cataluña...
min_budget = 1000
statuses = ["PUB", "EV"]
min_level = "medium"     # high | medium | low
include_awards = true

Development

PYTHONDONTWRITEBYTECODE=1 python -m unittest discover -s tests

Layout: tenderwatch/{models,parse,cpv,scoring,fetch,state,profiles,digest,cli}.py.

Data and license

Code under the MIT license. Tender data comes from the open-data syndication of the Plataforma de Contratación del Sector Público (Spanish Ministry of Finance), reused under Spain's public-sector information reuse rules. Sample digests and fixtures are illustrative extracts; the official notices are authoritative.

About

Archived experiment: fire-protection tender alerts from Spanish public-procurement open data (PLACSP). Stdlib Python, explainable scoring, case study.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages