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

234 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`](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](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/`.
```bash
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:
```bash
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`
```dotenv
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>`):
```sql
-- 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).