/** * Aufträge und Rechnungen: Appwrite-Schema der Collections auftraege und projektRechnungen sowie der Zusatzfelder * (Übersicht V1). Reine Daten, absichtlich ohne Import von server/config.js: test/support/schema.js liest sie vor * useTestEnv(), ein früh geladenes config.js würde den Endpunkt des Appwrite-Nachbaus verfehlen. Die Collection-IDs * stehen in config.collections.; scripts/auftraege-setup.mjs legt alles an. * * Attribut: { key, type: 'string' | 'integer' | 'boolean' | 'datetime', size (nur Text), required: false } * Index: { key, type: 'key', attributes: [...] } * Datumswerte sind UTC (toISOString()); Appwrite liefert sie als "+00:00" zurück, daher immer mit new Date() lesen. */ const str = (key, size) => ({ key, type: 'string', size, required: false }) const int = (key) => ({ key, type: 'integer', required: false }) const bool = (key) => ({ key, type: 'boolean', required: false }) const dt = (key) => ({ key, type: 'datetime', required: false }) const index = (key, ...attributes) => ({ key, type: 'key', attributes }) export const AUFTRAEGE_COLLECTIONS = { auftraege: { attributes: [ str('nummer', 20), int('jahr'), int('laufnummer'), str('status', 20), str('kundenId', 64), str('kundeJson', 2000), str('projektId', 64), str('titel', 200), str('zeitquelleJson', 1000), str('art', 20), str('positionenJson', 20000), int('stundensatzCents'), int('schaetzungMinuten'), int('summeCents'), str('zahlungsplanJson', 1000), int('zahlungszielTage'), str('auftragVom', 10), str('auftragWeg', 20), str('startAm', 10), str('fertigBis', 10), str('texteFassung', 20), str('agbFassung', 20), str('pdfDatei', 300), str('pdfSha256', 64), dt('gesendetAm'), str('gesendetAn', 255), str('mailStatus', 20), str('mailFehler', 500), str('tokenHash', 64), dt('tokenGueltigBis'), dt('bestaetigtAm'), str('bestaetigtUeber', 10), str('bestaetigtPdfSha256', 64), bool('fruehbeginn'), str('fruehbeginnFassung', 20), str('ersetztId', 64), str('ersetztDurchId', 64), dt('storniertAm'), dt('widerrufenAm'), str('erstelltVon', 255), dt('erstelltAm'), dt('geaendertAm'), ], // idx_nummer bewusst kein Unique-Index: Entwürfe haben nummer ''. Die Eindeutigkeit stellt vergibNummer unter // SPERRE_NUMMER her (L3). indexes: [index('idx_kunde', 'kundenId'), index('idx_projekt', 'projektId'), index('idx_jahr', 'jahr'), index('idx_token', 'tokenHash'), index('idx_nummer', 'nummer')], }, // Dokument-ID = Stripe-Rechnungs-ID (muss /^in_\w{1,33}$/ erfüllen; der Stripe-Nachbau vergibt in_test_) projektRechnungen: { attributes: [ str('invoiceId', 64), str('kundenId', 64), str('projektId', 64), str('auftragId', 64), str('art', 20), int('betragCents'), str('arbeitsblattIdsJson', 20000), str('rechnungsnummer', 64), bool('aktiv'), str('erstelltVon', 255), dt('erstelltAm'), ], indexes: [index('idx_kunde', 'kundenId'), index('idx_projekt', 'projektId'), index('idx_auftrag', 'auftragId')], }, } // Zusätzliche Felder bestehender Collections (Schlüssel = Name in config.collections) export const AUFTRAEGE_ZUSATZ_ATTRIBUTE = { customers: [str('kundenart', 20)], // '' | 'unternehmen' | 'privat' financeSettings: [str('steuernummer', 40)], } // Datumsfelder je Collection, für startAppwriteMock({ datetimes }) (Appwrite liefert sie mit "+00:00") export const AUFTRAEGE_DATETIMES = Object.fromEntries( Object.entries(AUFTRAEGE_COLLECTIONS).map(([name, { attributes }]) => [name, attributes.filter((a) => a.type === 'datetime').map((a) => a.key)]), )