10 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, duration, started, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | duration | started | completed | |||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 09-finalizacja | 02 | integrations |
|
|
|
|
|
|
|
|
~25min | 2026-05-06T11:00:00Z | 2026-05-06T11:25:00Z |
Phase 9 Plan 02: Globalna synchronizacja iCal Summary
Dwukierunkowa synchronizacja całej floty z jednym wspólnym Google Calendar przez iCal feedy, z automatycznym przypisaniem eventów do jachtów po prefiksie nazwy w tytule (separator " - ").
Performance
| Metric | Value |
|---|---|
| Duration | ~25min |
| Tasks | 3 auto + 1 human-verify (wszystkie zaakceptowane) |
| Files modified | 6 |
Acceptance Criteria Results
| Criterion | Status | Notes |
|---|---|---|
| AC-1: Globalny iCal Export feed | Pass | output_global_ics() zwraca .ics ze wszystkimi rezerwacjami, każda z prefiksem {yacht_title} - {customer_name}, anti-loop pomija source ical_import_global |
| AC-2: Globalny Import — dopasowanie po prefiksie | Pass | run_global_import() + match_yacht_by_prefix() parsuje SUMMARY przed pierwszym -, dopasowuje case-insensitive (mb_*), eventy bez dopasowania logowane i pomijane |
| AC-3: Globalny Import — czyszczenie usuniętych | Pass | existing_global_map vs seen_uids — zniknięte UID-y → Availability::clear_booking_availability() + wp_delete_post |
| AC-4: Alias jachtu | Pass | Yacht::get_gcal_alias() + update_gcal_alias(), build_yacht_lookup_map() używa aliasu z priorytetem |
| AC-5: Frontend filtrowanie (regresja) | Pass | Bez zmian w widget — działa przez _booking_yacht_id jak dotąd; klient zweryfikował na produkcji |
| AC-6: Settings UI | Pass | Nowa sekcja "Globalna synchronizacja iCal" (krok 1: export URL + kopiuj + regeneracja tokenu, krok 2: import URL + zapis, krok 3: importuj teraz, instrukcja) + alias w yacht-edit |
Accomplishments
- Klient może subskrybować jeden URL pluginu w Google Calendar i widzieć rezerwacje WSZYSTKICH jachtów w jednym widoku floty
- Klient może tworzyć ręczne eventy w GCal z tytułem
"Nazwa - opis"— plugin automatycznie przypisuje je do właściwego jachtu i blokuje availability tylko dla tego jachtu - Frontend kalendarz per-jacht pokazuje tylko swoje rezerwacje (bez zmian w widgecie — działa dzięki poprawnemu przypisaniu
_booking_yacht_idprzy imporcie) - Anti-loop zapobiega duplikacji (eventy zaimportowane z GCal nie są wysyłane z powrotem)
- Stale cleanup automatycznie usuwa rezerwacje gdy event zostanie skasowany w GCal
- Per-yacht feedy + OAuth push zostały zachowane (kompatybilność wsteczna)
Files Created/Modified
| File | Change | Purpose |
|---|---|---|
integrations/ical/class-ical-feed.php |
Modified | +rewrite rule ^yacht-ical-global/, +query var yacht_ical_global, +get_global_feed_token(), +regenerate_global_token(), +get_global_feed_url(), +output_global_ics() (anti-loop, prefiks per yacht) |
integrations/ical/class-ical-import.php |
Modified | +GLOBAL_IMPORT_SOURCE, +SUMMARY_SEPARATOR, +run_global_import(), +build_yacht_lookup_map() (alias priority), +match_yacht_by_prefix() (mb_*), +get_existing_global_import_map(), +upsert_global_booking(), cron yacht_booking_ical_global_import (hourly), zmiana visibility parse_ics na protected |
includes/class-yacht.php |
Modified | +get_gcal_alias(), +update_gcal_alias() (meta _yacht_gcal_alias) |
includes/class-installer.php |
Modified | +domyślne opcje: yacht_booking_global_ical_import_url, yacht_booking_global_ical_token, yacht_booking_global_ical_last_import |
admin/class-admin.php |
Modified | +obsługa 3 form actions (save/regenerate token/run import), +4 admin notices, +sekcja UI "Globalna synchronizacja iCal" w render_google_calendar_settings(), +zapis aliasu w save_yacht() |
admin/views/yacht-edit.php |
Modified | +pole yacht_gcal_alias z opisem |
Decisions Made
| Decision | Rationale | Impact |
|---|---|---|
| Separator " - " (spacja-myślnik-spacja) | Zgodność z istniejącym formatem output_ics (per-yacht feed już używał tego stylu) |
Klient nie musi uczyć się nowej konwencji; istniejące eksporty działają tak samo |
| Lookup po lowercase pełnej nazwy/aliasu (exact, nie substring) | Uniknięcie kolizji typu "Maja" trafia w "Maja" i "Maja Słoneczna" jednocześnie | Klient z długimi nazwami flot musi ustawić aliasy, ale ma pewność rozróżnienia |
| Eventy bez dopasowania — ignorowane (nie blokują) | Klient nie chce niespodzianek (przypadkowa blokada całej floty przez literówkę) | Dyscyplina nazewnictwa w GCal, ale przewidywalność |
Anti-loop przez _booking_source flag |
Najprostsze, niezawodne | Bez ryzyka eskalacji duplikatów między iteracjami |
| Per-yacht feedy zostają | Kompatybilność wsteczna (potencjalni subskrybenci OTA) | Out of scope ich usunięcia — decyzja na osobny plan po stabilizacji |
| Cron co godzinę dla globalnego importu | Spójne z per-yacht cron | Klient widzi import w panelu lub może wymusić "Importuj teraz" |
Deviations from Plan
Summary
| Type | Count | Impact |
|---|---|---|
| Auto-fixed | 0 | — |
| Scope additions | 0 | — |
| Deferred | 0 | — |
Total impact: Plan wykonany dokładnie zgodnie ze specyfikacją. Brak odchyleń.
Auto-fixed Issues
Brak.
Deferred Items
Brak.
Issues Encountered
Brak — żadnych problemów podczas implementacji ani weryfikacji manualnej.
Otwarte pytania (do następnego planu)
Klient w trakcie planowania prosił "zapytaj po zrobieniu importu i eksportu" — te pytania zostają otwarte:
-
Pola per-yacht "Google Calendar ID" i "iCal Import URL" w yacht-edit — czy je usunąć/ukryć teraz, gdy klient będzie używał globalnej synchronizacji? Jeśli tak: usunąć z UI ale zachować dane w meta na wypadek migracji.
-
OAuth push do GCal (sync_to_gcal cron + on_booking_created hook) — drugi mechanizm jest aktywny tylko gdy admin podłączył OAuth. Klient nie planuje tego używać. Czy wyłączyć całkowicie (żeby uniknąć ewentualnych duplikatów gdy ktoś przez pomyłkę połączy OAuth) czy zostawić jako opcję?
Reproduction Path (do testów regresyjnych)
- Settings → Google Calendar → sekcja "Globalna synchronizacja iCal" → skopiuj Export URL → wklej w GCal "Z URL-a"
- Utwórz w GCal event
"NazwaJachtu - Test"(data za tydzień, całodniowy) - Skopiuj iCal URL kalendarza Google → wklej w pole "iCal Import URL" → Zapisz → "Importuj teraz"
- WP Admin → Rezerwacje → pojawia się booking
"GCal: NazwaJachtu - Test"(sourceical_import_global) - Frontend kalendarz tego jachtu → data zablokowana; inny jacht → data wolna
- Usuń event w GCal → "Importuj teraz" → booking zniknął, daty zwolnione
Next Phase Readiness
Ready:
- Globalna synchronizacja iCal w pełni funkcjonalna i zweryfikowana przez klienta
- Architektura per-yacht zachowana (no breaking changes)
- 2 z 4 plans w fazie 9 ukończone
Concerns:
- Ewentualna kolizja gdy admin przypadkowo użyje OAuth obok iCal — drugi mechanizm tworzyłby duplikaty. Mitigacja: GCal_Service::create_event ustawia
_gcal_event_idktórego nie zerujemy, ale plugin już teraz ma anti-loop tylko na imporcie globalnym, nie na OAuth pull. Klient nie używa OAuth → praktyczny ryzyko zerowe. - Klient powinien wykonać deploy FTP + jednorazowy "Save" na stronie Permalinks żeby flush rewrite rules zarejestrowało nową regułę
^yacht-ical-global/(dokumentowane w instrukcji checkpointu).
Blockers: None
Phase: 09-finalizacja, Plan: 02 Completed: 2026-05-06