Files
shopPRO/.paul/phases/06-integrations-refactoring/06-02-PLAN.md
2026-03-12 13:36:06 +01:00

13 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous
phase plan type wave depends_on files_modified autonomous
06-integrations-refactoring 02 execute 1
06-01
autoload/admin/Controllers/IntegrationsController.php
autoload/admin/App.php
autoload/Domain/Order/OrderAdminService.php
cron.php
autoload/Domain/Integrations/IntegrationsRepository.php
tests/Unit/Domain/Integrations/IntegrationsRepositoryTest.php
true
## Goal Zmigrować wszystkich konsumentów metod `apilo*` z `IntegrationsRepository` na nowy `ApiloRepository`, a następnie usunąć metody Apilo z `IntegrationsRepository` (cleanup).

Purpose

Po tym planie IntegrationsRepository będzie lean (~225 linii): tylko settings, logi, product linking, ShopPRO import. ApiloRepository jest jedynym miejscem logiki Apilo.

Output

  • IntegrationsController: używa obu repozytoriów (IntegrationsRepository dla settings/logi, ApiloRepository dla apilo*)
  • OrderAdminService: 3 metody używają ApiloRepository dla apiloGetAccessToken
  • cron.php: apilo* wywołania przez $apiloRepository
  • IntegrationsRepository: usunięte metody apilo* (~650 linii mniej)
  • IntegrationsRepositoryTest: oczyszczony z duplikatów testów apilo*
## Project Context @.paul/PROJECT.md @.paul/STATE.md

Prior Work

@.paul/phases/06-integrations-refactoring/06-01-SUMMARY.md

Source Files

@autoload/admin/Controllers/IntegrationsController.php @autoload/admin/App.php @autoload/Domain/Order/OrderAdminService.php @autoload/Domain/Integrations/IntegrationsRepository.php @tests/Unit/Domain/Integrations/IntegrationsRepositoryTest.php

<acceptance_criteria>

AC-1: IntegrationsController używa ApiloRepository dla apilo*

Given IntegrationsController ma dwa repozytoria: $repository i $apiloRepository
When wywoływana jest dowolna metoda apilo* (apilo_settings, apilo_authorization, itp.)
Then używa $this->apiloRepository->apilo*() a nie $this->repository->apilo*()

AC-2: OrderAdminService i cron.php używają ApiloRepository dla apiloGetAccessToken

Given OrderAdminService::resendToApilo, syncApiloPayment, syncApiloStatus
  oraz cron.php potrzebują access tokenu
When wywoływana jest metoda apiloGetAccessToken()
Then używają new ApiloRepository($db) lub $apiloRepository, nie IntegrationsRepository

AC-3: IntegrationsRepository nie zawiera metod apilo*

Given plik IntegrationsRepository.php po cleanup
When sprawdzamy publiczne metody klasy
Then metody apilo* NIE ISTNIEJĄ, pozostają tylko:
     getSettings, getSetting, saveSetting,
     getLogs, deleteLog, clearLogs,
     linkProduct, unlinkProduct, getProductSku,
     shopproImportProduct

AC-4: Pełna suite testów green

Given wszystkie zmiany wprowadzone
When uruchamiane jest php phpunit.phar
Then wszystkie testy green (826+ testów, zero regresji)

</acceptance_criteria>

Task 1: Zaktualizuj IntegrationsController i App.php autoload/admin/Controllers/IntegrationsController.php, autoload/admin/App.php **IntegrationsController.php:**
1. Dodaj import: `use Domain\Integrations\ApiloRepository;`
2. Dodaj property: `private ApiloRepository $apiloRepository;`
3. Zmień konstruktor na:
   ```php
   public function __construct( IntegrationsRepository $repository, ApiloRepository $apiloRepository )
   {
       $this->repository = $repository;
       $this->apiloRepository = $apiloRepository;
   }
   ```
4. Zamień wszystkie wywołania `$this->repository->apilo*()` na `$this->apiloRepository->apilo*()`:
   - linia ~128: `$this->repository->apiloIntegrationStatus()` → `$this->apiloRepository->apiloIntegrationStatus()`
   - linia ~150: `$this->repository->apiloAuthorize(...)` → `$this->apiloRepository->apiloAuthorize(...)`
   - linia ~159: `$this->repository->apiloIntegrationStatus()` → `$this->apiloRepository->apiloIntegrationStatus()`
   - linia ~194: `$this->repository->apiloCreateProduct(...)` → `$this->apiloRepository->apiloCreateProduct(...)`
   - linia ~211: `$this->repository->apiloProductSearch(...)` → `$this->apiloRepository->apiloProductSearch(...)`
   - linia ~270: `$this->repository->apiloFetchListResult(...)` → `$this->apiloRepository->apiloFetchListResult(...)`

Pozostaw bez zmian: getLogs, clearLogs, getSettings, saveSetting, getProductSku,
linkProduct, unlinkProduct, getSettings('shoppro'), saveSetting('shoppro'), shopproImportProduct
— wszystkie przez `$this->repository`.

**App.php:**

W fabryce 'Integrations' (linia ~384) zmień:
```php
return new \admin\Controllers\IntegrationsController(
    new \Domain\Integrations\IntegrationsRepository( $mdb )
);
```
na:
```php
return new \admin\Controllers\IntegrationsController(
    new \Domain\Integrations\IntegrationsRepository( $mdb ),
    new \Domain\Integrations\ApiloRepository( $mdb )
);
```
php -l autoload/admin/Controllers/IntegrationsController.php — no syntax errors php -l autoload/admin/App.php — no syntax errors grep "apiloRepository" autoload/admin/Controllers/IntegrationsController.php — pokazuje 6+ wystąpień AC-1 spełnione Task 2: Zaktualizuj OrderAdminService i cron.php autoload/Domain/Order/OrderAdminService.php, cron.php **OrderAdminService.php** — 3 metody tworzą IntegrationsRepository i wołają apiloGetAccessToken(). Zmień tylko te 3 miejsca (linie ~422, ~678, ~751):
```php
// PRZED (w każdym z 3 miejsc):
$integrationsRepository = new \Domain\Integrations\IntegrationsRepository($db);
// lub: new \Domain\Integrations\IntegrationsRepository( $mdb );
$accessToken = $integrationsRepository->apiloGetAccessToken();

// PO (w każdym z 3 miejsc):
$apiloRepository = new \Domain\Integrations\ApiloRepository($db);
// lub z $mdb gdzie używano $mdb
$accessToken = $apiloRepository->apiloGetAccessToken();
```

POZOSTAW BEZ ZMIAN (linie ~579, ~628) — te tworzą IntegrationsRepository
i wołają tylko getSettings('apilo') — to metoda generyczna, zostaje w IntegrationsRepository.

**cron.php** — linia ~133:
Po linii `$integrationsRepository = new \Domain\Integrations\IntegrationsRepository( $mdb );`
dodaj:
```php
$apiloRepository = new \Domain\Integrations\ApiloRepository( $mdb );
```

Zamień wywołania apilo* przez `$integrationsRepository` na `$apiloRepository`:
- linia ~191: `$integrationsRepository->apiloKeepalive(300)` → `$apiloRepository->apiloKeepalive(300)`
- linia ~279: `$integrationsRepository->apiloGetAccessToken()` → `$apiloRepository->apiloGetAccessToken()`
- linia ~560: `$integrationsRepository->apiloGetAccessToken()` → `$apiloRepository->apiloGetAccessToken()`
- linia ~589: `$integrationsRepository->apiloGetAccessToken()` → `$apiloRepository->apiloGetAccessToken()`
- linia ~642: `$integrationsRepository->apiloGetAccessToken()` → `$apiloRepository->apiloGetAccessToken()`

POZOSTAW BEZ ZMIAN w cron.php:
- `$integrationsRepository->getSettings('apilo')` (linie ~188, ~198, ~553, ~586, ~632)
- `$integrationsRepository->saveSetting('apilo', ...)` (linia ~625)
php -l autoload/Domain/Order/OrderAdminService.php — no syntax errors php -l cron.php — no syntax errors grep "integrationsRepository->apilo" cron.php — brak wyników (wszystkie apilo przeniesione) grep "integrationsRepository->apilo" autoload/Domain/Order/OrderAdminService.php — brak wyników AC-2 spełnione Task 3: Usuń metody apilo* z IntegrationsRepository + cleanup testów autoload/Domain/Integrations/IntegrationsRepository.php, tests/Unit/Domain/Integrations/IntegrationsRepositoryTest.php **IntegrationsRepository.php:**
Usuń następujące bloki (cały kod między komentarzami sekcji a kolejną sekcją):

1. Sekcję "// ── Apilo OAuth" z metodami:
   - `apiloAuthorize()`
   - `apiloGetAccessToken()`
   - `apiloKeepalive()`
   - `refreshApiloAccessToken()` (private)
   - `shouldRefreshAccessToken()` (private)
   - `isFutureDate()` (private)

2. Stałe klasy:
   - `private const APILO_ENDPOINTS = [...]`
   - `private const APILO_SETTINGS_KEYS = [...]`

3. Sekcję "// ── Apilo API fetch lists" z metodami:
   - `apiloFetchList()`
   - `apiloFetchListResult()`
   - `normalizeApiloMapList()` (private)
   - `isMapListShape()` (private)
   - `extractApiloErrorMessage()` (private)

4. Z sekcji "// ── Apilo product operations" usuń tylko:
   - `apiloProductSearch()`
   - `apiloCreateProduct()`
   (ZACHOWAJ `getProductSku()` — jest generyczna, używana też przez ShopProductController)

Po usunięciu IntegrationsRepository powinna zawierać:
- settings (settingsTable, getSettings, getSetting, saveSetting)
- logs (getLogs, deleteLog, clearLogs)
- product linking (linkProduct, unlinkProduct, getProductSku)
- ShopPRO import (shopproImportProduct, missingShopproSetting, shopproDb)

**IntegrationsRepositoryTest.php:**

Usuń następujące metody testowe (zostały już przeniesione do ApiloRepositoryTest):
- `testApiloGetAccessTokenReturnsNullWithoutSettings()`
- `testShouldRefreshAccessTokenReturnsFalseForFarFutureDate()`
- `testShouldRefreshAccessTokenReturnsTrueForNearExpiryDate()`
- `testApiloFetchListThrowsForInvalidType()`
- `testApiloFetchListResultReturnsDetailedErrorWhenConfigMissing()`
- `testApiloIntegrationStatusReturnsMissingConfigMessage()`
- `testNormalizeApiloMapListRejectsErrorPayload()`
- `testNormalizeApiloMapListAcceptsIdNameList()`

W metodzie `testAllPublicMethodsExist()` usuń z tablicy `$expectedMethods` wpisy apilo*:
- `'apiloAuthorize'`, `'apiloGetAccessToken'`, `'apiloKeepalive'`, `'apiloIntegrationStatus'`
- `'apiloFetchList'`, `'apiloFetchListResult'`, `'apiloProductSearch'`, `'apiloCreateProduct'`
(Pozostaw: `'getSettings'`, `'getSetting'`, `'saveSetting'`, `'linkProduct'`, `'unlinkProduct'`,
 `'getProductSku'`, `'shopproImportProduct'`, `'getLogs'`, `'deleteLog'`, `'clearLogs'`)

Usuń też `testSettingsTableMapping()` i `testShopproProviderWorks()` tylko jeśli są duplikatami
(sprawdź przed usunięciem — jeśli nie mają odpowiedników, zostaw).
php -l autoload/Domain/Integrations/IntegrationsRepository.php — no syntax errors grep "apilo" autoload/Domain/Integrations/IntegrationsRepository.php — brak wyników (lub tylko komentarze) php phpunit.phar — wszystkie testy green (826+, zero regresji) php phpunit.phar tests/Unit/Domain/Integrations/ — oba pliki testów green AC-3 i AC-4 spełnione

DO NOT CHANGE

  • autoload/Domain/Integrations/ApiloRepository.php — gotowy, nie modyfikować
  • tests/Unit/Domain/Integrations/ApiloRepositoryTest.php — gotowy, nie modyfikować
  • autoload/admin/Controllers/ShopProductController.php — używa tylko getSetting(), nie apilo*
  • autoload/admin/Controllers/ShopStatusesController.php — używa tylko getSetting(), nie apilo*
  • autoload/admin/Controllers/ShopTransportController.php — używa tylko getSetting(), nie apilo*
  • autoload/admin/Controllers/ShopPaymentMethodController.php — używa tylko getSetting(), nie apilo*
  • Logika biznesowa nie zmienia się — czysta migracja wywołań

SCOPE LIMITS

  • Nie refaktoryzujemy OrderAdminService poza zmianą 3 instancji na ApiloRepository
  • Nie zmieniamy sygnatury metod ani logiki
  • Nie przenosimy ShopPRO import do osobnej klasy (to nie ten plan)
Before declaring plan complete: - [ ] php -l na wszystkich zmodyfikowanych plikach — no syntax errors - [ ] grep "apiloRepository->apilo" w IntegrationsController — 6 wystąpień (apilo metody) - [ ] grep "this->repository->apilo" w IntegrationsController — brak wyników - [ ] grep "integrationsRepository->apilo" w cron.php — brak wyników - [ ] grep "integrationsRepository->apilo" w OrderAdminService — brak wyników - [ ] grep "public function apilo" w IntegrationsRepository — brak wyników - [ ] php phpunit.phar — 826+ testów green

<success_criteria>

  • IntegrationsController używa ApiloRepository dla wszystkich metod apilo*
  • OrderAdminService i cron.php używają ApiloRepository dla apiloGetAccessToken
  • IntegrationsRepository nie zawiera żadnych metod apilo*
  • Pełna suite testów green bez regresji </success_criteria>
After completion, create `.paul/phases/06-integrations-refactoring/06-02-SUMMARY.md`