Finanzen: Bankbuchungen Rechnungen, Auszahlungen, Fixkosten und Kategorien zuordnen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
f14a6b7b57
commit
2bf67cb48d
3 files changed
+767
-3
No files matched your search
@@ -4,9 +4,10 @@ import { withLocks } from '../../services/keyedLock.js'
|
||||
import { EnableBankingError } from '../../services/finance/enableBanking.js'
|
||||
import { completeBankAuth, startBankAuth, syncBank } from '../../services/finance/bankSync.js'
|
||||
import { getConnection, listTransactions, saveConnection } from '../../services/finance/bankStore.js'
|
||||
import { AssignError, assignTransaction, unassignTransaction, withSuggestions } from '../../services/finance/assign.js'
|
||||
|
||||
/**
|
||||
* Finanzen im WOMS (nur Admins): Bankstatus, Abruf, Neuverbindung und Buchungen. Die Handler sind klein und rufen
|
||||
* Finanzen im WOMS (nur Admins): Bankstatus, Abruf, Neuverbindung, Buchungen und deren Zuordnung. Die Handler sind klein und rufen
|
||||
* die Dienste in server/services/finance auf; weitere Finanz-Routen kommen in dieselbe Datei.
|
||||
*/
|
||||
const router = Router()
|
||||
@@ -113,12 +114,52 @@ router.post('/bank/rueckkehr', async (req, res) => {
|
||||
|
||||
router.get('/buchungen', async (_req, res) => {
|
||||
try {
|
||||
const buchungen = (await listTransactions()).map(publicTransaction)
|
||||
return res.json({ buchungen })
|
||||
// Vorschlaege kommen von Stripe: ein Ausfall dort (stripeFehler) macht die Liste nie kaputt
|
||||
return res.json(await withSuggestions((await listTransactions()).map(publicTransaction)))
|
||||
} catch (err) {
|
||||
logFailure('Buchungen laden', err)
|
||||
return res.status(500).json({ error: 'Buchungen konnten nicht geladen werden.' })
|
||||
}
|
||||
})
|
||||
|
||||
const STRIPE_REJECTED_MESSAGE = 'Stripe hat die Änderung abgelehnt.'
|
||||
const STRIPE_UNAVAILABLE_MESSAGE = 'Stripe ist gerade nicht erreichbar.'
|
||||
|
||||
// Fehler des Stripe-Pakets (StripeInvalidRequestError, StripeConnectionError, ...) tragen type "Stripe..."
|
||||
const isStripeError = (err) => typeof err?.type === 'string' && err.type.startsWith('Stripe')
|
||||
|
||||
/**
|
||||
* Antwort auf einen Fehler beim Zuordnen: AssignError (eigene, anzeigbare Meldung) mit seinem Status; Stripe lehnt
|
||||
* ab (4xx, ausser 429) -> 409; Stripe sonst nicht erreichbar -> 502; alles andere 500. Meldungen von Stripe, Appwrite
|
||||
* und Netzfehlern (Adressen, Schluessel) gehen nie an die Seite.
|
||||
*/
|
||||
function sendAssignError(res, what, err) {
|
||||
if (err instanceof AssignError) return res.status(err.status).json({ error: err.message })
|
||||
logFailure(what, err)
|
||||
if (isStripeError(err)) {
|
||||
const status = err.statusCode
|
||||
if (status >= 400 && status < 500 && status !== 429) return res.status(409).json({ error: STRIPE_REJECTED_MESSAGE })
|
||||
return res.status(502).json({ error: STRIPE_UNAVAILABLE_MESSAGE })
|
||||
}
|
||||
return res.status(500).json({ error: 'Interner Fehler.' })
|
||||
}
|
||||
|
||||
router.post('/buchungen/:id/zuordnen', async (req, res) => {
|
||||
const { invoiceId, payoutId, fixedCostId, category, note } = req.body || {}
|
||||
try {
|
||||
const buchung = await assignTransaction(req.params.id, { invoiceId, payoutId, fixedCostId, category, note })
|
||||
return res.json({ buchung: publicTransaction(buchung) })
|
||||
} catch (err) {
|
||||
return sendAssignError(res, 'Buchung zuordnen', err)
|
||||
}
|
||||
})
|
||||
|
||||
router.delete('/buchungen/:id/zuordnung', async (req, res) => {
|
||||
try {
|
||||
return res.json({ buchung: publicTransaction(await unassignTransaction(req.params.id)) })
|
||||
} catch (err) {
|
||||
return sendAssignError(res, 'Zuordnung lösen', err)
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
||||
Reference in new issue
Block a user