Gutschriften Phase 1: Backend (Modell, Nummernkreis, CRUD, USt-Rechnung)
Neues Feature Gutschriftsverwaltung (Subventionen am Vertrag): - Modelle CreditNote + CreditNoteNumberRange + Enums (GELD/SACHWERT, PRIVAT/FIRMA, NETTO/BRUTTO) + Migration (IF NOT EXISTS, auf Dev angewandt). - USt pro Gutschrift waehlbar (vatRelevant + Basis Netto/Brutto + Satz); Netto/USt/Brutto werden berechnet und getrennt gespeichert (ZUGFeRD-tauglich). Kundentyp Privat/Firma aus Kunde vorbelegt. - Nummernkreis in Settings verwaltbar; Nummernvergabe transaktional mit SELECT ... FOR UPDATE (keine Doppelvergabe). Bsp GS-2026-0001. - Service/Controller/Routes: GET/POST /contracts/:id/credit-notes, GET .../defaults, GET/PUT/DELETE /credit-notes/:id, GET/PUT /credit-notes/number-range. Portal-Token geblockt (interner Bereich), CREATE/UPDATE/DELETE auditiert. Verifiziert: USt-Rechnung (200 netto->238, 200 brutto->168,07+31,93) und fortlaufende Nummernvergabe. Phase 2 (Vertrag-UI + Beleg-Upload + Nummernkreis-UI) und Phase 3 (PDF + ZUGFeRD) folgen. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -811,6 +811,7 @@ model Contract {
|
||||
historyEntries ContractHistoryEntry[]
|
||||
documents ContractDocument[]
|
||||
invoices Invoice[]
|
||||
creditNotes CreditNote[]
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@ -946,6 +947,89 @@ model Invoice {
|
||||
@@index([contractId])
|
||||
}
|
||||
|
||||
// ==================== GUTSCHRIFTEN (CREDIT NOTES / SUBVENTIONEN) ====================
|
||||
|
||||
// Art der Gutschrift: Geldbetrag (per Überweisung, in EUR) oder Sachwert
|
||||
// (Smartphone, Elektrogerät …, näher im Textfeld beschrieben).
|
||||
enum CreditNoteType {
|
||||
GELD
|
||||
SACHWERT
|
||||
}
|
||||
|
||||
// Kundentyp zum Zeitpunkt der Gutschrift – bestimmt die USt-Sicht
|
||||
// (Privat rechnet brutto, Firma zieht Vorsteuer). Wird aus dem Kunden
|
||||
// vorbelegt, ist aber pro Gutschrift überschreibbar.
|
||||
enum CreditNoteCustomerType {
|
||||
PRIVAT
|
||||
FIRMA
|
||||
}
|
||||
|
||||
// Basis, auf die sich der eingegebene Betrag bezieht (nur relevant, wenn
|
||||
// vatRelevant = true). Bei NETTO wird die USt aufgeschlagen, bei BRUTTO
|
||||
// herausgerechnet.
|
||||
enum CreditNoteAmountBasis {
|
||||
NETTO
|
||||
BRUTTO
|
||||
}
|
||||
|
||||
model CreditNote {
|
||||
id Int @id @default(autoincrement())
|
||||
contractId Int
|
||||
contract Contract @relation(fields: [contractId], references: [id], onDelete: Cascade)
|
||||
|
||||
number String @unique // aus Nummernkreis, z.B. GS-2026-0001
|
||||
|
||||
type CreditNoteType
|
||||
// Pflicht bei SACHWERT: was wird gewährt (z.B. "Smartphone Samsung A55").
|
||||
sachwertDescription String?
|
||||
|
||||
customerType CreditNoteCustomerType
|
||||
// USt-relevant ja/nein (Steuerberater-Auslegung: Vermittlungsleistung vs.
|
||||
// reiner Abschlussbonus/Entgeltminderung). Bei false: net = brutto, USt = 0.
|
||||
vatRelevant Boolean @default(false)
|
||||
amountBasis CreditNoteAmountBasis @default(BRUTTO)
|
||||
vatRate Float @default(19) // Prozent
|
||||
amountNet Float @default(0)
|
||||
amountVat Float @default(0)
|
||||
amountGross Float @default(0)
|
||||
currency String @default("EUR")
|
||||
|
||||
// Datum der Gutschrift (frei änderbar).
|
||||
creditDate DateTime
|
||||
// Ort der Unterschrift + Unterschrift-/Bestätigungszeitpunkt.
|
||||
place String?
|
||||
signedAt DateTime?
|
||||
// Sachwert: Bestätigung "Ware erhalten".
|
||||
goodsReceived Boolean @default(false)
|
||||
|
||||
// Überweisungsbeleg (nur GELD) – hochgeladene Datei.
|
||||
receiptPath String?
|
||||
// Generiertes Gutschrift-Dokument (PDF bzw. ZUGFeRD-Hybrid) – Phase 3.
|
||||
pdfPath String?
|
||||
|
||||
notes String?
|
||||
createdBy String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([contractId])
|
||||
}
|
||||
|
||||
// Nummernkreis für Gutschriften (Einzel-Zeile, in den Einstellungen
|
||||
// verwaltbar). Nummer wird transaktional vergeben, damit keine Lücken/
|
||||
// Doppelvergaben entstehen.
|
||||
model CreditNoteNumberRange {
|
||||
id Int @id @default(autoincrement())
|
||||
prefix String @default("GS-")
|
||||
includeYear Boolean @default(true)
|
||||
separator String @default("-")
|
||||
padding Int @default(4)
|
||||
nextNumber Int @default(1)
|
||||
resetYearly Boolean @default(true)
|
||||
currentYear Int?
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
// ==================== INTERNET CONTRACT DETAILS ====================
|
||||
|
||||
model InternetContractDetails {
|
||||
|
||||
Reference in New Issue
Block a user