Gutschrift: nur mit Empfaengeradresse anlegbar (Rechnung > Liefer)

Eine Gutschrift/ein Lieferschein braucht eine Empfaengeradresse aufs
Dokument. Rechnungsadresse hat Vorrang, sonst Lieferadresse. Ist keine
von beiden hinterlegt -> Anlegen blockiert.

- Frontend: Klick auf 'Gutschrift anlegen' prueft defaults.hasRecipient-
  Address; wenn false -> Modal-OK-Meldung statt Formular.
- Backend Defense-in-Depth: createCreditNote wirft 400, wenn weder
  billingAddressId noch addressId gesetzt. getCreditNoteDefaults liefert
  hasRecipientAddress.

Verifiziert: ohne Adresse -> hasRecipientAddress false + create 400;
mit Adresse -> ok.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-12 09:39:04 +02:00
co-authored by Claude Opus 4.8
parent 0078654465
commit 5047bfaab3
4 changed files with 50 additions and 2 deletions
+17 -1
View File
@@ -196,6 +196,8 @@ export async function getCreditNoteDefaults(contractId: number) {
where: { id: contractId },
select: {
bankCardId: true,
addressId: true,
billingAddressId: true,
customer: {
select: {
type: true,
@@ -218,6 +220,9 @@ export async function getCreditNoteDefaults(contractId: number) {
// Vertrags-Abbuchkarte als Default-Vorschlag markiert.
bankCards: contract?.customer?.bankCards ?? [],
contractBankCardId: contract?.bankCardId ?? null,
// Für die Empfängeradresse auf dem Beleg: Rechnungsadresse hat Vorrang,
// sonst Lieferadresse. Ohne beide kann kein Beleg erstellt werden.
hasRecipientAddress: !!(contract?.billingAddressId || contract?.addressId),
};
}
@@ -226,10 +231,21 @@ export async function createCreditNote(
input: CreateCreditNoteInput,
createdBy?: string,
) {
const contract = await prisma.contract.findUnique({ where: { id: contractId }, select: { id: true } });
const contract = await prisma.contract.findUnique({
where: { id: contractId },
select: { id: true, addressId: true, billingAddressId: true },
});
if (!contract) {
throw new ApiError(404, 'Vertrag nicht gefunden');
}
// Empfängeradresse für den Beleg: Rechnungsadresse bevorzugt, sonst
// Lieferadresse. Ohne beide kann kein Beleg erzeugt werden.
if (!contract.billingAddressId && !contract.addressId) {
throw new ApiError(
400,
'Keine Rechnungs- oder Lieferadresse am Vertrag hinterlegt. Bitte zuerst eine Adresse zuordnen.',
);
}
const normalized = validateAndNormalize(input);
if (normalized.payoutBankCardId) {