Files
orderPRO/.paul/phases/23-shipment-presets-backend/23-01-PLAN.md
Jacek Pyziak 03a237e7d2 feat(23-shipment-presets-backend): tabela DB, repository CRUD i JSON API dla presetów przesyłek
Phase 23 complete:
- Migracja shipment_presets (16 kolumn: name, color, carrier, wymiary, waga, itp.)
- ShipmentPresetRepository z findAll/findById/create/update/delete
- ShipmentPresetController z 4 endpointami JSON API
- Routing w routes/web.php z auth middleware

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 23:27:14 +01:00

8.9 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous
phase plan type wave depends_on files_modified autonomous
23-shipment-presets-backend 01 execute 1
database/migrations/20260322_000059_create_shipment_presets_table.sql
src/Modules/Shipments/ShipmentPresetRepository.php
src/Modules/Shipments/ShipmentPresetController.php
routes/web.php
true
## Goal Stworzyć tabelę DB `shipment_presets` oraz pełny backend CRUD (JSON API) do zarządzania presetami przesyłek.

Purpose

Presety przesyłek pozwalają użytkownikom jednym kliknięciem wypełnić formularz przygotowania przesyłki zapisanymi wcześniej parametrami (przewoźnik, usługa, wymiary, waga itp.). Ta faza buduje fundament danych i API — UI będzie w fazie 24.

Output

  • Migracja SQL tworząca tabelę shipment_presets
  • ShipmentPresetRepository z metodami CRUD
  • ShipmentPresetController z endpointami JSON API
  • Routing w routes/web.php
## Project Context @.paul/PROJECT.md @.paul/ROADMAP.md @.paul/STATE.md

Source Files

@routes/web.php @src/Modules/Shipments/ShipmentController.php @src/Modules/Shipments/ShipmentPackageRepository.php @resources/views/shipments/prepare.php

No specialized flows required for this plan (SPECIAL-FLOWS.md: sonar-scanner required post-APPLY).

<acceptance_criteria>

AC-1: Tabela shipment_presets istnieje w bazie

Given migracja została uruchomiona
When sprawdzam strukturę tabeli shipment_presets
Then tabela zawiera kolumny: id, name, color, carrier, provider_code, delivery_method_id, credentials_id, carrier_id, package_type, length_cm, width_cm, height_cm, weight_kg, sender_point_id, label_format, sort_order, created_at, updated_at

AC-2: API zwraca listę presetów

Given w tabeli istnieją presety
When wysyłam GET /api/shipment-presets
Then otrzymuję JSON z tablicą presetów posortowanych po sort_order

AC-3: API tworzy nowy preset

Given wysyłam POST /api/shipment-presets z danymi formularza
When dane są poprawne (name wymagane)
Then preset zostaje zapisany w bazie i zwrócony jako JSON z id

AC-4: API aktualizuje preset

Given istnieje preset o id=1
When wysyłam PUT /api/shipment-presets/1 z nowymi danymi
Then preset zostaje zaktualizowany w bazie

AC-5: API usuwa preset

Given istnieje preset o id=1
When wysyłam DELETE /api/shipment-presets/1
Then preset zostaje usunięty z bazy

</acceptance_criteria>

Task 1: Migracja DB — tabela shipment_presets database/migrations/20260322_000059_create_shipment_presets_table.sql Utworzyć migrację SQL tworzącą tabelę `shipment_presets`:
```sql
CREATE TABLE shipment_presets (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  color VARCHAR(7) NOT NULL DEFAULT '#3b82f6',
  carrier VARCHAR(32) NOT NULL COMMENT 'allegro, inpost, apaczka',
  provider_code VARCHAR(32) NOT NULL COMMENT 'allegro_wza, apaczka, inpost',
  delivery_method_id VARCHAR(128) NOT NULL,
  credentials_id VARCHAR(128) NOT NULL DEFAULT '',
  carrier_id VARCHAR(64) NOT NULL DEFAULT '',
  package_type VARCHAR(16) NOT NULL DEFAULT 'PACKAGE',
  length_cm DECIMAL(8,1) NOT NULL DEFAULT 25.0,
  width_cm DECIMAL(8,1) NOT NULL DEFAULT 20.0,
  height_cm DECIMAL(8,1) NOT NULL DEFAULT 8.0,
  weight_kg DECIMAL(8,3) NOT NULL DEFAULT 1.000,
  sender_point_id VARCHAR(64) NOT NULL DEFAULT '',
  label_format VARCHAR(8) NOT NULL DEFAULT 'PDF',
  sort_order INT UNSIGNED NOT NULL DEFAULT 0,
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```

Kolumna `color` przechowuje hex kolor przycisku (np. #3b82f6).
Brak user_id — presety globalne.
Uruchomić migrację na bazie: php -l na pliku SQL nie ma sensu, ale sprawdzić składnię wizualnie. Migracja zostanie uruchomiona ręcznie. AC-1 satisfied: tabela shipment_presets z pełnym zestawem kolumn Task 2: ShipmentPresetRepository — CRUD na tabeli src/Modules/Shipments/ShipmentPresetRepository.php Utworzyć klasę `ShipmentPresetRepository` w namespace `App\Modules\Shipments`:
- Constructor: `__construct(private readonly PDO $pdo)`
- `findAll(): array` — SELECT * ORDER BY sort_order ASC, id ASC
- `findById(int $id): ?array` — SELECT WHERE id = :id
- `create(array $data): int` — INSERT, return lastInsertId
- `update(int $id, array $data): void` — UPDATE WHERE id = :id
- `delete(int $id): void` — DELETE WHERE id = :id

Wzorować się na istniejącym `ShipmentPackageRepository` — ten sam styl (PDO prepared statements, final class).

Kolumny do zapisu w create/update:
name, color, carrier, provider_code, delivery_method_id, credentials_id, carrier_id,
package_type, length_cm, width_cm, height_cm, weight_kg, sender_point_id, label_format, sort_order

Avoid: Medoo — ten moduł używa czystego PDO (jak ShipmentPackageRepository).
php -l src/Modules/Shipments/ShipmentPresetRepository.php — brak błędów składniowych AC-2 partially (repository layer ready), AC-3, AC-4, AC-5 data layer ready Task 3: ShipmentPresetController + routing src/Modules/Shipments/ShipmentPresetController.php, routes/web.php 1. Utworzyć `ShipmentPresetController` w namespace `App\Modules\Shipments`: - Constructor: `__construct(private readonly ShipmentPresetRepository $repository)` - `list(Request $request): Response` — GET, zwraca JSON array presetów - `store(Request $request): Response` — POST, walidacja (name required), tworzy preset, zwraca JSON z id + 201 - `update(Request $request): Response` — PUT, walidacja, aktualizuje preset, zwraca JSON 200 - `destroy(Request $request): Response` — DELETE, usuwa preset, zwraca JSON 204
   Dla store/update wyciągnąć dane z request:
   - name, color, carrier, provider_code, delivery_method_id, credentials_id, carrier_id,
     package_type, length_cm, width_cm, height_cm, weight_kg, sender_point_id, label_format, sort_order

   Walidacja: `name` nie może być pusty. Resztę ustawić z defaults.
   Brak CSRF dla JSON API — ale wymagać auth middleware.

2. W `routes/web.php`:
   - Dodać `use App\Modules\Shipments\ShipmentPresetRepository;`
   - Dodać `use App\Modules\Shipments\ShipmentPresetController;`
   - Instancja: `$presetRepository = new ShipmentPresetRepository($app->db());`
   - Instancja: `$presetController = new ShipmentPresetController($presetRepository);`
   - Routing (z $authMiddleware):
     ```
     $router->get('/api/shipment-presets', [$presetController, 'list'], [$authMiddleware]);
     $router->post('/api/shipment-presets', [$presetController, 'store'], [$authMiddleware]);
     $router->put('/api/shipment-presets/{id}', [$presetController, 'update'], [$authMiddleware]);
     $router->delete('/api/shipment-presets/{id}', [$presetController, 'destroy'], [$authMiddleware]);
     ```

   Umieścić routing w sekcji API (po print API routes, przed zamknięciem).

Wzorować styl Response na istniejących API controllerach (PrintApiController — Response::json).
php -l src/Modules/Shipments/ShipmentPresetController.php — brak błędów składniowych. Sprawdzić że routes/web.php nie ma syntax errors: php -l routes/web.php AC-2, AC-3, AC-4, AC-5 satisfied: pełny JSON API dla presetów

DO NOT CHANGE

  • src/Modules/Shipments/ShipmentController.php (modyfikacja w fazie 24)
  • resources/views/shipments/prepare.php (modyfikacja w fazie 24)
  • src/Modules/Shipments/ShipmentPackageRepository.php (stabilne)
  • Istniejące migracje w database/migrations/

SCOPE LIMITS

  • Tylko backend (tabela + repository + controller + routing)
  • Brak zmian UI — to faza 24
  • Brak walidacji CSRF w API JSON (auth middleware wystarczający)
  • Presety globalne (bez user_id)
Before declaring plan complete: - [ ] Migracja SQL poprawna składniowo - [ ] php -l na ShipmentPresetRepository.php — OK - [ ] php -l na ShipmentPresetController.php — OK - [ ] php -l na routes/web.php — OK - [ ] Routing dodany z auth middleware - [ ] All acceptance criteria met

<success_criteria>

  • Tabela shipment_presets gotowa do migracji
  • Repository z pełnym CRUD
  • Controller z 4 endpointami JSON API
  • Routing zarejestrowany w routes/web.php
  • Brak błędów PHP </success_criteria>
After completion, create `.paul/phases/23-shipment-presets-backend/23-01-SUMMARY.md`