# GAEB Aufmaß (MVP) – PHP + MySQL

Dieses Paket ist ein **laufendes Minimalprodukt**, mit dem du:
- Projekte anlegen kannst
- **GAEB X83 (XML)** hochladen und Positionen importieren kannst (toleranter Import über `<Item>` / `Qty` / `QU` / `OutlineText` / `DetailTxt`)
- pro Position **Aufmaß nach Datum** erfassen kannst (Menge + Notiz)
- **Fotos je Aufmaß** hochladen kannst
- Soll/Ist/Delta pro Position siehst

## Installation (lokal / Server)

1) Datenbank anlegen:
```sql
CREATE DATABASE gaeb_aufmass CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
```

2) Tabellen + Admin anlegen:
- `schema.sql` ausführen.

3) Config setzen:
- `app/config.example.php` nach `app/config.php` kopieren
- DB-Zugangsdaten eintragen
- `app_key` ändern (lange zufällige Zeichenkette)

4) Webserver DocumentRoot auf `public/` setzen

### Lokal testen (PHP Built-in Server)
Im Projektordner:
```bash
php -S localhost:8080 -t public
```

Dann öffnen: http://localhost:8080

## Login
- E-Mail: `admin@example.com`
- Passwort: `admin123`  (bitte sofort ändern!)

## Hinweise / Nächste Schritte (wenn du willst)
- Titel/Gewerk/Los Baumstruktur aus GAEB (BoQBody / BoQPart / ...): im MVP noch nicht abgebildet
- PDF-Aufmaßblatt Export: ergänzbar
- Offline (PWA) + Sync: ergänzbar
- EXIF-Entfernung bei Fotos: empfehlenswert (DSGVO/Standortdaten)

Technischer Hintergrund (GAEB DA XML, Schema-Elemente wie Item/Qty/QU/OutlineText/DetailTxt): siehe GAEB Schema-/Fachdokumentation. 


## Neu
- Verbesserter X83 Text-Import (Kurz-/Langtext über mehrere GAEB-Varianten)
- Report: Mehr-/Mindermengen je Projekt (`?r=report&id=...`)
- Mobile: Quick-Buttons +1/+5/+10, Foto-Upload wird automatisch deaktiviert, wenn Upload-Ordner nicht beschreibbar ist.


## Audit-Log (Nachvollziehbarkeit)

Dieses Tool protokolliert sicherheits- und abrechnungsrelevante Aktionen in `audit_log` (z.B. Login, LV-Import, Aufmaß-Erfassung inkl. Fotos). Die Ansicht ist über **System-Log** (Admin) sowie **Log** im Projekt/Position erreichbar.

### Migration bestehender Installationen

Falls deine Datenbank älter ist, führe folgende SQLs aus:

```sql
ALTER TABLE users ADD COLUMN is_admin TINYINT(1) NOT NULL DEFAULT 0;
ALTER TABLE projects ADD COLUMN owner_user_id INT NULL;
CREATE TABLE IF NOT EXISTS login_attempts (
  ip VARCHAR(64) PRIMARY KEY,
  fail_count INT NOT NULL DEFAULT 0,
  first_fail_at DATETIME NULL,
  last_fail_at DATETIME NULL,
  banned_until DATETIME NULL
);
CREATE TABLE IF NOT EXISTS audit_log (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  ts_utc DATETIME NOT NULL,
  user_id INT NULL,
  username VARCHAR(190) NULL,
  is_admin TINYINT(1) NOT NULL DEFAULT 0,
  ip VARCHAR(64) NOT NULL,
  user_agent VARCHAR(255) NOT NULL,
  request_id VARCHAR(64) NULL,
  action VARCHAR(64) NOT NULL,
  object_type VARCHAR(32) NULL,
  object_id VARCHAR(64) NULL,
  project_id INT NULL,
  item_id INT NULL,
  oz VARCHAR(64) NULL,
  before_json LONGTEXT NULL,
  after_json LONGTEXT NULL,
  meta_json LONGTEXT NULL
);
```

Setze für bestehende Projekte einmal den Besitzer (Admin-ID meist 1):

```sql
UPDATE projects SET owner_user_id=1 WHERE owner_user_id IS NULL;
```

## Audit-Log (Nachvollziehbarkeit)

Das Tool protokolliert Aktionen (wer/wann/von welcher IP) in `audit_log`, u. a.:

- Login erfolgreich/fehlgeschlagen + IP-Sperre
- Benutzer anlegen/löschen, Passwort ändern
- Projekt anlegen/löschen
- LV Import (X83)
- Aufmaß erfassen (Menge/Datum/Notiz) + Foto-Uploads

### Migration bestehender Installationen (SQL)

```sql
ALTER TABLE users ADD COLUMN is_admin TINYINT(1) NOT NULL DEFAULT 0;

ALTER TABLE projects ADD COLUMN owner_user_id INT NULL;
ALTER TABLE projects ADD INDEX idx_projects_owner (owner_user_id);
ALTER TABLE projects ADD CONSTRAINT fk_projects_owner FOREIGN KEY (owner_user_id) REFERENCES users(id) ON DELETE RESTRICT;

CREATE TABLE IF NOT EXISTS login_attempts (
  ip VARCHAR(64) PRIMARY KEY,
  fail_count INT NOT NULL DEFAULT 0,
  first_fail_at DATETIME NULL,
  last_fail_at DATETIME NULL,
  banned_until DATETIME NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS audit_log (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  ts_utc DATETIME NOT NULL,
  user_id INT NULL,
  username VARCHAR(190) NULL,
  is_admin TINYINT(1) NOT NULL DEFAULT 0,
  ip VARCHAR(64) NOT NULL,
  user_agent VARCHAR(255) NOT NULL,
  request_id VARCHAR(64) NULL,
  action VARCHAR(64) NOT NULL,
  object_type VARCHAR(32) NULL,
  object_id VARCHAR(64) NULL,
  project_id INT NULL,
  item_id INT NULL,
  oz VARCHAR(64) NULL,
  before_json LONGTEXT NULL,
  after_json LONGTEXT NULL,
  meta_json LONGTEXT NULL,
  INDEX idx_audit_project_ts (project_id, ts_utc),
  INDEX idx_audit_item_ts (item_id, ts_utc),
  INDEX idx_audit_user_ts (user_id, ts_utc),
  INDEX idx_audit_action_ts (action, ts_utc),
  INDEX idx_audit_obj (object_type, object_id),
  CONSTRAINT fk_audit_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```

Hinweis: Für bestehende Projekte sollte `owner_user_id` einmalig gesetzt werden (z. B. Admin-ID 1):

```sql
UPDATE projects SET owner_user_id = 1 WHERE owner_user_id IS NULL;
```
