feat(v0.1): historia cen + jawnosc cen — milestone Initial Release

Historia cen:
- Tabela wp_price_history z WP Cronem dziennym (snapshot cen)
- AJAX endpoint apartamenty_get_price_history (zabezpieczony nonce)
- Popup "Historia cen" w widgecie — vanilla JS, modal zgodny z projektem

Jawnosc cen:
- Endpointy /ceny-mieszkan.xml + /dane-gov-pl.xml (XSD-compliant)
- Pliki MD5 dla obu XML
- Strona admina: Narzedzia -> Jawnosc Cen z URL-ami do Ministerstwa
- Transient cache 1h z inwalidacja przez cron

Dokumentacja: docs/readme.md + docs/jawnosc-cen.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-12 15:40:29 +01:00
parent c954889b64
commit 972c69b136
19 changed files with 2854 additions and 3 deletions

View File

@@ -0,0 +1,109 @@
---
phase: 01-historia-cen
plan: 01
subsystem: database
tags: [wordpress, acf, cron, ajax, mysql]
requires: []
provides:
- "Tabela wp_price_history z unikalnym kluczem (post_id, recorded_at)"
- "WP Cron dzienny zapisujący ceny apartamentów z ACF"
- "AJAX endpoint apartamenty_get_price_history (zalogowani i goście)"
- "wp_localize_script przekazujący ajaxUrl + nonce do JS"
affects: ["01-02-frontend"]
tech-stack:
added: []
patterns:
- "INSERT IGNORE dla idempotentnego zapisu dziennego"
- "dbDelta() + get_option version check dla migracji DB"
- "wp_localize_script na priorytecie 20 po register"
key-files:
modified:
- "wp-content/plugins/elementor-addon/elementor-addon.php"
key-decisions:
- "ACF flat meta keys (information_price, information_price_m2, information_floor_space) zamiast serializowanego pola 'information'"
- "INSERT IGNORE zamiast ON DUPLICATE KEY UPDATE — historia to snapshot, nie aktualizacja"
- "Hook 'wp' dla crona (nie 'init') — gwarantuje kontekst frontendu"
patterns-established:
- "Nonce: apartamenty_price_history_nonce — używany w JS i PHP"
- "AJAX action: apartamenty_get_price_history"
- "Dane JS: window.apartamentsData.ajaxUrl, .nonce"
duration: 15min
started: 2026-03-12T14:00:00Z
completed: 2026-03-12T14:15:00Z
---
# Faza 1 Plan 01: Backend Historii Cen — Summary
**Tabela `wp_price_history` + WP Cron dzienny + AJAX endpoint zabezpieczony nonce — cały backend historii cen gotowy.**
## Performance
| Metryka | Wartość |
|---------|---------|
| Czas wykonania | ~15 min |
| Zadania | 2 ukończone |
| Pliki zmienione | 1 |
## Acceptance Criteria Results
| Kryterium | Status | Uwagi |
|-----------|--------|-------|
| AC-1: Tabela istnieje w bazie | Pass | Zweryfikowano przez bezpośrednie połączenie DB — tabela `wp_price_history` założona |
| AC-2: Cron zapisuje ceny codziennie | Pass | Hook `apartamenty_record_prices` zarejestrowany na `daily`, INSERT IGNORE zweryfikowany |
| AC-3: AJAX endpoint zwraca historię | Pass | Akcje `wp_ajax_*` zarejestrowane, struktura JSON zgodna z planem |
| AC-4: Nonce zabezpiecza AJAX | Pass | `check_ajax_referer` przed jakimkolwiek dostępem do danych |
## Accomplishments
- Tabela `wp_price_history` założona w bazie przez `dbDelta()` — samonaprawiająca się migracja
- WP Cron `apartamenty_record_prices` dzienny — zapis snapshot cen ze wszystkich apartamentów
- AJAX endpoint publiczny (nopriv) zwracający tytuł, aktualne ceny i historię jako JSON
- Nonce `apartamenty_price_history_nonce` przekazany do JS przez `wp_localize_script`
## Files Created/Modified
| Plik | Zmiana | Co dodano |
|------|--------|-----------|
| `wp-content/plugins/elementor-addon/elementor-addon.php` | Zmodyfikowany | +~140 linii: tabela DB, cron, AJAX endpoint, wp_localize_script |
## Decisions Made
| Decyzja | Uzasadnienie | Wpływ |
|---------|--------------|-------|
| Flat meta keys zamiast `get_field('information')` | ACF zapisuje dane jako płaskie klucze — `information_price` etc. istnieją i są puste dla `information` | Cron pobiera dane bezpośrednio przez `get_post_meta` |
| INSERT IGNORE zamiast UPDATE | Historia to snapshot — nie nadpisujemy dawnych wpisów | Jeden rekord na apartament na dzień, bezpieczny dla wielu wywołań |
| Hook `wp` dla crona | Gwarantuje pełny kontekst WP przy rejestracji | Cron rejestruje się tylko na stronach frontendowych/adminowych |
## Deviations from Plan
Brak odchyleń — plan wykonany dokładnie jak zaplanowano.
## Issues Encountered
| Problem | Rozwiązanie |
|---------|-------------|
| Brak klienta mysql CLI na lokalnym środowisku | Weryfikacja przez PHP mysqli (tymczasowy skrypt `.paul/verify_task1.php`, usunięty po weryfikacji) |
## Next Phase Readiness
**Gotowe dla 01-02 (Frontend):**
- `window.apartamentsData.ajaxUrl` — URL do admin-ajax.php
- `window.apartamentsData.nonce` — nonce do requestu
- AJAX action: `apartamenty_get_price_history` z `post_id` w POST body
- Odpowiedź JSON: `{ success, data: { title, price, price_m2, floor_space, history: [{recorded_at, price, price_m2}] } }`
**Uwagi:**
- Tabela ma 1 testowy rekord dla apt 203 (2026-03-12) — wstawiony podczas weryfikacji
- Cron uruchomi się automatycznie przy pierwszym odwiedzeniu strony przez WP
**Blokady:** Brak
---
*Phase: 01-historia-cen, Plan: 01*
*Completed: 2026-03-12*