diff --git a/.paul/PROJECT.md b/.paul/PROJECT.md index 034922d..b5c6325 100644 --- a/.paul/PROJECT.md +++ b/.paul/PROJECT.md @@ -106,6 +106,7 @@ Sprzedawca moĹĽe obsĹ‚ugiwać zamĂłwienia ze wszystkich kanałów - [x] Wizualna flaga wiekowa na liscie zamowien: czerwona ramka o rosnacej intensywnosci dla zamowien 4-7+ dniowych — Phase 101 - [x] Naprawa tworzenia przesylek Apaczka dla dlugich adresow: auto-truncate dla uslug punktowych (ORLEN/Paczkomat), walidacja + blad dla uslug kurierskich — Phase 102 - [x] Naprawa auto-click etykiety po utworzeniu przesylki: klik na najnowsza paczke zamiast najstarszej (buttons[0] vs buttons[length-1]) — Phase 103 +- [x] Apaczka Paczka w Weekend: checkbox "Dostawa w weekend (sobota)" dla uslug InPost paczkomatowych + mapowanie pole formularza weekend_delivery -> option[19] w API Apaczki — Phase 104 - [ ] Eliminacja zduplikowanego kodu: SslCertificateResolver, ToggleableRepositoryTrait, RedirectPathResolver, ReceiptService — Phase 68 ### Active (In Progress) @@ -208,6 +209,6 @@ Quick Reference: --- *PROJECT.md — Updated when requirements or context change* -*Last updated: 2026-04-11 after Phase 96 completion (Automation Payment Method Condition)* +*Last updated: 2026-04-17 after Phase 104 completion (Apaczka Weekend Delivery)* diff --git a/.paul/ROADMAP.md b/.paul/ROADMAP.md index 6599b8d..060b8d8 100644 --- a/.paul/ROADMAP.md +++ b/.paul/ROADMAP.md @@ -64,6 +64,7 @@ Wersja mobilna aplikacji, modul po module. Cel: pelna uzywalnosc orderPRO na tel | 101 | Aged Orders Row Highlight | 1/1 | Complete | | 102 | Apaczka Receiver Street Length | 1/1 | Complete | | 103 | Print Autoclick Fix | 1/1 | Complete | +| 104 | Apaczka Weekend Delivery | 1/1 | Complete | | TBD | Mobile Orders List | - | Not started | | TBD | Mobile Order Details | - | Not started | | TBD | Mobile Settings | - | Not started | @@ -387,4 +388,4 @@ Archive: `.paul/milestones/v0.1-ROADMAP.md` --- *Roadmap created: 2026-03-12* -*Last updated: 2026-04-11 - phase 96 unified (Automation Payment Method Condition)* +*Last updated: 2026-04-17 - phase 104 unified (Apaczka Weekend Delivery)* diff --git a/.paul/STATE.md b/.paul/STATE.md index 06ce03d..da95262 100644 --- a/.paul/STATE.md +++ b/.paul/STATE.md @@ -2,22 +2,22 @@ ## Project Reference -See: .paul/PROJECT.md (updated 2026-04-12) +See: .paul/PROJECT.md (updated 2026-04-17) **Core value:** Sprzedawca moze obslugiwac zamowienia ze wszystkich kanalow sprzedazy i nadawac przesylki bez przelaczania sie miedzy platformami. -**Current focus:** Milestone v3.0 - Phase 97 complete, ready for next phase +**Current focus:** Milestone v3.0 - Phase 104 complete, ready for next phase ## Current Position Milestone: v3.0 Mobile Responsive - In progress -Phase: 103 (Print Autoclick Fix) — Complete -Plan: 103-01 Complete +Phase: 104 (Apaczka Weekend Delivery) — Complete +Plan: 104-01 Complete Status: Loop closed, ready for next PLAN -Last activity: 2026-04-16 — UNIFY Phase 103 complete +Last activity: 2026-04-17 — UNIFY Phase 104 complete Progress: - Milestone: [#########.] ~96% -- Phase 103: [##########] 100% +- Phase 104: [##########] 100% ## Loop Position @@ -29,7 +29,7 @@ PLAN ──▶ APPLY ──▶ UNIFY ## Session Continuity -Last session: 2026-04-16 -Stopped at: Phase 103 Complete +Last session: 2026-04-17 +Stopped at: Phase 104 Complete Next action: /paul:plan dla kolejnej fazy -Resume file: .paul/phases/103-print-autoclick-fix/103-01-SUMMARY.md +Resume file: .paul/phases/104-apaczka-weekend-delivery/104-01-SUMMARY.md diff --git a/.paul/changelog/2026-04-17.md b/.paul/changelog/2026-04-17.md new file mode 100644 index 0000000..1e5cec1 --- /dev/null +++ b/.paul/changelog/2026-04-17.md @@ -0,0 +1,25 @@ +# 2026-04-17 + +## Co zrobiono + +- [Phase 104, Plan 01] Apaczka Weekend Delivery — opcjonalna usluga "Paczka w Weekend" dla przesylek Apaczki paczkomatowych InPost +- Backend: `ApaczkaShipmentService::buildOptionsPayload()` mapuje pole `weekend_delivery` na `option[19] = 1` w payloadzie API Apaczki +- Stala `OPTION_KEYS = ['weekend_delivery' => 19]` jako rozszerzalne mapowanie pole formularza -> id opcji Apaczki +- Frontend: checkbox "Dostawa w weekend (sobota)" w formularzu prepare.php widoczny tylko dla supplier=INPOST + paczkomat (door_to_point=1 lub point_to_point=1) +- JS toggle oparty na atrybutach `data-supplier`/`data-paczkomat` na +
Wybierz przewoznika
@@ -601,6 +614,21 @@ $defaultCodAmount = $isCod ? number_format($totalWithTax, 2, '.', '') : '0'; if (providerInput) providerInput.value = carrier === 'apaczka' ? 'apaczka' : 'allegro_wza'; } + var weekendWrap = document.getElementById('shipment-apaczka-weekend-wrap'); + var weekendInput = document.getElementById('shipment-apaczka-weekend'); + function toggleWeekendOption() { + if (!weekendWrap || !weekendInput) return; + var carrierActive = carrierSelect ? carrierSelect.value === 'apaczka' : false; + var opt = apaczkaSelect ? apaczkaSelect.options[apaczkaSelect.selectedIndex] : null; + var supplier = (opt && opt.getAttribute('data-supplier')) || ''; + var paczkomat = (opt && opt.getAttribute('data-paczkomat')) === '1'; + var visible = carrierActive && supplier === 'INPOST' && paczkomat; + weekendWrap.style.display = visible ? '' : 'none'; + if (!visible) { + weekendInput.checked = false; + } + } + carrierSelect.addEventListener('change', function () { clearHiddenFields(); if (searchInput) searchInput.value = ''; @@ -614,6 +642,7 @@ $defaultCodAmount = $isCod ? number_format($totalWithTax, 2, '.', '') : '0'; } allegroOpts.forEach(function (o) { o.classList.remove('is-selected'); }); showPanel(carrierSelect.value); + toggleWeekendOption(); }); if (inpostSelect) { @@ -639,10 +668,12 @@ $defaultCodAmount = $isCod ? number_format($totalWithTax, 2, '.', '') : '0'; if (providerInput) providerInput.value = 'apaczka'; } apaczkaSelect.addEventListener('change', syncApaczkaFields); + apaczkaSelect.addEventListener('change', toggleWeekendOption); if (carrierSelect.value === 'apaczka' && apaczkaSelect.value !== '') { syncApaczkaFields(); } } + toggleWeekendOption(); if (wrapper && searchInput && dropdown) { var isAllegroOpen = false; diff --git a/src/Modules/Shipments/ApaczkaShipmentService.php b/src/Modules/Shipments/ApaczkaShipmentService.php index 66bdc97..69b3b3a 100644 --- a/src/Modules/Shipments/ApaczkaShipmentService.php +++ b/src/Modules/Shipments/ApaczkaShipmentService.php @@ -15,6 +15,15 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface { private const PICKUP_DATE_RETRY_DAYS = 7; + /** + * Mapowanie pol formularza na klucze opcji API Apaczki (option[]). + * Wartosci kluczy to identyfikatory z service_structure.response.options. + * - 19 = dostawa w sobote (InPost Paczka w Weekend) + */ + private const OPTION_KEYS = [ + 'weekend_delivery' => 19, + ]; + /** * @var array */ @@ -100,6 +109,10 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface 'content' => 'orderPRO ' . ($sourceOrderId !== '' ? $sourceOrderId : (string) $orderId), 'comment' => 'orderPRO ' . ($sourceOrderId !== '' ? $sourceOrderId : (string) $orderId), ]; + $options = $this->buildOptionsPayload($formData); + if ($options !== []) { + $apiPayload['option'] = $options; + } $pickup = $this->buildPickupPayload($serviceDefinition, $senderPointId, $formData); if ($pickup !== []) { $apiPayload['pickup'] = $pickup; @@ -818,6 +831,24 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface return 'COURIER'; } + /** + * @param array $formData + * @return array + */ + private function buildOptionsPayload(array $formData): array + { + $result = []; + foreach (self::OPTION_KEYS as $formField => $apiOptionId) { + $value = $formData[$formField] ?? null; + $isTruthy = filter_var($value, FILTER_VALIDATE_BOOL, FILTER_NULL_ON_FAILURE); + if ($isTruthy === true) { + $result[$apiOptionId] = 1; + } + } + + return $result; + } + /** * @param array|null $serviceDefinition * @param array $formData diff --git a/src/Modules/Shipments/ShipmentController.php b/src/Modules/Shipments/ShipmentController.php index 35321e8..b91b5be 100644 --- a/src/Modules/Shipments/ShipmentController.php +++ b/src/Modules/Shipments/ShipmentController.php @@ -204,6 +204,7 @@ final class ShipmentController 'receiver_email' => (string) $request->input('receiver_email', ''), 'receiver_point_id' => (string) $request->input('receiver_point_id', ''), 'sender_point_id' => (string) $request->input('sender_point_id', ''), + 'weekend_delivery' => (string) $request->input('weekend_delivery', ''), ]); $packageId = (int) ($result['package_id'] ?? 0); diff --git a/tests/Unit/ApaczkaShipmentServiceTest.php b/tests/Unit/ApaczkaShipmentServiceTest.php index e1dad1b..c52c2e4 100644 --- a/tests/Unit/ApaczkaShipmentServiceTest.php +++ b/tests/Unit/ApaczkaShipmentServiceTest.php @@ -43,6 +43,20 @@ final class ApaczkaShipmentServiceTest extends TestCase $method->invoke($this->service, $street); } + /** + * @param array $formData + * @return array + */ + private function invokeBuildOptions(array $formData): array + { + $method = new ReflectionMethod(ApaczkaShipmentService::class, 'buildOptionsPayload'); + $method->setAccessible(true); + /** @var array $result */ + $result = $method->invoke($this->service, $formData); + + return $result; + } + public function testTruncateStreetForPointShortensLongValue(): void { $input = 'Punkt odbioru POP-XYZ123 przy al. Jerozolimskich 55A/12'; @@ -107,4 +121,19 @@ final class ApaczkaShipmentServiceTest extends TestCase $this->invokeAssert('Ul. Generała Pilota Józefa Kowalskiego 6/1'); } + + public function testBuildOptionsPayloadWeekendEnabled(): void + { + $this->assertSame([19 => 1], $this->invokeBuildOptions(['weekend_delivery' => '1'])); + } + + public function testBuildOptionsPayloadWeekendDisabled(): void + { + $this->assertSame([], $this->invokeBuildOptions(['weekend_delivery' => '0'])); + } + + public function testBuildOptionsPayloadEmptyForm(): void + { + $this->assertSame([], $this->invokeBuildOptions([])); + } }