11 KiB
SoftSPM_2 - aplikacja Laravel (nakładka + szkielet)
Historycznie ten katalog trzymał tylko pliki specyficzne dla SoftSPM (modele,
kontrolery, widoki, konfiguracja, trasy), a czysty szkielet Laravela stał osobno
na UAT jako softspm_pge. Od 2026-09-03 katalog jest pełnym, uruchamialnym
projektem Laravel - szkielet został domieszany lokalnie, żeby dało się pracować
i testować na stacji roboczej.
Lista plików nakładki (to, co nakładamy na szkielet na UAT/produkcji) jest
zapisana w docker/overlay-files.txt.
Migracja legacy PHP 5.4/5.6 → Laravel. Źródło migracji:
C:\Programy\xampp_old\htdocs\trzeciCloude_v1\- NIEnewPGEani inne kopie whtdocs/. Audyt legacy i mapasiteNNN→ trasy: docs/LEGACY.md. Kontekst i decyzje: patrz pamięć projektu Claude. Charakterystyka: 3 bazy MariaDB, produkcja bez internetu (air-gap, LAN).
Wersja frameworka: Laravel 12 (nie 11). Laravel 11 jest EOL - Composer odmawia instalacji każdego wydania 11.31+ z powodu niezałatanych advisory bezpieczeństwa, a nowszych 11.x już nie ma. UAT/produkcję trzeba podnieść do 12. Kod nakładki nie wymagał żadnych zmian przy tym przejściu.
Tailwind v4, konfigurowany w CSS (
@themewresources/css/app.css). Plikutailwind.config.jsnie ma i nie powinno być - starsze fragmenty tego README, które go wymieniają, są nieaktualne.
Środowiska
| Środowisko | OS | Ścieżka | Internet |
|---|---|---|---|
| UAT / testowe | Debian | /var/www/html/softspm_pge |
jest (build assetów tutaj) |
| Produkcja | Windows Server | (web root → public/) |
BRAK (air-gap, LAN) |
Debian = case-sensitive! Nazwy plików/ścieżek (komponenty Blade, fonty, obrazki) muszą zgadzać się co do wielkości liter. Trzymamy wszystko lowercase.
Środowisko lokalne (Docker)
Stacja robocza ma tylko PHP 5.6 i 7.4 (XAMPP), a Laravel 12 wymaga PHP ≥ 8.2 -
dlatego dev stoi w kontenerze. Baza NIE jest kontenerem: łączymy się do
istniejącej MariaDB 10.42.1.210 (podejście database-first).
Kontener: docker/Dockerfile (PHP 8.3 + Apache + Node 20, rozszerzenia
pdo_mysql mysqli soap zip gd intl opcache; soap jest wymagany przez
SyndisService). DocumentRoot → public/.
docker compose up -d app # aplikacja na http://localhost:8000
docker compose exec app php artisan ... # artisan
docker compose exec app composer ... # composer
docker compose exec app npm run build # produkcyjny build assetów
docker compose --profile dev up vite # opcjonalny hot-reload (port 5173)
Pierwsze uruchomienie na czystej maszynie:
cp .env.example .env # uzupełnić DB_PASSWORD
docker compose build app
docker compose up -d app
docker compose exec app composer install
docker compose exec app npm install
docker compose exec app npm run build
docker compose exec app php artisan key:generate
docker compose exec app chmod -R 777 storage bootstrap/cache
docker compose exec app php docker/check/db-check.php # smoke-test 3 połączeń
php artisan migrate nie jest uruchamiane - sesje i cache lecą na pliki,
schematu legacy nie dotykamy.
Zasoby binarne (air-gap)
Nie da się ich pobrać na produkcji, więc leżą w repo (.gitignore ma na nie wyjątki):
| Plik | Skąd |
|---|---|
public/images/logo.png, dashboard_01.png, dashboard_02.png |
makiety newPGE/uj_dashboard/ (jedyna rzecz, po jaką sięgamy do newPGE - kodu legacy szukamy w trzeciCloude_v1) |
public/fonts/inter/Inter-Variable.woff2 |
fontsource (Inter VF, latin) |
public/fonts/jetbrains-mono/JetBrainsMono-Variable.woff2 |
fontsource (JetBrains Mono VF, latin) |
public/fonts/material-symbols/MaterialSymbolsOutlined.woff2 |
fontsource (Material Symbols Outlined VF) |
Vite przy buildzie ostrzega, że /fonts/... nie rozwiązuje się w czasie budowania -
to jest oczekiwane: ścieżki są absolutne i obsługuje je serwer z public/.
Jak nałożyć na softspm_pge (UAT, Debian)
- Skopiować pliki nakładki (lista:
docker/overlay-files.txt) do/var/www/html/softspm_pge/, nadpisując m.in.config/database.php,config/navigation.php,config/softspm.php,routes/web.php,resources/,package.json,vite.config.js.vendor/inode_modules/zostają; zpublic/kopiujemy tylkoimages/ifonts/. - Uprawnienia (Debian):
chown -R www-data:www-data storage bootstrap/cache. - Front-end (Tailwind v4 przez
@tailwindcss/vite, konfiguracja wresources/css/app.css; NIE matailwind.config.jsanipostcss.config.js):npm install npm run build # produkcyjny build do public/build .env(sekcja niżej) +php artisan config:cache. NIE uruchamiaćphp artisan migrate- sesje/cache trzymamy na plikach (patrz.env), więc nie tworzymy żadnych tabel; legacy schematu nie dotykamy.
Zmienne .env
APP_NAME=SoftSPM
APP_LOCALE=pl
# Database-first + brak potrzeby tabel pomocniczych → sesje/cache na plikach.
# Dzięki temu NIE uruchamiamy migracji i nie dorzucamy tabel do baz legacy.
SESSION_DRIVER=file
CACHE_STORE=file
QUEUE_CONNECTION=sync
DB_CONNECTION=softspm
# Baza operacyjna (domyślna)
DB_HOST=10.42.1.210
DB_PORT=3306
DB_DATABASE=softspm
DB_USERNAME=przemek
DB_PASSWORD=visia2209
# Bazy raportowa i historyczna (ten sam host/user, inna nazwa bazy)
DB_REP_DATABASE=softspm_rep
DB_HIS_DATABASE=softspm_his
# Migracja haseł MD5->bcrypt - włączyć DOPIERO po rozszerzeniu
# kolumny sys_users.USR_PASSWORD do VARCHAR(255).
SOFTSPM_REHASH=false
Air-gap (produkcja bez internetu) - zasady
- Zero CDN w runtime. Tailwind kompilujemy lokalnie (Vite). W makietach
(
uj_dashboard/) Tailwind/fonty szły z CDN - to tylko podgląd. - Fonty self-hosted. Pobrać i umieścić w
public/fonts/(na maszynie z netem), zgodnie z@font-facewresources/css/app.css:public/fonts/inter/Inter-Variable.woff2public/fonts/jetbrains-mono/JetBrainsMono-Variable.woff2public/fonts/material-symbols/MaterialSymbolsOutlined.woff2
- Tło logowania:
public/images/login-bg.jpg(zamiast obrazka z Google w makiecie - można użyćtrzeciCloude_v1/images/tlo.jpg). - Build na UAT (Debian, ma internet), wdrożenie na Windows (air-gap):
assety i zależności budujemy na UAT (
npm run build,composer install), a na produkcję Windows kopiujemy gotowy artefakt - pełnyvendor/+ skompilowanepublic/build/+ self-hostowane fonty/obrazki. Na produkcji bezcomposer install/npm install(brak internetu i często Node). - Web root produkcji (Windows): serwer (IIS/Apache) musi wskazywać podkatalog
public/, nie korzeń projektu.
Co już jest (pierwszy pionowy slice)
| Plik | Rola |
|---|---|
config/database.php |
3 połączenia MariaDB (database-first, bez zmiany schematu) |
config/softspm.php |
flaga migracji haseł MD5→bcrypt |
resources/css/app.css |
tokeny „Industrial Precision" (Tailwind v4, @theme) + fonty self-hosted |
resources/views/components/guest-layout.blade.php |
layout logowania |
resources/views/components/app-layout.blade.php |
layout aplikacji (topbar + sidebar) |
resources/views/auth/login.blade.php |
ekran logowania (wg makiety) |
resources/views/dashboard.blade.php |
pulpit (placeholder mapy) |
app/Models/User.php |
model na sys_users |
app/Http/Controllers/Auth/LoginController.php |
logowanie MD5/bcrypt + wybór oddziału |
app/Http/Controllers/WellController.php |
Studnie: lista (site401) + dodawanie/edycja (site301A/E/inf) |
app/Services/WellService.php |
transakcyjny zapis studni (lookupy + create + update) |
resources/views/wells/index.blade.php |
lista studni (wg makiety "Well Inventory") |
resources/views/wells/create.blade.php, edit.blade.php |
formularze dodania/edycji |
resources/views/components/well-field.blade.php, well-select.blade.php |
pola formularza |
routes/web.php |
trasy: login / logout / dashboard / wells (CRUD) |
Weryfikacja parytetu: Studnie (site401 → /wells)
Nowa lista zastępuje N+1 z legacy (podzapytania pompa/silnik/ON-OFF na każdy
wiersz) jednym zapytaniem z JOIN-ami. Przed zatwierdzeniem sprawdzić na
serwerze testowym, że zwraca ten sam zestaw studni co legacy, dla tego samego
oddziału i statusu. Szybki test liczności (MariaDB, podstaw <DZIAL>, <STATUS>):
-- Legacy: bazowa lista (przed N+1) - site401.php, zapytanie $query
SELECT COUNT(*) FROM seg_wells
LEFT JOIN seg_dev_resources ON DRS_DEV_ID=WLL_ID AND DRS_DEV_TYPE=12
LEFT JOIN seg_well_pump_eng_rel ON RWL_WLL_ID=WLL_ID
WHERE DRS_DEPARTMENT='<DZIAL>' AND DRS_STATUS_DIC_ID=<STATUS>;
Porównać z ->total() na /wells?status=<STATUS> (ten sam oddział z sesji).
Dodatkowo wyrywkowo sprawdzić kilka studni: nazwa pompy/silnika, nr seryjny i
ostatni stan ON/OFF (DRD_RESOURCES_DETAIL=507, najnowszy DRD_ID) muszą się zgadzać.
Świadome odstępstwa od legacy (do akceptacji)
- Paginacja serwerowa (
paginate(20)) zamiast cache w sesji + limit 100. Usuwa to limit 100 i checkbox „Pokaż wszystkie" (zbędny przy realnej paginacji). - Filtry przez GET (zamiast POST+sesja) - czyste linki, komponują się z paginacją.
- Stan ON/OFF jako chip (ON/OFF) zamiast ikon power_on/off.png.
Dodawanie / edycja studni (site301A/E/inf → /wells/create, /wells/{drs}/edit)
Zapis jest wielotabelowy. Dodanie studni wstawia do: seg_wells,
seg_dev_resources (typ 12), seg_dev_resources_det ×3 (średnica DST,
głębokość LS, zasilanie LZ), seg_object_hole_cards,
seg_object_hole_cards_his, seg_dev_resources_his. Edycja aktualizuje
seg_wells, seg_dev_resources, seg_object_hole_cards oraz (gdy istnieje)
datę zabudowy w seg_wells_exchanged. Cała logika w WellService.
Ulepszenia względem legacy
- Transakcja (
DB::transaction) - legacy robił te INSERT-y bez transakcji (ryzyko danych częściowych przy błędzie). Teraz zapis jest atomowy. - Walidacja wejścia + kontrola unikalności nazwy.
Świadome odstępstwa / pominięcia (do akceptacji)
- NIE przebudowujemy
rep_object_departmentspo każdym dodaniu (legacy robiłtruncate+insertcałej tabeli przez ajaxrefresh_departments). To wąskie gardło wydajności; nowa lista/wellsgo nie używa. Do rewizji przy migracji raportów, jeśli inne ekrany na nim polegają. - Słowniki w języku PL (
DIC_POL_LANG) - pełne i18n PL/EN/DE w osobnym etapie. build_timejako jedno poletime(HH:MM) zamiast dwóch selectów godz./min.
Weryfikacja (na serwerze testowym)
Dodać testową studnię w wybranym oddziale → sprawdzić, że pojawia się na /wells
(status 3, ten oddział) oraz że powstały spójne wpisy w 6 tabelach. Edytować →
sprawdzić aktualizację seg_wells/seg_dev_resources/seg_object_hole_cards.
Otwarte do ustalenia
- Hasła MD5 → bcrypt -
USR_PASSWORDtovarchar(64), więc bcrypt się mieści (rehash bezpieczny bez zmiany schematu). Czeka na zgodę klienta (SOFTSPM_REHASH=true). - Mapa offline - strategia kafelków bez internetu (lokalny tile-server / kafelki statyczne / własny podkład kopalni).
rep_object_departments- czy odtworzyć przebudowę po zapisie studni (na razie pominięta - patrz wyżej).