# Technical Changelog ## 2026-05-12 - SMSPLANET Inbound Webhook Fix **Co zrobiono:** - Poprawiono dopasowanie przychodzacych SMSPLANET po telefonie: `SmsMessageRepository::findLatestOrderIdByPhones()` nie odwoluje sie juz do nieistniejacej w produkcyjnej bazie kolumny `orders.buyer_phone`, tylko do `order_addresses.phone`. - Dodano obsluge `GET /webhooks/smsplanet/inbound` obok POST, bo sekcja odbierania SMS 2WAY w dokumentacji SMSPLANET opisuje przekierowanie na URL bez jednoznacznego kontraktu metody. - `SmsplanetWebhookController` obsluguje format 2WAY `POST application/x-www-form-urlencoded` z parametrem `message=`, scala JSON z body z parametrami requestu takze wtedy, gdy URL ma query string, i po sukcesie zwraca plain text `OK`. **Dlaczego:** - Publiczny endpoint byl osiagalny jako POST, ale odpowiedz SMS nie mogla zostac zapisana przez blad SQL `Unknown column 'o.buyer_phone'`. GET na ten sam URL zwracal 404. **BREAKING / migracja:** - Brak migracji. Zmiana usuwa bledne zalozenie o schemacie produkcyjnej tabeli `orders`. ## 2026-05-12 - Phase 122 Plan 01: SMSPLANET Default SMS Footer **Co zrobiono:** - Dodano migracje `20260512_000111_smsplanet_default_footer.sql` z kolumna `smsplanet_integration_settings.default_footer`. - Rozszerzono konfiguracje SMSPLANET o opcjonalna stopke SMS z limitem 300 znakow i zapisem oddzielnym od danych autoryzacji/nadawcy. - Testowa wysylka SMSPLANET oraz wysylka SMS z zamowienia dopinaja stopke przez pusta linie, waliduja finalna tresc w limicie 918 znakow i nie wywoluja API przy przekroczeniu limitu. - Historia `sms_messages.body` zapisuje finalna tresc wyslana do SMSPLANET, czyli razem ze stopka, gdy jest skonfigurowana. - Widok rozmowy SMS w zamowieniu pokazuje kompaktowa informacje, ze stopka zostanie dodana automatycznie. **Dlaczego:** - Operator ma utrzymywac jeden wspolny podpis firmy bez recznego kopiowania go do kazdej wiadomosci SMS. **BREAKING / migracja:** - Brak. Pusta stopka zachowuje dotychczasowe tresci SMS bez zmian. ## 2026-05-12 - Phase 121 Plan 01: SMSPLANET Conversation + Notifications **Co zrobiono:** - Dodano migracje `20260512_000110_smsplanet_conversation_notifications.sql` z tabelami `sms_messages`, `notifications` oraz polami `sender_mode` i `sender_phone` w `smsplanet_integration_settings`. - Rozszerzono SMSPLANET o wybor nadawcy: nadpis albo numer 2WAY, bez tymczasowego override testowego numeru. - Dodano publiczny webhook `/webhooks/smsplanet/inbound`, zapis przychodzacych SMS, dopasowanie do ostatniego zamowienia po telefonie i tworzenie globalnego powiadomienia. - Dodano zakladke SMS w szczegolach zamowienia z historia rozmowy i formularzem wysylki. - Dodano centrum powiadomien `/notifications`, API pollingu `/api/notifications/unread`, badge w topbarze i progresywne powiadomienia przegladarki. - Poprawiono migracje po pierwszej probie na bazie: rzeczywiste `orders.id` ma typ `BIGINT UNSIGNED`, wiec `sms_messages.order_id` i `notifications.related_order_id` tez musza miec `BIGINT UNSIGNED`. **Dlaczego:** - Operator ma prowadzic dwukierunkowa rozmowe SMSPLANET bez opuszczania zamowienia, a nowe odpowiedzi klientow maja byc widoczne globalnie. **BREAKING / migracja:** - Brak. Webhook SMSPLANET w tej fazie celowo nie weryfikuje podpisu. ## 2026-05-12 - SMSPLANET Test Sender Override **Co zrobiono:** - Tymczasowo ustawiono testowa wysylke SMSPLANET na `from=48532963363` w `SmsplanetIntegrationController::test()`. - Zapis konfiguracji SMSPLANET pozostaje bez zmian; override dotyczy tylko endpointu `/settings/integrations/smsplanet/test`. **Dlaczego:** - Operator sprawdza odbior odpowiedzi SMS z numeru 2WAY zamiast tekstowego nadpisu. ## 2026-05-12 - Phase 118 Plan 01: Fakturownia Single Instance **Co zrobiono:** - Dodano migracje `20260512_000109_fakturownia_single_instance.sql`, ktora wybiera aktywna instancje Fakturowni, przepina delegowane `invoice_configs.integration_id` na jeden globalny rekord i usuwa nadmiarowe konta Fakturowni po przepieciu zaleznosci. - Przebudowano `FakturowniaIntegrationRepository` na model jednej globalnej konfiguracji (`getSettings()`, `saveSettings()`, `getIntegrationId()`, `getCredentials()`), z kompatybilnym `findAll()` zwracajacym jeden element. - Uproszczono `FakturowniaIntegrationController` i widok `/settings/integrations/fakturownia` do pojedynczego formularza konfiguracji i testu polaczenia. - Hub integracji pokazuje Fakturownie jako jedna instancje, bez licznika kont. - Zapis delegowanej konfiguracji faktury ustawia `invoice_configs.integration_id` na globalny rekord Fakturowni; UI konfiguracji faktury nie pokazuje juz selecta kont. - Zaktualizowano `DOCS/DB_SCHEMA.md` i `DOCS/ARCHITECTURE.md` o kontrakt pojedynczej Fakturowni. **Dlaczego:** - Operator chce obslugiwac Fakturownie tak jak HostedSMS/SMSPLANET: jedna konfiguracja globalna zamiast wielu instancji. - Zachowanie `invoice_configs.integration_id` ogranicza ryzyko regresji w `InvoiceService` i historii faktur, a jednoczesnie usuwa wieloinstancyjny wybor z UI. **BREAKING / migracja:** - Po migracji nie ma juz wielu kont Fakturowni w UI. Jesli baza miala wiele rekordow `integrations.type='fakturownia'`, zachowany zostaje aktywny rekord (fallback: uzywany przez konfiguracje faktur, potem najnizsze id), a pozostale sa usuwane. ## 2026-05-12 - Phase 117 Plan 01: SMSPLANET Integration Settings + Test SMS **Co zrobiono:** - Dodano migracje `20260512_000108_create_smsplanet_integration_settings.sql` z pojedyncza konfiguracja `smsplanet_integration_settings` i bazowym wpisem `integrations` typu `smsplanet`. - Dodano `SmsplanetIntegrationRepository` z obsluga metod autoryzacji `token` oraz `key_password` i szyfrowaniem sekretow przez `IntegrationSecretCipher`. - Dodano `SmsplanetApiClient` dla SMSPLANET (`POST https://api2.smsplanet.pl/sms`) z obsluga Bearer token oraz `key` + `password`. - Dodano `SmsplanetIntegrationController` i trasy `/settings/integrations/smsplanet`, `/save`, `/test`. - Dodano widok `resources/views/settings/smsplanet.php` z konfiguracja i realna wysylka testowego SMS z edytowalna trescia oraz panelem ostatniego testu (`OK`, HTTP, `messageId`). - Dodano SMSPLANET do hubu integracji `/settings/integrations`. - Poprawiono import `IntegrationSecretCipher`, aby rzucal istniejacy `App\Core\Exceptions\IntegrationConfigException`. **Dlaczego:** - Operator potrzebuje drugiej bramki SMS analogicznej do HostedSMS, ale bez uruchamiania jeszcze automatyzacji lub historii wysylek. - SMSPLANET wspiera dwa warianty autoryzacji, wiec konfiguracja przechowuje wszystkie sekrety w formie szyfrowanej i waliduje wymagania zalezne od wyboru operatora. - Test uzywa rzeczywistej wysylki, bo celem tej fazy jest potwierdzenie realnej sciezki API. ## 2026-05-12 - Phase 116 Plan 01: HostedSMS Integration Settings + Test SMS **Co zrobiono:** - Dodano migracje `20260512_000107_create_hostedsms_integration_settings.sql` z pojedyncza konfiguracja `hostedsms_integration_settings` i bazowym wpisem `integrations` typu `hostedsms`. - Dodano `HostedSmsIntegrationRepository` z szyfrowaniem hasla przez `IntegrationSecretCipher`. - Dodano `HostedSmsApiClient` dla HostedSMS SimpleAPI (`POST https://api.hostedsms.pl/SimpleApi`). - Dodano `HostedSmsIntegrationController` i trasy `/settings/integrations/hostedsms`, `/save`, `/test`. - Dodano widok `resources/views/settings/hostedsms.php` z konfiguracja i realna wysylka testowego SMS z edytowalna trescia oraz czytelnym panelem ostatniego testu (`OK`, HTTP, MessageId). - Dodano HostedSMS do hubu integracji `/settings/integrations`. **Dlaczego:** - Operator potrzebuje najpierw zapisac dane HostedSMS i sprawdzic realna wysylke SMS, zanim integracja zostanie wykorzystana w automatyzacjach lub komunikacji z klientami. - Test uzywa rzeczywistej wysylki, bo SimpleAPI nie udostepnia osobnego endpointu ping/test. - Haslo nie jest ujawniane po zapisie; UI pokazuje tylko status zapisanego sekretu. ## 2026-04-28 - Phase 110 Plan 01: Statistics Summary **Co zrobiono:** - `/statistics/summary` - nowy widok podsumowania w menu `Statystyki -> Podsumowanie`. - `OrdersStatisticsController::summary()` - buduje miesieczny view-model dla wykresow liczby i wartosci zamowien. - `OrdersStatisticsRepository::aggregateByMonth()` - agreguje istniejace zamowienia po miesiacu i kanale/integracji. - `public/assets/js/modules/statistics-summary-charts.js` - renderer dwoch interaktywnych wykresow liniowych oparty o Chart.js 4.4.8 CDN. - `resources/views/statistics/summary.php` - filtry zgodne z raportem dziennym, dwa wykresy obok siebie na desktopie oraz dwie tabele fallback pod nimi. - Domyslny poczatek historii ustawiony na `2026-04-01` (`04-2026`) mimo starszych danych. **Dlaczego:** - Operator potrzebuje szybkiego trendu miesiecznego przed przejsciem do szczegolowych dziennych statystyk. - Wykresy uzywaja obecnych tabel `orders`, `integrations`, `order_status_groups` i `order_statuses`, wiec migracja DB nie jest potrzebna. - Seria `Razem` jest liczona z tych samych danych co serie integracji, co ulatwia sprawdzenie sum miesiecznych. ## 2026-04-28 - Phase 109 Plan 01: Checkbox Multiselect Filters **Co zrobiono:** - `public/assets/js/modules/checkbox-multiselect.js` - nowy vanilla JS enhancer dla natywnych `