---
phase: 45-shoppro-status-push
plan: 01
subsystem: integration
tags: [shoppro, status-sync, cron, curl-put, api]

requires:
  - phase: shoppro-integrations
    provides: ShopproApiClient, ShopproIntegrationsRepository, order_status_mappings, integration_order_sync_state

provides:
  - Bidirectional status sync between orderPRO and shopPRO
  - ShopproApiClient::updateOrderStatus() PUT method
  - Reverse status mapping (orderpro -> shoppro)

affects: []

tech-stack:
  added: []
  patterns: [reverse-status-mapping, cursor-based-push-sync]

key-files:
  created:
    - database/migrations/20260327_000071_add_last_status_pushed_at_to_sync_state.sql
  modified:
    - src/Modules/Settings/ShopproApiClient.php
    - src/Modules/Settings/ShopproStatusSyncService.php
    - src/Modules/Settings/ShopproOrderSyncStateRepository.php
    - src/Modules/Cron/CronHandlerFactory.php

key-decisions:
  - "Refactor: wydzielenie executeRequest() z requestJson() dla reuse GET/PUT"
  - "Push only change_source=manual to prevent sync loops"
  - "Fallback 24h when last_status_pushed_at is null"

patterns-established:
  - "Reverse mapping: orderpro_status_code -> shoppro_status_code (first match wins)"
  - "Cursor-based push: last_status_pushed_at tracks sync progress per integration"

duration: 15min
started: 2026-03-27T00:00:00Z
completed: 2026-03-27T00:15:00Z
---

# Phase 45 Plan 01: ShopPRO Status Push Summary

**Implementacja synchronizacji statusow zamowien orderPRO -> shopPRO przez cron z reverse mapping i PUT API**

## Performance

| Metric | Value |
|--------|-------|
| Duration | ~15min |
| Tasks | 3 completed |
| Files modified | 7 |

## Acceptance Criteria Results

| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: API Client obsluguje PUT change_status | Pass | `updateOrderStatus()` wysyla PUT z JSON body `{status_id, send_email}` |
| AC-2: Push kierunek dziala w cron sync | Pass | `syncPushDirection()` query manual changes, reverse map, API call, cursor update |
| AC-3: Brak mapowania nie blokuje synca | Pass | Brak mapowania = `$skipped++`, kontynuacja petli |

## Accomplishments

- `ShopproApiClient::updateOrderStatus()` — metoda PUT do `/api.php?endpoint=orders&action=change_status`
- `ShopproStatusSyncService::syncPushDirection()` — pelna logika push: reverse mapping, query `order_status_history` (tylko `change_source=manual`), wywolanie API, aktualizacja kursora
- Refactor `ShopproApiClient` — wydzielenie `executeRequest()` z `requestJson()` dla reuse GET/PUT (eliminacja duplikacji SSL/curl logic)
- Kursor `last_status_pushed_at` w `integration_order_sync_state` z defensywnym sprawdzaniem istnienia kolumny

## Files Created/Modified

| File | Change | Purpose |
|------|--------|---------|
| `database/migrations/20260327_000071_*.sql` | Created | Migracja: kolumna `last_status_pushed_at` |
| `src/Modules/Settings/ShopproApiClient.php` | Modified | Nowa metoda `updateOrderStatus()` + refactor na `executeRequest()` |
| `src/Modules/Settings/ShopproStatusSyncService.php` | Modified | Implementacja push direction z reverse mapping |
| `src/Modules/Settings/ShopproOrderSyncStateRepository.php` | Modified | Metody `getLastStatusPushedAt()`, `updateLastStatusPushedAt()` |
| `src/Modules/Cron/CronHandlerFactory.php` | Modified | Nowe zaleznosci dla ShopproStatusSyncService, reuse instancji repo |
| `DOCS/DB_SCHEMA.md` | Modified | Dokumentacja kolumny `last_status_pushed_at` |
| `DOCS/ARCHITECTURE.md` | Modified | Opis push direction i nowej metody API |
| `DOCS/TECH_CHANGELOG.md` | Modified | Wpis chronologiczny |

## Decisions Made

| Decision | Rationale | Impact |
|----------|-----------|--------|
| Refactor `requestJson()` na `executeRequest()` | Eliminacja duplikacji SSL/curl logic miedzy GET i PUT | Latwiejsze dodawanie kolejnych metod HTTP |
| Push tylko `change_source=manual` | Zapobieganie petli synchronizacji (import->push->import) | Bezpieczna dwukierunkowa synchronizacja |
| Fallback 24h dla null cursor | Przy pierwszym uruchomieniu nie pushowac calej historii | Ograniczenie zakresu pierwszego synca |
| `send_email=false` w push | Sync nie powinien generowac maili do klientow | Brak niechcianych powiadomien |

## Deviations from Plan

### Summary

| Type | Count | Impact |
|------|-------|--------|
| Auto-fixed | 1 | Minimal |

**Total impact:** Essential refactor, no scope creep

### Auto-fixed Issues

**1. Refactor: duplikacja curl logic**
- **Found during:** Task 1
- **Issue:** Plan sugerowal zduplikowanie SSL opts lub wydzielenie `buildCurlHandle()`. Duplikacja bylaby nieoptymalna.
- **Fix:** Wydzielono `executeRequest()` z pelna logika curl (GET/PUT), `requestJson()` i `requestJsonPut()` sa teraz thin wrappers.
- **Files:** `ShopproApiClient.php`
- **Verification:** `php -l` pass

### Deferred Items

None

## Issues Encountered

None

## Next Phase Readiness

**Ready:**
- Push direction w pelni funkcjonalny — po uruchomieniu migracji i restarcie crona, statusy beda synchronizowane
- Istniejace mapowania statusow (skonfigurowane w UI) beda uzywane w obu kierunkach

**Concerns:**
- Migracja `000071` musi byc uruchomiona na serwerze produkcyjnym
- Nalezy zweryfikowac mapowania statusow w konfiguracji integracji shopPRO (czy pokrywaja wszystkie uzywane statusy)

**Blockers:**
None

---
*Phase: 45-shoppro-status-push, Plan: 01*
*Completed: 2026-03-27*
