feat: Kontoauszug vom Telefon per Teilen-Menue einlesen
Revolut und Raiffeisen lassen die CSV auch am Handy exportieren; nur N26 verlangt die Web-Version. Ein zweiter Kurzbefehl nimmt die Datei aus dem Teilen-Menue entgegen und schickt sie mit dem gewaehlten Konto an /quick/statement. Am Telefon laesst sich keine Spaltenzuordnung vornehmen. Der Endpunkt verwendet deshalb die Einstellung, mit der dieses Konto zuletzt erfolgreich eingelesen wurde – und sagt klar Bescheid, wenn es noch keine gibt, statt mit falschen Spalten zu raten. Gebucht wird sofort: Ein Auszug hat hunderte Zeilen, die einzeln abzunicken waere keine Erleichterung. Sicher ist das durch die Duplikaterkennung und weil der Stapel im Import-Verlauf mit einem Klick zurueckzunehmen ist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -483,7 +483,14 @@
|
||||
"revokeConfirm": "Marke „{{name}}\" widerrufen? Der Kurzbefehl auf dem Gerät funktioniert danach nicht mehr. Bereits erfasste Buchungen bleiben.",
|
||||
"noDefault": "kein Standardkonto",
|
||||
"lastUsed": "schon benutzt",
|
||||
"neverUsed": "noch nie benutzt"
|
||||
"neverUsed": "noch nie benutzt",
|
||||
"fileGuideTitle": "Kontoauszug vom Handy einlesen",
|
||||
"fileGuideIntro": "Revolut und Raiffeisen lassen die CSV auch am Telefon exportieren. Ein zweiter Kurzbefehl nimmt sie aus dem Teilen-Menü entgegen. Voraussetzung: Du hast für dieses Konto schon einmal am Rechner eingelesen – Certain verwendet dann dieselbe Spaltenzuordnung.",
|
||||
"fileStep1": "Neuer Kurzbefehl → oben auf den Namen tippen → „Im Teilen-Menü anzeigen“ einschalten, Eingabetyp: Dateien",
|
||||
"fileStep2": "Suche nach „Liste“ → „Aus Liste wählen“ für das Konto (die Konto-Nummern findest du über die Adresse /api/quick/accounts)",
|
||||
"fileStep3": "Suche nach „URL“ → „Inhalte von URL abrufen“. Methode POST, Header X-Certain-Token wie oben, Anfragetext „Formular“ mit file = Kurzbefehleingabe und account_id = das gewählte Konto:",
|
||||
"fileStep4": "„Mitteilung anzeigen“ – dann siehst du „14 gebucht · 512 schon vorhanden“",
|
||||
"fileGuideNote": "Gebucht wird sofort, weil ein Auszug hunderte Zeilen hat. Das ist ungefährlich: Bereits vorhandene Buchungen werden erkannt und übersprungen, und der ganze Stapel lässt sich im Import-Verlauf mit einem Klick zurücknehmen."
|
||||
},
|
||||
"inbox": {
|
||||
"title": "Eingang",
|
||||
|
||||
@@ -483,7 +483,14 @@
|
||||
"revokeConfirm": "Revoke token “{{name}}”? The shortcut on that device will stop working. Bookings already recorded stay.",
|
||||
"noDefault": "no default account",
|
||||
"lastUsed": "used before",
|
||||
"neverUsed": "never used"
|
||||
"neverUsed": "never used",
|
||||
"fileGuideTitle": "Import a statement from your phone",
|
||||
"fileGuideIntro": "Revolut and Raiffeisen let you export the CSV on the phone too. A second shortcut takes it from the share sheet. Prerequisite: you have imported for this account on a computer once – Certain then reuses that column mapping.",
|
||||
"fileStep1": "New shortcut → tap its name → enable “Show in Share Sheet”, input type: Files",
|
||||
"fileStep2": "Search for “List” → “Choose from List” for the account (account ids are at /api/quick/accounts)",
|
||||
"fileStep3": "Search for “URL” → “Get Contents of URL”. Method POST, header X-Certain-Token as above, request body “Form” with file = Shortcut Input and account_id = the chosen account:",
|
||||
"fileStep4": "“Show Notification” – you then see “14 booked · 512 already present”",
|
||||
"fileGuideNote": "It books straight away because a statement has hundreds of rows. That is safe: existing bookings are recognised and skipped, and the whole batch can be undone with one click in the import history."
|
||||
},
|
||||
"inbox": {
|
||||
"title": "Captured",
|
||||
|
||||
@@ -154,6 +154,27 @@ export default function Geraetemarken() {
|
||||
<p className="muted small">{t("tokens.guideHomeScreen")}</p>
|
||||
<p className="muted small">{t("tokens.guideAutomation")}</p>
|
||||
</details>
|
||||
|
||||
<details style={{ marginTop: "var(--sp-3)" }}>
|
||||
<summary>{t("tokens.fileGuideTitle")}</summary>
|
||||
<p className="muted small">{t("tokens.fileGuideIntro")}</p>
|
||||
<ol className="muted small" style={{ paddingLeft: "1.2em" }}>
|
||||
<li>{t("tokens.fileStep1")}</li>
|
||||
<li>{t("tokens.fileStep2")}</li>
|
||||
<li>
|
||||
{t("tokens.fileStep3")}
|
||||
<div className="input-with-button" style={{ marginTop: 4 }}>
|
||||
<input readOnly className="selectable" value={`${basis}/api/quick/statement`} />
|
||||
<button type="button" className="btn sm"
|
||||
onClick={() => kopieren(`${basis}/api/quick/statement`)}>
|
||||
<Icon name="copy" size={14} />
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
<li>{t("tokens.fileStep4")}</li>
|
||||
</ol>
|
||||
<p className="muted small">{t("tokens.fileGuideNote")}</p>
|
||||
</details>
|
||||
<button className="btn sm ghost" style={{ marginTop: "var(--sp-2)" }}
|
||||
onClick={() => setFrisch(null)}>
|
||||
{t("tokens.hide")}
|
||||
|
||||
Reference in New Issue
Block a user