Files
kopalnia_2026/README_SOFTSPM.md
2026-09-03 12:21:17 +02:00

11 KiB
Raw Permalink Blame History

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\ - NIE newPGE ani inne kopie w htdocs/. Audyt legacy i mapa siteNNN → 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 (@theme w resources/css/app.css). Pliku tailwind.config.js nie 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)

  1. 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/ i node_modules/ zostają; z public/ kopiujemy tylko images/ i fonts/.
  2. Uprawnienia (Debian): chown -R www-data:www-data storage bootstrap/cache.
  3. Front-end (Tailwind v4 przez @tailwindcss/vite, konfiguracja w resources/css/app.css; NIE ma tailwind.config.js ani postcss.config.js):
    npm install
    npm run build          # produkcyjny build do public/build
    
  4. .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-face w resources/css/app.css:
    • public/fonts/inter/Inter-Variable.woff2
    • public/fonts/jetbrains-mono/JetBrainsMono-Variable.woff2
    • public/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łny vendor/ + skompilowane public/build/ + self-hostowane fonty/obrazki. Na produkcji bez composer 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_departments po każdym dodaniu (legacy robił truncate+insert całej tabeli przez ajax refresh_departments). To wąskie gardło wydajności; nowa lista /wells go 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_time jako jedno pole time (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_PASSWORD to varchar(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).