-- ===================================================================== -- Angebote mit Zusage im Portal -- -- Ein Angebot, das der Kunde online verbindlich annimmt, ist ein -- Vertragsschluss über eine elektronische Benutzeroberfläche. Daraus -- folgen zwei Dinge, die diese Tabelle tragen muss: -- -- 1. DER WORTLAUT WIRD FESTGEHALTEN, NICHT NUR DER PREIS. -- Bei einem Streit zählt, WAS dem Kunden gezeigt wurde, als er -- zusagte. Würde man nur preis_cent und paket speichern und den Text -- bei jeder Ansicht neu erzeugen, stünde nach der nächsten Änderung -- an den Vorlagen etwas anderes da als damals — und niemand könnte -- mehr belegen, worauf man sich geeinigt hat. Deshalb wird der -- vollständige Leistungstext beim ABSENDEN eingefroren. -- -- 2. DIE ZUSAGE WIRD MIT ZEITPUNKT UND HERKUNFT BELEGT. -- Wer zugesagt hat, wann, und von welcher Verbindung aus. Die -- Beweislast liegt beim Unternehmer. -- -- Ein Angebot hängt an einer ANFRAGE, nicht an einem Projekt: Es geht -- der Annahme voraus. Erst die Zusage des Kunden macht daraus ein -- Projekt. -- ===================================================================== CREATE TABLE IF NOT EXISTS wd_angebote ( id TEXT PRIMARY KEY, nummer TEXT NOT NULL UNIQUE, anfrage_id TEXT, kunde_id TEXT, projekt_id TEXT, -- entsteht erst mit der Zusage paket TEXT NOT NULL, titel TEXT NOT NULL, preis_cent INTEGER NOT NULL, anzahlung_cent INTEGER NOT NULL, waehrung TEXT NOT NULL DEFAULT 'EUR', laufzeit_werktage INTEGER, -- Der eingefrorene Wortlaut. Siehe Kopfkommentar: Er wird NICHT bei -- jeder Ansicht neu erzeugt. leistungen_text TEXT NOT NULL, hinweis_text TEXT, sprache TEXT NOT NULL DEFAULT 'de', -- entwurf | gesendet | angenommen | abgelehnt | abgelaufen | zurueckgezogen status TEXT NOT NULL DEFAULT 'entwurf', -- Ein Angebot ohne Ablauf bindet unbefristet. Vier Wochen sind lang -- genug zum Überlegen und kurz genug, dass ein Preis von damals nicht -- ein Jahr später noch gilt. gueltig_bis TEXT, gesendet_am TEXT, entschieden_am TEXT, zusage_ip_hash TEXT, ablehnung_grund TEXT, erstellt_am TEXT NOT NULL, aktualisiert_am TEXT, -- Bewusst ON DELETE SET NULL statt CASCADE: Wird eine Anfrage -- gelöscht, darf der Beleg über ein angenommenes Angebot nicht -- mitverschwinden. FOREIGN KEY (anfrage_id) REFERENCES wd_anfragen(id) ON DELETE SET NULL, FOREIGN KEY (kunde_id) REFERENCES wd_kunden(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS idx_wd_angebote_anfrage ON wd_angebote (anfrage_id); CREATE INDEX IF NOT EXISTS idx_wd_angebote_kunde ON wd_angebote (kunde_id, status); CREATE INDEX IF NOT EXISTS idx_wd_angebote_status ON wd_angebote (status, gueltig_bis);