Etappe 5. Bildet das laufende Verfahren beim Bezirk Oberfranken ab. Rechtsbehelfsfrist: § 187 Abs. 1, § 188 Abs. 2 und 3 BGB, danach § 64 Abs. 3 SGG - hier verschieben Wochenende und Feiertag das Fristende auf den naechsten Werktag. Das ist genau umgekehrt zu den Betreuerfristen, wo bewusst nicht verschoben wird, und deshalb liegt die Feiertagsliste getrennt. Zwei bayerische Sonderfaelle, die haeufig falsch gemacht werden: Mariae Himmelfahrt verschiebt NICHT (Art. 1 Abs. 1 S. 2 BayFTG - der Feiertag gilt nur in ueberwiegend katholischen Gemeinden, Bayreuth ist keine), und der Buss- und Bettag ist in Bayern seit 1995 kein Feiertag mehr. Beide erzeugen stattdessen einen ausdruecklichen Hinweis, damit man die Frist im Zweifel selbst nachrechnet. Der Rechenweg wird als Schrittliste ausgegeben. Heimkosten: Der Dashboard-Agent hatte einen fachlichen Widerspruch gefunden - der einrichtungseinheitliche Eigenanteil auf der Heimrechnung ist bereits um die Leistung der Pflegekasse gekuerzt. Wird sie zusaetzlich als Deckung erfasst, entsteht eine Doppelzaehlung von ueber tausend Euro im Monat. Das Modul rechnet jetzt ausdruecklich nach der Lesart EIGENANTEIL_NETTO, fuehrt die Pflegekassenleistung nur nachrichtlich mit und warnt, wenn sie doch belegt ist. Die Oberflaeche sagt auf einer eigenen Karte, was hier gegen was gerechnet wird. Die Schonvermoegens-Bewertung liefert Argumentationshilfen zum Uebernehmen, keine Automatik - die Einordnung obliegt dem Traeger und gegebenenfalls dem Sozialgericht. Das steht an jeder dieser Karten. Alle jaehrlich veraenderlichen Betraege stehen an einer Stelle mit Stand-Datum und Prueftermin. Die Bekleidungspauschale bewusst ohne Zahl: sie ist regional und steht im Bescheid. 46 Tests. Etappe: 5 Phase: Behoerde
233 lines
8.7 KiB
TypeScript
233 lines
8.7 KiB
TypeScript
import { SeitenKopf } from '@/components/seiten-kopf'
|
|
import { Rechtshinweis } from '@/components/rechtshinweis'
|
|
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
|
|
import { Card, CardContent } from '@/components/ui/card'
|
|
import { Vermoegensliste, type ListenPosten } from '@/components/sozialhilfe/vermoegensliste'
|
|
import { oeffnen } from '@/lib/crypto/feld'
|
|
import { centZuZahl, db, nichtGeloescht } from '@/lib/db'
|
|
import { alsIsoTag } from '@/lib/fristen/datum'
|
|
import { VERMOEGENS_ART_BESCHRIFTUNG } from '@/lib/finanzen/kategorien'
|
|
import { MIT_RUECKKAUFSWERT, VERTRAG_ART_BESCHRIFTUNG } from '@/lib/vertraege/konstanten'
|
|
import { BEWERTUNG_BESCHRIFTUNG } from '@/lib/sozialhilfe/schonvermoegen'
|
|
import { freibetragVergleichen, uebersichtBilden } from '@/lib/sozialhilfe/vermoegensuebersicht'
|
|
import { sozialhilfeKontext } from '@/lib/sozialhilfe/zugang'
|
|
import { formatCent } from '@/lib/utils'
|
|
import { AlertCircle } from 'lucide-react'
|
|
|
|
export const dynamic = 'force-dynamic'
|
|
|
|
/**
|
|
* Vermögens-Bewertungsansicht.
|
|
*
|
|
* Sie zählt zusammen und stellt gegenüber - sie entscheidet nichts. Was
|
|
* geschützt ist, sagt der Träger; bleibt man uneins, das Sozialgericht.
|
|
* Deshalb heißt die Spalte "Einschätzung" und nicht "Bewertung".
|
|
*/
|
|
export default async function VermoegensbewertungSeite() {
|
|
const { betreuteId, darfSchreiben } = await sozialhilfeKontext()
|
|
|
|
const [posten, vertraege] = await Promise.all([
|
|
db.vermoegensposten.findMany({
|
|
where: { betreuteId, ...nichtGeloescht },
|
|
include: { wertstaende: { orderBy: { stichtag: 'desc' }, take: 1 } },
|
|
orderBy: { bezeichnung: 'asc' },
|
|
}),
|
|
db.vertrag.findMany({
|
|
where: {
|
|
betreuteId,
|
|
// Nur Vertraege, die ueberhaupt einen Wert darstellen koennen. Ein
|
|
// Stromvertrag hat keinen Rueckkaufswert und wuerde die Liste zumuellen.
|
|
art: { in: [...MIT_RUECKKAUFSWERT] },
|
|
...nichtGeloescht,
|
|
},
|
|
orderBy: { bezeichnung: 'asc' },
|
|
}),
|
|
])
|
|
|
|
// Verträge, die schon als Vermögensposten geführt werden, nicht doppelt
|
|
// zeigen - sonst wäre die Summe zweimal drin.
|
|
const bereitsAlsPosten = new Set(
|
|
posten.map((p) => p.vertragId).filter((id): id is string => id !== null),
|
|
)
|
|
|
|
const zeilen: ListenPosten[] = [
|
|
...posten.map((p) => {
|
|
const geoeffnet = oeffnen('Vermoegensposten', p)
|
|
const stand = p.wertstaende[0]
|
|
return {
|
|
id: p.id,
|
|
bezeichnung: p.bezeichnung,
|
|
herkunft: 'VERMOEGEN' as const,
|
|
art: p.art,
|
|
artBeschriftung: VERMOEGENS_ART_BESCHRIFTUNG[p.art],
|
|
bewertung: p.bewertungSozialhilfe,
|
|
wertCent: stand ? centZuZahl(stand.wertCent) : null,
|
|
wertStichtag: stand ? alsIsoTag(stand.stichtag) : null,
|
|
begruendung: geoeffnet.bewertungBegruendung ?? '',
|
|
zusatz: stand ? stand.wertquelle : null,
|
|
}
|
|
}),
|
|
...vertraege
|
|
.filter((v) => !bereitsAlsPosten.has(v.id))
|
|
.map((v) => {
|
|
const geoeffnet = oeffnen('Vertrag', v)
|
|
return {
|
|
id: v.id,
|
|
bezeichnung: v.bezeichnung,
|
|
herkunft: 'VERTRAG' as const,
|
|
art: v.art,
|
|
artBeschriftung: VERTRAG_ART_BESCHRIFTUNG[v.art],
|
|
bewertung: v.bewertungSozialhilfe,
|
|
// Der Rückkaufswert steht am Vertrag nicht als Betrag; er wird
|
|
// als Vermögensposten mit Wertstand geführt. Bis dahin: offen.
|
|
wertCent: null,
|
|
wertStichtag: null,
|
|
begruendung: geoeffnet.bewertungBegruendung ?? '',
|
|
zusatz: v.gesellschaft,
|
|
}
|
|
}),
|
|
]
|
|
|
|
const uebersicht = uebersichtBilden(
|
|
zeilen.map((z) => ({
|
|
id: z.id,
|
|
bezeichnung: z.bezeichnung,
|
|
herkunft: z.herkunft,
|
|
artBeschriftung: z.artBeschriftung,
|
|
bewertung: z.bewertung,
|
|
wertCent: z.wertCent === null ? null : BigInt(z.wertCent),
|
|
wertStichtag: null,
|
|
begruendung: z.begruendung,
|
|
href: '#',
|
|
})),
|
|
)
|
|
|
|
const vergleich = freibetragVergleichen(uebersicht.jeBewertung.VERWERTBAR.summeCent)
|
|
|
|
return (
|
|
<div className="space-y-8">
|
|
<SeitenKopf
|
|
titel="Vermögen bewerten"
|
|
beschreibung="Jeder Posten bekommt eine Einschätzung und — das ist der wichtige Teil — eine Begründung. Ohne Begründung hilft die Einordnung im Widerspruchsverfahren nicht weiter."
|
|
pfad={[
|
|
{ titel: 'Start', href: '/heute' },
|
|
{ titel: 'Sozialhilfe', href: '/sozialhilfe' },
|
|
{ titel: 'Vermögen' },
|
|
]}
|
|
/>
|
|
|
|
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
|
<Summenkachel
|
|
titel={BEWERTUNG_BESCHRIFTUNG.VERWERTBAR}
|
|
betrag={uebersicht.jeBewertung.VERWERTBAR.summeCent}
|
|
anzahl={uebersicht.jeBewertung.VERWERTBAR.anzahl}
|
|
ohneWert={uebersicht.jeBewertung.VERWERTBAR.ohneWert}
|
|
farbe="text-ampel-rot"
|
|
/>
|
|
<Summenkachel
|
|
titel={BEWERTUNG_BESCHRIFTUNG.GESCHUETZT}
|
|
betrag={uebersicht.jeBewertung.GESCHUETZT.summeCent}
|
|
anzahl={uebersicht.jeBewertung.GESCHUETZT.anzahl}
|
|
ohneWert={uebersicht.jeBewertung.GESCHUETZT.ohneWert}
|
|
farbe="text-ampel-gruen"
|
|
/>
|
|
<Summenkachel
|
|
titel={BEWERTUNG_BESCHRIFTUNG.STRITTIG}
|
|
betrag={uebersicht.jeBewertung.STRITTIG.summeCent}
|
|
anzahl={uebersicht.jeBewertung.STRITTIG.anzahl}
|
|
ohneWert={uebersicht.jeBewertung.STRITTIG.ohneWert}
|
|
farbe="text-ampel-orange"
|
|
/>
|
|
<Summenkachel
|
|
titel={BEWERTUNG_BESCHRIFTUNG.UNGEPRUEFT}
|
|
betrag={uebersicht.jeBewertung.UNGEPRUEFT.summeCent}
|
|
anzahl={uebersicht.jeBewertung.UNGEPRUEFT.anzahl}
|
|
ohneWert={uebersicht.jeBewertung.UNGEPRUEFT.ohneWert}
|
|
farbe="text-muted-foreground"
|
|
/>
|
|
</div>
|
|
|
|
<Card>
|
|
<CardContent className="space-y-2 pt-5">
|
|
<div className="flex flex-wrap items-baseline justify-between gap-3">
|
|
<span className="text-sm text-muted-foreground">
|
|
Vermögensfreibetrag (§ 90 Abs. 2 Nr. 9 SGB XII)
|
|
</span>
|
|
<span className="text-lg font-semibold tabular-nums">
|
|
{formatCent(vergleich.freibetragCent)}
|
|
</span>
|
|
</div>
|
|
<div className="flex flex-wrap items-baseline justify-between gap-3">
|
|
<span className="text-sm text-muted-foreground">Über dem Freibetrag</span>
|
|
<span
|
|
className={`text-lg font-semibold tabular-nums ${
|
|
vergleich.ausgeschoepft ? 'text-ampel-rot' : 'text-ampel-gruen'
|
|
}`}
|
|
>
|
|
{formatCent(vergleich.ueberFreibetragCent)}
|
|
</span>
|
|
</div>
|
|
<p className="text-sm text-muted-foreground">{vergleich.hinweis}</p>
|
|
<Rechtshinweis rechtsgrundlage="§ 90 SGB XII" kurz />
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{uebersicht.ungeprueft.length > 0 && (
|
|
<Alert variant="warnung">
|
|
<AlertCircle aria-hidden="true" />
|
|
<AlertTitle>
|
|
{uebersicht.ungeprueft.length}{' '}
|
|
{uebersicht.ungeprueft.length === 1 ? 'Posten ist' : 'Posten sind'} noch ungeprüft
|
|
</AlertTitle>
|
|
<AlertDescription>
|
|
Vor dem Antrag sollte hier nichts mehr stehen — der Träger fragt sonst nach, und das
|
|
kostet Wochen.
|
|
</AlertDescription>
|
|
</Alert>
|
|
)}
|
|
|
|
{uebersicht.ohneBegruendung.length > 0 && (
|
|
<Alert variant="warnung">
|
|
<AlertCircle aria-hidden="true" />
|
|
<AlertTitle>Bewertung ohne Begründung</AlertTitle>
|
|
<AlertDescription>
|
|
{uebersicht.ohneBegruendung.map((p) => p.bezeichnung).join(', ')} — trag nach, worauf
|
|
sich die Einschätzung stützt. Im Widerspruchsverfahren zählt nur, was begründet ist.
|
|
</AlertDescription>
|
|
</Alert>
|
|
)}
|
|
|
|
<Vermoegensliste posten={zeilen} darfSchreiben={darfSchreiben} />
|
|
|
|
<Rechtshinweis rechtsgrundlage="§ 90 SGB XII, § 91 SGB XII" />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function Summenkachel({
|
|
titel,
|
|
betrag,
|
|
anzahl,
|
|
ohneWert,
|
|
farbe,
|
|
}: {
|
|
titel: string
|
|
betrag: bigint
|
|
anzahl: number
|
|
ohneWert: number
|
|
farbe: string
|
|
}) {
|
|
return (
|
|
<Card>
|
|
<CardContent className="pt-5">
|
|
<p className="text-sm text-muted-foreground">{titel}</p>
|
|
<p className={`text-xl font-semibold tabular-nums ${farbe}`}>{formatCent(betrag)}</p>
|
|
<p className="mt-1 text-xs text-muted-foreground">
|
|
{anzahl} {anzahl === 1 ? 'Posten' : 'Posten'}
|
|
{ohneWert > 0 && `, davon ${ohneWert} ohne Wert`}
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
)
|
|
}
|