Merge pull request 'Fix #21: Bargeld-Tool auch bei Adresse mit /api/v1 erreichen' (#39) from fds2610-bot/Finanzmanager:main into main

Reviewed-on: https://codeberg.org/fds2610/Finanzmanager/pulls/39
This commit is contained in:
fds2610 2026-08-19 08:42:14 +02:00
commit 18c1603dbd
7 changed files with 88 additions and 3 deletions

View file

@ -1,5 +1,13 @@
# Änderungen
## Bargeld-Tool: Adresse mit `/api/v1` (19.08.2026)
Der Verbindungstest scheiterte mit „Das Bargeld-Tool kennt die Schnittstelle nicht
(HTTP 404)“, wenn die hinterlegte Adresse den Schnittstellenpfad schon enthielt – der
Finanzmanager hängt ihn selbst an und fragte dann unter `/api/v1/api/v1/status` an. Ein
abschließendes `/api` bzw. `/api/v1` kürzt er jetzt beim Speichern weg; bereits
gespeicherte Adressen räumt Migration 017 auf.
## Abgleich mit dem Bargeld-Tool (19.08.2026)
Bargeldausgaben werden in einem zweiten Programm erfasst; im Finanzmanager kommen sie als

View file

@ -262,3 +262,8 @@ nicht (404), prüft der Verbindungstest über eine Suchabfrage.
Der Betrag geht vorzeichenbehaftet über die Leitung, so wie er im Finanzmanager steht:
Ausgaben negativ. Führt das Bargeld-Tool seine Beträge positiv, muss es umrechnen.
`{adresse}` ist die Basisadresse **ohne** Schnittstellenpfad. Steht am Ende der eingetragenen
Adresse trotzdem `/api` oder `/api/v1`, kürzt der Finanzmanager sie beim Speichern – die
Adresse aus der Browserzeile zu kopieren ist der naheliegende Weg und führte sonst zu
`/api/v1/api/v1/status` und einem 404 im Verbindungstest.

View file

@ -0,0 +1,14 @@
-- Die Adresse des Bargeld-Tools ohne den Schnittstellenpfad.
--
-- Der Finanzmanager hängt `/api/v1/...` selbst an die hinterlegte Adresse.
-- Wer sie aus dem Browser kopiert hat, trug den Pfad mit ein – dann fragte
-- der Verbindungstest unter `/api/v1/api/v1/status` an und bekam ein 404.
-- Neue Eingaben kürzt der Finanzmanager beim Speichern; bereits gespeicherte
-- Adressen räumt diese Migration auf.
--
-- Idempotent: Auf einer bereits gekürzten Adresse ändert der Ausdruck nichts.
UPDATE einstellungen
SET wert = REGEXP_REPLACE(TRIM(wert), '/+api(/+v[0-9]+)?/*$', '')
WHERE schluessel = 'bargeld_url'
AND wert REGEXP '/+api(/+v[0-9]+)?/*$';

View file

@ -232,7 +232,9 @@ class VerwaltungController extends BaseController
return;
}
Einstellung::set('bargeld_url', rtrim($url, '/'), 'bargeld');
// Ein mitkopiertes „/api/v1“ am Ende fliegt raus – sonst hinge der
// Schnittstellenpfad ein zweites Mal dran.
Einstellung::set('bargeld_url', $url === '' ? '' : BargeldTool::basisadresse($url), 'bargeld');
Einstellung::set('bargeld_benutzer', trim($this->post('bargeld_benutzer')), 'bargeld');
// Wie bei der FinTS-PIN: Ein leeres Feld heißt „unverändert“, sonst

View file

@ -41,11 +41,26 @@ class BargeldTool
/** Höchstzahl der Treffer, die die Gegenstelle liefern soll. */
private const GRENZE = 20;
private string $basisUrl;
public function __construct(
private string $basisUrl,
string $basisUrl,
private string $benutzer = '',
private string $passwort = ''
) {
$this->basisUrl = self::basisadresse($basisUrl);
}
/**
* Die Basisadresse ohne den Schnittstellenpfad. Wer die Adresse aus dem
* Browser kopiert, hat `/api/v1` schon dabei – ohne diese Kürzung fragte
* der Finanzmanager unter `/api/v1/api/v1/status` an und bekam ein 404.
*/
public static function basisadresse(string $url): string
{
$url = rtrim(trim($url), '/');
return (string)preg_replace('#/api(?:/v\\d+)?$#i', '', $url);
}
/**

View file

@ -55,7 +55,8 @@ include __DIR__ . '/../layout/kopf.php';
placeholder="https://…" inputmode="url">
<p class="feldhinweis">
Die Basisadresse des Bargeld-Tools ohne Pfad; der Finanzmanager hängt
<code>/api/v1/buchungen</code> selbst an. Leer lassen schaltet den Abgleich ab –
<code>/api/v1/buchungen</code> selbst an. Ein mitkopiertes <code>/api/v1</code>
am Ende entfernt er beim Speichern. Leer lassen schaltet den Abgleich ab –
das Kontoblatt zeigt dann überall den grauen Kreis.
</p>

View file

@ -39,6 +39,7 @@ class BargeldAbgleichTest extends TestCase
$this->stammdaten();
$this->antwortAuswerten();
$this->basisadresseKuerztDenSchnittstellenpfad();
$this->kategorienauswahl();
$this->ohneAdresseKeinAbgleich();
$this->passwortStehtVerschluesselt();
@ -113,6 +114,45 @@ class BargeldAbgleichTest extends TestCase
$this->assert($ohneFeld['fehler'], 'Ohne Feld „buchungen“ ist die Antwort unbrauchbar');
}
// ── Basisadresse ─────────────────────────────────────────────────────────
/**
* Wer die Adresse aus dem Browser kopiert, hat `/api/v1` schon dabei.
* Bleibt es stehen, fragt der Finanzmanager unter `/api/v1/api/v1/status`
* an und der Verbindungstest scheitert mit einem 404.
*/
private function basisadresseKuerztDenSchnittstellenpfad(): void
{
$erwartet = 'https://bargeld.example.org';
foreach ([
'https://bargeld.example.org',
'https://bargeld.example.org/',
'https://bargeld.example.org/api',
'https://bargeld.example.org/api/v1',
'https://bargeld.example.org/api/v1/',
' https://bargeld.example.org/api/v2 ',
] as $eingabe) {
$this->assertEquals(
$erwartet,
BargeldTool::basisadresse($eingabe),
'Basisadresse aus „' . trim($eingabe) . '“'
);
}
$this->assertEquals(
'https://example.org/fscash',
BargeldTool::basisadresse('https://example.org/fscash/api/v1'),
'Ein Unterverzeichnis vor dem Schnittstellenpfad bleibt erhalten'
);
$this->assertEquals(
'https://apianbieter.example.org',
BargeldTool::basisadresse('https://apianbieter.example.org'),
'Nur ein eigener Pfadteil „api“ wird gekürzt, kein Namensbestandteil'
);
}
// ── Auswahl der Kategorien ───────────────────────────────────────────────
private function kategorienauswahl(): void