Deeman
8f2ffd432b
fix(admin): correct docker volume mount + pipeline_routes repo root
...
CI / test (push) Successful in 50s
CI / tag (push) Successful in 2s
- docker-compose.prod.yml: fix volume mount for all 6 web containers
from /opt/padelnomics/data (stale) → /data/padelnomics (live supervisor output);
add LANDING_DIR=/app/data/pipeline/landing so extraction/landing stats work
- pipeline_routes.py: fix _REPO_ROOT parents[5] → parents[4] so workflows.toml
is found in dev and pipeline overview shows workflow schedules
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-03-01 11:41:29 +01:00
Deeman
ec839478c3
feat(affiliate): add program + URL assembly tests; update CHANGELOG + PROJECT.md
...
41 tests total (+15). New coverage: get_all_programs(), get_program(),
get_program_by_slug(), build_affiliate_url() (program path, legacy fallback,
no program_id, no program dict), program-based redirect, legacy redirect,
migration seed assertion, ASIN backfill assertion. All ruff checks pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-28 22:51:26 +01:00
Deeman
5c22ea9780
feat(affiliate): tests, ruff cleanup, CHANGELOG + PROJECT.md (commit 9/9)
...
- 26 tests in web/tests/test_affiliate.py covering hash_ip determinism,
daily rotation, product CRUD, bake_product_cards marker replacement,
click redirect (302 + logged), inactive/unknown 404, multi-retailer
- ruff: fix E741 ambiguous var (l → line in _form_to_product), F401 unused
import, I001 import sort in admin/routes.py
- CHANGELOG: affiliate product system entry
- PROJECT.md: affiliate system moved to Done, Wirecutter backlog item removed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-28 21:06:01 +01:00
Deeman
adf22924f6
feat(extract): three-tier proxy system with Webshare auto-fetch
...
Replace two-tier proxy setup (PROXY_URLS / PROXY_URLS_FALLBACK) with
N-tier escalation: free → datacenter → residential.
- proxy.py: fetch_webshare_proxies() auto-fetches the Webshare download
API on each run (no more stale manually-copied lists). load_proxy_tiers()
assembles tiers from WEBSHARE_DOWNLOAD_URL, PROXY_URLS_DATACENTER,
PROXY_URLS_RESIDENTIAL. make_tiered_cycler() generalised to list[list[str]]
with N-level escalation; is_fallback_active() replaced by is_exhausted().
Old load_proxy_urls() / load_fallback_proxy_urls() deleted.
- playtomic_availability.py: both extract() and extract_recheck() use
load_proxy_tiers() + generalised cycler. _fetch_venues_parallel fallback_urls
param removed. All is_fallback_active() checks → is_exhausted().
- playtomic_tenants.py: flattens tiers for simple round-robin.
- test_supervisor.py: TestLoadProxyUrls removed (function deleted).
Added TestFetchWebshareProxies, TestLoadProxyTiers, TestTieredCyclerNTier
(11 tests covering parse format, error handling, escalation, thread safety).
47 tests pass, ruff clean.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-28 16:57:07 +01:00
Deeman
120f974970
merge: Phase 2a + 2b — EU NUTS-2 spatial join + US state income
...
Phase 2a: NUTS-1 regional income for Germany (16 Bundesländer via admin1→NUTS-1 mapping)
Phase 2b: EU-wide NUTS-2 via GISCO spatial join + US Census ACS state income
- All EU-27+EFTA+UK locations now auto-resolve to NUTS-2 via ST_Contains
- Germany gets sub-Bundesland (38 Regierungsbezirke) differentiation
- US gets state-level income with PPS normalisation
- Income cascade: NUTS-2 → NUTS-1 → US state → country-level
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-27 11:11:36 +01:00
Deeman
c3531bd75d
feat(data): Phase 2b complete — EU NUTS-2 spatial join + US state income
...
- stg_regional_income: expanded NUTS-1+2 (LENGTH IN 3,4), nuts_code rename, nuts_level
- stg_nuts2_boundaries: new — ST_Read GISCO GeoJSON, bbox columns for spatial pre-filter
- stg_income_usa: new — Census ACS state-level income staging model
- dim_locations: spatial join replaces admin1_to_nuts1 VALUES CTE; us_income CTE with
PPS normalisation (income/80610×30000); income cascade: NUTS-2→NUTS-1→US state→country
- init_landing_seeds: compress=False for ST_Read files; gisco GeoJSON + census income seeds
- CHANGELOG + PROJECT.md updated
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-27 11:03:16 +01:00
Deeman
5e5a7c1bae
docs: CHANGELOG + PROJECT.md for Phase 2a NUTS-1 regional income
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-27 10:26:48 +01:00
Deeman
5fa8a98903
merge: opportunity score data quality improvements
...
Phase 0 — income ceiling fix (opportunity_score):
PPS normalisation /200→/35000; economic power now differentiates
countries (DE 13.2, ES 10.7, SE 14.3 pts; was 20.0 everywhere)
Phase 1b — overpass_tennis in workflows.toml:
Monthly schedule added; was only in combined extractor
Phase 2b — dim_cities spatial population fallback:
GeoNames spatial CTE (ST_Distance_Sphere, 0.14° bbox) resolves
localization mismatches: Wien→1.69M, Milano→1.37M, München→1.49M
Coverage: 70.5% → 98.5% (5,401/5,481 cities with population)
2026-02-27 08:52:35 +01:00
Deeman
e32f7ba4b8
docs: CHANGELOG + PROJECT.md for opportunity score data quality improvements
...
Documents Phase 0 (income ceiling fix), Phase 1b (overpass_tennis workflow),
and Phase 2b (dim_cities spatial population fallback, 70.5%→98.5% coverage).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-27 08:48:16 +01:00
Deeman
ce2171614b
docs: CHANGELOG + PROJECT.md for group_key grouping + report PDF
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-27 07:56:34 +01:00
Deeman
721b2a37df
docs: CHANGELOG + PROJECT.md for score recalibration (market_score v3 + opportunity_score v2)
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-27 06:58:48 +01:00
Deeman
0b3e1235fa
docs: CHANGELOG + PROJECT.md for opportunity_score integration
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-26 20:44:07 +01:00
Deeman
a98903646d
merge: pricing-overhaul — Basic free, card color €59, BP PDF €149, supplier page CRO, lead-back guarantee
2026-02-26 15:49:57 +01:00
Deeman
9dd0f30014
docs: pricing overhaul + lead-back guarantee — CHANGELOG + PROJECT.md
...
CHANGELOG: add Added section (guarantee, CRO restructure, credits-only callout,
ROI line) and Changed section (Basic free, card color €59, BP PDF €149,
hero CTA, comparison table, EN/DE translations, setup_paddle.py)
PROJECT.md:
- Correct Done section prices (Growth €199, Pro €499)
- Add Done entries: pricing overhaul, lead-back guarantee
- Add 3 Decisions Log entries (Basic free, guarantee credit-only, static ROI)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-26 15:24:06 +01:00
Deeman
ad1da5c335
feat: outreach follow-up scheduling, activity timeline, and pSEO noindex (migration 0025)
...
Feature A — Outreach follow-up + activity timeline:
- follow_up_at column on suppliers (migration 0025)
- HTMX date picker on outreach rows, POST /admin/outreach/<id>/follow-up
- Amber due-today banner on /admin/outreach with ?follow_up=due filter
- get_follow_up_due_count() for dashboard widget
- Activity timeline on /admin/suppliers/<id>: merges sent + received emails by contact_email
Feature B — pSEO article noindex:
- noindex column on articles (migration 0025)
- NOINDEX_THRESHOLDS per-template lambdas in content/__init__.py
- generate_articles() evaluates threshold and stores noindex=1 for thin-data articles
- <meta name="robots" content="noindex, follow"> in article_detail.html
- Sitemap excludes noindex articles (AND noindex = 0)
- pSEO dashboard noindex count card + article row badge
Tests: 49 new tests (29 outreach, 20 noindex), 1377 total, 0 failures
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-25 17:51:38 +01:00
Deeman
3b248871c2
docs: update CHANGELOG and PROJECT.md for follow-up scheduling, activity timeline, and noindex features
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-25 16:12:56 +01:00
Deeman
cee2e9babc
merge: standardise recheck availability to JSONL + update docs
2026-02-25 15:45:23 +01:00
Deeman
606d6f7d4c
merge(outreach): admin outreach pipeline + separate sending domain
...
# Conflicts:
# CHANGELOG.md
2026-02-25 15:29:20 +01:00
Deeman
b33dd51d76
feat: standardise recheck availability to JSONL output
...
- extract_recheck() now writes availability_{date}_recheck_{HH}.jsonl.gz
(one venue per line with date/captured_at_utc/recheck_hour injected);
uses compress_jsonl_atomic; removes write_gzip_atomic import
- stg_playtomic_availability: add recheck_jsonl CTE (newline_delimited
read_json on *.jsonl.gz recheck files); include in all_venues UNION ALL;
old recheck_blob CTE kept for transition
- init_landing_seeds.py: add JSONL recheck seed alongside blob seed
- Docs: README landing structure + data sources table updated; CHANGELOG
availability bullets updated; data-sources-inventory paths corrected
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-25 14:52:47 +01:00
Deeman
efaba2cb76
feat(outreach): admin outreach pipeline + separate sending domain (all subtasks)
...
Adds cold B2B supplier outreach pipeline isolated from transactional emails.
Subtask 1 — Migration + constants:
- Migration 0024: 4 new columns on suppliers (outreach_status, outreach_notes,
last_contacted_at, outreach_sequence_step); NULL status = not in pipeline
- EMAIL_ADDRESSES["outreach"] = hello.padelnomics.io (separate reputation domain)
- "outreach" added to EMAIL_TYPES
Subtask 2 — Query functions + routes:
- get_outreach_pipeline() — counts by status for pipeline cards
- get_outreach_suppliers() — filtered list with status/country/search
- GET /admin/outreach — pipeline dashboard
- GET /admin/outreach/results — HTMX partial
- POST /admin/outreach/<id>/status — inline status update
- POST /admin/outreach/<id>/note — inline note edit
- POST /admin/outreach/add-prospects — bulk set from supplier list
Subtask 3 — CSV import:
- GET/POST /admin/outreach/import
- Accepts name+contact_email (required), country_code/category/website (optional)
- Deduplicates by contact_email, auto-generates slug, capped at 500 rows
Subtask 4 — Templates:
- outreach.html (pipeline cards + HTMX filter + results table)
- outreach_import.html (CSV upload form)
- partials/outreach_results.html, partials/outreach_row.html
- base_admin.html: Outreach sidebar link
- suppliers.html + supplier_results.html: checkbox column + bulk action bar
Subtask 5 — Compose integration:
- email_compose() GET: ?from_key=outreach&email_type=outreach&supplier_id=<id>
pre-fills from-addr, stores hidden fields, defaults wrap=0 (plain text)
- email_compose() POST: on outreach send, advances prospect→contacted,
increments outreach_sequence_step, sets last_contacted_at
- email_compose.html: hidden email_type + supplier_id fields, outreach banner
- supplier_detail.html: outreach card (status, step, last contact, send button)
Subtask 6 — Tests:
- 44 tests in web/tests/test_outreach.py covering: constants, access control,
query functions, dashboard, HTMX partial, status update, note update,
add-prospects, CSV import, compose pre-fill, compose pipeline update
Subtask 7 — Docs:
- CHANGELOG.md and PROJECT.md updated
Manual step after deploy: add hello.padelnomics.io in Resend dashboard + DNS.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-25 14:06:53 +01:00
Deeman
d637687795
feat(pipeline): tests, docs, and ruff fixes (subtask 6/6)
...
- Add 29-test suite for all pipeline routes, data helpers, and query
execution (test_pipeline.py); all 1333 tests pass
- Fix ruff UP041: asyncio.TimeoutError → TimeoutError in analytics.py
- Fix ruff UP036/F401: replace sys.version_info tomllib block with
plain `import tomllib` (project requires Python 3.11+)
- Fix ruff F841: remove unused `cutoff` variable in pipeline_overview
- Update CHANGELOG.md with Pipeline Console entry
- Update PROJECT.md: add Pipeline Console to Admin Panel done list
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-25 13:02:51 +01:00
Deeman
4fbe53d7ca
merge: JSONL streaming landing format + regional overpass_tennis splitting
...
Converts extractors from large JSON blobs to streaming JSONL (.jsonl.gz),
eliminating in-memory accumulation, maximum_object_size workarounds, and
the playtomic availability consolidation step.
- compress_jsonl_atomic(): 1MB-chunk streaming compression, atomic rename
- playtomic_tenants → tenants.jsonl.gz (one tenant per line after dedup)
- playtomic_availability → availability_{date}.jsonl.gz (working file IS the output)
- geonames → cities_global.jsonl.gz (eliminates 30MB blob)
- overpass_tennis → 10 regional bbox queries + courts.jsonl.gz with crash recovery
- All modified staging SQL uses UNION ALL (JSONL + blob) for smooth transition
- init_landing_seeds.py: bootstrap seeds for both formats in 1970/01
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
# Conflicts:
# CHANGELOG.md
2026-02-25 12:34:03 +01:00
Deeman
683ca3fc24
docs: update CHANGELOG and PROJECT.md for JSONL landing format
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-25 12:28:43 +01:00
Deeman
578a409893
feat(email-templates): tests, docs, and fix quote_verification sample data (subtask 8)
...
- Add 50 tests in test_email_templates.py:
- TestRenderEmailTemplate: all 11 registry templates render in EN + DE
without error; checks DOCTYPE, wordmark, font, CTA color, template-
specific content (heat badges, brief rows, weekly digest loop, etc.)
and registry structure
- TestEmailGalleryRoutes: access control, gallery list (all labels
present, preview links), preview pages (EN/DE/nonexistent/invalid-lang),
compose preview endpoint (plain + wrapped + empty body)
- Fix _quote_verification_sample: add missing recap_parts key — StrictUndefined
raised on the {% if recap_parts %} check when the variable was absent
- Update CHANGELOG.md: document email template system (renderer, base,
macros, 11 templates, registry, gallery, compose preview, removed helpers)
- Update PROJECT.md: add email template system + gallery to Done section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-25 12:24:52 +01:00
Deeman
5ba4cabcd8
docs: update CHANGELOG and PROJECT.md for marketplace + lead forward tracking
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-25 09:37:26 +01:00
Deeman
d5947af8d4
merge: maximum performance extraction (parallel pages + crash-safe partial JSONL)
...
# Conflicts:
# .env.dev.sops
# .env.prod.sops
# extract/padelnomics_extract/src/padelnomics_extract/playtomic_tenants.py
2026-02-24 22:36:34 +01:00
Deeman
1ef22770aa
docs: update CHANGELOG for extraction performance improvements
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-24 22:31:19 +01:00
Deeman
a9b14b8f73
docs: update CHANGELOG + PROJECT.md for pSEO Engine
...
Records all Phase 1 deliverables: content gaps, data freshness,
health checks, generation job monitoring, 45 tests, bug fixes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-24 20:51:29 +01:00
Deeman
405efcfd19
docs: update docs and PROJECT.md for dual score pipeline
...
Task 8: documentation updates for the dual market score feature.
- CHANGELOG.md: comprehensive [Unreleased] entries for all additions
(Marktpotenzial-Score, tennis courts, dim_locations, GeoNames expansion,
DuckDB spatial, SOPS secrets, methodology page updates)
- docs/data-sources-inventory.md: add tennis courts Overpass row, update
GeoNames entry (cities1000, username=padelnomics, higher score)
- transform/sqlmesh_padelnomics/CLAUDE.md: add dim_locations to conformed
dimensions table, update source integration map with new pipeline branch,
document ST_Distance_Sphere bounding-box pattern
- PROJECT.md: add dual score to In Progress, add Gemeinde pSEO + top-50
ranking page to Next Up, add data backlog items (sports_centre, NUTS-3,
opportunity map), add Decisions Log entry
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-24 17:12:22 +01:00
Deeman
f0c041a00c
merge: fix datetime.utcnow() deprecation warnings across all files
...
Replaces 94 occurrences of deprecated datetime.utcnow() and
datetime.utcfromtimestamp() across 22 files with utcnow()/utcnow_iso()
helpers. Zero DeprecationWarnings remain. All 1201 tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-24 10:36:26 +01:00
Deeman
d42c4790b4
chore: update CHANGELOG for datetime deprecation fix
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-02-24 10:30:31 +01:00
Deeman
abc8be12c3
docs: update CHANGELOG and PROJECT.md with Market Score page
...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-24 10:16:15 +01:00
Deeman
c574fe7e62
docs: update CHANGELOG and PROJECT.md for pSEO template improvements
...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-24 02:14:14 +01:00
Deeman
a555331729
docs: update CHANGELOG and PROJECT.md for CMS admin improvement
...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-24 01:20:37 +01:00
Deeman
4006d47a79
docs: update CHANGELOG and PROJECT.md for visual test overhaul
...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-23 21:11:34 +01:00
Deeman
4ff0a0cce8
docs: update CHANGELOG and PROJECT.md for SOPS secrets migration
...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-23 17:19:09 +01:00
Deeman
84229e50f7
Merge branch 'worktree-supervisor-flags'
...
Python supervisor + DB-backed feature flags
- supervisor.py replaces supervisor.sh (topological wave scheduling, croniter)
- workflows.toml workflow registry (5 extractors, cron presets, depends_on)
- proxy.py round-robin + sticky proxy rotation via PROXY_URLS
- Feature flags: migration 0019, is_flag_enabled(), feature_gate() decorator
- Admin /admin/flags UI with toggle (admin-only)
- lead_unlock gate on unlock_lead route
- 59 new tests (test_supervisor.py + test_feature_flags.py)
- Fix is_flag_enabled bug (fetch_one instead of execute_fetchone)
# Conflicts:
# CHANGELOG.md
# web/pyproject.toml
2026-02-23 15:29:43 +01:00
Deeman
8b7d474ede
docs: update CHANGELOG and PROJECT.md for supervisor + feature flags
...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-23 15:27:23 +01:00
Deeman
024feeaac4
feat: SEO/GEO admin hub — GSC, Bing, Umami sync + search/funnel/scorecard views
...
# Conflicts:
# CHANGELOG.md
# uv.lock
# web/src/padelnomics/admin/templates/admin/base_admin.html
# web/src/padelnomics/core.py
2026-02-23 15:23:03 +01:00
Deeman
36b90eb4df
docs: update CHANGELOG and PROJECT.md for SEO/GEO hub
...
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-23 15:09:25 +01:00
Deeman
325b897f38
Merge branch 'worktree-landing-backup'
...
# Conflicts:
# CHANGELOG.md
2026-02-23 15:01:32 +01:00
Deeman
76814dade7
feat: landing zone backup to R2 via rclone + Litestream
...
Landing files (append-only JSON.gz) synced to R2 every 30 min via
systemd timer + rclone. Extraction state DB (.state.sqlite) continuously
replicated via Litestream (second DB entry). Auto-restore on container
startup for both app.db and .state.sqlite. Reuses existing R2 bucket
and credentials — no new env vars needed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-23 14:06:16 +01:00
Deeman
49cadf6995
Merge branch 'worktree-sitemap-improvement'
...
# Conflicts:
# web/src/padelnomics/admin/routes.py
2026-02-23 13:15:21 +01:00
Deeman
454b362c88
feat: admin email hub — sent log, inbox, compose, audiences, delivery tracking
...
Add full email management at /admin/emails with:
- email_log table tracking all outgoing emails with resend_id + delivery events
- inbound_emails table for Resend webhook-received messages
- Resend webhook handler (/webhooks/resend) updating delivery status in real-time
- send_email() returns resend_id (str|None) instead of bool; all 9 worker
handlers pass email_type= for per-type filtering
- Admin UI: sent log with HTMX filters, email detail with API-enriched HTML
preview, inbox with unread badges + reply, compose with branded wrapping,
audience management with contact list/remove
- Sidebar Email section with unread badge via blueprint context processor
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-23 13:00:23 +01:00
Deeman
1a6eae20d5
feat: pSEO CMS — SSG architecture with git templates + DuckDB
...
# Conflicts:
# web/pyproject.toml
2026-02-23 12:51:30 +01:00
Deeman
f1181342ad
feat: SSG-inspired pSEO CMS — git templates + DuckDB direct reads
...
Replace the old CSV-upload-based CMS with an SSG architecture where
templates live in git as .md.jinja files with YAML frontmatter and
data comes directly from DuckDB serving tables. Only articles and
published_scenarios remain in SQLite for routing/state.
- Content module: discover, load, generate, preview functions
- Migration 0018: drop article_templates + template_data, recreate
articles + published_scenarios without FK references, add
template_slug/language/date_modified/seo_head columns
- Admin routes: read-only template views with generate/regenerate/preview
- SEO pipeline: canonical URLs, hreflang (EN+DE), JSON-LD (Article,
FAQPage, BreadcrumbList), Open Graph tags baked at generation time
- Example template: city-cost-de.md.jinja for German city market data
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-23 12:25:44 +01:00
Deeman
894fd0c719
feat: email design & copy upgrade for all 9 transactional emails
...
Redesigned _email_wrap(): lowercase wordmark header matching website,
3px blue accent border, preheader text support, HR separators.
_email_button() now full-width block for mobile tap targets.
Rewrote copy: improved subject lines, urgency cues, quick-start links
in welcome, styled project recap in quote verify, heat badges on lead
forward, "what happens next" in lead matched, secondary CTAs.
~30 new/updated translation keys in both EN and DE.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-23 11:00:49 +01:00
Deeman
13c86ebf84
Merge branch 'worktree-extraction-overhaul'
...
# Conflicts:
# transform/sqlmesh_padelnomics/models/foundation/dim_cities.sql
# transform/sqlmesh_padelnomics/models/staging/stg_playtomic_venues.sql
2026-02-23 01:01:26 +01:00
Deeman
79f7fc6fad
feat: Playtomic pricing/occupancy pipeline + email i18n + audience restructure
...
Three workstreams:
1. Playtomic full data extraction & transform pipeline:
- Expand venue bounding boxes from 4 to 23 regions (global coverage)
- New staging models for court resources, opening hours, and slot-level
availability with real prices from the Playtomic API
- Foundation fact tables for venue capacity and daily occupancy/revenue
- City-level pricing benchmarks replacing hardcoded country estimates
- Planner defaults now use 3-tier cascade: city data → country → fallback
2. Transactional email i18n:
- _t() helper in worker.py with ~70 translation keys (EN + DE)
- All 8 email handlers translated, lang passed in task payloads
3. Resend audiences restructured to 3 named audiences (free plan limit)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-23 00:54:53 +01:00
Deeman
e270d54f62
feat: sitemap hreflang alternates, caching, and lastmod cleanup
...
Extract sitemap generation to sitemap.py with xhtml:link hreflang
alternates (en/de/x-default) on every URL entry. Add 1-hour in-memory
TTL cache with Cache-Control header. Include supplier pages in both
languages (were EN-only). Drop misleading "today" lastmod from static
pages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com >
2026-02-22 23:13:32 +01:00