feat(129): erli status mapping sync
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>
This commit is contained in:
304
.paul/phases/129-erli-status-mapping-sync/129-01-PLAN.md
Normal file
304
.paul/phases/129-erli-status-mapping-sync/129-01-PLAN.md
Normal file
@@ -0,0 +1,304 @@
|
||||
---
|
||||
phase: 129-erli-status-mapping-sync
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- database/migrations/20260515_000116_add_erli_status_mapping_sync.sql
|
||||
- src/Modules/Settings/ErliApiClient.php
|
||||
- src/Modules/Settings/ErliIntegrationController.php
|
||||
- src/Modules/Settings/ErliIntegrationRepository.php
|
||||
- src/Modules/Settings/ErliOrderMapper.php
|
||||
- src/Modules/Settings/ErliOrdersSyncService.php
|
||||
- src/Modules/Settings/ErliStatusMappingRepository.php
|
||||
- src/Modules/Settings/ErliPullStatusMappingRepository.php
|
||||
- src/Modules/Settings/ErliStatusSyncService.php
|
||||
- src/Modules/Cron/ErliStatusSyncHandler.php
|
||||
- src/Modules/Cron/CronHandlerFactory.php
|
||||
- routes/web.php
|
||||
- resources/views/settings/erli.php
|
||||
- resources/lang/pl.php
|
||||
- tests/Unit/ErliOrderMapperTest.php
|
||||
- tests/Unit/ErliStatusSyncServiceTest.php
|
||||
- DOCS/DB_SCHEMA.md
|
||||
- DOCS/ARCHITECTURE.md
|
||||
- DOCS/TECH_CHANGELOG.md
|
||||
autonomous: true
|
||||
delegation: auto
|
||||
---
|
||||
|
||||
<objective>
|
||||
## Goal
|
||||
Wdrozyc mapowanie i synchronizacje statusow Erli w obu kierunkach: Erli -> orderPRO przy imporcie `/inbox` oraz orderPRO -> Erli przez cron push na `PATCH /orders/{id}/status`.
|
||||
|
||||
## 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.
|
||||
</objective>
|
||||
|
||||
<context>
|
||||
<clarifications>
|
||||
- **Zakres** — Czy Phase 129 ma objac od razu oba kierunki synchronizacji statusow Erli?
|
||||
-> Odpowiedz: Tak, oba kierunki.
|
||||
- **Statusy** — Jak traktowac liste statusow Erli w UI mapowan?
|
||||
-> Odpowiedz: Seed + discovery.
|
||||
- **Push** — Ktore lokalne zmiany statusu orderPRO maja byc wysylane do Erli?
|
||||
-> Odpowiedz: Tylko reczne zmiany statusu (`order_status_history.change_source='manual'`).
|
||||
</clarifications>
|
||||
|
||||
## 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:
|
||||
- `/inbox` contains new orders and order status changes.
|
||||
- Base order status values documented for import: `pending`, `purchased`, `cancelled`.
|
||||
- Swagger exposes `PATCH /orders/{id}/status` with 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
|
||||
</context>
|
||||
|
||||
<skills>
|
||||
## 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-scanner` run or documented unavailable
|
||||
</skills>
|
||||
|
||||
<acceptance_criteria>
|
||||
|
||||
## AC-1: Erli status mapping schema and seeds
|
||||
```gherkin
|
||||
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
|
||||
```gherkin
|
||||
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
|
||||
```gherkin
|
||||
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
|
||||
```gherkin
|
||||
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
|
||||
```gherkin
|
||||
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
|
||||
```gherkin
|
||||
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>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add Erli status mapping persistence, seeds, API client method</name>
|
||||
<files>
|
||||
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
|
||||
</files>
|
||||
<action>
|
||||
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.
|
||||
</action>
|
||||
<verify>
|
||||
`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`.
|
||||
</verify>
|
||||
<done>AC-1 foundation is implemented and AC-5 has API error result shape available.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Add Erli settings UI and routes for pull/push mappings</name>
|
||||
<files>
|
||||
src/Modules/Settings/ErliIntegrationController.php,
|
||||
routes/web.php,
|
||||
resources/views/settings/erli.php,
|
||||
resources/lang/pl.php,
|
||||
DOCS/ARCHITECTURE.md
|
||||
</files>
|
||||
<action>
|
||||
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.
|
||||
</action>
|
||||
<verify>
|
||||
`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()`.
|
||||
</verify>
|
||||
<done>AC-2 is satisfied and existing Phase 127/128 settings actions remain reachable.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 3: Wire pull discovery and push cron sync</name>
|
||||
<files>
|
||||
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
|
||||
</files>
|
||||
<action>
|
||||
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.
|
||||
</action>
|
||||
<verify>
|
||||
`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.
|
||||
</verify>
|
||||
<done>AC-3, AC-4, AC-5 and AC-6 are satisfied.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<boundaries>
|
||||
|
||||
## DO NOT CHANGE
|
||||
- Do not change shipment/label generation flows; Erli shipment creation belongs to Phase 130.
|
||||
- Do not send Erli `trackingNumber` in 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_history` rows.
|
||||
- Do not alter Allegro/shopPRO mapping semantics except for reading patterns.
|
||||
- Do not use `DB_HOST_REMOTE` in 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.
|
||||
|
||||
</boundaries>
|
||||
|
||||
<verification>
|
||||
Before declaring plan complete:
|
||||
- [ ] PHP lint passes for all changed PHP/view/lang/test files.
|
||||
- [ ] Migration is idempotent and documented in `DOCS/DB_SCHEMA.md`.
|
||||
- [ ] Erli settings page renders pull/push mapping forms with CSRF and escaped values.
|
||||
- [ ] Mapper tests cover configured mapping fallback and unknown status handling.
|
||||
- [ ] Status sync tests cover successful push, skipped unmapped push, failed push, and cursor behavior.
|
||||
- [ ] `vendor/bin/phpunit tests/Unit/ErliOrderMapperTest.php tests/Unit/ErliStatusSyncServiceTest.php` run if available; otherwise gap documented.
|
||||
- [ ] `sonar-scanner` attempted per SPECIAL-FLOWS; unavailable CLI documented as gap.
|
||||
- [ ] `git diff --check` passes.
|
||||
- [ ] All acceptance criteria met.
|
||||
</verification>
|
||||
|
||||
<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>
|
||||
|
||||
<output>
|
||||
After completion, create `.paul/phases/129-erli-status-mapping-sync/129-01-SUMMARY.md`.
|
||||
</output>
|
||||
198
.paul/phases/129-erli-status-mapping-sync/129-01-SUMMARY.md
Normal file
198
.paul/phases/129-erli-status-mapping-sync/129-01-SUMMARY.md
Normal file
@@ -0,0 +1,198 @@
|
||||
---
|
||||
phase: 129-erli-status-mapping-sync
|
||||
plan: 01
|
||||
subsystem: settings, integrations, cron, database
|
||||
tags: [erli, status-mapping, status-sync, cron, marketplace]
|
||||
requires:
|
||||
- phase: 127-erli-integration-foundation
|
||||
provides: global Erli credentials, API client, settings page and hub row
|
||||
- phase: 128-erli-orders-import
|
||||
provides: Erli inbox import, order mapper, sync state and safe ACK flow
|
||||
provides:
|
||||
- Configurable Erli -> orderPRO pull status mappings with discovery
|
||||
- Configurable orderPRO -> Erli push status mappings
|
||||
- Cron-driven Erli status sync in pull or push direction
|
||||
- Tabbed Erli settings UI consistent with other integrations
|
||||
affects: [phase-130-erli-shipments-labels, phase-131-erli-tracking-automation, erli-settings]
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns: [separate pull/push marketplace status mappings, manual-only push cursor, tabbed integration settings]
|
||||
key-files:
|
||||
created:
|
||||
- database/migrations/20260515_000116_add_erli_status_mapping_sync.sql
|
||||
- src/Modules/Settings/ErliStatusMappingRepository.php
|
||||
- src/Modules/Settings/ErliPullStatusMappingRepository.php
|
||||
- src/Modules/Settings/ErliStatusSyncService.php
|
||||
- src/Modules/Cron/ErliStatusSyncHandler.php
|
||||
- tests/Unit/ErliStatusSyncServiceTest.php
|
||||
modified:
|
||||
- src/Modules/Settings/ErliApiClient.php
|
||||
- src/Modules/Settings/ErliIntegrationController.php
|
||||
- src/Modules/Settings/ErliOrderMapper.php
|
||||
- src/Modules/Settings/ErliOrdersSyncService.php
|
||||
- src/Modules/Settings/ErliOrderSyncStateRepository.php
|
||||
- src/Modules/Cron/CronHandlerFactory.php
|
||||
- routes/web.php
|
||||
- resources/views/settings/erli.php
|
||||
- resources/lang/pl.php
|
||||
- DOCS/DB_SCHEMA.md
|
||||
- DOCS/ARCHITECTURE.md
|
||||
- DOCS/TECH_CHANGELOG.md
|
||||
key-decisions:
|
||||
- "Push to Erli uses only manual orderPRO status changes from order_status_history.change_source='manual'."
|
||||
- "Pull status changes reuse the existing Erli inbox import and ACK flow instead of a separate status endpoint."
|
||||
- "Erli settings use the same tabbed UI pattern as Allegro/shopPRO."
|
||||
patterns-established:
|
||||
- "Erli has separate pull and push mapping repositories/tables to avoid mixing import and outbound sync semantics."
|
||||
- "Unknown Erli statuses discovered in inbox are stored for later operator mapping."
|
||||
duration: 35min
|
||||
started: 2026-05-16T00:00:00+02:00
|
||||
completed: 2026-05-16T00:23:35+02:00
|
||||
---
|
||||
|
||||
# Phase 129 Plan 01: Erli Status Mapping + Sync Summary
|
||||
|
||||
Erli now supports configurable pull/push status mapping, status discovery from inbox, and cron-based status synchronization with a tabbed settings UI.
|
||||
|
||||
## Performance
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Duration | ~35min |
|
||||
| Started | 2026-05-16T00:00:00+02:00 |
|
||||
| Completed | 2026-05-16T00:23:35+02:00 |
|
||||
| Tasks | 3 completed |
|
||||
| Files modified | 25 phase files, excluding unrelated `.vscode/ftp-kr.sync.cache.json` |
|
||||
|
||||
## Acceptance Criteria Results
|
||||
|
||||
| Criterion | Status | Notes |
|
||||
|-----------|--------|-------|
|
||||
| AC-1: Erli status mapping schema and seeds | Pass | Migration adds pull/push mapping tables, `integration_order_sync_state.last_status_pushed_at`, app settings, seed status options, and disabled `erli_status_sync` schedule. |
|
||||
| AC-2: Erli settings UI exposes status mappings | Pass | `/settings/integrations/erli` exposes tabbed panels for integration, statuses and settings; operators can save pull/push mappings, direction and interval with CSRF-protected forms. |
|
||||
| AC-3: Import uses configurable pull mappings with discovery | Pass | `ErliOrderMapper` uses configured pull mappings with safe fallbacks; `ErliOrdersSyncService` stores newly seen raw Erli statuses for later mapping. |
|
||||
| AC-4: Cron pushes only manual orderPRO status changes to Erli | Pass | `ErliStatusSyncService` selects only Erli orders with manual status history newer than `last_status_pushed_at` and calls `PATCH /orders/{id}/status` only when mapped. |
|
||||
| AC-5: Push is safe and observable | Pass | Sync result reports pushed/skipped/failed and bounded errors; cursor advances only through successfully processed timestamps. |
|
||||
| AC-6: Documentation and tests cover status behavior | Pass with env gaps | PHP lint and diff checks passed; PHPUnit and Sonar are documented gaps because local CLIs are unavailable/broken. Docs were updated. |
|
||||
|
||||
## Accomplishments
|
||||
|
||||
- Added Erli status persistence for both directions with seed statuses from the documented Erli status contract.
|
||||
- Extended Erli API client with `PATCH /orders/{id}/status`.
|
||||
- Added repositories and controller endpoints for saving pull and push mappings.
|
||||
- Reused the existing inbox import path for Erli -> orderPRO status pulls.
|
||||
- Added `ErliStatusSyncService` and cron handler for configurable pull/push sync.
|
||||
- Updated Erli settings UI to match other integrations with tabs.
|
||||
- Added mapper and status sync unit test coverage files.
|
||||
|
||||
## Task Commits
|
||||
|
||||
No per-task commits were created during APPLY. Phase transition creates the scoped phase commit.
|
||||
|
||||
| Task | Commit | Type | Description |
|
||||
|------|--------|------|-------------|
|
||||
| Task 1: Persistence/API foundation | pending phase commit | feat | Mapping tables, seeds, repositories and API status update method. |
|
||||
| Task 2: Settings UI/routes | pending phase commit | feat | Erli settings status controls, mapping forms, routes and translations. |
|
||||
| Task 3: Runtime sync/tests/docs | pending phase commit | feat/test/docs | Discovery, pull/push sync service, cron handler, tests and docs. |
|
||||
|
||||
## Files Created/Modified
|
||||
|
||||
| File | Change | Purpose |
|
||||
|------|--------|---------|
|
||||
| `database/migrations/20260515_000116_add_erli_status_mapping_sync.sql` | Created | Status mapping tables, sync cursor, seeds and cron/app settings. |
|
||||
| `src/Modules/Settings/ErliStatusMappingRepository.php` | Created | Push mapping persistence for orderPRO -> Erli. |
|
||||
| `src/Modules/Settings/ErliPullStatusMappingRepository.php` | Created | Pull mapping persistence and discovery for Erli -> orderPRO. |
|
||||
| `src/Modules/Settings/ErliStatusSyncService.php` | Created | Pull/push status sync orchestration and result counters. |
|
||||
| `src/Modules/Cron/ErliStatusSyncHandler.php` | Created | Cron entrypoint for `erli_status_sync`. |
|
||||
| `tests/Unit/ErliStatusSyncServiceTest.php` | Created | Unit tests for push success, skipped unmapped changes and failure cursor behavior. |
|
||||
| `src/Modules/Settings/ErliApiClient.php` | Modified | Added authenticated Erli status update request. |
|
||||
| `src/Modules/Settings/ErliIntegrationController.php` | Modified | Added tab state, status settings and mapping save handlers. |
|
||||
| `src/Modules/Settings/ErliOrderMapper.php` | Modified | Added configurable pull mapping with safe fallback. |
|
||||
| `src/Modules/Settings/ErliOrdersSyncService.php` | Modified | Added raw Erli status discovery during inbox import. |
|
||||
| `src/Modules/Settings/ErliOrderSyncStateRepository.php` | Modified | Added push cursor support. |
|
||||
| `src/Modules/Cron/CronHandlerFactory.php` | Modified | Registered `erli_status_sync`. |
|
||||
| `routes/web.php` | Modified | Wired repositories, status sync service and mapping routes. |
|
||||
| `resources/views/settings/erli.php` | Modified | Added tabbed UI and pull/push mapping forms. |
|
||||
| `resources/lang/pl.php` | Modified | Added Erli status mapping/sync/tabs translations. |
|
||||
| `DOCS/DB_SCHEMA.md` | Modified | Documented new tables/settings/cursor. |
|
||||
| `DOCS/ARCHITECTURE.md` | Modified | Documented Erli status sync flow and tabbed settings. |
|
||||
| `DOCS/TECH_CHANGELOG.md` | Modified | Logged Phase 129 and Erli settings tabs fix. |
|
||||
|
||||
## Decisions Made
|
||||
|
||||
| Decision | Rationale | Impact |
|
||||
|----------|-----------|--------|
|
||||
| Push only manual status changes | Prevents loops from imports, automation and system updates. | Operator intent is explicit; automated changes stay local unless manually changed. |
|
||||
| Pull uses inbox import | Erli status events arrive through inbox and the Phase 128 ACK flow is already safe. | One source of truth for Erli event processing. |
|
||||
| Separate pull/push mapping tables | Import statuses and outbound Erli status values have different semantics. | Safer UI and easier future extension. |
|
||||
| Unknown pull statuses are discovered | Erli can introduce or send statuses not present in seed data. | Operator can map new statuses without code changes. |
|
||||
| Erli settings use tabs | Page grew after Phase 129 and needed parity with Allegro/shopPRO. | Better scanability, same interaction model as other integrations. |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Summary
|
||||
|
||||
| Type | Count | Impact |
|
||||
|------|-------|--------|
|
||||
| Auto-fixed | 1 | UI parity fix, no backend contract change. |
|
||||
| Scope additions | 1 | Tabbed Erli settings page added during final verification. |
|
||||
| Deferred | 2 | Environment-dependent verification remains operator follow-up. |
|
||||
|
||||
**Total impact:** Positive UI consistency improvement; no expansion into shipments/labels/tracking.
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. Erli settings were missing tabs**
|
||||
- **Found during:** Post-APPLY manual inspection.
|
||||
- **Issue:** Erli settings displayed all integration/status/import/test sections in one vertical page, unlike Allegro/shopPRO.
|
||||
- **Fix:** Added active `tab` handling, `return_to` for forms and standard `content-tabs-nav` / `content-tab-panel` markup.
|
||||
- **Files:** `resources/views/settings/erli.php`, `src/Modules/Settings/ErliIntegrationController.php`, `resources/lang/pl.php`, docs.
|
||||
- **Verification:** PHP lint for view/controller/lang and `git diff --check`.
|
||||
|
||||
### Deferred Items
|
||||
|
||||
- Phase 129 follow-up: run `php bin/migrate.php`, verify `/settings/integrations/erli` mappings, set `orderPRO -> Erli`, manually change an Erli order status and run `erli_status_sync`.
|
||||
- Phase 129 verification gap: `vendor/bin/phpunit` is absent in this checkout and global XAMPP PHPUnit is incompatible with the current PHP, so PHPUnit tests were not executed.
|
||||
- Phase 129 skill gap: `sonar-scanner` is not available in PATH, so Sonar scan could not run.
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
| Issue | Resolution |
|
||||
|-------|------------|
|
||||
| `vendor/bin/phpunit` missing | Documented as verification gap; PHP lint and diff checks were run. |
|
||||
| Global XAMPP `phpunit` crashes on removed PHP `each()` | Documented as verification gap. |
|
||||
| `sonar-scanner` unavailable | Documented in SUMMARY and STATE skill audit. |
|
||||
|
||||
## Verification Results
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| `php -l resources/views/settings/erli.php` | Pass |
|
||||
| `php -l src/Modules/Settings/ErliIntegrationController.php` | Pass |
|
||||
| `php -l resources/lang/pl.php` | Pass |
|
||||
| Phase APPLY PHP lints for changed PHP/view/test files | Pass |
|
||||
| `git diff --check` | Pass |
|
||||
| `vendor/bin/phpunit tests/Unit/ErliOrderMapperTest.php tests/Unit/ErliStatusSyncServiceTest.php` | Not run: `vendor/bin/phpunit` missing |
|
||||
| `phpunit --version` | Failed: old XAMPP PHPUnit uses removed `each()` |
|
||||
| `sonar-scanner --version` | Failed: command not found |
|
||||
|
||||
Skill audit: required `sonar-scanner` was attempted and documented unavailable.
|
||||
|
||||
## Next Phase Readiness
|
||||
|
||||
**Ready:**
|
||||
- Erli status mapping and sync foundation is in place for later shipment/tracking work.
|
||||
- Erli settings now has the tab structure needed to host future shipment/label settings.
|
||||
- Push sync cursor and manual-change filtering provide a safe outbound pattern for future Erli API writes.
|
||||
|
||||
**Concerns:**
|
||||
- Live Erli behavior still needs migration and production credential smoke testing.
|
||||
- PHPUnit dev dependencies are missing locally, so unit tests need a `composer install` or CI run.
|
||||
- Sonar scan still depends on installing/configuring `sonar-scanner` in PATH.
|
||||
|
||||
**Blockers:**
|
||||
- None for planning Phase 130. Manual smoke remains required before production confidence.
|
||||
|
||||
---
|
||||
*Phase: 129-erli-status-mapping-sync, Plan: 01*
|
||||
*Completed: 2026-05-16*
|
||||
Reference in New Issue
Block a user