9.2 KiB
9.2 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, delegation
| phase | plan | type | wave | depends_on | files_modified | autonomous | delegation | ||
|---|---|---|---|---|---|---|---|---|---|
| 102-apaczka-receiver-street-length | 01 | execute | 1 |
|
true | off |
Purpose
Zamowienie OP/ID=372 (Klaudia Florek-Mach, Ul. Generała Pilota Józefa Kowalskiego 6/1 = 42 znaki, ORLEN Paczka) blokuje tworzenie przesylki. Automatyczne obcinanie jest bezpieczne dla punktow odbioru (street jest tylko labelem), ale NIE dla kuriera — moglibysmy uciac numer domu/mieszkania i paczka trafilaby w zle miejsce.
Output
ApaczkaShipmentService::buildReceiverAddress()rozroznia tryby i stosuje wlasciwa strategie- Dwa helpery:
truncateStreetForPoint()i walidacja dla kuriera - Unit testy pokrywajace oba scenariusze + edge cases
Source Files
@src/Modules/Shipments/ApaczkaShipmentService.php @src/Core/Exceptions/ApaczkaApiException.php
<acceptance_criteria>
AC-1: Usluga punktowa z dlugim street — auto-truncate
Given zamowienie z `receiver_point_id` = "POP-XYZ123" i street odbiorcy > 30 znakow (np. "Punkt odbioru POP-XYZ123 przy al. Jerozolimskich")
When ApaczkaShipmentService buduje receiver payload
Then receiver.line1 jest obcinane do 30 znakow (mb_substr + rtrim), request do API przechodzi
AC-2: Usluga kurierska z dlugim street — walidacja + blad
Given zamowienie bez `receiver_point_id` i street > 30 znakow (np. "Ul. Generała Pilota Józefa Kowalskiego 6/1" = 42 znaki)
When ApaczkaShipmentService buduje receiver payload
Then rzucany jest ApaczkaApiException z komunikatem "Ulica odbiorcy przekracza 30 znakow (limit API Apaczka dla uslug kurierskich). Skroc adres recznie przed utworzeniem przesylki. Obecna wartosc: {N} znakow: {street}"
And request do API Apaczka NIE jest wykonywany
AC-3: Krotki street — bez zmian (oba tryby)
Given street <= 30 znakow (np. "Polna 5")
When buduje receiver payload (usluga punktowa albo kurierska)
Then receiver.line1 = wartosc bez modyfikacji
AC-4: Adres dokladnie 30 znakow — bez zmian
Given street o dlugosci dokladnie 30 znakow
When buduje receiver payload
Then receiver.line1 pozostaje 30 znakow, bez obcinania, bez wyjatku
AC-5: Unit testy pokrywaja wszystkie AC
Given ApaczkaShipmentServiceTest
When uruchamiamy vendor/bin/phpunit --filter ApaczkaShipmentServiceTest
Then testy dla AC-1 (point truncate), AC-2 (courier throws), AC-3 (short passthrough), AC-4 (boundary 30) przechodza na zielono
</acceptance_criteria>
Task 1: Rozroznienie point vs courier w buildReceiverAddress + helpery src/Modules/Shipments/ApaczkaShipmentService.php W `buildReceiverAddress()` po wyliczeniu `$street` a przed wstawieniem do `$receiver['line1']`:1. Wyznacz tryb: `$isPointDelivery = $receiverPointId !== '';` (zmienna juz istnieje w metodzie).
2. Zastosuj strategie zaleznie od trybu:
- Point: `$street = $this->truncateStreetForPoint($street);`
- Courier: `$this->assertStreetWithinCourierLimit($street);` (rzuca ApaczkaApiException jesli > 30)
3. Dodaj dwie prywatne metody:
```php
/**
* Apaczka API: receiver.street limit 30 znakow.
* Dla uslug punktowych (ORLEN/Paczkomat) street to etykieta punktu — obcinamy bezpiecznie.
*/
private function truncateStreetForPoint(string $street): string
{
$street = trim($street);
if (mb_strlen($street, 'UTF-8') <= 30) {
return $street;
}
return rtrim(mb_substr($street, 0, 30, 'UTF-8'));
}
/**
* Apaczka API: receiver.street limit 30 znakow.
* Dla uslug kurierskich NIE obcinamy — ryzyko utraty numeru domu/mieszkania.
* Operator musi skrocic adres recznie w formularzu.
*/
private function assertStreetWithinCourierLimit(string $street): void
{
$length = mb_strlen($street, 'UTF-8');
if ($length <= 30) {
return;
}
throw new ApaczkaApiException(sprintf(
'Ulica odbiorcy przekracza 30 znakow (limit API Apaczka dla uslug kurierskich). '
. 'Skroc adres recznie przed utworzeniem przesylki. Obecna wartosc: %d znakow: "%s"',
$length,
$street
));
}
```
4. Uzyj `mb_strlen`/`mb_substr` z jawnym `'UTF-8'` (polskie znaki).
5. Upewnij sie, ze `ApaczkaApiException` jest zaimportowane w `use`.
Avoid:
- `substr()`/`strlen()` bez `mb_` (psuje UTF-8)
- Automatyczne obcinanie w trybie kuriera (ryzyko utraty numeru)
- Modyfikacja innych pol odbiorcy
- Zmiana sygnatury `buildReceiverAddress`
grep -nE "truncateStreetForPoint|assertStreetWithinCourierLimit|isPointDelivery" src/Modules/Shipments/ApaczkaShipmentService.php — widoczne wywolania + definicje
AC-1, AC-2, AC-3, AC-4 spelnione
Task 2: Unit testy truncation point + walidacja courier
tests/Unit/Modules/Shipments/ApaczkaShipmentServiceTest.php
Dodaj/rozszerz testy pokrywajace logike street length:
**Helper access:** Jesli `truncateStreetForPoint` / `assertStreetWithinCourierLimit` sa private — uzyj `ReflectionMethod::setAccessible(true)`.
**Test cases:**
1. `testTruncateStreetForPointShortensLongValue` — input 45 znakow → output mb_strlen = 30
2. `testTruncateStreetForPointPreservesShortValue` — "Polna 5" → "Polna 5" bez zmian
3. `testTruncateStreetForPointBoundary30` — 30 znakow → 30 znakow (bez zmian)
4. `testTruncateStreetForPointUtf8Safe` — polskie znaki (35 znakow z ą/ę/ł) → mb_strlen = 30, bez uszkodzonych bajtow (sprawdz `mb_check_encoding($result, 'UTF-8')`)
5. `testTruncateStreetForPointRtrimTrailingSpace` — gdy znak 30 to spacja, wynik bez koncowej spacji
6. `testAssertStreetWithinCourierLimitAcceptsShort` — "Polna 5" → brak wyjatku
7. `testAssertStreetWithinCourierLimitAcceptsBoundary30` — 30 znakow → brak wyjatku
8. `testAssertStreetWithinCourierLimitRejectsLong` — "Ul. Generała Pilota Józefa Kowalskiego 6/1" (42 znaki) → `ApaczkaApiException` z komunikatem zawierajacym "przekracza 30 znakow" (PHPUnit `expectException` + `expectExceptionMessageMatches`)
Uzyj `dg/bypass-finals` jesli klasa jest final.
Avoid: integration testy (prawdziwe API), mockowanie calego flow order import.
vendor/bin/phpunit --filter ApaczkaShipmentServiceTest
AC-5 spelnione
DO NOT CHANGE
- Pozostale pola receiver (name, city, postal_code, country_code, phone, email) — nie ruszac
buildSenderAddressi sender logic — poza zakresemvalidateServiceRequirements,resolvePointAddress,applyPointIdentifiers— nie ruszac- Struktura payloadu API Apaczka (klucze: line1, line2, city, postal_code, ...)
- Inne providery (InPost ShipX, Allegro WZA) — poza zakresem
- UI/formularz przygotowania przesylki — brak zmian w widokach i kontrolerze
SCOPE LIMITS
- Tylko pole
receiver.street/line1dla Apaczka - Brak obslugi innych limitow dlugosci (name, city — jesli wystapia, osobne fazy)
- Brak automatycznego truncate w trybie kuriera (operator skraca recznie — celowa decyzja)
- Brak nowych komunikatow Flash/toast (blad przechodzi przez istniejacy kanal ApaczkaApiException -> ShipmentController)
<success_criteria>
- Usluga punktowa z dlugim street: przesylka tworzona pomyslnie (auto-truncate)
- Usluga kurierska z dlugim street: jasny komunikat dla operatora, brak ryzyka utraty numeru domu
- Krotkie adresy (<=30): obie sciezki bez zmian
- Unit testy pokrywaja 8 przypadkow
- Zero regresji w innych metodach serwisu </success_criteria>