Phase 110 complete: - add Statistics -> Podsumowanie page - add monthly order count and value charts per integration plus total - use Chart.js with table fallback and 04-2026 default history start - update PAUL and DOCS technical documentation
10 KiB
10 KiB
Architecture
Request Flow
HTTP Request
→ public/index.php
→ bootstrap/app.php (loads config, registers PDO, services)
→ Application::boot() (loads routes/web.php)
→ Router::dispatch(Request) (matches URL, runs middleware pipeline)
→ [Middleware] (AuthMiddleware, ApiKeyMiddleware)
→ Controller::method() (parse input → call repository/service → render)
→ Template::render() (PHP native, layout composition)
→ Response::send()
Layer Map
| Layer | Location | Responsibility |
|---|---|---|
| Entry | public/index.php |
Bootstrap only |
| Routes | routes/web.php (581 lines) |
All ~80 routes; manual DI wiring |
| Core | src/Core/ (25 files) |
Framework infrastructure |
| Controllers | src/Modules/*/Controller.php |
Request parsing → response |
| Services | src/Modules/*/Service.php |
Business logic |
| Repositories | src/Modules/*/Repository.php |
PDO data access (34+ repos) |
| Views | resources/views/ |
PHP templates with $e() / $t() |
| Components | resources/views/components/ |
Reusable UI blocks |
| Frontend modules | public/assets/js/modules/ |
Small vanilla JS enhancements loaded by layout |
Module Inventory (src/Modules/)
| Module | Files | Key Classes | Purpose |
|---|---|---|---|
| Auth | 3 | AuthController, AuthMiddleware, AuthService |
Login/logout, session |
| Users | 2 | UserController, UserRepository |
User CRUD |
| Orders | 3 | OrdersController (1187 LOC), OrdersRepository (1221 LOC) |
Order list, detail, status, payment, correlated subquery for return-risk |
| Shipments | 17 | ShipmentController, provider services + tracking services |
Shipment creation, label download, tracking polling |
| Accounting | 5 | AccountingController, ReceiptService, ReceiptRepository |
Receipts, invoices, PDF, Excel export |
| 3 | EmailSendingService, VariableResolver, AttachmentGenerator |
Template-based email with PDF attachments | |
| Automation | 6 | AutomationService (834 LOC), AutomationRepository, AutomationExecutionLogRepository |
Event→condition→action rules, email triggers |
| Settings | 51+ | Integration controllers, OAuth clients, API clients, mappers | Allegro/shopPRO/Apaczka/InPost config, status mappings |
| Cron | 12 | CronRepository, CronHandlerFactory, handler classes |
Scheduled imports, syncs, token refresh |
| Printing | 4 | PrintApiController, PrintJobRepository, ApiKeyMiddleware |
REST API for Windows print client |
| Statistics | 3 | OrdersStatisticsController, OrdersStatisticsRepository, statistics-summary-charts.js |
Daily order statistics and monthly summary charts |
| Info | 1 | InfoController |
Health check |
Frontend Enhancement Modules
Checkbox Multiselect (public/assets/js/modules/checkbox-multiselect.js)
- Loaded globally from
resources/views/layouts/app.php. - Enhances native
<select multiple data-checkbox-multiselect>controls afterDOMContentLoaded. - Keeps the original select in the form, synchronizes option
selectedstate, and preserves native GET/POST names such aschannels[]andstatus_groups[]. - Used by
/statistics/ordersand/statistics/summaryfilters to display a compact trigger, checkbox dropdown, "Wszystkie" bulk toggle, and selected count. - Progressive enhancement: if JavaScript fails, the native multi-select remains visible.
Statistics Summary Charts (public/assets/js/modules/statistics-summary-charts.js)
- Loaded globally from
resources/views/layouts/app.phpafter Chart.js 4.4.8 CDN; activates only when#js-statistics-summary-dataexists. - Reads JSON produced by
OrdersStatisticsController::summary()and renders two interactive Chart.js line charts on/statistics/summary. - Chart 1 displays monthly order counts per selected integration plus a
Razemline. - Chart 2 displays monthly gross order values per selected integration plus a
Razemline. - The PHP view keeps table fallbacks under both charts, so the data remains visible if JavaScript fails.
Key Data Flows
Order Lifecycle
- Import — Cron handler → API client →
OrderImportService→OrdersRepository::insertOrder()→AutomationService::executeForNewOrder() - Status update —
OrdersController::updateStatus()→OrdersRepository::updateStatus()→ automation check - Status sync — Cron →
AllegroStatusSyncService/ShopproStatusSyncService→ carrier API
Statistics Summary
- Request —
/statistics/summary→OrdersStatisticsController::summary() - Filters — controller reuses statistics filter semantics: date range,
channels[],status_groups[], default status groups excluding cancelled; default history starts at2026-04-01. - Aggregation —
OrdersStatisticsRepository::aggregateByMonth()groups existingordersrows byYYYY-MMand channel key, using the same effective date/channel/status/gross amount SQL helpers as the daily report. - View model — controller builds per-integration series and total series for order count and gross value charts.
- Render —
resources/views/statistics/summary.phprenders filters, chart JSON, two canvas targets, and table fallbacks.
Shipment Flow
- Create —
ShipmentController::create()→ShipmentProviderRegistry→ carrierShipmentService::createShipment()→ShipmentPackageRepository::insert() - Track — Cron
ShipmentTrackingHandler→ShipmentTrackingRegistry→ carrier tracking API →ShipmentPackageRepository::updateDeliveryStatus()
Receipt / Invoice
- Generate —
ReceiptController::store()→ReceiptService::generateReceipt()→ReceiptRepository::insert()+ Dompdf PDF - Email —
EmailSendingService::send()→VariableResolver::resolve()→AttachmentGenerator::generatePdf()→ PHPMailer SMTP
Automation Rules
- Setup —
AutomationController→AutomationRepository::insertRule() - Trigger —
AutomationService::executeForOrder()→ evaluates trigger (order_status_changed,order_status_aged) → runs action (send email, update status) - Log —
AutomationExecutionLogRepositorytracks every run
Cron Jobs
| Handler | Task |
|---|---|
AllegroOrdersImportHandler |
Fetch new Allegro orders |
AllegroStatusSyncHandler |
Push status changes to Allegro |
AllegroTokenRefreshHandler |
OAuth token refresh (24h expiry) |
ShopproOrdersImportHandler |
Fetch new shopPRO orders |
ShopproStatusSyncHandler |
Push status to shopPRO |
ShopproPaymentStatusSyncHandler |
Sync payment statuses |
ShipmentTrackingHandler |
Poll carrier tracking APIs |
OrderStatusAgedHandler |
Trigger automation for stuck statuses |
AutomationHistoryCleanupHandler |
Purge old automation logs |
Dependency Injection
Manual constructor injection in routes/web.php — no DI container library. Example:
$ordersController = new OrdersController(
$template, $translator, $auth,
$app->orders(), $shipmentPackageRepository,
$receiptRepository, $receiptConfigRepository, ...
);
All production classes are final — prevents accidental inheritance.
Directory Structure
bootstrap/ app.php (service wiring, config loading)
bin/ migrate.php, cron.php (CLI entry points)
config/ app.php, database.php
database/
migrations/ 84 SQL files (YYYYMMDD_NNNNNN_description.sql)
drafts/ WIP migrations
public/
index.php HTTP entry point
.htaccess Apache rewrite rules
assets/css/ Compiled CSS (app.css, login.css, modules/)
assets/js/ jquery-alerts.js, global-search.js, automation-form.js
resources/
views/ PHP templates by module + components/ layouts/
scss/ SCSS sources (app.scss, login.scss, modules/_*.scss)
modules/ jquery-alerts JS+SCSS source
lang/pl/ Polish translations
routes/
web.php All routes (581 lines)
src/
Core/ Framework (25 files)
Modules/ 13 feature modules (~200+ PHP files)
storage/
logs/ app.log
sessions/ PHP session files
cache/ PHPUnit cache, etc.
tests/
Unit/ PHPUnit tests (7+ service test files)
bootstrap.php PSR-4 autoloader for tests
Phase 108 — Delivery Status Management
DeliveryStatusRepository (src/Modules/Shipments/DeliveryStatusRepository.php)
- CRUD dla tabeli
delivery_statuses - Per-request static cache (
private static ?array $cache) - Blokuje edycję/usunięcie statusów systemowych (
is_system=1) - Blokuje usunięcie statusów używanych w
delivery_status_mappingslubshipment_packages
DeliveryStatusesController (src/Modules/Settings/DeliveryStatusesController.php)
- Panel
/settings/delivery-statuses - Dwie zakładki via
?tab=param:statuses(CRUD) imapping(embed mapowania) - Wstrzykuje
DeliveryStatusRepositoryiDeliveryStatusMappingRepository
DeliveryStatus::setRepository() (dynamic loading)
- Wywoływane raz w
routes/web.phppo bootstrap label(),getAllOptions(),getAllStatuses(),getColor()ładują z DB gdy repo ustawione- Fallback na hardcoded stałe gdy repo niedostępne
AutomationController + AutomationService (Phase 108 Plan 02)
AutomationController::buildShipmentStatusOptions()— buduje listę opcji[key => ['label' => ...]]zDeliveryStatus::getAllOptions()(DB-driven)- Walidacja
shipment_statuswarunku iupdate_shipment_statusakcji wparseConditionValue()/parseActionConfig()używaDeliveryStatus::getAllStatuses() AutomationService::evaluateShipmentStatusCondition()— bezpośrednie porównanie kluczy DB (usunięto mapping grupowySHIPMENT_STATUS_OPTION_MAP)AutomationService::resolveStatusFromActionKey()— bezpośredni klucz statusu z DB jako target- BREAKING: stare reguły z grupowymi kluczami (
registered,courier_pickup,dropped_at_point,unclaimed,picked_up_return) nie matchują się — operator musi je odtworzyć przy użyciu nowych kluczy DB