Files
orderPRO/.paul/phases/130-erli-shipments-labels/130-01-PLAN.md

14 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, delegation
phase plan type wave depends_on files_modified autonomous delegation
130-erli-shipments-labels 01 execute 1
src/Core/Constants/IntegrationSources.php
src/Modules/Settings/ErliApiClient.php
src/Modules/Settings/ErliDeliveryMappingController.php
src/Modules/Settings/ErliIntegrationController.php
src/Modules/Settings/CarrierDeliveryMethodMappingRepository.php
src/Modules/Settings/ErliExternalShipmentService.php
src/Modules/Shipments/ShipmentController.php
routes/web.php
resources/views/settings/erli.php
resources/views/shipments/prepare.php
resources/lang/pl.php
tests/Unit/ErliExternalShipmentServiceTest.php
DOCS/DB_SCHEMA.md
DOCS/ARCHITECTURE.md
DOCS/TECH_CHANGELOG.md
true auto
## Goal Dodac obsluge przesylek dla zamowien Erli: mapowanie metod dostawy w osobnej zakladce ustawien, uzycie istniejacych providerow etykiet (InPost/Apaczka tam, gdzie sa dostepne), zapis paczek w `shipment_packages` oraz rejestracje numeru nadania w Erli przez natywny endpoint przesylek zewnetrznych.

Purpose

Sprzedawca ma nadawac zamowienia Erli z orderPRO bez przelaczania sie do panelu marketplace, ale bez wymuszania nadawania "na umowie Erli". Natywne Erli w tym planie oznacza wykorzystanie oficjalnych slownikow/cennikow/shipping API tam, gdzie pasuja do wlasnych umow operatora.

Output

Nowa zakladka dostaw w /settings/integrations/erli, rozszerzony Erli API client, flow tworzenia etykiety dla zmapowanych zamowien Erli oraz synchronizacja paczki zewnetrznej do Erli po uzyskaniu numeru przesylki.

- **Natywne Erli** - Czy probujemy najpierw API shipping Erli, czy od razu tylko istniejacy provider etykiet? -> Odpowiedz: Trzeba sprobowac natywnego z erli. - **Konfiguracja** - Gdzie operator ma mapowac metody dostawy Erli? -> Odpowiedz: zakladka. - **Umowa/cenniki** - Czy nadawac przez Erli na ich umowie, czy tylko to, co da sie spiac z wlasnymi providerami/cennikami? -> Odpowiedz: Nie chce nadawac przez Erli na ich umowie, to co sie da. Tak jak allegro ma swoje cenniki.

Project Context

@.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md @.paul/codebase/architecture.md @.paul/codebase/db_schema.md @AGENTS.md

Prior Work

@.paul/phases/127-erli-integration-foundation/127-01-SUMMARY.md @.paul/phases/128-erli-orders-import/128-01-SUMMARY.md @.paul/phases/129-erli-status-mapping-sync/129-01-SUMMARY.md

External Contract

@https://erli.pl/svc/shop-api/doc/swagger.json

Notes from official swagger checked during planning:

  • GET /dictionaries/shippingMethods, GET /dictionaries/deliveryMethods, GET /dictionaries/deliveryVendors, GET /delivery/priceLists, GET /delivery/priceListsDetails expose Erli shipping/delivery dictionaries and cenniki.
  • POST /shipping/external creates external parcels with orderId, vendor, status, trackingNumber.
  • POST /shipping/parcels/ creates Erli parcels, but this path is treated as optional/discovery only because the user does not want to ship on Erli's carrier agreement.
  • No label-download endpoint was found in the swagger path list; local label generation must continue through existing provider services unless APPLY finds a documented endpoint with compatible contract.

Source Files

@src/Modules/Settings/ErliApiClient.php @src/Modules/Settings/ErliIntegrationController.php @src/Modules/Settings/CarrierDeliveryMethodMappingRepository.php @src/Modules/Settings/AllegroDeliveryMappingController.php @src/Modules/Shipments/ShipmentController.php @src/Modules/Shipments/ShipmentProviderInterface.php @src/Modules/Shipments/InpostShipmentService.php @src/Modules/Shipments/ApaczkaShipmentService.php @resources/views/settings/erli.php @resources/views/shipments/prepare.php @routes/web.php @DOCS/DB_SCHEMA.md @DOCS/ARCHITECTURE.md

## Required Skills (from SPECIAL-FLOWS.md)
Skill Priority When to Invoke Loaded?
sonar-scanner required Po APPLY, przed UNIFY
/feature-dev optional Przed implementacja integracji marketplace/shipping
/frontend-design optional Przy dodaniu zakladki UI w ustawieniach Erli
/code-review optional Po implementacji, przed UNIFY

BLOCKING: Required sonar-scanner must be attempted before UNIFY. If CLI is still unavailable in PATH, document the gap in SUMMARY and STATE like Phase 128/129.

Skill Invocation Checklist

  • sonar-scanner attempted after APPLY
  • Optional flows considered if implementation risk warrants them

<acceptance_criteria>

AC-1: Erli Shipping Contract Is Used Where Safe

Given Erli API credentials are configured
When orderPRO loads shipment configuration for Erli
Then it can fetch Erli shipping/delivery dictionaries, delivery vendors and price list data from the official Erli API
And it does not assume native Erli label download exists unless a documented endpoint is confirmed during implementation.

AC-2: Erli Delivery Mapping Tab Exists

Given the operator opens /settings/integrations/erli
When they select the delivery/shipping tab
Then they see distinct Erli delivery methods from imported orders plus Erli dictionary context
And they can map each method to an available local label provider/service and Erli vendor with a CSRF-protected save form.

AC-3: Erli Orders Preselect Shipment Provider

Given an Erli order has a saved delivery mapping
When the operator opens the shipment prepare page for that order
Then orderPRO preselects the mapped provider/service and shows a clear unmapped diagnostic if no mapping exists.

AC-4: Labels Are Generated Without Erli Carrier Agreement

Given an Erli order is mapped to an existing local provider such as InPost or Apaczka
When the operator creates a shipment
Then the existing provider creates the local shipment package, stores it in shipment_packages and makes the label available for download/print queue
And the flow does not create Erli-contract parcels unless explicitly supported and selected in future work.

AC-5: External Parcel Is Registered In Erli

Given a local Erli shipment package has a tracking number and a mapped Erli vendor
When the package creation/status check reaches a label-ready or sent state
Then orderPRO calls POST /shipping/external with order id, vendor, status and tracking number
And API failures are logged as non-critical local shipment warnings rather than losing the label.

AC-6: Documentation And Verification Cover The Flow

Given the implementation is complete
When verification runs
Then PHP syntax checks, focused tests or documented PHPUnit gap, diff checks and documentation updates cover the new Erli shipment behavior.

</acceptance_criteria>

Task 1: Extend Erli API and mapping repository for shipping src/Core/Constants/IntegrationSources.php, src/Modules/Settings/ErliApiClient.php, src/Modules/Settings/CarrierDeliveryMethodMappingRepository.php, DOCS/DB_SCHEMA.md, DOCS/ARCHITECTURE.md Add `erli` as an explicit integration source constant/path wherever current generic delivery mappings normalize only `allegro` and `shoppro`. Extend `CarrierDeliveryMethodMappingRepository` so `listMappings`, `findByOrderMethod`, `saveMappings`, `hasMappingsForSource` and `getDistinctOrderDeliveryMethods` work for `source_system='erli'` and global `source_integration_id=0`. Extend `ErliApiClient` with small focused methods for shipping dictionaries and external parcels: - `getShippingMethods()` - `getDeliveryMethods()` - `getDeliveryVendors()` - `getPriceLists()` / `getPriceListsDetails()` if the response is needed for operator context - `createExternalParcel(array $payload)` Keep request/response handling consistent with existing Erli client methods and keep runtime on `DB_HOST`, never `DB_HOST_REMOTE`. Do not add a new table unless APPLY proves existing `carrier_delivery_method_mappings` cannot represent the mapping. If a schema change becomes unavoidable, add a migration and update DB docs in the same task. `C:\xampp\php\php.exe -l src/Modules/Settings/ErliApiClient.php` and `C:\xampp\php\php.exe -l src/Modules/Settings/CarrierDeliveryMethodMappingRepository.php`; repository can list/save/find Erli mappings without falling back to Allegro. AC-1 foundation complete and AC-2 persistence ready. Task 2: Add Erli delivery mapping tab src/Modules/Settings/ErliDeliveryMappingController.php, src/Modules/Settings/ErliIntegrationController.php, routes/web.php, resources/views/settings/erli.php, resources/lang/pl.php, DOCS/ARCHITECTURE.md Create or wire a focused Erli delivery mapping controller, following the clarity of `AllegroDeliveryMappingController` but without Allegro OAuth assumptions. Load: - distinct Erli delivery methods from imported orders, - current `carrier_delivery_method_mappings` rows for `erli`, - available local label provider services already supported by the shipment flow, - Erli vendors/dictionaries for choosing the vendor sent to `/shipping/external`. Add a new Erli settings tab (for example `delivery`) next to existing integration/status/settings tabs. Saving must use POST + `_token`, `Flash`, bounded validation and redirect back to `/settings/integrations/erli?tab=delivery`. Escape all view output with `$e()`, avoid inline CSS in the view, and do not add native `alert()`/`confirm()`. `C:\xampp\php\php.exe -l src/Modules/Settings/ErliDeliveryMappingController.php`, `C:\xampp\php\php.exe -l resources/views/settings/erli.php`, and manual route smoke: opening `/settings/integrations/erli?tab=delivery` renders the tab even when Erli API metadata fetch fails. AC-2 satisfied; UI is consistent with Phase 129 tab pattern. Task 3: Use mappings during shipment creation and sync external parcel to Erli src/Modules/Shipments/ShipmentController.php, src/Modules/Settings/ErliExternalShipmentService.php, resources/views/shipments/prepare.php, routes/web.php, tests/Unit/ErliExternalShipmentServiceTest.php, DOCS/ARCHITECTURE.md, DOCS/TECH_CHANGELOG.md Update shipment prepare flow so Erli orders are eligible for `CarrierDeliveryMethodMappingRepository::findByOrderMethod('erli', 0, ...)` just like Allegro/shopPRO. Ensure the mapped provider/service can preselect existing local provider forms. Preserve existing Allegro/shopPRO behavior. Add an `ErliExternalShipmentService` that reads the local package/order context and calls `ErliApiClient::createExternalParcel()` with: - Erli external order id, - mapped Erli vendor, - tracking number from `shipment_packages`, - status matching Erli's accepted external parcel status contract. Trigger this service after a local provider has produced a tracking number/label-ready package (for example from `checkStatus()` and/or label-ready creation path), and make the call idempotent enough for retries by treating duplicate/already-existing responses as non-fatal where Erli exposes that signal. Log or flash bounded warnings for Erli sync failure but never discard the local label. Add focused unit coverage for payload building and failure behavior. If PHPUnit remains unavailable, leave the test file and document the run gap. `C:\xampp\php\php.exe -l src/Modules/Shipments/ShipmentController.php`; `C:\xampp\php\php.exe -l src/Modules/Settings/ErliExternalShipmentService.php`; if dependencies exist, run `vendor/bin/phpunit tests/Unit/ErliExternalShipmentServiceTest.php`; manual smoke on a mapped Erli order reaches local `shipment_packages` and attempts `/shipping/external` only after tracking exists. AC-3, AC-4, AC-5 and AC-6 satisfied.

DO NOT CHANGE

  • Do not change unrelated .vscode/ftp-kr.sync.cache.json.
  • Do not regress Allegro, shopPRO, InPost or Apaczka shipment behavior.
  • Do not connect runtime application code to DB_HOST_REMOTE.
  • Do not add inline CSS to resources/views/....
  • Do not add native alert() / confirm() in views.

SCOPE LIMITS

  • This plan does not implement Phase 131 carrier tracking polling, automation expansion or delivery-status cron beyond the immediate external parcel registration.
  • This plan does not force creating shipments through Erli's own carrier agreement. POST /shipping/parcels/ may be inspected during APPLY, but shipping via Erli-contract parcels is out of scope unless it is clearly just external/seller-contract compatible.
  • This plan does not build product/stock sync or Erli offer management.
  • This plan keeps Erli as one global integration unless a future phase explicitly introduces multi-account support.
  • This plan should avoid new schema if existing generic mapping storage is enough.
Before declaring plan complete: - [ ] `C:\xampp\php\php.exe -l` for every changed PHP/view/test file. - [ ] `git diff --check`. - [ ] `vendor/bin/phpunit tests/Unit/ErliExternalShipmentServiceTest.php` if PHPUnit dependencies are available; otherwise document the environment gap. - [ ] Attempt `sonar-scanner` after APPLY; if unavailable, document the gap in SUMMARY and STATE. - [ ] Manual smoke: `/settings/integrations/erli?tab=delivery` renders, saves mapping with `_token`, and survives Erli API metadata errors. - [ ] Manual smoke: a mapped Erli order preselects shipment provider/service on prepare page. - [ ] Manual smoke: local provider label creation still stores `shipment_packages` and the Erli external parcel sync is attempted only with a tracking number. - [ ] `DOCS/DB_SCHEMA.md`, `DOCS/ARCHITECTURE.md`, `DOCS/TECH_CHANGELOG.md` updated for changed behavior and any schema decision. - [ ] All acceptance criteria met.

<success_criteria>

  • Erli settings has a working delivery/shipping mapping tab.
  • Erli delivery mappings are stored and used by shipment prepare.
  • Erli orders can generate local labels through existing providers when mapped.
  • Erli receives external parcel/tracking data through native shipping API when tracking exists.
  • Native Erli-contract parcel creation is either explicitly not used or documented as future/manual decision.
  • Tests/lints/docs and required skill audit are completed or gaps documented. </success_criteria>
After completion, create `.paul/phases/130-erli-shipments-labels/130-01-SUMMARY.md`.