Phase 129 complete: - Add Erli pull/push status mapping tables, seeds and repositories - Wire Erli status sync cron for inbox pull and manual-only push - Add tabbed Erli settings UI, tests and documentation Co-Authored-By: Claude <noreply@anthropic.com>
15 KiB
phase, plan, type, wave, depends_on, files_modified, autonomous, delegation
| phase | plan | type | wave | depends_on | files_modified | autonomous | delegation | |||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 129-erli-status-mapping-sync | 01 | execute | 1 |
|
true | auto |
Purpose
Phase 128 importuje zamowienia Erli, ale statusy sa jeszcze mapowane sztywnymi defaultami. Phase 129 ma dac operatorowi kontrolowane mapowania pull/push, bezpieczne odkrywanie nowych statusow z inboxa oraz automatyczny push recznych zmian statusu z orderPRO do Erli.
Output
Nowe tabele mapowan statusow Erli, UI w ustawieniach Erli, endpointy zapisu mapowan, serwis synchronizacji statusow, handler crona erli_status_sync, rozszerzony mapper importu oraz testy i dokumentacja.
Project Context
@.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md @.paul/codebase/architecture.md @.paul/codebase/db_schema.md @DOCS/DB_SCHEMA.md @DOCS/ARCHITECTURE.md
Prior Work
@.paul/phases/127-erli-integration-foundation/127-01-SUMMARY.md @.paul/phases/128-erli-orders-import/128-01-SUMMARY.md
External API Context
- Official Erli docs checked 2026-05-15:
https://erli.pl/svc/shop-api/doc/ - Relevant Erli contract:
/inboxcontains new orders and order status changes.- Base order status values documented for import:
pending,purchased,cancelled. - Swagger exposes
PATCH /orders/{id}/statuswith body{"status": "created|canceled|readyToProcess|inProgress|sent|readyToPickup|received|returned|returningToSender|unknown"}. - Erli docs state that order update for Erli shipments should not send
trackingNumber; shipment/tracking remains Phase 130-131.
Source Files
@src/Modules/Settings/ErliApiClient.php @src/Modules/Settings/ErliIntegrationRepository.php @src/Modules/Settings/ErliIntegrationController.php @src/Modules/Settings/ErliOrderMapper.php @src/Modules/Settings/ErliOrdersSyncService.php @src/Modules/Settings/AllegroStatusMappingRepository.php @src/Modules/Settings/AllegroPullStatusMappingRepository.php @src/Modules/Settings/AllegroStatusMappingController.php @src/Modules/Settings/AllegroStatusSyncService.php @src/Modules/Settings/ShopproStatusSyncService.php @src/Modules/Settings/OrderStatusRepository.php @src/Modules/Cron/CronHandlerFactory.php @src/Modules/Cron/AllegroStatusSyncHandler.php @resources/views/settings/erli.php @resources/views/settings/allegro.php @routes/web.php @resources/lang/pl.php @tests/Unit/AllegroStatusSyncServiceTest.php @tests/Unit/ErliOrderMapperTest.php
## Required Skills (from SPECIAL-FLOWS.md)| Skill | Priority | When to Invoke | Loaded? |
|---|---|---|---|
sonar-scanner |
required | After APPLY, before UNIFY | ○ |
/feature-dev |
optional | New marketplace integration feature | ○ |
/code-review |
optional | Before UNIFY if broad risks remain | ○ |
/frontend-design |
optional | If Erli settings UI needs significant redesign | ○ |
BLOCKING: Required skills MUST be attempted before UNIFY. If sonar-scanner is unavailable in PATH, document the gap in SUMMARY and STATE as in Phase 128.
Skill Invocation Checklist
sonar-scannerrun or documented unavailable
<acceptance_criteria>
AC-1: Erli status mapping schema and seeds
Given Phase 129 migration is applied
When the database is inspected
Then Erli has separate pull and push mapping tables, seeded with documented Erli statuses, and `erli_status_sync` exists as a disabled-by-default or settings-controlled cron schedule
AC-2: Erli settings UI exposes status mappings
Given an operator opens `/settings/integrations/erli`
When they review the settings page
Then they can configure Erli -> orderPRO pull mappings, orderPRO -> Erli push mappings, status sync direction, and status sync interval without editing code
AC-3: Import uses configurable pull mappings with discovery
Given an Erli inbox message contains status `pending`, `purchased`, `cancelled`, or a new status
When `ErliOrdersSyncService` imports the message
Then `ErliOrderMapper` uses the configured pull mapping when present, falls back to safe defaults when absent, and stores unknown Erli statuses for later mapping
AC-4: Cron pushes only manual orderPRO status changes to Erli
Given an Erli order has a manual status change in `order_status_history`
When the `erli_status_sync` cron handler runs in orderPRO -> Erli direction
Then the service maps the current orderPRO status to an Erli status and calls `PATCH /orders/{id}/status` only for mapped manual changes after the last pushed cursor
AC-5: Push is safe and observable
Given Erli credentials are missing, mappings are incomplete, or Erli API returns an error
When status sync runs
Then the result reports pushed/skipped/failed counts, records bounded errors, and advances the push cursor only for successfully processed change timestamps
AC-6: Documentation and tests cover status behavior
Given Phase 129 implementation is complete
When verification runs
Then mapper/status-sync unit tests, PHP lint, docs, and PAUL summary describe the new status mapping and sync behavior
</acceptance_criteria>
Task 1: Add Erli status mapping persistence, seeds, API client method database/migrations/20260515_000116_add_erli_status_mapping_sync.sql, src/Modules/Settings/ErliApiClient.php, src/Modules/Settings/ErliIntegrationRepository.php, src/Modules/Settings/ErliStatusMappingRepository.php, src/Modules/Settings/ErliPullStatusMappingRepository.php, DOCS/DB_SCHEMA.md Create the persistence foundation: - Add `erli_order_status_mappings` for push mappings (`orderpro_status_code` -> `erli_status_code`, name, timestamps). - Add `erli_order_status_pull_mappings` for pull mappings (`erli_status_code` -> `orderpro_status_code`, name, timestamps). - Seed documented pull statuses: `pending -> nieoplacone`, `purchased -> nowe`, `cancelled -> anulowane`. - Seed documented push status options from official swagger: `created`, `canceled`, `readyToProcess`, `inProgress`, `sent`, `readyToPickup`, `received`, `returned`, `returningToSender`, `unknown`. Keep orderPRO mappings nullable where no safe default exists. - Seed `app_settings` keys `erli_status_sync_direction=erli_to_orderpro` and `erli_status_sync_interval_minutes=15`. - Seed `cron_schedules.job_type='erli_status_sync'` idempotently; prefer disabled until operator enables/import settings are confirmed, unless existing local pattern makes enabled safer. - Add repositories mirroring Allegro style: list, replaceAll, find mapped status, upsertDiscoveredStatus, build reverse map. - Add `ErliApiClient::updateOrderStatus(array $credentials, string $orderId, string $erliStatus): array` calling `PATCH /orders/{id}/status` with JSON `{status: ...}`. - Extend repository credentials/settings only as needed for status sync settings; do not introduce per-account Erli complexity. - Update DB schema docs. `C:\xampp\php\php.exe -l src/Modules/Settings/ErliApiClient.php` `C:\xampp\php\php.exe -l src/Modules/Settings/ErliStatusMappingRepository.php` `C:\xampp\php\php.exe -l src/Modules/Settings/ErliPullStatusMappingRepository.php` Inspect migration for idempotent DDL/seed and no raw runtime use of `DB_HOST_REMOTE`. AC-1 foundation is implemented and AC-5 has API error result shape available. Task 2: Add Erli settings UI and routes for pull/push mappings src/Modules/Settings/ErliIntegrationController.php, routes/web.php, resources/views/settings/erli.php, resources/lang/pl.php, DOCS/ARCHITECTURE.md Extend the Erli settings page without creating inline CSS or native alert/confirm: - Inject `OrderStatusRepository`, `ErliStatusMappingRepository`, and `ErliPullStatusMappingRepository`. - Pass orderPRO statuses, Erli push statuses, Erli pull mappings, current sync direction and interval to the view. - Add POST handlers for saving pull mappings and push mappings with CSRF validation. - Add status sync direction and interval fields to the existing Erli settings form, validating direction against `erli_to_orderpro` / `orderpro_to_erli` and interval 1-1440. - Add routes under `/settings/integrations/erli/statuses/save-pull` and `/settings/integrations/erli/statuses/save-push` (or one clear equivalent route if controller shape is cleaner). - Render compact mapping tables similar to Allegro, but keep Erli page simple; do not build a landing/marketing page. - Add Polish translations for labels, hints, empty states, validation and flash messages. - Preserve existing test/import flash behavior from Phase 128. `C:\xampp\php\php.exe -l src/Modules/Settings/ErliIntegrationController.php` `C:\xampp\php\php.exe -l routes/web.php` `C:\xampp\php\php.exe -l resources/views/settings/erli.php` `C:\xampp\php\php.exe -l resources/lang/pl.php` Manual inspect that forms include `_token` and use escaped output via `$e()`. AC-2 is satisfied and existing Phase 127/128 settings actions remain reachable. Task 3: Wire pull discovery and push cron sync src/Modules/Settings/ErliOrderMapper.php, src/Modules/Settings/ErliOrdersSyncService.php, src/Modules/Settings/ErliStatusSyncService.php, src/Modules/Cron/ErliStatusSyncHandler.php, src/Modules/Cron/CronHandlerFactory.php, tests/Unit/ErliOrderMapperTest.php, tests/Unit/ErliStatusSyncServiceTest.php, DOCS/ARCHITECTURE.md, DOCS/TECH_CHANGELOG.md Implement runtime behavior: - Let `ErliOrderMapper` accept an optional pull mapping dependency or mapping array while preserving the existing no-dependency unit-test usage. - During import, discover any raw Erli order status from inbox and upsert it into the pull mapping repository before/while mapping. - Use configured pull mapping when available; otherwise keep Phase 128 defaults (`pending`, `purchased`, `cancelled`) and safe fallback. - Add `ErliStatusSyncService` similar to Allegro/shopPRO: - Direction `erli_to_orderpro`: run Erli inbox import with `ignore_orders_fetch_enabled=true` so status-change messages are pulled via the same safe ACK path. - Direction `orderpro_to_erli`: find only Erli orders with `order_status_history.change_source='manual'` newer than `last_status_pushed_at` for the active Erli integration. - Use push mapping to call `ErliApiClient::updateOrderStatus()`. - Count `pushed`, `skipped`, `failed`; keep bounded errors; advance cursor only to latest successfully processed change timestamp. - Add `ErliStatusSyncHandler` and register `erli_status_sync` in `CronHandlerFactory`. - Add/update unit tests for pull mapping override, unknown status discovery behavior, skipped unmapped push, successful push, and failed push cursor behavior. - Update architecture/changelog docs. `C:\xampp\php\php.exe -l src/Modules/Settings/ErliOrderMapper.php` `C:\xampp\php\php.exe -l src/Modules/Settings/ErliOrdersSyncService.php` `C:\xampp\php\php.exe -l src/Modules/Settings/ErliStatusSyncService.php` `C:\xampp\php\php.exe -l src/Modules/Cron/ErliStatusSyncHandler.php` `C:\xampp\php\php.exe -l src/Modules/Cron/CronHandlerFactory.php` `C:\xampp\php\php.exe -l tests/Unit/ErliStatusSyncServiceTest.php` If available: `vendor/bin/phpunit tests/Unit/ErliOrderMapperTest.php tests/Unit/ErliStatusSyncServiceTest.php` Required skill: `sonar-scanner` or document unavailable. AC-3, AC-4, AC-5 and AC-6 are satisfied.DO NOT CHANGE
- Do not change shipment/label generation flows; Erli shipment creation belongs to Phase 130.
- Do not send Erli
trackingNumberin status sync; official docs say shipment number is handled after shipment generation. - Do not broaden push to automation/system/import changes; Phase 129 push covers only manual
order_status_historyrows. - Do not alter Allegro/shopPRO mapping semantics except for reading patterns.
- Do not use
DB_HOST_REMOTEin runtime code. - Do not add native
alert()/confirm()or inline CSS in Erli settings.
SCOPE LIMITS
- No Erli webhook registration in this plan; inbox/cron remains the source.
- No product stock adjustment on Erli cancellation; document if needed for a later products/inventory phase.
- No manual live Erli API call is required during APPLY; live smoke is an operator follow-up unless credentials and DB are ready.
- No redesign of the whole integrations UI; keep changes scoped to Erli settings.
<success_criteria>
- Erli status pull/push mappings can be configured from UI.
- Erli import uses configured pull mapping and discovers unknown raw statuses.
- Erli status cron can push only manual orderPRO status changes to Erli using
PATCH /orders/{id}/status. - Failures are observable and do not incorrectly advance push cursor.
- Docs and tests reflect the new behavior. </success_criteria>