update
This commit is contained in:
@@ -2,11 +2,11 @@
|
||||
|
||||
## What This Is
|
||||
|
||||
Autorski silnik sklepu internetowego pisany od podstaw — odpowiednik WooCommerce lub PrestaShop, ale bez zależności od zewnętrznych platform. Składa się z panelu administratora (zarządzanie zamówieniami, produktami, klientami) oraz części frontowej dla klienta końcowego.
|
||||
Autorski silnik sklepu internetowego pisany od podstaw - odpowiednik WooCommerce lub PrestaShop, ale bez zależności od zewnętrznych platform. Składa się z panelu administratora (zarządzanie zamówieniami, produktami, klientami) oraz części frontowej dla klienta końcowego.
|
||||
|
||||
## Core Value
|
||||
|
||||
Właściciel sklepu internetowego ma pełną kontrolę nad sprzedażą online — produktami, zamówieniami i klientami — w jednym spójnym systemie pisanym od podstaw, bez narzutów zewnętrznych platform.
|
||||
Właściciel sklepu internetowego ma pełną kontrolę nad sprzedażą online - produktami, zamówieniami i klientami - w jednym spójnym systemie pisanym od podstaw, bez narzutów zewnętrznych platform.
|
||||
|
||||
## Current State
|
||||
|
||||
@@ -20,16 +20,16 @@ Właściciel sklepu internetowego ma pełną kontrolę nad sprzed
|
||||
|
||||
### Validated (Shipped)
|
||||
|
||||
- [x] Panel administratora — zarządzanie produktami, kategoriami, atrybutami
|
||||
- [x] Panel administratora — zarządzanie zamówieniami
|
||||
- [x] Panel administratora — zarządzanie klientami
|
||||
- [x] Część frontowa — przeglądanie i kupowanie produktów
|
||||
- [x] Koszyk i składanie zamówień
|
||||
- [x] Integracje płatności i dostaw
|
||||
- [x] Panel administratora - zarządzanie produktami, kategoriami, atrybutami
|
||||
- [x] Panel administratora - zarządzanie zamówieniami
|
||||
- [x] Panel administratora - zarządzanie klientami
|
||||
- [x] Część frontowa - przeglądanie i kupowanie produktów
|
||||
- [x] Koszyk i składanie zamówień
|
||||
- [x] Integracje płatności i dostaw
|
||||
- [x] REST API (ordersPRO + Ekomi)
|
||||
- [x] Redis caching
|
||||
- [x] Ochrona przed podwójnym składaniem zamówienia
|
||||
- [x] Domain-Driven Architecture (migracja z legacy zakończona)
|
||||
- [x] Ochrona przed podwójnym składaniem zamówienia
|
||||
- [x] Domain-Driven Architecture (migracja z legacy zakończona)
|
||||
|
||||
### Active (In Progress)
|
||||
|
||||
@@ -41,16 +41,16 @@ Właściciel sklepu internetowego ma pełną kontrolę nad sprzed
|
||||
|
||||
### Out of Scope
|
||||
|
||||
- Multitenancy (wiele sklepów w jednej instancji) — nie planowane
|
||||
- Multitenancy (wiele sklepów w jednej instancji) - nie planowane
|
||||
|
||||
## Target Users
|
||||
|
||||
**Primary:** Właściciel/administrator sklepu internetowego
|
||||
- ZarzÄ…dza produktami, zamĂłwieniami, klientami przez panel admina
|
||||
- Potrzebuje niezawodnego, szybkiego narzędzia bez zbędnych zależności
|
||||
**Primary:** Właściciel/administrator sklepu internetowego
|
||||
- Zarządza produktami, zamówieniami, klientami przez panel admina
|
||||
- Potrzebuje niezawodnego, szybkiego narzędzia bez zbędnych zależności
|
||||
|
||||
**Secondary:** Klient końcowy sklepu
|
||||
- Przegląda produkty, dodaje do koszyka, składa zamówienia
|
||||
**Secondary:** Klient końcowy sklepu
|
||||
- Przegląda produkty, dodaje do koszyka, składa zamówienia
|
||||
|
||||
## Context
|
||||
|
||||
@@ -58,26 +58,26 @@ Właściciel sklepu internetowego ma pełną kontrolę nad sprzed
|
||||
- PHP 7.4+ (produkcja: PHP < 8.0)
|
||||
- Medoo ORM (`$mdb`), Redis caching
|
||||
- Domain-Driven Design z Dependency Injection
|
||||
- PHPUnit 9.6, 810+ testĂłw
|
||||
- PHPUnit 9.6, 810+ testów
|
||||
- Namespace: `\Domain\`, `\admin\`, `\front\`, `\api\`, `\Shared\`
|
||||
|
||||
## Constraints
|
||||
|
||||
### Technical Constraints
|
||||
- PHP < 8.0 na produkcji (brak `match`, named arguments, union types)
|
||||
- Medoo ORM — prepared statements bez wyjątków
|
||||
- Medoo ORM - prepared statements bez wyjątków
|
||||
- Redis wymagany dla cache
|
||||
|
||||
### Business Constraints
|
||||
- System wdraĹĽany u klientĂłw jako update package (ZIP)
|
||||
- System wdrażany u klientów jako update package (ZIP)
|
||||
|
||||
## Key Decisions
|
||||
|
||||
| Decision | Rationale | Date | Status |
|
||||
|----------|-----------|------|--------|
|
||||
| DDD + DI zamiast legacy architektury | Testowalność, separacja odpowiedzialności | 2025 | Active |
|
||||
| PHP < 8.0 kompatybilność | Klienci na starszych serwerach | 2025 | Active |
|
||||
| Własny silnik zamiast frameworka | Pełna kontrola, brak narzutów | - | Active |
|
||||
| DDD + DI zamiast legacy architektury | Testowalność, separacja odpowiedzialności | 2025 | Active |
|
||||
| PHP < 8.0 kompatybilność | Klienci na starszych serwerach | 2025 | Active |
|
||||
| Własny silnik zamiast frameworka | Pełna kontrola, brak narzutów | - | Active |
|
||||
| `id` w tabbed FormEdit przez `hiddenFields` | Zapobiega insert zamiast update przy edycji encji | 2026-04-18 | Active |
|
||||
|
||||
## Success Metrics
|
||||
@@ -94,7 +94,7 @@ Właściciel sklepu internetowego ma pełną kontrolę nad sprzed
|
||||
| Backend | PHP 7.4+ | < 8.0 na produkcji |
|
||||
| ORM | Medoo | `$mdb` global |
|
||||
| Cache | Redis | CacheHandler singleton |
|
||||
| Frontend | HTML/CSS/JS | Własny silnik szablonów (Tpl) |
|
||||
| Frontend | HTML/CSS/JS | Własny silnik szablonów (Tpl) |
|
||||
| Auth | Sesje PHP | CSRF, XSS protection |
|
||||
| Testy | PHPUnit 9.6 | phpunit.phar |
|
||||
|
||||
@@ -103,15 +103,14 @@ Właściciel sklepu internetowego ma pełną kontrolę nad sprzed
|
||||
See: .paul/SPECIAL-FLOWS.md
|
||||
|
||||
Quick Reference:
|
||||
- /feature-dev → Nowe funkcje, większe zmiany (required)
|
||||
- /koniec-pracy → Release, update package (required)
|
||||
- /frontend-design → Komponenty UI, szablony widoków
|
||||
- /code-review → Przegląd kodu przed release
|
||||
- /simplify → Upraszczanie po implementacji
|
||||
- /claude-md-improver → Utrzymanie CLAUDE.md
|
||||
- /zapisz + /wznow → Zapis i wznowienie sesji
|
||||
- /feature-dev -> Nowe funkcje, większe zmiany (required)
|
||||
- /koniec-pracy -> Release, update package (required)
|
||||
- /frontend-design -> Komponenty UI, szablony widoków
|
||||
- /code-review -> Przegląd kodu przed release
|
||||
- /simplify -> Upraszczanie po implementacji
|
||||
- /claude-md-improver -> Utrzymanie CLAUDE.md
|
||||
- /zapisz + /wznow -> Zapis i wznowienie sesji
|
||||
|
||||
---
|
||||
*PROJECT.md — Updated when requirements or context change*
|
||||
*PROJECT.md - Updated when requirements or context change*
|
||||
*Last updated: 2026-04-18 after Phase 15*
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Overview
|
||||
|
||||
shopPRO to autorski silnik sklepu internetowego rozwijany iteracyjnie. Projekt jest już na produkcji (v0.333) — roadmap obejmuje planowane funkcje i usprawnienia kolejnych wersji.
|
||||
shopPRO to autorski silnik sklepu internetowego rozwijany iteracyjnie. Projekt jest już na produkcji (v0.333) — roadmap obejmuje planowane funkcje i usprawnienia kolejnych wersji.
|
||||
|
||||
## Current Milestone
|
||||
|
||||
@@ -16,25 +16,25 @@ Phases: 4 of 4 complete
|
||||
|-------|------|-------|--------|-----------|
|
||||
| 1 | Sensitive data logging fix | 1 | Done | 2026-03 |
|
||||
| 2 | Path traversal + XSS escaping | 1 | Done | 2026-03 (v0.335) |
|
||||
| 3 | Error handling w krytycznych ścieżkach | 1 | Done | 2026-03 (v0.336) |
|
||||
| 4 | CSRF protection — admin panel forms | 1 | Applied | 2026-03 (v0.337) |
|
||||
| 5 | Order bugs fix — duplicate + COD status | 1 | Applied | 2026-03 (v0.338) |
|
||||
| 3 | Error handling w krytycznych ścieżkach | 1 | Done | 2026-03 (v0.336) |
|
||||
| 4 | CSRF protection — admin panel forms | 1 | Applied | 2026-03 (v0.337) |
|
||||
| 5 | Order bugs fix — duplicate + COD status | 1 | Applied | 2026-03 (v0.338) |
|
||||
|
||||
## Next Milestone
|
||||
|
||||
**Tech debt — Integrations refactoring**
|
||||
**Tech debt — Integrations refactoring**
|
||||
Status: Planning
|
||||
|
||||
| Phase | Name | Plans | Status | Completed |
|
||||
|-------|------|-------|--------|-----------|
|
||||
| 6 | IntegrationsRepository split → ApiloRepository | 2 | Done | 2026-03 |
|
||||
| 6 | IntegrationsRepository split → ApiloRepository | 2 | Done | 2026-03 |
|
||||
|
||||
## Hotfix
|
||||
|
||||
| Phase | Name | Plans | Status | Completed |
|
||||
|-------|------|-------|--------|-----------|
|
||||
| 7 | Coupon Fatal Error — order placement crash | 1 | Done | 2026-03-15 |
|
||||
| 8 | Apilo orders not sending — diagnoza i naprawa | 1 | Done | 2026-03-16 |
|
||||
| 7 | Coupon Fatal Error — order placement crash | 1 | Done | 2026-03-15 |
|
||||
| 8 | Apilo orders not sending — diagnoza i naprawa | 1 | Done | 2026-03-16 |
|
||||
| 9 | Apilo email notification + infinite retry | 1 | Done | 2026-03-19 |
|
||||
| 15 | Scontainers edit saves as new record | 1 | Done | 2026-04-18 |
|
||||
|
||||
@@ -44,72 +44,72 @@ Status: Planning
|
||||
|-------|------|-------|--------|-----------|
|
||||
| 10 | Edycja personalizacji produktu w koszyku | 1 | Done | 2026-03-19 |
|
||||
| 11 | DataLayer GA4 analytics fix | 1 | Done | 2026-03-25 |
|
||||
| 12 | summaryView redirect fix — double order block | 1 | Done | 2026-03-25 |
|
||||
| 12 | summaryView redirect fix — double order block | 1 | Done | 2026-03-25 |
|
||||
| 13 | Basket logging + TTL token fix | 1 | Done | 2026-03-25 |
|
||||
| 14 | Custom fields delete bug — usunięcie wszystkich pól | 1 | Done | 2026-04-16 |
|
||||
| 14 | Custom fields delete bug — usunięcie wszystkich pól | 1 | Done | 2026-04-16 |
|
||||
|
||||
## Phase Details
|
||||
|
||||
### Phase 4 — CSRF protection
|
||||
### Phase 4 — CSRF protection
|
||||
|
||||
**Problem:** Brak tokenĂłw CSRF na formularzach panelu admina. State-changing POST endpointy (create/update/delete) sÄ… potencjalnie podatne na ataki CSRF.
|
||||
**Problem:** Brak tokenów CSRF na formularzach panelu admina. State-changing POST endpointy (create/update/delete) są potencjalnie podatne na ataki CSRF.
|
||||
|
||||
**Scope:** Dodanie CSRF tokenĂłw do formularzy i walidacji w panelu administracyjnym.
|
||||
**Scope:** Dodanie CSRF tokenów do formularzy i walidacji w panelu administracyjnym.
|
||||
|
||||
**Reference:** `.paul/codebase/concerns.md` — MEDIUM — Missing CSRF tokens
|
||||
**Reference:** `.paul/codebase/concerns.md` — MEDIUM — Missing CSRF tokens
|
||||
|
||||
### Phase 6 — IntegrationsRepository split
|
||||
### Phase 6 — IntegrationsRepository split
|
||||
|
||||
**Problem:** `IntegrationsRepository` ma 875 linii — miesza logikę generyczną (settings, logi, product linking) z logiką specyficzną dla Apilo (~650 linii). Narusza zasadę jednej odpowiedzialności.
|
||||
**Problem:** `IntegrationsRepository` ma 875 linii — miesza logikę generyczną (settings, logi, product linking) z logiką specyficzną dla Apilo (~650 linii). Narusza zasadę jednej odpowiedzialności.
|
||||
|
||||
**Scope:**
|
||||
- Plan 06-01: UtwĂłrz `ApiloRepository` z metodami apilo* (non-breaking)
|
||||
- Plan 06-02: Zmigruj konsumentów (IntegrationsController, ShopProductController, OrderAdminService, cron.php), usuń apilo* z IntegrationsRepository
|
||||
- Plan 06-01: Utwórz `ApiloRepository` z metodami apilo* (non-breaking)
|
||||
- Plan 06-02: Zmigruj konsumentów (IntegrationsController, ShopProductController, OrderAdminService, cron.php), usuń apilo* z IntegrationsRepository
|
||||
|
||||
---
|
||||
|
||||
### Phase 5 — Order bugs fix
|
||||
### Phase 5 — Order bugs fix
|
||||
|
||||
**Problem 1:** Zduplikowane zamówienia — klient widzi błąd i klika złóż zamówienie ponownie. Pierwsze zamówienie trafiło do bazy mimo błędu. Powrót do `/podsumowanie` regeneruje token i pozwala złożyć drugie zamówienie.
|
||||
**Problem 1:** Zduplikowane zamówienia — klient widzi błąd i klika złóż zamówienie ponownie. Pierwsze zamówienie trafiło do bazy mimo błędu. Powrót do `/podsumowanie` regeneruje token i pozwala złożyć drugie zamówienie.
|
||||
|
||||
**Problem 2:** Zamówienia COD (płatność przy odbiorze) dostają status "Zamówienie złożone" zamiast "Przyjęte do realizacji". Kod sprawdza hardkodowane `payment_id == 3`, które jest inne w tej instancji sklepu.
|
||||
**Problem 2:** Zamówienia COD (płatność przy odbiorze) dostają status "Zamówienie złożone" zamiast "Przyjęte do realizacji". Kod sprawdza hardkodowane `payment_id == 3`, które jest inne w tej instancji sklepu.
|
||||
|
||||
**Scope:** Guard w `summaryView()`, try-catch w `basketSave()`, kolumna `is_cod` w `pp_shop_payment_methods`, uĹĽycie flagi zamiast hardkodowanego ID.
|
||||
**Scope:** Guard w `summaryView()`, try-catch w `basketSave()`, kolumna `is_cod` w `pp_shop_payment_methods`, użycie flagi zamiast hardkodowanego ID.
|
||||
|
||||
---
|
||||
*Roadmap created: 2026-03-12*
|
||||
### Phase 11 — DataLayer GA4 analytics fix
|
||||
|
||||
**Problem:** Eventy dataLayer ecommerce (purchase, begin_checkout, view_item, add_to_cart) używają starego formatu UA (id/name zamiast item_id/item_name), brak currency w view_item, price:0 w purchase, brak eventu view_cart. Remarketing dynamiczny i konwersje GA4 nie działają poprawnie.
|
||||
### Phase 11 — DataLayer GA4 analytics fix
|
||||
|
||||
**Scope:** Poprawka 4 istniejÄ…cych eventĂłw do formatu GA4 + dodanie nowego eventu view_cart na stronie koszyka.
|
||||
**Problem:** Eventy dataLayer ecommerce (purchase, begin_checkout, view_item, add_to_cart) używają starego formatu UA (id/name zamiast item_id/item_name), brak currency w view_item, price:0 w purchase, brak eventu view_cart. Remarketing dynamiczny i konwersje GA4 nie działają poprawnie.
|
||||
|
||||
**Reference:** `poprawki_datalayer_projectpro.md` — audyt analityki z pomysloweprezenty.pl
|
||||
**Scope:** Poprawka 4 istniejących eventów do formatu GA4 + dodanie nowego eventu view_cart na stronie koszyka.
|
||||
|
||||
### Phase 12 — summaryView redirect fix
|
||||
**Reference:** `poprawki_datalayer_projectpro.md` — audyt analityki z pomysloweprezenty.pl
|
||||
|
||||
**Problem:** Po złożeniu pierwszego zamówienia, guard w `summaryView()` sprawdzał sesyjny `order-submit-last-order-id` i redirectował na stronę starego zamówienia. Blokował dostęp do `/koszyk-podsumowanie` dla kolejnych zamówień. Poprawka z instancji klienta (change.md) do wdrożenia globalnie.
|
||||
### Phase 12 — summaryView redirect fix
|
||||
|
||||
**Scope:** Usunięcie bloku redirect z `summaryView()` w `ShopBasketController.php`. Double-submit protection w `basketSave()` pozostaje bez zmian.
|
||||
**Problem:** Po złożeniu pierwszego zamówienia, guard w `summaryView()` sprawdzał sesyjny `order-submit-last-order-id` i redirectował na stronę starego zamówienia. Blokował dostęp do `/koszyk-podsumowanie` dla kolejnych zamówień. Poprawka z instancji klienta (change.md) do wdrożenia globalnie.
|
||||
|
||||
### Phase 13 — Basket logging + TTL token fix
|
||||
**Scope:** Usunięcie bloku redirect z `summaryView()` w `ShopBasketController.php`. Double-submit protection w `basketSave()` pozostaje bez zmian.
|
||||
|
||||
**Problem:** Brak logowania w basketSave() uniemożliwia diagnozę błędów zamówień. Token zamówienia jednorazowy — nadpisywany przy każdym wejściu na podsumowanie, co powoduje że druga karta, "wstecz" lub odświeżenie unieważnia formularz.
|
||||
### Phase 13 — Basket logging + TTL token fix
|
||||
|
||||
**Scope:** Dodanie metody logOrder() z 4 punktami logowania, zmiana tokena z jednorazowego na TTL 30 min, redirect przy błędzie tokena na /koszyk-podsumowanie zamiast /koszyk, nowy double-submit guard.
|
||||
**Problem:** Brak logowania w basketSave() uniemożliwia diagnozę błędów zamówień. Token zamówienia jednorazowy — nadpisywany przy każdym wejściu na podsumowanie, co powoduje że druga karta, "wstecz" lub odświeżenie unieważnia formularz.
|
||||
|
||||
### Phase 14 — Custom fields delete bug
|
||||
**Scope:** Dodanie metody logOrder() z 4 punktami logowania, zmiana tokena z jednorazowego na TTL 30 min, redirect przy błędzie tokena na /koszyk-podsumowanie zamiast /koszyk, nowy double-submit guard.
|
||||
|
||||
**Problem:** Usunięcie WSZYSTKICH dodatkowych pól z produktu nie działa. jQuery `.serialize()` nie wysyła klucza `custom_field_name[]` gdy nie ma żadnych pól → `array_key_exists('custom_field_name', $d)` w ProductRepository zwraca false → `saveCustomFields()` nigdy nie jest wywoływany → pola pozostają w bazie.
|
||||
### Phase 14 — Custom fields delete bug
|
||||
|
||||
**Problem:** Usunięcie WSZYSTKICH dodatkowych pól z produktu nie działa. jQuery `.serialize()` nie wysyła klucza `custom_field_name[]` gdy nie ma żadnych pól → `array_key_exists('custom_field_name', $d)` w ProductRepository zwraca false → `saveCustomFields()` nigdy nie jest wywoływany → pola pozostają w bazie.
|
||||
|
||||
**Scope:** Dodanie hidden markera `custom_field_name_present` w szablonie JS + zmiana warunku w ProductRepository na sprawdzanie tego markera. Test jednostkowy.
|
||||
|
||||
### Phase 15 - Scontainers edit saves as new record
|
||||
|
||||
**Problem:** Edycja kontenera statycznego (`/admin/scontainers/edit/id={id}`) zapisuje rekord jako nowy wpis zamiast aktualizacji. W praktyce podczas zapisu gubi sie `id` i repository wykonuje insert.
|
||||
**Problem:** Edycja kontenera statycznego (`/admin/scontainers/edit/id={id}`) zapisuje rekord jako nowy wpis zamiast aktualizacji. W praktyce podczas zapisu gubi się `id` i repository wykonuje insert.
|
||||
|
||||
**Scope:** Poprawic przekazywanie `id` w nowym flow formularza ScontainersController + dodac test regresyjny dla edycji, bez zmian globalnych w innych kontrolerach.
|
||||
**Scope:** Poprawić przekazywanie `id` w nowym flow formularza ScontainersController + dodać test regresyjny dla edycji, bez zmian globalnych w innych kontrolerach.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-18*
|
||||
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
# Specialized Flows: shopPRO
|
||||
# Specialized Flows: shopPRO
|
||||
|
||||
## Project-Level Dependencies
|
||||
|
||||
| Work Type | Skill/Command | Priority | Kiedy używać |
|
||||
| Work Type | Skill/Command | Priority | Kiedy uzywac |
|
||||
|-----------|---------------|----------|--------------|
|
||||
| Komponenty UI, szablony widoków | /frontend-design | optional | Przy tworzeniu HTML/CSS |
|
||||
| Nowe funkcje, większe zmiany | /feature-dev | required | Przed implementacją fazy |
|
||||
| Przegląd kodu | /code-review | optional | Przed release / KONIEC PRACY |
|
||||
| Upraszczanie po zmianach | /simplify | optional | Po zakończeniu implementacji |
|
||||
| Utrzymanie CLAUDE.md | /claude-md-improver | optional | Co kilka faz / po dużych zmianach |
|
||||
| Release, budowanie update package | /koniec-pracy | required | Na koniec każdej sesji roboczej |
|
||||
| Zapis i wznowienie sesji | /zapisz + /wznow | optional | Na przerwę / powrót do pracy |
|
||||
| Komponenty UI, szablony widokow | /frontend-design | optional | Przy tworzeniu HTML/CSS |
|
||||
| Nowe funkcje, wieksze zmiany | /feature-dev | required | Przed implementacja fazy |
|
||||
| Przeglad kodu | /code-review | optional | Przed release / KONIEC PRACY |
|
||||
| Upraszczanie po zmianach | /simplify | optional | Po zakonczeniu implementacji |
|
||||
| Utrzymanie CLAUDE.md | /claude-md-improver | optional | Co kilka faz / po duzych zmianach |
|
||||
| Release, budowanie update package | /koniec-pracy | required | Na koniec kazdej sesji roboczej |
|
||||
| Zapis i wznowienie sesji | /zapisz + /wznow | optional | Na przerwe / powrot do pracy |
|
||||
|
||||
## Phase Overrides
|
||||
|
||||
Brak — domyślna konfiguracja obowiązuje dla wszystkich faz.
|
||||
Brak - domyslna konfiguracja obowiazuje dla wszystkich faz.
|
||||
|
||||
## Templates & Assets
|
||||
|
||||
| Asset Type | Location | When Used |
|
||||
|------------|----------|-----------|
|
||||
| CLAUDE.md | CLAUDE.md | Konwencje kodu, architektura, stack techniczny |
|
||||
| Struktura bazy | docs/DATABASE_STRUCTURE.md | Przy zmianach schematu DB |
|
||||
| Dokumentacja API | api-docs/api-reference.json | Przy zmianach API |
|
||||
| TODO | docs/TODO.md | Planowanie nowych funkcji |
|
||||
| Struktura bazy | .paul/docs/DB_SCHEMA.md | Przy zmianach schematu DB |
|
||||
| Dokumentacja API | .paul/docs/API.md | Przy zmianach API |
|
||||
| TODO | .paul/docs/TODO.md | Planowanie nowych funkcji |
|
||||
|
||||
## Verification (UNIFY)
|
||||
|
||||
Podczas UNIFY sprawdź:
|
||||
- `/feature-dev` — czy był użyty przed implementacją fazy?
|
||||
- `/koniec-pracy` — czy release został wykonany?
|
||||
Podczas UNIFY sprawdz:
|
||||
- `/feature-dev` - czy byl uzyty przed implementacja fazy?
|
||||
- `/koniec-pracy` - czy release zostal wykonany?
|
||||
|
||||
Braki dokumentuj w STATE.md (Deferred Issues), nie blokują UNIFY.
|
||||
Braki dokumentuj w STATE.md (Deferred Issues), nie blokuja UNIFY.
|
||||
|
||||
---
|
||||
*SPECIAL-FLOWS.md — Created: 2026-03-12*
|
||||
*SPECIAL-FLOWS.md - Created: 2026-03-12*
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
See: .paul/PROJECT.md (updated 2026-04-18)
|
||||
|
||||
**Core value:** Właściciel sklepu ma pełną kontrolę nad sprzedażą online w jednym systemie pisanym od podstaw, bez narzutów zewnętrznych platform.
|
||||
**Core value:** Właściciel sklepu ma pełną kontrolę nad sprzedażą online w jednym systemie pisanym od podstaw, bez narzutów zewnętrznych platform.
|
||||
**Current focus:** Phase 15 complete - loop closed (scontainers edit save fix)
|
||||
|
||||
## Current Position
|
||||
@@ -51,22 +51,22 @@ Phase 15: PLAN --> APPLY --> UNIFY ✓ ✓ ✓ [COMPLETE - 2026-04-18]
|
||||
- 2026-04-18: /koniec-pracy requirement mapped to .claude/commands/koniec-pracy.md guidance for end-of-session release flow
|
||||
- 2026-04-18: Scontainers edit fix - ID from tabbed form can be omitted when hidden field is defined as FormField and not as hiddenFields
|
||||
- Use existing `CouponRepository::markAsUsed()` instead of adding methods to stdClass
|
||||
- 2026-03-16: Przyczyna braku wysyłki = brakujące $apiloRepository w use() closures cron.php (regresja z fazy 6)
|
||||
- 2026-03-16: Przyczyna braku wysyłki = brakujące $apiloRepository w use() closures cron.php (regresja z fazy 6)
|
||||
- 2026-03-16: Retry -1 orders co 1h zamiast permanent failure
|
||||
- 2026-03-16: Email notification o trwale failed Apilo jobach
|
||||
- 2026-03-19: Order-related Apilo joby — infinite retry co 30 min (nigdy permanent failure)
|
||||
- 2026-03-19: Email z danymi zamĂłwienia + rozróżnienie PONAWIANY vs TRWAĹY BĹÄ„D
|
||||
- 2026-03-19: Cleanup stuck sync_payment/sync_status jobów po udanym wysłaniu
|
||||
- 2026-03-19: Edycja custom fields w koszyku — product_code przeliczany po zmianie, merge duplikatów przy identycznym hashu
|
||||
- 2026-03-19: Order-related Apilo joby — infinite retry co 30 min (nigdy permanent failure)
|
||||
- 2026-03-19: Email z danymi zamówienia + rozróżnienie PONAWIANY vs TRWAŁY BŁĄD
|
||||
- 2026-03-19: Cleanup stuck sync_payment/sync_status jobów po udanym wysłaniu
|
||||
- 2026-03-19: Edycja custom fields w koszyku — product_code przeliczany po zmianie, merge duplikatów przy identycznym hashu
|
||||
- 2026-03-19: JS handlery koszyka w basket.php (nie basket-details.php) bo basket-details jest AJAX-replaceable
|
||||
- 2026-03-25: view_cart event w basket.php (nie basket-details.php) — ten sam powód
|
||||
- 2026-03-25: view_cart event w basket.php (nie basket-details.php) — ten sam powód
|
||||
- 2026-03-25: GA4 item format standard: item_id (string), item_name, price (number), quantity (int), google_business_vertical: "retail"
|
||||
- 2026-03-25: Brak user_data w purchase — wymaga analizy RODO
|
||||
- 2026-03-25: summaryView() redirect guard usunięty — blokował kolejne zamówienia po pierwszym (z change.md instancji klienta)
|
||||
- 2026-03-25: Token zamówienia z jednorazowego na TTL 30 min — backward compat z plain string
|
||||
- 2026-03-25: logOrder() — logowanie błędów zamówień do logs/logs-order-YYYY-MM-DD.log
|
||||
- 2026-03-25: Redirect przy złym tokenie: /koszyk-podsumowanie zamiast /koszyk
|
||||
- 2026-04-16: Custom fields delete fix — hidden marker `custom_field_name_present` zamiast `array_key_exists('custom_field_name')`
|
||||
- 2026-03-25: Brak user_data w purchase — wymaga analizy RODO
|
||||
- 2026-03-25: summaryView() redirect guard usunięty — blokował kolejne zamówienia po pierwszym (z change.md instancji klienta)
|
||||
- 2026-03-25: Token zamówienia z jednorazowego na TTL 30 min — backward compat z plain string
|
||||
- 2026-03-25: logOrder() — logowanie błędów zamówień do logs/logs-order-YYYY-MM-DD.log
|
||||
- 2026-03-25: Redirect przy złym tokenie: /koszyk-podsumowanie zamiast /koszyk
|
||||
- 2026-04-16: Custom fields delete fix — hidden marker `custom_field_name_present` zamiast `array_key_exists('custom_field_name')`
|
||||
|
||||
### Deferred Issues
|
||||
None.
|
||||
@@ -87,5 +87,4 @@ Stopped at: Phase 15 complete, loop closed
|
||||
Next action: Start next work with $paul-plan (or run /koniec-pracy for release flow)
|
||||
Resume file: .paul/phases/15-scontainers-edit-save-fix/15-01-SUMMARY.md
|
||||
---
|
||||
*STATE.md — Updated after every significant action*
|
||||
|
||||
*STATE.md — Updated after every significant action*
|
||||
|
||||
@@ -1,3 +1,255 @@
|
||||
# API
|
||||
|
||||
> Endpointy, kontrakty request/response, autentykacja.
|
||||
## Scope
|
||||
|
||||
Dokument opisuje aktualne REST API dostepne przez `api.php` (ordersPRO + slowniki + produkty + kategorie).
|
||||
|
||||
## Base URL
|
||||
|
||||
- Endpoint techniczny: `/api.php`
|
||||
- Routing odbywa sie przez query params:
|
||||
- `endpoint` (np. `orders`, `products`)
|
||||
- `action` (np. `list`, `get`)
|
||||
|
||||
Przyklad:
|
||||
|
||||
```text
|
||||
GET /api.php?endpoint=orders&action=list
|
||||
```
|
||||
|
||||
## Authentication
|
||||
|
||||
- Wymagany naglowek: `X-Api-Key: <api_key>`
|
||||
- Klucz jest porownywany z wartoscia `pp_settings.api_key`
|
||||
- Brak lub zly klucz:
|
||||
- HTTP `401`
|
||||
- payload:
|
||||
```json
|
||||
{
|
||||
"status": "error",
|
||||
"code": "UNAUTHORIZED",
|
||||
"message": "Invalid or missing API key"
|
||||
}
|
||||
```
|
||||
|
||||
## Response format
|
||||
|
||||
Sukces:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
Blad:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "error",
|
||||
"code": "BAD_REQUEST",
|
||||
"message": "..."
|
||||
}
|
||||
```
|
||||
|
||||
## Common HTTP/logic errors
|
||||
|
||||
- `400 BAD_REQUEST` - brak wymaganych parametrow/body
|
||||
- `401 UNAUTHORIZED` - brak/zly API key
|
||||
- `404 NOT_FOUND` - nieznany endpoint/action lub brak rekordu
|
||||
- `405 METHOD_NOT_ALLOWED` - zla metoda HTTP
|
||||
- `500 INTERNAL_ERROR` - blad serwera
|
||||
|
||||
## Endpoints
|
||||
|
||||
### Orders (`endpoint=orders`)
|
||||
|
||||
- `GET action=list`
|
||||
- filtry (opcjonalne): `status`, `paid`, `date_from`, `date_to`, `updated_since`, `number`, `client`
|
||||
- paginacja: `page` (default 1), `per_page` (default 50, max 100)
|
||||
- `GET action=get&id={id}`
|
||||
- `PUT action=change_status&id={id}`
|
||||
- body JSON:
|
||||
- `status_id` (required, int)
|
||||
- `send_email` (optional, bool)
|
||||
- `PUT action=set_paid&id={id}`
|
||||
- body JSON optional: `send_email` (bool)
|
||||
- `PUT action=set_unpaid&id={id}`
|
||||
|
||||
### Products (`endpoint=products`)
|
||||
|
||||
- `GET action=list`
|
||||
- filtry:
|
||||
- `search`, `status`, `promoted`
|
||||
- `attribute_{attributeId}={valueId}` (np. `attribute_12=37`)
|
||||
- sortowanie: `sort` (default `id`), `sort_dir` (default `DESC`)
|
||||
- paginacja: `page`, `per_page` (max 100)
|
||||
- `GET action=get&id={id}`
|
||||
- `POST action=create`
|
||||
- wymagane minimum:
|
||||
- `languages` (array, co najmniej jeden jezyk z `name`)
|
||||
- `price_brutto` (number >= 0)
|
||||
- `PUT action=update&id={id}`
|
||||
- partial update przez JSON body
|
||||
- `GET action=variants&id={parentProductId}`
|
||||
- dla produktu glownego (nie wariantu)
|
||||
- `POST action=create_variant&id={parentProductId}`
|
||||
- body:
|
||||
- `attributes` (required array)
|
||||
- opcjonalnie pola wariantu (np. `price_brutto`, `quantity`, `sku`, ...)
|
||||
- `PUT action=update_variant&id={variantId}`
|
||||
- partial update wariantu
|
||||
- `DELETE action=delete_variant&id={variantId}`
|
||||
- `POST action=upload_image`
|
||||
- body:
|
||||
- `id` (product id, required)
|
||||
- `file_name` (required)
|
||||
- `content_base64` (required)
|
||||
- `alt` (optional)
|
||||
- `o` (optional position)
|
||||
|
||||
### Dictionaries (`endpoint=dictionaries`)
|
||||
|
||||
- `GET action=statuses`
|
||||
- `GET action=transports`
|
||||
- `GET action=payment_methods`
|
||||
- `GET action=attributes`
|
||||
- `POST action=ensure_attribute`
|
||||
- body: `name` (required), `type` (optional int), `lang` (optional, default `pl`)
|
||||
- `POST action=ensure_attribute_value`
|
||||
- body: `attribute_id` (required), `name` (required), `lang` (optional, default `pl`)
|
||||
- `POST action=ensure_producer`
|
||||
- body: `name` (required)
|
||||
|
||||
### Categories (`endpoint=categories`)
|
||||
|
||||
- `GET action=list`
|
||||
- zwraca aktywne kategorie w formie flat list:
|
||||
- `id`
|
||||
- `parent_id`
|
||||
- `title`
|
||||
- tytuly pobierane najpierw w jezyku domyslnym (`pp_langs.start=1`), potem fallback.
|
||||
|
||||
## Source of truth (mapa API w kodzie)
|
||||
|
||||
### 1) Wejscie i dispatch
|
||||
|
||||
- `api.php`
|
||||
- wykrywa request API przez `$_GET['endpoint']`
|
||||
- ustawia JSON content-type
|
||||
- tworzy `medoo` + `SettingsRepository`
|
||||
- przekazuje sterowanie do `\api\ApiRouter::handle()`
|
||||
- `autoload/api/ApiRouter.php`
|
||||
- autentykacja (`X-Api-Key` vs `pp_settings.api_key`)
|
||||
- walidacja `endpoint` i `action`
|
||||
- mapowanie endpoint -> kontroler (`getControllerFactories()`)
|
||||
- helpery odpowiedzi: `sendSuccess()`, `sendError()`
|
||||
- helpery requestu: `getJsonBody()`, `requireMethod()`
|
||||
|
||||
### 2) Endpointy i kontrolery (runtime source)
|
||||
|
||||
#### `endpoint=orders`
|
||||
|
||||
- plik: `autoload/api/Controllers/OrdersApiController.php`
|
||||
- akcje:
|
||||
- `list` (GET)
|
||||
- `get` (GET)
|
||||
- `change_status` (PUT)
|
||||
- `set_paid` (PUT)
|
||||
- `set_unpaid` (PUT)
|
||||
|
||||
#### `endpoint=products`
|
||||
|
||||
- plik: `autoload/api/Controllers/ProductsApiController.php`
|
||||
- akcje:
|
||||
- `list` (GET)
|
||||
- `get` (GET)
|
||||
- `create` (POST)
|
||||
- `update` (PUT)
|
||||
- `variants` (GET)
|
||||
- `create_variant` (POST)
|
||||
- `update_variant` (PUT)
|
||||
- `delete_variant` (DELETE)
|
||||
- `upload_image` (POST)
|
||||
|
||||
#### `endpoint=dictionaries`
|
||||
|
||||
- plik: `autoload/api/Controllers/DictionariesApiController.php`
|
||||
- akcje:
|
||||
- `statuses` (GET)
|
||||
- `transports` (GET)
|
||||
- `payment_methods` (GET)
|
||||
- `attributes` (GET)
|
||||
- `ensure_attribute` (POST)
|
||||
- `ensure_attribute_value` (POST)
|
||||
- `ensure_producer` (POST)
|
||||
|
||||
#### `endpoint=categories`
|
||||
|
||||
- plik: `autoload/api/Controllers/CategoriesApiController.php`
|
||||
- akcje:
|
||||
- `list` (GET)
|
||||
|
||||
### 3) Warstwa domenowa pod API (shape danych)
|
||||
|
||||
- Orders:
|
||||
- `Domain\Order\OrderRepository::listForApi()`
|
||||
- `Domain\Order\OrderRepository::findForApi()`
|
||||
- `Domain\Order\OrderAdminService` (zmiana statusu/platnosci)
|
||||
- Products:
|
||||
- `Domain\Product\ProductRepository::listForApi()`
|
||||
- `Domain\Product\ProductRepository::findForApi()`
|
||||
- `Domain\Product\ProductRepository::saveProduct()`
|
||||
- metody wariantow `*VariantForApi()`
|
||||
- Dictionaries:
|
||||
- `Domain\ShopStatus\ShopStatusRepository`
|
||||
- `Domain\Transport\TransportRepository`
|
||||
- `Domain\PaymentMethod\PaymentMethodRepository`
|
||||
- `Domain\Attribute\AttributeRepository`
|
||||
- `Domain\Producer\ProducerRepository`
|
||||
- Categories:
|
||||
- bezposrednio query przez `$GLOBALS['mdb']` w `CategoriesApiController`
|
||||
|
||||
### 4) Testy API (behavior source)
|
||||
|
||||
- `tests/Unit/api/ApiRouterTest.php`
|
||||
- `tests/Unit/api/Controllers/OrdersApiControllerTest.php`
|
||||
- `tests/Unit/api/Controllers/ProductsApiControllerTest.php`
|
||||
- `tests/Unit/api/Controllers/DictionariesApiControllerTest.php`
|
||||
|
||||
### 5) Dokumentacja kontraktu (human source)
|
||||
|
||||
- `api-docs/api-reference.json`
|
||||
- `api-docs/index.html`
|
||||
|
||||
Uwaga: dokumentacja z `api-docs/*` moze byc starsza od runtime.
|
||||
Zrodlem prawdy dla dzialania endpointow jest zawsze:
|
||||
`api.php` + `autoload/api/ApiRouter.php` + aktualne kontrolery `autoload/api/Controllers/*`.
|
||||
|
||||
## Curl examples
|
||||
|
||||
Pobranie listy zamowien:
|
||||
|
||||
```bash
|
||||
curl -X GET "https://example.com/api.php?endpoint=orders&action=list&page=1&per_page=20" \
|
||||
-H "X-Api-Key: YOUR_API_KEY"
|
||||
```
|
||||
|
||||
Zmiana statusu zamowienia:
|
||||
|
||||
```bash
|
||||
curl -X PUT "https://example.com/api.php?endpoint=orders&action=change_status&id=123" \
|
||||
-H "X-Api-Key: YOUR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"status_id\": 6, \"send_email\": true}"
|
||||
```
|
||||
|
||||
Dodanie wariantu produktu:
|
||||
|
||||
```bash
|
||||
curl -X POST "https://example.com/api.php?endpoint=products&action=create_variant&id=50" \
|
||||
-H "X-Api-Key: YOUR_API_KEY" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"attributes\":[{\"attribute_id\":12,\"attribute_value_id\":37}],\"price_brutto\":99.99,\"quantity\":10}"
|
||||
```
|
||||
|
||||
@@ -1,3 +1,192 @@
|
||||
# ARCHITECTURE
|
||||
|
||||
> Struktura klas, modulow, przeplywow i zaleznosci w projekcie.
|
||||
## Scope
|
||||
|
||||
Dokument opisuje aktualna architekture runtime projektu `shopPRO`:
|
||||
- warstwy aplikacji i ich odpowiedzialnosci,
|
||||
- przeplywy requestow (admin/front/api),
|
||||
- Dependency Injection i miejsca wiringu,
|
||||
- konwencje autoloadera i namespace,
|
||||
- granice miedzy nowa architektura a pozostalosciami legacy.
|
||||
|
||||
## High-level layout
|
||||
|
||||
Kod aplikacji jest podzielony na 4 glowne warstwy:
|
||||
|
||||
1. `autoload/Domain/` - logika biznesowa i dostep do danych (28 modulow)
|
||||
2. `autoload/admin/` - panel administracyjny (router + kontrolery + form system)
|
||||
3. `autoload/front/` - frontend sklepu (router + layout engine + kontrolery/widoki)
|
||||
4. `autoload/api/` - REST API (`api.php`, `ApiRouter`, kontrolery endpointow)
|
||||
|
||||
Komponenty wspoldzielone sa trzymane w `autoload/Shared/`.
|
||||
|
||||
## Directory map (runtime)
|
||||
|
||||
```text
|
||||
autoload/
|
||||
Domain/ # 28 modulow domenowych
|
||||
Shared/ # Cache, Helpers, Tpl, Html, Email, Image
|
||||
admin/
|
||||
App.php # routing + DI factories
|
||||
Controllers/ # 28 kontrolerow admin
|
||||
Support/ # formularze/tabele
|
||||
Validation/ # walidacja formularzy
|
||||
ViewModels/ # modele widokow
|
||||
front/
|
||||
App.php # routing + DI factories + fallback legacy
|
||||
LayoutEngine.php # silnik layoutu frontend
|
||||
Controllers/ # 8 kontrolerow frontend
|
||||
Views/ # 11 statycznych klas widokow
|
||||
api/
|
||||
ApiRouter.php # auth + endpoint dispatch
|
||||
Controllers/ # 4 kontrolery API
|
||||
```
|
||||
|
||||
## Entry points i przeplyw
|
||||
|
||||
### Admin (`admin/index.php`)
|
||||
|
||||
1. Bootstrap (sesja, DB, autoload)
|
||||
2. `admin\App::update()` - uruchamia pending migracje
|
||||
3. `admin\App::special_actions()` - logowanie/wylogowanie/2FA
|
||||
4. `admin\App::render()`:
|
||||
- auth gate (lub formularz logowania),
|
||||
- `route()` -> kontroler + akcja,
|
||||
- render przez `Shared\Tpl\Tpl`.
|
||||
|
||||
### Front (`index.php`)
|
||||
|
||||
1. Bootstrap (sesja, DB, autoload, jezyk)
|
||||
2. Mapowanie URL (redirecty + routes)
|
||||
3. `front\App::checkUrlParams()`
|
||||
4. `front\App::route()`:
|
||||
- artykul/produkt/kategoria,
|
||||
- nowe kontrolery DI,
|
||||
- fallback do `front\controls\*` (legacy, jesli istnieje)
|
||||
5. `front\LayoutEngine::show()` sklada finalny HTML.
|
||||
|
||||
### API (`api.php`)
|
||||
|
||||
1. Bootstrap (bez sesji biznesowej)
|
||||
2. Tworzenie `\api\ApiRouter`
|
||||
3. `ApiRouter::handle()`:
|
||||
- auth przez `X-Api-Key`,
|
||||
- walidacja `endpoint` i `action`,
|
||||
- dispatch do kontrolera API,
|
||||
- JSON response przez `sendSuccess()` / `sendError()`.
|
||||
|
||||
Szczegolowa specyfikacja endpointow: `.paul/docs/API.md`.
|
||||
|
||||
## Dependency Injection (manual factories)
|
||||
|
||||
DI jest realizowane recznie w mapach factory:
|
||||
|
||||
- admin: `autoload/admin/App.php` -> `getControllerFactories()`
|
||||
- front: `autoload/front/App.php` -> `getControllerFactories()`
|
||||
- api: `autoload/api/ApiRouter.php` -> `getControllerFactories()`
|
||||
|
||||
Wzorzec:
|
||||
- router tworzy repozytoria domenowe,
|
||||
- repozytoria sa wstrzykiwane do kontrolerow przez konstruktor,
|
||||
- kontroler wywoluje metody domenowe i zwraca HTML/JSON.
|
||||
|
||||
## Autoloader i namespace rules
|
||||
|
||||
Kazdy entry point korzysta z custom autoloadera:
|
||||
|
||||
1. `autoload/{namespace}/class.{ClassName}.php` (legacy)
|
||||
2. `autoload/{namespace}/{ClassName}.php` (nowy format)
|
||||
|
||||
Mapowanie namespace -> katalog (case-sensitive na Linux):
|
||||
|
||||
- `\Domain\` -> `autoload/Domain/`
|
||||
- `\Shared\` -> `autoload/Shared/`
|
||||
- `\admin\` -> `autoload/admin/` (male `a`)
|
||||
- `\front\` -> `autoload/front/`
|
||||
- `\api\` -> `autoload/api/`
|
||||
|
||||
Nie uzywac `\Admin\` (duze `A`), bo katalog runtime to `admin/`.
|
||||
|
||||
## Domain layer (28 modulow)
|
||||
|
||||
Aktualne moduly:
|
||||
|
||||
`Article`, `Attribute`, `Banner`, `Basket`, `Cache`, `Category`, `Client`, `Coupon`, `CronJob`, `Dashboard`, `Dictionaries`, `Integrations`, `Languages`, `Layouts`, `Newsletter`, `Order`, `Pages`, `PaymentMethod`, `Producer`, `Product`, `ProductSet`, `Promotion`, `Scontainers`, `Settings`, `ShopStatus`, `Transport`, `Update`, `User`.
|
||||
|
||||
Zasada: logika biznesowa i dostep do danych sa w Domain, bez duplikowania osobnych warstw "admin service" i "front service" dla tych samych przypadkow (wyjatki tylko tam, gdzie historycznie juz istnieja, np. `OrderAdminService`).
|
||||
|
||||
## Admin architecture
|
||||
|
||||
- Router: `admin\App`
|
||||
- Kontrolery: `autoload/admin/Controllers/*.php` (28 klas)
|
||||
- Form system:
|
||||
- `admin\ViewModels\Forms\*`
|
||||
- `admin\Support\Forms\FormRequestHandler`
|
||||
- `admin\Support\Forms\FormFieldRenderer`
|
||||
- `admin\Validation\FormValidator`
|
||||
- template: `admin/templates/components/form-edit.php`
|
||||
|
||||
Admin ma pelne DI i nie korzysta z fallbacku na legacy kontrolery.
|
||||
|
||||
## Front architecture
|
||||
|
||||
- Router: `front\App`
|
||||
- Layout engine: `front\LayoutEngine`
|
||||
- Kontrolery DI: `autoload/front/Controllers/*.php` (8 klas)
|
||||
- Widoki statyczne: `autoload/front/Views/*.php` (11 klas)
|
||||
|
||||
Wazne: frontend nadal ma fallback do `\front\controls\*`, wiec architektura jest hybrydowa (new DI + remaining legacy paths).
|
||||
|
||||
## API architecture
|
||||
|
||||
- Router: `api\ApiRouter`
|
||||
- Endpointy: `orders`, `products`, `dictionaries`, `categories`
|
||||
- Kontrolery: `autoload/api/Controllers/*ApiController.php` (4 klasy)
|
||||
- API jest stateless, autoryzowane naglowkiem `X-Api-Key`
|
||||
|
||||
Source-of-truth API to runtime:
|
||||
- `api.php`
|
||||
- `autoload/api/ApiRouter.php`
|
||||
- `autoload/api/Controllers/*`
|
||||
|
||||
## Shared components
|
||||
|
||||
Najwazniejsze klasy wspoldzielone:
|
||||
|
||||
- `Shared\Cache\CacheHandler`, `Shared\Cache\RedisConnection`
|
||||
- `Shared\Helpers\Helpers`
|
||||
- `Shared\Tpl\Tpl`
|
||||
- `Shared\Html\Html`
|
||||
- `Shared\Email\Email`
|
||||
- `Shared\Image\ImageManipulator`
|
||||
|
||||
## Data and cache conventions
|
||||
|
||||
- ORM: Medoo (`$mdb`)
|
||||
- Prefix tabel: `pp_`
|
||||
- Cache: Redis, domyslnie TTL `86400`
|
||||
- Dane cache czesto serializowane (`serialize`/`unserialize`)
|
||||
- Czyszczenie cache produktu: pattern `shop\\product:{id}:*`
|
||||
|
||||
## Security boundaries
|
||||
|
||||
- Admin:
|
||||
- sesja uzytkownika admina,
|
||||
- CSRF token w akcjach POST,
|
||||
- 2FA email flow (pending session + verify).
|
||||
- API:
|
||||
- `X-Api-Key` porownywany przez `hash_equals()`,
|
||||
- brak logiki sesyjnej.
|
||||
- Front:
|
||||
- sesja klienta + walidacja przeplywow frontendowych.
|
||||
|
||||
## Source files
|
||||
|
||||
Najwazniejsze pliki do szybkiej orientacji:
|
||||
|
||||
- `autoload/admin/App.php`
|
||||
- `autoload/front/App.php`
|
||||
- `autoload/front/LayoutEngine.php`
|
||||
- `autoload/api/ApiRouter.php`
|
||||
- `.paul/docs/API.md`
|
||||
- `docs/PROJECT_STRUCTURE.md`
|
||||
|
||||
@@ -1,3 +1,228 @@
|
||||
# DB_SCHEMA
|
||||
# DB_SCHEMA
|
||||
|
||||
> Schemat bazy danych — tabele, kolumny, FK, indeksy.
|
||||
## Scope
|
||||
|
||||
Dokument opisuje praktyczny schema map dla `shopPRO`:
|
||||
- najwazniejsze tabele i relacje,
|
||||
- grupowanie po domenach biznesowych,
|
||||
- kluczowe kolumny i indeksy, ktore maja znaczenie runtime,
|
||||
- mapowanie tabela -> warstwa Domain.
|
||||
|
||||
Pelna lista tabel i historyczne notki migracyjne:
|
||||
`docs/DATABASE_STRUCTURE.md` (source of truth dla detali kolumnowych).
|
||||
|
||||
## Konwencje globalne
|
||||
|
||||
- ORM: Medoo (`$mdb`)
|
||||
- Prefix tabel: `pp_`
|
||||
- Primary key: najczesciej `id` (INT AUTO_INCREMENT)
|
||||
- Jezyki/translations: zwykle tabele `*_langs` z kluczem `lang_id`
|
||||
- Wiele-do-wielu: tabele lacznikowe `*_products`, `*_payment_methods`, itp.
|
||||
|
||||
## Core commerce
|
||||
|
||||
### Produkty
|
||||
|
||||
- `pp_shop_products`
|
||||
- core produktu i wariantu (`parent_id` dla kombinacji)
|
||||
- ceny (`price_brutto`, `price_brutto_promo`), stany (`quantity`)
|
||||
- flagi (`status`, `archive`, `promoted`)
|
||||
- `pp_shop_products_langs`
|
||||
- nazwy/opisy per jezyk
|
||||
- `pp_shop_products_images`
|
||||
- obrazy produktu
|
||||
- `pp_shop_products_categories`
|
||||
- przypisania produkt-kategoria
|
||||
- `pp_shop_products_attributes`
|
||||
- przypisania wariantu do wartosci cech
|
||||
- `pp_shop_products_custom_fields`
|
||||
- dodatkowe pola produktu
|
||||
|
||||
Warstwa: `Domain\Product\ProductRepository`, `Domain\Attribute\AttributeRepository`.
|
||||
|
||||
### Kategorie
|
||||
|
||||
- `pp_shop_categories`
|
||||
- drzewo kategorii (`parent_id`), status, kolejnosc
|
||||
- `pp_shop_categories_langs`
|
||||
- tresci SEO i opisy kategorii
|
||||
|
||||
Warstwa: `Domain\Category\CategoryRepository`.
|
||||
|
||||
### Zamowienia
|
||||
|
||||
- `pp_shop_orders`
|
||||
- dane klienta "w momencie zakupu", summary, status/platnosc, daty
|
||||
- kluczowe pole integracyjne: `updated_at` (polling API)
|
||||
|
||||
Warstwa: `Domain\Order\OrderRepository`, `Domain\Order\OrderAdminService`.
|
||||
|
||||
### Klienci
|
||||
|
||||
- `pp_shop_clients`
|
||||
- konto klienta i dane adresowe/logowania (uzywane przez ClientRepository)
|
||||
|
||||
Warstwa: `Domain\Client\ClientRepository`.
|
||||
|
||||
## Slowniki i checkout
|
||||
|
||||
### Platnosci
|
||||
|
||||
- `pp_shop_payment_methods`
|
||||
- status, opis, mapowanie Apilo
|
||||
- limity kwotowe: `min_order_amount`, `max_order_amount`
|
||||
- COD flag: `is_cod`
|
||||
|
||||
Warstwa: `Domain\PaymentMethod\PaymentMethodRepository`.
|
||||
|
||||
### Transport
|
||||
|
||||
- `pp_shop_transports`
|
||||
- koszt, status, limity, mapowanie Apilo
|
||||
- `pp_shop_transport_payment_methods`
|
||||
- relacja transport <-> platnosc (N:M)
|
||||
|
||||
Warstwa: `Domain\Transport\TransportRepository`.
|
||||
|
||||
### Statusy zamowien
|
||||
|
||||
- `pp_shop_statuses`
|
||||
- statusy predefiniowane, kolor, mapowanie Apilo
|
||||
|
||||
Warstwa: `Domain\ShopStatus\ShopStatusRepository`.
|
||||
|
||||
## Marketing i merch
|
||||
|
||||
### Promocje i kupony
|
||||
|
||||
- `pp_shop_promotion`
|
||||
- reguly promocji, daty aktywnosci, warunki i zakresy (JSON categories)
|
||||
- `pp_shop_coupon`
|
||||
- kupony, licznik uzyc, ograniczenia
|
||||
|
||||
Warstwa: `Domain\Promotion\PromotionRepository`, `Domain\Coupon\CouponRepository`.
|
||||
|
||||
### Producenci
|
||||
|
||||
- `pp_shop_producer`
|
||||
- `pp_shop_producer_lang`
|
||||
|
||||
Warstwa: `Domain\Producer\ProducerRepository`.
|
||||
|
||||
### Zestawy produktow
|
||||
|
||||
- `pp_shop_product_sets`
|
||||
- `pp_shop_product_sets_products`
|
||||
|
||||
Warstwa: `Domain\ProductSet\ProductSetRepository`.
|
||||
|
||||
### Cechy i wartosci
|
||||
|
||||
- `pp_shop_attributes`
|
||||
- `pp_shop_attributes_langs`
|
||||
- `pp_shop_attributes_values`
|
||||
- `pp_shop_attributes_values_langs`
|
||||
|
||||
Warstwa: `Domain\Attribute\AttributeRepository`.
|
||||
|
||||
## CMS i frontend content
|
||||
|
||||
### Artykuly
|
||||
|
||||
- `pp_articles`
|
||||
- `pp_articles_langs`
|
||||
- `pp_articles_pages`
|
||||
- `pp_articles_images`
|
||||
- `pp_articles_files`
|
||||
|
||||
Warstwa: `Domain\Article\ArticleRepository`.
|
||||
|
||||
### Strony i layouty
|
||||
|
||||
- `pp_pages`
|
||||
- `pp_layouts`
|
||||
- `pp_layouts_pages`
|
||||
- `pp_layouts_categories`
|
||||
|
||||
Warstwa: `Domain\Pages\PagesRepository`, `Domain\Layouts\LayoutsRepository`.
|
||||
|
||||
### Banery i kontenery statyczne
|
||||
|
||||
- `pp_banners`
|
||||
- `pp_banners_langs`
|
||||
- `pp_scontainers`
|
||||
- `pp_scontainers_langs`
|
||||
|
||||
Warstwa: `Domain\Banner\BannerRepository`, `Domain\Scontainers\ScontainersRepository`.
|
||||
|
||||
## Ustawienia i system
|
||||
|
||||
### Ustawienia aplikacji
|
||||
|
||||
- `pp_settings`
|
||||
- klucze globalne (w tym `api_key` dla REST API)
|
||||
- `pp_shop_apilo_settings`
|
||||
- `pp_shop_shoppro_settings`
|
||||
|
||||
Warstwa: `Domain\Settings\SettingsRepository`, `Domain\Integrations\IntegrationsRepository`.
|
||||
|
||||
### Jezyki i tlumaczenia
|
||||
|
||||
- `pp_langs`
|
||||
- `pp_langs_translations`
|
||||
|
||||
Warstwa: `Domain\Languages\LanguagesRepository`.
|
||||
|
||||
### Uzytkownicy admina
|
||||
|
||||
- `pp_users`
|
||||
- login, hash hasla, status
|
||||
- pola 2FA (`twofa_*`)
|
||||
|
||||
Warstwa: `Domain\User\UserRepository`.
|
||||
|
||||
## Routing i URL mapping
|
||||
|
||||
- `pp_routes`
|
||||
- regex `pattern` -> `destination` query string
|
||||
- obsluguje trasy encji oraz trasy systemowe
|
||||
- cache Redis: `pp_routes:all`
|
||||
|
||||
Runtime wykorzystanie:
|
||||
- `index.php`
|
||||
- `Shared\Helpers\Helpers::htacces()`
|
||||
- repozytoria encji generujace/odswiezajace trasy.
|
||||
|
||||
## Kolejka cron
|
||||
|
||||
- `pp_cron_jobs`
|
||||
- status processing pipeline (`pending`, `processing`, `completed`, `failed`, `cancelled`)
|
||||
- retry/backoff: `attempts`, `max_attempts`, `scheduled_at`
|
||||
- indeksy:
|
||||
- `(status, priority, scheduled_at)`
|
||||
- `(job_type)`
|
||||
- `(status)`
|
||||
- `pp_cron_schedules`
|
||||
- harmonogramy okresowe (`interval_seconds`, `next_run_at`)
|
||||
- indeks `(enabled, next_run_at)`
|
||||
|
||||
Warstwa: `Domain\CronJob\CronJobRepository`, `Domain\CronJob\CronJobProcessor`.
|
||||
|
||||
## Najwazniejsze relacje (FK logiczne)
|
||||
|
||||
- Produkt glowny -> wariant: `pp_shop_products.parent_id -> pp_shop_products.id`
|
||||
- Produkt -> tlumaczenia: `pp_shop_products_langs.product_id -> pp_shop_products.id`
|
||||
- Produkt -> kategoria: `pp_shop_products_categories.product_id -> pp_shop_products.id`
|
||||
- Kategoria -> tlumaczenia: `pp_shop_categories_langs.category_id -> pp_shop_categories.id`
|
||||
- Zamowienie -> klient: `pp_shop_orders.client_id -> pp_shop_clients.id` (opcjonalne)
|
||||
- Transport <-> platnosc: `pp_shop_transport_payment_methods`
|
||||
- Cecha -> wartosci -> warianty: `attributes -> values -> shop_products_attributes`
|
||||
- Producent -> tlumaczenia: `pp_shop_producer_lang.producer_id -> pp_shop_producer.id`
|
||||
- Kontener -> tlumaczenia: `pp_scontainers_langs.container_id -> pp_scontainers.id`
|
||||
|
||||
## Uwaga operacyjna
|
||||
|
||||
Ten dokument jest skrotem architektonicznym.
|
||||
Przy zmianach SQL/migracji zawsze aktualizuj rownolegle:
|
||||
1. `docs/DATABASE_STRUCTURE.md` (detal techniczny)
|
||||
2. `.paul/docs/DB_SCHEMA.md` (mapa domenowa i impact runtime)
|
||||
|
||||
3611
.paul/docs/TODO.md
3611
.paul/docs/TODO.md
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user