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:
@@ -69,7 +69,7 @@ HTTP Request
|
||||
1. **Import** — Cron handler → API client → `OrderImportService` → `OrdersRepository::insertOrder()` → `AutomationService::executeForNewOrder()`
|
||||
2. **Re-import (Phase 111 + 112 + 119)** — `OrderImportRepository::upsertOrderAggregate` wykrywa tranzycje `payment_status` z 0/1 na 2 i zwraca `payment_transition=true`. `AllegroOrderImportService` i `ShopproOrdersSyncService` na tej fladze emituja `payment.status_changed`, co przez chain reguly automatyzacji #7 zmienia `status_code` na `w_realizacji`. Logika preservacji `status_code` z Phase 62 pozostaje rozdzielona (`statusOverwriteAllowed` = `currentStatus='nieoplacone' && newPaymentStatus===2`). **Phase 112-01 (delta-only re-import):** przy `created=false` repo nie wywoluje `replaceAddresses/replaceItems/replaceNotes/replaceShipments/replaceStatusHistory` — `order_items.id` i flagi lokalne (np. `project_generated` z Phase 97) pozostaja stabilne. `updateOrderDelta()` aktualizuje wylacznie `status_code` (warunkowo, z propagacja anulowania), `payment_status`, `total_paid`, `is_canceled_by_buyer`, `source_updated_at`, `payload_json`, `fetched_at`, `updated_at`. Anulowanie ze zrodla (`is_canceled_by_buyer=1` lub zmapowany pull `status_code='anulowane'`) nadpisuje preservacje statusu. Identical-payload guard (`normalizePayloadJson`) pomija UPDATE gdy znormalizowany payload nie rozni sie od DB i brak innych tranzycji. **Phase 119-01 (total_paid protection):** gdy `paymentStatusUnchanged=true` (`oldPaymentStatus === newPaymentStatus`), `updateOrderDelta()` nie dolacza `total_paid` do UPDATE — chroni reczne korekty kwoty (np. zwroty czesciowe). `is_canceled_by_buyer` jest pomijane analogicznie, chyba ze `cancelledBySource=true` (cancel propagation ze zrodla zawsze wymusza wpis flagi). Pozostale pola (`status_code`, `payment_status`, `source_updated_at`, `payload_json`, `fetched_at`, `updated_at`) zachowuja niezmieniony kontrakt z Phase 112-01.
|
||||
3. **Status update** — `OrdersController::updateStatus()` → `OrdersRepository::updateStatus()` → automation check
|
||||
4. **Status sync** — Cron → `AllegroStatusSyncService` / `ShopproStatusSyncService` → carrier API
|
||||
4. **Status sync** — Cron → `AllegroStatusSyncService` / `ShopproStatusSyncService` / `ErliStatusSyncService` → marketplace API
|
||||
|
||||
### Statistics Summary
|
||||
1. **Request** — `/statistics/summary` → `OrdersStatisticsController::summary()`
|
||||
@@ -97,6 +97,7 @@ HTTP Request
|
||||
|---------|------|
|
||||
| `AllegroOrdersImportHandler` | Fetch new Allegro orders |
|
||||
| `AllegroStatusSyncHandler` | Push status changes to Allegro |
|
||||
| `ErliStatusSyncHandler` | Pull Erli status events via inbox or push manual local status changes to Erli |
|
||||
| `AllegroTokenRefreshHandler` | OAuth token refresh (24h expiry) |
|
||||
| `ShopproOrdersImportHandler` | Fetch new shopPRO orders |
|
||||
| `ShopproStatusSyncHandler` | Push status to shopPRO |
|
||||
|
||||
@@ -370,6 +370,7 @@ UNIQUE: `(order_id, source_payment_id)`
|
||||
UNIQUE: `(integration_id, shoppro_status_code)`
|
||||
|
||||
**integration_order_sync_state** — Track order fetch progress per integration
|
||||
- Phase 129 adds `last_status_pushed_at` for Erli manual status push cursor.
|
||||
|
||||
**integration_order_status_sync_state** — Track status sync progress per integration and direction
|
||||
|
||||
@@ -517,6 +518,14 @@ UNIQUE: `(type, name)`
|
||||
| `created_at` | DATETIME | |
|
||||
| `updated_at` | DATETIME | |
|
||||
|
||||
**erli_order_status_mappings** — orderPRO status → Erli status used for status push
|
||||
- Seeded official Erli statuses: `created`, `canceled`, `readyToProcess`, `inProgress`, `sent`, `readyToPickup`, `received`, `returned`, `returningToSender`, `unknown`.
|
||||
- `orderpro_status_code` is nullable; unmapped status rows are skipped by push sync.
|
||||
|
||||
**erli_order_status_pull_mappings** — Erli status → orderPRO status used during inbox import
|
||||
- Seeded defaults: `pending -> nieoplacone`, `purchased -> nowe`, `cancelled -> anulowane`.
|
||||
- Unknown Erli statuses are discovered from `/inbox` and inserted with nullable mapping.
|
||||
|
||||
**allegro_delivery_method_mappings** — Map order delivery method strings to Allegro services
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
# Technical Changelog
|
||||
|
||||
## 2026-05-16 - Phase 129 Plan 01: Erli Status Mapping + Sync
|
||||
|
||||
**Co zrobiono:**
|
||||
- Dodano mapowania statusow Erli pull/push, `ErliStatusSyncService`, `ErliStatusSyncHandler`, endpoint `PATCH /orders/{id}/status` w kliencie API oraz UI mapowan w `/settings/integrations/erli`.
|
||||
- Import Erli odkrywa surowe statusy z inboxa i uzywa `erli_order_status_pull_mappings`; push obejmuje tylko reczne zmiany statusu z `order_status_history.change_source='manual'`.
|
||||
|
||||
**Dlaczego:**
|
||||
- Phase 128 miala domyslne statusy; Phase 129 daje operatorowi kontrolowane mapowanie i bezpieczny push bez petli automatyzacji.
|
||||
|
||||
---
|
||||
|
||||
## 2026-05-13 - Phase 126 Plan 01: Invoice GUS Field Mapping Fix (KRS heuristic)
|
||||
|
||||
**Co zrobiono:**
|
||||
|
||||
Reference in New Issue
Block a user