Initial commit

This commit is contained in:
2026-09-03 12:21:17 +02:00
commit 6d40da0410
155 changed files with 21554 additions and 0 deletions
+233
View File
@@ -0,0 +1,233 @@
# 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).