feat(shipments): add ShipmentProviderInterface and ShipmentProviderRegistry

- Introduced ShipmentProviderInterface to define the contract for shipment providers.
- Implemented ShipmentProviderRegistry to manage and retrieve shipment providers.
- Added a new tool for probing Apaczka order_send payload variants, enhancing debugging capabilities.
This commit is contained in:
2026-03-08 23:45:10 +01:00
parent af052e1ff5
commit 2b12fde248
34 changed files with 3285 additions and 233 deletions

View File

@@ -2,6 +2,7 @@
## Status
- Projekt po resecie do trybu `users-only`.
- UI korzysta z globalnego standardu naglowkow sekcji (`h2/h3/h4.section-title`) definiowanego centralnie w `resources/scss/app.scss` i buildowanego do `public/assets/css/app.css`.
## Moduly aktywne
- `App\Modules\Auth`
@@ -44,6 +45,7 @@
- `GET /settings/integrations/allegro/oauth/callback`
- `GET /settings/integrations/apaczka`
- `POST /settings/integrations/apaczka/save`
- `POST /settings/integrations/apaczka/test`
- `GET /settings/integrations/inpost`
- `POST /settings/integrations/inpost/save`
- `GET /settings/integrations/shoppro`
@@ -92,6 +94,8 @@
- `App\Modules\Users\UserRepository`
- `App\Modules\Settings\ApaczkaIntegrationController`
- `App\Modules\Settings\ApaczkaIntegrationRepository`
- `App\Modules\Settings\ApaczkaApiClient`
- `App\Modules\Settings\CarrierDeliveryMethodMappingRepository`
- `App\Modules\Settings\InpostIntegrationController`
- `App\Modules\Settings\InpostIntegrationRepository`
- `App\Modules\Settings\IntegrationsHubController`
@@ -106,6 +110,9 @@
- `App\Modules\Settings\AllegroOrdersSyncService`
- `App\Modules\Settings\AllegroOrderSyncStateRepository`
- `App\Modules\Settings\AllegroStatusSyncService`
- `App\Modules\Shipments\ShipmentProviderInterface`
- `App\Modules\Shipments\ShipmentProviderRegistry`
- `App\Modules\Shipments\ApaczkaShipmentService`
## Przeplyw Zamowienia > Lista zamowien
- `GET /orders/list`:
@@ -220,6 +227,29 @@
- `shoppro_order_status_sync` -> `ShopproStatusSyncHandler::handle(...)` (synchronizacja statusow shopPRO wg kierunku ustawionego per instancja).
- `shoppro_payment_status_sync` -> `ShopproPaymentStatusSyncHandler::handle(...)` (odswiezanie statusu platnosci zamowien shopPRO na podstawie flagi `paid`).
## Przeplyw tworzenia przesylki
- `GET /orders/{id}/shipment/prepare`:
- `ShipmentController::prepare(Request): Response`,
- laduje uslugi dostawy providerow z `ShipmentProviderRegistry` (aktualnie: `allegro_wza`, `apaczka`),
- pobiera automatyczne mapowanie formy dostawy przez `CarrierDeliveryMethodMappingRepository` (`source_system` + `source_integration_id` + `order_delivery_method`),
- dla dostaw punktowych (`parcel_external_id`/`parcel_name`) prefillem `receiver_name` sa dane klienta (a nie nazwa punktu/metody dostawy),
- gdy mapowanie nie zostanie znalezione, buduje komunikat diagnostyczny (brak mapowan dla instancji lub brak mapowania konkretnej metody) i przekazuje go do widoku.
- `POST /orders/{id}/shipment/create`:
- `ShipmentController::create(Request): Response`,
- wybiera providera dynamicznie po `provider_code` i deleguje do `ShipmentProviderInterface::createShipment(...)`,
- dla `apaczka` waliduje wymagane punkty odbioru/nadania wg definicji uslugi (`service_structure`) i przy bledzie wyceny zwraca rozszerzona diagnostyke parametrow,
- `apaczka` uzupelnia i wysyla `contact_person` dla nadawcy (z `Ustawienia > Dane firmy`) i odbiorcy (fallback z danych zamowienia),
- `apaczka` ustawia jawnie `pickup.type` (`SELF`/`COURIER`) na podstawie uslugi i obecnosci `sender_point_id`; dla `COURIER` dopelnia tez `pickup.date`, `pickup.hours_from`, `pickup.hours_to`,
- dla uslug punktowych `apaczka` payload adresu zawiera aliasy identyfikatora punktu (`point`, `foreign_address_id`, `point_id`) dla nadania i odbioru,
- `ApaczkaShipmentService::buildReceiverAddress(...)` sklada dane odbiorcy z fallbackami (formularz -> delivery -> punkt odbioru z `parcel_name` -> customer), a dla przesylek punktowych dodatkowo probuje uzupelnic adres punktu przez API `points`; przy dalszych brakach dopelnia minimum techniczne, aby nie blokowac tworzenia.
- `GET /orders/{id}/shipment/{packageId}/status`:
- `ShipmentController::checkStatus(Request): Response`,
- wybiera providera po `shipment_packages.provider` i deleguje `checkCreationStatus(...)`.
- `POST /orders/{id}/shipment/{packageId}/label`:
- `ShipmentController::label(Request): Response`,
- wybiera providera po `shipment_packages.provider` i deleguje `downloadLabel(...)`,
- dla Apaczka bledy typu `Label is not available for this order` oznaczaja paczke jako `error`, aby nie ponawiac nieskutecznych prob pobrania.
## Przeplyw Ustawienia > Integracje > Allegro
- `GET /settings/integrations/allegro`:
- `AllegroIntegrationController::index(Request): Response`
@@ -394,6 +424,8 @@
- pobiera liste zamowien i (opcjonalnie) szczegoly zamowienia z API shopPRO,
- mapuje kwoty z fallbackami (`summary`, `paid`, `transport_cost`) oraz ceny pozycji (`price_brutto`),
- uzupelnia `order_items.media_url` przez pobranie `products/get` po `product_id`, gdy zamowienie nie zawiera obrazu.
- wykrywa zadanie faktury takze po obecnosci danych firmowych (`firm_*`) i ustawia `orders.is_invoice`,
- mapuje adres faktury do `order_addresses.address_type=invoice` (firma/NIP/adres) na podstawie pol `invoice`/`billing*`/`firm_*`,
- mapuje punkty odbioru (`inpost_paczkomat` / `orlen_point`) do adresu `delivery` (`parcel_external_id`, `parcel_name`, ulica/kod/miasto),
- uzupelnia `delivery` o telefon/e-mail klienta i etykiete metody dostawy z kosztem (`transport_cost`).
- `ShopproStatusSyncService`:

View File

@@ -45,6 +45,32 @@
- tabela przechowuje mapowanie formy shopPRO na usluge Allegro WZA/InPost (`allegro_delivery_method_id`, `allegro_credentials_id`, `allegro_carrier_id`, `allegro_service_name`, `carrier`).
- 2026-03-08: Poprawiono mapowanie importu zamowien shopPRO (kwoty i miniatury pozycji) - bez zmian schematu bazy.
- 2026-03-08: Poprawiono mapowanie danych wysylki shopPRO (paczkomat/punkt odbioru + kontakt klienta + koszt transportu) - bez zmian schematu bazy.
- 2026-03-08: Dodano migracje `20260308_000044_create_carrier_delivery_method_mappings_table.sql`:
- nowa tabela `carrier_delivery_method_mappings` (wspolne mapowanie form dostawy dla roznych zrodel zamowien i providerow wysylek),
- migracja backfilluje dane z `allegro_delivery_method_mappings` i `shoppro_delivery_method_mappings`.
- 2026-03-08: Dodano migracje `20260308_000045_extend_apaczka_credentials.sql`:
- rozszerzenie `apaczka_integration_settings` o `app_id` i `app_secret_encrypted`,
- migracja przenosi legacy sekret z `api_key_encrypted` do `app_secret_encrypted`.
- 2026-03-08: Poprawiono mapowanie danych faktury w imporcie shopPRO - bez zmian schematu:
- `orders.is_invoice` jest wykrywany takze po polach firmowych (`firm_*`),
- adres faktury jest zapisywany do istniejacej tabeli `order_addresses` (`address_type=invoice`, `company_name`, `company_tax_number`).
- 2026-03-08: Poprawiono diagnostyke tworzenia przesylek Apaczka - bez zmian schematu:
- payload tworzenia przesylki przekazuje punkty odbioru/nadania (`receiver.point`, `sender.point`) z danych formularza,
- komunikaty bledow tworzenia zawieraja rozszerzona diagnostyke parametrow wyceny.
- 2026-03-08: Poprawiono obsluge bledow etykiet Apaczka - bez zmian schematu:
- przy odpowiedzi API `Label is not available for this order` rekord `shipment_packages` jest oznaczany statusem `error` i zachowuje tresc bledu.
- 2026-03-08: Poprawiono fallback danych odbiorcy dla przesylek punktowych Apaczka (Orlen/InPost) - bez zmian schematu:
- brakujace dane adresowe odbiorcy sa uzupelniane na etapie budowania payloadu z danych zamowienia (`delivery`, `customer`) oraz metadanych punktu (`parcel_name`).
- 2026-03-08: Rozszerzono fallback adresu odbiorcy dla przesylek punktowych Apaczka - bez zmian schematu:
- serwis probuje uzupelnic adres punktu przez API `points` po `receiver_point_id`,
- przy dalszych brakach danych dla przesylki punktowej dopelniane jest minimum techniczne wymagane przez lokalna walidacje payloadu.
- 2026-03-08: Poprawiono przekazywanie punktow w payloadzie Apaczka (nadanie/odbior) - bez zmian schematu:
- payload wysyla aliasy identyfikatora punktu (`point`, `foreign_address_id`, `point_id`) dla zgodnosci z wariantami API.
- 2026-03-08: Uzupelniono payload odbioru kurierem Apaczka (`pickup.date`, `pickup.hours_from`, `pickup.hours_to`) - bez zmian schematu.
- 2026-03-08: Dodano migracje `20260308_000046_extend_company_settings_contact_person.sql`:
- rozszerzenie `company_settings` o `sender_contact_person` (osoba kontaktowa nadawcy),
- wykorzystywane w payloadzie Apaczka jako `address.sender.contact_person`.
- 2026-03-08: Ujednolicono styl naglowkow sekcji UI (`section-title`) - bez zmian schematu bazy.
## Tabele
@@ -218,9 +244,29 @@
- Kolumny:
- `id` (PK, tinyint unsigned),
- `integration_id` (int unsigned, UNIQUE, FK -> `integrations.id`),
- `app_id` (varchar 128, nullable),
- `app_secret_encrypted` (text, nullable),
- `api_key_encrypted` (text, nullable),
- `created_at`, `updated_at`.
### `carrier_delivery_method_mappings`
- Wspolne mapowanie form dostawy zamowien na providerow wysylek (model docelowy pod wielu kurierow: `allegro_wza`, `apaczka`, kolejne).
- Kolumny:
- `id` (PK, int unsigned, AI),
- `source_system` (varchar 32; np. `allegro`, `shoppro`),
- `source_integration_id` (int unsigned; `0` dla mapowan globalnych, np. Allegro),
- `order_delivery_method` (varchar 200),
- `provider` (varchar 50; np. `allegro_wza`, `apaczka`),
- `provider_service_id` (varchar 128),
- `provider_account_id` (varchar 128, nullable),
- `provider_carrier_id` (varchar 128, nullable),
- `provider_service_name` (varchar 255, nullable),
- `created_at`, `updated_at`.
- Indeksy:
- `carrier_dm_mapping_unique` (UNIQUE: `source_system`, `source_integration_id`, `order_delivery_method`),
- `carrier_dm_mapping_provider_idx` (`provider`),
- `carrier_dm_mapping_source_idx` (`source_system`, `source_integration_id`).
### `inpost_integration_settings`
- Tabela ustawien specyficznych InPost ShipX (`id = 1`); token API utrzymywany bazowo w `integrations.api_key_encrypted`.
- Kolumny:
@@ -238,6 +284,29 @@
- `weekend_delivery`, `auto_insurance_value`, `multi_parcel` (tinyint 0/1),
- `created_at`, `updated_at`.
### `company_settings`
- Ustawienia firmy/nadawcy wykorzystywane m.in. przy tworzeniu przesylek.
- Kolumny:
- `id` (PK, tinyint unsigned),
- `company_name` (varchar 200, nullable),
- `person_name` (varchar 200, nullable),
- `sender_contact_person` (varchar 200, nullable),
- `street` (varchar 200, nullable),
- `city` (varchar 128, nullable),
- `postal_code` (varchar 16, nullable),
- `country_code` (char 2, default `PL`),
- `phone` (varchar 64, nullable),
- `email` (varchar 128, nullable),
- `tax_number` (varchar 64, nullable),
- `bank_account` (varchar 64, nullable),
- `bank_owner_name` (varchar 200, nullable),
- `default_package_length_cm` (decimal 8,1),
- `default_package_width_cm` (decimal 8,1),
- `default_package_height_cm` (decimal 8,1),
- `default_package_weight_kg` (decimal 8,3),
- `default_label_format` (varchar 8),
- `created_at`, `updated_at`.
## Zasady aktualizacji
- Po kazdej migracji dopisz:
- nowe/zmienione tabele i kolumny,

View File

@@ -1,6 +1,101 @@
# Tech Changelog
## 2026-03-08
- Poprawiono date podjazdu kuriera w payloadzie Apaczka:
- `pickup.date` dla trybu `COURIER` jest normalizowane tak, aby nie wypadal w niedziele (niedziela -> poniedzialek),
- `pickup.hours_to` jest ograniczane do `16:00` (wg limitu API), a okno godzinowe jest korygowane do poprawnej relacji `hours_from < hours_to`,
- eliminuje blad API `Field PickupLocation->MaxPickupDate cannot be set to Sunday`.
- Dodano pole firmy `sender_contact_person` (osoba kontaktowa nadawcy):
- nowa migracja `20260308_000046_extend_company_settings_contact_person.sql`,
- UI `Ustawienia > Dane firmy` ma nowe pole `Osoba kontaktowa nadawcy`,
- `ApaczkaShipmentService` wysyla `contact_person` dla nadawcy z ustawien firmy.
- Uzupelniono kontakt odbiorcy w payloadzie Apaczka:
- `ApaczkaShipmentService` wysyla `receiver.contact_person` (fallback na dane odbiorcy/klienta z zamowienia),
- eliminuje blad API: `Osoba kontaktowa nadawcy/odbiorcy: Pole jest wymagane`.
- Dla tworzenia przesylek Apaczka dodano jawne pole `pickup.type` w payloadzie `order_send`:
- gdy podano `sender_point_id` ustawiane jest `SELF`,
- gdy brak punktu nadania i usluga dopuszcza odbior kurierem ustawiane jest `COURIER`.
- Poprawiono obsluge punktow nadania/odbioru w payloadzie Apaczka:
- adres `sender` i `receiver` wysyla teraz komplet aliasow punktu (`point`, `foreign_address_id`, `point_id`),
- rozszerzono diagnostyke dla bledu API `Niepoprawny sposob nadania przesylki` o wskazowke dot. `sender_point_id` / doboru uslugi.
- Wzmocniono fallback adresu odbiorcy dla przesylek punktowych Apaczka (Orlen/InPost):
- `ApaczkaShipmentService` probuje teraz dodatkowo uzupelnic adres punktu (`street`, `postal_code`, `city`) przez API `points` na podstawie `receiver_point_id`,
- jezeli zamowienie punktowe dalej nie ma kompletu danych adresowych, serwis uzupelnia techniczne minimum (`line1`, `city`, `postal_code`) zamiast blokowac tworzenie przesylki bledem walidacji lokalnej.
- Ujednolicono i wzmocniono naglowki sekcji UI (`h2/h3/h4.section-title`) w widokach:
- naglowki sekcyjne maja teraz wyrazniejszy styl (akcent lewy, delikatne tlo, obramowanie),
- zmiana jest globalna (SCSS), obejmuje m.in. `Zamowienia > Przygotuj przesylke` oraz pozostale ekrany korzystajace z `section-title`.
- Poprawiono fallback danych odbiorcy dla przesylek punktowych Apaczka (w tym Orlen Paczka):
- `ApaczkaShipmentService::buildReceiverAddress(...)` uzupelnia brakujace pola z wielu zrodel w kolejnosci:
- dane z formularza,
- adres `delivery` z zamowienia,
- dane punktu z `parcel_name` (`ulica`, `kod`, `miasto`),
- dane klienta (`name`, `phone`, `email`, `country`),
- adres ulicy sklada teraz `street_name + street_number`,
- naprawiono fallback `receiver_point_id` (uzywa `delivery.parcel_external_id`, usunieto bledne odwolanie do niezdefiniowanej zmiennej).
- Poprawiono obsluge usunietych/nieosiagalnych etykiet Apaczka:
- gdy API zwraca `Label is not available for this order`, rekord paczki jest oznaczany jako `error` i zapisywany jest `error_message`,
- dzieki temu przycisk etykiety nie jest ponownie pokazywany dla tego rekordu.
- Ujednolicono flow etykiet w `Zamowienia > Przygotuj przesylke` (dla wszystkich providerow):
- po statusie `created` etykieta jest generowana automatycznie przez cykliczne sprawdzanie statusu (backend probuje `downloadLabel`),
- UI nie pokazuje juz przycisku `Generuj etykiete`; do czasu gotowosci widoczny jest stan `Generowanie etykiety...`,
- przycisk `Pobierz` pojawia sie dopiero po zapisaniu pliku etykiety (`label_path`).
- Uzgodniono payload `order_send` Apaczka z dokumentacja API v2:
- `ApaczkaShipmentService` wysyla teraz strukture `address.sender/receiver` + `shipment[]` (`dimension1/2/3`, `weight` w kg),
- `cod` jest przekazywany jako obiekt (`amount`, `currency`), a wartosc ubezpieczenia przez `shipment_value` + `shipment_currency`,
- punkty sa przekazywane jako `foreign_address_id` (z aliasami diagnostycznymi),
- naprawilo to blad wyceny dla zamowienia testowego `#21` (utworzenie przesylki zakonczone sukcesem).
- Dodano techniczny skrypt diagnostyczny `tools/apaczka_probe_order.php`:
- wykonuje automatyczne proby `order_send` dla wskazanego zamowienia (bez klikania w UI),
- testuje kombinacje uslug i wariantow pol punktu, raportujac sukces/blad per proba.
- Rozszerzono payload punktow w tworzeniu przesylki Apaczka:
- oprocz `point` przekazywane sa teraz aliasy `foreign_address_id` i `point_id` (dla odbiorcy i nadawcy),
- cel: kompatybilnosc z wariantami API wymagajacymi innej nazwy pola punktu.
- Korekta walidacji punktu odbioru Apaczka:
- usunieto twarde blokowanie tworzenia przesylki na podstawie prefiksu punktu (`POP-`),
- informacja o prefiksie punktu pozostaje tylko jako sugestia diagnostyczna.
- Poprawiono prefill danych odbiorcy na ekranie `Zamowienia > Przygotuj przesylke`:
- `ShipmentController` dla dostaw do punktu (`parcel_external_id`/`parcel_name`) ustawia `receiver_name` na dane klienta (`address_type=customer`),
- eliminuje przypadek podstawiania nazwy punktu/metody dostawy w polu `Imie i nazwisko`.
- Poprawiono diagnostyke bledow tworzenia przesylki Apaczka:
- `ApaczkaShipmentService` przekazuje teraz `receiver_point_id` do payloadu `receiver.point` (oraz `sender_point_id` do `sender.point`),
- dodano walidacje wymagan uslugi na podstawie `service_structure` (np. wymagany punkt odbioru/nadania),
- dla bledu API `Brak wyceny dla podanych parametrów zamówienia` komunikat zawiera rozszerzona diagnostyke (service_id/nazwa/supplier, punkt odbioru/nadania, gabaryt/waga) i hint o niedopasowaniu uslugi do typu punktu.
- Poprawiono import danych faktury z shopPRO:
- `ShopproOrdersSyncService` wykrywa fakture nie tylko po `is_invoice`/`invoice.required`, ale takze po danych firmowych (`firm_name`/`firm_nip`),
- `ShopproOrdersSyncService::mapAddresses(...)` zapisuje adres `invoice` (firma, NIP, adres) na podstawie pol `invoice`/`billing*`/`firm_*`,
- widok `orders/show` wyswietla teraz `company_name` i `company_tax_number` dla adresu faktury.
- Fix prewyboru uslugi Apaczka na ekranie `Zamowienia > Przygotuj przesylke`:
- widok `resources/views/shipments/prepare.php` odczytuje ID uslugi Apaczka z fallbackiem `service_id -> id`,
- naprawia przypadek, gdy przewoznik (`Apaczka`) byl wybierany poprawnie, ale usluga dostawy pozostawala pusta mimo mapowania.
- Poprawiono diagnostyke mapowania form dostawy na ekranie `Zamowienia > Przygotuj przesylke`:
- `ShipmentController` zwraca teraz komunikat diagnostyczny, gdy brak mapowania metody dostawy,
- komunikat rozroznia brak mapowan dla instancji `shopPRO` (`source_integration_id`) od braku mapowania konkretnej metody,
- widok `resources/views/shipments/prepare.php` wyswietla ten komunikat bezposrednio pod informacja o metodzie z zamowienia.
- Poprawiono UX wyszukiwania w selectach mapowania form dostawy (zakladki `Formy dostawy`):
- `resources/views/settings/allegro.php` przeszlo z przebudowy opcji `<select>` na tryb bezpieczny (`focus first match` bez modyfikacji listy opcji),
- eliminuje przypadki „znikajacych” opcji i problem z wyborem uslugi po zmianie przewoznika na `Apaczka`,
- ujednolicono zachowanie z `resources/views/settings/shoppro.php`.
- Poprawiono inicjalizacje stanu mapowania przewoznika (`allegro.php`, `shoppro.php`):
- dla niezamapowanych form domyslny przewoznik to teraz pusty wybor (zamiast `allegro`),
- panel uslugi (`Allegro/InPost/Apaczka/pusty`) jest synchronizowany na starcie z realna wartoscia selecta przewoznika (`showPanel(carrierSelect.value)`),
- usunieto pozostaly po refaktorze odwolanie do nieistniejacej zmiennej `$currentAllegroId` (zastapione `$currentMethodId`).
- Dodano architekture provider-agnostic dla wysylek:
- nowy kontrakt `ShipmentProviderInterface`,
- nowy rejestr `ShipmentProviderRegistry`,
- `ShipmentController` wybiera providera dynamicznie (`allegro_wza` / `apaczka`) przy tworzeniu przesylki, sprawdzaniu statusu i pobieraniu etykiety.
- Dodano integracje API Apaczka v2:
- nowy klient `App\Modules\Settings\ApaczkaApiClient` (`service_structure`, `order_send`, `order_details`, `waybill`, `points`),
- nowy serwis wysylkowy `App\Modules\Shipments\ApaczkaShipmentService`,
- rozszerzone `Ustawienia > Integracje > Apaczka` o pola `App ID`, `App Secret` oraz test polaczenia (`POST /settings/integrations/apaczka/test`).
- poprawiono format podpisu/requestu zgodnie z API v2 (`app_id:route:request_json:expires`, endpointy URL zamiast pola `method`), co naprawia blad testu polaczenia (`brak JSON`).
- Dodano wspolny model mapowania form dostawy dla wielu providerow:
- nowa tabela `carrier_delivery_method_mappings` (migracja `20260308_000044_create_carrier_delivery_method_mappings_table.sql`),
- nowy repo `CarrierDeliveryMethodMappingRepository`,
- backfill danych z tabel legacy (`allegro_delivery_method_mappings`, `shoppro_delivery_method_mappings`),
- zakladki `Formy dostawy` w Allegro i shopPRO obsluguja mapowanie na `allegro_wza` i `apaczka`.
- Dodano migracje `20260308_000045_extend_apaczka_credentials.sql`:
- rozszerzenie `apaczka_integration_settings` o `app_id` i `app_secret_encrypted`,
- migracja danych legacy sekretu z `api_key_encrypted`.
- Dodano zakladke `Formy dostawy` dla integracji `shopPRO` (analogicznie do Allegro):
- nowy endpoint `POST /settings/integrations/shoppro/delivery/save`,
- mapowanie per instancja: forma dostawy shopPRO -> usluga dostawy Allegro/InPost WZA,