Feature: Nextcloud-Konfiguration in Einstellungen-UI (Migration 023)

This commit is contained in:
fds2610-bot 2026-04-10 21:34:59 +02:00
parent 880c479024
commit 092ea1f02f
7 changed files with 91 additions and 37 deletions

View file

@ -6,7 +6,8 @@
### Neu ### Neu
- `NextcloudImportService`: importiert Belege aus einem Nextcloud-Ordner via WebDAV (PROPFIND → GET → MOVE/DELETE); Duplikat-Erkennung via SHA-256; JPEG/PNG werden nach dem Download automatisch zugeschnitten - `NextcloudImportService`: importiert Belege aus einem Nextcloud-Ordner via WebDAV (PROPFIND → GET → MOVE/DELETE); Duplikat-Erkennung via SHA-256; JPEG/PNG werden nach dem Download automatisch zugeschnitten
- `scripts/nextcloud-import.php`: CLI-Einstiegspunkt für Cron-Betrieb; Konfiguration über `.env`-Variablen `NEXTCLOUD_URL`, `NEXTCLOUD_USER`, `NEXTCLOUD_PASS`, `NEXTCLOUD_FOLDER`, `NEXTCLOUD_DONE` - `scripts/nextcloud-import.php`: CLI-Einstiegspunkt für Cron-Betrieb
- Migration 023: Nextcloud-Zugangsdaten (`nextcloud_url`, `nextcloud_user`, `nextcloud_pass`, `nextcloud_folder`, `nextcloud_done`) in `company_settings`; Konfiguration über Einstellungen → Nextcloud-Belegimport in der UI
--- ---

View file

@ -168,17 +168,9 @@ Belege können automatisch aus einem Nextcloud-Ordner via WebDAV importiert werd
### Konfiguration ### Konfiguration
Umgebungsvariablen in der `.env`-Datei: Die Zugangsdaten werden in der Steuerkram-UI gepflegt: **Einstellungen → Nextcloud-Belegimport**.
```env Empfehlung: Ein Nextcloud-App-Passwort verwenden (Nextcloud → Einstellungen → Sicherheit → App-Passwörter).
NEXTCLOUD_URL=https://cloud.example.com
NEXTCLOUD_USER=meinbenutzername
NEXTCLOUD_PASS=mein-app-passwort
NEXTCLOUD_FOLDER=/Belege/Import # Ordner in Nextcloud, der überwacht wird
NEXTCLOUD_DONE=/Belege/Importiert # Ziel nach Import (leer lassen = Datei löschen)
```
**Empfehlung:** Ein Nextcloud-App-Passwort verwenden (Nextcloud → Einstellungen → Sicherheit → App-Passwörter).
### Manueller Aufruf ### Manueller Aufruf

View file

@ -0,0 +1,7 @@
-- Migration 023: Nextcloud-Import-Konfiguration in company_settings
ALTER TABLE company_settings
ADD COLUMN IF NOT EXISTS nextcloud_url VARCHAR(500) NULL AFTER ocr_aktiv,
ADD COLUMN IF NOT EXISTS nextcloud_user VARCHAR(255) NULL AFTER nextcloud_url,
ADD COLUMN IF NOT EXISTS nextcloud_pass VARCHAR(500) NULL AFTER nextcloud_user,
ADD COLUMN IF NOT EXISTS nextcloud_folder VARCHAR(500) NULL DEFAULT '/Belege/Import' AFTER nextcloud_pass,
ADD COLUMN IF NOT EXISTS nextcloud_done VARCHAR(500) NULL AFTER nextcloud_folder;

View file

@ -3,30 +3,26 @@
/** /**
* Nextcloud-Belegimport – CLI-Einstiegspunkt. * Nextcloud-Belegimport – CLI-Einstiegspunkt.
* *
* Liest Belege aus dem konfigurierten Nextcloud-Ordner (WebDAV) und legt * Liest Belege aus dem in den Einstellungen konfigurierten Nextcloud-Ordner
* sie in Steuerkram an. Danach werden die Dateien in Nextcloud in den * (WebDAV) und legt sie in Steuerkram an. Danach werden die Dateien in
* Erledigte-Ordner verschoben (oder gelöscht, wenn kein DONE-Ordner gesetzt). * Nextcloud in den Erledigte-Ordner verschoben (oder gelöscht, wenn dieser
* nicht konfiguriert ist).
*
* Konfiguration: Einstellungen → Nextcloud-Belegimport in der Steuerkram-UI.
* *
* Aufruf: * Aufruf:
* docker compose exec web php scripts/nextcloud-import.php * docker compose exec web php scripts/nextcloud-import.php
* *
* Für Cronjob (im Kontext des Containers): * Für Cronjob (auf dem Host):
* * * * * * docker compose -f /path/to/Steuerkram/docker-compose.yml exec -T web \ * *\/15 * * * * docker compose -f /opt/steuerkram/docker-compose.yml exec -T web \
* php scripts/nextcloud-import.php >> /var/log/steuerkram-import.log 2>&1 * php scripts/nextcloud-import.php >> /var/log/steuerkram-import.log 2>&1
*
* Umgebungsvariablen (in .env oder Systemumgebung):
* NEXTCLOUD_URL Basis-URL, z.B. https://cloud.example.com
* NEXTCLOUD_USER Benutzername
* NEXTCLOUD_PASS Passwort oder App-Passwort
* NEXTCLOUD_FOLDER Import-Ordner, z.B. /Belege/Import (Standard: /Belege/Import)
* NEXTCLOUD_DONE Erledigte-Ordner, z.B. /Belege/Importiert (leer = Datei löschen)
*/ */
declare(strict_types=1); declare(strict_types=1);
chdir(dirname(__DIR__)); chdir(dirname(__DIR__));
// .env laden falls vorhanden // DB-Zugangsdaten aus .env laden (für CLI-Kontext ohne Apache-Umgebung)
if (file_exists('.env')) { if (file_exists('.env')) {
foreach (file('.env', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) { foreach (file('.env', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
if (str_starts_with(trim($line), '#') || !str_contains($line, '=')) { if (str_starts_with(trim($line), '#') || !str_contains($line, '=')) {

View file

@ -29,7 +29,9 @@ class Setting
iban=?, bic=?, bank_name=?, iban=?, bic=?, bank_name=?,
ustva_steuernummer=?, ustva_bundesland=?, ustva_steuernummer=?, ustva_bundesland=?,
invoice_nr_prefix=?, beleg_nr_prefix=?, invoice_nr_prefix=?, beleg_nr_prefix=?,
payment_days_default=?, test_mode=?, ki_vorschlag_aktiv=?, ocr_aktiv=? payment_days_default=?, test_mode=?, ki_vorschlag_aktiv=?, ocr_aktiv=?,
nextcloud_url=?, nextcloud_user=?, nextcloud_pass=?,
nextcloud_folder=?, nextcloud_done=?
WHERE id=1', WHERE id=1',
[ [
$data['firma'] ?? '', $data['firma'] ?? '',
@ -54,6 +56,11 @@ class Setting
isset($data['test_mode']) ? 1 : 0, isset($data['test_mode']) ? 1 : 0,
isset($data['ki_vorschlag_aktiv']) ? 1 : 0, isset($data['ki_vorschlag_aktiv']) ? 1 : 0,
isset($data['ocr_aktiv']) ? 1 : 0, isset($data['ocr_aktiv']) ? 1 : 0,
$data['nextcloud_url'] ?: null,
$data['nextcloud_user'] ?: null,
$data['nextcloud_pass'] ?: null,
$data['nextcloud_folder'] ?: '/Belege/Import',
$data['nextcloud_done'] ?: null,
] ]
); );
} }

View file

@ -6,16 +6,17 @@ namespace Steuerkram\Services;
use Steuerkram\Database; use Steuerkram\Database;
use Steuerkram\Models\Beleg; use Steuerkram\Models\Beleg;
use Steuerkram\Models\Setting;
/** /**
* Importiert Belege aus einem Nextcloud-Ordner via WebDAV. * Importiert Belege aus einem Nextcloud-Ordner via WebDAV.
* *
* Konfiguration über Umgebungsvariablen: * Konfiguration über Einstellungen → Nextcloud-Belegimport (gespeichert in company_settings):
* NEXTCLOUD_URL – Basis-URL der Nextcloud, z.B. https://cloud.example.com * nextcloud_url – Basis-URL der Nextcloud, z.B. https://cloud.example.com
* NEXTCLOUD_USER – Benutzername * nextcloud_user – Benutzername
* NEXTCLOUD_PASS – Passwort oder App-Passwort * nextcloud_pass – Passwort oder App-Passwort
* NEXTCLOUD_FOLDER – Pfad zum Import-Ordner, z.B. /Belege/Import * nextcloud_folder – Pfad zum Import-Ordner, z.B. /Belege/Import
* NEXTCLOUD_DONE – Pfad für verarbeitete Dateien (optional), z.B. /Belege/Importiert * nextcloud_done – Pfad für verarbeitete Dateien (optional), z.B. /Belege/Importiert
* *
* Ablauf pro Datei: * Ablauf pro Datei:
* 1. PROPFIND → Dateiliste * 1. PROPFIND → Dateiliste
@ -47,11 +48,12 @@ class NextcloudImportService
public function __construct() public function __construct()
{ {
$this->baseUrl = rtrim(getenv('NEXTCLOUD_URL') ?: '', '/'); $cfg = Setting::get();
$this->user = getenv('NEXTCLOUD_USER') ?: ''; $this->baseUrl = rtrim($cfg['nextcloud_url'] ?? '', '/');
$this->pass = getenv('NEXTCLOUD_PASS') ?: ''; $this->user = $cfg['nextcloud_user'] ?? '';
$this->folder = '/' . trim(getenv('NEXTCLOUD_FOLDER') ?: 'Belege/Import', '/'); $this->pass = $cfg['nextcloud_pass'] ?? '';
$doneRaw = getenv('NEXTCLOUD_DONE') ?: ''; $this->folder = '/' . trim($cfg['nextcloud_folder'] ?: 'Belege/Import', '/');
$doneRaw = $cfg['nextcloud_done'] ?? '';
$this->doneFolder = $doneRaw !== '' ? ('/' . trim($doneRaw, '/')) : null; $this->doneFolder = $doneRaw !== '' ? ('/' . trim($doneRaw, '/')) : null;
$this->davBase = $this->baseUrl . '/remote.php/dav/files/' . rawurlencode($this->user); $this->davBase = $this->baseUrl . '/remote.php/dav/files/' . rawurlencode($this->user);
} }

View file

@ -172,6 +172,55 @@
</div> </div>
</div> </div>
<!-- Nextcloud-Import -->
<div class="card mb-2">
<div class="card-header"><div class="card-title">Nextcloud-Belegimport</div></div>
<div class="card-body">
<p class="text-muted text-sm" style="margin:0 0 .75rem">
Belege werden automatisch per WebDAV aus dem angegebenen Nextcloud-Ordner importiert.
Verarbeitete Dateien werden in den Erledigte-Ordner verschoben (oder gelöscht, wenn leer).
</p>
<div class="form-group">
<label>Nextcloud-URL</label>
<input type="url" name="nextcloud_url"
value="<?= $h($settings['nextcloud_url'] ?? '') ?>"
placeholder="https://cloud.example.com">
</div>
<div class="form-grid form-grid-2">
<div class="form-group">
<label>Benutzername</label>
<input type="text" name="nextcloud_user"
value="<?= $h($settings['nextcloud_user'] ?? '') ?>"
autocomplete="off">
</div>
<div class="form-group">
<label>App-Passwort</label>
<input type="password" name="nextcloud_pass"
value="<?= $h($settings['nextcloud_pass'] ?? '') ?>"
autocomplete="new-password"
placeholder="<?= !empty($settings['nextcloud_pass']) ? '(gespeichert)' : '' ?>">
<div class="form-hint">Empfohlen: App-Passwort aus Nextcloud → Einstellungen → Sicherheit</div>
</div>
</div>
<div class="form-group">
<label>Import-Ordner</label>
<input type="text" name="nextcloud_folder"
value="<?= $h($settings['nextcloud_folder'] ?? '/Belege/Import') ?>"
placeholder="/Belege/Import">
</div>
<div class="form-group">
<label>Erledigte-Ordner <span class="text-muted">(leer = Datei löschen)</span></label>
<input type="text" name="nextcloud_done"
value="<?= $h($settings['nextcloud_done'] ?? '') ?>"
placeholder="/Belege/Importiert">
</div>
<div class="form-hint">
Import manuell starten:
<code>docker compose exec web php scripts/nextcloud-import.php</code>
</div>
</div>
</div>
<div class="card mb-2"> <div class="card mb-2">
<div class="card-header"><div class="card-title">Bankdaten</div></div> <div class="card-header"><div class="card-title">Bankdaten</div></div>
<div class="card-body"> <div class="card-body">