ver. 0.296: REST API for ordersPRO — orders management, dictionaries, API key auth
- New API layer: ApiRouter, OrdersApiController, DictionariesApiController - Orders API: list (with filters/pagination/updated_since), details, change status, set paid/unpaid - Dictionaries API: order statuses, transport methods, payment methods - X-Api-Key authentication via pp_settings.api_key - OrderRepository: listForApi(), findForApi(), touchUpdatedAt() - updated_at column on pp_shop_orders for polling support - api.php: skip session for API requests, route to ApiRouter - SettingsController: api_key field in system tab - 30 new tests (666 total, 1930 assertions) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
198
docs/API.md
Normal file
198
docs/API.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# shopPRO REST API
|
||||
|
||||
REST API do integracji z ordersPRO i innymi systemami zewnetrznymi.
|
||||
|
||||
## Autentykacja
|
||||
|
||||
Kazde zapytanie wymaga headera `X-Api-Key` z kluczem API.
|
||||
|
||||
```
|
||||
X-Api-Key: {klucz_api}
|
||||
```
|
||||
|
||||
Klucz przechowywany jest w `pp_settings` jako parametr `api_key`. API jest stateless (bez sesji).
|
||||
|
||||
## Format odpowiedzi
|
||||
|
||||
### Sukces (HTTP 200)
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"data": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
### Blad
|
||||
```json
|
||||
{
|
||||
"status": "error",
|
||||
"code": "UNAUTHORIZED",
|
||||
"message": "Invalid or missing API key"
|
||||
}
|
||||
```
|
||||
|
||||
Kody bledow:
|
||||
| Kod | HTTP | Opis |
|
||||
|-----|------|------|
|
||||
| `UNAUTHORIZED` | 401 | Brak lub nieprawidlowy klucz API |
|
||||
| `BAD_REQUEST` | 400 | Brakujace lub niepoprawne parametry |
|
||||
| `NOT_FOUND` | 404 | Nie znaleziono zasobu/endpointu/akcji |
|
||||
| `METHOD_NOT_ALLOWED` | 405 | Nieprawidlowa metoda HTTP |
|
||||
| `INTERNAL_ERROR` | 500 | Blad wewnetrzny serwera |
|
||||
|
||||
## Endpointy
|
||||
|
||||
### Zamowienia
|
||||
|
||||
#### Lista zamowien
|
||||
```
|
||||
GET api.php?endpoint=orders&action=list
|
||||
```
|
||||
|
||||
Parametry filtrowania (opcjonalne):
|
||||
| Parametr | Typ | Opis |
|
||||
|----------|-----|------|
|
||||
| `status` | int | Filtruj po statusie zamowienia |
|
||||
| `paid` | int (0/1) | Filtruj po statusie platnosci |
|
||||
| `date_from` | date (YYYY-MM-DD) | Zamowienia od daty |
|
||||
| `date_to` | date (YYYY-MM-DD) | Zamowienia do daty |
|
||||
| `updated_since` | datetime (YYYY-MM-DD HH:MM:SS) | Zamowienia zmodyfikowane od podanej daty (klucz do pollingu) |
|
||||
| `number` | string | Szukaj po numerze zamowienia |
|
||||
| `client` | string | Szukaj po imieniu, nazwisku lub emailu klienta |
|
||||
| `page` | int | Numer strony (domyslnie 1) |
|
||||
| `per_page` | int | Wynikow na strone (domyslnie 50, max 100) |
|
||||
|
||||
Odpowiedz:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"id": 42,
|
||||
"number": "2026/02/001",
|
||||
"date_order": "2026-02-19 10:30:00",
|
||||
"updated_at": "2026-02-19 12:00:00",
|
||||
"status": 4,
|
||||
"paid": 1,
|
||||
"client_name": "Jan",
|
||||
"client_surname": "Kowalski",
|
||||
"client_email": "jan@example.com",
|
||||
"client_phone": "111222333",
|
||||
"client_street": "Testowa 1",
|
||||
"client_postal_code": "00-000",
|
||||
"client_city": "Warszawa",
|
||||
"firm_name": null,
|
||||
"firm_nip": null,
|
||||
"transport": "Kurier DPD",
|
||||
"transport_cost": 15.00,
|
||||
"payment_method": "Przelew bankowy",
|
||||
"summary": 150.00
|
||||
}
|
||||
],
|
||||
"total": 1,
|
||||
"page": 1,
|
||||
"per_page": 50
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Szczegoly zamowienia
|
||||
```
|
||||
GET api.php?endpoint=orders&action=get&id={order_id}
|
||||
```
|
||||
|
||||
Zwraca pelne dane zamowienia z produktami i historia statusow.
|
||||
|
||||
#### Zmiana statusu zamowienia
|
||||
```
|
||||
PUT api.php?endpoint=orders&action=change_status&id={order_id}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"status_id": 5,
|
||||
"send_email": true
|
||||
}
|
||||
```
|
||||
|
||||
Odpowiedz:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"data": {
|
||||
"order_id": 42,
|
||||
"status_id": 5,
|
||||
"changed": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Oznacz jako oplacone
|
||||
```
|
||||
PUT api.php?endpoint=orders&action=set_paid&id={order_id}
|
||||
```
|
||||
|
||||
Opcjonalnie w body: `{"send_email": true}`
|
||||
|
||||
#### Oznacz jako nieoplacone
|
||||
```
|
||||
PUT api.php?endpoint=orders&action=set_unpaid&id={order_id}
|
||||
```
|
||||
|
||||
### Slowniki
|
||||
|
||||
#### Lista statusow zamowien
|
||||
```
|
||||
GET api.php?endpoint=dictionaries&action=statuses
|
||||
```
|
||||
|
||||
Odpowiedz:
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"data": [
|
||||
{"id": 0, "name": "Nowe"},
|
||||
{"id": 1, "name": "Oplacone"},
|
||||
{"id": 4, "name": "W realizacji"},
|
||||
{"id": 6, "name": "Wyslane"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Lista metod transportu
|
||||
```
|
||||
GET api.php?endpoint=dictionaries&action=transports
|
||||
```
|
||||
|
||||
#### Lista metod platnosci
|
||||
```
|
||||
GET api.php?endpoint=dictionaries&action=payment_methods
|
||||
```
|
||||
|
||||
## Polling
|
||||
|
||||
Aby pobierac tylko nowe/zmienione zamowienia, uzyj parametru `updated_since`:
|
||||
|
||||
```
|
||||
GET api.php?endpoint=orders&action=list&updated_since=2026-02-19 12:00:00
|
||||
```
|
||||
|
||||
Kolumna `updated_at` w `pp_shop_orders` jest aktualizowana automatycznie przy kazdej modyfikacji zamowienia (zmiana statusu, platnosci, edycja danych, tworzenie zamowienia).
|
||||
|
||||
## Konfiguracja
|
||||
|
||||
Klucz API ustawia sie w panelu admina w ustawieniach sklepu lub bezposrednio w bazie:
|
||||
|
||||
```sql
|
||||
INSERT INTO pp_settings (param, value) VALUES ('api_key', 'twoj-klucz-api');
|
||||
-- lub
|
||||
UPDATE pp_settings SET value = 'twoj-klucz-api' WHERE param = 'api_key';
|
||||
```
|
||||
|
||||
## Architektura
|
||||
|
||||
- Entry point: `api.php`
|
||||
- Router: `\api\ApiRouter` (`autoload/api/ApiRouter.php`)
|
||||
- Kontrolery: `autoload/api/Controllers/`
|
||||
- `OrdersApiController` — zamowienia (5 akcji)
|
||||
- `DictionariesApiController` — slowniki (3 akcje)
|
||||
@@ -4,6 +4,26 @@ Logi zmian z migracji na Domain-Driven Architecture. Najnowsze na gorze.
|
||||
|
||||
---
|
||||
|
||||
## ver. 0.296 (2026-02-19) - REST API zamówień dla ordersPRO
|
||||
|
||||
- **NEW**: REST API do zarządzania zamówieniami — lista, szczegóły, zmiana statusu, oznaczanie płatności
|
||||
- **NEW**: Endpointy słownikowe — statusy zamówień, metody transportu, metody płatności
|
||||
- **NEW**: Autentykacja API przez header `X-Api-Key` (klucz w `pp_settings`)
|
||||
- **NEW**: `\api\ApiRouter` — router API z autentykacją, routingiem i helperami odpowiedzi
|
||||
- **NEW**: `\api\Controllers\OrdersApiController` — 5 akcji (list, get, change_status, set_paid, set_unpaid)
|
||||
- **NEW**: `\api\Controllers\DictionariesApiController` — 3 akcje (statuses, transports, payment_methods)
|
||||
- **NEW**: `OrderRepository::listForApi()` — lista zamówień z filtrowaniem i paginacją (z `updated_since` do pollingu)
|
||||
- **NEW**: `OrderRepository::findForApi()` — szczegóły zamówienia z produktami i historią statusów
|
||||
- **NEW**: `OrderRepository::touchUpdatedAt()` — aktualizacja `updated_at` przy modyfikacji zamówienia
|
||||
- **NEW**: Kolumna `pp_shop_orders.updated_at` — data ostatniej modyfikacji (polling API)
|
||||
- **NEW**: Setting `api_key` w `pp_settings` — klucz autentykacji API
|
||||
- **UPDATE**: `api.php` — skip sesji dla requestów API, routing do `ApiRouter`
|
||||
- **UPDATE**: Metody `updateOrderStatus`, `setAsPaid`, `setAsUnpaid`, `saveOrderByAdmin`, `saveNotes`, `createFromBasket` wywołują `touchUpdatedAt()`
|
||||
- **NEW**: `docs/API.md` — dokumentacja REST API
|
||||
- **Tests**: 30 nowych testów API (ApiRouter, OrdersApiController, DictionariesApiController)
|
||||
|
||||
---
|
||||
|
||||
## ver. 0.295 (2026-02-19) - Admin: edycja produktów w zamówieniu + wyszukiwanie AJAX + korekta stanów magazynowych
|
||||
|
||||
- **NEW**: Edycja produktów w zamówieniu z panelu admina (dodawanie, usuwanie, zmiana ilości/cen)
|
||||
|
||||
@@ -110,8 +110,9 @@ Zamówienia sklepu (źródło danych dla list i szczegółów klientów w panelu
|
||||
| payment_method | Nazwa metody płatności |
|
||||
| transport | Nazwa transportu |
|
||||
| message | Wiadomość klienta |
|
||||
| updated_at | Data ostatniej modyfikacji (polling API) |
|
||||
|
||||
**Używane w:** `Domain\Client\ClientRepository::listForAdmin()`, `Domain\Client\ClientRepository::ordersForClient()`, `Domain\Client\ClientRepository::totalsForClient()`.
|
||||
**Używane w:** `Domain\Client\ClientRepository::listForAdmin()`, `Domain\Client\ClientRepository::ordersForClient()`, `Domain\Client\ClientRepository::totalsForClient()`, `Domain\Order\OrderRepository::listForApi()`, `Domain\Order\OrderRepository::findForApi()`.
|
||||
|
||||
**Aktualizacja 2026-02-15 (ver. 0.274):** moduł `/admin/shop_clients/*` korzysta z `Domain\Client\ClientRepository` przez `admin\Controllers\ShopClientsController`.
|
||||
|
||||
|
||||
@@ -72,6 +72,20 @@ Newsletter, Search, ShopBasket, ShopClient, ShopCoupon, ShopOrder, ShopProducer,
|
||||
### Widoki (`front\Views\`) — 11 klas statycznych
|
||||
Articles, Banners, Languages, Menu, Newsletter, Scontainers, ShopCategory, ShopClient, ShopPaymentMethod, ShopProduct, ShopSearch
|
||||
|
||||
## Warstwa API (`autoload/api/`)
|
||||
|
||||
REST API dla ordersPRO. Entry point: `api.php`. Stateless (bez sesji), autentykacja przez `X-Api-Key` header.
|
||||
|
||||
### Router: `api\ApiRouter`
|
||||
- `handle()` — autentykacja → routing → dispatch
|
||||
- Helpery statyczne: `sendSuccess()`, `sendError()`, `getJsonBody()`, `requireMethod()`
|
||||
|
||||
### Kontrolery (`api\Controllers\`)
|
||||
- `OrdersApiController` — lista, szczegoly, zmiana statusu, platnosc (5 akcji)
|
||||
- `DictionariesApiController` — statusy, transporty, metody platnosci (3 akcje)
|
||||
|
||||
Dokumentacja: `docs/API.md`
|
||||
|
||||
## Warstwa wspoldzielona (`autoload/Shared/`)
|
||||
|
||||
| Klasa | Opis |
|
||||
@@ -106,7 +120,7 @@ ProductRepository::productSetsWhenAddToBasket:{id} — zestawy "kupowane r
|
||||
|------|------|
|
||||
| `index.php` | Frontend — autoload, sesja, DB, routing (`front\App`), layout (`front\LayoutEngine`), DOM post-processing |
|
||||
| `ajax.php` | Frontend AJAX — koszyk, transport, kontakt |
|
||||
| `api.php` | REST API (Ekomi CSV) |
|
||||
| `api.php` | REST API (ordersPRO + Ekomi CSV) — router: `\api\ApiRouter`, kontrolery: `\api\Controllers\` |
|
||||
| `admin/index.php` | Admin — autoload, sesja, DB, routing (`admin\App`) |
|
||||
| `admin/ajax.php` | Admin AJAX |
|
||||
| `cron.php` | CRON: Apilo sync (ceny/stany co 10min, cennik co 1h, retry queue) |
|
||||
|
||||
@@ -23,10 +23,10 @@ composer test # standard
|
||||
## Aktualny stan
|
||||
|
||||
```text
|
||||
OK (636 tests, 1868 assertions)
|
||||
OK (666 tests, 1930 assertions)
|
||||
```
|
||||
|
||||
Zweryfikowano: 2026-02-19 (ver. 0.295)
|
||||
Zweryfikowano: 2026-02-19 (ver. 0.296)
|
||||
|
||||
## Konfiguracja
|
||||
|
||||
@@ -85,12 +85,17 @@ tests/
|
||||
| |-- ShopStatusesControllerTest.php
|
||||
| |-- ShopTransportControllerTest.php
|
||||
| `-- UsersControllerTest.php
|
||||
| `-- api/
|
||||
| |-- ApiRouterTest.php
|
||||
| `-- Controllers/
|
||||
| |-- OrdersApiControllerTest.php
|
||||
| `-- DictionariesApiControllerTest.php
|
||||
`-- Integration/ (puste — zarezerwowane)
|
||||
```
|
||||
|
||||
## Dodawanie nowych testow
|
||||
|
||||
1. Plik w `tests/Unit/Domain/<Module>/<Class>Test.php` lub `tests/Unit/admin/Controllers/<Class>Test.php`.
|
||||
1. Plik w `tests/Unit/Domain/<Module>/<Class>Test.php`, `tests/Unit/admin/Controllers/<Class>Test.php` lub `tests/Unit/api/Controllers/<Class>Test.php`.
|
||||
2. Rozszerz `PHPUnit\Framework\TestCase`.
|
||||
3. Nazwy metod zaczynaj od `test`.
|
||||
4. Wzorzec AAA: Arrange, Act, Assert.
|
||||
|
||||
@@ -18,16 +18,17 @@ Aktualizacje znajdują się w folderze `updates/0.XX/` gdzie XX oznacza dziesią
|
||||
|
||||
## Procedura tworzenia nowej aktualizacji
|
||||
|
||||
## Status biezacej aktualizacji (ver. 0.295)
|
||||
## Status biezacej aktualizacji (ver. 0.296)
|
||||
|
||||
- Wersja udostepniona: `0.295` (data: 2026-02-19).
|
||||
- Wersja udostepniona: `0.296` (data: 2026-02-19).
|
||||
- Pliki publikacyjne:
|
||||
- `updates/0.20/ver_0.295.zip`
|
||||
- `updates/0.20/ver_0.296.zip`
|
||||
- `updates/0.20/ver_0.296_sql.txt`
|
||||
- Pliki metadanych aktualizacji:
|
||||
- `updates/changelog.php`
|
||||
- `updates/versions.php` (`$current_ver = 295`)
|
||||
- `updates/versions.php` (`$current_ver = 296`)
|
||||
- Weryfikacja testow przed publikacja:
|
||||
- `OK (636 tests, 1868 assertions)`
|
||||
- `OK (666 tests, 1930 assertions)`
|
||||
|
||||
### 1. Określ numer wersji
|
||||
Sprawdź ostatnią wersję w `updates/` i zwiększ o 1.
|
||||
|
||||
Reference in New Issue
Block a user