feat: Sozialhilfe-Modul mit Nachforderungs-Tracker und Fristpruefung
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
This commit is contained in:
@@ -1,149 +1,149 @@
|
||||
import { notFound } from 'next/navigation'
|
||||
import { Trash2 } from 'lucide-react'
|
||||
import { SeitenKopf } from '@/components/seiten-kopf'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { AktionMitRueckfrage } from '@/components/sozialhilfe/bausteine'
|
||||
import { BescheidFormular } from '@/components/sozialhilfe/bescheid-formular'
|
||||
import { BescheidPruefung } from '@/components/sozialhilfe/bescheid-pruefung'
|
||||
import { oeffnen } from '@/lib/crypto/feld'
|
||||
import { db, nichtGeloescht } from '@/lib/db'
|
||||
import { alsIsoTag, heuteAlsTag } from '@/lib/fristen/datum'
|
||||
import { BESCHEID_ART_BESCHRIFTUNG } from '@/lib/sozialhilfe/bescheide'
|
||||
import { centZuEingabe } from '@/lib/sozialhilfe/betrag'
|
||||
import {
|
||||
fristAmpel,
|
||||
rechtsbehelfsfristBerechnen,
|
||||
zugangsvermutung,
|
||||
} from '@/lib/sozialhilfe/rechtsbehelf'
|
||||
import { sozialhilfeKontext } from '@/lib/sozialhilfe/zugang'
|
||||
import { bescheidLoeschen } from '@/server/actions/sozialhilfe'
|
||||
import { formatDatum } from '@/lib/utils'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
/**
|
||||
* Bescheid-Prüfung.
|
||||
*
|
||||
* Der Rechenweg der Widerspruchsfrist steht ausgeschrieben da - die
|
||||
* Anwendung kann sich irren, und wer eine Frist verpasst, soll sehen
|
||||
* können, wo die Rechnung abgebogen ist.
|
||||
*/
|
||||
export default async function BescheidSeite({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ antragId: string; bescheidId: string }>
|
||||
}) {
|
||||
const { antragId, bescheidId } = await params
|
||||
const { betreuteId, darfSchreiben } = await sozialhilfeKontext()
|
||||
|
||||
const bescheid = await db.bescheid.findFirst({
|
||||
where: { id: bescheidId, antragId, antrag: { betreuteId }, ...nichtGeloescht },
|
||||
include: { antrag: { select: { id: true, traeger: true, aktenzeichen: true } } },
|
||||
})
|
||||
if (!bescheid) notFound()
|
||||
|
||||
const offen = oeffnen('Bescheid', bescheid)
|
||||
const heute = heuteAlsTag()
|
||||
|
||||
const ergebnis = rechtsbehelfsfristBerechnen({
|
||||
zugegangenAm: bescheid.zugegangenAm,
|
||||
bescheidVom: bescheid.bescheidVom,
|
||||
fristMonate: bescheid.rechtsbehelfsfristMonate,
|
||||
heute,
|
||||
})
|
||||
|
||||
const vorschlag = zugangsvermutung(bescheid.bescheidVom)
|
||||
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<SeitenKopf
|
||||
titel={`${BESCHEID_ART_BESCHRIFTUNG[bescheid.art]} vom ${formatDatum(bescheid.bescheidVom)}`}
|
||||
beschreibung={
|
||||
<>
|
||||
{bescheid.antrag.traeger}
|
||||
{bescheid.antrag.aktenzeichen ? ` · Az. ${bescheid.antrag.aktenzeichen}` : ''} · Zugang{' '}
|
||||
{formatDatum(bescheid.zugegangenAm)}
|
||||
</>
|
||||
}
|
||||
pfad={[
|
||||
{ titel: 'Start', href: '/heute' },
|
||||
{ titel: 'Sozialhilfe', href: '/sozialhilfe' },
|
||||
{ titel: 'Antragsakte', href: `/sozialhilfe/${antragId}` },
|
||||
{ titel: 'Bescheid' },
|
||||
]}
|
||||
/>
|
||||
|
||||
<BescheidPruefung
|
||||
bescheidId={bescheid.id}
|
||||
pruefStatus={bescheid.pruefStatus}
|
||||
widerspruchEingelegtAm={
|
||||
bescheid.widerspruchEingelegtAm ? alsIsoTag(bescheid.widerspruchEingelegtAm) : ''
|
||||
}
|
||||
darfSchreiben={darfSchreiben}
|
||||
rechenweg={{
|
||||
berechenbar: ergebnis.berechenbar,
|
||||
widerspruchMoeglichBis: ergebnis.widerspruchMoeglichBis
|
||||
? alsIsoTag(ergebnis.widerspruchMoeglichBis)
|
||||
: null,
|
||||
rechnerischesEnde: ergebnis.rechnerischesEnde
|
||||
? alsIsoTag(ergebnis.rechnerischesEnde)
|
||||
: null,
|
||||
verschoben: ergebnis.verschoben,
|
||||
tageVerbleibend: ergebnis.tageVerbleibend,
|
||||
abgelaufen: ergebnis.abgelaufen,
|
||||
ampel: fristAmpel(ergebnis),
|
||||
schritte: ergebnis.schritte,
|
||||
hinweise: ergebnis.hinweise,
|
||||
}}
|
||||
/>
|
||||
|
||||
{offen.notizen && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Notizen</CardTitle>
|
||||
<CardDescription>Verschlüsselt gespeichert.</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="whitespace-pre-line text-sm">{offen.notizen}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{darfSchreiben && (
|
||||
<section className="space-y-4">
|
||||
<h2 className="text-lg font-semibold">Bescheid bearbeiten</h2>
|
||||
<BescheidFormular
|
||||
antragId={antragId}
|
||||
zugangsvorschlag={{ datum: alsIsoTag(vorschlag.datum), hinweis: vorschlag.hinweis }}
|
||||
werte={{
|
||||
id: bescheid.id,
|
||||
art: bescheid.art,
|
||||
bescheidVom: alsIsoTag(bescheid.bescheidVom),
|
||||
zugegangenAm: bescheid.zugegangenAm ? alsIsoTag(bescheid.zugegangenAm) : '',
|
||||
zeitraumVon: bescheid.zeitraumVon ? alsIsoTag(bescheid.zeitraumVon) : '',
|
||||
zeitraumBis: bescheid.zeitraumBis ? alsIsoTag(bescheid.zeitraumBis) : '',
|
||||
betrag: centZuEingabe(bescheid.betragCent),
|
||||
rechtsbehelfsfristMonate: bescheid.rechtsbehelfsfristMonate,
|
||||
widerspruchEingelegtAm: bescheid.widerspruchEingelegtAm
|
||||
? alsIsoTag(bescheid.widerspruchEingelegtAm)
|
||||
: '',
|
||||
notizen: offen.notizen ?? '',
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="border-t pt-6">
|
||||
<AktionMitRueckfrage
|
||||
aktion={bescheidLoeschen.bind(null, bescheid.id)}
|
||||
frage="Diesen Bescheid in den Papierkorb legen? Er bleibt dort 30 Tage."
|
||||
variant="outline"
|
||||
size="default"
|
||||
>
|
||||
<Trash2 aria-hidden="true" />
|
||||
Bescheid löschen
|
||||
</AktionMitRueckfrage>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
import { notFound } from 'next/navigation'
|
||||
import { Trash2 } from 'lucide-react'
|
||||
import { SeitenKopf } from '@/components/seiten-kopf'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { AktionMitRueckfrage } from '@/components/sozialhilfe/bausteine'
|
||||
import { BescheidFormular } from '@/components/sozialhilfe/bescheid-formular'
|
||||
import { BescheidPruefung } from '@/components/sozialhilfe/bescheid-pruefung'
|
||||
import { oeffnen } from '@/lib/crypto/feld'
|
||||
import { db, nichtGeloescht } from '@/lib/db'
|
||||
import { alsIsoTag, heuteAlsTag } from '@/lib/fristen/datum'
|
||||
import { BESCHEID_ART_BESCHRIFTUNG } from '@/lib/sozialhilfe/bescheide'
|
||||
import { betragFormatieren } from '@/lib/finanzen/betrag'
|
||||
import {
|
||||
fristAmpel,
|
||||
rechtsbehelfsfristBerechnen,
|
||||
zugangsvermutung,
|
||||
} from '@/lib/sozialhilfe/rechtsbehelf'
|
||||
import { sozialhilfeKontext } from '@/lib/sozialhilfe/zugang'
|
||||
import { bescheidLoeschen } from '@/server/actions/sozialhilfe'
|
||||
import { formatDatum } from '@/lib/utils'
|
||||
|
||||
export const dynamic = 'force-dynamic'
|
||||
|
||||
/**
|
||||
* Bescheid-Prüfung.
|
||||
*
|
||||
* Der Rechenweg der Widerspruchsfrist steht ausgeschrieben da - die
|
||||
* Anwendung kann sich irren, und wer eine Frist verpasst, soll sehen
|
||||
* können, wo die Rechnung abgebogen ist.
|
||||
*/
|
||||
export default async function BescheidSeite({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ antragId: string; bescheidId: string }>
|
||||
}) {
|
||||
const { antragId, bescheidId } = await params
|
||||
const { betreuteId, darfSchreiben } = await sozialhilfeKontext()
|
||||
|
||||
const bescheid = await db.bescheid.findFirst({
|
||||
where: { id: bescheidId, antragId, antrag: { betreuteId }, ...nichtGeloescht },
|
||||
include: { antrag: { select: { id: true, traeger: true, aktenzeichen: true } } },
|
||||
})
|
||||
if (!bescheid) notFound()
|
||||
|
||||
const offen = oeffnen('Bescheid', bescheid)
|
||||
const heute = heuteAlsTag()
|
||||
|
||||
const ergebnis = rechtsbehelfsfristBerechnen({
|
||||
zugegangenAm: bescheid.zugegangenAm,
|
||||
bescheidVom: bescheid.bescheidVom,
|
||||
fristMonate: bescheid.rechtsbehelfsfristMonate,
|
||||
heute,
|
||||
})
|
||||
|
||||
const vorschlag = zugangsvermutung(bescheid.bescheidVom)
|
||||
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
<SeitenKopf
|
||||
titel={`${BESCHEID_ART_BESCHRIFTUNG[bescheid.art]} vom ${formatDatum(bescheid.bescheidVom)}`}
|
||||
beschreibung={
|
||||
<>
|
||||
{bescheid.antrag.traeger}
|
||||
{bescheid.antrag.aktenzeichen ? ` · Az. ${bescheid.antrag.aktenzeichen}` : ''} · Zugang{' '}
|
||||
{formatDatum(bescheid.zugegangenAm)}
|
||||
</>
|
||||
}
|
||||
pfad={[
|
||||
{ titel: 'Start', href: '/heute' },
|
||||
{ titel: 'Sozialhilfe', href: '/sozialhilfe' },
|
||||
{ titel: 'Antragsakte', href: `/sozialhilfe/${antragId}` },
|
||||
{ titel: 'Bescheid' },
|
||||
]}
|
||||
/>
|
||||
|
||||
<BescheidPruefung
|
||||
bescheidId={bescheid.id}
|
||||
pruefStatus={bescheid.pruefStatus}
|
||||
widerspruchEingelegtAm={
|
||||
bescheid.widerspruchEingelegtAm ? alsIsoTag(bescheid.widerspruchEingelegtAm) : ''
|
||||
}
|
||||
darfSchreiben={darfSchreiben}
|
||||
rechenweg={{
|
||||
berechenbar: ergebnis.berechenbar,
|
||||
widerspruchMoeglichBis: ergebnis.widerspruchMoeglichBis
|
||||
? alsIsoTag(ergebnis.widerspruchMoeglichBis)
|
||||
: null,
|
||||
rechnerischesEnde: ergebnis.rechnerischesEnde
|
||||
? alsIsoTag(ergebnis.rechnerischesEnde)
|
||||
: null,
|
||||
verschoben: ergebnis.verschoben,
|
||||
tageVerbleibend: ergebnis.tageVerbleibend,
|
||||
abgelaufen: ergebnis.abgelaufen,
|
||||
ampel: fristAmpel(ergebnis),
|
||||
schritte: ergebnis.schritte,
|
||||
hinweise: ergebnis.hinweise,
|
||||
}}
|
||||
/>
|
||||
|
||||
{offen.notizen && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Notizen</CardTitle>
|
||||
<CardDescription>Verschlüsselt gespeichert.</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="whitespace-pre-line text-sm">{offen.notizen}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{darfSchreiben && (
|
||||
<section className="space-y-4">
|
||||
<h2 className="text-lg font-semibold">Bescheid bearbeiten</h2>
|
||||
<BescheidFormular
|
||||
antragId={antragId}
|
||||
zugangsvorschlag={{ datum: alsIsoTag(vorschlag.datum), hinweis: vorschlag.hinweis }}
|
||||
werte={{
|
||||
id: bescheid.id,
|
||||
art: bescheid.art,
|
||||
bescheidVom: alsIsoTag(bescheid.bescheidVom),
|
||||
zugegangenAm: bescheid.zugegangenAm ? alsIsoTag(bescheid.zugegangenAm) : '',
|
||||
zeitraumVon: bescheid.zeitraumVon ? alsIsoTag(bescheid.zeitraumVon) : '',
|
||||
zeitraumBis: bescheid.zeitraumBis ? alsIsoTag(bescheid.zeitraumBis) : '',
|
||||
betrag: bescheid.betragCent === null ? '' : betragFormatieren(bescheid.betragCent),
|
||||
rechtsbehelfsfristMonate: bescheid.rechtsbehelfsfristMonate,
|
||||
widerspruchEingelegtAm: bescheid.widerspruchEingelegtAm
|
||||
? alsIsoTag(bescheid.widerspruchEingelegtAm)
|
||||
: '',
|
||||
notizen: offen.notizen ?? '',
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="border-t pt-6">
|
||||
<AktionMitRueckfrage
|
||||
aktion={bescheidLoeschen.bind(null, bescheid.id)}
|
||||
frage="Diesen Bescheid in den Papierkorb legen? Er bleibt dort 30 Tage."
|
||||
variant="outline"
|
||||
size="default"
|
||||
>
|
||||
<Trash2 aria-hidden="true" />
|
||||
Bescheid löschen
|
||||
</AktionMitRueckfrage>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user